From 93888542d26c2d3083bb816375740f6af3810059 Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Tue, 30 May 2023 02:19:46 +0200 Subject: video/pc_vga.cpp: part 1 of interface modernization (#11284) - video/pc_vga.cpp: Move everything that doesn't belong to main VGA/SVGA interfaces to per-manufacturer family files; - shared/pcshare.cpp: retire pcat_base_state::pcvideo_* fns; - video/pc_vga.cpp: temporary move gamtor_vga_device to misc/gamtor.cpp; - bus/isa/isa_cards.cpp: retire TGUI9680 from being selected (all refs points to be a PCI card only, there's mention of a VLB card but haven't seen a single retail dump/photo yet) - bus/isa/svga_trident.cpp: add TVGA9000 ISA card - bus/isa/svga_tseng.cpp: add earlier ColorImage ET4000AX variant - bus/isa/svga_tseng.cpp: add Kasan Hangulmadang-16 Korean variant ISA - Adds a very preliminary implementation of nVidia Riva 128 PCI card, added as a temp target in pc/pcipc.cpp (pcinv3); - video/pc_vga.cpp: Rework and fix VGA input sense (necessary to allow Riva 128 to survive POST); - video/pc_vga_s3.cpp: Fix s3_vga_device inheritance (was subclassing from ati_vga_device) - pc/calchase.cpp: convert custom JAMMA i/f to ISA device; - pc/calchase.cpp: connect Trident VGA to ISA bus; --- scripts/src/bus.lua | 2 - scripts/src/video.lua | 132 +- src/devices/bus/isa/isa_cards.cpp | 5 +- src/devices/bus/isa/mach32.cpp | 395 --- src/devices/bus/isa/mach32.h | 243 -- src/devices/bus/isa/s3virge.cpp | 9 +- src/devices/bus/isa/s3virge.h | 3 +- src/devices/bus/isa/svga_s3.h | 2 +- src/devices/bus/isa/svga_trident.cpp | 85 +- src/devices/bus/isa/svga_trident.h | 27 +- src/devices/bus/isa/svga_tseng.cpp | 60 +- src/devices/bus/isa/svga_tseng.h | 20 +- src/devices/bus/isa/trident.cpp | 1709 ------------ src/devices/bus/isa/trident.h | 170 -- src/devices/bus/isa/vga_ati.cpp | 7 +- src/devices/bus/isa/vga_ati.h | 5 +- src/devices/machine/sis630_gui.cpp | 1 - src/devices/video/ati_mach32.cpp | 407 +++ src/devices/video/ati_mach32.h | 242 ++ src/devices/video/ati_mach8.cpp | 337 +++ src/devices/video/ati_mach8.h | 84 + src/devices/video/atirage.h | 2 +- src/devices/video/clgd542x.cpp | 32 +- src/devices/video/clgd542x.h | 5 +- src/devices/video/ibm8514a.cpp | 1662 ++++++++++++ src/devices/video/ibm8514a.h | 155 ++ src/devices/video/pc_vga.cpp | 4973 +--------------------------------- src/devices/video/pc_vga.h | 550 +--- src/devices/video/pc_vga_ati.cpp | 352 +++ src/devices/video/pc_vga_ati.h | 52 + src/devices/video/pc_vga_nvidia.cpp | 440 +++ src/devices/video/pc_vga_nvidia.h | 49 + src/devices/video/pc_vga_s3.cpp | 1172 ++++++++ src/devices/video/pc_vga_s3.h | 105 + src/devices/video/pc_vga_trident.cpp | 1719 ++++++++++++ src/devices/video/pc_vga_trident.h | 172 ++ src/devices/video/pc_vga_tseng.cpp | 427 +++ src/devices/video/pc_vga_tseng.h | 57 + src/devices/video/pc_xga.cpp | 867 ++++++ src/devices/video/pc_xga.h | 94 + src/devices/video/riva128.cpp | 297 ++ src/devices/video/riva128.h | 57 + src/mame/konami/konmedal020.cpp | 4 +- src/mame/mame.lst | 1 + src/mame/midway/midqslvr.cpp | 16 - src/mame/misc/gammagic.cpp | 19 +- src/mame/misc/gamtor.cpp | 128 + src/mame/misc/magtouch.cpp | 18 +- src/mame/misc/pntnpuzl.cpp | 3 +- src/mame/misc/savquest.cpp | 11 +- src/mame/misc/su2000.cpp | 9 +- src/mame/misc/voyager.cpp | 487 +--- src/mame/pc/at.cpp | 3 +- src/mame/pc/calchase.cpp | 573 ++-- src/mame/pc/fruitpc.cpp | 9 +- src/mame/pc/igspc.cpp | 4 +- src/mame/pc/pangofun.cpp | 9 +- src/mame/pc/paokaipc.cpp | 21 +- src/mame/pc/pcat_dyn.cpp | 19 +- src/mame/pc/pcat_nit.cpp | 18 +- src/mame/pc/pcipc.cpp | 19 +- src/mame/pc/queen.cpp | 17 +- src/mame/shared/pcshare.cpp | 64 +- src/mame/shared/pcshare.h | 5 - src/mame/skeleton/indiana.cpp | 2 - src/mame/taito/taitowlf.cpp | 35 - 66 files changed, 9699 insertions(+), 8979 deletions(-) delete mode 100644 src/devices/bus/isa/mach32.cpp delete mode 100644 src/devices/bus/isa/mach32.h delete mode 100644 src/devices/bus/isa/trident.cpp delete mode 100644 src/devices/bus/isa/trident.h create mode 100644 src/devices/video/ati_mach32.cpp create mode 100644 src/devices/video/ati_mach32.h create mode 100644 src/devices/video/ati_mach8.cpp create mode 100644 src/devices/video/ati_mach8.h create mode 100644 src/devices/video/ibm8514a.cpp create mode 100644 src/devices/video/ibm8514a.h create mode 100644 src/devices/video/pc_vga_ati.cpp create mode 100644 src/devices/video/pc_vga_ati.h create mode 100644 src/devices/video/pc_vga_nvidia.cpp create mode 100644 src/devices/video/pc_vga_nvidia.h create mode 100644 src/devices/video/pc_vga_s3.cpp create mode 100644 src/devices/video/pc_vga_s3.h create mode 100644 src/devices/video/pc_vga_trident.cpp create mode 100644 src/devices/video/pc_vga_trident.h create mode 100644 src/devices/video/pc_vga_tseng.cpp create mode 100644 src/devices/video/pc_vga_tseng.h create mode 100644 src/devices/video/pc_xga.cpp create mode 100644 src/devices/video/pc_xga.h create mode 100644 src/devices/video/riva128.cpp create mode 100644 src/devices/video/riva128.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index e39ddec815f..41894e6d422 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1698,8 +1698,6 @@ if (BUSES["ISA"]~=null) then MAME_DIR .. "src/devices/bus/isa/lpt.h", MAME_DIR .. "src/devices/bus/isa/lrk330.cpp", MAME_DIR .. "src/devices/bus/isa/lrk330.h", - MAME_DIR .. "src/devices/bus/isa/mach32.cpp", - MAME_DIR .. "src/devices/bus/isa/mach32.h", MAME_DIR .. "src/devices/bus/isa/mc1502_fdc.cpp", MAME_DIR .. "src/devices/bus/isa/mc1502_fdc.h", MAME_DIR .. "src/devices/bus/isa/mc1502_rom.cpp", diff --git a/scripts/src/video.lua b/scripts/src/video.lua index 2f1b0abfb39..dd0d6575a75 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -281,6 +281,18 @@ if (VIDEOS["FIXFREQ"]~=null) then } end +-------------------------------------------------- +-- +--@src/devices/video/riva128.h,VIDEOS["RIVA128"] = true +-------------------------------------------------- + +if (VIDEOS["RIVA128"]~=null) then + files { + MAME_DIR .. "src/devices/video/riva128.cpp", + MAME_DIR .. "src/devices/video/riva128.h", + } +end + -------------------------------------------------- -- --@src/devices/video/gf4500.h,VIDEOS["GF4500"] = true @@ -818,13 +830,129 @@ if (VIDEOS["PC_VGA"]~=null) then files { MAME_DIR .. "src/devices/video/pc_vga.cpp", MAME_DIR .. "src/devices/video/pc_vga.h", - MAME_DIR .. "src/devices/bus/isa/trident.cpp", - MAME_DIR .. "src/devices/bus/isa/trident.h", + } +end + +-------------------------------------------------- +-- +--@src/devices/video/pc_vga_ati.h,VIDEOS["PC_VGA_ATI"] = true +-------------------------------------------------- + +if (VIDEOS["PC_VGA_ATI"]~=null) then + files { + MAME_DIR .. "src/devices/video/pc_vga_ati.cpp", + MAME_DIR .. "src/devices/video/pc_vga_ati.h", + } +end + +-------------------------------------------------- +-- +--@src/devices/video/ibm8514a.h,VIDEOS["IBM8514A"] = true +-------------------------------------------------- + +if (VIDEOS["IBM8514A"]~=null) then + files { + MAME_DIR .. "src/devices/video/ibm8514a.cpp", + MAME_DIR .. "src/devices/video/ibm8514a.h", + } +end + +-------------------------------------------------- +-- +--@src/devices/video/ati_mach8.h,VIDEOS["ATI_MACH8"] = true +-------------------------------------------------- + +if (VIDEOS["ATI_MACH8"]~=null) then + files { + MAME_DIR .. "src/devices/video/ati_mach8.cpp", + MAME_DIR .. "src/devices/video/ati_mach8.h", + } +end + +-------------------------------------------------- +-- +--@src/devices/video/ati_mach8.h,VIDEOS["ATI_MACH32"] = true +-------------------------------------------------- + +if (VIDEOS["ATI_MACH32"]~=null) then + files { + MAME_DIR .. "src/devices/video/ati_mach32.cpp", + MAME_DIR .. "src/devices/video/ati_mach32.h", + } +end + +-------------------------------------------------- +-- +--@src/devices/video/clgd542x.h,VIDEOS["PC_VGA_CIRRUS"] = true +-------------------------------------------------- + +if (VIDEOS["PC_VGA_CIRRUS"]~=null) then + files { MAME_DIR .. "src/devices/video/clgd542x.cpp", MAME_DIR .. "src/devices/video/clgd542x.h", } end +-------------------------------------------------- +-- +--@src/devices/video/pc_vga_nvidia.h,VIDEOS["PC_VGA_NVIDIA"] = true +-------------------------------------------------- + +if (VIDEOS["PC_VGA_NVIDIA"]~=null) then + files { + MAME_DIR .. "src/devices/video/pc_vga_nvidia.cpp", + MAME_DIR .. "src/devices/video/pc_vga_nvidia.h", + } +end + +-------------------------------------------------- +-- +--@src/devices/video/pc_vga_nvidia.h,VIDEOS["PC_VGA_S3"] = true +-------------------------------------------------- + +if (VIDEOS["PC_VGA_S3"]~=null) then + files { + MAME_DIR .. "src/devices/video/pc_vga_s3.cpp", + MAME_DIR .. "src/devices/video/pc_vga_s3.h", + } +end + +-------------------------------------------------- +-- +--@src/devices/video/pc_vga_trident.h,VIDEOS["PC_VGA_TRIDENT"] = true +-------------------------------------------------- + +if (VIDEOS["PC_VGA_TRIDENT"]~=null) then + files { + MAME_DIR .. "src/devices/video/pc_vga_trident.cpp", + MAME_DIR .. "src/devices/video/pc_vga_trident.h", + } +end + +-------------------------------------------------- +-- +--@src/devices/video/pc_vga_tseng.h,VIDEOS["PC_VGA_TSENG"] = true +-------------------------------------------------- + +if (VIDEOS["PC_VGA_TSENG"]~=null) then + files { + MAME_DIR .. "src/devices/video/pc_vga_tseng.cpp", + MAME_DIR .. "src/devices/video/pc_vga_tseng.h", + } +end + +-------------------------------------------------- +-- +--@src/devices/video/pc_xga.h,VIDEOS["PC_XGA"] = true +-------------------------------------------------- + +if (VIDEOS["PC_XGA"]~=null) then + files { + MAME_DIR .. "src/devices/video/pc_xga.cpp", + MAME_DIR .. "src/devices/video/pc_xga.h", + } +end + -------------------------------------------------- -- --@src/devices/video/virge_pci.h,VIDEOS["VIRGE_PCI"] = true diff --git a/src/devices/bus/isa/isa_cards.cpp b/src/devices/bus/isa/isa_cards.cpp index b3a02da884b..957a2a388ac 100644 --- a/src/devices/bus/isa/isa_cards.cpp +++ b/src/devices/bus/isa/isa_cards.cpp @@ -105,6 +105,7 @@ void pc_isa8_cards(device_slot_interface &device) device.option_add("pgc", ISA8_PGC); device.option_add("vga", ISA8_VGA); device.option_add("svga_et4k", ISA8_SVGA_ET4K); + device.option_add("svga_et4k_kasan16", ISA8_SVGA_ET4K_KASAN16); device.option_add("num9rev",ISA8_NUM_9_REV); device.option_add("com", ISA8_COM); device.option_add("fdc", ISA8_FDC_SUPERIO); @@ -158,6 +159,7 @@ void pc_isa16_cards(device_slot_interface &device) device.option_add("pgc", ISA8_PGC); device.option_add("vga", ISA8_VGA); device.option_add("svga_et4k", ISA8_SVGA_ET4K); + device.option_add("svga_et4k_kasan16", ISA8_SVGA_ET4K_KASAN16); device.option_add("num9rev",ISA8_NUM_9_REV); device.option_add("com", ISA8_COM); device.option_add("comat", ISA8_COM_AT); @@ -213,7 +215,8 @@ void pc_isa16_cards(device_slot_interface &device) device.option_add("clgd542x",ISA16_SVGA_CIRRUS_GD542X); device.option_add("gfxultra", ISA16_VGA_GFXULTRA); device.option_add("gfxultrap", ISA16_SVGA_GFXULTRAPRO); - device.option_add("tgui9680",ISA16_SVGA_TGUI9680); + device.option_add("tvga9000", ISA16_SVGA_TVGA9000); +// device.option_add("tgui9680",ISA16_SVGA_TGUI9680); device.option_add("3c505", ISA16_3C505); device.option_add("mach64", ISA16_SVGA_MACH64); device.option_add("sb16_lle", ISA16_SB16); diff --git a/src/devices/bus/isa/mach32.cpp b/src/devices/bus/isa/mach32.cpp deleted file mode 100644 index 3033f626db0..00000000000 --- a/src/devices/bus/isa/mach32.cpp +++ /dev/null @@ -1,395 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Barry Rodewald -/* - * mach32.c - * - * Implementation of the ATi mach32 and mach64 video chips - * Based on ati_vga and mach8 - * - * Created on: 16/05/2014 - */ - -#include "emu.h" -#include "mach32.h" - -#include "screen.h" - -DEFINE_DEVICE_TYPE(ATIMACH32, mach32_device, "mach32", "ATi mach32") -DEFINE_DEVICE_TYPE(ATIMACH32_8514A, mach32_8514a_device, "mach32_8514a", "ATi mach32 (2D acceleration module)") -DEFINE_DEVICE_TYPE(ATIMACH64, mach64_device, "mach64", "ATi mach64") -DEFINE_DEVICE_TYPE(ATIMACH64_8514A, mach64_8514a_device, "mach64_8514a", "ATi mach64 (2D acceleration module)") - - -/* - * mach32 - */ - -// 8514/A device -mach32_8514a_device::mach32_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : mach32_8514a_device(mconfig, ATIMACH32_8514A, tag, owner, clock) -{ -} - -mach32_8514a_device::mach32_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : mach8_device(mconfig, type, tag, owner, clock), m_chip_ID(0), m_membounds(0) -{ -} - - -// SVGA device -mach32_device::mach32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : mach32_device(mconfig, ATIMACH32, tag, owner, clock) -{ -} - -mach32_device::mach32_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), m_8514a(*this,"8514a") -{ -} - -void mach32_device::device_add_mconfig(machine_config &config) -{ - ATIMACH32_8514A(config, "8514a", 0).set_vga(DEVICE_SELF); - EEPROM_93C56_16BIT(config, "ati_eeprom"); -} - -void mach32_8514a_device::device_start() -{ - mach8_device::device_start(); - // 017h 68800-AX - // 177h 68800-LX - // 2F7h 68800-6 - // The 68800-3 appears to return 0 for this field (undocumented) - m_chip_ID = 0x17; - m_membounds = 0; -} - -// Configuration Status Register 1 (read only) -// bit 0: Disable VGA: 0=VGA+8514/A, 1=8514/A only -// bits 1-3: Bus Type: 0=16-bit ISA. 1=EISA, 2=16-bit MCA, 3=32-bit MCA, 4=LBus 386SX -// 5=LBus 386DX, 6=LBus 486. 7=PCI -// bits 4-6: RAM Type: 3=256Kx16 DRAM -// bit 7: Chip Disable -// bit 8: TST_VCTR_ENA: 1=delay memory write by 1/2 MCLK to test vector generation -// bits 9-11: DAC Type: 0=ATI68830, 1=SC11483, 2=ATI68875, 3=Bt476, 4=Bt481, 5=ATI68860 (68800AX or higher) -// The Graphics Ultra Pro has an ATI68875 -// bit 12: Enable internal uC address decode -// bit 13-15: Card ID: ID when using multiple controllers -uint16_t mach32_8514a_device::mach32_config1_r() -{ - return 0x0430; // enable VGA, 16-bit ISA, 256Kx16 DRAM, ATI68875 -} - - -/* 7AEE (W) Mach 32 - * bits 0-2 Monitor Alias - Monitor ID - * bit 3 Enable reporting of Monitor Alias - * bits 4-5 Pixel Width (0=4bpp, 1=8bpp, 2=16bpp, 3=24bpp) - * bits 6-7 16bpp colour mode (0=555, 1=565, 2=655, 3=664) - * bit 8 Multiplex pixels - processes 4 pixels in parallel by the DAC - * bit 9 24bpp config (0=3Bytes/pixel, 1=4Bytes/pixel) - * bit 10 24bpp colour order (0=RGB, LSB reserved in 4Bpp, 1=BGR, MSB reserved in 4Bpp) - * bit 11 Display pixel size to be written - * bits 12-13 DAC extended address inputs RS2,RS3 - * bit 14 Enabled 8-bit DAC (0=6-bit) - * bit 15 Draw pixel size to be written - * If bits 11 and 15 are both 0, then for compatibility, both will be written - */ -void mach32_8514a_device::mach32_ge_ext_config_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if(offset == 1) - { - COMBINE_DATA(&mach8.ge_ext_config); - if(data & 0x0800) - display_mode_change = true; - if(!(data & 0x8000) && (!(data & 0x0800))) - display_mode_change = true; - } -} - -void mach32_8514a_device::device_reset() -{ -} - -void mach32_device::device_start() -{ - ati_vga_device::device_start(); - ati.vga_chip_id = 0x00; // correct? -} - -void mach32_device::device_reset() -{ - ati_vga_device::device_reset(); -} - -void mach32_device::ati_define_video_mode() -{ - uint16_t config = m_8514a->get_ext_config(); - - if(ati.ext_reg[0x30] & 0x20) - { - if(m_8514a->has_display_mode_changed()) - { - svga.rgb8_en = 0; - svga.rgb15_en = 0; - svga.rgb16_en = 0; - svga.rgb32_en = 0; - - switch(config & 0x0030) // pixel depth - { - case 0x0000: - break; - case 0x0010: - svga.rgb8_en = 1; - break; - case 0x0020: - svga.rgb15_en = 1; - break; - case 0x0030: - svga.rgb32_en = 1; - break; - } - } - } - else - { - ati_vga_device::ati_define_video_mode(); - return; - } - - set_dot_clock(); -} - -uint16_t mach32_device::offset() -{ - if(get_video_depth() >= 15) - return ati_vga_device::offset() << 1; - return ati_vga_device::offset(); -} - -uint32_t mach32_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - ati_vga_device::screen_update(screen, bitmap, cliprect); - draw_hw_cursor(screen, bitmap, cliprect); - - return 0; -} - -uint32_t mach32_device::draw_hw_cursor(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - uint8_t depth = get_video_depth(); - - if(!m_cursor_enable) - return 0; - - uint32_t src = (m_cursor_address & 0x000fffff) << 2; - - uint32_t colour0, colour1; - if(depth == 8) - { - colour0 = pen(m_cursor_colour0_b); - colour1 = pen(m_cursor_colour1_b); - } - else // 16/24/32bpp - { - colour0 = (m_cursor_colour0_r << 16) | (m_cursor_colour0_g << 8) | (m_cursor_colour0_b); - colour1 = (m_cursor_colour1_r << 16) | (m_cursor_colour1_g << 8) | (m_cursor_colour1_b); - } - - // draw hardware pointer (64x64 max) - for(uint8_t y=0;y<64;y++) - { - uint32_t *dst = &bitmap.pix(m_cursor_vertical + y, m_cursor_horizontal); - for(uint8_t x=0;x<64;x+=8) - { - uint16_t const bits = (vga.memory[(src+0) % vga.svga_intf.vram_size] | ((vga.memory[(src+1) % vga.svga_intf.vram_size]) << 8)); - - for(uint8_t z=0;z<8;z++) - { - if(((z + x) > (m_cursor_offset_horizontal-1)) && (y < (63 - m_cursor_offset_vertical))) - { - uint8_t const val = (bits >> (z*2)) & 0x03; - switch(val) - { - case 0: // cursor colour 0 - *dst = colour0; - break; - case 1: // cursor colour 1 - *dst = colour1; - break; - case 2: // transparent - break; - case 3: // complement - *dst = ~(*dst); - break; - } - dst++; - } - } - src+=2; - } - } - - return 0; -} - -// mach32 Hardware Pointer -void mach32_device::mach32_cursor_l_w(offs_t offset, uint16_t data) -{ - if(offset == 1) - m_cursor_address = (m_cursor_address & 0xf0000) | data; - if(LOG_MACH32) logerror("mach32 HW pointer data address: %05x",m_cursor_address); -} - -void mach32_device::mach32_cursor_h_w(offs_t offset, uint16_t data) -{ - if(offset == 1) - { - m_cursor_address = (m_cursor_address & 0x0ffff) | ((data & 0x000f) << 16); - m_cursor_enable = data & 0x8000; - if(LOG_MACH32) logerror("mach32 HW pointer data address: %05x",m_cursor_address); - } -} - -void mach32_device::mach32_cursor_pos_h(offs_t offset, uint16_t data) -{ - if(offset == 1) - m_cursor_horizontal = data & 0x07ff; -} - -void mach32_device::mach32_cursor_pos_v(offs_t offset, uint16_t data) -{ - if(offset == 1) - m_cursor_vertical = data & 0x0fff; -} - -void mach32_device::mach32_cursor_colour_b_w(offs_t offset, uint16_t data) -{ - if(offset == 1) - { - m_cursor_colour0_b = data & 0xff; - m_cursor_colour1_b = data >> 8; - if(LOG_MACH32) logerror("Mach32: HW Cursor Colour Blue write RGB: 0: %02x %02x %02x 1: %02x %02x %02x\n" - ,m_cursor_colour0_r,m_cursor_colour0_g,m_cursor_colour0_b,m_cursor_colour1_r,m_cursor_colour1_g,m_cursor_colour1_b); - } -} - -void mach32_device::mach32_cursor_colour_0_w(offs_t offset, uint16_t data) -{ - if(offset == 1) - { - m_cursor_colour0_g = data & 0xff; - m_cursor_colour0_r = data >> 8; - if(LOG_MACH32) logerror("Mach32: HW Cursor Colour 0 write RGB: %02x %02x %02x\n",m_cursor_colour0_r,m_cursor_colour0_g,m_cursor_colour0_b); - } -} - -void mach32_device::mach32_cursor_colour_1_w(offs_t offset, uint16_t data) -{ - if(offset == 1) - { - m_cursor_colour1_g = data & 0xff; - m_cursor_colour1_r = data >> 8; - if(LOG_MACH32) logerror("Mach32: HW Cursor Colour 1 write RGB: %02x %02x %02x\n",m_cursor_colour1_r,m_cursor_colour1_g,m_cursor_colour1_b); - } -} - -void mach32_device::mach32_cursor_offset_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if(offset == 1) - { - if(ACCESSING_BITS_0_7) - m_cursor_offset_horizontal = data & 0x00ff; - if(ACCESSING_BITS_8_15) - m_cursor_offset_vertical = data >> 8; - if(LOG_MACH32) logerror("Mach32: HW Cursor Offset write H:%i V:%i\n",m_cursor_offset_horizontal,m_cursor_offset_vertical); - } -} - -/* - * mach64 - */ - -// 8514/A device -mach64_8514a_device::mach64_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : mach64_8514a_device(mconfig, ATIMACH64_8514A, tag, owner, clock) -{ -} - -mach64_8514a_device::mach64_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : mach32_8514a_device(mconfig, type, tag, owner, clock) -{ -} - - -// SVGA device -mach64_device::mach64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : mach64_device(mconfig, ATIMACH64, tag, owner, clock) -{ -} - -mach64_device::mach64_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : mach32_device(mconfig, type, tag, owner, clock), m_8514a(*this, "8514a") -{ -} - -void mach64_device::device_add_mconfig(machine_config &config) -{ - ATIMACH64_8514A(config, "8514a", 0).set_vga(DEVICE_SELF); - EEPROM_93C56_16BIT(config, "ati_eeprom"); -} - -void mach64_8514a_device::device_start() -{ - mach32_8514a_device::device_start(); - // 017h 68800-AX - // 177h 68800-LX - // 2F7h 68800-6 - // The 68800-3 appears to return 0 for this field (undocumented) - m_chip_ID = 0x0000; // value is unknown for mach64 - m_membounds = 0; -} - -void mach64_8514a_device::device_reset() -{ -} - -void mach64_device::device_start() -{ - mach32_device::device_start(); -} - -void mach64_device::device_reset() -{ - mach32_device::device_reset(); -} - -void mach64_device::set_color(u8 index, u32 color) -{ - // update the palette device so we can see in the F4 viewer what the Rage is doing - set_pen_color(index, (color>>16) & 0xff, (color>>8) & 0xff, color & 0xff); -} - -u32 mach64_device::framebuffer_r(offs_t offset, u32 mem_mask) -{ - const u32 *target = (u32 *)&vga.memory[offset<<2]; - return *target; -} - -void mach64_device::framebuffer_w(offs_t offset, u32 data, u32 mem_mask) -{ - COMBINE_DATA((u32*)&vga.memory[offset<<2]); -} - -u32 mach64_device::framebuffer_be_r(offs_t offset, u32 mem_mask) -{ - const u32 *target = (u32 *)&vga.memory[offset<<2]; - return swapendian_int32(*target); -} - -void mach64_device::framebuffer_be_w(offs_t offset, u32 data, u32 mem_mask) -{ - data = swapendian_int32(data); - mem_mask = swapendian_int32(mem_mask); - COMBINE_DATA((u32*)&vga.memory[offset<<2]); -} diff --git a/src/devices/bus/isa/mach32.h b/src/devices/bus/isa/mach32.h deleted file mode 100644 index 09ad9475cb9..00000000000 --- a/src/devices/bus/isa/mach32.h +++ /dev/null @@ -1,243 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Barry Rodewald -/* - * mach32.h - * - * Created on: 16/05/2014 - */ - -#ifndef MAME_BUS_ISA_MACH32_H -#define MAME_BUS_ISA_MACH32_H - -#pragma once - -#include "video/pc_vga.h" -#include "machine/eepromser.h" - -#define LOG_MACH32 1 - -// 8514/A module of the Mach32 -class mach32_8514a_device : public mach8_device -{ -public: - // construction/destruction - mach32_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - uint16_t mach32_chipid_r() { return m_chip_ID; } - uint16_t mach32_mem_boundary_r() { return m_membounds; } - void mach32_mem_boundary_w(uint16_t data) { m_membounds = data; if(data & 0x10) logerror("ATI: Unimplemented memory boundary activated."); } - void mach32_ge_ext_config_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - - uint16_t mach32_config1_r(); - void mach32_horz_overscan_w(uint16_t data) {} // TODO - uint16_t mach32_ext_ge_r() { return 0x0000; } // TODO - - bool has_display_mode_changed() { if(display_mode_change) { display_mode_change = false; return true; } else return false; } - -protected: - mach32_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void device_reset() override; - - uint16_t m_chip_ID; - uint16_t m_membounds; - bool display_mode_change; - -}; - -// main SVGA device -class mach32_device : public ati_vga_device -{ -public: - // construction/destruction - mach32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override; - uint32_t draw_hw_cursor(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - - required_device m_8514a; // provides accelerated 2D drawing, derived from the Mach8 device - - // map 8514/A functions to 8514/A module - uint16_t mach8_ec0_r() { return m_8514a->mach8_ec0_r(); } - void mach8_ec0_w(uint16_t data) { m_8514a->mach8_ec0_w(data); } - uint16_t mach8_ec1_r() { return m_8514a->mach8_ec1_r(); } - void mach8_ec1_w(uint16_t data) { m_8514a->mach8_ec1_w(data); } - uint16_t mach8_ec2_r() { return m_8514a->mach8_ec2_r(); } - void mach8_ec2_w(uint16_t data) { m_8514a->mach8_ec2_w(data); } - uint16_t mach8_ec3_r() { return m_8514a->mach8_ec3_r(); } - void mach8_ec3_w(uint16_t data) { m_8514a->mach8_ec3_w(data); } - uint16_t mach8_ext_fifo_r() { return m_8514a->mach8_ext_fifo_r(); } - void mach8_linedraw_index_w(uint16_t data) { m_8514a->mach8_linedraw_index_w(data); } - uint16_t mach8_bresenham_count_r() { return m_8514a->mach8_bresenham_count_r(); } - void mach8_bresenham_count_w(uint16_t data) { m_8514a->mach8_bresenham_count_w(data); } - void mach8_linedraw_w(uint16_t data) { m_8514a->mach8_linedraw_w(data); } - uint16_t mach8_linedraw_r() { return m_8514a->mach8_linedraw_r(); } - uint16_t mach8_scratch0_r() { return m_8514a->mach8_scratch0_r(); } - void mach8_scratch0_w(uint16_t data) { m_8514a->mach8_scratch0_w(data); } - uint16_t mach8_scratch1_r() { return m_8514a->mach8_scratch1_r(); } - void mach8_scratch1_w(uint16_t data) { m_8514a->mach8_scratch1_w(data); } - void mach8_crt_pitch_w(uint16_t data) { m_8514a->mach8_crt_pitch_w(data); } - uint16_t mach8_config1_r() { return m_8514a->mach8_config1_r(); } - uint16_t mach8_config2_smo_r() { return m_8514a->mach8_config2_r(); } - uint16_t mach8_config2_sm_r(offs_t offset) { return m_8514a->mach8_config2_r(); } - uint16_t mach8_sourcex_r() { return m_8514a->mach8_sourcex_r(); } - uint16_t mach8_sourcey_r() { return m_8514a->mach8_sourcey_r(); } - void mach8_ext_leftscissor_w(uint16_t data) { m_8514a->mach8_ext_leftscissor_w(data); } - void mach8_ext_topscissor_w(uint16_t data) { m_8514a->mach8_ext_topscissor_w(data); } - void mach8_ge_offset_l_w(uint16_t data) { m_8514a->mach8_ge_offset_l_w(data); } - void mach8_ge_offset_h_w(uint16_t data) { m_8514a->mach8_ge_offset_h_w(data); } - void mach8_scan_x_w(uint16_t data) { m_8514a->mach8_scan_x_w(data); } - void mach8_dp_config_w(uint16_t data) { m_8514a->mach8_dp_config_w(data); } - void mach8_ge_pitch_w(uint16_t data) { m_8514a->mach8_ge_pitch_w(data); } - uint16_t mach8_ge_ext_config_r() { return m_8514a->mach8_ge_ext_config_r(); } - void mach8_patt_data_w(uint16_t data) { m_8514a->mach8_patt_data_w(data); } - - uint16_t ibm8514_vtotal_r() { return m_8514a->ibm8514_vtotal_r(); } - void ibm8514_vtotal_w(uint16_t data) { m_8514a->ibm8514_vtotal_w(data); } - uint16_t ibm8514_htotal_r() { return m_8514a->ibm8514_htotal_r(); } - void ibm8514_htotal_w(offs_t offset, uint8_t data) { m_8514a->ibm8514_htotal_w(offset,data); } - uint16_t ibm8514_vdisp_r() { return m_8514a->ibm8514_vdisp_r(); } - void ibm8514_vdisp_w(uint16_t data) { m_8514a->ibm8514_vdisp_w(data); } - uint16_t ibm8514_vsync_r() { return m_8514a->ibm8514_vsync_r(); } - void ibm8514_vsync_w(uint16_t data) { m_8514a->ibm8514_vsync_w(data); } - uint16_t ibm8514_substatus_r() { return m_8514a->ibm8514_substatus_r(); } - void ibm8514_subcontrol_w(uint16_t data) { m_8514a->ibm8514_subcontrol_w(data); } - uint16_t ibm8514_subcontrol_r() { return m_8514a->ibm8514_subcontrol_r(); } - uint16_t ibm8514_currentx_r() { return m_8514a->ibm8514_currentx_r(); } - void ibm8514_currentx_w(uint16_t data) { m_8514a->ibm8514_currentx_w(data); } - uint16_t ibm8514_currenty_r() { return m_8514a->ibm8514_currenty_r(); } - void ibm8514_currenty_w(uint16_t data) { m_8514a->ibm8514_currenty_w(data); } - uint16_t ibm8514_desty_r() { return m_8514a->ibm8514_desty_r(); } - void ibm8514_desty_w(uint16_t data) { m_8514a->ibm8514_desty_w(data); } - uint16_t ibm8514_destx_r() { return m_8514a->ibm8514_destx_r(); } - void ibm8514_destx_w(uint16_t data) { m_8514a->ibm8514_destx_w(data); } - uint16_t ibm8514_line_error_r() { return m_8514a->ibm8514_line_error_r(); } - void ibm8514_line_error_w(uint16_t data) { m_8514a->ibm8514_line_error_w(data); } - uint16_t ibm8514_width_r() { return m_8514a->ibm8514_width_r(); } - void ibm8514_width_w(uint16_t data) { m_8514a->ibm8514_width_w(data); } - uint16_t ibm8514_gpstatus_r() { return m_8514a->ibm8514_gpstatus_r(); } - void ibm8514_cmd_w(uint16_t data) { m_8514a->ibm8514_cmd_w(data); } - uint16_t ibm8514_ssv_r() { return m_8514a->ibm8514_ssv_r(); } - void ibm8514_ssv_w(uint16_t data) { m_8514a->ibm8514_ssv_w(data); } - uint16_t ibm8514_fgcolour_r() { return m_8514a->ibm8514_fgcolour_r(); } - void ibm8514_fgcolour_w(uint16_t data) { m_8514a->ibm8514_fgcolour_w(data); } - uint16_t ibm8514_bgcolour_r() { return m_8514a->ibm8514_bgcolour_r(); } - void ibm8514_bgcolour_w(uint16_t data) { m_8514a->ibm8514_bgcolour_w(data); } - uint16_t ibm8514_read_mask_r() { return m_8514a->ibm8514_read_mask_r(); } - void ibm8514_read_mask_w(uint16_t data) { m_8514a->ibm8514_read_mask_w(data); } - uint16_t ibm8514_write_mask_r() { return m_8514a->ibm8514_write_mask_r(); } - void ibm8514_write_mask_w(uint16_t data) { m_8514a->ibm8514_write_mask_w(data); } - uint16_t ibm8514_backmix_r() { return m_8514a->ibm8514_backmix_r(); } - void ibm8514_backmix_w(uint16_t data) { m_8514a->ibm8514_backmix_w(data); } - uint16_t ibm8514_foremix_r() { return m_8514a->ibm8514_foremix_r(); } - void ibm8514_foremix_w(uint16_t data) { m_8514a->ibm8514_foremix_w(data); } - uint16_t ibm8514_multifunc_r() { return m_8514a->ibm8514_multifunc_r(); } - void ibm8514_multifunc_w(uint16_t data) { m_8514a->ibm8514_multifunc_w(data); } - uint16_t ibm8514_pixel_xfer_r(offs_t offset) { return m_8514a->ibm8514_pixel_xfer_r(offset); } - void mach8_pixel_xfer_w(offs_t offset, uint16_t data) { m_8514a->mach8_pixel_xfer_w(offset, data); } - void mach8_advfunc_w(uint16_t data) { m_8514a->mach8_advfunc_w(data); } - - uint16_t mach32_chipid_r() { return m_8514a->mach32_chipid_r(); } - uint16_t mach8_clksel_r() { return m_8514a->mach8_clksel_r(); } - void mach8_clksel_w(uint16_t data) { m_8514a->mach8_clksel_w(data); } // read only on the mach8 - uint16_t mach32_mem_boundary_r() { return m_8514a->mach32_mem_boundary_r(); } - void mach32_mem_boundary_w(uint16_t data) { m_8514a->mach32_mem_boundary_w(data); } // read only on the mach8 - uint8_t mach32_status_r(offs_t offset) { return m_8514a->ibm8514_status_r(offset); } - uint16_t mach32_config1_smo_r() { return m_8514a->mach32_config1_r(); } - uint16_t mach32_config1_sm_r(offs_t offset) { return m_8514a->mach32_config1_r(); } - void mach32_horz_overscan_w(uint16_t data) { m_8514a->mach32_horz_overscan_w(data); } - void mach32_ge_ext_config_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { m_8514a->mach32_ge_ext_config_w(offset, data, mem_mask); ati_define_video_mode(); } - uint16_t mach32_ext_ge_r() { return m_8514a->mach32_ext_ge_r(); } - uint16_t mach32_readonly_s_r(offs_t offset, uint16_t mem_mask) { return 0; } - uint16_t mach32_readonly_sm_r(offs_t offset) { return 0; } - uint16_t mach32_readonly_smo_r() { return 0; } - void mach32_cursor_pos_h(offs_t offset, uint16_t data); - void mach32_cursor_pos_v(offs_t offset, uint16_t data); - void mach32_cursor_colour_b_w(offs_t offset, uint16_t data); - void mach32_cursor_colour_0_w(offs_t offset, uint16_t data); - void mach32_cursor_colour_1_w(offs_t offset, uint16_t data); - void mach32_cursor_l_w(offs_t offset, uint16_t data); - void mach32_cursor_h_w(offs_t offset, uint16_t data); - void mach32_cursor_offset_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - -protected: - mach32_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_add_mconfig(machine_config &config) override; - virtual void ati_define_video_mode() override; - virtual uint16_t offset() override; - - // hardware pointer - bool m_cursor_enable; - uint32_t m_cursor_address; - uint16_t m_cursor_horizontal; - uint16_t m_cursor_vertical; - uint8_t m_cursor_colour0_b; - uint8_t m_cursor_colour0_r; - uint8_t m_cursor_colour0_g; - uint8_t m_cursor_colour1_b; - uint8_t m_cursor_colour1_r; - uint8_t m_cursor_colour1_g; - uint8_t m_cursor_offset_horizontal; - uint8_t m_cursor_offset_vertical; - -}; - -/* - * ATi mach64 - */ - -// 8514/A module of the Mach64 -class mach64_8514a_device : public mach32_8514a_device -{ -public: - // construction/destruction - mach64_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - mach64_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void device_reset() override; -}; - -// main SVGA device -class mach64_device : public mach32_device -{ -public: - // construction/destruction - mach64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - void mach64_config1_w(uint16_t data) { } // why does the mach64 BIOS write to these, they are read only on the mach32 and earlier - void mach64_config2_w(uint16_t data) { } - - void set_color(u8 index, u32 color); - u32 framebuffer_r(offs_t offset, u32 mem_mask); - void framebuffer_w(offs_t offset, u32 data, u32 mem_mask); - u32 framebuffer_be_r(offs_t offset, u32 mem_mask); - void framebuffer_be_w(offs_t offset, u32 data, u32 mem_mask); - u8 *get_framebuffer_addr() { return &vga.memory[0]; } - -protected: - mach64_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_add_mconfig(machine_config &config) override; - - required_device m_8514a; // provides accelerated 2D drawing, derived from the Mach8 device - -private: -}; - -// device type definition -DECLARE_DEVICE_TYPE(ATIMACH32, mach32_device) -DECLARE_DEVICE_TYPE(ATIMACH32_8514A, mach32_8514a_device) -DECLARE_DEVICE_TYPE(ATIMACH64, mach64_device) -DECLARE_DEVICE_TYPE(ATIMACH64_8514A, mach64_8514a_device) - -#endif // MAME_BUS_ISA_MACH32_H diff --git a/src/devices/bus/isa/s3virge.cpp b/src/devices/bus/isa/s3virge.cpp index aa41b8d0ce9..737256d8b61 100644 --- a/src/devices/bus/isa/s3virge.cpp +++ b/src/devices/bus/isa/s3virge.cpp @@ -88,7 +88,6 @@ void s3virge_vga_device::device_start() vga.crtc.maximum_scan_line = 1; // copy over interfaces - vga.read_dipswitch.set(nullptr); //read_dipswitch; vga.svga_intf.seq_regcount = 0x1c; vga.svga_intf.crtc_regcount = 0x19; vga.memory = std::make_unique(vga.svga_intf.vram_size); @@ -759,7 +758,7 @@ uint8_t s3virge_vga_device::port_03b0_r(offs_t offset) { uint8_t res = 0xff; - if (CRTC_PORT_ADDR == 0x3b0) + if (get_crtc_port() == 0x3b0) { switch(offset) { @@ -777,7 +776,7 @@ uint8_t s3virge_vga_device::port_03b0_r(offs_t offset) void s3virge_vga_device::port_03b0_w(offs_t offset, uint8_t data) { - if (CRTC_PORT_ADDR == 0x3b0) + if (get_crtc_port() == 0x3b0) { switch(offset) { @@ -820,7 +819,7 @@ uint8_t s3virge_vga_device::port_03d0_r(offs_t offset) { uint8_t res = 0xff; - if (CRTC_PORT_ADDR == 0x3d0) + if (get_crtc_port() == 0x3d0) { switch(offset) { @@ -838,7 +837,7 @@ uint8_t s3virge_vga_device::port_03d0_r(offs_t offset) void s3virge_vga_device::port_03d0_w(offs_t offset, uint8_t data) { - if (CRTC_PORT_ADDR == 0x3d0) + if (get_crtc_port() == 0x3d0) { switch(offset) { diff --git a/src/devices/bus/isa/s3virge.h b/src/devices/bus/isa/s3virge.h index 03281adfe19..ba2abd8cfd9 100644 --- a/src/devices/bus/isa/s3virge.h +++ b/src/devices/bus/isa/s3virge.h @@ -12,7 +12,7 @@ #pragma once -#include "video/pc_vga.h" +#include "video/pc_vga_s3.h" // ======================> s3virge_vga_device @@ -52,7 +52,6 @@ public: } } - uint16_t get_crtc_port() { return (vga.miscellaneous_output&1)?0x3d0:0x3b0; } uint32_t get_linear_address() { return s3virge.linear_address; } void set_linear_address(uint32_t addr) { s3virge.linear_address = addr; } uint8_t get_linear_address_size() { return s3virge.linear_address_size; } diff --git a/src/devices/bus/isa/svga_s3.h b/src/devices/bus/isa/svga_s3.h index a07b0e039c6..b5b650bd594 100644 --- a/src/devices/bus/isa/svga_s3.h +++ b/src/devices/bus/isa/svga_s3.h @@ -6,7 +6,7 @@ #pragma once #include "isa.h" -#include "video/pc_vga.h" +#include "video/pc_vga_s3.h" #include "s3virge.h" //************************************************************************** diff --git a/src/devices/bus/isa/svga_trident.cpp b/src/devices/bus/isa/svga_trident.cpp index f3b4e0f9a6f..2d818d76735 100644 --- a/src/devices/bus/isa/svga_trident.cpp +++ b/src/devices/bus/isa/svga_trident.cpp @@ -1,17 +1,77 @@ // license:BSD-3-Clause // copyright-holders:Barry Rodewald /* - * svga_trident.c + * svga_trident.cpp * * Created on: 6/09/2014 + * + * TODO: + * - tgui9680 is a PCI card, not ISA! + * \- the only client is pc/calchase.cpp, which at the time of this writing uses legacy PCI bus; + * */ #include "emu.h" #include "svga_trident.h" -#include "video/pc_vga.h" +#include "video/pc_vga_trident.h" #include "screen.h" +ROM_START( tvga9000 ) + ROM_REGION( 0x8000, "tvga9000", 0 ) + ROM_SYSTEM_BIOS(0, "v350", "Version D3.50 12/02/92") + ROMX_LOAD( "trident_quadtel_tvga9000_isa16.bin", 0x0000, 0x8000, CRC(ad0e7351) SHA1(eb525460a80e1c1baa34642b93d54caf2607920d), ROM_BIOS(0) ) + ROM_IGNORE ( 0x8000 ) + ROM_SYSTEM_BIOS(1, "v300", "Version D3.00 11/12/91") + ROMX_LOAD( "quadtel_tvga_bios_software_1991_ver_d3_0_lh.bin", 0x0000, 0x8000, CRC(d35a8ce9) SHA1(9cff3cb86a85dcbd34234bc4fd1dd0011f3d48fd), ROM_BIOS(1) ) + ROM_IGNORE ( 0x8000 ) +ROM_END + +DEFINE_DEVICE_TYPE(ISA16_SVGA_TVGA9000, isa16_svga_tvga9000_device, "tvga9000", "Trident/Quadtel TVGA9000B SVGA card") + +void isa16_svga_tvga9000_device::device_add_mconfig(machine_config &config) +{ + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480); + screen.set_screen_update(m_vga, FUNC(trident_vga_device::screen_update)); + + TVGA9000_VGA(config, m_vga, 0); + m_vga->set_screen("screen"); + m_vga->set_vram_size(512 * 1024); // 0x80000 +} + +const tiny_rom_entry *isa16_svga_tvga9000_device::device_rom_region() const +{ + return ROM_NAME( tvga9000 ); +} + +isa16_svga_tvga9000_device::isa16_svga_tvga9000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, ISA16_SVGA_TVGA9000, tag, owner, clock) + , device_isa16_card_interface(mconfig, *this) + , m_vga(*this, "vga") +{ +} + +uint8_t isa16_svga_tvga9000_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); } + +void isa16_svga_tvga9000_device::device_start() +{ + set_isa_device(); + + m_isa->install_rom(this, 0xc0000, 0xc7fff, "tvga9000"); + + m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03b0_w))); + m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03c0_w))); + m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_03d0_w))); + m_isa->install_device(0x43c4, 0x43cb, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_43c6_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_43c6_w))); + m_isa->install_device(0x83c4, 0x83cb, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_83c6_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_83c6_w))); + + m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(tvga9000_device::mem_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::mem_w))); +} + +/* + * TGUI9680 + */ ROM_START( tgui9680 ) ROM_REGION( 0x8000, "tgui9680", 0 ) @@ -19,9 +79,6 @@ ROM_START( tgui9680 ) ROM_CONTINUE( 0x0001, 0x4000 ) ROM_END -//************************************************************************** -// GLOBAL VARIABLES -//************************************************************************** DEFINE_DEVICE_TYPE(ISA16_SVGA_TGUI9680, isa16_svga_tgui9680_device, "tgui9680", "Trident TGUI9680 Graphics Card (BIOS X5.5 (02) 02/13/96)") @@ -58,10 +115,10 @@ const tiny_rom_entry *isa16_svga_tgui9680_device::device_rom_region() const // isa8_vga_device - constructor //------------------------------------------------- -isa16_svga_tgui9680_device::isa16_svga_tgui9680_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, ISA16_SVGA_TGUI9680, tag, owner, clock), - device_isa16_card_interface(mconfig, *this), - m_vga(*this, "vga") +isa16_svga_tgui9680_device::isa16_svga_tgui9680_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, ISA16_SVGA_TGUI9680, tag, owner, clock) + , device_isa16_card_interface(mconfig, *this) + , m_vga(*this, "vga") { } @@ -88,16 +145,8 @@ void isa16_svga_tgui9680_device::device_start() // m_isa->install_memory(0x4400000, 0x45fffff, read8sm_delegate(*m_vga, FUNC(trident_vga_device::vram_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::vram_w))); // win95 drivers -// m_isa->install_memory(0x4000000, 0x41fffff, read8sm_delegate(*m_vga, FUNC(trident_vga_device::vram_r)), write8sm_delegate(FUNC(*m_vga, trident_vga_device::vram_w))); +// m_isa->install_memory(0x4000000, 0x41fffff, read8sm_delegate(*m_vga, FUNC(trident_vga_device::vram_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::vram_w))); // acceleration ports m_isa->install_device(0x2120, 0x21ff, read8sm_delegate(*m_vga, FUNC(trident_vga_device::accel_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::accel_w))); } - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void isa16_svga_tgui9680_device::device_reset() -{ -} diff --git a/src/devices/bus/isa/svga_trident.h b/src/devices/bus/isa/svga_trident.h index c5c7bfdcf1d..350d598f213 100644 --- a/src/devices/bus/isa/svga_trident.h +++ b/src/devices/bus/isa/svga_trident.h @@ -10,14 +10,33 @@ #define MAME_BUS_ISA_SVGA_TRIDENT_H #include "isa.h" -#include "video/pc_vga.h" -#include "bus/isa/trident.h" +#include "video/pc_vga_trident.h" //************************************************************************** // TYPE DEFINITIONS //************************************************************************** -// ======================> isa16_vga_device +class isa16_svga_tvga9000_device : + public device_t, + public device_isa16_card_interface +{ +public: + // construction/destruction + isa16_svga_tvga9000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + uint8_t input_port_0_r(); + +protected: + // device-level overrides + virtual void device_start() override; + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + +private: + required_device m_vga; +}; class isa16_svga_tgui9680_device : public device_t, @@ -32,7 +51,6 @@ public: protected: // device-level overrides virtual void device_start() override; - virtual void device_reset() override; // optional information overrides virtual void device_add_mconfig(machine_config &config) override; @@ -44,6 +62,7 @@ private: // device type definition +DECLARE_DEVICE_TYPE(ISA16_SVGA_TVGA9000, isa16_svga_tvga9000_device) DECLARE_DEVICE_TYPE(ISA16_SVGA_TGUI9680, isa16_svga_tgui9680_device) diff --git a/src/devices/bus/isa/svga_tseng.cpp b/src/devices/bus/isa/svga_tseng.cpp index 0d1485ad17d..be93e3188fe 100644 --- a/src/devices/bus/isa/svga_tseng.cpp +++ b/src/devices/bus/isa/svga_tseng.cpp @@ -4,25 +4,36 @@ ISA SVGA Tseng wrapper + TODO: + - Implement Korean font ROM for Kasan 16 + ***************************************************************************/ #include "emu.h" #include "svga_tseng.h" -#include "video/pc_vga.h" - -#include "screen.h" - +/* + * (tseng labs famous et4000 isa vga card (oem)) + * ROM_LOAD("et4000b.bin", 0xc0000, 0x8000, CRC(a903540d) SHA1(unknown) ) + * + * Version "8.06X 04/15/92" (yay for semver) + * Tested, draws corrupted GFX, likely bad + * ROM_LOAD("et4000.bin.other", 0xc0000, 0x8000, CRC(f01e4be0) SHA1(95d75ff41bcb765e50bd87a8da01835fd0aa01d5) ) + */ ROM_START( et4000 ) ROM_REGION(0x8000,"et4000", 0) - ROM_LOAD("et4000.bin", 0x00000, 0x8000, CRC(f1e817a8) SHA1(945d405b0fb4b8f26830d495881f8587d90e5ef9) ) + ROM_SYSTEM_BIOS(0, "v801x", "Tseng Version 8.01X 04/07/93") + ROMX_LOAD("et4000.bin", 0x00000, 0x8000, CRC(f1e817a8) SHA1(945d405b0fb4b8f26830d495881f8587d90e5ef9), ROM_BIOS(0) ) + ROM_SYSTEM_BIOS(1, "v800x", "ColorImage Version 8.00X 09/18/90") + ROMX_LOAD("cvet4kax.bin", 0x00000, 0x8000, CRC(a3ab496c) SHA1(8644b4178cd0e841139bfa06c9da493dd74d22e8), ROM_BIOS(1) ) ROM_END //************************************************************************** // GLOBAL VARIABLES //************************************************************************** -DEFINE_DEVICE_TYPE(ISA8_SVGA_ET4K, isa8_svga_et4k_device, "et4000", "SVGA Tseng ET4000 Graphics Card") +DEFINE_DEVICE_TYPE(ISA8_SVGA_ET4K, isa8_svga_et4k_device, "et4000", "SVGA Tseng ET4000AX Graphics Card") +DEFINE_DEVICE_TYPE(ISA8_SVGA_ET4K_KASAN16, isa8_svga_et4k_kasan16_device, "et4000_kasan16", "SVGA Kasan Hangulmadang-16 ET4000AX Graphics Card") //------------------------------------------------- @@ -58,9 +69,14 @@ const tiny_rom_entry *isa8_svga_et4k_device::device_rom_region() const //------------------------------------------------- isa8_svga_et4k_device::isa8_svga_et4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, ISA8_SVGA_ET4K, tag, owner, clock), - device_isa8_card_interface(mconfig, *this), - m_vga(*this, "vga") + isa8_svga_et4k_device(mconfig, ISA8_SVGA_ET4K, tag, owner, clock) +{ +} + +isa8_svga_et4k_device::isa8_svga_et4k_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_isa8_card_interface(mconfig, *this) + , m_vga(*this, "vga") { } @@ -118,3 +134,29 @@ void isa8_svga_et4k_device::map_rom() { m_isa->install_rom(this, 0xc0000, 0xc7fff, "et4000"); } + +/* + * Korean cards + * + * Same as regular ET4000AX with extra font I/Os + */ + +isa8_svga_et4k_kasan16_device::isa8_svga_et4k_kasan16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : isa8_svga_et4k_device(mconfig, ISA8_SVGA_ET4K_KASAN16, tag, owner, clock) + , m_hangul_rom(*this, "hangul") +{ +} + +ROM_START( kasan16 ) + ROM_REGION(0x8000,"et4000", 0) + ROM_SYSTEM_BIOS(0, "v802x", "Version 8.02X 06/13/90, Kasan BIOS Ver 1.0a 05/01/91") + ROMX_LOAD("et4000_kasan16.bin", 0x00000, 0x8000, CRC(57bcc3ad) SHA1(a55e7eb27ef2b4f118ea2028835e88988f07cf57), ROM_BIOS(0) ) + + ROM_REGION(0x80000, "hangul", 0) + ROM_LOAD("kasan_ksc5601.rom", 0x00000, 0x80000, CRC(a547c5ec) SHA1(1358feb2ccaca040a176bedc7c256ec481351b41) ) +ROM_END + +const tiny_rom_entry *isa8_svga_et4k_kasan16_device::device_rom_region() const +{ + return ROM_NAME( kasan16 ); +} diff --git a/src/devices/bus/isa/svga_tseng.h b/src/devices/bus/isa/svga_tseng.h index 690956741b5..6603b3b9d71 100644 --- a/src/devices/bus/isa/svga_tseng.h +++ b/src/devices/bus/isa/svga_tseng.h @@ -6,7 +6,8 @@ #pragma once #include "isa.h" -#include "video/pc_vga.h" +#include "video/pc_vga_tseng.h" +#include "screen.h" //************************************************************************** // TYPE DEFINITIONS @@ -27,6 +28,8 @@ public: virtual void remap(int space_id, offs_t start, offs_t end) override; protected: + isa8_svga_et4k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + // device-level overrides virtual void device_start() override; virtual void device_reset() override; @@ -42,8 +45,21 @@ private: required_device m_vga; }; +class isa8_svga_et4k_kasan16_device : + public isa8_svga_et4k_device +{ +public: + isa8_svga_et4k_kasan16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + +private: + required_region_ptr m_hangul_rom; +}; // device type definition -DECLARE_DEVICE_TYPE(ISA8_SVGA_ET4K, isa8_svga_et4k_device) +DECLARE_DEVICE_TYPE(ISA8_SVGA_ET4K, isa8_svga_et4k_device) +DECLARE_DEVICE_TYPE(ISA8_SVGA_ET4K_KASAN16, isa8_svga_et4k_kasan16_device) #endif // MAME_BUS_ISA_SVGA_TSENG_H diff --git a/src/devices/bus/isa/trident.cpp b/src/devices/bus/isa/trident.cpp deleted file mode 100644 index b7b4117ae25..00000000000 --- a/src/devices/bus/isa/trident.cpp +++ /dev/null @@ -1,1709 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Barry Rodewald -/* - * trident.cpp - * - * Implementation of Trident VGA GUI accelerators - * - * - */ - -#include "emu.h" -#include "trident.h" - -#include "debugger.h" -#include "screen.h" - -#define LOG_WARN (1U << 1) -#define LOG_TODO (1U << 2) -#define LOG_ACCEL (1U << 3) -#define LOG_CRTC (1U << 4) - -#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_ACCEL | LOG_TODO | LOG_CRTC) - -#include "logmacro.h" - -#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) -#define LOGACCEL(...) LOGMASKED(LOG_ACCEL, __VA_ARGS__) -#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__) -#define LOGCRTC(...) LOGMASKED(LOG_CRTC, __VA_ARGS__) - -DEFINE_DEVICE_TYPE(TRIDENT_VGA, tgui9860_device, "trident_vga", "Trident TGUI9860") -DEFINE_DEVICE_TYPE(TVGA9000_VGA, tvga9000_device, "tvga9000_vga", "Trident TVGA9000") - -#define CRTC_PORT_ADDR ((vga.miscellaneous_output&1)?0x3d0:0x3b0) - -trident_vga_device::trident_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) -{ -} - -tgui9860_device::tgui9860_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : trident_vga_device(mconfig, TRIDENT_VGA, tag, owner, clock) -{ - m_version = 0xd3; // 0xd3 identifies at TGUI9660XGi (set to 0xe3 to identify at TGUI9440AGi) -} - -tvga9000_device::tvga9000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : trident_vga_device(mconfig, TVGA9000_VGA, tag, owner, clock) -{ - m_version = 0x43; -} - -uint8_t trident_vga_device::READPIXEL8(int16_t x, int16_t y) -{ - return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)) % vga.svga_intf.vram_size]); -} - -uint16_t trident_vga_device::READPIXEL15(int16_t x, int16_t y) -{ - return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*2) % vga.svga_intf.vram_size] | - (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*2)+1) % vga.svga_intf.vram_size] << 8)); -} - -uint16_t trident_vga_device::READPIXEL16(int16_t x, int16_t y) -{ - return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*2) % vga.svga_intf.vram_size] | - (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*2)+1) % vga.svga_intf.vram_size] << 8)); -} - -uint32_t trident_vga_device::READPIXEL32(int16_t x, int16_t y) -{ - return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*4) % vga.svga_intf.vram_size] | - (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+1) % vga.svga_intf.vram_size] << 8) | - (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+2) % vga.svga_intf.vram_size] << 16) | - (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+3) % vga.svga_intf.vram_size] << 24)); -} - -void trident_vga_device::WRITEPIXEL8(int16_t x, int16_t y, uint8_t data) -{ - if((x & 0xfff)> 8; - } -} - -void trident_vga_device::WRITEPIXEL16(int16_t x, int16_t y, uint16_t data) -{ - if((x & 0xfff)> 8; - } -} - -void trident_vga_device::WRITEPIXEL32(int16_t x, int16_t y, uint32_t data) -{ - if((x & 0xfff)> 8; - vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+2) % vga.svga_intf.vram_size] = (data & 0x00ff0000) >> 16; - vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+3) % vga.svga_intf.vram_size] = (data & 0xff000000) >> 24; - } -} - -uint32_t trident_vga_device::handle_rop(uint32_t src, uint32_t dst) -{ - switch(tri.accel_fmix) // TODO: better understand this register - { - case 0xf0: // PAT - case 0xcc: // SRC - break; // pass data through - case 0x00: // 0 - src = 0; - break; - case 0xff: // 1 - src = 0xffffffff; - break; - case 0x66: // XOR - case 0x5a: // XOR PAT - src = dst ^ src; - break; - case 0xb8: // PAT xor (SRC and (DST xor PAT)) (correct?) - src = src & (dst ^ src); - break; - } - return src; -} - -uint32_t trident_vga_device::READPIXEL(int16_t x,int16_t y) -{ - if(svga.rgb8_en) - return READPIXEL8(x,y) & 0xff; - if(svga.rgb15_en) - return READPIXEL15(x,y) & 0x7fff; - if(svga.rgb16_en) - return READPIXEL16(x,y) & 0xffff; - if(svga.rgb32_en) - return READPIXEL32(x,y); - return 0; // should never reach here -} - -void trident_vga_device::WRITEPIXEL(int16_t x,int16_t y, uint32_t data) -{ - if(svga.rgb8_en) - WRITEPIXEL8(x,y,(((data >> 8) & 0xff) | (data & 0xff))); // XFree86 3.3 sets bits 0-7 to 0 when using mono patterns, does it OR each byte? - if(svga.rgb15_en) - WRITEPIXEL15(x,y,data & 0x7fff); - if(svga.rgb16_en) - WRITEPIXEL16(x,y,data & 0xffff); - if(svga.rgb32_en) - WRITEPIXEL32(x,y,data); -} - - -void trident_vga_device::device_start() -{ - zero(); - - 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.set(nullptr); //read_dipswitch; - vga.memory = std::make_unique(vga.svga_intf.vram_size); - memset(&vga.memory[0], 0, vga.svga_intf.vram_size); - - save_pointer(NAME(vga.memory), vga.svga_intf.vram_size); - save_pointer(vga.crtc.data,"CRTC Registers",0x100); - save_pointer(vga.sequencer.data,"Sequencer Registers",0x100); - save_pointer(vga.attribute.data,"Attribute Registers", 0x15); - save_pointer(tri.accel_pattern,"Pattern Data", 0x80); - save_pointer(tri.lutdac_reg,"LUTDAC registers", 0x100); - - m_vblank_timer = timer_alloc(FUNC(vga_device::vblank_timer_cb), this); - vga.svga_intf.seq_regcount = 0x0f; - vga.svga_intf.crtc_regcount = 0x60; - svga.ignore_chain4 = true; - memset(&tri, 0, sizeof(tri)); -} - -void trident_vga_device::device_reset() -{ - svga_device::device_reset(); - svga.id = m_version; - tri.revision = 0x01; // revision identifies as TGUI9680 - tri.new_mode = false; // start up in old mode - tri.dac_active = false; - tri.linear_active = false; - tri.mmio_active = false; - tri.sr0f = 0x6f; - tri.sr0c = 0x70; - tri.cr2a = 0x03; // set ISA interface? - tri.mem_clock = 0x2c6; // 50MHz default - tri.vid_clock = 0; - tri.port_3c3 = true; - tri.accel_busy = false; - tri.accel_memwrite_active = false; - // Windows 3.1 TGUI9440AGi drivers do not set the pointer colour registers? - tri.cursor_bg = 0x00000000; - tri.cursor_fg = 0xffffffff; - tri.pixel_depth = 0x10; //disable 8bpp mode by default -} - -uint32_t trident_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - svga_device::screen_update(screen,bitmap,cliprect); - uint8_t const cur_mode = pc_vga_choosevideomode(); - - // draw hardware graphics cursor - if(tri.cursor_ctrl & 0x80) // if cursor is enabled - { - uint16_t const cx = tri.cursor_x & 0x0fff; - uint16_t const cy = tri.cursor_y & 0x0fff; - uint8_t const cursor_size = (tri.cursor_ctrl & 0x01) ? 64 : 32; - - 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 - - uint32_t src = tri.cursor_loc * 1024; // start address is in units of 1024 bytes - - uint32_t bg_col, fg_col; - if(cur_mode == RGB16_MODE) - { - bg_col = tri.cursor_bg; - fg_col = tri.cursor_fg; - } - else /* TODO: other modes */ - { - bg_col = pen(tri.cursor_bg & 0xff); - fg_col = pen(tri.cursor_fg & 0xff); - } - - for(int y=0;y> 7; - k = (tri.vid_clock & 0x1000) >> 12; - freq = ((double)(m+8) / (double)((n+2)*(pow(2.0,k)))) * 14.31818; // there is a 14.31818MHz clock on the board - - return freq * 1000000; -} - -void trident_vga_device::trident_define_video_mode() -{ - int divisor = 1; - int xtal; - - /* // clock select for TGUI9440CXi and earlier - switch(tri.clock) - { - case 0: - default: xtal = 25174800; break; - case 1: xtal = 28636363; break; - case 2: xtal = 44900000; break; - case 3: xtal = 36000000; break; - case 4: xtal = 57272000; break; - case 5: xtal = 65000000; break; - case 6: xtal = 50350000; break; - case 7: xtal = 40000000; break; - case 8: xtal = 88000000; break; - case 9: xtal = 98000000; break; - case 10: xtal = 118800000; break; - case 11: xtal = 108000000; break; - case 12: xtal = 72000000; break; - case 13: xtal = 77000000; break; - case 14: xtal = 80000000; break; - case 15: xtal = 75000000; break; - } - - switch((tri.sr0d_new & 0x06) >> 1) - { - case 0: - default: break; // no division - case 1: xtal = xtal / 2; break; - case 2: xtal = xtal / 4; break; - case 3: xtal = xtal / 1.5; break; - }*/ - - - // TGUI9440AGi/9660/9680/9682 programmable clock - switch((vga.miscellaneous_output & 0x0c) >> 2) - { - case 0: - default: xtal = 25174800; break; - case 1: xtal = 28636363; break; - case 2: xtal = calculate_clock(); break; - } - - if(tri.gc0f & 0x08) // 16 pixels per character clock - xtal = xtal / 2; - - if(tri.port_3db & 0x20) - xtal = xtal / 2; // correct? - - svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb32_en = 0; - switch((tri.pixel_depth & 0x0c) >> 2) - { - case 0: - default: if(!(tri.pixel_depth & 0x10) || (tri.cr1e & 0x80)) svga.rgb8_en = 1; break; - case 1: if((tri.dac & 0xf0) == 0x30) svga.rgb16_en = 1; else svga.rgb15_en = 1; break; - case 2: svga.rgb32_en = 1; break; - } - - if((tri.cr1e & 0x80) && (svga.id == 0x43)) - divisor = 2; - - recompute_params_clock(divisor, xtal); -} - -uint8_t trident_vga_device::trident_seq_reg_read(uint8_t index) -{ - uint8_t res; - - res = 0xff; - - if(index <= 0x04) - res = vga.sequencer.data[index]; - else - { - switch(index) - { - case 0x09: - res = tri.revision; - break; - case 0x0b: - res = svga.id; - tri.new_mode = true; - break; - case 0x0c: // Power Up Mode register 1 - res = tri.sr0c & 0xef; - if(tri.port_3c3) - res |= 0x10; - break; - case 0x0d: // Mode Control 2 - //res = svga.rgb15_en; - if(tri.new_mode) - res = tri.sr0d_new; - else - res = tri.sr0d_old; - break; - case 0x0e: // Mode Control 1 - if(tri.new_mode) - res = tri.sr0e_new; - else - res = tri.sr0e_old; - break; - case 0x0f: // Power Up Mode 2 - res = tri.sr0f; - break; - default: - res = vga.sequencer.data[index]; - LOGWARN("Trident: Sequencer index %02x read\n",index); - } - } - LOG("Trident SR%02X: read %02x\n",index,res); - return res; -} - -void trident_vga_device::trident_seq_reg_write(uint8_t index, uint8_t data) -{ - vga.sequencer.data[vga.sequencer.index] = data; - if(index <= 0x04) - { - seq_reg_write(vga.sequencer.index,data); - recompute_params(); - } - else - { - switch(index) - { - case 0x0b: - tri.new_mode = false; - break; - case 0x0c: // Power Up Mode register 1 - if(data & 0x10) - tri.port_3c3 = true; // 'post port at 0x3c3' - else - tri.port_3c3 = false; // 'post port at 0x46e8' - tri.sr0c = data; - break; - case 0x0d: // Mode Control 2 - if(tri.new_mode) - { - tri.sr0d_new = data; - tri.clock = ((vga.miscellaneous_output & 0x0c) >> 2) | ((data & 0x01) << 2) | ((data & 0x40) >> 3); - trident_define_video_mode(); - } - else - tri.sr0d_old = data; - break; - case 0x0e: // Mode Control 1 - if(tri.new_mode) - { - tri.sr0e_new = data ^ 0x02; - svga.bank_w = (data & 0x3f) ^ 0x02; // bit 1 is inverted, used for card detection, it is not XORed on reading - if(!(tri.gc0f & 0x01)) - svga.bank_r = (data & 0x3f) ^ 0x02; - // TODO: handle planar modes, where bits 0 and 2 only are used - } - else - { - tri.sr0e_old = data; - svga.bank_w = data & 0x0e; - if(!(tri.gc0f & 0x01)) - svga.bank_r = data & 0x0e; - } - break; - case 0x0f: // Power Up Mode 2 - tri.sr0f = data; - break; - default: - LOGWARN("Trident: Sequencer index %02x read\n",index); - } - } - LOG("Trident SR%02X: %s mode write %02x\n",index,tri.new_mode ? "new" : "old",data); -} - -uint8_t trident_vga_device::trident_crtc_reg_read(uint8_t index) -{ - uint8_t res = 0; - - if(index <= 0x18) - res = crtc_reg_read(index); - else - { - switch(index) - { - case 0x1e: - res = tri.cr1e; - break; - case 0x1f: - res = tri.cr1f; - break; - case 0x20: - res = tri.cr20; - break; - case 0x21: - res = tri.cr21; - break; - case 0x24: - if(vga.attribute.state != 0) - res |= 0x80; - break; - case 0x26: - res = vga.attribute.index; - break; - case 0x27: - res = (vga.crtc.start_addr & 0x60000) >> 17; - break; - case 0x29: - res = tri.cr29; - break; - case 0x2a: - res = tri.cr2a; - break; - case 0x38: - res = tri.pixel_depth; - break; - case 0x39: - res = tri.cr39; - break; - case 0x40: - res = (tri.cursor_x & 0x00ff); - break; - case 0x41: - res = (tri.cursor_x & 0xff00) >> 8; - break; - case 0x42: - res = (tri.cursor_y & 0x00ff); - break; - case 0x43: - res = (tri.cursor_y & 0xff00) >> 8; - break; - case 0x44: - res = (tri.cursor_loc & 0x00ff); - break; - case 0x45: - res = (tri.cursor_loc & 0xff00) >> 8; - break; - case 0x46: - res = tri.cursor_x_off; - break; - case 0x47: - res = tri.cursor_y_off; - break; - case 0x48: - res = (tri.cursor_fg & 0x000000ff); - break; - case 0x49: - res = (tri.cursor_fg & 0x0000ff00) >> 8; - break; - case 0x4a: - res = (tri.cursor_fg & 0x00ff0000) >> 16; - break; - case 0x4b: - res = (tri.cursor_fg & 0xff000000) >> 24; - break; - case 0x4c: - res = (tri.cursor_bg & 0x000000ff); - break; - case 0x4d: - res = (tri.cursor_bg & 0x0000ff00) >> 8; - break; - case 0x4e: - res = (tri.cursor_bg & 0x00ff0000) >> 16; - break; - case 0x4f: - res = (tri.cursor_bg & 0xff000000) >> 24; - break; - case 0x50: - res = tri.cursor_ctrl; - break; - default: - res = vga.crtc.data[index]; - LOGWARN("Trident: CRTC index %02x read\n",index); - break; - } - } - LOG("Trident CR%02X: read %02x\n",index,res); - return res; -} -void trident_vga_device::trident_crtc_reg_write(uint8_t index, uint8_t data) -{ - if(index <= 0x18) - { - crtc_reg_write(index,data); - trident_define_video_mode(); - } - else - { - switch(index) - { - case 0x1e: // Module Testing Register - tri.cr1e = data; - vga.crtc.start_addr = (vga.crtc.start_addr & 0xfffeffff) | ((data & 0x20)<<11); - trident_define_video_mode(); - break; - case 0x1f: - tri.cr1f = data; // "Software Programming Register" written to by the BIOS - break; - case 0x20: // FIFO Control (old MMIO enable? no documentation of this register) - tri.cr20 = data; - break; - case 0x21: // Linear aperture - tri.cr21 = data; - tri.linear_address = ((data & 0xc0)<<18) | ((data & 0x0f)<<20); - tri.linear_active = data & 0x20; - if(tri.linear_active) - popmessage("Trident: Linear Aperture active - %08x, %s",tri.linear_address,(tri.cr21 & 0x10) ? "2MB" : "1MB" ); - break; - case 0x27: - vga.crtc.start_addr = (vga.crtc.start_addr & 0xfff9ffff) | ((data & 0x03)<<17); - break; - case 0x29: - tri.cr29 = data; - vga.crtc.offset = (vga.crtc.offset & 0xfeff) | ((data & 0x10)<<4); - break; - case 0x2a: - tri.cr2a = data; - break; - case 0x38: - // bit 0: 16 bit bus - // bits 2-3: pixel depth (1=15/16bit, 2=24/32bit, 0=anything else) - // bit 5: packed mode - tri.pixel_depth = data; - trident_define_video_mode(); - break; - case 0x39: - tri.cr39 = data; - tri.mmio_active = data & 0x01; - if(tri.mmio_active) - popmessage("Trident: MMIO activated"); - break; - case 0x40: - tri.cursor_x = (tri.cursor_x & 0xff00) | data; - break; - case 0x41: - tri.cursor_x = (tri.cursor_x & 0x00ff) | (data << 8); - break; - case 0x42: - tri.cursor_y = (tri.cursor_y & 0xff00) | data; - break; - case 0x43: - tri.cursor_y = (tri.cursor_y & 0x00ff) | (data << 8); - break; - case 0x44: - tri.cursor_loc = (tri.cursor_loc & 0xff00) | data; - break; - case 0x45: - tri.cursor_loc = (tri.cursor_loc & 0x00ff) | (data << 8); - break; - case 0x46: - tri.cursor_x_off = data; - break; - case 0x47: - tri.cursor_y_off = data; - break; - case 0x48: - tri.cursor_fg = (tri.cursor_fg & 0xffffff00) | data; - break; - case 0x49: - tri.cursor_fg = (tri.cursor_fg & 0xffff00ff) | (data << 8); - break; - case 0x4a: - tri.cursor_fg = (tri.cursor_fg & 0xff00ffff) | (data << 16); - break; - case 0x4b: - tri.cursor_fg = (tri.cursor_fg & 0x00ffffff) | (data << 24); - break; - case 0x4c: - tri.cursor_bg = (tri.cursor_bg & 0xffffff00) | data; - break; - case 0x4d: - tri.cursor_bg = (tri.cursor_bg & 0xffff00ff) | (data << 8); - break; - case 0x4e: - tri.cursor_bg = (tri.cursor_bg & 0xff00ffff) | (data << 16); - break; - case 0x4f: - tri.cursor_bg = (tri.cursor_bg & 0x00ffffff) | (data << 24); - break; - case 0x50: - tri.cursor_ctrl = data; - break; - default: - LOGWARN("Trident: 3D4 index %02x write %02x\n",index,data); - break; - } - } - LOG("Trident CR%02X: write %02x\n",index,data); -} - -uint8_t trident_vga_device::trident_gc_reg_read(uint8_t index) -{ - uint8_t res; - - if(index <= 0x0d) - res = gc_reg_read(index); - else - { - switch(index) - { - case 0x0e: - res = tri.gc0e; - break; - case 0x0f: - res = tri.gc0f; - break; - case 0x2f: - res = tri.gc2f; - break; - default: - res = 0xff; - LOGWARN("Trident: Sequencer index %02x read\n",index); - break; - } - } - LOG("Trident GC%02X: read %02x\n",index,res); - return res; -} - -void trident_vga_device::trident_gc_reg_write(uint8_t index, uint8_t data) -{ - if(index <= 0x0d) - gc_reg_write(index,data); - else - { - LOG("Trident GC%02X: write %02x\n",index,data); - switch(index) - { - case 0x0e: // New Source Address Register (bit 1 is inverted here, also) - tri.gc0e = data ^ 0x02; - if(!(tri.gc0f & 0x04)) // if bank regs at 0x3d8/9 are not enabled - { - if(tri.gc0f & 0x01) // if bank regs are separated - svga.bank_r = (data & 0x1f) ^ 0x02; - } - break; - case 0x0f: - tri.gc0f = data; - trident_define_video_mode(); - break; - case 0x2f: // XFree86 refers to this register as "MiscIntContReg", setting bit 2, but gives no indication as to what it does - tri.gc2f = data; - break; - default: - LOGWARN("Trident: Unimplemented GC register %02x write %02x\n",index,data); - break; - } - } - LOG("Trident GC%02X: write %02x\n",index,data); -} - -uint8_t trident_vga_device::port_03c0_r(offs_t offset) -{ - uint8_t res; - - switch(offset) - { - case 0x05: - res = trident_seq_reg_read(vga.sequencer.index); - break; - case 0x06: - tri.dac_count++; - if(tri.dac_count > 3) - tri.dac_active = true; - if(tri.dac_active) - res = tri.dac; - else - res = vga_device::port_03c0_r(offset); - break; - case 0x07: - case 0x08: - case 0x09: - tri.dac_active = false; - tri.dac_count = 0; - res = vga_device::port_03c0_r(offset); - break; - case 0x0f: - res = trident_gc_reg_read(vga.gc.index); - break; - default: - res = vga_device::port_03c0_r(offset); - break; - } - - return res; -} - -void trident_vga_device::port_03c0_w(offs_t offset, uint8_t data) -{ - switch(offset) - { - case 0x05: - trident_seq_reg_write(vga.sequencer.index,data); - break; - case 0x06: - if(tri.dac_active) - { - tri.dac = data; // DAC command register - tri.dac_active = false; - tri.dac_count = 0; - trident_define_video_mode(); - } - else - vga_device::port_03c0_w(offset,data); - break; - case 0x07: - case 0x08: - case 0x09: - tri.dac_active = false; - tri.dac_count = 0; - vga_device::port_03c0_w(offset,data); - break; - case 0x0f: - trident_gc_reg_write(vga.gc.index,data); - break; - default: - vga_device::port_03c0_w(offset,data); - break; - } -} - - -uint8_t trident_vga_device::port_03d0_r(offs_t offset) -{ - uint8_t res = 0xff; - - if (CRTC_PORT_ADDR == 0x3d0) - { - switch(offset) - { - case 5: - res = trident_crtc_reg_read(vga.crtc.index); - break; - case 8: - if(tri.gc0f & 0x04) // if enabled - { - res = svga.bank_w & 0x3f; - } - else - res = 0xff; - break; - case 9: - if(tri.gc0f & 0x04) // if enabled - if(tri.gc0f & 0x01) // and if bank regs are separated - res = svga.bank_r & 0x3f; - else - res = 0xff; - else - res = 0xff; - break; - case 11: - res = tri.port_3db; - break; - default: - res = vga_device::port_03d0_r(offset); - break; - } - } - - return res; -} - -void trident_vga_device::port_03d0_w(offs_t offset, uint8_t data) -{ - if (CRTC_PORT_ADDR == 0x3d0) - { - switch(offset) - { - case 5: - vga.crtc.data[vga.crtc.index] = data; - trident_crtc_reg_write(vga.crtc.index,data); - break; - case 8: - if(tri.gc0f & 0x04) // if enabled - { - svga.bank_w = data & 0x3f; - LOG("Trident: Write Bank set to %02x\n",data); - if(!(tri.gc0f & 0x01)) // if bank regs are not separated - { - svga.bank_r = data & 0x3f; // then this is also the read bank register - LOG("Trident: Read Bank set to %02x\n",data); - } - } - break; - case 9: - if(tri.gc0f & 0x04) // if enabled - { - if(tri.gc0f & 0x01) // and if bank regs are separated - { - svga.bank_r = data & 0x3f; - LOG("Trident: Read Bank set to %02x\n",data); - } - } - break; - case 11: - tri.port_3db = data; // no info on this port? Bit 5 appears to be a clock divider... - break; - default: - vga_device::port_03d0_w(offset,data); - break; - } - } -} - -uint8_t trident_vga_device::port_43c6_r(offs_t offset) -{ - uint8_t res = 0xff; - switch(offset) - { - case 2: - res = tri.mem_clock & 0xff; - break; - case 3: - res = tri.mem_clock >> 8; - break; - case 4: - res = tri.vid_clock & 0xff; - break; - case 5: - res = tri.vid_clock >> 8; - break; - } - return res; -} - -void trident_vga_device::port_43c6_w(offs_t offset, uint8_t data) -{ - switch(offset) - { - case 2: - if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80)) - { - tri.mem_clock = (tri.mem_clock & 0xff00) | (data); - LOG("Trident: Memory clock write %04x\n",tri.mem_clock); - } - break; - case 3: - if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80)) - { - tri.mem_clock = (tri.mem_clock & 0x00ff) | (data << 8); - LOG("Trident: Memory clock write %04x\n",tri.mem_clock); - } - break; - case 4: - if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80)) - { - tri.vid_clock = (tri.vid_clock & 0xff00) | (data); - LOG("Trident: Video clock write %04x\n",tri.vid_clock); - } - break; - case 5: - if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80)) - { - tri.vid_clock = (tri.vid_clock & 0x00ff) | (data << 8); - LOG("Trident: Video clock write %04x\n",tri.vid_clock); - } - break; - } -} - -// Trident refers to these registers as a LUTDAC -// Not much else is known. XFree86 uses register 4 for something related to DPMS -uint8_t trident_vga_device::port_83c6_r(offs_t offset) -{ - uint8_t res = 0xff; - switch(offset) - { - case 2: - res = tri.lutdac_reg[tri.lutdac_index]; - LOG("Trident: LUTDAC reg read %02x\n",res); - break; - case 4: - res = tri.lutdac_index; - LOG("Trident: LUTDAC index read %02x\n",res); - break; - } - return res; -} - -void trident_vga_device::port_83c6_w(offs_t offset, uint8_t data) -{ - switch(offset) - { - case 2: - LOG("Trident: LUTDAC reg write %02x\n",data); - tri.lutdac_reg[tri.lutdac_index] = data; - break; - case 4: - LOG("Trident: LUTDAC index write %02x\n",data); - tri.lutdac_index = data; - break; - } -} - -uint8_t trident_vga_device::vram_r(offs_t offset) -{ - if (tri.linear_active) - return vga.memory[offset % vga.svga_intf.vram_size]; - else - return 0xff; -} - -void trident_vga_device::vram_w(offs_t offset, uint8_t data) -{ - if (tri.linear_active) - { - if(tri.accel_memwrite_active) - { - tri.accel_transfer = (tri.accel_transfer & (~(0x000000ff << (24-(8*(offset % 4)))))) | (data << (24-(8 * (offset % 4)))); - if(offset % 4 == 3) - accel_data_write(tri.accel_transfer); - return; - } - vga.memory[offset % vga.svga_intf.vram_size] = data; - } -} - -uint8_t trident_vga_device::mem_r(offs_t offset) -{ - if((tri.cr20 & 0x10) && (offset >= 0x1ff00)) // correct for old MMIO? - { - return old_mmio_r(offset-0x1ff00); - } - - if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en) - { - int data; - - if(tri.new_mode) // 64k from 0xA0000-0xAFFFF - { - offset &= 0xffff; - data=vga.memory[(offset + (svga.bank_r*0x10000)) % vga.svga_intf.vram_size]; - } - else // 128k from 0xA0000-0xBFFFF - { - data=vga.memory[(offset + (svga.bank_r*0x10000)) % vga.svga_intf.vram_size]; - } - return data; - } - - return vga_device::mem_r(offset); -} - -void trident_vga_device::mem_w(offs_t offset, uint8_t data) -{ - if((tri.cr20 & 0x10) && (offset >= 0x1ff00)) // correct for old MMIO? - { - old_mmio_w(offset-0x1ff00,data); - return; - } - - if(tri.accel_memwrite_active) - { - tri.accel_transfer = (tri.accel_transfer & (~(0x000000ff << (24-(8*(offset % 4)))))) | (data << (24-(8 * (offset % 4)))); - if(offset % 4 == 3) - accel_data_write(tri.accel_transfer); - return; - } - - if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en) - { - if(tri.new_mode) // 64k from 0xA0000-0xAFFFF - { - offset &= 0xffff; - vga.memory[(offset + (svga.bank_w*0x10000)) % vga.svga_intf.vram_size] = data; - } - else // 128k from 0xA0000-0xBFFFF - { - vga.memory[(offset + (svga.bank_w*0x10000)) % vga.svga_intf.vram_size] = data; - } - return; - } - - vga_device::mem_w(offset,data); -} - -// Old style MMIO (maps to 0xbff00) -void trident_vga_device::old_mmio_w(offs_t offset, uint8_t data) -{ - if(offset >= 0x20) - accel_w(offset-0x20,data); -} - -uint8_t trident_vga_device::old_mmio_r(offs_t offset) -{ - if(offset == 0x20) - { - if(tri.accel_busy) - return 0x20; - } - if(offset > 0x20) - return accel_r(offset-0x20); - else - return 0x00; -} - - -// 2D Acceleration functions (very WIP) - -// From XFree86 source: -/* -Graphics Engine for 9440/9660/9680 - -#define GER_STATUS 0x2120 -#define GE_BUSY 0x80 -#define GER_OPERMODE 0x2122 Byte for 9440, Word for 96xx -#define DST_ENABLE 0x200 // Destination Transparency -#define GER_COMMAND 0x2124 -#define GE_NOP 0x00 // No Operation -#define GE_BLT 0x01 // BitBLT ROP3 only -#define GE_BLT_ROP4 0x02 // BitBLT ROP4 (96xx only) -#define GE_SCANLINE 0x03 // Scan Line -#define GE_BRESLINE 0x04 // Bresenham Line -#define GE_SHVECTOR 0x05 // Short Vector -#define GE_FASTLINE 0x06 // Fast Line (96xx only) -#define GE_TRAPEZ 0x07 // Trapezoidal fill (96xx only) -#define GE_ELLIPSE 0x08 // Ellipse (96xx only) (RES) -#define GE_ELLIP_FILL 0x09 // Ellipse Fill (96xx only) (RES) -#define GER_FMIX 0x2127 -#define GER_DRAWFLAG 0x2128 // long -#define FASTMODE 1<<28 -#define STENCIL 0x8000 -#define SOLIDFILL 0x4000 -#define TRANS_ENABLE 0x1000 -#define TRANS_REVERSE 0x2000 -#define YMAJ 0x0400 -#define XNEG 0x0200 -#define YNEG 0x0100 -#define SRCMONO 0x0040 -#define PATMONO 0x0020 -#define SCR2SCR 0x0004 -#define PAT2SCR 0x0002 -#define GER_FCOLOUR 0x212C // Word for 9440, long for 96xx -#define GER_BCOLOUR 0x2130 // Word for 9440, long for 96xx -#define GER_PATLOC 0x2134 // Word -#define GER_DEST_XY 0x2138 -#define GER_DEST_X 0x2138 // Word -#define GER_DEST_Y 0x213A // Word -#define GER_SRC_XY 0x213C -#define GER_SRC_X 0x213C // Word -#define GER_SRC_Y 0x213E // Word -#define GER_DIM_XY 0x2140 -#define GER_DIM_X 0x2140 // Word -#define GER_DIM_Y 0x2142 // Word -#define GER_STYLE 0x2144 // Long -#define GER_CKEY 0x2168 // Long -#define GER_FPATCOL 0x2178 -#define GER_BPATCOL 0x217C -#define GER_PATTERN 0x2180 // from 0x2180 to 0x21FF - - Additional - Graphics Engine for 96xx -#define GER_SRCCLIP_XY 0x2148 -#define GER_SRCCLIP_X 0x2148 // Word -#define GER_SRCCLIP_Y 0x214A // Word -#define GER_DSTCLIP_XY 0x214C -#define GER_DSTCLIP_X 0x214C // Word -#define GER_DSTCLIP_Y 0x214E // Word -*/ - -uint8_t trident_vga_device::accel_r(offs_t offset) -{ - uint8_t res = 0xff; - - if(offset >= 0x60) - return tri.accel_pattern[(offset-0x60) % 0x80]; - - switch(offset) - { - case 0x00: // Status - if(tri.accel_busy) - res = 0x80; - else - res = 0x00; - break; - // Operation mode: - // bit 8: disable clipping if set - case 0x02: // Operation Mode - res = tri.accel_opermode & 0x00ff; - break; - case 0x03: - res = (tri.accel_opermode & 0xff00) >> 8; - break; - case 0x04: // Command register - res = tri.accel_command; - break; - case 0x07: // Foreground Mix? - res = tri.accel_fmix; - break; - default: - LOGTODO("Trident: unimplemented acceleration register offset %02x read\n",offset); - } - return res; -} - -void trident_vga_device::accel_w(offs_t offset, uint8_t data) -{ - if(offset >= 0x60) - { - tri.accel_pattern[(offset-0x60) % 0x80] = data; - return; - } - - switch(offset) - { - case 0x02: // Operation Mode - tri.accel_opermode = (tri.accel_opermode & 0xff00) | data; - LOGACCEL("Trident: Operation Mode set to %04x\n",tri.accel_opermode); - break; - case 0x03: - tri.accel_opermode = (tri.accel_opermode & 0x00ff) | (data << 8); - LOGACCEL("Trident: Operation Mode set to %04x\n",tri.accel_opermode); - break; - case 0x04: // Command register - tri.accel_command = data; - accel_command(); - break; - case 0x07: // Foreground Mix? - tri.accel_fmix = data; - LOGACCEL("Trident: FMIX set to %02x\n",data); - break; - case 0x08: // Draw flags - tri.accel_drawflags = (tri.accel_drawflags & 0xffffff00) | data; - LOGACCEL("Trident: Draw flags set to %08x\n",tri.accel_drawflags); - break; - case 0x09: - tri.accel_drawflags = (tri.accel_drawflags & 0xffff00ff) | (data << 8); - LOGACCEL("Trident: Draw flags set to %08x\n",tri.accel_drawflags); - break; - case 0x0a: - tri.accel_drawflags = (tri.accel_drawflags & 0xff00ffff) | (data << 16); - LOGACCEL("Trident: Draw flags set to %08x\n",tri.accel_drawflags); - break; - case 0x0b: - tri.accel_drawflags = (tri.accel_drawflags & 0x00ffffff) | (data << 24); - LOGACCEL("Trident: Draw flags set to %08x\n",tri.accel_drawflags); - break; - case 0x0c: // Foreground Colour - tri.accel_fgcolour = (tri.accel_fgcolour & 0xffffff00) | data; - LOGACCEL("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour); - break; - case 0x0d: - tri.accel_fgcolour = (tri.accel_fgcolour & 0xffff00ff) | (data << 8); - LOGACCEL("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour); - break; - case 0x0e: - tri.accel_fgcolour = (tri.accel_fgcolour & 0xff00ffff) | (data << 16); - LOGACCEL("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour); - break; - case 0x0f: - tri.accel_fgcolour = (tri.accel_fgcolour & 0x00ffffff) | (data << 24); - LOGACCEL("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour); - break; - case 0x10: // Background Colour - tri.accel_bgcolour = (tri.accel_bgcolour & 0xffffff00) | data; - LOGACCEL("Trident: Background Colour set to %08x\n",tri.accel_bgcolour); - break; - case 0x11: - tri.accel_bgcolour = (tri.accel_bgcolour & 0xffff00ff) | (data << 8); - LOGACCEL("Trident: Background Colour set to %08x\n",tri.accel_bgcolour); - break; - case 0x12: - tri.accel_bgcolour = (tri.accel_bgcolour & 0xff00ffff) | (data << 16); - LOGACCEL("Trident: Background Colour set to %08x\n",tri.accel_bgcolour); - break; - case 0x13: - tri.accel_bgcolour = (tri.accel_bgcolour & 0x00ffffff) | (data << 24); - LOGACCEL("Trident: Background Colour set to %08x\n",tri.accel_bgcolour); - break; - case 0x14: // Pattern Location - tri.accel_pattern_loc = (tri.accel_pattern_loc & 0xff00) | data; - LOGACCEL("Trident: Pattern Location set to %04x\n",tri.accel_pattern_loc); - break; - case 0x15: - tri.accel_pattern_loc = (tri.accel_pattern_loc & 0x00ff) | (data << 8); - LOGACCEL("Trident: Pattern Location set to %04x\n",tri.accel_pattern_loc); - break; - case 0x18: // Destination X - tri.accel_dest_x = (tri.accel_dest_x & 0xff00) | data; - LOGACCEL("Trident: Destination X set to %04x\n",tri.accel_dest_x); - break; - case 0x19: - tri.accel_dest_x = (tri.accel_dest_x & 0x00ff) | (data << 8); - LOGACCEL("Trident: Destination X set to %04x\n",tri.accel_dest_x); - break; - case 0x1a: // Destination Y - tri.accel_dest_y = (tri.accel_dest_y & 0xff00) | data; - LOGACCEL("Trident: Destination Y set to %04x\n",tri.accel_dest_y); - break; - case 0x1b: - tri.accel_dest_y = (tri.accel_dest_y & 0x00ff) | (data << 8); - LOGACCEL("Trident: Destination Y set to %04x\n",tri.accel_dest_y); - break; - case 0x1c: // Source X - tri.accel_source_x = (tri.accel_source_x & 0xff00) | data; - LOGACCEL("Trident: Source X set to %04x\n",tri.accel_source_x); - break; - case 0x1d: - tri.accel_source_x = (tri.accel_source_x & 0x00ff) | (data << 8); - LOGACCEL("Trident: Source X set to %04x\n",tri.accel_source_x); - break; - case 0x1e: // Source Y - tri.accel_source_y = (tri.accel_source_y & 0xff00) | data; - LOGACCEL("Trident: Source Y set to %04x\n",tri.accel_source_y); - break; - case 0x1f: - tri.accel_source_y = (tri.accel_source_y & 0x00ff) | (data << 8); - LOGACCEL("Trident: Source Y set to %04x\n",tri.accel_source_y); - break; - case 0x20: // Dimension(?) X - tri.accel_dim_x = (tri.accel_dim_x & 0xff00) | data; - LOGACCEL("Trident: Dimension X set to %04x\n",tri.accel_dim_x); - break; - case 0x21: - tri.accel_dim_x = (tri.accel_dim_x & 0x00ff) | (data << 8); - LOGACCEL("Trident: Dimension X set to %04x\n",tri.accel_dim_x); - break; - case 0x22: // Dimension(?) Y - tri.accel_dim_y = (tri.accel_dim_y & 0xff00) | data; - LOGACCEL("Trident: Dimension y set to %04x\n",tri.accel_dim_y); - break; - case 0x23: - tri.accel_dim_y = (tri.accel_dim_y & 0x00ff) | (data << 8); - LOGACCEL("Trident: Dimension y set to %04x\n",tri.accel_dim_y); - break; - case 0x24: // Style - tri.accel_style = (tri.accel_style & 0xffffff00) | data; - LOGACCEL("Trident: Style set to %08x\n",tri.accel_style); - break; - case 0x25: - tri.accel_style = (tri.accel_style & 0xffff00ff) | (data << 8); - LOGACCEL("Trident: Style set to %08x\n",tri.accel_style); - break; - case 0x26: - tri.accel_style = (tri.accel_style & 0xff00ffff) | (data << 16); - LOGACCEL("Trident: Style set to %08x\n",tri.accel_style); - break; - case 0x27: - tri.accel_style = (tri.accel_style & 0x00ffffff) | (data << 24); - LOGACCEL("Trident: Style set to %08x\n",tri.accel_style); - break; - case 0x28: // Source Clip X - tri.accel_source_x_clip = (tri.accel_source_x_clip & 0xff00) | data; - LOGACCEL("Trident: Source X Clip set to %04x\n",tri.accel_source_x_clip); - break; - case 0x29: - tri.accel_source_x_clip = (tri.accel_source_x_clip & 0x00ff) | (data << 8); - LOGACCEL("Trident: Source X Clip set to %04x\n",tri.accel_source_x_clip); - break; - case 0x2a: // Source Clip Y - tri.accel_source_y_clip = (tri.accel_source_y_clip & 0xff00) | data; - LOGACCEL("Trident: Source Y Clip set to %04x\n",tri.accel_source_y_clip); - break; - case 0x2b: - tri.accel_source_y_clip = (tri.accel_source_y_clip & 0x00ff) | (data << 8); - LOGACCEL("Trident: Source Y Clip set to %04x\n",tri.accel_source_y_clip); - break; - case 0x2c: // Destination Clip X - tri.accel_dest_x_clip = (tri.accel_dest_x_clip & 0xff00) | data; - LOGACCEL("Trident: Destination X Clip set to %04x\n",tri.accel_dest_x_clip); - break; - case 0x2d: - tri.accel_dest_x_clip = (tri.accel_dest_x_clip & 0x00ff) | (data << 8); - LOGACCEL("Trident: Destination X Clip set to %04x\n",tri.accel_dest_x_clip); - break; - case 0x2e: // Destination Clip Y - tri.accel_dest_y_clip = (tri.accel_dest_y_clip & 0xff00) | data; - LOGACCEL("Trident: Destination Y Clip set to %04x\n",tri.accel_dest_y_clip); - break; - case 0x2f: - tri.accel_dest_y_clip = (tri.accel_dest_y_clip & 0x00ff) | (data << 8); - LOGACCEL("Trident: Destination Y Clip set to %04x\n",tri.accel_dest_y_clip); - break; - case 0x48: // CKEY (Chromakey?) - tri.accel_ckey = (tri.accel_ckey & 0xffffff00) | data; - LOGACCEL("Trident: CKey set to %08x\n",tri.accel_ckey); - break; - case 0x49: - tri.accel_ckey = (tri.accel_ckey & 0xffff00ff) | (data << 8); - LOGACCEL("Trident: CKey set to %08x\n",tri.accel_ckey); - break; - case 0x4a: - tri.accel_ckey = (tri.accel_ckey & 0xff00ffff) | (data << 16); - LOGACCEL("Trident: CKey set to %08x\n",tri.accel_ckey); - break; - case 0x4b: - tri.accel_ckey = (tri.accel_ckey & 0x00ffffff) | (data << 24); - LOGACCEL("Trident: CKey set to %08x\n",tri.accel_ckey); - break; - case 0x58: // Foreground Pattern Colour - tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0xffffff00) | data; - LOGACCEL("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour); - break; - case 0x59: - tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0xffff00ff) | (data << 8); - LOGACCEL("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour); - break; - case 0x5a: - tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0xff00ffff) | (data << 16); - LOGACCEL("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour); - break; - case 0x5b: - tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0x00ffffff) | (data << 24); - LOGACCEL("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour); - break; - case 0x5c: // Background Pattern Colour - tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0xffffff00) | data; - LOGACCEL("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour); - break; - case 0x5d: - tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0xffff00ff) | (data << 8); - LOGACCEL("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour); - break; - case 0x5e: - tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0xff00ffff) | (data << 16); - LOGACCEL("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour); - break; - case 0x5f: - tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0x00ffffff) | (data << 24); - LOGACCEL("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour); - break; - default: - LOGTODO("Trident: unimplemented acceleration register offset %02x write %02x\n",offset,data); - } -} - -void trident_vga_device::accel_command() -{ - switch(tri.accel_command) - { - case 0x00: - LOG("Trident: Command: NOP\n"); - break; - case 0x01: - LOG("Trident: Command: BitBLT ROP3 (Source %i,%i Dest %i,%i Size %i,%i)\n",tri.accel_source_x,tri.accel_source_y,tri.accel_dest_x,tri.accel_dest_y,tri.accel_dim_x,tri.accel_dim_y); - LOG("BitBLT: Drawflags = %08x FMIX = %02x\n",tri.accel_drawflags,tri.accel_fmix); - accel_bitblt(); - break; - case 0x02: - LOG("Trident: Command: BitBLT ROP4\n"); - break; - case 0x03: - LOG("Trident: Command: Scanline\n"); - break; - case 0x04: - LOG("Trident: Command: Bresenham Line (Source %i,%i Dest %i,%i Size %i,%i)\n",tri.accel_source_x,tri.accel_source_y,tri.accel_dest_x,tri.accel_dest_y,tri.accel_dim_x,tri.accel_dim_y); - LOG("BLine: Drawflags = %08x FMIX = %02x\n",tri.accel_drawflags,tri.accel_fmix); - accel_line(); - break; - case 0x05: - LOG("Trident: Command: Short Vector\n"); - break; - case 0x06: - LOG("Trident: Command: Fast Line\n"); - break; - case 0x07: - LOG("Trident: Command: Trapezoid Fill\n"); - break; - case 0x08: - LOG("Trident: Command: Ellipse\n"); - break; - case 0x09: - LOG("Trident: Command: Ellipse Fill\n"); - break; - default: - LOGTODO("Trident: Unknown acceleration command %02x\n",tri.accel_command); - } -} - -void trident_vga_device::accel_bitblt() -{ - int x,y; - int sx,sy; - int xdir,ydir; - int xstart,xend,ystart,yend; - - if(tri.accel_drawflags & 0x0040) // TODO: handle PATMONO also - { - tri.accel_mem_x = tri.accel_dest_x; - tri.accel_mem_y = tri.accel_dest_y; - tri.accel_memwrite_active = true; - return; - } - - if(tri.accel_drawflags & 0x0200) - { - xdir = -1; - xstart = tri.accel_dest_x; - xend = tri.accel_dest_x-tri.accel_dim_x-1; - } - else - { - xdir = 1; - xstart = tri.accel_dest_x; - xend = tri.accel_dest_x+tri.accel_dim_x+1; - } - if(tri.accel_drawflags & 0x0100) - { - ydir = -1; - ystart = tri.accel_dest_y; - yend = tri.accel_dest_y-tri.accel_dim_y-1; - } - else - { - ydir = 1; - ystart = tri.accel_dest_y; - yend = tri.accel_dest_y+tri.accel_dim_y+1; - } - sy = tri.accel_source_y; - - for(y=ystart;y!=yend;y+=ydir,sy+=ydir) - { - sx = tri.accel_source_x; - for(x=xstart;x!=xend;x+=xdir,sx+=xdir) - { - if(tri.accel_drawflags & 0x4000) // Solid fill - { - WRITEPIXEL(x,y,tri.accel_fgcolour); - } - else - { - WRITEPIXEL(x,y,READPIXEL(sx,sy)); - } - } - } -} - -void trident_vga_device::accel_line() -{ - uint32_t col = tri.accel_fgcolour; -// TGUI_SRC_XY(dmin-dmaj,dmin); -// TGUI_DEST_XY(x,y); -// TGUI_DIM_XY(dmin+e,len); - int16_t dx = tri.accel_source_y - tri.accel_source_x; - int16_t dy = tri.accel_source_y; - int16_t err = tri.accel_dim_x + tri.accel_source_y; - int sx = (tri.accel_drawflags & 0x0200) ? -1 : 1; - int sy = (tri.accel_drawflags & 0x0100) ? -1 : 1; - int x,y,z; - - x = tri.accel_dest_x; - y = tri.accel_dest_y; - - WRITEPIXEL(x,y,col); - for(z=0;z 0) - { - if(tri.accel_drawflags & 0x0400) - x += sx; - else - y += sy; - WRITEPIXEL(x,y,col); - err += (dy-dx); - } - else - { - WRITEPIXEL(x,y,col); - err += dy; - } - } -} - -// feed data written to VRAM to an active BitBLT command -void trident_vga_device::accel_data_write(uint32_t data) -{ - int xdir = 1,ydir = 1; - - if(tri.accel_drawflags & 0x0200) // XNEG - xdir = -1; - if(tri.accel_drawflags & 0x0100) // YNEG - ydir = -1; - - for(int x=31;x>=0;x--) - { - if(tri.accel_mem_x <= tri.accel_dest_x+tri.accel_dim_x && tri.accel_mem_x >= tri.accel_dest_x-tri.accel_dim_x) - { - if(((data >> x) & 0x01) != 0) - WRITEPIXEL(tri.accel_mem_x,tri.accel_mem_y,tri.accel_fgcolour); - else - WRITEPIXEL(tri.accel_mem_x,tri.accel_mem_y,tri.accel_bgcolour); - } - tri.accel_mem_x+=xdir; - } - if(tri.accel_mem_x > tri.accel_dest_x+tri.accel_dim_x || tri.accel_mem_x < tri.accel_dest_x-tri.accel_dim_x) - { - tri.accel_mem_x = tri.accel_dest_x; - tri.accel_mem_y+=ydir; - if(tri.accel_mem_y > tri.accel_dest_y+tri.accel_dim_y || tri.accel_mem_y < tri.accel_dest_y-tri.accel_dim_y) - tri.accel_memwrite_active = false; // completed - } -} - -// tvga9000 CRTC override -// not extensively tested, just enough for pntnpuzl to not throw a 168 Hz refresh rate. -void tvga9000_device::trident_define_video_mode() -{ - int divisor = 1; - int xtal; - - u8 xtal_select = (vga.miscellaneous_output & 0x0c) >> 2; - xtal_select |= (tri.sr0d_new & 0x01) << 2; - xtal_select |= (tri.sr0d_new & 0x40) >> 3; - - switch(xtal_select) - { - case 0: xtal = 25174800; break; - case 1: xtal = 28636363; break; - case 2: xtal = 44900000; break; - case 3: xtal = 36000000; break; - case 4: xtal = 57272000; break; - case 5: xtal = 65000000; break; - case 6: xtal = 50350000; break; - case 7: xtal = 40000000; break; - case 8: xtal = 25174800; break; - case 9: xtal = 28636363; break; - case 10: xtal = 62300000; break; - case 11: xtal = 44900000; break; - case 12: xtal = 72000000; break; - case 13: xtal = 77000000; break; - case 14: xtal = 80000000; break; - case 15: xtal = 75000000; break; - } - - LOGCRTC("trident_define_video_mode: %d (%d)\n", xtal_select, xtal); - - switch((tri.sr0d_new & 0x06) >> 1) - { - case 0: break; // no division - case 1: xtal /= 2; break; - case 2: xtal /= 4; break; - case 3: xtal /= 1.5; break; - } - - if(tri.gc0f & 0x08) // 16 pixels per character clock - xtal = xtal / 2; - - if(tri.port_3db & 0x20) - xtal = xtal / 2; // correct? - - LOGCRTC("division setting %d %02x %02x (new xtal %d)\n", (tri.sr0d_new & 0x06) >> 1, tri.gc0f, tri.port_3db, xtal); - - svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb32_en = 0; - switch((tri.pixel_depth & 0x0c) >> 2) - { - case 0: - default: if(!(tri.pixel_depth & 0x10) || (tri.cr1e & 0x80)) svga.rgb8_en = 1; break; - case 1: if((tri.dac & 0xf0) == 0x30) svga.rgb16_en = 1; else svga.rgb15_en = 1; break; - case 2: svga.rgb32_en = 1; break; - } - - // TODO: is this right? - // documentation claims to be "host address bit 16" - // pntnpuzl definitely needs to halve divisor and xtal otherwise it will draw in 800 x 240. - if(BIT(tri.cr1e, 7)) - { - divisor = 2; - xtal /= 2; - } - // TODO: tri.cr1e bit 2 for interlace - - LOGCRTC("pixel depth %02x module testing %02x\n", tri.pixel_depth, tri.cr1e); - - recompute_params_clock(divisor, xtal); -} diff --git a/src/devices/bus/isa/trident.h b/src/devices/bus/isa/trident.h deleted file mode 100644 index 47edc7e760c..00000000000 --- a/src/devices/bus/isa/trident.h +++ /dev/null @@ -1,170 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Barry Rodewald -/* - * trident.h - * - */ - -#ifndef MAME_BUS_ISA_TRIDENT_H -#define MAME_BUS_ISA_TRIDENT_H - -#pragma once - -#include "video/pc_vga.h" - -// ======================> trident_vga_device - -class trident_vga_device : public svga_device -{ -public: - virtual uint8_t port_03c0_r(offs_t offset) override; - virtual void port_03c0_w(offs_t offset, uint8_t data) override; - virtual uint8_t port_03d0_r(offs_t offset) override; - virtual void port_03d0_w(offs_t offset, uint8_t data) override; - uint8_t port_83c6_r(offs_t offset); - void port_83c6_w(offs_t offset, uint8_t data); - uint8_t port_43c6_r(offs_t offset); - void port_43c6_w(offs_t offset, uint8_t data); - uint8_t vram_r(offs_t offset); - void vram_w(offs_t offset, uint8_t data); - virtual uint8_t mem_r(offs_t offset) override; - virtual void mem_w(offs_t offset, uint8_t data) override; - virtual uint16_t offset() override; - - uint8_t accel_r(offs_t offset); - void accel_w(offs_t offset, uint8_t data); - - virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override; - -protected: - // construction/destruction - trident_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void device_reset() override; - - struct - { - uint8_t sr0c; - uint8_t sr0d_old; - uint8_t sr0d_new; - uint8_t sr0e_old; - uint8_t sr0e_new; - uint8_t sr0f; - uint8_t gc0e; - uint8_t gc0f; - uint8_t gc2f; - uint8_t cr1e; - uint8_t cr1f; - uint8_t cr20; - uint8_t cr21; - uint8_t cr29; - uint8_t cr2a; - uint8_t cr39; - uint8_t dac; - uint8_t lutdac_reg[0x100]; - uint8_t lutdac_index; - bool new_mode; - bool port_3c3; - uint8_t port_3db; - uint8_t clock; - uint8_t pixel_depth; - uint8_t revision; - bool dac_active; - uint8_t dac_count; - uint32_t linear_address; - bool linear_active; - bool mmio_active; - uint16_t mem_clock; // I/O 0x43c6 - uint16_t vid_clock; // I/O 0x43c8 - uint16_t cursor_x; - uint16_t cursor_y; - uint16_t cursor_loc; - uint8_t cursor_x_off; - uint8_t cursor_y_off; - uint32_t cursor_fg; // colour - uint32_t cursor_bg; // colour - uint8_t cursor_ctrl; - - // 2D acceleration - uint16_t accel_opermode; - uint8_t accel_command; - uint8_t accel_fmix; - uint32_t accel_drawflags; - uint32_t accel_fgcolour; - uint32_t accel_bgcolour; - uint16_t accel_pattern_loc; - int16_t accel_source_x; - int16_t accel_source_y; - int16_t accel_dest_x; - int16_t accel_dest_y; - int16_t accel_dim_x; - int16_t accel_dim_y; - uint32_t accel_style; - uint32_t accel_ckey; - int16_t accel_source_x_clip; - int16_t accel_source_y_clip; - int16_t accel_dest_x_clip; - int16_t accel_dest_y_clip; - uint32_t accel_fg_pattern_colour; - uint32_t accel_bg_pattern_colour; - uint8_t accel_pattern[0x80]; - bool accel_busy; - bool accel_memwrite_active; // true when writing to VRAM will push data to an ongoing command (SRCMONO/PATMONO) - int16_t accel_mem_x; - int16_t accel_mem_y; - uint32_t accel_transfer; - } tri; - uint8_t m_version; -private: - uint8_t trident_seq_reg_read(uint8_t index); - void trident_seq_reg_write(uint8_t index, uint8_t data); - virtual void trident_define_video_mode(); - uint8_t trident_crtc_reg_read(uint8_t index); - void trident_crtc_reg_write(uint8_t index, uint8_t data); - uint8_t trident_gc_reg_read(uint8_t index); - void trident_gc_reg_write(uint8_t index, uint8_t data); - - int calculate_clock(); - - // old style MMIO (0xBFF00) - void old_mmio_w(offs_t offset, uint8_t data); - uint8_t old_mmio_r(offs_t offset); - - // 2D acceleration - void accel_command(); - void accel_bitblt(); - void accel_line(); - void accel_data_write(uint32_t data); - uint8_t READPIXEL8(int16_t x, int16_t y); - uint16_t READPIXEL15(int16_t x, int16_t y); - uint16_t READPIXEL16(int16_t x, int16_t y); - uint32_t READPIXEL32(int16_t x, int16_t y); - void WRITEPIXEL8(int16_t x, int16_t y, uint8_t data); - void WRITEPIXEL15(int16_t x, int16_t y, uint16_t data); - void WRITEPIXEL16(int16_t x, int16_t y, uint16_t data); - void WRITEPIXEL32(int16_t x, int16_t y, uint32_t data); - uint32_t READPIXEL(int16_t x,int16_t y); - void WRITEPIXEL(int16_t x,int16_t y, uint32_t data); - uint32_t handle_rop(uint32_t src, uint32_t dst); -}; - -class tgui9860_device : public trident_vga_device -{ -public: - tgui9860_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - -class tvga9000_device : public trident_vga_device -{ -public: - tvga9000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual void trident_define_video_mode() override; -}; - -// device type definition -DECLARE_DEVICE_TYPE(TRIDENT_VGA, tgui9860_device) -DECLARE_DEVICE_TYPE(TVGA9000_VGA, tvga9000_device) - -#endif // MAME_BUS_ISA_TRIDENT_H diff --git a/src/devices/bus/isa/vga_ati.cpp b/src/devices/bus/isa/vga_ati.cpp index aaebcf3969b..b3a7c1414bc 100644 --- a/src/devices/bus/isa/vga_ati.cpp +++ b/src/devices/bus/isa/vga_ati.cpp @@ -1,7 +1,7 @@ // license:BSD-3-Clause // copyright-holders:Barry Rodewald /* - * isa_vga_ati.c + * isa_vga_ati.cpp * * ATi Graphics Ultra ISA Video card * - Uses ATi 28800-6 (VGA Wonder) and ATi 38800-1 (Mach8, 8514/A clone) @@ -17,9 +17,10 @@ #include "emu.h" #include "vga_ati.h" -#include "mach32.h" -#include "video/pc_vga.h" +#include "video/pc_vga_ati.h" +#include "video/ati_mach8.h" +#include "video/ati_mach32.h" #include "screen.h" diff --git a/src/devices/bus/isa/vga_ati.h b/src/devices/bus/isa/vga_ati.h index f92f3c563ca..98d0df0f7fe 100644 --- a/src/devices/bus/isa/vga_ati.h +++ b/src/devices/bus/isa/vga_ati.h @@ -13,8 +13,9 @@ #pragma once #include "isa.h" -#include "video/pc_vga.h" -#include "mach32.h" +#include "video/pc_vga_ati.h" +#include "video/ati_mach8.h" +#include "video/ati_mach32.h" //************************************************************************** // TYPE DEFINITIONS diff --git a/src/devices/machine/sis630_gui.cpp b/src/devices/machine/sis630_gui.cpp index 24270f95e02..cdbd4fe9db9 100644 --- a/src/devices/machine/sis630_gui.cpp +++ b/src/devices/machine/sis630_gui.cpp @@ -81,7 +81,6 @@ void sis630_svga_device::device_start() vga.crtc.maximum_scan_line = 1; // copy over interfaces - vga.read_dipswitch.set(nullptr); //read_dipswitch; vga.svga_intf.seq_regcount = 0x05; vga.svga_intf.crtc_regcount = 0x27; vga.svga_intf.vram_size = 64*1024*1024; diff --git a/src/devices/video/ati_mach32.cpp b/src/devices/video/ati_mach32.cpp new file mode 100644 index 00000000000..a5af855516f --- /dev/null +++ b/src/devices/video/ati_mach32.cpp @@ -0,0 +1,407 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald +/* + * mach32.c + * + * Implementation of the ATi mach32 and mach64 video chips + * Based on ati_vga and mach8 + * + * Created on: 16/05/2014 + */ + +#include "emu.h" +#include "video/ati_mach32.h" + +#include "screen.h" + +#define VERBOSE (LOG_GENERAL) +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(ATIMACH32, mach32_device, "mach32", "ATi mach32") +DEFINE_DEVICE_TYPE(ATIMACH32_8514A, mach32_8514a_device, "mach32_8514a", "ATi mach32 (2D acceleration module)") +DEFINE_DEVICE_TYPE(ATIMACH64, mach64_device, "mach64", "ATi mach64") +DEFINE_DEVICE_TYPE(ATIMACH64_8514A, mach64_8514a_device, "mach64_8514a", "ATi mach64 (2D acceleration module)") + + +/* + * mach32 + */ + +// 8514/A device +mach32_8514a_device::mach32_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mach32_8514a_device(mconfig, ATIMACH32_8514A, tag, owner, clock) +{ +} + +mach32_8514a_device::mach32_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : mach8_device(mconfig, type, tag, owner, clock), m_chip_ID(0), m_membounds(0) +{ +} + + +// SVGA device +mach32_device::mach32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mach32_device(mconfig, ATIMACH32, tag, owner, clock) +{ +} + +mach32_device::mach32_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), m_8514a(*this,"8514a") +{ +} + +void mach32_device::device_add_mconfig(machine_config &config) +{ + ATIMACH32_8514A(config, "8514a", 0).set_vga(DEVICE_SELF); + EEPROM_93C56_16BIT(config, "ati_eeprom"); +} + +void mach32_8514a_device::device_start() +{ + mach8_device::device_start(); + // 017h 68800-AX + // 177h 68800-LX + // 2F7h 68800-6 + // The 68800-3 appears to return 0 for this field (undocumented) + m_chip_ID = 0x17; + m_membounds = 0; +} + +// Configuration Status Register 1 (read only) +// bit 0: Disable VGA: 0=VGA+8514/A, 1=8514/A only +// bits 1-3: Bus Type: 0=16-bit ISA. 1=EISA, 2=16-bit MCA, 3=32-bit MCA, 4=LBus 386SX +// 5=LBus 386DX, 6=LBus 486. 7=PCI +// bits 4-6: RAM Type: 3=256Kx16 DRAM +// bit 7: Chip Disable +// bit 8: TST_VCTR_ENA: 1=delay memory write by 1/2 MCLK to test vector generation +// bits 9-11: DAC Type: 0=ATI68830, 1=SC11483, 2=ATI68875, 3=Bt476, 4=Bt481, 5=ATI68860 (68800AX or higher) +// The Graphics Ultra Pro has an ATI68875 +// bit 12: Enable internal uC address decode +// bit 13-15: Card ID: ID when using multiple controllers +uint16_t mach32_8514a_device::mach32_config1_r() +{ + return 0x0430; // enable VGA, 16-bit ISA, 256Kx16 DRAM, ATI68875 +} + + +/* 7AEE (W) Mach 32 + * bits 0-2 Monitor Alias - Monitor ID + * bit 3 Enable reporting of Monitor Alias + * bits 4-5 Pixel Width (0=4bpp, 1=8bpp, 2=16bpp, 3=24bpp) + * bits 6-7 16bpp colour mode (0=555, 1=565, 2=655, 3=664) + * bit 8 Multiplex pixels - processes 4 pixels in parallel by the DAC + * bit 9 24bpp config (0=3Bytes/pixel, 1=4Bytes/pixel) + * bit 10 24bpp colour order (0=RGB, LSB reserved in 4Bpp, 1=BGR, MSB reserved in 4Bpp) + * bit 11 Display pixel size to be written + * bits 12-13 DAC extended address inputs RS2,RS3 + * bit 14 Enabled 8-bit DAC (0=6-bit) + * bit 15 Draw pixel size to be written + * If bits 11 and 15 are both 0, then for compatibility, both will be written + */ +void mach32_8514a_device::mach32_ge_ext_config_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if(offset == 1) + { + COMBINE_DATA(&mach8.ge_ext_config); + if(data & 0x0800) + display_mode_change = true; + if(!(data & 0x8000) && (!(data & 0x0800))) + display_mode_change = true; + } +} + +void mach32_8514a_device::device_reset() +{ +} + +void mach32_8514a_device::mach32_mem_boundary_w(uint16_t data) +{ + m_membounds = data; + if(data & 0x10) + LOG("ATI: Unimplemented memory boundary activated.\n"); +} + + +void mach32_device::device_start() +{ + ati_vga_device::device_start(); + ati.vga_chip_id = 0x00; // correct? +} + +void mach32_device::device_reset() +{ + ati_vga_device::device_reset(); +} + +void mach32_device::ati_define_video_mode() +{ + uint16_t config = m_8514a->get_ext_config(); + + if(ati.ext_reg[0x30] & 0x20) + { + if(m_8514a->has_display_mode_changed()) + { + svga.rgb8_en = 0; + svga.rgb15_en = 0; + svga.rgb16_en = 0; + svga.rgb32_en = 0; + + switch(config & 0x0030) // pixel depth + { + case 0x0000: + break; + case 0x0010: + svga.rgb8_en = 1; + break; + case 0x0020: + svga.rgb15_en = 1; + break; + case 0x0030: + svga.rgb32_en = 1; + break; + } + } + } + else + { + ati_vga_device::ati_define_video_mode(); + return; + } + + set_dot_clock(); +} + +uint16_t mach32_device::offset() +{ + if(get_video_depth() >= 15) + return ati_vga_device::offset() << 1; + return ati_vga_device::offset(); +} + +uint32_t mach32_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + ati_vga_device::screen_update(screen, bitmap, cliprect); + draw_hw_cursor(screen, bitmap, cliprect); + + return 0; +} + +uint32_t mach32_device::draw_hw_cursor(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + uint8_t depth = get_video_depth(); + + if(!m_cursor_enable) + return 0; + + uint32_t src = (m_cursor_address & 0x000fffff) << 2; + + uint32_t colour0, colour1; + if(depth == 8) + { + colour0 = pen(m_cursor_colour0_b); + colour1 = pen(m_cursor_colour1_b); + } + else // 16/24/32bpp + { + colour0 = (m_cursor_colour0_r << 16) | (m_cursor_colour0_g << 8) | (m_cursor_colour0_b); + colour1 = (m_cursor_colour1_r << 16) | (m_cursor_colour1_g << 8) | (m_cursor_colour1_b); + } + + // draw hardware pointer (64x64 max) + for(uint8_t y=0;y<64;y++) + { + uint32_t *dst = &bitmap.pix(m_cursor_vertical + y, m_cursor_horizontal); + for(uint8_t x=0;x<64;x+=8) + { + uint16_t const bits = (vga.memory[(src+0) % vga.svga_intf.vram_size] | ((vga.memory[(src+1) % vga.svga_intf.vram_size]) << 8)); + + for(uint8_t z=0;z<8;z++) + { + if(((z + x) > (m_cursor_offset_horizontal-1)) && (y < (63 - m_cursor_offset_vertical))) + { + uint8_t const val = (bits >> (z*2)) & 0x03; + switch(val) + { + case 0: // cursor colour 0 + *dst = colour0; + break; + case 1: // cursor colour 1 + *dst = colour1; + break; + case 2: // transparent + break; + case 3: // complement + *dst = ~(*dst); + break; + } + dst++; + } + } + src+=2; + } + } + + return 0; +} + +// mach32 Hardware Pointer +void mach32_device::mach32_cursor_l_w(offs_t offset, uint16_t data) +{ + if(offset == 1) + m_cursor_address = (m_cursor_address & 0xf0000) | data; + LOG("mach32 HW pointer data address: %05x",m_cursor_address); +} + +void mach32_device::mach32_cursor_h_w(offs_t offset, uint16_t data) +{ + if(offset == 1) + { + m_cursor_address = (m_cursor_address & 0x0ffff) | ((data & 0x000f) << 16); + m_cursor_enable = data & 0x8000; + LOG("mach32 HW pointer data address: %05x",m_cursor_address); + } +} + +void mach32_device::mach32_cursor_pos_h(offs_t offset, uint16_t data) +{ + if(offset == 1) + m_cursor_horizontal = data & 0x07ff; +} + +void mach32_device::mach32_cursor_pos_v(offs_t offset, uint16_t data) +{ + if(offset == 1) + m_cursor_vertical = data & 0x0fff; +} + +void mach32_device::mach32_cursor_colour_b_w(offs_t offset, uint16_t data) +{ + if(offset == 1) + { + m_cursor_colour0_b = data & 0xff; + m_cursor_colour1_b = data >> 8; + LOG("Mach32: HW Cursor Colour Blue write RGB: 0: %02x %02x %02x 1: %02x %02x %02x\n" + ,m_cursor_colour0_r,m_cursor_colour0_g,m_cursor_colour0_b,m_cursor_colour1_r,m_cursor_colour1_g,m_cursor_colour1_b); + } +} + +void mach32_device::mach32_cursor_colour_0_w(offs_t offset, uint16_t data) +{ + if(offset == 1) + { + m_cursor_colour0_g = data & 0xff; + m_cursor_colour0_r = data >> 8; + LOG("Mach32: HW Cursor Colour 0 write RGB: %02x %02x %02x\n",m_cursor_colour0_r,m_cursor_colour0_g,m_cursor_colour0_b); + } +} + +void mach32_device::mach32_cursor_colour_1_w(offs_t offset, uint16_t data) +{ + if(offset == 1) + { + m_cursor_colour1_g = data & 0xff; + m_cursor_colour1_r = data >> 8; + LOG("Mach32: HW Cursor Colour 1 write RGB: %02x %02x %02x\n",m_cursor_colour1_r,m_cursor_colour1_g,m_cursor_colour1_b); + } +} + +void mach32_device::mach32_cursor_offset_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if(offset == 1) + { + if(ACCESSING_BITS_0_7) + m_cursor_offset_horizontal = data & 0x00ff; + if(ACCESSING_BITS_8_15) + m_cursor_offset_vertical = data >> 8; + LOG("Mach32: HW Cursor Offset write H:%i V:%i\n",m_cursor_offset_horizontal,m_cursor_offset_vertical); + } +} + +/* + * mach64 + */ + +// 8514/A device +mach64_8514a_device::mach64_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mach64_8514a_device(mconfig, ATIMACH64_8514A, tag, owner, clock) +{ +} + +mach64_8514a_device::mach64_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : mach32_8514a_device(mconfig, type, tag, owner, clock) +{ +} + + +// SVGA device +mach64_device::mach64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mach64_device(mconfig, ATIMACH64, tag, owner, clock) +{ +} + +mach64_device::mach64_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : mach32_device(mconfig, type, tag, owner, clock), m_8514a(*this, "8514a") +{ +} + +void mach64_device::device_add_mconfig(machine_config &config) +{ + ATIMACH64_8514A(config, "8514a", 0).set_vga(DEVICE_SELF); + EEPROM_93C56_16BIT(config, "ati_eeprom"); +} + +void mach64_8514a_device::device_start() +{ + mach32_8514a_device::device_start(); + // 017h 68800-AX + // 177h 68800-LX + // 2F7h 68800-6 + // The 68800-3 appears to return 0 for this field (undocumented) + m_chip_ID = 0x0000; // value is unknown for mach64 + m_membounds = 0; +} + +void mach64_8514a_device::device_reset() +{ +} + +void mach64_device::device_start() +{ + mach32_device::device_start(); +} + +void mach64_device::device_reset() +{ + mach32_device::device_reset(); +} + +void mach64_device::set_color(u8 index, u32 color) +{ + // update the palette device so we can see in the F4 viewer what the Rage is doing + set_pen_color(index, (color>>16) & 0xff, (color>>8) & 0xff, color & 0xff); +} + +u32 mach64_device::framebuffer_r(offs_t offset, u32 mem_mask) +{ + const u32 *target = (u32 *)&vga.memory[offset<<2]; + return *target; +} + +void mach64_device::framebuffer_w(offs_t offset, u32 data, u32 mem_mask) +{ + COMBINE_DATA((u32*)&vga.memory[offset<<2]); +} + +u32 mach64_device::framebuffer_be_r(offs_t offset, u32 mem_mask) +{ + const u32 *target = (u32 *)&vga.memory[offset<<2]; + return swapendian_int32(*target); +} + +void mach64_device::framebuffer_be_w(offs_t offset, u32 data, u32 mem_mask) +{ + data = swapendian_int32(data); + mem_mask = swapendian_int32(mem_mask); + COMBINE_DATA((u32*)&vga.memory[offset<<2]); +} diff --git a/src/devices/video/ati_mach32.h b/src/devices/video/ati_mach32.h new file mode 100644 index 00000000000..edecf45303a --- /dev/null +++ b/src/devices/video/ati_mach32.h @@ -0,0 +1,242 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald +/* + * mach32.h + * + * Created on: 16/05/2014 + */ + +#ifndef MAME_BUS_ISA_MACH32_H +#define MAME_BUS_ISA_MACH32_H + +#pragma once + +#include "video/ati_mach8.h" +#include "video/pc_vga_ati.h" +#include "machine/eepromser.h" + +// 8514/A module of the Mach32 +class mach32_8514a_device : public mach8_device +{ +public: + // construction/destruction + mach32_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + uint16_t mach32_chipid_r() { return m_chip_ID; } + uint16_t mach32_mem_boundary_r() { return m_membounds; } + void mach32_mem_boundary_w(uint16_t data); + void mach32_ge_ext_config_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + uint16_t mach32_config1_r(); + void mach32_horz_overscan_w(uint16_t data) {} // TODO + uint16_t mach32_ext_ge_r() { return 0x0000; } // TODO + + bool has_display_mode_changed() { if(display_mode_change) { display_mode_change = false; return true; } else return false; } + +protected: + mach32_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + + uint16_t m_chip_ID; + uint16_t m_membounds; + bool display_mode_change; + +}; + +// main SVGA device +class mach32_device : public ati_vga_device +{ +public: + // construction/destruction + mach32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override; + uint32_t draw_hw_cursor(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + + required_device m_8514a; // provides accelerated 2D drawing, derived from the Mach8 device + + // map 8514/A functions to 8514/A module + uint16_t mach8_ec0_r() { return m_8514a->mach8_ec0_r(); } + void mach8_ec0_w(uint16_t data) { m_8514a->mach8_ec0_w(data); } + uint16_t mach8_ec1_r() { return m_8514a->mach8_ec1_r(); } + void mach8_ec1_w(uint16_t data) { m_8514a->mach8_ec1_w(data); } + uint16_t mach8_ec2_r() { return m_8514a->mach8_ec2_r(); } + void mach8_ec2_w(uint16_t data) { m_8514a->mach8_ec2_w(data); } + uint16_t mach8_ec3_r() { return m_8514a->mach8_ec3_r(); } + void mach8_ec3_w(uint16_t data) { m_8514a->mach8_ec3_w(data); } + uint16_t mach8_ext_fifo_r() { return m_8514a->mach8_ext_fifo_r(); } + void mach8_linedraw_index_w(uint16_t data) { m_8514a->mach8_linedraw_index_w(data); } + uint16_t mach8_bresenham_count_r() { return m_8514a->mach8_bresenham_count_r(); } + void mach8_bresenham_count_w(uint16_t data) { m_8514a->mach8_bresenham_count_w(data); } + void mach8_linedraw_w(uint16_t data) { m_8514a->mach8_linedraw_w(data); } + uint16_t mach8_linedraw_r() { return m_8514a->mach8_linedraw_r(); } + uint16_t mach8_scratch0_r() { return m_8514a->mach8_scratch0_r(); } + void mach8_scratch0_w(uint16_t data) { m_8514a->mach8_scratch0_w(data); } + uint16_t mach8_scratch1_r() { return m_8514a->mach8_scratch1_r(); } + void mach8_scratch1_w(uint16_t data) { m_8514a->mach8_scratch1_w(data); } + void mach8_crt_pitch_w(uint16_t data) { m_8514a->mach8_crt_pitch_w(data); } + uint16_t mach8_config1_r() { return m_8514a->mach8_config1_r(); } + uint16_t mach8_config2_smo_r() { return m_8514a->mach8_config2_r(); } + uint16_t mach8_config2_sm_r(offs_t offset) { return m_8514a->mach8_config2_r(); } + uint16_t mach8_sourcex_r() { return m_8514a->mach8_sourcex_r(); } + uint16_t mach8_sourcey_r() { return m_8514a->mach8_sourcey_r(); } + void mach8_ext_leftscissor_w(uint16_t data) { m_8514a->mach8_ext_leftscissor_w(data); } + void mach8_ext_topscissor_w(uint16_t data) { m_8514a->mach8_ext_topscissor_w(data); } + void mach8_ge_offset_l_w(uint16_t data) { m_8514a->mach8_ge_offset_l_w(data); } + void mach8_ge_offset_h_w(uint16_t data) { m_8514a->mach8_ge_offset_h_w(data); } + void mach8_scan_x_w(uint16_t data) { m_8514a->mach8_scan_x_w(data); } + void mach8_dp_config_w(uint16_t data) { m_8514a->mach8_dp_config_w(data); } + void mach8_ge_pitch_w(uint16_t data) { m_8514a->mach8_ge_pitch_w(data); } + uint16_t mach8_ge_ext_config_r() { return m_8514a->mach8_ge_ext_config_r(); } + void mach8_patt_data_w(uint16_t data) { m_8514a->mach8_patt_data_w(data); } + + uint16_t ibm8514_vtotal_r() { return m_8514a->ibm8514_vtotal_r(); } + void ibm8514_vtotal_w(uint16_t data) { m_8514a->ibm8514_vtotal_w(data); } + uint16_t ibm8514_htotal_r() { return m_8514a->ibm8514_htotal_r(); } + void ibm8514_htotal_w(offs_t offset, uint8_t data) { m_8514a->ibm8514_htotal_w(offset,data); } + uint16_t ibm8514_vdisp_r() { return m_8514a->ibm8514_vdisp_r(); } + void ibm8514_vdisp_w(uint16_t data) { m_8514a->ibm8514_vdisp_w(data); } + uint16_t ibm8514_vsync_r() { return m_8514a->ibm8514_vsync_r(); } + void ibm8514_vsync_w(uint16_t data) { m_8514a->ibm8514_vsync_w(data); } + uint16_t ibm8514_substatus_r() { return m_8514a->ibm8514_substatus_r(); } + void ibm8514_subcontrol_w(uint16_t data) { m_8514a->ibm8514_subcontrol_w(data); } + uint16_t ibm8514_subcontrol_r() { return m_8514a->ibm8514_subcontrol_r(); } + uint16_t ibm8514_currentx_r() { return m_8514a->ibm8514_currentx_r(); } + void ibm8514_currentx_w(uint16_t data) { m_8514a->ibm8514_currentx_w(data); } + uint16_t ibm8514_currenty_r() { return m_8514a->ibm8514_currenty_r(); } + void ibm8514_currenty_w(uint16_t data) { m_8514a->ibm8514_currenty_w(data); } + uint16_t ibm8514_desty_r() { return m_8514a->ibm8514_desty_r(); } + void ibm8514_desty_w(uint16_t data) { m_8514a->ibm8514_desty_w(data); } + uint16_t ibm8514_destx_r() { return m_8514a->ibm8514_destx_r(); } + void ibm8514_destx_w(uint16_t data) { m_8514a->ibm8514_destx_w(data); } + uint16_t ibm8514_line_error_r() { return m_8514a->ibm8514_line_error_r(); } + void ibm8514_line_error_w(uint16_t data) { m_8514a->ibm8514_line_error_w(data); } + uint16_t ibm8514_width_r() { return m_8514a->ibm8514_width_r(); } + void ibm8514_width_w(uint16_t data) { m_8514a->ibm8514_width_w(data); } + uint16_t ibm8514_gpstatus_r() { return m_8514a->ibm8514_gpstatus_r(); } + void ibm8514_cmd_w(uint16_t data) { m_8514a->ibm8514_cmd_w(data); } + uint16_t ibm8514_ssv_r() { return m_8514a->ibm8514_ssv_r(); } + void ibm8514_ssv_w(uint16_t data) { m_8514a->ibm8514_ssv_w(data); } + uint16_t ibm8514_fgcolour_r() { return m_8514a->ibm8514_fgcolour_r(); } + void ibm8514_fgcolour_w(uint16_t data) { m_8514a->ibm8514_fgcolour_w(data); } + uint16_t ibm8514_bgcolour_r() { return m_8514a->ibm8514_bgcolour_r(); } + void ibm8514_bgcolour_w(uint16_t data) { m_8514a->ibm8514_bgcolour_w(data); } + uint16_t ibm8514_read_mask_r() { return m_8514a->ibm8514_read_mask_r(); } + void ibm8514_read_mask_w(uint16_t data) { m_8514a->ibm8514_read_mask_w(data); } + uint16_t ibm8514_write_mask_r() { return m_8514a->ibm8514_write_mask_r(); } + void ibm8514_write_mask_w(uint16_t data) { m_8514a->ibm8514_write_mask_w(data); } + uint16_t ibm8514_backmix_r() { return m_8514a->ibm8514_backmix_r(); } + void ibm8514_backmix_w(uint16_t data) { m_8514a->ibm8514_backmix_w(data); } + uint16_t ibm8514_foremix_r() { return m_8514a->ibm8514_foremix_r(); } + void ibm8514_foremix_w(uint16_t data) { m_8514a->ibm8514_foremix_w(data); } + uint16_t ibm8514_multifunc_r() { return m_8514a->ibm8514_multifunc_r(); } + void ibm8514_multifunc_w(uint16_t data) { m_8514a->ibm8514_multifunc_w(data); } + uint16_t ibm8514_pixel_xfer_r(offs_t offset) { return m_8514a->ibm8514_pixel_xfer_r(offset); } + void mach8_pixel_xfer_w(offs_t offset, uint16_t data) { m_8514a->mach8_pixel_xfer_w(offset, data); } + void mach8_advfunc_w(uint16_t data) { m_8514a->mach8_advfunc_w(data); } + + uint16_t mach32_chipid_r() { return m_8514a->mach32_chipid_r(); } + uint16_t mach8_clksel_r() { return m_8514a->mach8_clksel_r(); } + void mach8_clksel_w(uint16_t data) { m_8514a->mach8_clksel_w(data); } // read only on the mach8 + uint16_t mach32_mem_boundary_r() { return m_8514a->mach32_mem_boundary_r(); } + void mach32_mem_boundary_w(uint16_t data) { m_8514a->mach32_mem_boundary_w(data); } // read only on the mach8 + uint8_t mach32_status_r(offs_t offset) { return m_8514a->ibm8514_status_r(offset); } + uint16_t mach32_config1_smo_r() { return m_8514a->mach32_config1_r(); } + uint16_t mach32_config1_sm_r(offs_t offset) { return m_8514a->mach32_config1_r(); } + void mach32_horz_overscan_w(uint16_t data) { m_8514a->mach32_horz_overscan_w(data); } + void mach32_ge_ext_config_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { m_8514a->mach32_ge_ext_config_w(offset, data, mem_mask); ati_define_video_mode(); } + uint16_t mach32_ext_ge_r() { return m_8514a->mach32_ext_ge_r(); } + uint16_t mach32_readonly_s_r(offs_t offset, uint16_t mem_mask) { return 0; } + uint16_t mach32_readonly_sm_r(offs_t offset) { return 0; } + uint16_t mach32_readonly_smo_r() { return 0; } + void mach32_cursor_pos_h(offs_t offset, uint16_t data); + void mach32_cursor_pos_v(offs_t offset, uint16_t data); + void mach32_cursor_colour_b_w(offs_t offset, uint16_t data); + void mach32_cursor_colour_0_w(offs_t offset, uint16_t data); + void mach32_cursor_colour_1_w(offs_t offset, uint16_t data); + void mach32_cursor_l_w(offs_t offset, uint16_t data); + void mach32_cursor_h_w(offs_t offset, uint16_t data); + void mach32_cursor_offset_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + +protected: + mach32_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + virtual void ati_define_video_mode() override; + virtual uint16_t offset() override; + + // hardware pointer + bool m_cursor_enable; + uint32_t m_cursor_address; + uint16_t m_cursor_horizontal; + uint16_t m_cursor_vertical; + uint8_t m_cursor_colour0_b; + uint8_t m_cursor_colour0_r; + uint8_t m_cursor_colour0_g; + uint8_t m_cursor_colour1_b; + uint8_t m_cursor_colour1_r; + uint8_t m_cursor_colour1_g; + uint8_t m_cursor_offset_horizontal; + uint8_t m_cursor_offset_vertical; + +}; + +/* + * ATi mach64 + */ + +// 8514/A module of the Mach64 +class mach64_8514a_device : public mach32_8514a_device +{ +public: + // construction/destruction + mach64_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + mach64_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; +}; + +// main SVGA device +class mach64_device : public mach32_device +{ +public: + // construction/destruction + mach64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void mach64_config1_w(uint16_t data) { } // why does the mach64 BIOS write to these, they are read only on the mach32 and earlier + void mach64_config2_w(uint16_t data) { } + + void set_color(u8 index, u32 color); + u32 framebuffer_r(offs_t offset, u32 mem_mask); + void framebuffer_w(offs_t offset, u32 data, u32 mem_mask); + u32 framebuffer_be_r(offs_t offset, u32 mem_mask); + void framebuffer_be_w(offs_t offset, u32 data, u32 mem_mask); + u8 *get_framebuffer_addr() { return &vga.memory[0]; } + +protected: + mach64_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + required_device m_8514a; // provides accelerated 2D drawing, derived from the Mach8 device + +private: +}; + +// device type definition +DECLARE_DEVICE_TYPE(ATIMACH32, mach32_device) +DECLARE_DEVICE_TYPE(ATIMACH32_8514A, mach32_8514a_device) +DECLARE_DEVICE_TYPE(ATIMACH64, mach64_device) +DECLARE_DEVICE_TYPE(ATIMACH64_8514A, mach64_8514a_device) + +#endif // MAME_BUS_ISA_MACH32_H diff --git a/src/devices/video/ati_mach8.cpp b/src/devices/video/ati_mach8.cpp new file mode 100644 index 00000000000..19306139d82 --- /dev/null +++ b/src/devices/video/ati_mach8.cpp @@ -0,0 +1,337 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald + +#include "emu.h" +#include "ati_mach8.h" + +#define VERBOSE (LOG_GENERAL) +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + +// TODO: remove this enum +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_DEVICE_TYPE(MACH8, mach8_device, "mach8", "Mach8") + +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) +{ +} + +void mach8_device::device_start() +{ + ibm8514a_device::device_start(); + memset(&mach8, 0, sizeof(mach8)); +} + +uint16_t mach8_device::mach8_ec0_r() +{ + return ibm8514.ec0; +} + +void mach8_device::mach8_ec0_w(uint16_t data) +{ + ibm8514.ec0 = data; + LOG( "8514/A: Extended configuration 0 write %04x\n",data); +} + +uint16_t mach8_device::mach8_ec1_r() +{ + return ibm8514.ec1; +} + +void mach8_device::mach8_ec1_w(uint16_t data) +{ + ibm8514.ec1 = data; + LOG( "8514/A: Extended configuration 1 write %04x\n",data); +} + +uint16_t mach8_device::mach8_ec2_r() +{ + return ibm8514.ec2; +} + +void mach8_device::mach8_ec2_w(uint16_t data) +{ + ibm8514.ec2 = data; + LOG( "8514/A: Extended configuration 2 write %04x\n",data); +} + +uint16_t mach8_device::mach8_ec3_r() +{ + return ibm8514.ec3; +} + +void mach8_device::mach8_ec3_w(uint16_t data) +{ + ibm8514.ec3 = data; + LOG( "8514/A: Extended configuration 3 write %04x\n",data); +} + +uint16_t mach8_device::mach8_ext_fifo_r() +{ + return 0x00; // for now, report all FIFO slots as free +} + +void mach8_device::mach8_linedraw_index_w(uint16_t data) +{ + mach8.linedraw = data & 0x07; + LOG( "Mach8: Line Draw Index write %04x\n",data); +} + +uint16_t mach8_device::mach8_bresenham_count_r() +{ + return ibm8514.rect_width & 0x1fff; +} + +void mach8_device::mach8_bresenham_count_w(uint16_t data) +{ + ibm8514.rect_width = data & 0x1fff; + LOG( "Mach8: Bresenham count write %04x\n",data); +} + +uint16_t mach8_device::mach8_linedraw_r() +{ + return 0xff; +} + +void mach8_device::mach8_linedraw_w(uint16_t data) +{ + // 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; + } + LOG( "ATI: Linedraw register write %04x, mode %i\n",data,mach8.linedraw); +} + +uint16_t mach8_device::mach8_sourcex_r() +{ + return ibm8514.dest_x & 0x07ff; +} + +uint16_t mach8_device::mach8_sourcey_r() +{ + return ibm8514.dest_y & 0x07ff; +} + +void mach8_device::mach8_ext_leftscissor_w(uint16_t data) +{ + // TODO +} + +void mach8_device::mach8_ext_topscissor_w(uint16_t data) +{ + // TODO +} + +uint16_t mach8_device::mach8_scratch0_r() +{ + return mach8.scratch0; +} + +void mach8_device::mach8_scratch0_w(uint16_t data) +{ + mach8.scratch0 = data; + LOG( "Mach8: Scratch Pad 0 write %04x\n",data); +} + +uint16_t mach8_device::mach8_scratch1_r() +{ + return mach8.scratch1; +} + +void mach8_device::mach8_scratch1_w(uint16_t data) +{ + mach8.scratch1 = data; + LOG( "Mach8: Scratch Pad 1 write %04x\n",data); +} + +void mach8_device::mach8_crt_pitch_w(uint16_t data) +{ + mach8.crt_pitch = data & 0x00ff; + m_vga->set_offset(mach8.crt_pitch); + LOG( "Mach8: CRT pitch write %04x\n",mach8.crt_pitch); +} + +void mach8_device::mach8_ge_offset_l_w(uint16_t data) +{ + mach8.ge_offset = (mach8.ge_offset & 0x0f0000) | data; + LOG( "Mach8: Graphics Engine Offset (Low) write %05x\n",mach8.ge_offset); +} + +void mach8_device::mach8_ge_offset_h_w(uint16_t data) +{ + mach8.ge_offset = (mach8.ge_offset & 0x00ffff) | ((data & 0x000f) << 16); + LOG( "Mach8: Graphics Engine Offset (High) write %05x\n",mach8.ge_offset); +} + +void mach8_device::mach8_ge_pitch_w(uint16_t data) +{ + mach8.ge_pitch = data & 0x00ff; + LOG( "Mach8: Graphics Engine pitch write %04x\n",mach8.ge_pitch); +} + +void mach8_device::mach8_scan_x_w(uint16_t data) +{ + mach8.scan_x = data & 0x07ff; + + if((mach8.dp_config & 0xe000) == 0x4000) // foreground source is the Pixel Transfer register + { + ibm8514.state = MACH8_DRAWING_SCAN; + ibm8514.bus_size = (mach8.dp_config & 0x0200) >> 9; + ibm8514.data_avail = true; + } + // TODO: non-wait version of Scan To X + LOG( "Mach8: Scan To X write %04x\n",mach8.scan_x); +} + +void mach8_device::mach8_pixel_xfer_w(offs_t offset, uint16_t data) +{ + ibm8514_pixel_xfer_w(offset, data); + + if(ibm8514.state == MACH8_DRAWING_SCAN) + mach8_wait_scan(); +} + +void mach8_device::mach8_wait_scan() +{ + uint32_t offset = mach8.ge_offset << 2; + uint32_t addr = (ibm8514.prev_y * (mach8.ge_pitch * 8)) + ibm8514.prev_x; + + // TODO: support reverse direction + if(mach8.dp_config & 0x0010) // drawing enabled + { + 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; + } + } + } +} + +/* + * 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) + */ +void mach8_device::mach8_dp_config_w(uint16_t data) +{ + mach8.dp_config = data; + LOG( "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) + */ +uint16_t 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 + */ +uint16_t 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) + */ +void mach8_device::mach8_ge_ext_config_w(uint16_t data) +{ + mach8.ge_ext_config = data; + if(data & 0x8000) + popmessage("EEPROM enabled via 7AEE"); +} diff --git a/src/devices/video/ati_mach8.h b/src/devices/video/ati_mach8.h new file mode 100644 index 00000000000..8b190c9b2d7 --- /dev/null +++ b/src/devices/video/ati_mach8.h @@ -0,0 +1,84 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald + +#ifndef MAME_VIDEO_MACH8_H +#define MAME_VIDEO_MACH8_H + +#pragma once + +#include "video/pc_vga.h" +#include "video/ibm8514a.h" + +class mach8_device : public ibm8514a_device +{ +public: + mach8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + uint16_t mach8_ec0_r(); + void mach8_ec0_w(uint16_t data); + uint16_t mach8_ec1_r(); + void mach8_ec1_w(uint16_t data); + uint16_t mach8_ec2_r(); + void mach8_ec2_w(uint16_t data); + uint16_t mach8_ec3_r(); + void mach8_ec3_w(uint16_t data); + uint16_t mach8_ext_fifo_r(); + void mach8_linedraw_index_w(uint16_t data); + uint16_t mach8_bresenham_count_r(); + void mach8_bresenham_count_w(uint16_t data); + void mach8_linedraw_w(uint16_t data); + uint16_t mach8_linedraw_r(); + uint16_t mach8_scratch0_r(); + void mach8_scratch0_w(uint16_t data); + uint16_t mach8_scratch1_r(); + void mach8_scratch1_w(uint16_t data); + uint16_t mach8_config1_r(); + uint16_t mach8_config2_r(); + uint16_t mach8_sourcex_r(); + uint16_t mach8_sourcey_r(); + void mach8_ext_leftscissor_w(uint16_t data); + void mach8_ext_topscissor_w(uint16_t data); + uint16_t mach8_clksel_r() { return mach8.clksel; } + void mach8_crt_pitch_w(uint16_t data); + void mach8_patt_data_w(uint16_t data) { logerror("Mach8: Pattern Data write (unimplemented)\n"); } + void mach8_ge_offset_l_w(uint16_t data); + void mach8_ge_offset_h_w(uint16_t data); + void mach8_ge_pitch_w(uint16_t data); + uint16_t mach8_ge_ext_config_r() { return mach8.ge_ext_config; } + void mach8_ge_ext_config_w(uint16_t data); // TODO: handle 8-bit I/O + void mach8_scan_x_w(uint16_t data); + void mach8_dp_config_w(uint16_t data); + uint16_t mach8_readonly_r() { return 0; } + void mach8_pixel_xfer_w(offs_t offset, uint16_t data); + void mach8_clksel_w(uint16_t data) { mach8.ati_mode = true; ibm8514.passthrough = data & 0x0001; mach8.clksel = data; } // read only on the mach8 + void mach8_advfunc_w(uint16_t data) { mach8.ati_mode = false; ibm8514_advfunc_w(data); } + uint16_t get_ext_config() { return mach8.ge_ext_config; } + uint16_t offset() { if(mach8.ati_mode) return mach8.ge_pitch; else return 128; } + +protected: + mach8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + virtual void device_start() override; + struct + { + uint16_t scratch0; + uint16_t scratch1; + uint16_t linedraw; + uint16_t clksel; + uint16_t crt_pitch; + uint16_t dp_config; + uint32_t ge_offset; + uint16_t ge_pitch; + uint16_t ge_ext_config; // usage varies between the mach8 and mach32 (except for 8514/A monitor alias) + uint16_t scan_x; + bool ati_mode; + } mach8; + +private: + void mach8_wait_scan(); + +}; + +// device type definition +DECLARE_DEVICE_TYPE(MACH8, mach8_device) + +#endif // MAME_VIDEO_MACH8_H diff --git a/src/devices/video/atirage.h b/src/devices/video/atirage.h index 464d0de41ef..403f9f70697 100644 --- a/src/devices/video/atirage.h +++ b/src/devices/video/atirage.h @@ -7,7 +7,7 @@ #pragma once #include "machine/pci.h" -#include "bus/isa/mach32.h" +#include "video/ati_mach32.h" class atirage_device : public pci_device { diff --git a/src/devices/video/clgd542x.cpp b/src/devices/video/clgd542x.cpp index 61a5a9b9ae8..e3429d03e2b 100644 --- a/src/devices/video/clgd542x.cpp +++ b/src/devices/video/clgd542x.cpp @@ -17,8 +17,6 @@ #define VERBOSE (0) #include "logmacro.h" -#define CRTC_PORT_ADDR ((vga.miscellaneous_output&1)?0x3d0:0x3b0) - //#define TEXT_LINES (LINES_HELPER) #define LINES (vga.crtc.vert_disp_end+1) #define TEXT_LINES (vga.crtc.vert_disp_end+1) @@ -79,7 +77,6 @@ void cirrus_gd5428_device::device_start() vga.crtc.maximum_scan_line = 1; // copy over interfaces - vga.read_dipswitch.set(nullptr); //read_dipswitch; vga.svga_intf.seq_regcount = 0x1f; vga.svga_intf.crtc_regcount = 0x2d; vga.memory = std::make_unique(vga.svga_intf.vram_size); @@ -1018,7 +1015,7 @@ uint8_t cirrus_gd5428_device::port_03b0_r(offs_t offset) { uint8_t res = 0xff; - if (CRTC_PORT_ADDR == 0x3b0) + if (get_crtc_port() == 0x3b0) { switch(offset) { @@ -1038,7 +1035,7 @@ uint8_t cirrus_gd5428_device::port_03d0_r(offs_t offset) { uint8_t res = 0xff; - if (CRTC_PORT_ADDR == 0x3d0) + if (get_crtc_port() == 0x3d0) { switch(offset) { @@ -1056,7 +1053,7 @@ uint8_t cirrus_gd5428_device::port_03d0_r(offs_t offset) void cirrus_gd5428_device::port_03b0_w(offs_t offset, uint8_t data) { - if (CRTC_PORT_ADDR == 0x3b0) + if (get_crtc_port() == 0x3b0) { switch(offset) { @@ -1074,7 +1071,7 @@ void cirrus_gd5428_device::port_03b0_w(offs_t offset, uint8_t data) void cirrus_gd5428_device::port_03d0_w(offs_t offset, uint8_t data) { - if (CRTC_PORT_ADDR == 0x3d0) + if (get_crtc_port() == 0x3d0) { switch(offset) { @@ -1157,28 +1154,17 @@ void cirrus_gd5428_device::cirrus_crtc_reg_write(uint8_t index, uint8_t data) } -inline uint8_t cirrus_gd5428_device::cirrus_vga_latch_write(int offs, uint8_t data) +uint8_t cirrus_gd5428_device::vga_latch_write(int offs, uint8_t data) { uint8_t res = 0; uint8_t mode_mask = (gc_mode_ext & 0x04) ? 0x07 : 0x03; switch (vga.gc.write_mode & mode_mask) { case 0: - data = rotate_right(data); - if(vga.gc.enable_set_reset & 1<offset()) + +DEFINE_DEVICE_TYPE(IBM8514A, ibm8514a_device, "ibm8514a", "IBM 8514/A Video") + +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) +{ +} + +void ibm8514a_device::device_start() +{ + memset(&ibm8514, 0, sizeof(ibm8514)); + ibm8514.read_mask = 0x00000000; + ibm8514.write_mask = 0xffffffff; +} + +void ibm8514a_device::ibm8514_write_fg(uint32_t offset) +{ + offset %= m_vga->vga.svga_intf.vram_size; + uint8_t dst = m_vga->mem_linear_r(offset); + 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: + { + // Windows 95 in svga 8bpp mode wants this (start logo, moving icons around, games etc.) + u32 shift_values[4] = { 0, 8, 16, 24 }; + src = (ibm8514.pixel_xfer >> shift_values[(ibm8514.curr_x - ibm8514.prev_x) & 3]) & 0xff; + break; + } + case 0x0060: + // video memory - presume the memory is sourced from the current X/Y co-ords + src = m_vga->mem_linear_r(((ibm8514.curr_y * IBM8514_LINE_LENGTH) + ibm8514.curr_x)); + break; + } + + // write the data + switch(ibm8514.fgmix & 0x000f) + { + case 0x0000: + m_vga->mem_linear_w(offset,~dst); + break; + case 0x0001: + m_vga->mem_linear_w(offset,0x00); + break; + case 0x0002: + m_vga->mem_linear_w(offset,0xff); + break; + case 0x0003: + m_vga->mem_linear_w(offset,dst); + break; + case 0x0004: + m_vga->mem_linear_w(offset,~src); + break; + case 0x0005: + m_vga->mem_linear_w(offset,src ^ dst); + break; + case 0x0006: + m_vga->mem_linear_w(offset,~(src ^ dst)); + break; + case 0x0007: + m_vga->mem_linear_w(offset,src); + break; + case 0x0008: + m_vga->mem_linear_w(offset,~(src & dst)); + break; + case 0x0009: + m_vga->mem_linear_w(offset,(~src) | dst); + break; + case 0x000a: + m_vga->mem_linear_w(offset,src | (~dst)); + break; + case 0x000b: + m_vga->mem_linear_w(offset,src | dst); + break; + case 0x000c: + m_vga->mem_linear_w(offset,src & dst); + break; + case 0x000d: + m_vga->mem_linear_w(offset,src & (~dst)); + break; + case 0x000e: + m_vga->mem_linear_w(offset,(~src) & dst); + break; + case 0x000f: + m_vga->mem_linear_w(offset,~(src | dst)); + break; + } +} + +void ibm8514a_device::ibm8514_write_bg(uint32_t offset) +{ + offset %= m_vga->vga.svga_intf.vram_size; + uint8_t dst = m_vga->mem_linear_r(offset); + 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(((ibm8514.curr_y * IBM8514_LINE_LENGTH) + ibm8514.curr_x)); + break; + } + + // write the data + switch(ibm8514.bgmix & 0x000f) + { + case 0x0000: + m_vga->mem_linear_w(offset,~dst); + break; + case 0x0001: + m_vga->mem_linear_w(offset,0x00); + break; + case 0x0002: + m_vga->mem_linear_w(offset,0xff); + break; + case 0x0003: + m_vga->mem_linear_w(offset,dst); + break; + case 0x0004: + m_vga->mem_linear_w(offset,~src); + break; + case 0x0005: + m_vga->mem_linear_w(offset,src ^ dst); + break; + case 0x0006: + m_vga->mem_linear_w(offset,~(src ^ dst)); + break; + case 0x0007: + m_vga->mem_linear_w(offset,src); + break; + case 0x0008: + m_vga->mem_linear_w(offset,~(src & dst)); + break; + case 0x0009: + m_vga->mem_linear_w(offset,(~src) | dst); + break; + case 0x000a: + m_vga->mem_linear_w(offset,src | (~dst)); + break; + case 0x000b: + m_vga->mem_linear_w(offset,src | dst); + break; + case 0x000c: + m_vga->mem_linear_w(offset,src & dst); + break; + case 0x000d: + m_vga->mem_linear_w(offset,src & (~dst)); + break; + case 0x000e: + m_vga->mem_linear_w(offset,(~src) & dst); + break; + case 0x000f: + m_vga->mem_linear_w(offset,~(src | dst)); + break; + } +} + +void ibm8514a_device::ibm8514_write(uint32_t offset, uint32_t src) +{ + int data_size = 8; + uint32_t xfer; + + 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); + } + 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(src) != 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. + */ +uint16_t ibm8514a_device::ibm8514_line_error_r() +{ + return ibm8514.line_errorterm; +} + +void ibm8514a_device::ibm8514_line_error_w(uint16_t data) +{ + ibm8514.line_errorterm = data; + LOG( "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. + */ +uint16_t ibm8514a_device::ibm8514_gpstatus_r() +{ + uint16_t ret = 0x0000; + + //LOG( "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) +{ + 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++; + } +} + +/* +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. + */ +void ibm8514a_device::ibm8514_cmd_w(uint16_t data) +{ + 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) + { + case 0x0000: // NOP (for "Short Stroke Vectors") + ibm8514.state = IBM8514_IDLE; + ibm8514.gpbusy = false; + LOG( "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; + LOG( "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); + LOG( "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; + + LOG( "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; + LOG( "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; + } + LOG( "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? + LOG( "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((src+x)) & ~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 + LOG( "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++) + { + for(x=0;x<=ibm8514.rect_width;x++) + { + 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; + } + } + + // 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; + } + } + ibm8514.state = IBM8514_IDLE; + ibm8514.gpbusy = false; + break; + default: + ibm8514.state = IBM8514_IDLE; + ibm8514.gpbusy = false; + LOG( "8514/A: Unknown command: %04x\n",data); + break; + } +} + +/* +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 + + */ +uint16_t ibm8514a_device::ibm8514_desty_r() +{ + return ibm8514.line_axial_step; +} + +void ibm8514a_device::ibm8514_desty_w(uint16_t data) +{ + ibm8514.line_axial_step = data; + ibm8514.dest_y = data; + LOG( "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 + + */ +uint16_t ibm8514a_device::ibm8514_destx_r() +{ + return ibm8514.line_diagonal_step; +} + +void ibm8514a_device::ibm8514_destx_w(uint16_t data) +{ + ibm8514.line_diagonal_step = data; + ibm8514.dest_x = data; + LOG( "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() +{ + 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; + } + + for(x=0;x count) + { + 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; + return; + } + else if(ibm8514.state == IBM8514_DRAWING_SSV_2) + { + ibm8514.state = IBM8514_IDLE; + ibm8514.gpbusy = false; + ibm8514.data_avail = false; + return; + } + } + + 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; + } + } + } +} + +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); +} + +uint16_t ibm8514a_device::ibm8514_ssv_r() +{ + return ibm8514.ssv; +} + +void ibm8514a_device::ibm8514_ssv_w(uint16_t data) +{ + 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; + } + + 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); + } + LOG( "8514/A: Short Stroke Vector write %04x\n",data); +} + +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 count) + { + if(ibm8514.state == IBM8514_DRAWING_LINE) + { + ibm8514.state = IBM8514_IDLE; + ibm8514.gpbusy = false; + ibm8514.data_avail = false; + 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) + { + 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; + } + } + } +} + +/* +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 + */ +uint16_t ibm8514a_device::ibm8514_width_r() +{ + return ibm8514.rect_width; +} + +void ibm8514a_device::ibm8514_width_w(uint16_t data) +{ + ibm8514.rect_width = data & 0x1fff; + LOG( "8514/A: Major Axis Pixel Count / Rectangle Width write %04x\n",data); +} + +uint16_t ibm8514a_device::ibm8514_currentx_r() +{ + return ibm8514.curr_x; +} + +void ibm8514a_device::ibm8514_currentx_w(uint16_t data) +{ + ibm8514.curr_x = data; + ibm8514.prev_x = data; + LOG( "8514/A: Current X set to %04x (%i)\n",data,ibm8514.curr_x); +} + +uint16_t ibm8514a_device::ibm8514_currenty_r() +{ + return ibm8514.curr_y; +} + +void ibm8514a_device::ibm8514_currenty_w(uint16_t data) +{ + ibm8514.curr_y = data; + ibm8514.prev_y = data; + LOG( "8514/A: Current Y set to %04x (%i)\n",data,ibm8514.curr_y); +} + +uint16_t ibm8514a_device::ibm8514_fgcolour_r() +{ + return ibm8514.fgcolour; +} + +void ibm8514a_device::ibm8514_fgcolour_w(uint16_t data) +{ + ibm8514.fgcolour = data; + LOG( "8514/A: Foreground Colour write %04x\n",data); +} + +uint16_t ibm8514a_device::ibm8514_bgcolour_r() +{ + return ibm8514.bgcolour; +} + +void ibm8514a_device::ibm8514_bgcolour_w(uint16_t data) +{ + ibm8514.bgcolour = data; + LOG( "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. + */ +uint16_t ibm8514a_device::ibm8514_read_mask_r() +{ + return ibm8514.read_mask & 0xffff; +} + +void ibm8514a_device::ibm8514_read_mask_w(uint16_t data) +{ + ibm8514.read_mask = (ibm8514.read_mask & 0xffff0000) | data; + LOG( "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. + */ +uint16_t ibm8514a_device::ibm8514_write_mask_r() +{ + return ibm8514.write_mask & 0xffff; +} + +void ibm8514a_device::ibm8514_write_mask_w(uint16_t data) +{ + ibm8514.write_mask = (ibm8514.write_mask & 0xffff0000) | data; + LOG( "8514/A: Write Mask (Low) write = %08x\n",ibm8514.write_mask); +} + +uint16_t 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: + LOG( "8514/A: Unimplemented multifunction register %i selected\n",ibm8514.multifunc_sel); + return 0xff; + } +} + +void ibm8514a_device::ibm8514_multifunc_w(uint16_t data) +{ + 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; + LOG( "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; + LOG( "S3: Scissors Top write %04x\n",data); + break; + case 0x2000: + ibm8514.scissors_left = data & 0x0fff; + LOG( "S3: Scissors Left write %04x\n",data); + break; + case 0x3000: + ibm8514.scissors_bottom = data & 0x0fff; + LOG( "S3: Scissors Bottom write %04x\n",data); + break; + case 0x4000: + ibm8514.scissors_right = data & 0x0fff; + LOG( "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; + LOG( "S3: Pixel control write %04x\n",data); + break; + case 0xe000: + ibm8514.multifunc_misc = data; + LOG( "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; + LOG( "S3: Multifunction select write %04x\n",data); + break; + default: + LOG( "S3: Unimplemented multifunction register %i write %03x\n",data >> 12,data & 0x0fff); + break; + } +} + +void ibm8514a_device::ibm8514_wait_draw() +{ + 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" + { + for(x=0;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; + } + } + } + } + else + { + // "through plane" mode (single pixel) + for(x=0;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 + { + 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; + } + } + } + } +} + +/* +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). + */ +uint16_t ibm8514a_device::ibm8514_backmix_r() +{ + return ibm8514.bgmix; +} + +void ibm8514a_device::ibm8514_backmix_w(uint16_t data) +{ + ibm8514.bgmix = data; + LOG( "8514/A: BG Mix write %04x\n",data); +} + +uint16_t ibm8514a_device::ibm8514_foremix_r() +{ + return ibm8514.fgmix; +} + +void ibm8514a_device::ibm8514_foremix_w(uint16_t data) +{ + ibm8514.fgmix = data; + LOG( "8514/A: FG Mix write %04x\n",data); +} + +uint16_t ibm8514a_device::ibm8514_pixel_xfer_r(offs_t offset) +{ + if(offset == 1) + return (ibm8514.pixel_xfer & 0xffff0000) >> 16; + else + return ibm8514.pixel_xfer & 0x0000ffff; +} + +void ibm8514a_device::ibm8514_pixel_xfer_w(offs_t offset, uint16_t data) +{ + 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(); + + LOG( "8514/A: Pixel Transfer = %08x\n",ibm8514.pixel_xfer); +} + +/* +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) + */ +uint8_t ibm8514a_device::ibm8514_status_r(offs_t offset) +{ + switch(offset) + { + case 0: + return m_vga->vga_vblank() << 1; + case 2: + return m_vga->port_03c0_r(6); + case 3: + return m_vga->port_03c0_r(7); + case 4: + return m_vga->port_03c0_r(8); + case 5: + return m_vga->port_03c0_r(9); + } + return 0; +} + +void ibm8514a_device::ibm8514_htotal_w(offs_t offset, uint8_t data) +{ + switch(offset) + { + case 0: + ibm8514.htotal = data & 0xff; + break; + case 2: + m_vga->port_03c0_w(6,data); + break; + case 3: + m_vga->port_03c0_w(7,data); + break; + case 4: + m_vga->port_03c0_w(8,data); + break; + case 5: + m_vga->port_03c0_w(9,data); + break; + } + //vga.crtc.horz_total = data & 0x01ff; + LOG( "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. + */ +uint16_t 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). + */ +void ibm8514a_device::ibm8514_subcontrol_w(uint16_t data) +{ + ibm8514.subctrl = data; + ibm8514.substatus &= ~(data & 0x0f); // reset interrupts +// LOG( "8514/A: Subsystem control write %04x\n",data); +} + +uint16_t 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 + */ +void ibm8514a_device::ibm8514_display_ctrl_w(uint16_t data) +{ + 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; + } +} + +void ibm8514a_device::ibm8514_advfunc_w(uint16_t data) +{ + ibm8514.advfunction_ctrl = data; + ibm8514.passthrough = data & 0x0001; +} + +uint16_t ibm8514a_device::ibm8514_htotal_r() +{ + return ibm8514.htotal; +} + +uint16_t ibm8514a_device::ibm8514_vtotal_r() +{ + return ibm8514.vtotal; +} + +void ibm8514a_device::ibm8514_vtotal_w(uint16_t data) +{ + ibm8514.vtotal = data; +// vga.crtc.vert_total = data; + LOG( "8514/A: Vertical total write %04x\n",data); +} + +uint16_t ibm8514a_device::ibm8514_vdisp_r() +{ + return ibm8514.vdisp; +} + +void ibm8514a_device::ibm8514_vdisp_w(uint16_t data) +{ + ibm8514.vdisp = data; +// vga.crtc.vert_disp_end = data >> 3; + LOG( "8514/A: Vertical Displayed write %04x\n",data); +} + +uint16_t ibm8514a_device::ibm8514_vsync_r() +{ + return ibm8514.vsync; +} + +void ibm8514a_device::ibm8514_vsync_w(uint16_t data) +{ + ibm8514.vsync = data; + LOG( "8514/A: Vertical Sync write %04x\n",data); +} + +void ibm8514a_device::enabled() +{ + ibm8514.state = IBM8514_IDLE; + ibm8514.gpbusy = false; +} + + diff --git a/src/devices/video/ibm8514a.h b/src/devices/video/ibm8514a.h new file mode 100644 index 00000000000..9366ef8d3a8 --- /dev/null +++ b/src/devices/video/ibm8514a.h @@ -0,0 +1,155 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald + +#ifndef MAME_VIDEO_IBM8514A_H +#define MAME_VIDEO_IBM8514A_H + +#pragma once + +#include "screen.h" +#include "video/pc_vga.h" + +class svga_device; + +class ibm8514a_device : public device_t +{ +public: + ibm8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template void set_vga(T &&tag) { m_vga.set_tag(std::forward(tag)); } + void set_vga_owner() { m_vga.set_tag(DEVICE_SELF); } + + void enabled(); + + bool is_8514a_enabled() { return ibm8514.enabled; } + bool is_passthrough_set() { return ibm8514.passthrough; } + + uint16_t ibm8514_gpstatus_r(); + void ibm8514_cmd_w(uint16_t data); + void ibm8514_display_ctrl_w(uint16_t data); + uint16_t ibm8514_line_error_r(); + void ibm8514_line_error_w(uint16_t data); + uint8_t ibm8514_status_r(offs_t offset); + void ibm8514_htotal_w(offs_t offset, uint8_t data); + uint16_t ibm8514_substatus_r(); + void ibm8514_subcontrol_w(uint16_t data); + uint16_t ibm8514_subcontrol_r(); + uint16_t ibm8514_htotal_r(); + uint16_t ibm8514_vtotal_r(); + void ibm8514_vtotal_w(uint16_t data); + uint16_t ibm8514_vdisp_r(); + void ibm8514_vdisp_w(uint16_t data); + uint16_t ibm8514_vsync_r(); + void ibm8514_vsync_w(uint16_t data); + uint16_t ibm8514_desty_r(); + void ibm8514_desty_w(uint16_t data); + uint16_t ibm8514_destx_r(); + void ibm8514_destx_w(uint16_t data); + uint16_t ibm8514_ssv_r(); + void ibm8514_ssv_w(uint16_t data); + uint16_t ibm8514_currentx_r(); + void ibm8514_currentx_w(uint16_t data); + uint16_t ibm8514_currenty_r(); + void ibm8514_currenty_w(uint16_t data); + uint16_t ibm8514_width_r(); + void ibm8514_width_w(uint16_t data); + uint16_t ibm8514_fgcolour_r(); + void ibm8514_fgcolour_w(uint16_t data); + uint16_t ibm8514_bgcolour_r(); + void ibm8514_bgcolour_w(uint16_t data); + uint16_t ibm8514_multifunc_r(); + void ibm8514_multifunc_w(uint16_t data); + uint16_t ibm8514_backmix_r(); + void ibm8514_backmix_w(uint16_t data); + uint16_t ibm8514_foremix_r(); + void ibm8514_foremix_w(uint16_t data); + uint16_t ibm8514_pixel_xfer_r(offs_t offset); + virtual void ibm8514_pixel_xfer_w(offs_t offset, uint16_t data); + uint16_t ibm8514_read_mask_r(); + void ibm8514_read_mask_w(uint16_t data); + uint16_t ibm8514_write_mask_r(); + void ibm8514_write_mask_w(uint16_t data); + void ibm8514_advfunc_w(uint16_t data); + + void ibm8514_wait_draw(); + struct + { + uint16_t htotal; // Horizontal total (9 bits) + uint16_t vtotal; // Vertical total adjust (3 bits), Vertical total base (9 bit) + uint16_t vdisp; + uint16_t vsync; + uint16_t subctrl; + uint16_t substatus; + uint8_t display_ctrl; + uint16_t ssv; + uint16_t ec0; + uint16_t ec1; + uint16_t ec2; + uint16_t ec3; + bool gpbusy; + bool data_avail; + int16_t dest_x; + int16_t dest_y; + int16_t curr_x; + int16_t curr_y; + int16_t prev_x; + int16_t prev_y; + int16_t line_axial_step; + int16_t line_diagonal_step; + int16_t line_errorterm; + uint16_t current_cmd; + uint16_t src_x; + uint16_t src_y; + int16_t scissors_left; + int16_t scissors_right; + int16_t scissors_top; + int16_t scissors_bottom; + uint16_t rect_width; + uint16_t rect_height; + uint32_t fgcolour; + uint32_t bgcolour; + uint16_t fgmix; + uint16_t bgmix; + uint32_t pixel_xfer; + uint16_t pixel_control; + uint8_t bus_size; + uint8_t multifunc_sel; + uint16_t multifunc_misc; + uint32_t read_mask; + uint32_t write_mask; + uint16_t advfunction_ctrl; + bool enabled; + bool passthrough; + + int state; + uint8_t wait_vector_len; + uint8_t wait_vector_dir; + bool wait_vector_draw; + uint8_t wait_vector_count; + + } ibm8514; + +protected: + ibm8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + void ibm8514_write(uint32_t offset, uint32_t src); + void ibm8514_write_fg(uint32_t offset); + void ibm8514_write_bg(uint32_t offset); + + required_device m_vga; // for pass-through +private: + void ibm8514_draw_vector(uint8_t len, uint8_t dir, bool draw); + void ibm8514_wait_draw_ssv(); + void ibm8514_draw_ssv(uint8_t data); + void ibm8514_wait_draw_vector(); + + //uint8_t* m_vram; // the original 8514/A has it's own VRAM, but most VGA+8514 combination cards will have + // only one set of VRAM, so this will only be needed in standalone 8514/A cards + //uint32_t m_vramsize; +}; + +// device type definition +DECLARE_DEVICE_TYPE(IBM8514A, ibm8514a_device) + +#endif // MAME_VIDEO_IBM8514A_H diff --git a/src/devices/video/pc_vga.cpp b/src/devices/video/pc_vga.cpp index 502a0f11202..db3b71fbd03 100644 --- a/src/devices/video/pc_vga.cpp +++ b/src/devices/video/pc_vga.cpp @@ -37,36 +37,26 @@ (oti 037 chip) ROM_LOAD("oakvga.bin", 0xc0000, 0x8000, CRC(318c5f43) SHA1(2aeb6cf737fd87dfd08c9f5b5bc421fcdbab4ce9) ) - (tseng labs famous et4000 isa vga card (oem)) - ROM_LOAD("et4000b.bin", 0xc0000, 0x8000, CRC(a903540d) SHA1(unknown) ) - (tseng labs famous et4000 isa vga card) - ROM_LOAD("et4000.bin", 0xc0000, 0x8000, CRC(f01e4be0) SHA1(95d75ff41bcb765e50bd87a8da01835fd0aa01d5) ) ***************************************************************************/ #include "emu.h" #include "pc_vga.h" -#include "bus/isa/trident.h" -#include "machine/eepromser.h" - -#include "debugger.h" #include "screen.h" -#define LOG_ACCESSES (1U << 1) -#define LOG_REGISTERS (1U << 2) -#define LOG_8514 (1U << 3) -#define LOG_UNIMPL (1U << 4) -#define LOG_WARNINGS (1U << 5) -#define LOG_INVALID (1U << 6) -#define LOG_COMMANDS (1U << 7) -#define LOG_ATI (1U << 8) -#define LOG_OAK (1U << 9) -#define LOG_MEM_READS (1U << 10) - -#define VERBOSE (LOG_GENERAL | LOG_8514 | LOG_ATI | LOG_OAK | LOG_INVALID | LOG_COMMANDS) +#define LOG_WARN (1U << 1) +#define LOG_REGS (1U << 2) // deprecated +#define LOG_DSW (1U << 3) // Input sense at $3c2 + +#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_DSW) +//#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__) + /*************************************************************************** @@ -74,20 +64,6 @@ ***************************************************************************/ -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 TEXT_LINES (vga.crtc.vert_disp_end+1) @@ -102,8 +78,6 @@ enum #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) @@ -126,20 +100,13 @@ enum ***************************************************************************/ // 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(XGA_COPRO, xga_copro_device, "xga_copro", "IBM XGA Coprocessor") -DEFINE_DEVICE_TYPE(OTI111, oak_oti111_vga_device, "oti111_vga", "Oak Technologies Spitfire 64111") 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) , vga(*this) + , m_input_sense(*this, "VGA_SENSE") { } @@ -153,57 +120,6 @@ svga_device::svga_device(const machine_config &mconfig, device_type type, const { } -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() { @@ -234,17 +150,6 @@ TIMER_CALLBACK_MEMBER(vga_device::vblank_timer_cb) 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) -{ - // 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) ); -} - void vga_device::device_start() { zero(); @@ -257,7 +162,6 @@ void vga_device::device_start() // copy over interfaces - vga.read_dipswitch.set(nullptr); //read_dipswitch; vga.svga_intf.seq_regcount = 0x05; vga.svga_intf.crtc_regcount = 0x19; @@ -372,62 +276,6 @@ void svga_device::device_start() save_item(NAME(svga.id)); } -void ati_vga_device::device_start() -{ - svga_device::device_start(); - memset(&ati, 0, sizeof(ati)); - save_pointer(ati.ext_reg,"ATi Extended Registers",64); - m_8514 = subdevice("8514a"); - ati.vga_chip_id = 0x06; // 28800-6 -} - -void s3_vga_device::device_start() -{ - 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++) - { - s3.cursor_fg[x] = 0xff; - s3.cursor_bg[x] = 0x00; - } - m_8514 = subdevice("8514a"); - // set device ID - s3.id_high = 0x88; // CR2D - s3.id_low = 0x11; // CR2E - s3.revision = 0x00; // CR2F - s3.id_cr30 = 0xe1; // CR30 -} - -void tseng_vga_device::device_start() -{ - 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)); -} - -void ibm8514a_device::device_start() -{ - memset(&ibm8514, 0, sizeof(ibm8514)); - ibm8514.read_mask = 0x00000000; - ibm8514.write_mask = 0xffffffff; -} - -void mach8_device::device_start() -{ - ibm8514a_device::device_start(); - memset(&mach8, 0, sizeof(mach8)); -} - uint16_t vga_device::offset() { // popmessage("Offset: %04x %s %s **",vga.crtc.offset,vga.crtc.dw?"DW":"--",vga.crtc.word_mode?"BYTE":"WORD"); @@ -1070,133 +918,9 @@ uint32_t svga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, return 0; } -uint32_t s3_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - svga_device::screen_update(screen, bitmap, cliprect); - - uint8_t 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 - { - uint16_t cx = s3.cursor_x & 0x07ff; - uint16_t cy = s3.cursor_y & 0x07ff; - - 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 - - uint32_t src = s3.cursor_start_addr * 1024; // start address is in units of 1024 bytes - - uint32_t bg_col; - uint32_t fg_col; - int r,g,b; - uint32_t datax; - switch(cur_mode) - { - case RGB15_MODE: - case RGB16_MODE: - 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); - break; - case RGB24_MODE: - datax = s3.cursor_bg[0]|s3.cursor_bg[1]<<8|s3.cursor_bg[2]<<16; - r = (datax&0xff0000)>>16; - g = (datax&0x00ff00)>>8; - b = (datax&0x0000ff)>>0; - bg_col = (0xff<<24)|(r<<16)|(g<<8)|(b<<0); - - datax = s3.cursor_fg[0]|s3.cursor_fg[1]<<8|s3.cursor_fg[2]<<16; - r = (datax&0xff0000)>>16; - g = (datax&0x00ff00)>>8; - b = (datax&0x0000ff)>>0; - fg_col = (0xff<<24)|(r<<16)|(g<<8)|(b<<0); - break; - case RGB8_MODE: - default: - bg_col = pen(s3.cursor_bg[0]); - fg_col = pen(s3.cursor_fg[0]); - break; - } - - //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(int y=0;y<64;y++) - { - if(cy + y < cliprect.max_y && cx < cliprect.max_x) - { - uint32_t *const dst = &bitmap.pix(cy + y, cx); - for(int 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)); - uint8_t 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 vga_device::vga_latch_write(int offs, uint8_t data) { uint8_t res = 0; @@ -1366,7 +1090,7 @@ void vga_device::recompute_params_clock(int divisor, int xtal) void vga_device::recompute_params() { if(vga.miscellaneous_output & 8) - LOGMASKED(LOG_WARNINGS, "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()); } @@ -1517,7 +1241,7 @@ void vga_device::crtc_reg_write(uint8_t index, uint8_t data) vga.crtc.line_compare |= data & 0xff; break; default: - LOGMASKED(LOG_UNIMPL, "Unhandled CRTC reg w %02x %02x\n",index,data); + LOG( "Unhandled CRTC reg w %02x %02x\n",index,data); break; } } @@ -1628,7 +1352,7 @@ void vga_device::vga_crtc_w(offs_t offset, uint8_t data) break; case 5: - LOGMASKED(LOG_REGISTERS, "vga_crtc_w(): CRTC[0x%02X%s] = 0x%02X\n", + LOGREGS("vga_crtc_w(): CRTC[0x%02X%s] = 0x%02X\n", vga.crtc.index, (vga.crtc.index < vga.svga_intf.crtc_regcount) ? "" : "?", data); @@ -1652,7 +1376,7 @@ void vga_device::vga_crtc_w(offs_t offset, uint8_t data) uint8_t vga_device::port_03b0_r(offs_t offset) { uint8_t data = 0xff; - if (CRTC_PORT_ADDR==0x3b0) + if (get_crtc_port() == 0x3b0) data = vga_crtc_r(offset); return data; } @@ -1707,10 +1431,49 @@ uint8_t vga_device::gc_reg_read(uint8_t index) uint8_t vga_device::seq_reg_read(uint8_t index) { - LOGMASKED(LOG_UNIMPL, "Reading unmapped sequencer read register %02x (SVGA?)\n", index); + LOG( "Reading unmapped sequencer read register %02x (SVGA?)\n", index); return 0; } +/* + 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 + +ioport_constructor vga_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(vga_sense); +} + uint8_t vga_device::port_03c0_r(offs_t offset) { uint8_t data = 0xff; @@ -1729,36 +1492,14 @@ uint8_t vga_device::port_03c0_r(offs_t offset) 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() & 0x01) - data |= 0x10; - else - data |= 0x10; - break; - case 2: - if (!vga.read_dipswitch.isnull() && vga.read_dipswitch() & 0x02) - data |= 0x10; - else - data |= 0x10; - break; - case 1: - if (!vga.read_dipswitch.isnull() && vga.read_dipswitch() & 0x04) - data |= 0x10; - else - data |= 0x10; - break; - case 0: - if (!vga.read_dipswitch.isnull() && vga.read_dipswitch() & 0x08) - data |= 0x10; - else - data |= 0x10; - break; - } + 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)) + data |= 0x10; break; + } case 3: data = vga.oak.reg; @@ -1833,7 +1574,7 @@ uint8_t vga_device::port_03c0_r(offs_t offset) uint8_t vga_device::port_03d0_r(offs_t offset) { uint8_t data = 0xff; - if (CRTC_PORT_ADDR == 0x3d0) + if (get_crtc_port() == 0x3d0) data = vga_crtc_r(offset); if(offset == 8) { @@ -1846,9 +1587,7 @@ uint8_t vga_device::port_03d0_r(offs_t offset) void vga_device::port_03b0_w(offs_t offset, uint8_t data) { - LOGMASKED(LOG_ACCESSES, "vga_port_03b0_w(): port=0x%04x data=0x%02x\n", offset + 0x3b0, data); - - if (CRTC_PORT_ADDR == 0x3b0) + if (get_crtc_port() == 0x3b0) vga_crtc_w(offset, data); } @@ -1920,8 +1659,6 @@ void vga_device::gc_reg_write(uint8_t index,uint8_t data) void vga_device::port_03c0_w(offs_t offset, uint8_t data) { - LOGMASKED(LOG_ACCESSES, "vga_port_03c0_w(): port=0x%04x data=0x%02x\n", offset + 0x3c0, data); - switch (offset) { case 0: if (vga.attribute.state==0) @@ -1945,7 +1682,7 @@ void vga_device::port_03c0_w(offs_t offset, uint8_t data) vga.sequencer.index = data; break; case 5: - LOGMASKED(LOG_REGISTERS, "vga_port_03c0_w(): SEQ[0x%02X%s] = 0x%02X\n", + LOGREGS("vga_port_03c0_w(): SEQ[0x%02X%s] = 0x%02X\n", vga.sequencer.index, (vga.sequencer.index < vga.svga_intf.seq_regcount) ? "" : "?", data); @@ -2004,9 +1741,7 @@ void vga_device::port_03c0_w(offs_t offset, uint8_t data) void vga_device::port_03d0_w(offs_t offset, uint8_t data) { - LOGMASKED(LOG_ACCESSES, "vga_port_03d0_w(): port=0x%04x data=0x%02x\n", offset + 0x3d0, data); - - if (CRTC_PORT_ADDR == 0x3d0) + if (get_crtc_port() == 0x3d0) vga_crtc_w(offset, data); } @@ -2035,20 +1770,10 @@ void vga_device::device_reset() /* TODO: real defaults */ vga.crtc.line_compare = 0x3ff; - /* indiana.c boot PROM doesn't set this and assumes it's 0xff */ + /* skeleton/indiana.cpp boot PROM doesn't set this and assumes it's 0xff */ vga.dac.mask = 0xff; } -void s3_vga_device::device_reset() -{ - 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; -} - uint8_t vga_device::mem_r(offs_t offset) { /* TODO: check me */ @@ -2165,4567 +1890,3 @@ 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; - } - } -} - -uint8_t tseng_vga_device::port_03b0_r(offs_t offset) -{ - uint8_t res = 0xff; - - if (CRTC_PORT_ADDR == 0x3b0) - { - 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(offset); - break; - } - } - - return res; -} - -void tseng_vga_device::port_03b0_w(offs_t offset, uint8_t data) -{ - 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(offset,data); - break; - } - } - tseng_define_video_mode(); -} - -void tseng_vga_device::tseng_attribute_reg_write(uint8_t index, uint8_t data) -{ - 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); - } - -} - -uint8_t tseng_vga_device::port_03c0_r(offs_t offset) -{ - uint8_t res; - - switch(offset) - { - 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(offset); - 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(offset); - break; - case 0x08: - et4k.dac_state = 0; - [[fallthrough]]; - default: - res = vga_device::port_03c0_r(offset); - break; - } - - return res; -} - -void tseng_vga_device::port_03c0_w(offs_t offset, uint8_t data) -{ - 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; - - 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; - } - [[fallthrough]]; - default: - vga_device::port_03c0_w(offset,data); - break; - } - tseng_define_video_mode(); -} - -uint8_t tseng_vga_device::port_03d0_r(offs_t offset) -{ - 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(offset); - break; - } - } - - return res; -} - -void tseng_vga_device::port_03d0_w(offs_t offset, uint8_t data) -{ - 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(offset,data); - break; - } - } - tseng_define_video_mode(); -} - -uint8_t tseng_vga_device::mem_r(offs_t offset) -{ - 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(offset); -} - -void tseng_vga_device::mem_w(offs_t offset, uint8_t data) -{ - 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(offset,data); -} - -/****************************************** - -S3 implementation - -******************************************/ - -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(); -} - -uint8_t s3_vga_device::s3_crtc_reg_read(uint8_t index) -{ - 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; -} - -void s3_vga_device::s3_define_video_mode() -{ - 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; - } - - 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); -} - -void s3_vga_device::s3_crtc_reg_write(uint8_t index, uint8_t data) -{ - if(index <= 0x18) - crtc_reg_write(index,data); - else - { - switch(index) - { - 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 - 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; - LOG("CR36: Strapping data = %08x\n",s3.strapping); - } - break; - case 0x37: - if(s3.reg_lock2 == 0xa5) - { - s3.strapping = (s3.strapping & 0xffff00ff) | (data << 8); - LOG("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); - LOG("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) - { - s3.strapping = (s3.strapping & 0x00ffffff) | (data << 24); - LOG("CR6F: Strapping data = %08x\n",s3.strapping); - } - break; - default: - LOGMASKED(LOG_8514, "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; - } - } -} - - - -uint8_t s3_vga_device::port_03b0_r(offs_t offset) -{ - 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(offset); - break; - } - } - - return res; -} - -void s3_vga_device::port_03b0_w(offs_t offset, uint8_t data) -{ - 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(offset,data); - break; - } - } -} - -uint8_t s3_vga_device::port_03c0_r(offs_t offset) -{ - uint8_t res; - - switch(offset) - { - case 5: - res = s3_seq_reg_read(vga.sequencer.index); - break; - default: - res = vga_device::port_03c0_r(offset); - break; - } - - return res; -} - -void s3_vga_device::port_03c0_w(offs_t offset, uint8_t data) -{ - switch(offset) - { - case 5: - s3_seq_reg_write(vga.sequencer.index,data); - break; - default: - vga_device::port_03c0_w(offset,data); - break; - } -} - -uint8_t s3_vga_device::port_03d0_r(offs_t offset) -{ - 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(offset); - break; - } - } - - return res; -} - -void s3_vga_device::port_03d0_w(offs_t offset, uint8_t data) -{ - if (CRTC_PORT_ADDR == 0x3d0) - { - switch(offset) - { - case 5: - vga.crtc.data[vga.crtc.index] = data; - s3_crtc_reg_write(vga.crtc.index,data); - break; - default: - vga_device::port_03d0_w(offset,data); - break; - } - } -} - -uint8_t ati_vga_device::port_03c0_r(offs_t offset) -{ - 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(offset); - break; - } - return data; -} - - -/* accelerated ports, TBD ... */ - -void ibm8514a_device::ibm8514_write_fg(uint32_t offset) -{ - offset %= m_vga->vga.svga_intf.vram_size; - uint8_t dst = m_vga->mem_linear_r(offset); - 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: - { - // Windows 95 in svga 8bpp mode wants this (start logo, moving icons around, games etc.) - u32 shift_values[4] = { 0, 8, 16, 24 }; - src = (ibm8514.pixel_xfer >> shift_values[(ibm8514.curr_x - ibm8514.prev_x) & 3]) & 0xff; - break; - } - case 0x0060: - // video memory - presume the memory is sourced from the current X/Y co-ords - src = m_vga->mem_linear_r(((ibm8514.curr_y * IBM8514_LINE_LENGTH) + ibm8514.curr_x)); - break; - } - - // write the data - switch(ibm8514.fgmix & 0x000f) - { - case 0x0000: - m_vga->mem_linear_w(offset,~dst); - break; - case 0x0001: - m_vga->mem_linear_w(offset,0x00); - break; - case 0x0002: - m_vga->mem_linear_w(offset,0xff); - break; - case 0x0003: - m_vga->mem_linear_w(offset,dst); - break; - case 0x0004: - m_vga->mem_linear_w(offset,~src); - break; - case 0x0005: - m_vga->mem_linear_w(offset,src ^ dst); - break; - case 0x0006: - m_vga->mem_linear_w(offset,~(src ^ dst)); - break; - case 0x0007: - m_vga->mem_linear_w(offset,src); - break; - case 0x0008: - m_vga->mem_linear_w(offset,~(src & dst)); - break; - case 0x0009: - m_vga->mem_linear_w(offset,(~src) | dst); - break; - case 0x000a: - m_vga->mem_linear_w(offset,src | (~dst)); - break; - case 0x000b: - m_vga->mem_linear_w(offset,src | dst); - break; - case 0x000c: - m_vga->mem_linear_w(offset,src & dst); - break; - case 0x000d: - m_vga->mem_linear_w(offset,src & (~dst)); - break; - case 0x000e: - m_vga->mem_linear_w(offset,(~src) & dst); - break; - case 0x000f: - m_vga->mem_linear_w(offset,~(src | dst)); - break; - } -} - -void ibm8514a_device::ibm8514_write_bg(uint32_t offset) -{ - offset %= m_vga->vga.svga_intf.vram_size; - uint8_t dst = m_vga->mem_linear_r(offset); - 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(((ibm8514.curr_y * IBM8514_LINE_LENGTH) + ibm8514.curr_x)); - break; - } - - // write the data - switch(ibm8514.bgmix & 0x000f) - { - case 0x0000: - m_vga->mem_linear_w(offset,~dst); - break; - case 0x0001: - m_vga->mem_linear_w(offset,0x00); - break; - case 0x0002: - m_vga->mem_linear_w(offset,0xff); - break; - case 0x0003: - m_vga->mem_linear_w(offset,dst); - break; - case 0x0004: - m_vga->mem_linear_w(offset,~src); - break; - case 0x0005: - m_vga->mem_linear_w(offset,src ^ dst); - break; - case 0x0006: - m_vga->mem_linear_w(offset,~(src ^ dst)); - break; - case 0x0007: - m_vga->mem_linear_w(offset,src); - break; - case 0x0008: - m_vga->mem_linear_w(offset,~(src & dst)); - break; - case 0x0009: - m_vga->mem_linear_w(offset,(~src) | dst); - break; - case 0x000a: - m_vga->mem_linear_w(offset,src | (~dst)); - break; - case 0x000b: - m_vga->mem_linear_w(offset,src | dst); - break; - case 0x000c: - m_vga->mem_linear_w(offset,src & dst); - break; - case 0x000d: - m_vga->mem_linear_w(offset,src & (~dst)); - break; - case 0x000e: - m_vga->mem_linear_w(offset,(~src) & dst); - break; - case 0x000f: - m_vga->mem_linear_w(offset,~(src | dst)); - break; - } -} - -void ibm8514a_device::ibm8514_write(uint32_t offset, uint32_t src) -{ - int data_size = 8; - uint32_t xfer; - - 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); - } - 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(src) != 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. - */ -uint16_t ibm8514a_device::ibm8514_line_error_r() -{ - return ibm8514.line_errorterm; -} - -void ibm8514a_device::ibm8514_line_error_w(uint16_t data) -{ - ibm8514.line_errorterm = data; - LOGMASKED(LOG_8514, "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. - */ -uint16_t ibm8514a_device::ibm8514_gpstatus_r() -{ - uint16_t ret = 0x0000; - - //LOGMASKED(LOG_8514, "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) -{ - 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++; - } -} - -/* -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. - */ -void ibm8514a_device::ibm8514_cmd_w(uint16_t data) -{ - 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) - { - case 0x0000: // NOP (for "Short Stroke Vectors") - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - LOGMASKED(LOG_8514, "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; - LOGMASKED(LOG_8514, "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); - LOGMASKED(LOG_8514, "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; - - LOGMASKED(LOG_8514, "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; - LOGMASKED(LOG_8514, "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; - } - LOGMASKED(LOG_8514, "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? - LOGMASKED(LOG_8514, "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((src+x)) & ~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 - LOGMASKED(LOG_8514, "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++) - { - for(x=0;x<=ibm8514.rect_width;x++) - { - 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; - } - } - - // 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; - } - } - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - break; - default: - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - LOGMASKED(LOG_8514, "8514/A: Unknown command: %04x\n",data); - break; - } -} - -/* -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 - - */ -uint16_t ibm8514a_device::ibm8514_desty_r() -{ - return ibm8514.line_axial_step; -} - -void ibm8514a_device::ibm8514_desty_w(uint16_t data) -{ - ibm8514.line_axial_step = data; - ibm8514.dest_y = data; - LOGMASKED(LOG_8514, "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 - - */ -uint16_t ibm8514a_device::ibm8514_destx_r() -{ - return ibm8514.line_diagonal_step; -} - -void ibm8514a_device::ibm8514_destx_w(uint16_t data) -{ - ibm8514.line_diagonal_step = data; - ibm8514.dest_x = data; - LOGMASKED(LOG_8514, "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() -{ - 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; - } - - for(x=0;x count) - { - 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; - return; - } - else if(ibm8514.state == IBM8514_DRAWING_SSV_2) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; - return; - } - } - - 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; - } - } - } -} - -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); -} - -uint16_t ibm8514a_device::ibm8514_ssv_r() -{ - return ibm8514.ssv; -} - -void ibm8514a_device::ibm8514_ssv_w(uint16_t data) -{ - 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; - } - - 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); - } - LOGMASKED(LOG_8514, "8514/A: Short Stroke Vector write %04x\n",data); -} - -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 count) - { - if(ibm8514.state == IBM8514_DRAWING_LINE) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; - 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) - { - 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; - } - } - } -} - -/* -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 - */ -uint16_t ibm8514a_device::ibm8514_width_r() -{ - return ibm8514.rect_width; -} - -void ibm8514a_device::ibm8514_width_w(uint16_t data) -{ - ibm8514.rect_width = data & 0x1fff; - LOGMASKED(LOG_8514, "8514/A: Major Axis Pixel Count / Rectangle Width write %04x\n",data); -} - -uint16_t ibm8514a_device::ibm8514_currentx_r() -{ - return ibm8514.curr_x; -} - -void ibm8514a_device::ibm8514_currentx_w(uint16_t data) -{ - ibm8514.curr_x = data; - ibm8514.prev_x = data; - LOGMASKED(LOG_8514, "8514/A: Current X set to %04x (%i)\n",data,ibm8514.curr_x); -} - -uint16_t ibm8514a_device::ibm8514_currenty_r() -{ - return ibm8514.curr_y; -} - -void ibm8514a_device::ibm8514_currenty_w(uint16_t data) -{ - ibm8514.curr_y = data; - ibm8514.prev_y = data; - LOGMASKED(LOG_8514, "8514/A: Current Y set to %04x (%i)\n",data,ibm8514.curr_y); -} - -uint16_t ibm8514a_device::ibm8514_fgcolour_r() -{ - return ibm8514.fgcolour; -} - -void ibm8514a_device::ibm8514_fgcolour_w(uint16_t data) -{ - ibm8514.fgcolour = data; - LOGMASKED(LOG_8514, "8514/A: Foreground Colour write %04x\n",data); -} - -uint16_t ibm8514a_device::ibm8514_bgcolour_r() -{ - return ibm8514.bgcolour; -} - -void ibm8514a_device::ibm8514_bgcolour_w(uint16_t data) -{ - ibm8514.bgcolour = data; - LOGMASKED(LOG_8514, "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. - */ -uint16_t ibm8514a_device::ibm8514_read_mask_r() -{ - return ibm8514.read_mask & 0xffff; -} - -void ibm8514a_device::ibm8514_read_mask_w(uint16_t data) -{ - ibm8514.read_mask = (ibm8514.read_mask & 0xffff0000) | data; - LOGMASKED(LOG_8514, "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. - */ -uint16_t ibm8514a_device::ibm8514_write_mask_r() -{ - return ibm8514.write_mask & 0xffff; -} - -void ibm8514a_device::ibm8514_write_mask_w(uint16_t data) -{ - ibm8514.write_mask = (ibm8514.write_mask & 0xffff0000) | data; - LOGMASKED(LOG_8514, "8514/A: Write Mask (Low) write = %08x\n",ibm8514.write_mask); -} - -uint16_t 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: - LOGMASKED(LOG_8514, "8514/A: Unimplemented multifunction register %i selected\n",ibm8514.multifunc_sel); - return 0xff; - } -} - -void ibm8514a_device::ibm8514_multifunc_w(uint16_t data) -{ - 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; - LOGMASKED(LOG_8514, "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; - LOGMASKED(LOG_8514, "S3: Scissors Top write %04x\n",data); - break; - case 0x2000: - ibm8514.scissors_left = data & 0x0fff; - LOGMASKED(LOG_8514, "S3: Scissors Left write %04x\n",data); - break; - case 0x3000: - ibm8514.scissors_bottom = data & 0x0fff; - LOGMASKED(LOG_8514, "S3: Scissors Bottom write %04x\n",data); - break; - case 0x4000: - ibm8514.scissors_right = data & 0x0fff; - LOGMASKED(LOG_8514, "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; - LOGMASKED(LOG_8514, "S3: Pixel control write %04x\n",data); - break; - case 0xe000: - ibm8514.multifunc_misc = data; - LOGMASKED(LOG_8514, "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; - LOGMASKED(LOG_8514, "S3: Multifunction select write %04x\n",data); - break; - default: - LOGMASKED(LOG_8514, "S3: Unimplemented multifunction register %i write %03x\n",data >> 12,data & 0x0fff); - break; - } -} - -void ibm8514a_device::ibm8514_wait_draw() -{ - 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" - { - for(x=0;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; - } - } - } - } - else - { - // "through plane" mode (single pixel) - for(x=0;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 - { - 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; - } - } - } - } -} - -/* -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). - */ -uint16_t ibm8514a_device::ibm8514_backmix_r() -{ - return ibm8514.bgmix; -} - -void ibm8514a_device::ibm8514_backmix_w(uint16_t data) -{ - ibm8514.bgmix = data; - LOGMASKED(LOG_8514, "8514/A: BG Mix write %04x\n",data); -} - -uint16_t ibm8514a_device::ibm8514_foremix_r() -{ - return ibm8514.fgmix; -} - -void ibm8514a_device::ibm8514_foremix_w(uint16_t data) -{ - ibm8514.fgmix = data; - LOGMASKED(LOG_8514, "8514/A: FG Mix write %04x\n",data); -} - -uint16_t ibm8514a_device::ibm8514_pixel_xfer_r(offs_t offset) -{ - if(offset == 1) - return (ibm8514.pixel_xfer & 0xffff0000) >> 16; - else - return ibm8514.pixel_xfer & 0x0000ffff; -} - -void ibm8514a_device::ibm8514_pixel_xfer_w(offs_t offset, uint16_t data) -{ - 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(); - - LOGMASKED(LOG_8514, "8514/A: Pixel Transfer = %08x\n",ibm8514.pixel_xfer); -} - -uint8_t s3_vga_device::mem_r(offs_t offset) -{ - 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++) - { - 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))]; - } - } - } - return data; - } - if((offset + (svga.bank_r*0x10000)) < vga.svga_intf.vram_size) - return vga_device::mem_r(offset); - else - return 0xff; -} - -void s3_vga_device::mem_w(offs_t offset, uint8_t data) -{ - 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) - { - // 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; - } - switch(offset) - { - 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(s3.mmio_9ae8); - 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(s3.mmio_bee8); - 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(s3.mmio_96e8); - break; - case 0xe2e8: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xffffff00) | data; - dev->ibm8514_wait_draw(); - break; - default: - LOGMASKED(LOG_8514, "S3: MMIO offset %05x write %02x\n",offset+0xa0000,data); - break; - } - 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) - { - if((offset + (svga.bank_w*0x10000)) < vga.svga_intf.vram_size) - vga.memory[(offset + (svga.bank_w*0x10000))] = data; - } - else - { - 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; - } - - if((offset + (svga.bank_w*0x10000)) < vga.svga_intf.vram_size) - vga_device::mem_w(offset,data); -} - -/****************************************** - -gamtor.cpp implementation - -******************************************/ - -// TODO: Chips & Technologies 65550 with swapped address lines? Move to separate file regardless -// 65550 is used by Apple PowerBook 2400c -// 65535 is used by IBM PC-110 - -uint8_t gamtor_vga_device::mem_linear_r(offs_t offset) -{ - if (!machine().side_effects_disabled()) - LOGMASKED(LOG_MEM_READS, "Reading gamtor SVGA memory %08x\n", offset); - return vga.memory[offset]; -} - -void gamtor_vga_device::mem_linear_w(offs_t offset, uint8_t data) -{ - if (offset & 2) - vga.memory[(offset >> 2) + 0x20000] = data; - else - vga.memory[(offset & 1) | (offset >> 1)] = data; -} - - -uint8_t gamtor_vga_device::port_03b0_r(offs_t offset) -{ - uint8_t res; - - switch(offset) - { - default: - res = vga_device::port_03b0_r(offset ^ 3); - break; - } - - return res; -} - -void gamtor_vga_device::port_03b0_w(offs_t offset, uint8_t data) -{ - switch(offset) - { - default: - vga_device::port_03b0_w(offset ^ 3,data); - break; - } -} - -uint8_t gamtor_vga_device::port_03c0_r(offs_t offset) -{ - uint8_t res; - - switch(offset) - { - default: - res = vga_device::port_03c0_r(offset ^ 3); - break; - } - - return res; -} - -void gamtor_vga_device::port_03c0_w(offs_t offset, uint8_t data) -{ - switch(offset) - { - default: - vga_device::port_03c0_w(offset ^ 3,data); - break; - } -} - -uint8_t gamtor_vga_device::port_03d0_r(offs_t offset) -{ - uint8_t res; - - switch(offset) - { - default: - res = vga_device::port_03d0_r(offset ^ 3); - break; - } - - return res; -} - -void gamtor_vga_device::port_03d0_w(offs_t offset, uint8_t data) -{ - switch(offset) - { - default: - vga_device::port_03d0_w(offset ^ 3,data); - break; - } -} - -uint16_t gamtor_vga_device::offset() -{ - // TODO: pinpoint whatever extra register that wants this shifted by 1 - return vga_device::offset() << 1; -} - -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(); - LOGMASKED(LOG_INVALID, "Invalid dot clock %i selected.\n",clock_type); - break; - } -// LOG("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(); -} - -uint8_t ati_vga_device::mem_r(offs_t offset) -{ - if(svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en) - { - if(ati.ext_reg[0x3d] & 0x04) - { - offset &= 0x1ffff; - return vga.memory[(offset+svga.bank_r*0x20000) % vga.svga_intf.vram_size]; - } - else - { - offset &= 0xffff; - return vga.memory[(offset+svga.bank_r*0x10000) % vga.svga_intf.vram_size]; - } - } - - return vga_device::mem_r(offset); -} - -void ati_vga_device::mem_w(offs_t offset, uint8_t data) -{ - if(svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en) - { - if(ati.ext_reg[0x3d] & 0x04) - { - offset &= 0x1ffff; - vga.memory[(offset+svga.bank_w*0x20000) % vga.svga_intf.vram_size] = data; - } - else - { - offset &= 0xffff; - vga.memory[(offset+svga.bank_w*0x10000) % vga.svga_intf.vram_size] = data; - } - } - else - vga_device::mem_w(offset,data); -} - - -uint8_t ati_vga_device::ati_port_ext_r(offs_t offset) -{ - uint8_t ret = 0xff; - - switch(offset) - { - case 0: - break; - case 1: - switch(ati.ext_reg_select) - { - case 0x20: - ret = 0x10; // 16-bit ROM access - LOGMASKED(LOG_ATI, "ATI20 read\n"); - break; - case 0x28: // Vertical line counter (high) - ret = (screen().vpos() >> 8) & 0x03; - LOGMASKED(LOG_ATI, "ATI28 (vertical line high) read\n"); - break; - case 0x29: // Vertical line counter (low) - ret = screen().vpos() & 0xff; // correct? - LOGMASKED(LOG_ATI, "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 - LOGMASKED(LOG_ATI, "ATI2A (VGA ID) read\n"); - break; - case 0x37: - { - eeprom_serial_93cxx_device* eep = subdevice("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 - LOGMASKED(LOG_ATI, "ATI3D (EGA DIP emulation) read\n"); - break; - default: - ret = ati.ext_reg[ati.ext_reg_select]; - LOGMASKED(LOG_ATI, "ATI: Extended VGA register 0x01CE index %02x read\n",ati.ext_reg_select); - break; - } - break; - } - return ret; -} - -void ati_vga_device::ati_port_ext_w(offs_t offset, uint8_t data) -{ - 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) - { - 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; - LOGMASKED(LOG_ATI, "ATI: ATI23 write %02x\n",data); - break; - case 0x26: - ati.ext_reg[ati.ext_reg_select] = data & 0xc9; - LOGMASKED(LOG_ATI, "ATI: ATI26 write %02x\n",data); - break; - case 0x2b: - ati.ext_reg[ati.ext_reg_select] = data & 0xdf; - LOGMASKED(LOG_ATI, "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 - } - LOGMASKED(LOG_ATI, "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; - LOGMASKED(LOG_ATI, "ATI: ATI30 write %02x\n",data); - break; - case 0x31: - ati.ext_reg[ati.ext_reg_select] = data & 0x7f; - LOGMASKED(LOG_ATI, "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); - } - //LOGMASKED(LOG_ATI, "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("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 - { - LOGMASKED(LOG_ATI, "ATI: ATI33 write %02x\n",data); - } - break; - case 0x38: - ati.ext_reg[ati.ext_reg_select] = data & 0xef; - LOGMASKED(LOG_ATI, "ATI: ATI38 write %02x\n",data); - break; - case 0x39: - ati.ext_reg[ati.ext_reg_select] = data & 0xfe; - LOGMASKED(LOG_ATI, "ATI: ATI39 write %02x\n",data); - break; - case 0x3a: // General purpose read-write bits - ati.ext_reg[ati.ext_reg_select] = data & 0x07; - LOGMASKED(LOG_ATI, "ATI: ATI3A write %02x\n",data); - break; - case 0x3c: // Reserved, should be 0 - ati.ext_reg[ati.ext_reg_select] = 0; - LOGMASKED(LOG_ATI, "ATI: ATI3C write %02x\n",data); - break; - case 0x3d: - ati.ext_reg[ati.ext_reg_select] = data & 0xfd; - LOGMASKED(LOG_ATI, "ATI: ATI3D write %02x\n",data); - break; - case 0x3e: - ati.ext_reg[ati.ext_reg_select] = data & 0x1f; - LOGMASKED(LOG_ATI, "ATI: ATI3E write %02x\n",data); - break; - case 0x3f: - ati.ext_reg[ati.ext_reg_select] = data & 0x0f; - LOGMASKED(LOG_ATI, "ATI: ATI3F write %02x\n",data); - break; - default: - LOGMASKED(LOG_ATI, "ATI: Extended VGA register 0x01CE index %02x write %02x\n",ati.ext_reg_select,data); - break; - } - 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) - */ -uint8_t ibm8514a_device::ibm8514_status_r(offs_t offset) -{ - switch(offset) - { - case 0: - return m_vga->vga_vblank() << 1; - case 2: - return m_vga->port_03c0_r(6); - case 3: - return m_vga->port_03c0_r(7); - case 4: - return m_vga->port_03c0_r(8); - case 5: - return m_vga->port_03c0_r(9); - } - return 0; -} - -void ibm8514a_device::ibm8514_htotal_w(offs_t offset, uint8_t data) -{ - switch(offset) - { - case 0: - ibm8514.htotal = data & 0xff; - break; - case 2: - m_vga->port_03c0_w(6,data); - break; - case 3: - m_vga->port_03c0_w(7,data); - break; - case 4: - m_vga->port_03c0_w(8,data); - break; - case 5: - m_vga->port_03c0_w(9,data); - break; - } - //vga.crtc.horz_total = data & 0x01ff; - LOGMASKED(LOG_8514, "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. - */ -uint16_t 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). - */ -void ibm8514a_device::ibm8514_subcontrol_w(uint16_t data) -{ - ibm8514.subctrl = data; - ibm8514.substatus &= ~(data & 0x0f); // reset interrupts -// LOGMASKED(LOG_8514, "8514/A: Subsystem control write %04x\n",data); -} - -uint16_t 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 - */ -void ibm8514a_device::ibm8514_display_ctrl_w(uint16_t data) -{ - 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; - } -} - -void ibm8514a_device::ibm8514_advfunc_w(uint16_t data) -{ - ibm8514.advfunction_ctrl = data; - ibm8514.passthrough = data & 0x0001; -} - -uint16_t ibm8514a_device::ibm8514_htotal_r() -{ - return ibm8514.htotal; -} - -uint16_t ibm8514a_device::ibm8514_vtotal_r() -{ - return ibm8514.vtotal; -} - -void ibm8514a_device::ibm8514_vtotal_w(uint16_t data) -{ - ibm8514.vtotal = data; -// vga.crtc.vert_total = data; - LOGMASKED(LOG_8514, "8514/A: Vertical total write %04x\n",data); -} - -uint16_t ibm8514a_device::ibm8514_vdisp_r() -{ - return ibm8514.vdisp; -} - -void ibm8514a_device::ibm8514_vdisp_w(uint16_t data) -{ - ibm8514.vdisp = data; -// vga.crtc.vert_disp_end = data >> 3; - LOGMASKED(LOG_8514, "8514/A: Vertical Displayed write %04x\n",data); -} - -uint16_t ibm8514a_device::ibm8514_vsync_r() -{ - return ibm8514.vsync; -} - -void ibm8514a_device::ibm8514_vsync_w(uint16_t data) -{ - ibm8514.vsync = data; - LOGMASKED(LOG_8514, "8514/A: Vertical Sync write %04x\n",data); -} - -void ibm8514a_device::enabled() -{ - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; -} - -uint16_t mach8_device::mach8_ec0_r() -{ - return ibm8514.ec0; -} - -void mach8_device::mach8_ec0_w(uint16_t data) -{ - ibm8514.ec0 = data; - LOGMASKED(LOG_8514, "8514/A: Extended configuration 0 write %04x\n",data); -} - -uint16_t mach8_device::mach8_ec1_r() -{ - return ibm8514.ec1; -} - -void mach8_device::mach8_ec1_w(uint16_t data) -{ - ibm8514.ec1 = data; - LOGMASKED(LOG_8514, "8514/A: Extended configuration 1 write %04x\n",data); -} - -uint16_t mach8_device::mach8_ec2_r() -{ - return ibm8514.ec2; -} - -void mach8_device::mach8_ec2_w(uint16_t data) -{ - ibm8514.ec2 = data; - LOGMASKED(LOG_8514, "8514/A: Extended configuration 2 write %04x\n",data); -} - -uint16_t mach8_device::mach8_ec3_r() -{ - return ibm8514.ec3; -} - -void mach8_device::mach8_ec3_w(uint16_t data) -{ - ibm8514.ec3 = data; - LOGMASKED(LOG_8514, "8514/A: Extended configuration 3 write %04x\n",data); -} - -uint16_t mach8_device::mach8_ext_fifo_r() -{ - return 0x00; // for now, report all FIFO slots as free -} - -void mach8_device::mach8_linedraw_index_w(uint16_t data) -{ - mach8.linedraw = data & 0x07; - LOGMASKED(LOG_8514, "Mach8: Line Draw Index write %04x\n",data); -} - -uint16_t mach8_device::mach8_bresenham_count_r() -{ - return ibm8514.rect_width & 0x1fff; -} - -void mach8_device::mach8_bresenham_count_w(uint16_t data) -{ - ibm8514.rect_width = data & 0x1fff; - LOGMASKED(LOG_8514, "Mach8: Bresenham count write %04x\n",data); -} - -uint16_t mach8_device::mach8_linedraw_r() -{ - return 0xff; -} - -void mach8_device::mach8_linedraw_w(uint16_t data) -{ - // 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; - } - LOGMASKED(LOG_ATI, "ATI: Linedraw register write %04x, mode %i\n",data,mach8.linedraw); -} - -uint16_t mach8_device::mach8_sourcex_r() -{ - return ibm8514.dest_x & 0x07ff; -} - -uint16_t mach8_device::mach8_sourcey_r() -{ - return ibm8514.dest_y & 0x07ff; -} - -void mach8_device::mach8_ext_leftscissor_w(uint16_t data) -{ - // TODO -} - -void mach8_device::mach8_ext_topscissor_w(uint16_t data) -{ - // TODO -} - -uint16_t mach8_device::mach8_scratch0_r() -{ - return mach8.scratch0; -} - -void mach8_device::mach8_scratch0_w(uint16_t data) -{ - mach8.scratch0 = data; - LOGMASKED(LOG_8514, "Mach8: Scratch Pad 0 write %04x\n",data); -} - -uint16_t mach8_device::mach8_scratch1_r() -{ - return mach8.scratch1; -} - -void mach8_device::mach8_scratch1_w(uint16_t data) -{ - mach8.scratch1 = data; - LOGMASKED(LOG_8514, "Mach8: Scratch Pad 1 write %04x\n",data); -} - -void mach8_device::mach8_crt_pitch_w(uint16_t data) -{ - mach8.crt_pitch = data & 0x00ff; - m_vga->set_offset(mach8.crt_pitch); - LOGMASKED(LOG_8514, "Mach8: CRT pitch write %04x\n",mach8.crt_pitch); -} - -void mach8_device::mach8_ge_offset_l_w(uint16_t data) -{ - mach8.ge_offset = (mach8.ge_offset & 0x0f0000) | data; - LOGMASKED(LOG_8514, "Mach8: Graphics Engine Offset (Low) write %05x\n",mach8.ge_offset); -} - -void mach8_device::mach8_ge_offset_h_w(uint16_t data) -{ - mach8.ge_offset = (mach8.ge_offset & 0x00ffff) | ((data & 0x000f) << 16); - LOGMASKED(LOG_8514, "Mach8: Graphics Engine Offset (High) write %05x\n",mach8.ge_offset); -} - -void mach8_device::mach8_ge_pitch_w(uint16_t data) -{ - mach8.ge_pitch = data & 0x00ff; - LOGMASKED(LOG_8514, "Mach8: Graphics Engine pitch write %04x\n",mach8.ge_pitch); -} - -void mach8_device::mach8_scan_x_w(uint16_t data) -{ - mach8.scan_x = data & 0x07ff; - - if((mach8.dp_config & 0xe000) == 0x4000) // foreground source is the Pixel Transfer register - { - ibm8514.state = MACH8_DRAWING_SCAN; - ibm8514.bus_size = (mach8.dp_config & 0x0200) >> 9; - ibm8514.data_avail = true; - } - // TODO: non-wait version of Scan To X - LOGMASKED(LOG_8514, "Mach8: Scan To X write %04x\n",mach8.scan_x); -} - -void mach8_device::mach8_pixel_xfer_w(offs_t offset, uint16_t data) -{ - ibm8514_pixel_xfer_w(offset, data); - - if(ibm8514.state == MACH8_DRAWING_SCAN) - mach8_wait_scan(); -} - -void mach8_device::mach8_wait_scan() -{ - uint32_t offset = mach8.ge_offset << 2; - uint32_t addr = (ibm8514.prev_y * (mach8.ge_pitch * 8)) + ibm8514.prev_x; - - // TODO: support reverse direction - if(mach8.dp_config & 0x0010) // drawing enabled - { - 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; - } - } - } -} - -/* - * 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) - */ -void mach8_device::mach8_dp_config_w(uint16_t data) -{ - mach8.dp_config = data; - LOGMASKED(LOG_8514, "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) - */ -uint16_t 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 - */ -uint16_t 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) - */ -void mach8_device::mach8_ge_ext_config_w(uint16_t data) -{ - mach8.ge_ext_config = data; - if(data & 0x8000) - popmessage("EEPROM enabled via 7AEE"); -} - -xga_copro_device::xga_copro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, XGA_COPRO, tag, owner, clock) - , m_var(TYPE::XGA) - , m_mem_read_cb(*this) - , m_mem_write_cb(*this) -{ -} - -void xga_copro_device::start_command() -{ - switch((m_pelop >> 24) & 15) - { - case 11: - if(m_var == TYPE::OTI111) - { - LOGMASKED(LOG_OAK, "oak specific textblt\n"); - break; - } - [[fallthrough]]; - case 12: - if(m_var == TYPE::OTI111) - { - LOGMASKED(LOG_OAK, "oak specific fast pattern copy\n"); - break; - } - [[fallthrough]]; - default: - LOGMASKED(LOG_INVALID, "invalid pel op step func %d\n", (m_pelop >> 24) & 15); - break; - case 2: - LOGMASKED(LOG_COMMANDS, "draw and step read\n"); - break; - case 3: - LOGMASKED(LOG_COMMANDS, "line draw read\n"); - break; - case 4: - LOGMASKED(LOG_COMMANDS, "draw and step write\n"); - break; - case 5: - LOGMASKED(LOG_COMMANDS, "line draw write\n"); - break; - case 8: - do_pxblt(); - break; - case 9: - LOGMASKED(LOG_COMMANDS, "inverting pxblt\n"); - break; - case 10: - LOGMASKED(LOG_COMMANDS, "area fill pxblt\n"); - break; - } -} - -// Can maps be not byte aligned? XGA manual says they must be 32bit aligned in at least some cases. -u32 xga_copro_device::read_map_pixel(int x, int y, int map) -{ - offs_t addr = m_pelmap_base[map]; - int width = m_pelmap_width[map] + 1; - int height = m_pelmap_height[map] + 1; - int endian = m_pelmap_format[map] & 8; - int wbytes, bits; - u8 byte; - if((x > width) || (y > height) || (x < 0) || (y < 0)) - return 0; - switch(m_pelmap_format[map] & 7) - { - case 0: - wbytes = width / 8; - addr += y * wbytes; - addr += x / 8; - byte = m_mem_read_cb(addr); - bits = (x % 8) - (endian ? 8 : 0); - return (byte >> bits) & 1; - case 1: - wbytes = width / 4; - addr += y * wbytes; - addr += x / 4; - byte = m_mem_read_cb(addr); - bits = (x % 4) - (endian ? 4 : 0); - return (byte >> (bits * 2)) & 3; - case 2: - wbytes = width / 2; - addr += y * wbytes; - addr += x / 2; - byte = m_mem_read_cb(addr); - bits = (x % 2) - (endian ? 2 : 0); - return (byte >> (bits * 4)) & 0xf; - case 3: - wbytes = width; - addr += y * wbytes; - addr += x; - //LOG("r %d %d %d %d %d %x\n",map,width, height,x,y, addr); - return m_mem_read_cb(addr); - case 4: - wbytes = width * 2; - addr += y * wbytes; - addr += x * 2; - if(endian) - return m_mem_read_cb(addr + 1) | (m_mem_read_cb(addr) << 8); - return m_mem_read_cb(addr) | (m_mem_read_cb(addr + 1) << 8); - case 5: - wbytes = width * 4; - addr += y * wbytes; - addr += x * 4; - if(endian) - return m_mem_read_cb(addr + 3) | (m_mem_read_cb(addr + 2) << 8) | - (m_mem_read_cb(addr + 1) << 16) | (m_mem_read_cb(addr) << 24); - return m_mem_read_cb(addr) | (m_mem_read_cb(addr + 1) << 8) | - (m_mem_read_cb(addr + 2) << 16) | (m_mem_read_cb(addr + 3) << 24); - } - LOGMASKED(LOG_INVALID, "invalid pixel map mode %d %d\n", map, m_pelmap_format[map] & 7); - return 0; -} - -void xga_copro_device::write_map_pixel(int x, int y, int map, u32 pixel) -{ - offs_t addr = m_pelmap_base[map]; - int width = m_pelmap_width[map] + 1; - int height = m_pelmap_height[map] + 1; - int endian = m_pelmap_format[map] & 8; - int wbytes; - u8 byte, mask; - if((x > width) || (y > height) || (x < 0) || (y < 0)) - return; - switch(m_pelmap_format[map] & 7) - { - case 0: - wbytes = width / 8; - addr += y * wbytes; - addr += x / 8; - byte = m_mem_read_cb(addr); - mask = 1 << ((x % 8) - (endian ? 8 : 0)); - byte = (byte & ~mask) | ((pixel ? 0xff : 0) & mask); - m_mem_write_cb(addr, byte); - break; - case 1: - wbytes = width / 4; - addr += y * wbytes; - addr += x / 4; - byte = m_mem_read_cb(addr); - mask = 3 << (((x % 4) - (endian ? 4 : 0)) * 2); - byte = (byte & ~mask) | ((pixel ? 0xff : 0) & mask); - m_mem_write_cb(addr, byte); - break; - case 2: - wbytes = width / 2; - addr += y * wbytes; - addr += x / 2; - byte = m_mem_read_cb(addr); - mask = 0xf << (((x % 2) - (endian ? 2 : 0)) * 4); - byte = (byte & ~mask) | ((pixel ? 0xff : 0) & mask); - m_mem_write_cb(addr, byte); - break; - case 3: - wbytes = width; - addr += y * wbytes; - addr += x; - //LOG("w %d %d %d %d %d %x %x\n",map,width, height,x,y, addr, pixel); - m_mem_write_cb(addr, (u8)pixel); - break; - case 4: - wbytes = width * 2; - addr += y * wbytes; - addr += x * 2; - if(endian) - { - m_mem_write_cb(addr + 1, pixel & 0xff); - m_mem_write_cb(addr, pixel >> 8); - } - else - { - m_mem_write_cb(addr, pixel & 0xff); - m_mem_write_cb(addr + 1, pixel >> 8); - } - break; - case 5: - wbytes = width * 4; - addr += y * wbytes; - addr += x * 4; - if(endian) - { - m_mem_write_cb(addr + 3, pixel & 0xff); - m_mem_write_cb(addr + 2, pixel >> 8); - m_mem_write_cb(addr + 1, pixel >> 16); - m_mem_write_cb(addr, pixel >> 24); - } - else - { - m_mem_write_cb(addr, pixel & 0xff); - m_mem_write_cb(addr + 1, pixel >> 8); - m_mem_write_cb(addr + 2, pixel >> 16); - m_mem_write_cb(addr + 3, pixel >> 24); - } - break; - default: - LOGMASKED(LOG_INVALID, "invalid pixel map mode %d %d\n", map, m_pelmap_format[map] & 7); - break; - } -} - -u32 xga_copro_device::rop(u32 s, u32 d, u8 op) -{ - if(m_var == TYPE::OTI111) - { - switch(op) - { - default: - case 0: - return 0; - case 1: - return ~s & ~d; - case 2: - return ~s & d; - case 3: - return ~s; - case 4: - return s & ~d; - case 5: - return ~d; - case 6: - return s ^ d; - case 7: - return ~s | ~d; - case 8: - return s & d; - case 9: - return s ^ ~d; - case 10: - return d; - case 11: - return ~s | d; - case 12: - return s; - case 13: - return s | ~d; - case 14: - return s | d; - case 15: - return -1; - } - } - switch(op) - { - default: - case 0: - return 0; - case 1: - return s & d; - case 2: - return s & ~d; - case 3: - return s; - case 4: - return ~s & d; - case 5: - return d; - case 6: - return s ^ d; - case 7: - return s | d; - case 8: - return ~s & ~d; - case 9: - return s ^ ~d; - case 10: - return ~d; - case 11: - return s | ~d; - case 12: - return ~s; - case 13: - return ~s | d; - case 14: - return ~s | ~d; - case 15: - return -1; - case 16: - return std::max(s, d); - case 17: - return std::min(s, d); - case 18: - return 0; // saturate add - case 19: - return 0; // saturate sub d - s - case 20: - return 0; // saturate sub s - d - case 21: - return 0; // avg - } -} - -void xga_copro_device::do_pxblt() -{ - u8 dir = (m_pelop >> 25) & 2; - int xstart, xend, xdir, ystart, yend, ydir; - u8 srcmap = ((m_pelop >> 20) & 0xf) - 1; - u8 dstmap = ((m_pelop >> 16) & 0xf) - 1; - u8 patmap = ((m_pelop >> 12) & 0xf) - 1; - LOGMASKED(LOG_COMMANDS, "pxblt src %d pat %d dst %d dim1 %d dim2 %d srcbase %x dstbase %x\n", srcmap+1, dstmap+1, patmap+1, m_opdim1 & 0xfff, m_opdim2 & 0xfff, m_pelmap_base[srcmap+1], m_pelmap_base[dstmap+1]); - LOGMASKED(LOG_COMMANDS, "%d %d %d %d\n", m_srcxaddr & 0xfff, m_srcyaddr & 0xfff, m_dstxaddr & 0xfff, m_dstyaddr & 0xfff); - if((srcmap > 2) || (dstmap > 2) || ((patmap > 2) && (patmap != 7) && (patmap != 8))) - { - LOGMASKED(LOG_INVALID, "invalid pelmap\n"); - return; - } - if(dir & 1) - { - ystart = (m_opdim2 & 0xfff) + 1; - yend = 0; - ydir = -1; - } - else - { - ystart = 0; - yend = (m_opdim2 & 0xfff) + 1; - ydir = 1; - } - if(dir & 2) - { - xstart = (m_opdim1 & 0xfff) + 1; - xend = 0; - xdir = -1; - } - else - { - xstart = 0; - xend = (m_opdim1 & 0xfff) + 1; - xdir = 1; - } - - std::function dstwrap; - if(m_var == TYPE::OTI111) - dstwrap = [](s16 addr) { return addr & 0xfff; }; - else - { - dstwrap = [](s16 addr) - { - addr = addr & 0x1fff; - return (addr & 0x1800) == 0x1800 ? addr | 0xf800 : addr; - }; - } - - for(int y = ystart; y != yend; y += ydir) - { - u16 patxaddr = m_patxaddr & 0xfff; - u16 srcxaddr = m_srcxaddr & 0xfff; - s16 dstxaddr = dstwrap(m_dstxaddr); - s16 dstyaddr = dstwrap(m_dstyaddr); - for(int x = xstart; x != xend; x += xdir) - { - u32 src, dst, pat; - if(patmap < 3) - { - pat = read_map_pixel(patxaddr, m_patyaddr & 0xfff, patmap + 1); - patxaddr += xdir; - } - else - pat = 1; //TODO: generate from source mode - if(pat) - src = (((m_pelop >> 28) & 3) == 2) ? read_map_pixel(srcxaddr, m_srcyaddr & 0xfff, srcmap + 1) : m_fcolor; - else - src = (((m_pelop >> 30) & 3) == 2) ? read_map_pixel(srcxaddr, m_srcyaddr & 0xfff, srcmap + 1) : m_bcolor; - srcxaddr += xdir; - dst = read_map_pixel(dstxaddr, dstyaddr, dstmap + 1); - dst = (dst & ~m_pelbmask) | (rop(src, dst, pat ? m_fmix : m_bmix) & m_pelbmask); - write_map_pixel(dstxaddr, dstyaddr, dstmap + 1, dst); // TODO: color compare - dstxaddr = dstwrap(dstxaddr + xdir); - } - m_patyaddr += ydir; - m_srcyaddr += ydir; - m_dstyaddr += ydir; - } -} - -u8 xga_copro_device::xga_read(offs_t offset) -{ - switch(offset) - { - case 0x12: - return m_pelmap; - case 0x14: - return m_pelmap_base[m_pelmap]; - case 0x15: - return m_pelmap_base[m_pelmap] >> 8; - case 0x16: - return m_pelmap_base[m_pelmap] >> 16; - case 0x17: - return m_pelmap_base[m_pelmap] >> 24; - case 0x18: - return m_pelmap_width[m_pelmap]; - case 0x19: - return m_pelmap_width[m_pelmap] >> 8; - case 0x1a: - return m_pelmap_height[m_pelmap]; - case 0x1b: - return m_pelmap_height[m_pelmap] >> 8; - case 0x1c: - return m_pelmap_format[m_pelmap]; - case 0x20: - return m_bresh_err; - case 0x21: - return m_bresh_err >> 8; - case 0x24: - return m_bresh_k1; - case 0x25: - return m_bresh_k1 >> 8; - case 0x28: - return m_bresh_k2; - case 0x29: - return m_bresh_k2 >> 8; - case 0x2c: - return m_dir; - case 0x2d: - return m_dir >> 8; - case 0x2e: - return m_dir >> 16; - case 0x2f: - return m_dir >> 24; - case 0x48: - if(m_var == TYPE::OTI111) - return m_fmix << 4 | m_bmix; - return m_fmix; - case 0x49: - if(m_var == TYPE::OTI111) - return 0; - return m_bmix; - case 0x4a: - return m_destccc; - case 0x4c: - return m_destccv; - case 0x4d: - return m_destccv >> 8; - case 0x4e: - return m_destccv >> 16; - case 0x4f: - return m_destccv >> 24; - case 0x50: - return m_pelbmask; - case 0x51: - return m_pelbmask >> 8; - case 0x52: - return m_pelbmask >> 16; - case 0x53: - return m_pelbmask >> 24; - case 0x54: - return m_carrychain; - case 0x55: - return m_carrychain >> 8; - case 0x56: - return m_carrychain >> 16; - case 0x57: - return m_carrychain >> 24; - case 0x58: - return m_fcolor; - case 0x59: - return m_fcolor >> 8; - case 0x5a: - return m_fcolor >> 16; - case 0x5b: - return m_fcolor >> 24; - case 0x5c: - return m_bcolor; - case 0x5d: - return m_bcolor >> 8; - case 0x5e: - return m_bcolor >> 16; - case 0x5f: - return m_bcolor >> 24; - case 0x60: - return m_opdim1; - case 0x61: - return m_opdim1 >> 8; - case 0x62: - return m_opdim2; - case 0x63: - return m_opdim2 >> 8; - case 0x6c: - return m_maskorigx; - case 0x6d: - return m_maskorigx >> 8; - case 0x6e: - return m_maskorigy; - case 0x6f: - return m_maskorigy >> 8; - case 0x70: - return m_srcxaddr; - case 0x71: - return m_srcxaddr >> 8; - case 0x72: - return m_srcyaddr; - case 0x73: - return m_srcyaddr >> 8; - case 0x74: - return m_patxaddr; - case 0x75: - return m_patxaddr >> 8; - case 0x76: - return m_patyaddr; - case 0x77: - return m_patyaddr >> 8; - case 0x78: - return m_dstxaddr; - case 0x79: - return m_dstxaddr >> 8; - case 0x7a: - return m_dstyaddr; - case 0x7b: - return m_dstyaddr >> 8; - case 0x7c: - return m_pelop; - case 0x7d: - return m_pelop >> 8; - case 0x7e: - return m_pelop >> 16; - case 0x7f: - return m_pelop >> 24; - } - return 0; -} - -void xga_copro_device::xga_write(offs_t offset, u8 data) -{ - switch(offset) - { - case 0x12: - m_pelmap = data & 3; - break; - case 0x14: - m_pelmap_base[m_pelmap] = (m_pelmap_base[m_pelmap] & ~0xff) | data; - break; - case 0x15: - m_pelmap_base[m_pelmap] = (m_pelmap_base[m_pelmap] & ~0xff00) | (data << 8); - break; - case 0x16: - m_pelmap_base[m_pelmap] = (m_pelmap_base[m_pelmap] & ~0xff0000) | (data << 16); - break; - case 0x17: - m_pelmap_base[m_pelmap] = (m_pelmap_base[m_pelmap] & ~0xff000000) | (data << 24); - break; - case 0x18: - m_pelmap_width[m_pelmap] = (m_pelmap_width[m_pelmap] & ~0xff) | data; - break; - case 0x19: - m_pelmap_width[m_pelmap] = (m_pelmap_width[m_pelmap] & ~0xff00) | (data << 8); - break; - case 0x1a: - m_pelmap_height[m_pelmap] = (m_pelmap_height[m_pelmap] & ~0xff) | data; - break; - case 0x1b: - m_pelmap_height[m_pelmap] = (m_pelmap_height[m_pelmap] & ~0xff00) | (data << 8); - break; - case 0x1c: - m_pelmap_format[m_pelmap] = data; - break; - case 0x20: - m_bresh_err = (m_bresh_err & ~0xff) | data; - break; - case 0x21: - m_bresh_err = (m_bresh_err & ~0xff00) | (data << 8); - break; - case 0x24: - m_bresh_k1 = (m_bresh_k1 & ~0xff) | data; - break; - case 0x25: - m_bresh_k1 = (m_bresh_k1 & ~0xff00) | (data << 8); - break; - case 0x28: - m_bresh_k2 = (m_bresh_k2 & ~0xff) | data; - break; - case 0x29: - m_bresh_k2 = (m_bresh_k2 & ~0xff00) | (data << 8); - break; - case 0x2c: - m_dir = (m_dir & ~0xff) | data; - break; - case 0x2d: - m_dir = (m_dir & ~0xff00) | (data << 8); - break; - case 0x2e: - m_dir = (m_dir & ~0xff0000) | (data << 16); - break; - case 0x2f: - m_dir = (m_dir & ~0xff000000) | (data << 24); - break; - case 0x48: - if(m_var == TYPE::OTI111) - { - m_fmix = data >> 4; - m_bmix = data & 0xf; - break; - } - m_fmix = data; - break; - case 0x49: - if(m_var == TYPE::OTI111) - break; - m_bmix = data; - break; - case 0x4a: - m_destccc = data; - break; - case 0x4c: - m_destccv = (m_destccv & ~0xff) | data; - break; - case 0x4d: - m_destccv = (m_destccv & ~0xff00) | (data << 8); - break; - case 0x4e: - m_destccv = (m_destccv & ~0xff0000) | (data << 16); - break; - case 0x4f: - m_destccv = (m_destccv & ~0xff000000) | (data << 24); - break; - case 0x50: - m_pelbmask = (m_pelbmask & ~0xff) | data; - break; - case 0x51: - m_pelbmask = (m_pelbmask & ~0xff00) | (data << 8); - break; - case 0x52: - m_pelbmask = (m_pelbmask & ~0xff0000) | (data << 16); - break; - case 0x53: - m_pelbmask = (m_pelbmask & ~0xff000000) | (data << 24); - break; - case 0x54: - m_carrychain = (m_carrychain & ~0xff) | data; - break; - case 0x55: - m_carrychain = (m_carrychain & ~0xff00) | (data << 8); - break; - case 0x56: - m_carrychain = (m_carrychain & ~0xff0000) | (data << 16); - break; - case 0x57: - m_carrychain = (m_carrychain & ~0xff000000) | (data << 24); - break; - case 0x58: - m_fcolor = (m_fcolor & ~0xff) | data; - break; - case 0x59: - m_fcolor = (m_fcolor & ~0xff00) | (data << 8); - break; - case 0x5a: - m_fcolor = (m_fcolor & ~0xff0000) | (data << 16); - break; - case 0x5b: - m_fcolor = (m_fcolor & ~0xff000000) | (data << 24); - break; - case 0x5c: - m_bcolor = (m_bcolor & ~0xff) | data; - break; - case 0x5d: - m_bcolor = (m_bcolor & ~0xff00) | (data << 8); - break; - case 0x5e: - m_bcolor = (m_bcolor & ~0xff0000) | (data << 16); - break; - case 0x5f: - m_bcolor = (m_bcolor & ~0xff000000) | (data << 24); - break; - case 0x60: - m_opdim1 = (m_opdim1 & ~0xff) | data; - break; - case 0x61: - m_opdim1 = (m_opdim1 & ~0xff00) | (data << 8); - break; - case 0x62: - m_opdim2 = (m_opdim2 & ~0xff) | data; - break; - case 0x63: - m_opdim2 = (m_opdim2 & ~0xff00) | (data << 8); - break; - case 0x6c: - m_maskorigx = (m_maskorigx & ~0xff) | data; - break; - case 0x6d: - m_maskorigx = (m_maskorigx & ~0xff00) | (data << 8); - break; - case 0x6e: - m_maskorigy = (m_maskorigy & ~0xff) | data; - break; - case 0x6f: - m_maskorigy = (m_maskorigy & ~0xff00) | (data << 8); - break; - case 0x70: - m_srcxaddr = (m_srcxaddr & ~0xff) | data; - break; - case 0x71: - m_srcxaddr = (m_srcxaddr & ~0xff00) | (data << 8); - break; - case 0x72: - m_srcyaddr = (m_srcyaddr & ~0xff) | data; - break; - case 0x73: - m_srcyaddr = (m_srcyaddr & ~0xff00) | (data << 8); - break; - case 0x74: - m_patxaddr = (m_patxaddr & ~0xff) | data; - break; - case 0x75: - m_patxaddr = (m_patxaddr & ~0xff00) | (data << 8); - break; - case 0x76: - m_patyaddr = (m_patyaddr & ~0xff) | data; - break; - case 0x77: - m_patyaddr = (m_patyaddr & ~0xff00) | (data << 8); - break; - case 0x78: - m_dstxaddr = (m_dstxaddr & ~0xff) | data; - break; - case 0x79: - m_dstxaddr = (m_dstxaddr & ~0xff00) | (data << 8); - break; - case 0x7a: - m_dstyaddr = (m_dstyaddr & ~0xff) | data; - break; - case 0x7b: - m_dstyaddr = (m_dstyaddr & ~0xff00) | (data << 8); - break; - case 0x7c: - m_pelop = (m_pelop & ~0xff) | data; - break; - case 0x7d: - m_pelop = (m_pelop & ~0xff00) | (data << 8); - break; - case 0x7e: - m_pelop = (m_pelop & ~0xff0000) | (data << 16); - break; - case 0x7f: - m_pelop = (m_pelop & ~0xff000000) | (data << 24); - start_command(); - break; - } -} - -void xga_copro_device::device_start() -{ - m_mem_read_cb.resolve_safe(0); - m_mem_write_cb.resolve_safe(); -} - -void xga_copro_device::device_reset() -{ - m_pelmap = 0; -} - -oak_oti111_vga_device::oak_oti111_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : svga_device(mconfig, OTI111, tag, owner, clock) - , m_xga(*this, "xga") -{ -} - -void oak_oti111_vga_device::device_add_mconfig(machine_config &config) -{ - XGA_COPRO(config, m_xga, 0); - m_xga->mem_read_callback().set(FUNC(oak_oti111_vga_device::mem_linear_r)); - m_xga->mem_write_callback().set(FUNC(oak_oti111_vga_device::mem_linear_w)); - m_xga->set_type(xga_copro_device::TYPE::OTI111); -} - -u8 oak_oti111_vga_device::xga_read(offs_t offset) -{ - switch(offset) - { - case 0x13: //fifo status - return 0xf; - default: - return m_xga->xga_read(offset); - } - return 0; -} - -void oak_oti111_vga_device::xga_write(offs_t offset, u8 data) -{ - m_xga->xga_write(offset, data); -} - -void oak_oti111_vga_device::device_start() -{ - svga_device::device_start(); - std::fill(std::begin(m_oak_regs), std::end(m_oak_regs), 0); -} - -u8 oak_oti111_vga_device::dac_read(offs_t offset) -{ - if(offset >= 6) - return vga_device::port_03c0_r(offset); - return 0; -} - -void oak_oti111_vga_device::dac_write(offs_t offset, u8 data) -{ - if(offset >= 6) - vga_device::port_03c0_w(offset, data); -} - - -u8 oak_oti111_vga_device::port_03d0_r(offs_t offset) -{ - uint8_t res = 0xff; - switch(offset) - { - case 14: - return m_oak_idx; - case 15: - return m_oak_idx <= 0x3a ? m_oak_regs[m_oak_idx] : 0; - default: - if (CRTC_PORT_ADDR == 0x3d0) - res = vga_device::port_03d0_r(offset); - break; - } - - return res; -} - -void oak_oti111_vga_device::port_03d0_w(offs_t offset, uint8_t data) -{ - switch(offset) - { - case 14: - m_oak_idx = data; - break; - case 15: - if(m_oak_idx > 0x3a) - break; - m_oak_regs[m_oak_idx] = data; - switch(m_oak_idx) - { - case 0x21: - svga.rgb8_en = BIT(data, 2); - break; - case 0x33: - vga.crtc.no_wrap = BIT(data, 0); - break; - } - break; - default: - if (CRTC_PORT_ADDR == 0x3d0) - vga_device::port_03d0_w(offset,data); - break; - } -} - -uint16_t oak_oti111_vga_device::offset() -{ - uint16_t off = svga_device::offset(); - - if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en) - return vga.crtc.offset << 4; // TODO: there must a register to control this - else - return off; -} diff --git a/src/devices/video/pc_vga.h b/src/devices/video/pc_vga.h index 233b824cae6..bf0a9252c3b 100644 --- a/src/devices/video/pc_vga.h +++ b/src/devices/video/pc_vga.h @@ -11,7 +11,12 @@ #ifndef MAME_VIDEO_PC_VGA_H #define MAME_VIDEO_PC_VGA_H +#pragma once + #include "screen.h" +#include "ibm8514a.h" + +class ibm8514a_device; // ======================> vga_device @@ -40,6 +45,8 @@ public: void set_offset(uint16_t val) { vga.crtc.offset = val; } void set_vram_size(size_t vram_size) { vga.svga_intf.vram_size = vram_size; } + // FIXME: should be protected, but virge_pci.cpp violates this + inline uint16_t get_crtc_port() { return BIT(vga.miscellaneous_output, 0) ? 0x3d0 : 0x3b0; } protected: enum @@ -62,6 +69,7 @@ protected: // device-level overrides virtual void device_start() override; virtual void device_reset() override; + virtual ioport_constructor device_input_ports() const override; // device_palette_interface overrides virtual uint32_t palette_entries() const noexcept override { return 0x100; } @@ -86,7 +94,7 @@ protected: void gc_reg_write(uint8_t index,uint8_t data); virtual uint16_t offset(); virtual uint32_t start_addr(); - inline uint8_t vga_latch_write(int offs, uint8_t data); + virtual uint8_t vga_latch_write(int offs, uint8_t data); inline uint8_t rotate_right(uint8_t val) { return (val >> vga.gc.rotate_count) | (val << (8 - vga.gc.rotate_count)); } inline uint8_t vga_logical_op(uint8_t data, uint8_t plane, uint8_t mask) { @@ -111,12 +119,9 @@ protected: return res; } - struct vga_t { - vga_t(device_t &owner) : read_dipswitch(owner) { } - - read8smo_delegate read_dipswitch; + vga_t(device_t &owner) { } struct { size_t vram_size; @@ -237,6 +242,8 @@ protected: struct { uint8_t reg; } oak; } vga; + required_ioport m_input_sense; + emu_timer *m_vblank_timer; }; @@ -277,514 +284,6 @@ protected: } svga; }; -// ======================> ibm8514_device - -class ibm8514a_device : public device_t -{ -public: - ibm8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - template void set_vga(T &&tag) { m_vga.set_tag(std::forward(tag)); } - void set_vga_owner() { m_vga.set_tag(DEVICE_SELF); } - - void enabled(); - - bool is_8514a_enabled() { return ibm8514.enabled; } - bool is_passthrough_set() { return ibm8514.passthrough; } - - uint16_t ibm8514_gpstatus_r(); - void ibm8514_cmd_w(uint16_t data); - void ibm8514_display_ctrl_w(uint16_t data); - uint16_t ibm8514_line_error_r(); - void ibm8514_line_error_w(uint16_t data); - uint8_t ibm8514_status_r(offs_t offset); - void ibm8514_htotal_w(offs_t offset, uint8_t data); - uint16_t ibm8514_substatus_r(); - void ibm8514_subcontrol_w(uint16_t data); - uint16_t ibm8514_subcontrol_r(); - uint16_t ibm8514_htotal_r(); - uint16_t ibm8514_vtotal_r(); - void ibm8514_vtotal_w(uint16_t data); - uint16_t ibm8514_vdisp_r(); - void ibm8514_vdisp_w(uint16_t data); - uint16_t ibm8514_vsync_r(); - void ibm8514_vsync_w(uint16_t data); - uint16_t ibm8514_desty_r(); - void ibm8514_desty_w(uint16_t data); - uint16_t ibm8514_destx_r(); - void ibm8514_destx_w(uint16_t data); - uint16_t ibm8514_ssv_r(); - void ibm8514_ssv_w(uint16_t data); - uint16_t ibm8514_currentx_r(); - void ibm8514_currentx_w(uint16_t data); - uint16_t ibm8514_currenty_r(); - void ibm8514_currenty_w(uint16_t data); - uint16_t ibm8514_width_r(); - void ibm8514_width_w(uint16_t data); - uint16_t ibm8514_fgcolour_r(); - void ibm8514_fgcolour_w(uint16_t data); - uint16_t ibm8514_bgcolour_r(); - void ibm8514_bgcolour_w(uint16_t data); - uint16_t ibm8514_multifunc_r(); - void ibm8514_multifunc_w(uint16_t data); - uint16_t ibm8514_backmix_r(); - void ibm8514_backmix_w(uint16_t data); - uint16_t ibm8514_foremix_r(); - void ibm8514_foremix_w(uint16_t data); - uint16_t ibm8514_pixel_xfer_r(offs_t offset); - virtual void ibm8514_pixel_xfer_w(offs_t offset, uint16_t data); - uint16_t ibm8514_read_mask_r(); - void ibm8514_read_mask_w(uint16_t data); - uint16_t ibm8514_write_mask_r(); - void ibm8514_write_mask_w(uint16_t data); - void ibm8514_advfunc_w(uint16_t data); - - void ibm8514_wait_draw(); - struct - { - uint16_t htotal; // Horizontal total (9 bits) - uint16_t vtotal; // Vertical total adjust (3 bits), Vertical total base (9 bit) - uint16_t vdisp; - uint16_t vsync; - uint16_t subctrl; - uint16_t substatus; - uint8_t display_ctrl; - uint16_t ssv; - uint16_t ec0; - uint16_t ec1; - uint16_t ec2; - uint16_t ec3; - bool gpbusy; - bool data_avail; - int16_t dest_x; - int16_t dest_y; - int16_t curr_x; - int16_t curr_y; - int16_t prev_x; - int16_t prev_y; - int16_t line_axial_step; - int16_t line_diagonal_step; - int16_t line_errorterm; - uint16_t current_cmd; - uint16_t src_x; - uint16_t src_y; - int16_t scissors_left; - int16_t scissors_right; - int16_t scissors_top; - int16_t scissors_bottom; - uint16_t rect_width; - uint16_t rect_height; - uint32_t fgcolour; - uint32_t bgcolour; - uint16_t fgmix; - uint16_t bgmix; - uint32_t pixel_xfer; - uint16_t pixel_control; - uint8_t bus_size; - uint8_t multifunc_sel; - uint16_t multifunc_misc; - uint32_t read_mask; - uint32_t write_mask; - uint16_t advfunction_ctrl; - bool enabled; - bool passthrough; - - int state; - uint8_t wait_vector_len; - uint8_t wait_vector_dir; - bool wait_vector_draw; - uint8_t wait_vector_count; - - } ibm8514; - -protected: - ibm8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - void ibm8514_write(uint32_t offset, uint32_t src); - void ibm8514_write_fg(uint32_t offset); - void ibm8514_write_bg(uint32_t offset); - - required_device m_vga; // for pass-through -private: - void ibm8514_draw_vector(uint8_t len, uint8_t dir, bool draw); - void ibm8514_wait_draw_ssv(); - void ibm8514_draw_ssv(uint8_t data); - void ibm8514_wait_draw_vector(); - - //uint8_t* m_vram; // the original 8514/A has it's own VRAM, but most VGA+8514 combination cards will have - // only one set of VRAM, so this will only be needed in standalone 8514/A cards - //uint32_t m_vramsize; -}; - -// device type definition -DECLARE_DEVICE_TYPE(IBM8514A, ibm8514a_device) - - -class mach8_device : public ibm8514a_device -{ -public: - mach8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - uint16_t mach8_ec0_r(); - void mach8_ec0_w(uint16_t data); - uint16_t mach8_ec1_r(); - void mach8_ec1_w(uint16_t data); - uint16_t mach8_ec2_r(); - void mach8_ec2_w(uint16_t data); - uint16_t mach8_ec3_r(); - void mach8_ec3_w(uint16_t data); - uint16_t mach8_ext_fifo_r(); - void mach8_linedraw_index_w(uint16_t data); - uint16_t mach8_bresenham_count_r(); - void mach8_bresenham_count_w(uint16_t data); - void mach8_linedraw_w(uint16_t data); - uint16_t mach8_linedraw_r(); - uint16_t mach8_scratch0_r(); - void mach8_scratch0_w(uint16_t data); - uint16_t mach8_scratch1_r(); - void mach8_scratch1_w(uint16_t data); - uint16_t mach8_config1_r(); - uint16_t mach8_config2_r(); - uint16_t mach8_sourcex_r(); - uint16_t mach8_sourcey_r(); - void mach8_ext_leftscissor_w(uint16_t data); - void mach8_ext_topscissor_w(uint16_t data); - uint16_t mach8_clksel_r() { return mach8.clksel; } - void mach8_crt_pitch_w(uint16_t data); - void mach8_patt_data_w(uint16_t data) { logerror("Mach8: Pattern Data write (unimplemented)\n"); } - void mach8_ge_offset_l_w(uint16_t data); - void mach8_ge_offset_h_w(uint16_t data); - void mach8_ge_pitch_w(uint16_t data); - uint16_t mach8_ge_ext_config_r() { return mach8.ge_ext_config; } - void mach8_ge_ext_config_w(uint16_t data); // TODO: handle 8-bit I/O - void mach8_scan_x_w(uint16_t data); - void mach8_dp_config_w(uint16_t data); - uint16_t mach8_readonly_r() { return 0; } - void mach8_pixel_xfer_w(offs_t offset, uint16_t data); - void mach8_clksel_w(uint16_t data) { mach8.ati_mode = true; ibm8514.passthrough = data & 0x0001; mach8.clksel = data; } // read only on the mach8 - void mach8_advfunc_w(uint16_t data) { mach8.ati_mode = false; ibm8514_advfunc_w(data); } - uint16_t get_ext_config() { return mach8.ge_ext_config; } - uint16_t offset() { if(mach8.ati_mode) return mach8.ge_pitch; else return 128; } - -protected: - mach8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - virtual void device_start() override; - struct - { - uint16_t scratch0; - uint16_t scratch1; - uint16_t linedraw; - uint16_t clksel; - uint16_t crt_pitch; - uint16_t dp_config; - uint32_t ge_offset; - uint16_t ge_pitch; - uint16_t ge_ext_config; // usage varies between the mach8 and mach32 (except for 8514/A monitor alias) - uint16_t scan_x; - bool ati_mode; - } mach8; - -private: - void mach8_wait_scan(); - -}; - -// device type definition -DECLARE_DEVICE_TYPE(MACH8, mach8_device) - - -// ======================> tseng_vga_device - -class tseng_vga_device : public svga_device -{ -public: - // construction/destruction - tseng_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t port_03b0_r(offs_t offset) override; - virtual void port_03b0_w(offs_t offset, uint8_t data) override; - virtual uint8_t port_03c0_r(offs_t offset) override; - virtual void port_03c0_w(offs_t offset, uint8_t data) override; - virtual uint8_t port_03d0_r(offs_t offset) override; - virtual void port_03d0_w(offs_t offset, uint8_t data) override; - virtual uint8_t mem_r(offs_t offset) override; - virtual void mem_w(offs_t offset, uint8_t data) override; - -protected: - virtual void device_start() override; - -private: - void tseng_define_video_mode(); - uint8_t tseng_crtc_reg_read(uint8_t index); - void tseng_crtc_reg_write(uint8_t index, uint8_t data); - uint8_t tseng_seq_reg_read(uint8_t index); - void tseng_seq_reg_write(uint8_t index, uint8_t data); - void tseng_attribute_reg_write(uint8_t index, uint8_t data); - - struct - { - uint8_t reg_3d8; - uint8_t dac_ctrl; - uint8_t dac_state; - uint8_t horz_overflow; - uint8_t aux_ctrl; - bool ext_reg_ena; - uint8_t misc1; - uint8_t misc2; - }et4k; - -}; - - -// device type definition -DECLARE_DEVICE_TYPE(TSENG_VGA, tseng_vga_device) - - -// ======================> ati_vga_device - -class ati_vga_device : public svga_device -{ -public: - // construction/destruction - ati_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t mem_r(offs_t offset) override; - virtual void mem_w(offs_t offset, uint8_t data) override; - - // VGA registers - virtual uint8_t port_03c0_r(offs_t offset) override; - uint8_t ati_port_ext_r(offs_t offset); - void ati_port_ext_w(offs_t offset, uint8_t data); - - virtual uint16_t offset() override; - - mach8_device* get_8514() { return m_8514; } -protected: - ati_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void device_add_mconfig(machine_config &config) override; - virtual void ati_define_video_mode(); - void set_dot_clock(); - struct - { - uint8_t ext_reg[64]; - uint8_t ext_reg_select; - uint8_t vga_chip_id; - } ati; - -private: - mach8_device* m_8514; -}; - -// device type definition -DECLARE_DEVICE_TYPE(ATI_VGA, ati_vga_device) - - -// ======================> s3_vga_device - -class s3_vga_device : public ati_vga_device -{ -public: - // construction/destruction - s3_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t port_03b0_r(offs_t offset) override; - virtual void port_03b0_w(offs_t offset, uint8_t data) override; - virtual uint8_t port_03c0_r(offs_t offset) override; - virtual void port_03c0_w(offs_t offset, uint8_t data) override; - virtual uint8_t port_03d0_r(offs_t offset) override; - virtual void port_03d0_w(offs_t offset, uint8_t data) override; - virtual uint8_t mem_r(offs_t offset) override; - virtual void mem_w(offs_t offset, uint8_t data) override; - - virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override; - - virtual TIMER_CALLBACK_MEMBER(vblank_timer_cb) override; - - ibm8514a_device* get_8514() { return m_8514; } - -protected: - s3_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_add_mconfig(machine_config &config) override; - - struct - { - uint8_t memory_config; - uint8_t ext_misc_ctrl_2; - uint8_t crt_reg_lock; - uint8_t reg_lock1; - uint8_t reg_lock2; - uint8_t enable_8514; - uint8_t enable_s3d; - uint8_t cr3a; - uint8_t cr42; - uint8_t cr43; - uint8_t cr51; - uint8_t cr53; - uint8_t id_high; - uint8_t id_low; - uint8_t revision; - uint8_t id_cr30; - uint32_t strapping; // power-on strapping bits - uint8_t sr10; // MCLK PLL - uint8_t sr11; // MCLK PLL - uint8_t sr12; // DCLK PLL - uint8_t sr13; // DCLK PLL - uint8_t sr15; // CLKSYN control 2 - uint8_t sr17; // CLKSYN test - uint8_t clk_pll_r; // individual DCLK PLL values - uint8_t clk_pll_m; - uint8_t clk_pll_n; - - // data for memory-mapped I/O - uint16_t mmio_9ae8; - uint16_t mmio_bee8; - uint16_t mmio_96e8; - - // hardware graphics cursor - uint8_t cursor_mode; - uint16_t cursor_x; - uint16_t cursor_y; - uint16_t cursor_start_addr; - uint8_t cursor_pattern_x; // cursor pattern origin - uint8_t cursor_pattern_y; - uint8_t cursor_fg[4]; - uint8_t cursor_bg[4]; - uint8_t cursor_fg_ptr; - uint8_t cursor_bg_ptr; - uint8_t extended_dac_ctrl; - } s3; - virtual uint16_t offset() override; - -private: - uint8_t s3_crtc_reg_read(uint8_t index); - void s3_define_video_mode(void); - void s3_crtc_reg_write(uint8_t index, uint8_t data); - uint8_t s3_seq_reg_read(uint8_t index); - void s3_seq_reg_write(uint8_t index, uint8_t data); - ibm8514a_device* m_8514; -}; - -// device type definition -DECLARE_DEVICE_TYPE(S3_VGA, s3_vga_device) - -// ======================> gamtor_vga_device - -class gamtor_vga_device : public svga_device -{ -public: - // construction/destruction - gamtor_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - - virtual uint8_t port_03b0_r(offs_t offset) override; - virtual void port_03b0_w(offs_t offset, uint8_t data) override; - virtual uint8_t port_03c0_r(offs_t offset) override; - virtual void port_03c0_w(offs_t offset, uint8_t data) override; - virtual uint8_t port_03d0_r(offs_t offset) override; - virtual void port_03d0_w(offs_t offset, uint8_t data) override; -// virtual uint8_t mem_r(offs_t offset) override; -// virtual void mem_w(offs_t offset, uint8_t data) override; - virtual uint8_t mem_linear_r(offs_t offset) override; - virtual void mem_linear_w(offs_t offset,uint8_t data) override; - -protected: - virtual uint16_t offset() override; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(GAMTOR_VGA, gamtor_vga_device) - -class xga_copro_device : public device_t -{ -public: - enum class TYPE { - XGA, - OTI111 - }; - - xga_copro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - u8 xga_read(offs_t offset); - void xga_write(offs_t offset, u8 data); - - auto mem_read_callback() { return m_mem_read_cb.bind(); } - auto mem_write_callback() { return m_mem_write_cb.bind(); } - auto set_type(TYPE var) { m_var = var; } -protected: - virtual void device_start() override; - virtual void device_reset() override; -private: - void start_command(); - void do_pxblt(); - u32 read_map_pixel(int x, int y, int map); - void write_map_pixel(int x, int y, int map, u32 pixel); - u32 rop(u32 src, u32 dst, u8 rop); - - u8 m_pelmap; - u32 m_pelmap_base[4]; - u16 m_pelmap_width[4]; - u16 m_pelmap_height[4]; - u8 m_pelmap_format[4]; - s16 m_bresh_err; - s16 m_bresh_k1; - s16 m_bresh_k2; - u32 m_dir; - u8 m_fmix; - u8 m_bmix; - u8 m_destccc; - u32 m_destccv; - u32 m_pelbmask; - u32 m_carrychain; - u32 m_fcolor; - u32 m_bcolor; - u16 m_opdim1; - u16 m_opdim2; - u16 m_maskorigx; - u16 m_maskorigy; - u16 m_srcxaddr; - u16 m_srcyaddr; - u16 m_patxaddr; - u16 m_patyaddr; - u16 m_dstxaddr; - u16 m_dstyaddr; - u32 m_pelop; - TYPE m_var; - devcb_read8 m_mem_read_cb; - devcb_write8 m_mem_write_cb; -}; - -DECLARE_DEVICE_TYPE(XGA_COPRO, xga_copro_device) - -class oak_oti111_vga_device : public svga_device -{ -public: - oak_oti111_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - u8 xga_read(offs_t offset); - void xga_write(offs_t offset, u8 data); - u8 dac_read(offs_t offset); - void dac_write(offs_t offset, u8 data); - virtual u8 port_03d0_r(offs_t offset) override; - virtual void port_03d0_w(offs_t offset, uint8_t data) override; -protected: - virtual void device_add_mconfig(machine_config &config) override; - virtual void device_start() override; - virtual uint16_t offset() override; -private: - u8 m_oak_regs[0x3b]; - u8 m_oak_idx; - required_device m_xga; -}; - -DECLARE_DEVICE_TYPE(OTI111, oak_oti111_vga_device) /* pega notes (paradise) @@ -792,31 +291,6 @@ DECLARE_DEVICE_TYPE(OTI111, oak_oti111_vga_device) ROM_LOAD("40100", 0xc0000, 0x8000, CRC(d2d1f1ae) SHA1(98302006ee38a17c09bd75504cc18c0649174e33) ) - 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 - */ /* diff --git a/src/devices/video/pc_vga_ati.cpp b/src/devices/video/pc_vga_ati.cpp new file mode 100644 index 00000000000..b50d7b562ff --- /dev/null +++ b/src/devices/video/pc_vga_ati.cpp @@ -0,0 +1,352 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald + +#include "emu.h" +#include "pc_vga_ati.h" + +#define LOG_WARN (1U << 1) + +#define VERBOSE (LOG_GENERAL) +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + +#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) + +DEFINE_DEVICE_TYPE(ATI_VGA, ati_vga_device, "ati_vga", "ATi VGA") + +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) +{ +} + +void ati_vga_device::device_start() +{ + svga_device::device_start(); + memset(&ati, 0, sizeof(ati)); + save_pointer(ati.ext_reg,"ATi Extended Registers",64); + m_8514 = subdevice("8514a"); + ati.vga_chip_id = 0x06; // 28800-6 +} + +//------------------------------------------------- +// 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"); +} + +uint8_t ati_vga_device::port_03c0_r(offs_t offset) +{ + 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(offset); + break; + } + return data; +} + +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(); + LOGWARN( "Invalid dot clock %i selected.\n",clock_type); + break; + } +// LOG("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(); +} + +uint8_t ati_vga_device::mem_r(offs_t offset) +{ + if(svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en) + { + if(ati.ext_reg[0x3d] & 0x04) + { + offset &= 0x1ffff; + return vga.memory[(offset+svga.bank_r*0x20000) % vga.svga_intf.vram_size]; + } + else + { + offset &= 0xffff; + return vga.memory[(offset+svga.bank_r*0x10000) % vga.svga_intf.vram_size]; + } + } + + return vga_device::mem_r(offset); +} + +void ati_vga_device::mem_w(offs_t offset, uint8_t data) +{ + if(svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en) + { + if(ati.ext_reg[0x3d] & 0x04) + { + offset &= 0x1ffff; + vga.memory[(offset+svga.bank_w*0x20000) % vga.svga_intf.vram_size] = data; + } + else + { + offset &= 0xffff; + vga.memory[(offset+svga.bank_w*0x10000) % vga.svga_intf.vram_size] = data; + } + } + else + vga_device::mem_w(offset,data); +} + + +uint8_t ati_vga_device::ati_port_ext_r(offs_t offset) +{ + uint8_t ret = 0xff; + + switch(offset) + { + case 0: + break; + case 1: + switch(ati.ext_reg_select) + { + case 0x20: + ret = 0x10; // 16-bit ROM access + LOG( "ATI20 read\n"); + break; + case 0x28: // Vertical line counter (high) + ret = (screen().vpos() >> 8) & 0x03; + LOG( "ATI28 (vertical line high) read\n"); + break; + case 0x29: // Vertical line counter (low) + ret = screen().vpos() & 0xff; // correct? + LOG( "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 + LOG( "ATI2A (VGA ID) read\n"); + break; + case 0x37: + { + eeprom_serial_93cxx_device* eep = subdevice("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 + LOG( "ATI3D (EGA DIP emulation) read\n"); + break; + default: + ret = ati.ext_reg[ati.ext_reg_select]; + LOG( "ATI: Extended VGA register 0x01CE index %02x read\n",ati.ext_reg_select); + break; + } + break; + } + return ret; +} + +void ati_vga_device::ati_port_ext_w(offs_t offset, uint8_t data) +{ + 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) + { + 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; + LOG( "ATI: ATI23 write %02x\n",data); + break; + case 0x26: + ati.ext_reg[ati.ext_reg_select] = data & 0xc9; + LOG( "ATI: ATI26 write %02x\n",data); + break; + case 0x2b: + ati.ext_reg[ati.ext_reg_select] = data & 0xdf; + LOG( "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 + } + LOG( "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; + LOG( "ATI: ATI30 write %02x\n",data); + break; + case 0x31: + ati.ext_reg[ati.ext_reg_select] = data & 0x7f; + LOG( "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); + } + //LOG( "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("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 + { + LOG( "ATI: ATI33 write %02x\n",data); + } + break; + case 0x38: + ati.ext_reg[ati.ext_reg_select] = data & 0xef; + LOG( "ATI: ATI38 write %02x\n",data); + break; + case 0x39: + ati.ext_reg[ati.ext_reg_select] = data & 0xfe; + LOG( "ATI: ATI39 write %02x\n",data); + break; + case 0x3a: // General purpose read-write bits + ati.ext_reg[ati.ext_reg_select] = data & 0x07; + LOG( "ATI: ATI3A write %02x\n",data); + break; + case 0x3c: // Reserved, should be 0 + ati.ext_reg[ati.ext_reg_select] = 0; + LOG( "ATI: ATI3C write %02x\n",data); + break; + case 0x3d: + ati.ext_reg[ati.ext_reg_select] = data & 0xfd; + LOG( "ATI: ATI3D write %02x\n",data); + break; + case 0x3e: + ati.ext_reg[ati.ext_reg_select] = data & 0x1f; + LOG( "ATI: ATI3E write %02x\n",data); + break; + case 0x3f: + ati.ext_reg[ati.ext_reg_select] = data & 0x0f; + LOG( "ATI: ATI3F write %02x\n",data); + break; + default: + LOG( "ATI: Extended VGA register 0x01CE index %02x write %02x\n",ati.ext_reg_select,data); + break; + } + break; + } + ati_define_video_mode(); +} diff --git a/src/devices/video/pc_vga_ati.h b/src/devices/video/pc_vga_ati.h new file mode 100644 index 00000000000..d8c8b31d47b --- /dev/null +++ b/src/devices/video/pc_vga_ati.h @@ -0,0 +1,52 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald + +#ifndef MAME_VIDEO_PC_VGA_ATI_H +#define MAME_VIDEO_PC_VGA_ATI_H + +#pragma once + +#include "screen.h" +#include "video/pc_vga.h" +#include "video/ati_mach8.h" +#include "machine/eepromser.h" + +class ati_vga_device : public svga_device +{ +public: + // construction/destruction + ati_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual uint8_t mem_r(offs_t offset) override; + virtual void mem_w(offs_t offset, uint8_t data) override; + + // VGA registers + virtual uint8_t port_03c0_r(offs_t offset) override; + uint8_t ati_port_ext_r(offs_t offset); + void ati_port_ext_w(offs_t offset, uint8_t data); + + virtual uint16_t offset() override; + + mach8_device* get_8514() { return m_8514; } +protected: + ati_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_add_mconfig(machine_config &config) override; + virtual void ati_define_video_mode(); + void set_dot_clock(); + struct + { + uint8_t ext_reg[64]; + uint8_t ext_reg_select; + uint8_t vga_chip_id; + } ati; + +private: + mach8_device* m_8514; +}; + +// device type definition +DECLARE_DEVICE_TYPE(ATI_VGA, ati_vga_device) + +#endif // MAME_VIDEO_PC_VGA_ATI_H diff --git a/src/devices/video/pc_vga_nvidia.cpp b/src/devices/video/pc_vga_nvidia.cpp new file mode 100644 index 00000000000..51c51692383 --- /dev/null +++ b/src/devices/video/pc_vga_nvidia.cpp @@ -0,0 +1,440 @@ +// license:BSD-3-Clause +// copyright-holders: Angelo Salese +// thanks-to: Marcelina Koscielnicka +/************************************************************************************************** + +nVidia NV3:G80 VGA core + +TODO: +- Many blanks in the CRTC section; +\- Untested beyond 16bpp modes; +\- Regular VGA gfx modes don't draw text properly in some tests (common bug with other VGA archs); +\- Diamond Viper BIOS don't report back the video card string at POST; +\- STB BIOS sets 640x481 after POST; +\- ASUS BIOS sets 640x428 (?); +- The "red screen" from VGA SENSE may really be a ping from monitor signal; +- Sequencer register $6 for lock/unlock of extended VGA; +- I2C; +- Interrupts; +- RMA access; +- PLL portion(s), understand how it chooses extended clocks; +- Verify that NV10 really uses this chip (seems to access more regs?) +- Video overlay (PVIDEO, NV10+); +- VGA stack (NV40+); +- TV encoder (NV17:NV20, NV30:G80); + +Notes: +- NV1 looks very different, not worth to subclass here; + +References: +- https://envytools.readthedocs.io/en/latest/hw/display/nv3/index.html + +**************************************************************************************************/ + +#include "emu.h" +#include "pc_vga_nvidia.h" + +#define LOG_WARN (1U << 1) +#define LOG_RMA (1U << 2) // extensively accessed even on POST +#define LOG_CRTC (1U << 3) + +#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_CRTC) +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + +#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) +#define LOGRMA(...) LOGMASKED(LOG_RMA, __VA_ARGS__) +#define LOGCRTC(...) LOGMASKED(LOG_CRTC, __VA_ARGS__) + +DEFINE_DEVICE_TYPE(NVIDIA_NV3_VGA, nvidia_nv3_vga_device, "nvidia_nv3_vga", "nVidia NV3 VGA i/f") + +nvidia_nv3_vga_device::nvidia_nv3_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : svga_device(mconfig, NVIDIA_NV3_VGA, tag, owner, clock) +{ +} + +void nvidia_nv3_vga_device::device_add_mconfig(machine_config &config) +{ + // TODO: I2C, likely for DDC (AIDA16 extensively test that in non-safe mode) +} + +static INPUT_PORTS_START(nv3_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_HIGH, IPT_UNKNOWN ) // causes a red screen at POST if low + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) +INPUT_PORTS_END + +ioport_constructor nvidia_nv3_vga_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(nv3_vga_sense); +} + +void nvidia_nv3_vga_device::device_start() +{ + svga_device::device_start(); + zero(); + + vga.crtc.maximum_scan_line = 1; + + vga.svga_intf.seq_regcount = 0x05; + vga.svga_intf.crtc_regcount = 0x40; + // TODO: shared with main GPU, fake it for now + // Start address ends at 20 bits so 0x1fffff mask / 2,097,151 bytes / 2MB window is (theorically) given + // we assume that is really 4 MB, VESA tests extensively tests with 0x7f banks + vga.svga_intf.vram_size = 4*1024*1024; + + for (int i = 0; i < 0x100; i++) + set_pen_color(i, pal1bit(i & 1), pal1bit((i & 2) >> 1), pal1bit((i & 4) >> 2)); + +// vga.miscellaneous_output = 0; + m_ext_offset = 0; + save_item(NAME(m_ext_offset)); +} + +// TODO: should really calculate the access bit internally +uint8_t nvidia_nv3_vga_device::port_03b0_r(offs_t offset) +{ + uint8_t res = 0xff; + + if (get_crtc_port() == 0x3b0) + { + switch(offset) + { + case 0: + case 1: + case 2: + case 3: + LOGRMA("RMA_ACCESS R %02x\n", offset & 3); + break; + + case 5: + res = crtc_reg_read(vga.crtc.index); + break; + + default: + res = vga_device::port_03b0_r(offset); + break; + } + } + + return res; +} + +void nvidia_nv3_vga_device::port_03b0_w(offs_t offset, uint8_t data) +{ + if (get_crtc_port() == 0x3b0) + { + switch(offset) + { + case 0: + case 1: + case 2: + case 3: + LOGRMA("RMA_ACCESS W %02x -> %02x\n", offset & 3, data); + break; + + case 5: + vga.crtc.data[vga.crtc.index] = data; + crtc_reg_write(vga.crtc.index, data); + break; + + default: + vga_device::port_03b0_w(offset, data); + break; + } + } + //define_video_mode(); +} + +uint8_t nvidia_nv3_vga_device::port_03d0_r(offs_t offset) +{ + uint8_t res = 0xff; + + if (get_crtc_port() == 0x3d0) + { + switch(offset) + { + case 0: + case 1: + case 2: + case 3: + LOGRMA("RMA_ACCESS R %02x\n", offset & 3); + break; + + case 5: + res = crtc_reg_read(vga.crtc.index); + break; + + default: + res = vga_device::port_03d0_r(offset); + break; + } + } + + return res; +} + +void nvidia_nv3_vga_device::port_03d0_w(offs_t offset, uint8_t data) +{ + if (get_crtc_port() == 0x3d0) + { + switch(offset) + { + case 0: + case 1: + case 2: + case 3: + LOGRMA("RMA_ACCESS W %02x -> %02x\n", offset & 3, data); + break; + + case 5: + vga.crtc.data[vga.crtc.index] = data; + crtc_reg_write(vga.crtc.index, data); + break; + + default: + vga_device::port_03d0_w(offset, data); + break; + } + } + //define_video_mode(); +} + +uint8_t nvidia_nv3_vga_device::mem_r(offs_t offset) +{ + if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en) + return svga_device::mem_linear_r(offset + (svga.bank_r * 0x8000)); + return svga_device::mem_r(offset); +} + +void nvidia_nv3_vga_device::mem_w(offs_t offset, uint8_t data) +{ + if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en) + { + svga_device::mem_linear_w(offset + (svga.bank_w * 0x8000), data); + return; + } + svga_device::mem_w(offset, data); +} + +uint16_t nvidia_nv3_vga_device::offset() +{ + if (svga.rgb8_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en) + return (vga.crtc.offset << 3) + m_ext_offset; + return svga_device::offset(); +} + +/* + * xxx- ---- Row offset bits 3-5 + * ---x xxxx Start address bits 16-20 + */ +// map(0x19, 0x19) REPAINT_0 + +/* + * ???? ?-?? + * ---- -x-- Shifts row offset by 1 bit (verify) + */ +// map(0x1a, 0x1a) REPAINT_1 + +/* + * --xx xxxx write bank, in 32k units + */ +// map(0x1d, 0x1d) WRITE_BANK + +/* + * --xx xxxx read bank + */ +// map(0x1e, 0x1e) READ_BANK + +/* + * ---x ---- Horizontal Total bit 8 + * ---- x--- Vertical Sync Start bit 10 + * ---- -x-- Vertical Blank Start bit 10 + * ---- --x- Vertical Display End bit 10 + * ---- ---x Vertical Total bit 10 + */ +// map(0x25, 0x25) EXTENDED_VERT + +/* + * ---- --xx Pixel Format + * ---- --00 VGA + * ---- --01 8bpp + * ---- --10 16bpp + * ---- --11 32bpp + */ +// map(0x28, 0x28) PIXEL_FMT + +/* + * ---- ---x Horizontal Display End bit 8 + */ +// map(0x2d, 0x2d) EXTENDED_HORZ + +/* + * ---- xxx- RMA index + * ---- ---x enable RMA + */ +// map(0x38, 0x38) RMA_MODE + +/* + * ---- x--- SDA + * ---- -x-- SCL + */ +// map(0x3e, 0x3e) I2C_READ + +/* + * ---x ---- SCL + * ---- x--- SDA + */ +// map(0x3f, 0x3f) I2C_WRITE + +uint8_t nvidia_nv3_vga_device::crtc_reg_read(uint8_t index) +{ + uint8_t res = 0; + + //index &= 0x3f; + + if(index <= 0x18) + return svga_device::crtc_reg_read(index); + + switch(index) + { + case 0x19: + res = m_repaint[0]; + break; + case 0x1a: + res = m_repaint[1]; + break; + case 0x1d: + res = svga.bank_w; + break; + case 0x1e: + res = svga.bank_r; + break; + case 0x25: + res = vga.crtc.data[0x25]; + break; + case 0x28: + res = svga.rgb32_en ? 3 : svga.rgb16_en ? 2 : svga.rgb8_en ? 1 : 0; + break; + case 0x2d: + res = (vga.crtc.horz_disp_end >> 10) & 1; + break; + case 0x38: + res = vga.crtc.data[0x38]; + LOGRMA("RMA_MODE read %02x\n", res); + break; + default: + LOGCRTC("EXT CRTC: %02x Read\n", index); + //machine().debug_break(); + res = vga.crtc.data[index]; + + break; + } + + return res; +} + +void nvidia_nv3_vga_device::crtc_reg_write(uint8_t index, uint8_t data) +{ + //index &= 0x3f; + if(index <= 0x18) + { + svga_device::crtc_reg_write(index,data); + return; + } + + switch(index) + { + case 0x19: + // TODO: untested, likely used in extended text modes + //vga.crtc.start_addr_latch &= ~0x1f0000; + //vga.crtc.start_addr_latch |= ((data & 0x1f) << 16); + m_ext_offset = ((data & 0xe0) >> 5) << 11; + m_repaint[0] = data; + //m_ext_offset = recalculate_ext_offset(); + LOGCRTC("EXT CRTC: REPAINT_0 %02x\n", data); + break; + case 0x1a: + // TODO: this definitely uses more regs in the equation + // REPAINT_0 REPAINT_1 base_offset + // 10eh 320x200 16bpp 0x00 0x3c 0x50 560 / 0x230 (with scan doubler?) + // 111h 640x480 16bpp 0x00 0x3c 0xa0 1120 / 0x460 + // 114h 800x600 16bpp 0x00 0x3c 0xc8 1400 / 0x578 + // 117h 1024x768 16bpp 0x20 0x3c 0x00 2048 / 0x800 + // 11ah 1280x1024 16bpp 0x20 0x38 0x40 2496 / 0x9c0 + // 132h 320x400 16bpp 0x00 0x3c 0x50 560 / 0x230 + // 13dh 640x400 16bpp 0x00 0x3c 0xa0 1120 / 0x460 + // 142h 1152x864 16bpp 0x20 0x3c 0x20 2272 / 0x8e0 + // 146h 1600x1200 16bpp 0x00 0x38 0x90 3056 / 0xbf0 + // 14bh 960x720 16bpp 0x10 0x3c 0xf0 1680 / 0x690 + m_repaint[1] = data; + //m_ext_offset = recalculate_ext_offset(); + LOGCRTC("EXT CRTC: REPAINT_1 %02x\n", data); + break; + case 0x1d: + if (data & 0x80) + LOGWARN("WRITE_BANK: attempt to write to undocumented bits %02x\n", data); + svga.bank_w = data & 0x7f; + break; + case 0x1e: + if (data & 0x80) + LOGWARN("READ_BANK: attempt to write to undocumented bits %02x\n", data); + svga.bank_r = data & 0x7f; + break; + case 0x25: + if (data & 0xe0) + LOGWARN("EXTENDED_VERT: attempt to write to undocumented bits %02x\n", data); + LOGCRTC("EXT CRTC: EXTENDED_VERT %02x\n", data & 0x1f); + vga.crtc.horz_total = (vga.crtc.horz_total & 0x00ff) | ((BIT(data, 4) << 8)); + //vga.crtc.?? = (vga.crtc.?? & 0x03ff) | ((BIT(data, 3) << 8)); + vga.crtc.vert_blank_start = (vga.crtc.vert_blank_start & 0x03ff) | ((BIT(data, 2) << 10)); + vga.crtc.vert_disp_end = (vga.crtc.vert_disp_end & 0x03ff) | ((BIT(data, 1) << 10)); + vga.crtc.vert_total = (vga.crtc.vert_total & 0x03ff) | ((BIT(data, 0) << 10)); + vga.crtc.data[0x25] = data; + recompute_params(); + break; + case 0x28: + if (data & 0xfc) + LOGWARN("PIXEL_FMT: attempt to write to undocumented bits %02x\n", data); + data &= 3; + // NB: NV3 VESA doesn't have 15bpp support + svga.rgb32_en = svga.rgb16_en = svga.rgb15_en = svga.rgb8_en = 0; + switch(data) + { + case 0: + LOGCRTC("PIXEL_FMT: VGA mode selected\n"); + break; + case 1: + svga.rgb8_en = 1; + LOGCRTC("PIXEL_FMT: SVGA 8bpp mode selected\n"); + break; + case 2: + svga.rgb16_en = 1; + LOGCRTC("PIXEL_FMT: SVGA 16bpp mode selected\n"); + break; + case 3: + svga.rgb32_en = 1; + LOGCRTC("PIXEL_FMT: SVGA 32bpp mode selected\n"); + break; + } + break; + case 0x2d: + if (data & 0xfc) + LOGWARN("EXTENDED_HORZ: attempt to write to undocumented bits %02x\n", data); + LOGCRTC("EXT CRTC: EXTENDED_HORZ %02x\n", data & 1); + vga.crtc.horz_disp_end = (vga.crtc.horz_disp_end & 0x00ff) | ((data & 0x01) << 8); + recompute_params(); + break; + case 0x38: + vga.crtc.data[index] = data; + LOGRMA("RMA_MODE write %s, index %d\n", data & 1 ? "enable" : "disable", (data & 0xe) >> 1); + break; + default: + vga.crtc.data[index] = data; + + LOGCRTC("EXT CRTC [%02x] <- %02x\n",index,data); + break; + } +} diff --git a/src/devices/video/pc_vga_nvidia.h b/src/devices/video/pc_vga_nvidia.h new file mode 100644 index 00000000000..2b75bba2f26 --- /dev/null +++ b/src/devices/video/pc_vga_nvidia.h @@ -0,0 +1,49 @@ +// license:BSD-3-Clause +// copyright-holders: Angelo Salese + +#ifndef MAME_VIDEO_PC_VGA_NVIDIA_H +#define MAME_VIDEO_PC_VGA_NVIDIA_H + +#pragma once + +#include "screen.h" +#include "video/pc_vga.h" + +class nvidia_nv3_vga_device : public svga_device +{ +public: + static constexpr feature_type imperfect_features() { return feature::GRAPHICS; } + + // construction/destruction + nvidia_nv3_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual uint8_t mem_r(offs_t offset) override; + virtual void mem_w(offs_t offset, uint8_t data) override; + + virtual uint8_t port_03b0_r(offs_t offset) override; + virtual void port_03b0_w(offs_t offset, uint8_t data) override; +// virtual uint8_t port_03c0_r(offs_t offset) override; +// virtual void port_03c0_w(offs_t offset, uint8_t data) override; + virtual uint8_t port_03d0_r(offs_t offset) override; + virtual void port_03d0_w(offs_t offset, uint8_t data) override; +// virtual uint8_t mem_r(offs_t offset) override; +// virtual void mem_w(offs_t offset, uint8_t data) override; + +protected: + virtual void device_start() override; + virtual uint8_t crtc_reg_read(uint8_t index) override; + virtual void crtc_reg_write(uint8_t index, uint8_t data) override; + + virtual ioport_constructor device_input_ports() const override; + + virtual void device_add_mconfig(machine_config &config) override; + virtual uint16_t offset() override; + +private: + u8 m_repaint[2]{}; + u16 m_ext_offset = 0; +}; + +DECLARE_DEVICE_TYPE(NVIDIA_NV3_VGA, nvidia_nv3_vga_device) + +#endif // MAME_VIDEO_PC_VGA_NVIDIA_H diff --git a/src/devices/video/pc_vga_s3.cpp b/src/devices/video/pc_vga_s3.cpp new file mode 100644 index 00000000000..28bc2b5de90 --- /dev/null +++ b/src/devices/video/pc_vga_s3.cpp @@ -0,0 +1,1172 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald + +#include "emu.h" +#include "pc_vga_s3.h" + +#define VERBOSE (LOG_GENERAL) +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + +// TODO: remove this enum +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_DEVICE_TYPE(S3_VGA, s3_vga_device, "s3_vga", "S3 Graphics VGA") + +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) + : svga_device(mconfig, type, tag, owner, clock) +{ +} + +void s3_vga_device::device_add_mconfig(machine_config &config) +{ + IBM8514A(config, "8514a", 0).set_vga_owner(); +} + +TIMER_CALLBACK_MEMBER(s3_vga_device::vblank_timer_cb) +{ + // 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) ); +} + +void s3_vga_device::device_start() +{ + svga_device::device_start(); + memset(&s3, 0, sizeof(s3)); + + // Initialise hardware graphics cursor colours, Windows 95 doesn't touch the registers for some reason + for(int x = 0; x < 4; x++) + { + s3.cursor_fg[x] = 0xff; + s3.cursor_bg[x] = 0x00; + } + m_8514 = subdevice("8514a"); + // set device ID + s3.id_high = 0x88; // CR2D + s3.id_low = 0x11; // CR2E + s3.revision = 0x00; // CR2F + s3.id_cr30 = 0xe1; // CR30 +} + +void s3_vga_device::device_reset() +{ + 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; +} + +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(); +} + +void s3_vga_device::s3_define_video_mode() +{ + 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; + } + + 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); +} + +uint8_t s3_vga_device::crtc_reg_read(uint8_t index) +{ + uint8_t res; + + if(index <= 0x18) + res = svga_device::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; +} + +void s3_vga_device::crtc_reg_write(uint8_t index, uint8_t data) +{ + if(index <= 0x18) + svga_device::crtc_reg_write(index,data); + else + { + switch(index) + { + 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 + 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; + LOG("CR36: Strapping data = %08x\n",s3.strapping); + } + break; + case 0x37: + if(s3.reg_lock2 == 0xa5) + { + s3.strapping = (s3.strapping & 0xffff00ff) | (data << 8); + LOG("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); + LOG("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) + { + s3.strapping = (s3.strapping & 0x00ffffff) | (data << 24); + LOG("CR6F: Strapping data = %08x\n",s3.strapping); + } + break; + default: + LOG( "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; + } + } +} + + + +uint8_t s3_vga_device::port_03b0_r(offs_t offset) +{ + uint8_t res = 0xff; + + if (get_crtc_port() == 0x3b0) + { + switch(offset) + { + case 5: + res = s3_vga_device::crtc_reg_read(vga.crtc.index); + break; + default: + res = vga_device::port_03b0_r(offset); + break; + } + } + + return res; +} + +void s3_vga_device::port_03b0_w(offs_t offset, uint8_t data) +{ + if (get_crtc_port() == 0x3b0) + { + switch(offset) + { + case 5: + vga.crtc.data[vga.crtc.index] = data; + s3_vga_device::crtc_reg_write(vga.crtc.index,data); + break; + default: + vga_device::port_03b0_w(offset,data); + break; + } + } +} + +uint8_t s3_vga_device::port_03c0_r(offs_t offset) +{ + uint8_t res; + + switch(offset) + { + case 5: + res = s3_seq_reg_read(vga.sequencer.index); + break; + default: + res = vga_device::port_03c0_r(offset); + break; + } + + return res; +} + +void s3_vga_device::port_03c0_w(offs_t offset, uint8_t data) +{ + switch(offset) + { + case 5: + s3_seq_reg_write(vga.sequencer.index,data); + break; + default: + vga_device::port_03c0_w(offset,data); + break; + } +} + +uint8_t s3_vga_device::port_03d0_r(offs_t offset) +{ + uint8_t res = 0xff; + + if (get_crtc_port() == 0x3d0) + { + switch(offset) + { + case 5: + res = s3_vga_device::crtc_reg_read(vga.crtc.index); + break; + default: + res = vga_device::port_03d0_r(offset); + break; + } + } + + return res; +} + +void s3_vga_device::port_03d0_w(offs_t offset, uint8_t data) +{ + if (get_crtc_port() == 0x3d0) + { + switch(offset) + { + case 5: + vga.crtc.data[vga.crtc.index] = data; + crtc_reg_write(vga.crtc.index,data); + break; + default: + vga_device::port_03d0_w(offset,data); + break; + } + } +} + +uint8_t s3_vga_device::mem_r(offs_t offset) +{ + 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++) + { + 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))]; + } + } + } + return data; + } + if((offset + (svga.bank_r*0x10000)) < vga.svga_intf.vram_size) + return vga_device::mem_r(offset); + else + return 0xff; +} + +void s3_vga_device::mem_w(offs_t offset, uint8_t data) +{ + 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) + { + // 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; + } + switch(offset) + { + 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(s3.mmio_9ae8); + 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(s3.mmio_bee8); + 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(s3.mmio_96e8); + break; + case 0xe2e8: + dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xffffff00) | data; + dev->ibm8514_wait_draw(); + break; + default: + LOG( "S3: MMIO offset %05x write %02x\n",offset+0xa0000,data); + break; + } + 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) + { + if((offset + (svga.bank_w*0x10000)) < vga.svga_intf.vram_size) + vga.memory[(offset + (svga.bank_w*0x10000))] = data; + } + else + { + 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; + } + + if((offset + (svga.bank_w*0x10000)) < vga.svga_intf.vram_size) + vga_device::mem_w(offset,data); +} + + +uint32_t s3_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + svga_device::screen_update(screen, bitmap, cliprect); + + uint8_t cur_mode = pc_vga_choosevideomode(); + + // draw hardware graphics cursor + // TODO: support 16 bit and greater video modes + // TODO: should be a derived function from svga_device + if(s3.cursor_mode & 0x01) // if cursor is enabled + { + uint16_t cx = s3.cursor_x & 0x07ff; + uint16_t cy = s3.cursor_y & 0x07ff; + + 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 + + uint32_t src = s3.cursor_start_addr * 1024; // start address is in units of 1024 bytes + + uint32_t bg_col; + uint32_t fg_col; + int r,g,b; + uint32_t datax; + switch(cur_mode) + { + case RGB15_MODE: + case RGB16_MODE: + 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); + break; + case RGB24_MODE: + datax = s3.cursor_bg[0]|s3.cursor_bg[1]<<8|s3.cursor_bg[2]<<16; + r = (datax&0xff0000)>>16; + g = (datax&0x00ff00)>>8; + b = (datax&0x0000ff)>>0; + bg_col = (0xff<<24)|(r<<16)|(g<<8)|(b<<0); + + datax = s3.cursor_fg[0]|s3.cursor_fg[1]<<8|s3.cursor_fg[2]<<16; + r = (datax&0xff0000)>>16; + g = (datax&0x00ff00)>>8; + b = (datax&0x0000ff)>>0; + fg_col = (0xff<<24)|(r<<16)|(g<<8)|(b<<0); + break; + case RGB8_MODE: + default: + bg_col = pen(s3.cursor_bg[0]); + fg_col = pen(s3.cursor_fg[0]); + break; + } + + //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(int y=0;y<64;y++) + { + if(cy + y < cliprect.max_y && cx < cliprect.max_x) + { + uint32_t *const dst = &bitmap.pix(cy + y, cx); + for(int 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)); + uint8_t 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; +} diff --git a/src/devices/video/pc_vga_s3.h b/src/devices/video/pc_vga_s3.h new file mode 100644 index 00000000000..1811e5bb703 --- /dev/null +++ b/src/devices/video/pc_vga_s3.h @@ -0,0 +1,105 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald + +#ifndef MAME_VIDEO_PC_VGA_S3_H +#define MAME_VIDEO_PC_VGA_S3_H + +#pragma once + +#include "screen.h" +#include "video/pc_vga.h" + +class s3_vga_device : public svga_device +{ +public: + // construction/destruction + s3_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual uint8_t port_03b0_r(offs_t offset) override; + virtual void port_03b0_w(offs_t offset, uint8_t data) override; + virtual uint8_t port_03c0_r(offs_t offset) override; + virtual void port_03c0_w(offs_t offset, uint8_t data) override; + virtual uint8_t port_03d0_r(offs_t offset) override; + virtual void port_03d0_w(offs_t offset, uint8_t data) override; + virtual uint8_t mem_r(offs_t offset) override; + virtual void mem_w(offs_t offset, uint8_t data) override; + + virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override; + + virtual TIMER_CALLBACK_MEMBER(vblank_timer_cb) override; + + ibm8514a_device* get_8514() { return m_8514; } + +protected: + s3_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + struct + { + uint8_t memory_config; + uint8_t ext_misc_ctrl_2; + uint8_t crt_reg_lock; + uint8_t reg_lock1; + uint8_t reg_lock2; + uint8_t enable_8514; + uint8_t enable_s3d; + uint8_t cr3a; + uint8_t cr42; + uint8_t cr43; + uint8_t cr51; + uint8_t cr53; + uint8_t id_high; + uint8_t id_low; + uint8_t revision; + uint8_t id_cr30; + uint32_t strapping; // power-on strapping bits + uint8_t sr10; // MCLK PLL + uint8_t sr11; // MCLK PLL + uint8_t sr12; // DCLK PLL + uint8_t sr13; // DCLK PLL + uint8_t sr15; // CLKSYN control 2 + uint8_t sr17; // CLKSYN test + uint8_t clk_pll_r; // individual DCLK PLL values + uint8_t clk_pll_m; + uint8_t clk_pll_n; + + // data for memory-mapped I/O + uint16_t mmio_9ae8; + uint16_t mmio_bee8; + uint16_t mmio_96e8; + + // hardware graphics cursor + uint8_t cursor_mode; + uint16_t cursor_x; + uint16_t cursor_y; + uint16_t cursor_start_addr; + uint8_t cursor_pattern_x; // cursor pattern origin + uint8_t cursor_pattern_y; + uint8_t cursor_fg[4]; + uint8_t cursor_bg[4]; + uint8_t cursor_fg_ptr; + uint8_t cursor_bg_ptr; + uint8_t extended_dac_ctrl; + } s3; + virtual uint16_t offset() override; + +protected: + uint8_t crtc_reg_read(uint8_t index) override; + void crtc_reg_write(uint8_t index, uint8_t data) override; + +private: + + void s3_define_video_mode(void); + uint8_t s3_seq_reg_read(uint8_t index); + void s3_seq_reg_write(uint8_t index, uint8_t data); + ibm8514a_device* m_8514; +}; + +// device type definition +DECLARE_DEVICE_TYPE(S3_VGA, s3_vga_device) + +#endif // MAME_VIDEO_PC_VGA_S3_H diff --git a/src/devices/video/pc_vga_trident.cpp b/src/devices/video/pc_vga_trident.cpp new file mode 100644 index 00000000000..53d34ea571d --- /dev/null +++ b/src/devices/video/pc_vga_trident.cpp @@ -0,0 +1,1719 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald +/* + * trident.cpp + * + * Implementation of Trident VGA GUI accelerators + * + * TODO: + * - TVGA8200LX (just bog standard VGA?) + * - TVGA8800 early SVGA + * - TVGA8900 (2MB VRAM) + * - TVGA9000 needs to be downgraded from '9680 + * \- none of the SVGA modes works + * \- subclassed from TGUI9680 just for pntnpuzl, consider swapping inheritance or even decouple; + * \- it's also really a downgraded version of '8900 + * - TVGA92xx, TVGA938x (2d accelerator) + * - TVGA94xx (PCI version of above) + * - TGUI9680 is a PCI SVGA + * \- several missing features (namely YUV-to-RGB conversions) + * - ProVidia 968x ('9680 + TV video out & AD724 for NTSC/PAL conversion) + * - AGP cards (3DImage, Blade3D, XP series) + * + */ + +#include "emu.h" +#include "pc_vga_trident.h" + +#include "screen.h" + +#define LOG_WARN (1U << 1) +#define LOG_TODO (1U << 2) +#define LOG_ACCEL (1U << 3) +#define LOG_CRTC (1U << 4) + +#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_ACCEL | LOG_TODO | LOG_CRTC) + +#include "logmacro.h" + +#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) +#define LOGACCEL(...) LOGMASKED(LOG_ACCEL, __VA_ARGS__) +#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__) +#define LOGCRTC(...) LOGMASKED(LOG_CRTC, __VA_ARGS__) + +DEFINE_DEVICE_TYPE(TRIDENT_VGA, tgui9860_device, "trident_vga", "Trident TGUI9860") +DEFINE_DEVICE_TYPE(TVGA9000_VGA, tvga9000_device, "tvga9000_vga", "Trident TVGA9000") + +trident_vga_device::trident_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) +{ +} + +tgui9860_device::tgui9860_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : trident_vga_device(mconfig, TRIDENT_VGA, tag, owner, clock) +{ + m_version = 0xd3; // 0xd3 identifies at TGUI9660XGi (set to 0xe3 to identify at TGUI9440AGi) +} + +tvga9000_device::tvga9000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : trident_vga_device(mconfig, TVGA9000_VGA, tag, owner, clock) +{ + m_version = 0x43; +} + +uint8_t trident_vga_device::READPIXEL8(int16_t x, int16_t y) +{ + return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)) % vga.svga_intf.vram_size]); +} + +uint16_t trident_vga_device::READPIXEL15(int16_t x, int16_t y) +{ + return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*2) % vga.svga_intf.vram_size] | + (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*2)+1) % vga.svga_intf.vram_size] << 8)); +} + +uint16_t trident_vga_device::READPIXEL16(int16_t x, int16_t y) +{ + return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*2) % vga.svga_intf.vram_size] | + (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*2)+1) % vga.svga_intf.vram_size] << 8)); +} + +uint32_t trident_vga_device::READPIXEL32(int16_t x, int16_t y) +{ + return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*4) % vga.svga_intf.vram_size] | + (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+1) % vga.svga_intf.vram_size] << 8) | + (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+2) % vga.svga_intf.vram_size] << 16) | + (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+3) % vga.svga_intf.vram_size] << 24)); +} + +void trident_vga_device::WRITEPIXEL8(int16_t x, int16_t y, uint8_t data) +{ + if((x & 0xfff)> 8; + } +} + +void trident_vga_device::WRITEPIXEL16(int16_t x, int16_t y, uint16_t data) +{ + if((x & 0xfff)> 8; + } +} + +void trident_vga_device::WRITEPIXEL32(int16_t x, int16_t y, uint32_t data) +{ + if((x & 0xfff)> 8; + vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+2) % vga.svga_intf.vram_size] = (data & 0x00ff0000) >> 16; + vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+3) % vga.svga_intf.vram_size] = (data & 0xff000000) >> 24; + } +} + +uint32_t trident_vga_device::handle_rop(uint32_t src, uint32_t dst) +{ + switch(tri.accel_fmix) // TODO: better understand this register + { + case 0xf0: // PAT + case 0xcc: // SRC + break; // pass data through + case 0x00: // 0 + src = 0; + break; + case 0xff: // 1 + src = 0xffffffff; + break; + case 0x66: // XOR + case 0x5a: // XOR PAT + src = dst ^ src; + break; + case 0xb8: // PAT xor (SRC and (DST xor PAT)) (correct?) + src = src & (dst ^ src); + break; + } + return src; +} + +uint32_t trident_vga_device::READPIXEL(int16_t x,int16_t y) +{ + if(svga.rgb8_en) + return READPIXEL8(x,y) & 0xff; + if(svga.rgb15_en) + return READPIXEL15(x,y) & 0x7fff; + if(svga.rgb16_en) + return READPIXEL16(x,y) & 0xffff; + if(svga.rgb32_en) + return READPIXEL32(x,y); + return 0; // should never reach here +} + +void trident_vga_device::WRITEPIXEL(int16_t x,int16_t y, uint32_t data) +{ + if(svga.rgb8_en) + WRITEPIXEL8(x,y,(((data >> 8) & 0xff) | (data & 0xff))); // XFree86 3.3 sets bits 0-7 to 0 when using mono patterns, does it OR each byte? + if(svga.rgb15_en) + WRITEPIXEL15(x,y,data & 0x7fff); + if(svga.rgb16_en) + WRITEPIXEL16(x,y,data & 0xffff); + if(svga.rgb32_en) + WRITEPIXEL32(x,y,data); +} + + +void trident_vga_device::device_start() +{ + zero(); + + 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.memory = std::make_unique(vga.svga_intf.vram_size); + memset(&vga.memory[0], 0, vga.svga_intf.vram_size); + + save_pointer(NAME(vga.memory), vga.svga_intf.vram_size); + save_pointer(vga.crtc.data,"CRTC Registers",0x100); + save_pointer(vga.sequencer.data,"Sequencer Registers",0x100); + save_pointer(vga.attribute.data,"Attribute Registers", 0x15); + save_pointer(tri.accel_pattern,"Pattern Data", 0x80); + save_pointer(tri.lutdac_reg,"LUTDAC registers", 0x100); + + m_vblank_timer = timer_alloc(FUNC(vga_device::vblank_timer_cb), this); + vga.svga_intf.seq_regcount = 0x0f; + vga.svga_intf.crtc_regcount = 0x60; + svga.ignore_chain4 = true; + memset(&tri, 0, sizeof(tri)); +} + +void trident_vga_device::device_reset() +{ + svga_device::device_reset(); + svga.id = m_version; + tri.revision = 0x01; // revision identifies as TGUI9680 + tri.new_mode = false; // start up in old mode + tri.dac_active = false; + tri.linear_active = false; + tri.mmio_active = false; + tri.sr0f = 0x6f; + tri.sr0c = 0x70; + tri.cr2a = 0x03; // set ISA interface? + tri.mem_clock = 0x2c6; // 50MHz default + tri.vid_clock = 0; + tri.port_3c3 = true; + tri.accel_busy = false; + tri.accel_memwrite_active = false; + // Windows 3.1 TGUI9440AGi drivers do not set the pointer colour registers? + tri.cursor_bg = 0x00000000; + tri.cursor_fg = 0xffffffff; + tri.pixel_depth = 0x10; //disable 8bpp mode by default +} + +uint32_t trident_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + svga_device::screen_update(screen,bitmap,cliprect); + uint8_t const cur_mode = pc_vga_choosevideomode(); + + // draw hardware graphics cursor + if(tri.cursor_ctrl & 0x80) // if cursor is enabled + { + uint16_t const cx = tri.cursor_x & 0x0fff; + uint16_t const cy = tri.cursor_y & 0x0fff; + uint8_t const cursor_size = (tri.cursor_ctrl & 0x01) ? 64 : 32; + + 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 + + uint32_t src = tri.cursor_loc * 1024; // start address is in units of 1024 bytes + + uint32_t bg_col, fg_col; + if(cur_mode == RGB16_MODE) + { + bg_col = tri.cursor_bg; + fg_col = tri.cursor_fg; + } + else /* TODO: other modes */ + { + bg_col = pen(tri.cursor_bg & 0xff); + fg_col = pen(tri.cursor_fg & 0xff); + } + + for(int y=0;y> 7; + k = (tri.vid_clock & 0x1000) >> 12; + freq = ((double)(m+8) / (double)((n+2)*(pow(2.0,k)))) * 14.31818; // there is a 14.31818MHz clock on the board + + return freq * 1000000; +} + +void trident_vga_device::trident_define_video_mode() +{ + int divisor = 1; + int xtal; + + /* // clock select for TGUI9440CXi and earlier + switch(tri.clock) + { + case 0: + default: xtal = 25174800; break; + case 1: xtal = 28636363; break; + case 2: xtal = 44900000; break; + case 3: xtal = 36000000; break; + case 4: xtal = 57272000; break; + case 5: xtal = 65000000; break; + case 6: xtal = 50350000; break; + case 7: xtal = 40000000; break; + case 8: xtal = 88000000; break; + case 9: xtal = 98000000; break; + case 10: xtal = 118800000; break; + case 11: xtal = 108000000; break; + case 12: xtal = 72000000; break; + case 13: xtal = 77000000; break; + case 14: xtal = 80000000; break; + case 15: xtal = 75000000; break; + } + + switch((tri.sr0d_new & 0x06) >> 1) + { + case 0: + default: break; // no division + case 1: xtal = xtal / 2; break; + case 2: xtal = xtal / 4; break; + case 3: xtal = xtal / 1.5; break; + }*/ + + + // TGUI9440AGi/9660/9680/9682 programmable clock + switch((vga.miscellaneous_output & 0x0c) >> 2) + { + case 0: + default: xtal = 25174800; break; + case 1: xtal = 28636363; break; + case 2: xtal = calculate_clock(); break; + } + + if(tri.gc0f & 0x08) // 16 pixels per character clock + xtal = xtal / 2; + + if(tri.port_3db & 0x20) + xtal = xtal / 2; // correct? + + svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb32_en = 0; + switch((tri.pixel_depth & 0x0c) >> 2) + { + case 0: + default: if(!(tri.pixel_depth & 0x10) || (tri.cr1e & 0x80)) svga.rgb8_en = 1; break; + case 1: if((tri.dac & 0xf0) == 0x30) svga.rgb16_en = 1; else svga.rgb15_en = 1; break; + case 2: svga.rgb32_en = 1; break; + } + + if((tri.cr1e & 0x80) && (svga.id == 0x43)) + divisor = 2; + + recompute_params_clock(divisor, xtal); +} + +uint8_t trident_vga_device::trident_seq_reg_read(uint8_t index) +{ + uint8_t res; + + res = 0xff; + + if(index <= 0x04) + res = vga.sequencer.data[index]; + else + { + switch(index) + { + case 0x09: + res = tri.revision; + break; + case 0x0b: + res = svga.id; + tri.new_mode = true; + break; + case 0x0c: // Power Up Mode register 1 + res = tri.sr0c & 0xef; + if(tri.port_3c3) + res |= 0x10; + break; + case 0x0d: // Mode Control 2 + //res = svga.rgb15_en; + if(tri.new_mode) + res = tri.sr0d_new; + else + res = tri.sr0d_old; + break; + case 0x0e: // Mode Control 1 + if(tri.new_mode) + res = tri.sr0e_new; + else + res = tri.sr0e_old; + break; + case 0x0f: // Power Up Mode 2 + res = tri.sr0f; + break; + default: + res = vga.sequencer.data[index]; + LOGWARN("Trident: Sequencer index %02x read\n",index); + } + } + LOG("Trident SR%02X: read %02x\n",index,res); + return res; +} + +void trident_vga_device::trident_seq_reg_write(uint8_t index, uint8_t data) +{ + vga.sequencer.data[vga.sequencer.index] = data; + if(index <= 0x04) + { + seq_reg_write(vga.sequencer.index,data); + recompute_params(); + } + else + { + switch(index) + { + case 0x0b: + tri.new_mode = false; + break; + case 0x0c: // Power Up Mode register 1 + if(data & 0x10) + tri.port_3c3 = true; // 'post port at 0x3c3' + else + tri.port_3c3 = false; // 'post port at 0x46e8' + tri.sr0c = data; + break; + case 0x0d: // Mode Control 2 + if(tri.new_mode) + { + tri.sr0d_new = data; + tri.clock = ((vga.miscellaneous_output & 0x0c) >> 2) | ((data & 0x01) << 2) | ((data & 0x40) >> 3); + trident_define_video_mode(); + } + else + tri.sr0d_old = data; + break; + case 0x0e: // Mode Control 1 + if(tri.new_mode) + { + tri.sr0e_new = data ^ 0x02; + svga.bank_w = (data & 0x3f) ^ 0x02; // bit 1 is inverted, used for card detection, it is not XORed on reading + if(!(tri.gc0f & 0x01)) + svga.bank_r = (data & 0x3f) ^ 0x02; + // TODO: handle planar modes, where bits 0 and 2 only are used + } + else + { + tri.sr0e_old = data; + svga.bank_w = data & 0x0e; + if(!(tri.gc0f & 0x01)) + svga.bank_r = data & 0x0e; + } + break; + case 0x0f: // Power Up Mode 2 + tri.sr0f = data; + break; + default: + LOGWARN("Trident: Sequencer index %02x read\n",index); + } + } + LOG("Trident SR%02X: %s mode write %02x\n",index,tri.new_mode ? "new" : "old",data); +} + +uint8_t trident_vga_device::trident_crtc_reg_read(uint8_t index) +{ + uint8_t res = 0; + + if(index <= 0x18) + res = crtc_reg_read(index); + else + { + switch(index) + { + case 0x1e: + res = tri.cr1e; + break; + case 0x1f: + res = tri.cr1f; + break; + case 0x20: + res = tri.cr20; + break; + case 0x21: + res = tri.cr21; + break; + case 0x24: + if(vga.attribute.state != 0) + res |= 0x80; + break; + case 0x26: + res = vga.attribute.index; + break; + case 0x27: + res = (vga.crtc.start_addr & 0x60000) >> 17; + break; + case 0x29: + res = tri.cr29; + break; + case 0x2a: + res = tri.cr2a; + break; + case 0x38: + res = tri.pixel_depth; + break; + case 0x39: + res = tri.cr39; + break; + case 0x40: + res = (tri.cursor_x & 0x00ff); + break; + case 0x41: + res = (tri.cursor_x & 0xff00) >> 8; + break; + case 0x42: + res = (tri.cursor_y & 0x00ff); + break; + case 0x43: + res = (tri.cursor_y & 0xff00) >> 8; + break; + case 0x44: + res = (tri.cursor_loc & 0x00ff); + break; + case 0x45: + res = (tri.cursor_loc & 0xff00) >> 8; + break; + case 0x46: + res = tri.cursor_x_off; + break; + case 0x47: + res = tri.cursor_y_off; + break; + case 0x48: + res = (tri.cursor_fg & 0x000000ff); + break; + case 0x49: + res = (tri.cursor_fg & 0x0000ff00) >> 8; + break; + case 0x4a: + res = (tri.cursor_fg & 0x00ff0000) >> 16; + break; + case 0x4b: + res = (tri.cursor_fg & 0xff000000) >> 24; + break; + case 0x4c: + res = (tri.cursor_bg & 0x000000ff); + break; + case 0x4d: + res = (tri.cursor_bg & 0x0000ff00) >> 8; + break; + case 0x4e: + res = (tri.cursor_bg & 0x00ff0000) >> 16; + break; + case 0x4f: + res = (tri.cursor_bg & 0xff000000) >> 24; + break; + case 0x50: + res = tri.cursor_ctrl; + break; + default: + res = vga.crtc.data[index]; + LOGWARN("Trident: CRTC index %02x read\n",index); + break; + } + } + LOG("Trident CR%02X: read %02x\n",index,res); + return res; +} +void trident_vga_device::trident_crtc_reg_write(uint8_t index, uint8_t data) +{ + if(index <= 0x18) + { + crtc_reg_write(index,data); + trident_define_video_mode(); + } + else + { + switch(index) + { + case 0x1e: // Module Testing Register + tri.cr1e = data; + vga.crtc.start_addr = (vga.crtc.start_addr & 0xfffeffff) | ((data & 0x20)<<11); + trident_define_video_mode(); + break; + case 0x1f: + tri.cr1f = data; // "Software Programming Register" written to by the BIOS + break; + case 0x20: // FIFO Control (old MMIO enable? no documentation of this register) + tri.cr20 = data; + break; + case 0x21: // Linear aperture + tri.cr21 = data; + tri.linear_address = ((data & 0xc0)<<18) | ((data & 0x0f)<<20); + tri.linear_active = data & 0x20; + if(tri.linear_active) + popmessage("Trident: Linear Aperture active - %08x, %s",tri.linear_address,(tri.cr21 & 0x10) ? "2MB" : "1MB" ); + break; + case 0x27: + vga.crtc.start_addr = (vga.crtc.start_addr & 0xfff9ffff) | ((data & 0x03)<<17); + break; + case 0x29: + tri.cr29 = data; + vga.crtc.offset = (vga.crtc.offset & 0xfeff) | ((data & 0x10)<<4); + break; + case 0x2a: + tri.cr2a = data; + break; + case 0x38: + // bit 0: 16 bit bus + // bits 2-3: pixel depth (1=15/16bit, 2=24/32bit, 0=anything else) + // bit 5: packed mode + tri.pixel_depth = data; + trident_define_video_mode(); + break; + case 0x39: + tri.cr39 = data; + tri.mmio_active = data & 0x01; + if(tri.mmio_active) + popmessage("Trident: MMIO activated"); + break; + case 0x40: + tri.cursor_x = (tri.cursor_x & 0xff00) | data; + break; + case 0x41: + tri.cursor_x = (tri.cursor_x & 0x00ff) | (data << 8); + break; + case 0x42: + tri.cursor_y = (tri.cursor_y & 0xff00) | data; + break; + case 0x43: + tri.cursor_y = (tri.cursor_y & 0x00ff) | (data << 8); + break; + case 0x44: + tri.cursor_loc = (tri.cursor_loc & 0xff00) | data; + break; + case 0x45: + tri.cursor_loc = (tri.cursor_loc & 0x00ff) | (data << 8); + break; + case 0x46: + tri.cursor_x_off = data; + break; + case 0x47: + tri.cursor_y_off = data; + break; + case 0x48: + tri.cursor_fg = (tri.cursor_fg & 0xffffff00) | data; + break; + case 0x49: + tri.cursor_fg = (tri.cursor_fg & 0xffff00ff) | (data << 8); + break; + case 0x4a: + tri.cursor_fg = (tri.cursor_fg & 0xff00ffff) | (data << 16); + break; + case 0x4b: + tri.cursor_fg = (tri.cursor_fg & 0x00ffffff) | (data << 24); + break; + case 0x4c: + tri.cursor_bg = (tri.cursor_bg & 0xffffff00) | data; + break; + case 0x4d: + tri.cursor_bg = (tri.cursor_bg & 0xffff00ff) | (data << 8); + break; + case 0x4e: + tri.cursor_bg = (tri.cursor_bg & 0xff00ffff) | (data << 16); + break; + case 0x4f: + tri.cursor_bg = (tri.cursor_bg & 0x00ffffff) | (data << 24); + break; + case 0x50: + tri.cursor_ctrl = data; + break; + default: + LOGWARN("Trident: 3D4 index %02x write %02x\n",index,data); + break; + } + } + LOG("Trident CR%02X: write %02x\n",index,data); +} + +uint8_t trident_vga_device::trident_gc_reg_read(uint8_t index) +{ + uint8_t res; + + if(index <= 0x0d) + res = gc_reg_read(index); + else + { + switch(index) + { + case 0x0e: + res = tri.gc0e; + break; + case 0x0f: + res = tri.gc0f; + break; + case 0x2f: + res = tri.gc2f; + break; + default: + res = 0xff; + LOGWARN("Trident: Sequencer index %02x read\n",index); + break; + } + } + LOG("Trident GC%02X: read %02x\n",index,res); + return res; +} + +void trident_vga_device::trident_gc_reg_write(uint8_t index, uint8_t data) +{ + if(index <= 0x0d) + gc_reg_write(index,data); + else + { + LOG("Trident GC%02X: write %02x\n",index,data); + switch(index) + { + case 0x0e: // New Source Address Register (bit 1 is inverted here, also) + tri.gc0e = data ^ 0x02; + if(!(tri.gc0f & 0x04)) // if bank regs at 0x3d8/9 are not enabled + { + if(tri.gc0f & 0x01) // if bank regs are separated + svga.bank_r = (data & 0x1f) ^ 0x02; + } + break; + case 0x0f: + tri.gc0f = data; + trident_define_video_mode(); + break; + case 0x2f: // XFree86 refers to this register as "MiscIntContReg", setting bit 2, but gives no indication as to what it does + tri.gc2f = data; + break; + default: + LOGWARN("Trident: Unimplemented GC register %02x write %02x\n",index,data); + break; + } + } + LOG("Trident GC%02X: write %02x\n",index,data); +} + +uint8_t trident_vga_device::port_03c0_r(offs_t offset) +{ + uint8_t res; + + switch(offset) + { + case 0x05: + res = trident_seq_reg_read(vga.sequencer.index); + break; + case 0x06: + tri.dac_count++; + if(tri.dac_count > 3) + tri.dac_active = true; + if(tri.dac_active) + res = tri.dac; + else + res = vga_device::port_03c0_r(offset); + break; + case 0x07: + case 0x08: + case 0x09: + tri.dac_active = false; + tri.dac_count = 0; + res = vga_device::port_03c0_r(offset); + break; + case 0x0f: + res = trident_gc_reg_read(vga.gc.index); + break; + default: + res = vga_device::port_03c0_r(offset); + break; + } + + return res; +} + +void trident_vga_device::port_03c0_w(offs_t offset, uint8_t data) +{ + switch(offset) + { + case 0x05: + trident_seq_reg_write(vga.sequencer.index,data); + break; + case 0x06: + if(tri.dac_active) + { + tri.dac = data; // DAC command register + tri.dac_active = false; + tri.dac_count = 0; + trident_define_video_mode(); + } + else + vga_device::port_03c0_w(offset,data); + break; + case 0x07: + case 0x08: + case 0x09: + tri.dac_active = false; + tri.dac_count = 0; + vga_device::port_03c0_w(offset,data); + break; + case 0x0f: + trident_gc_reg_write(vga.gc.index,data); + break; + default: + vga_device::port_03c0_w(offset,data); + break; + } +} + + +uint8_t trident_vga_device::port_03d0_r(offs_t offset) +{ + uint8_t res = 0xff; + + if (get_crtc_port() == 0x3d0) + { + switch(offset) + { + case 5: + res = trident_crtc_reg_read(vga.crtc.index); + break; + case 8: + if(tri.gc0f & 0x04) // if enabled + { + res = svga.bank_w & 0x3f; + } + else + res = 0xff; + break; + case 9: + if(tri.gc0f & 0x04) // if enabled + if(tri.gc0f & 0x01) // and if bank regs are separated + res = svga.bank_r & 0x3f; + else + res = 0xff; + else + res = 0xff; + break; + case 11: + res = tri.port_3db; + break; + default: + res = vga_device::port_03d0_r(offset); + break; + } + } + + return res; +} + +void trident_vga_device::port_03d0_w(offs_t offset, uint8_t data) +{ + if (get_crtc_port() == 0x3d0) + { + switch(offset) + { + case 5: + vga.crtc.data[vga.crtc.index] = data; + trident_crtc_reg_write(vga.crtc.index,data); + break; + case 8: + if(tri.gc0f & 0x04) // if enabled + { + svga.bank_w = data & 0x3f; + LOG("Trident: Write Bank set to %02x\n",data); + if(!(tri.gc0f & 0x01)) // if bank regs are not separated + { + svga.bank_r = data & 0x3f; // then this is also the read bank register + LOG("Trident: Read Bank set to %02x\n",data); + } + } + break; + case 9: + if(tri.gc0f & 0x04) // if enabled + { + if(tri.gc0f & 0x01) // and if bank regs are separated + { + svga.bank_r = data & 0x3f; + LOG("Trident: Read Bank set to %02x\n",data); + } + } + break; + case 11: + tri.port_3db = data; // no info on this port? Bit 5 appears to be a clock divider... + break; + default: + vga_device::port_03d0_w(offset,data); + break; + } + } +} + +uint8_t trident_vga_device::port_43c6_r(offs_t offset) +{ + uint8_t res = 0xff; + switch(offset) + { + case 2: + res = tri.mem_clock & 0xff; + break; + case 3: + res = tri.mem_clock >> 8; + break; + case 4: + res = tri.vid_clock & 0xff; + break; + case 5: + res = tri.vid_clock >> 8; + break; + } + return res; +} + +void trident_vga_device::port_43c6_w(offs_t offset, uint8_t data) +{ + switch(offset) + { + case 2: + if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80)) + { + tri.mem_clock = (tri.mem_clock & 0xff00) | (data); + LOG("Trident: Memory clock write %04x\n",tri.mem_clock); + } + break; + case 3: + if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80)) + { + tri.mem_clock = (tri.mem_clock & 0x00ff) | (data << 8); + LOG("Trident: Memory clock write %04x\n",tri.mem_clock); + } + break; + case 4: + if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80)) + { + tri.vid_clock = (tri.vid_clock & 0xff00) | (data); + LOG("Trident: Video clock write %04x\n",tri.vid_clock); + } + break; + case 5: + if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80)) + { + tri.vid_clock = (tri.vid_clock & 0x00ff) | (data << 8); + LOG("Trident: Video clock write %04x\n",tri.vid_clock); + } + break; + } +} + +// Trident refers to these registers as a LUTDAC +// Not much else is known. XFree86 uses register 4 for something related to DPMS +uint8_t trident_vga_device::port_83c6_r(offs_t offset) +{ + uint8_t res = 0xff; + switch(offset) + { + case 2: + res = tri.lutdac_reg[tri.lutdac_index]; + LOG("Trident: LUTDAC reg read %02x\n",res); + break; + case 4: + res = tri.lutdac_index; + LOG("Trident: LUTDAC index read %02x\n",res); + break; + } + return res; +} + +void trident_vga_device::port_83c6_w(offs_t offset, uint8_t data) +{ + switch(offset) + { + case 2: + LOG("Trident: LUTDAC reg write %02x\n",data); + tri.lutdac_reg[tri.lutdac_index] = data; + break; + case 4: + LOG("Trident: LUTDAC index write %02x\n",data); + tri.lutdac_index = data; + break; + } +} + +uint8_t trident_vga_device::vram_r(offs_t offset) +{ + if (tri.linear_active) + return vga.memory[offset % vga.svga_intf.vram_size]; + else + return 0xff; +} + +void trident_vga_device::vram_w(offs_t offset, uint8_t data) +{ + if (tri.linear_active) + { + if(tri.accel_memwrite_active) + { + tri.accel_transfer = (tri.accel_transfer & (~(0x000000ff << (24-(8*(offset % 4)))))) | (data << (24-(8 * (offset % 4)))); + if(offset % 4 == 3) + accel_data_write(tri.accel_transfer); + return; + } + vga.memory[offset % vga.svga_intf.vram_size] = data; + } +} + +uint8_t trident_vga_device::mem_r(offs_t offset) +{ + if((tri.cr20 & 0x10) && (offset >= 0x1ff00)) // correct for old MMIO? + { + return old_mmio_r(offset-0x1ff00); + } + + if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en) + { + int data; + + if(tri.new_mode) // 64k from 0xA0000-0xAFFFF + { + offset &= 0xffff; + data=vga.memory[(offset + (svga.bank_r*0x10000)) % vga.svga_intf.vram_size]; + } + else // 128k from 0xA0000-0xBFFFF + { + data=vga.memory[(offset + (svga.bank_r*0x10000)) % vga.svga_intf.vram_size]; + } + return data; + } + + return vga_device::mem_r(offset); +} + +void trident_vga_device::mem_w(offs_t offset, uint8_t data) +{ + if((tri.cr20 & 0x10) && (offset >= 0x1ff00)) // correct for old MMIO? + { + old_mmio_w(offset-0x1ff00,data); + return; + } + + if(tri.accel_memwrite_active) + { + tri.accel_transfer = (tri.accel_transfer & (~(0x000000ff << (24-(8*(offset % 4)))))) | (data << (24-(8 * (offset % 4)))); + if(offset % 4 == 3) + accel_data_write(tri.accel_transfer); + return; + } + + if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en) + { + if(tri.new_mode) // 64k from 0xA0000-0xAFFFF + { + offset &= 0xffff; + vga.memory[(offset + (svga.bank_w*0x10000)) % vga.svga_intf.vram_size] = data; + } + else // 128k from 0xA0000-0xBFFFF + { + vga.memory[(offset + (svga.bank_w*0x10000)) % vga.svga_intf.vram_size] = data; + } + return; + } + + vga_device::mem_w(offset,data); +} + +// Old style MMIO (maps to 0xbff00) +void trident_vga_device::old_mmio_w(offs_t offset, uint8_t data) +{ + if(offset >= 0x20) + accel_w(offset-0x20,data); +} + +uint8_t trident_vga_device::old_mmio_r(offs_t offset) +{ + if(offset == 0x20) + { + if(tri.accel_busy) + return 0x20; + } + if(offset > 0x20) + return accel_r(offset-0x20); + else + return 0x00; +} + + +// 2D Acceleration functions (very WIP) + +// From XFree86 source: +/* +Graphics Engine for 9440/9660/9680 + +#define GER_STATUS 0x2120 +#define GE_BUSY 0x80 +#define GER_OPERMODE 0x2122 Byte for 9440, Word for 96xx +#define DST_ENABLE 0x200 // Destination Transparency +#define GER_COMMAND 0x2124 +#define GE_NOP 0x00 // No Operation +#define GE_BLT 0x01 // BitBLT ROP3 only +#define GE_BLT_ROP4 0x02 // BitBLT ROP4 (96xx only) +#define GE_SCANLINE 0x03 // Scan Line +#define GE_BRESLINE 0x04 // Bresenham Line +#define GE_SHVECTOR 0x05 // Short Vector +#define GE_FASTLINE 0x06 // Fast Line (96xx only) +#define GE_TRAPEZ 0x07 // Trapezoidal fill (96xx only) +#define GE_ELLIPSE 0x08 // Ellipse (96xx only) (RES) +#define GE_ELLIP_FILL 0x09 // Ellipse Fill (96xx only) (RES) +#define GER_FMIX 0x2127 +#define GER_DRAWFLAG 0x2128 // long +#define FASTMODE 1<<28 +#define STENCIL 0x8000 +#define SOLIDFILL 0x4000 +#define TRANS_ENABLE 0x1000 +#define TRANS_REVERSE 0x2000 +#define YMAJ 0x0400 +#define XNEG 0x0200 +#define YNEG 0x0100 +#define SRCMONO 0x0040 +#define PATMONO 0x0020 +#define SCR2SCR 0x0004 +#define PAT2SCR 0x0002 +#define GER_FCOLOUR 0x212C // Word for 9440, long for 96xx +#define GER_BCOLOUR 0x2130 // Word for 9440, long for 96xx +#define GER_PATLOC 0x2134 // Word +#define GER_DEST_XY 0x2138 +#define GER_DEST_X 0x2138 // Word +#define GER_DEST_Y 0x213A // Word +#define GER_SRC_XY 0x213C +#define GER_SRC_X 0x213C // Word +#define GER_SRC_Y 0x213E // Word +#define GER_DIM_XY 0x2140 +#define GER_DIM_X 0x2140 // Word +#define GER_DIM_Y 0x2142 // Word +#define GER_STYLE 0x2144 // Long +#define GER_CKEY 0x2168 // Long +#define GER_FPATCOL 0x2178 +#define GER_BPATCOL 0x217C +#define GER_PATTERN 0x2180 // from 0x2180 to 0x21FF + + Additional - Graphics Engine for 96xx +#define GER_SRCCLIP_XY 0x2148 +#define GER_SRCCLIP_X 0x2148 // Word +#define GER_SRCCLIP_Y 0x214A // Word +#define GER_DSTCLIP_XY 0x214C +#define GER_DSTCLIP_X 0x214C // Word +#define GER_DSTCLIP_Y 0x214E // Word +*/ + +uint8_t trident_vga_device::accel_r(offs_t offset) +{ + uint8_t res = 0xff; + + if(offset >= 0x60) + return tri.accel_pattern[(offset-0x60) % 0x80]; + + switch(offset) + { + case 0x00: // Status + if(tri.accel_busy) + res = 0x80; + else + res = 0x00; + break; + // Operation mode: + // bit 8: disable clipping if set + case 0x02: // Operation Mode + res = tri.accel_opermode & 0x00ff; + break; + case 0x03: + res = (tri.accel_opermode & 0xff00) >> 8; + break; + case 0x04: // Command register + res = tri.accel_command; + break; + case 0x07: // Foreground Mix? + res = tri.accel_fmix; + break; + default: + LOGTODO("Trident: unimplemented acceleration register offset %02x read\n",offset); + } + return res; +} + +void trident_vga_device::accel_w(offs_t offset, uint8_t data) +{ + if(offset >= 0x60) + { + tri.accel_pattern[(offset-0x60) % 0x80] = data; + return; + } + + switch(offset) + { + case 0x02: // Operation Mode + tri.accel_opermode = (tri.accel_opermode & 0xff00) | data; + LOGACCEL("Trident: Operation Mode set to %04x\n",tri.accel_opermode); + break; + case 0x03: + tri.accel_opermode = (tri.accel_opermode & 0x00ff) | (data << 8); + LOGACCEL("Trident: Operation Mode set to %04x\n",tri.accel_opermode); + break; + case 0x04: // Command register + tri.accel_command = data; + accel_command(); + break; + case 0x07: // Foreground Mix? + tri.accel_fmix = data; + LOGACCEL("Trident: FMIX set to %02x\n",data); + break; + case 0x08: // Draw flags + tri.accel_drawflags = (tri.accel_drawflags & 0xffffff00) | data; + LOGACCEL("Trident: Draw flags set to %08x\n",tri.accel_drawflags); + break; + case 0x09: + tri.accel_drawflags = (tri.accel_drawflags & 0xffff00ff) | (data << 8); + LOGACCEL("Trident: Draw flags set to %08x\n",tri.accel_drawflags); + break; + case 0x0a: + tri.accel_drawflags = (tri.accel_drawflags & 0xff00ffff) | (data << 16); + LOGACCEL("Trident: Draw flags set to %08x\n",tri.accel_drawflags); + break; + case 0x0b: + tri.accel_drawflags = (tri.accel_drawflags & 0x00ffffff) | (data << 24); + LOGACCEL("Trident: Draw flags set to %08x\n",tri.accel_drawflags); + break; + case 0x0c: // Foreground Colour + tri.accel_fgcolour = (tri.accel_fgcolour & 0xffffff00) | data; + LOGACCEL("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour); + break; + case 0x0d: + tri.accel_fgcolour = (tri.accel_fgcolour & 0xffff00ff) | (data << 8); + LOGACCEL("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour); + break; + case 0x0e: + tri.accel_fgcolour = (tri.accel_fgcolour & 0xff00ffff) | (data << 16); + LOGACCEL("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour); + break; + case 0x0f: + tri.accel_fgcolour = (tri.accel_fgcolour & 0x00ffffff) | (data << 24); + LOGACCEL("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour); + break; + case 0x10: // Background Colour + tri.accel_bgcolour = (tri.accel_bgcolour & 0xffffff00) | data; + LOGACCEL("Trident: Background Colour set to %08x\n",tri.accel_bgcolour); + break; + case 0x11: + tri.accel_bgcolour = (tri.accel_bgcolour & 0xffff00ff) | (data << 8); + LOGACCEL("Trident: Background Colour set to %08x\n",tri.accel_bgcolour); + break; + case 0x12: + tri.accel_bgcolour = (tri.accel_bgcolour & 0xff00ffff) | (data << 16); + LOGACCEL("Trident: Background Colour set to %08x\n",tri.accel_bgcolour); + break; + case 0x13: + tri.accel_bgcolour = (tri.accel_bgcolour & 0x00ffffff) | (data << 24); + LOGACCEL("Trident: Background Colour set to %08x\n",tri.accel_bgcolour); + break; + case 0x14: // Pattern Location + tri.accel_pattern_loc = (tri.accel_pattern_loc & 0xff00) | data; + LOGACCEL("Trident: Pattern Location set to %04x\n",tri.accel_pattern_loc); + break; + case 0x15: + tri.accel_pattern_loc = (tri.accel_pattern_loc & 0x00ff) | (data << 8); + LOGACCEL("Trident: Pattern Location set to %04x\n",tri.accel_pattern_loc); + break; + case 0x18: // Destination X + tri.accel_dest_x = (tri.accel_dest_x & 0xff00) | data; + LOGACCEL("Trident: Destination X set to %04x\n",tri.accel_dest_x); + break; + case 0x19: + tri.accel_dest_x = (tri.accel_dest_x & 0x00ff) | (data << 8); + LOGACCEL("Trident: Destination X set to %04x\n",tri.accel_dest_x); + break; + case 0x1a: // Destination Y + tri.accel_dest_y = (tri.accel_dest_y & 0xff00) | data; + LOGACCEL("Trident: Destination Y set to %04x\n",tri.accel_dest_y); + break; + case 0x1b: + tri.accel_dest_y = (tri.accel_dest_y & 0x00ff) | (data << 8); + LOGACCEL("Trident: Destination Y set to %04x\n",tri.accel_dest_y); + break; + case 0x1c: // Source X + tri.accel_source_x = (tri.accel_source_x & 0xff00) | data; + LOGACCEL("Trident: Source X set to %04x\n",tri.accel_source_x); + break; + case 0x1d: + tri.accel_source_x = (tri.accel_source_x & 0x00ff) | (data << 8); + LOGACCEL("Trident: Source X set to %04x\n",tri.accel_source_x); + break; + case 0x1e: // Source Y + tri.accel_source_y = (tri.accel_source_y & 0xff00) | data; + LOGACCEL("Trident: Source Y set to %04x\n",tri.accel_source_y); + break; + case 0x1f: + tri.accel_source_y = (tri.accel_source_y & 0x00ff) | (data << 8); + LOGACCEL("Trident: Source Y set to %04x\n",tri.accel_source_y); + break; + case 0x20: // Dimension(?) X + tri.accel_dim_x = (tri.accel_dim_x & 0xff00) | data; + LOGACCEL("Trident: Dimension X set to %04x\n",tri.accel_dim_x); + break; + case 0x21: + tri.accel_dim_x = (tri.accel_dim_x & 0x00ff) | (data << 8); + LOGACCEL("Trident: Dimension X set to %04x\n",tri.accel_dim_x); + break; + case 0x22: // Dimension(?) Y + tri.accel_dim_y = (tri.accel_dim_y & 0xff00) | data; + LOGACCEL("Trident: Dimension y set to %04x\n",tri.accel_dim_y); + break; + case 0x23: + tri.accel_dim_y = (tri.accel_dim_y & 0x00ff) | (data << 8); + LOGACCEL("Trident: Dimension y set to %04x\n",tri.accel_dim_y); + break; + case 0x24: // Style + tri.accel_style = (tri.accel_style & 0xffffff00) | data; + LOGACCEL("Trident: Style set to %08x\n",tri.accel_style); + break; + case 0x25: + tri.accel_style = (tri.accel_style & 0xffff00ff) | (data << 8); + LOGACCEL("Trident: Style set to %08x\n",tri.accel_style); + break; + case 0x26: + tri.accel_style = (tri.accel_style & 0xff00ffff) | (data << 16); + LOGACCEL("Trident: Style set to %08x\n",tri.accel_style); + break; + case 0x27: + tri.accel_style = (tri.accel_style & 0x00ffffff) | (data << 24); + LOGACCEL("Trident: Style set to %08x\n",tri.accel_style); + break; + case 0x28: // Source Clip X + tri.accel_source_x_clip = (tri.accel_source_x_clip & 0xff00) | data; + LOGACCEL("Trident: Source X Clip set to %04x\n",tri.accel_source_x_clip); + break; + case 0x29: + tri.accel_source_x_clip = (tri.accel_source_x_clip & 0x00ff) | (data << 8); + LOGACCEL("Trident: Source X Clip set to %04x\n",tri.accel_source_x_clip); + break; + case 0x2a: // Source Clip Y + tri.accel_source_y_clip = (tri.accel_source_y_clip & 0xff00) | data; + LOGACCEL("Trident: Source Y Clip set to %04x\n",tri.accel_source_y_clip); + break; + case 0x2b: + tri.accel_source_y_clip = (tri.accel_source_y_clip & 0x00ff) | (data << 8); + LOGACCEL("Trident: Source Y Clip set to %04x\n",tri.accel_source_y_clip); + break; + case 0x2c: // Destination Clip X + tri.accel_dest_x_clip = (tri.accel_dest_x_clip & 0xff00) | data; + LOGACCEL("Trident: Destination X Clip set to %04x\n",tri.accel_dest_x_clip); + break; + case 0x2d: + tri.accel_dest_x_clip = (tri.accel_dest_x_clip & 0x00ff) | (data << 8); + LOGACCEL("Trident: Destination X Clip set to %04x\n",tri.accel_dest_x_clip); + break; + case 0x2e: // Destination Clip Y + tri.accel_dest_y_clip = (tri.accel_dest_y_clip & 0xff00) | data; + LOGACCEL("Trident: Destination Y Clip set to %04x\n",tri.accel_dest_y_clip); + break; + case 0x2f: + tri.accel_dest_y_clip = (tri.accel_dest_y_clip & 0x00ff) | (data << 8); + LOGACCEL("Trident: Destination Y Clip set to %04x\n",tri.accel_dest_y_clip); + break; + case 0x48: // CKEY (Chromakey?) + tri.accel_ckey = (tri.accel_ckey & 0xffffff00) | data; + LOGACCEL("Trident: CKey set to %08x\n",tri.accel_ckey); + break; + case 0x49: + tri.accel_ckey = (tri.accel_ckey & 0xffff00ff) | (data << 8); + LOGACCEL("Trident: CKey set to %08x\n",tri.accel_ckey); + break; + case 0x4a: + tri.accel_ckey = (tri.accel_ckey & 0xff00ffff) | (data << 16); + LOGACCEL("Trident: CKey set to %08x\n",tri.accel_ckey); + break; + case 0x4b: + tri.accel_ckey = (tri.accel_ckey & 0x00ffffff) | (data << 24); + LOGACCEL("Trident: CKey set to %08x\n",tri.accel_ckey); + break; + case 0x58: // Foreground Pattern Colour + tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0xffffff00) | data; + LOGACCEL("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour); + break; + case 0x59: + tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0xffff00ff) | (data << 8); + LOGACCEL("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour); + break; + case 0x5a: + tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0xff00ffff) | (data << 16); + LOGACCEL("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour); + break; + case 0x5b: + tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0x00ffffff) | (data << 24); + LOGACCEL("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour); + break; + case 0x5c: // Background Pattern Colour + tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0xffffff00) | data; + LOGACCEL("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour); + break; + case 0x5d: + tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0xffff00ff) | (data << 8); + LOGACCEL("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour); + break; + case 0x5e: + tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0xff00ffff) | (data << 16); + LOGACCEL("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour); + break; + case 0x5f: + tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0x00ffffff) | (data << 24); + LOGACCEL("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour); + break; + default: + LOGTODO("Trident: unimplemented acceleration register offset %02x write %02x\n",offset,data); + } +} + +void trident_vga_device::accel_command() +{ + switch(tri.accel_command) + { + case 0x00: + LOG("Trident: Command: NOP\n"); + break; + case 0x01: + LOG("Trident: Command: BitBLT ROP3 (Source %i,%i Dest %i,%i Size %i,%i)\n",tri.accel_source_x,tri.accel_source_y,tri.accel_dest_x,tri.accel_dest_y,tri.accel_dim_x,tri.accel_dim_y); + LOG("BitBLT: Drawflags = %08x FMIX = %02x\n",tri.accel_drawflags,tri.accel_fmix); + accel_bitblt(); + break; + case 0x02: + LOG("Trident: Command: BitBLT ROP4\n"); + break; + case 0x03: + LOG("Trident: Command: Scanline\n"); + break; + case 0x04: + LOG("Trident: Command: Bresenham Line (Source %i,%i Dest %i,%i Size %i,%i)\n",tri.accel_source_x,tri.accel_source_y,tri.accel_dest_x,tri.accel_dest_y,tri.accel_dim_x,tri.accel_dim_y); + LOG("BLine: Drawflags = %08x FMIX = %02x\n",tri.accel_drawflags,tri.accel_fmix); + accel_line(); + break; + case 0x05: + LOG("Trident: Command: Short Vector\n"); + break; + case 0x06: + LOG("Trident: Command: Fast Line\n"); + break; + case 0x07: + LOG("Trident: Command: Trapezoid Fill\n"); + break; + case 0x08: + LOG("Trident: Command: Ellipse\n"); + break; + case 0x09: + LOG("Trident: Command: Ellipse Fill\n"); + break; + default: + LOGTODO("Trident: Unknown acceleration command %02x\n",tri.accel_command); + } +} + +void trident_vga_device::accel_bitblt() +{ + int x,y; + int sx,sy; + int xdir,ydir; + int xstart,xend,ystart,yend; + + if(tri.accel_drawflags & 0x0040) // TODO: handle PATMONO also + { + tri.accel_mem_x = tri.accel_dest_x; + tri.accel_mem_y = tri.accel_dest_y; + tri.accel_memwrite_active = true; + return; + } + + if(tri.accel_drawflags & 0x0200) + { + xdir = -1; + xstart = tri.accel_dest_x; + xend = tri.accel_dest_x-tri.accel_dim_x-1; + } + else + { + xdir = 1; + xstart = tri.accel_dest_x; + xend = tri.accel_dest_x+tri.accel_dim_x+1; + } + if(tri.accel_drawflags & 0x0100) + { + ydir = -1; + ystart = tri.accel_dest_y; + yend = tri.accel_dest_y-tri.accel_dim_y-1; + } + else + { + ydir = 1; + ystart = tri.accel_dest_y; + yend = tri.accel_dest_y+tri.accel_dim_y+1; + } + sy = tri.accel_source_y; + + for(y=ystart;y!=yend;y+=ydir,sy+=ydir) + { + sx = tri.accel_source_x; + for(x=xstart;x!=xend;x+=xdir,sx+=xdir) + { + if(tri.accel_drawflags & 0x4000) // Solid fill + { + WRITEPIXEL(x,y,tri.accel_fgcolour); + } + else + { + WRITEPIXEL(x,y,READPIXEL(sx,sy)); + } + } + } +} + +void trident_vga_device::accel_line() +{ + uint32_t col = tri.accel_fgcolour; +// TGUI_SRC_XY(dmin-dmaj,dmin); +// TGUI_DEST_XY(x,y); +// TGUI_DIM_XY(dmin+e,len); + int16_t dx = tri.accel_source_y - tri.accel_source_x; + int16_t dy = tri.accel_source_y; + int16_t err = tri.accel_dim_x + tri.accel_source_y; + int sx = (tri.accel_drawflags & 0x0200) ? -1 : 1; + int sy = (tri.accel_drawflags & 0x0100) ? -1 : 1; + int x,y,z; + + x = tri.accel_dest_x; + y = tri.accel_dest_y; + + WRITEPIXEL(x,y,col); + for(z=0;z 0) + { + if(tri.accel_drawflags & 0x0400) + x += sx; + else + y += sy; + WRITEPIXEL(x,y,col); + err += (dy-dx); + } + else + { + WRITEPIXEL(x,y,col); + err += dy; + } + } +} + +// feed data written to VRAM to an active BitBLT command +void trident_vga_device::accel_data_write(uint32_t data) +{ + int xdir = 1,ydir = 1; + + if(tri.accel_drawflags & 0x0200) // XNEG + xdir = -1; + if(tri.accel_drawflags & 0x0100) // YNEG + ydir = -1; + + for(int x=31;x>=0;x--) + { + if(tri.accel_mem_x <= tri.accel_dest_x+tri.accel_dim_x && tri.accel_mem_x >= tri.accel_dest_x-tri.accel_dim_x) + { + if(((data >> x) & 0x01) != 0) + WRITEPIXEL(tri.accel_mem_x,tri.accel_mem_y,tri.accel_fgcolour); + else + WRITEPIXEL(tri.accel_mem_x,tri.accel_mem_y,tri.accel_bgcolour); + } + tri.accel_mem_x+=xdir; + } + if(tri.accel_mem_x > tri.accel_dest_x+tri.accel_dim_x || tri.accel_mem_x < tri.accel_dest_x-tri.accel_dim_x) + { + tri.accel_mem_x = tri.accel_dest_x; + tri.accel_mem_y+=ydir; + if(tri.accel_mem_y > tri.accel_dest_y+tri.accel_dim_y || tri.accel_mem_y < tri.accel_dest_y-tri.accel_dim_y) + tri.accel_memwrite_active = false; // completed + } +} + +// tvga9000 CRTC override +// not extensively tested, just enough for pntnpuzl to not throw a 168 Hz refresh rate. +void tvga9000_device::trident_define_video_mode() +{ + int divisor = 1; + int xtal; + + u8 xtal_select = (vga.miscellaneous_output & 0x0c) >> 2; + xtal_select |= (tri.sr0d_new & 0x01) << 2; + xtal_select |= (tri.sr0d_new & 0x40) >> 3; + + switch(xtal_select) + { + case 0: xtal = 25174800; break; + case 1: xtal = 28636363; break; + case 2: xtal = 44900000; break; + case 3: xtal = 36000000; break; + case 4: xtal = 57272000; break; + case 5: xtal = 65000000; break; + case 6: xtal = 50350000; break; + case 7: xtal = 40000000; break; + case 8: xtal = 25174800; break; + case 9: xtal = 28636363; break; + case 10: xtal = 62300000; break; + case 11: xtal = 44900000; break; + case 12: xtal = 72000000; break; + case 13: xtal = 77000000; break; + case 14: xtal = 80000000; break; + case 15: xtal = 75000000; break; + } + + LOGCRTC("trident_define_video_mode: %d (%d)\n", xtal_select, xtal); + + switch((tri.sr0d_new & 0x06) >> 1) + { + case 0: break; // no division + case 1: xtal /= 2; break; + case 2: xtal /= 4; break; + case 3: xtal /= 1.5; break; + } + + if(tri.gc0f & 0x08) // 16 pixels per character clock + xtal = xtal / 2; + + if(tri.port_3db & 0x20) + xtal = xtal / 2; // correct? + + LOGCRTC("division setting %d %02x %02x (new xtal %d)\n", (tri.sr0d_new & 0x06) >> 1, tri.gc0f, tri.port_3db, xtal); + + svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb32_en = 0; + switch((tri.pixel_depth & 0x0c) >> 2) + { + case 0: + default: if(!(tri.pixel_depth & 0x10) || (tri.cr1e & 0x80)) svga.rgb8_en = 1; break; + case 1: if((tri.dac & 0xf0) == 0x30) svga.rgb16_en = 1; else svga.rgb15_en = 1; break; + case 2: svga.rgb32_en = 1; break; + } + + // TODO: is this right? + // documentation claims to be "host address bit 16" + // pntnpuzl definitely needs to halve divisor and xtal otherwise it will draw in 800 x 240. + if(BIT(tri.cr1e, 7)) + { + divisor = 2; + xtal /= 2; + } + // TODO: tri.cr1e bit 2 for interlace + + LOGCRTC("pixel depth %02x module testing %02x\n", tri.pixel_depth, tri.cr1e); + + recompute_params_clock(divisor, xtal); +} diff --git a/src/devices/video/pc_vga_trident.h b/src/devices/video/pc_vga_trident.h new file mode 100644 index 00000000000..c0c72b0b939 --- /dev/null +++ b/src/devices/video/pc_vga_trident.h @@ -0,0 +1,172 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald +/* + * trident.h + * + */ + +#ifndef MAME_VIDEO_PC_VGA_TRIDENT_H +#define MAME_VIDEO_PC_VGA_TRIDENT_H + +#pragma once + +#include "video/pc_vga.h" + +// ======================> trident_vga_device + +class trident_vga_device : public svga_device +{ +public: + virtual uint8_t port_03c0_r(offs_t offset) override; + virtual void port_03c0_w(offs_t offset, uint8_t data) override; + virtual uint8_t port_03d0_r(offs_t offset) override; + virtual void port_03d0_w(offs_t offset, uint8_t data) override; + uint8_t port_83c6_r(offs_t offset); + void port_83c6_w(offs_t offset, uint8_t data); + uint8_t port_43c6_r(offs_t offset); + void port_43c6_w(offs_t offset, uint8_t data); + uint8_t vram_r(offs_t offset); + void vram_w(offs_t offset, uint8_t data); + virtual uint8_t mem_r(offs_t offset) override; + virtual void mem_w(offs_t offset, uint8_t data) override; + virtual uint16_t offset() override; + + uint8_t accel_r(offs_t offset); + void accel_w(offs_t offset, uint8_t data); + + virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override; + +protected: + // construction/destruction + trident_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + + struct + { + uint8_t sr0c; + uint8_t sr0d_old; + uint8_t sr0d_new; + uint8_t sr0e_old; + uint8_t sr0e_new; + uint8_t sr0f; + uint8_t gc0e; + uint8_t gc0f; + uint8_t gc2f; + uint8_t cr1e; + uint8_t cr1f; + uint8_t cr20; + uint8_t cr21; + uint8_t cr29; + uint8_t cr2a; + uint8_t cr39; + uint8_t dac; + uint8_t lutdac_reg[0x100]; + uint8_t lutdac_index; + bool new_mode; + bool port_3c3; + uint8_t port_3db; + uint8_t clock; + uint8_t pixel_depth; + uint8_t revision; + bool dac_active; + uint8_t dac_count; + uint32_t linear_address; + bool linear_active; + bool mmio_active; + uint16_t mem_clock; // I/O 0x43c6 + uint16_t vid_clock; // I/O 0x43c8 + uint16_t cursor_x; + uint16_t cursor_y; + uint16_t cursor_loc; + uint8_t cursor_x_off; + uint8_t cursor_y_off; + uint32_t cursor_fg; // colour + uint32_t cursor_bg; // colour + uint8_t cursor_ctrl; + + // 2D acceleration + uint16_t accel_opermode; + uint8_t accel_command; + uint8_t accel_fmix; + uint32_t accel_drawflags; + uint32_t accel_fgcolour; + uint32_t accel_bgcolour; + uint16_t accel_pattern_loc; + int16_t accel_source_x; + int16_t accel_source_y; + int16_t accel_dest_x; + int16_t accel_dest_y; + int16_t accel_dim_x; + int16_t accel_dim_y; + uint32_t accel_style; + uint32_t accel_ckey; + int16_t accel_source_x_clip; + int16_t accel_source_y_clip; + int16_t accel_dest_x_clip; + int16_t accel_dest_y_clip; + uint32_t accel_fg_pattern_colour; + uint32_t accel_bg_pattern_colour; + uint8_t accel_pattern[0x80]; + bool accel_busy; + bool accel_memwrite_active; // true when writing to VRAM will push data to an ongoing command (SRCMONO/PATMONO) + int16_t accel_mem_x; + int16_t accel_mem_y; + uint32_t accel_transfer; + } tri; + uint8_t m_version; +private: + uint8_t trident_seq_reg_read(uint8_t index); + void trident_seq_reg_write(uint8_t index, uint8_t data); + virtual void trident_define_video_mode(); + uint8_t trident_crtc_reg_read(uint8_t index); + void trident_crtc_reg_write(uint8_t index, uint8_t data); + uint8_t trident_gc_reg_read(uint8_t index); + void trident_gc_reg_write(uint8_t index, uint8_t data); + + int calculate_clock(); + + // old style MMIO (0xBFF00) + void old_mmio_w(offs_t offset, uint8_t data); + uint8_t old_mmio_r(offs_t offset); + + // 2D acceleration + void accel_command(); + void accel_bitblt(); + void accel_line(); + void accel_data_write(uint32_t data); + uint8_t READPIXEL8(int16_t x, int16_t y); + uint16_t READPIXEL15(int16_t x, int16_t y); + uint16_t READPIXEL16(int16_t x, int16_t y); + uint32_t READPIXEL32(int16_t x, int16_t y); + void WRITEPIXEL8(int16_t x, int16_t y, uint8_t data); + void WRITEPIXEL15(int16_t x, int16_t y, uint16_t data); + void WRITEPIXEL16(int16_t x, int16_t y, uint16_t data); + void WRITEPIXEL32(int16_t x, int16_t y, uint32_t data); + uint32_t READPIXEL(int16_t x,int16_t y); + void WRITEPIXEL(int16_t x,int16_t y, uint32_t data); + uint32_t handle_rop(uint32_t src, uint32_t dst); +}; + +class tgui9860_device : public trident_vga_device +{ +public: + tgui9860_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +class tvga9000_device : public trident_vga_device +{ +public: + static constexpr feature_type imperfect_features() { return feature::GRAPHICS; } + + tvga9000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void trident_define_video_mode() override; +}; + +// device type definition +DECLARE_DEVICE_TYPE(TRIDENT_VGA, tgui9860_device) +DECLARE_DEVICE_TYPE(TVGA9000_VGA, tvga9000_device) + +#endif // MAME_VIDEO_PC_VGA_TRIDENT_H diff --git a/src/devices/video/pc_vga_tseng.cpp b/src/devices/video/pc_vga_tseng.cpp new file mode 100644 index 00000000000..4e5ff89a721 --- /dev/null +++ b/src/devices/video/pc_vga_tseng.cpp @@ -0,0 +1,427 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald +/* + * Tseng Labs VGA family + * + * TODO: + * - ET3000 (VGA only?) + * - ET4000AX + * \- No logging whatsoever; + * \- Unsupported True Color modes; + * - ET4000/W32 (2d accelerator) + * - ET4000/W32p (PCI version) + * + */ + +#include "emu.h" +#include "pc_vga_tseng.h" + +// TODO: refactor this macro +#define GRAPHIC_MODE (vga.gc.alpha_dis) /* else text mode */ + +DEFINE_DEVICE_TYPE(TSENG_VGA, tseng_vga_device, "tseng_vga", "Tseng Labs ET4000AX SVGA") + +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) +{ +} + +void tseng_vga_device::device_start() +{ + 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)); +} + +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; + } + } +} + +uint8_t tseng_vga_device::port_03b0_r(offs_t offset) +{ + uint8_t res = 0xff; + + if (get_crtc_port() == 0x3b0) + { + 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(offset); + break; + } + } + + return res; +} + +void tseng_vga_device::port_03b0_w(offs_t offset, uint8_t data) +{ + if (get_crtc_port() == 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(offset,data); + break; + } + } + tseng_define_video_mode(); +} + +void tseng_vga_device::tseng_attribute_reg_write(uint8_t index, uint8_t data) +{ + 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); + } + +} + +uint8_t tseng_vga_device::port_03c0_r(offs_t offset) +{ + uint8_t res; + + switch(offset) + { + 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(offset); + 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(offset); + break; + case 0x08: + et4k.dac_state = 0; + [[fallthrough]]; + default: + res = vga_device::port_03c0_r(offset); + break; + } + + return res; +} + +void tseng_vga_device::port_03c0_w(offs_t offset, uint8_t data) +{ + 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; + + 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; + } + [[fallthrough]]; + default: + vga_device::port_03c0_w(offset,data); + break; + } + tseng_define_video_mode(); +} + +uint8_t tseng_vga_device::port_03d0_r(offs_t offset) +{ + uint8_t res = 0xff; + + if (get_crtc_port() == 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(offset); + break; + } + } + + return res; +} + +void tseng_vga_device::port_03d0_w(offs_t offset, uint8_t data) +{ + if (get_crtc_port() == 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(offset,data); + break; + } + } + tseng_define_video_mode(); +} + +uint8_t tseng_vga_device::mem_r(offs_t offset) +{ + 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(offset); +} + +void tseng_vga_device::mem_w(offs_t offset, uint8_t data) +{ + 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(offset,data); +} diff --git a/src/devices/video/pc_vga_tseng.h b/src/devices/video/pc_vga_tseng.h new file mode 100644 index 00000000000..5354bfb82e2 --- /dev/null +++ b/src/devices/video/pc_vga_tseng.h @@ -0,0 +1,57 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald + +#ifndef MAME_VIDEO_PC_VGA_TSENG_H +#define MAME_VIDEO_PC_VGA_TSENG_H + +#pragma once + +#include "screen.h" +#include "video/pc_vga.h" + +class tseng_vga_device : public svga_device +{ +public: + static constexpr feature_type imperfect_features() { return feature::GRAPHICS; } + + // construction/destruction + tseng_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual uint8_t port_03b0_r(offs_t offset) override; + virtual void port_03b0_w(offs_t offset, uint8_t data) override; + virtual uint8_t port_03c0_r(offs_t offset) override; + virtual void port_03c0_w(offs_t offset, uint8_t data) override; + virtual uint8_t port_03d0_r(offs_t offset) override; + virtual void port_03d0_w(offs_t offset, uint8_t data) override; + virtual uint8_t mem_r(offs_t offset) override; + virtual void mem_w(offs_t offset, uint8_t data) override; + +protected: + virtual void device_start() override; + +private: + void tseng_define_video_mode(); + uint8_t tseng_crtc_reg_read(uint8_t index); + void tseng_crtc_reg_write(uint8_t index, uint8_t data); + uint8_t tseng_seq_reg_read(uint8_t index); + void tseng_seq_reg_write(uint8_t index, uint8_t data); + void tseng_attribute_reg_write(uint8_t index, uint8_t data); + + struct + { + uint8_t reg_3d8; + uint8_t dac_ctrl; + uint8_t dac_state; + uint8_t horz_overflow; + uint8_t aux_ctrl; + bool ext_reg_ena; + uint8_t misc1; + uint8_t misc2; + }et4k; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(TSENG_VGA, tseng_vga_device) + +#endif // MAME_VIDEO_PC_VGA_TSENG_H diff --git a/src/devices/video/pc_xga.cpp b/src/devices/video/pc_xga.cpp new file mode 100644 index 00000000000..bc474a81cfb --- /dev/null +++ b/src/devices/video/pc_xga.cpp @@ -0,0 +1,867 @@ +// license:BSD-3-Clause +// copyright-holders: Carl + +#include "emu.h" +#include "pc_xga.h" + + +#define VERBOSE (LOG_GENERAL) +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(XGA_COPRO, xga_copro_device, "xga_copro", "IBM XGA Coprocessor") +DEFINE_DEVICE_TYPE(OTI111, oak_oti111_vga_device, "oti111_vga", "Oak Technologies Spitfire 64111") + +xga_copro_device::xga_copro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, XGA_COPRO, tag, owner, clock) + , m_var(TYPE::XGA) + , m_mem_read_cb(*this) + , m_mem_write_cb(*this) +{ +} + +void xga_copro_device::start_command() +{ + switch((m_pelop >> 24) & 15) + { + case 11: + if(m_var == TYPE::OTI111) + { + LOG("oak specific textblt\n"); + break; + } + [[fallthrough]]; + case 12: + if(m_var == TYPE::OTI111) + { + LOG("oak specific fast pattern copy\n"); + break; + } + [[fallthrough]]; + default: + LOG("invalid pel op step func %d\n", (m_pelop >> 24) & 15); + break; + case 2: + LOG("draw and step read\n"); + break; + case 3: + LOG("line draw read\n"); + break; + case 4: + LOG("draw and step write\n"); + break; + case 5: + LOG("line draw write\n"); + break; + case 8: + do_pxblt(); + break; + case 9: + LOG("inverting pxblt\n"); + break; + case 10: + LOG("area fill pxblt\n"); + break; + } +} + +// Can maps be not byte aligned? XGA manual says they must be 32bit aligned in at least some cases. +u32 xga_copro_device::read_map_pixel(int x, int y, int map) +{ + offs_t addr = m_pelmap_base[map]; + int width = m_pelmap_width[map] + 1; + int height = m_pelmap_height[map] + 1; + int endian = m_pelmap_format[map] & 8; + int wbytes, bits; + u8 byte; + if((x > width) || (y > height) || (x < 0) || (y < 0)) + return 0; + switch(m_pelmap_format[map] & 7) + { + case 0: + wbytes = width / 8; + addr += y * wbytes; + addr += x / 8; + byte = m_mem_read_cb(addr); + bits = (x % 8) - (endian ? 8 : 0); + return (byte >> bits) & 1; + case 1: + wbytes = width / 4; + addr += y * wbytes; + addr += x / 4; + byte = m_mem_read_cb(addr); + bits = (x % 4) - (endian ? 4 : 0); + return (byte >> (bits * 2)) & 3; + case 2: + wbytes = width / 2; + addr += y * wbytes; + addr += x / 2; + byte = m_mem_read_cb(addr); + bits = (x % 2) - (endian ? 2 : 0); + return (byte >> (bits * 4)) & 0xf; + case 3: + wbytes = width; + addr += y * wbytes; + addr += x; + //LOG("r %d %d %d %d %d %x\n",map,width, height,x,y, addr); + return m_mem_read_cb(addr); + case 4: + wbytes = width * 2; + addr += y * wbytes; + addr += x * 2; + if(endian) + return m_mem_read_cb(addr + 1) | (m_mem_read_cb(addr) << 8); + return m_mem_read_cb(addr) | (m_mem_read_cb(addr + 1) << 8); + case 5: + wbytes = width * 4; + addr += y * wbytes; + addr += x * 4; + if(endian) + return m_mem_read_cb(addr + 3) | (m_mem_read_cb(addr + 2) << 8) | + (m_mem_read_cb(addr + 1) << 16) | (m_mem_read_cb(addr) << 24); + return m_mem_read_cb(addr) | (m_mem_read_cb(addr + 1) << 8) | + (m_mem_read_cb(addr + 2) << 16) | (m_mem_read_cb(addr + 3) << 24); + } + LOG("invalid pixel map mode %d %d\n", map, m_pelmap_format[map] & 7); + return 0; +} + +void xga_copro_device::write_map_pixel(int x, int y, int map, u32 pixel) +{ + offs_t addr = m_pelmap_base[map]; + int width = m_pelmap_width[map] + 1; + int height = m_pelmap_height[map] + 1; + int endian = m_pelmap_format[map] & 8; + int wbytes; + u8 byte, mask; + if((x > width) || (y > height) || (x < 0) || (y < 0)) + return; + switch(m_pelmap_format[map] & 7) + { + case 0: + wbytes = width / 8; + addr += y * wbytes; + addr += x / 8; + byte = m_mem_read_cb(addr); + mask = 1 << ((x % 8) - (endian ? 8 : 0)); + byte = (byte & ~mask) | ((pixel ? 0xff : 0) & mask); + m_mem_write_cb(addr, byte); + break; + case 1: + wbytes = width / 4; + addr += y * wbytes; + addr += x / 4; + byte = m_mem_read_cb(addr); + mask = 3 << (((x % 4) - (endian ? 4 : 0)) * 2); + byte = (byte & ~mask) | ((pixel ? 0xff : 0) & mask); + m_mem_write_cb(addr, byte); + break; + case 2: + wbytes = width / 2; + addr += y * wbytes; + addr += x / 2; + byte = m_mem_read_cb(addr); + mask = 0xf << (((x % 2) - (endian ? 2 : 0)) * 4); + byte = (byte & ~mask) | ((pixel ? 0xff : 0) & mask); + m_mem_write_cb(addr, byte); + break; + case 3: + wbytes = width; + addr += y * wbytes; + addr += x; + //LOG("w %d %d %d %d %d %x %x\n",map,width, height,x,y, addr, pixel); + m_mem_write_cb(addr, (u8)pixel); + break; + case 4: + wbytes = width * 2; + addr += y * wbytes; + addr += x * 2; + if(endian) + { + m_mem_write_cb(addr + 1, pixel & 0xff); + m_mem_write_cb(addr, pixel >> 8); + } + else + { + m_mem_write_cb(addr, pixel & 0xff); + m_mem_write_cb(addr + 1, pixel >> 8); + } + break; + case 5: + wbytes = width * 4; + addr += y * wbytes; + addr += x * 4; + if(endian) + { + m_mem_write_cb(addr + 3, pixel & 0xff); + m_mem_write_cb(addr + 2, pixel >> 8); + m_mem_write_cb(addr + 1, pixel >> 16); + m_mem_write_cb(addr, pixel >> 24); + } + else + { + m_mem_write_cb(addr, pixel & 0xff); + m_mem_write_cb(addr + 1, pixel >> 8); + m_mem_write_cb(addr + 2, pixel >> 16); + m_mem_write_cb(addr + 3, pixel >> 24); + } + break; + default: + LOG("invalid pixel map mode %d %d\n", map, m_pelmap_format[map] & 7); + break; + } +} + +u32 xga_copro_device::rop(u32 s, u32 d, u8 op) +{ + if(m_var == TYPE::OTI111) + { + switch(op) + { + default: + case 0: + return 0; + case 1: + return ~s & ~d; + case 2: + return ~s & d; + case 3: + return ~s; + case 4: + return s & ~d; + case 5: + return ~d; + case 6: + return s ^ d; + case 7: + return ~s | ~d; + case 8: + return s & d; + case 9: + return s ^ ~d; + case 10: + return d; + case 11: + return ~s | d; + case 12: + return s; + case 13: + return s | ~d; + case 14: + return s | d; + case 15: + return -1; + } + } + switch(op) + { + default: + case 0: + return 0; + case 1: + return s & d; + case 2: + return s & ~d; + case 3: + return s; + case 4: + return ~s & d; + case 5: + return d; + case 6: + return s ^ d; + case 7: + return s | d; + case 8: + return ~s & ~d; + case 9: + return s ^ ~d; + case 10: + return ~d; + case 11: + return s | ~d; + case 12: + return ~s; + case 13: + return ~s | d; + case 14: + return ~s | ~d; + case 15: + return -1; + case 16: + return std::max(s, d); + case 17: + return std::min(s, d); + case 18: + return 0; // saturate add + case 19: + return 0; // saturate sub d - s + case 20: + return 0; // saturate sub s - d + case 21: + return 0; // avg + } +} + +void xga_copro_device::do_pxblt() +{ + u8 dir = (m_pelop >> 25) & 2; + int xstart, xend, xdir, ystart, yend, ydir; + u8 srcmap = ((m_pelop >> 20) & 0xf) - 1; + u8 dstmap = ((m_pelop >> 16) & 0xf) - 1; + u8 patmap = ((m_pelop >> 12) & 0xf) - 1; + LOG("pxblt src %d pat %d dst %d dim1 %d dim2 %d srcbase %x dstbase %x\n", srcmap+1, dstmap+1, patmap+1, m_opdim1 & 0xfff, m_opdim2 & 0xfff, m_pelmap_base[srcmap+1], m_pelmap_base[dstmap+1]); + LOG("%d %d %d %d\n", m_srcxaddr & 0xfff, m_srcyaddr & 0xfff, m_dstxaddr & 0xfff, m_dstyaddr & 0xfff); + if((srcmap > 2) || (dstmap > 2) || ((patmap > 2) && (patmap != 7) && (patmap != 8))) + { + LOG("invalid pelmap\n"); + return; + } + if(dir & 1) + { + ystart = (m_opdim2 & 0xfff) + 1; + yend = 0; + ydir = -1; + } + else + { + ystart = 0; + yend = (m_opdim2 & 0xfff) + 1; + ydir = 1; + } + if(dir & 2) + { + xstart = (m_opdim1 & 0xfff) + 1; + xend = 0; + xdir = -1; + } + else + { + xstart = 0; + xend = (m_opdim1 & 0xfff) + 1; + xdir = 1; + } + + std::function dstwrap; + if(m_var == TYPE::OTI111) + dstwrap = [](s16 addr) { return addr & 0xfff; }; + else + { + dstwrap = [](s16 addr) + { + addr = addr & 0x1fff; + return (addr & 0x1800) == 0x1800 ? addr | 0xf800 : addr; + }; + } + + for(int y = ystart; y != yend; y += ydir) + { + u16 patxaddr = m_patxaddr & 0xfff; + u16 srcxaddr = m_srcxaddr & 0xfff; + s16 dstxaddr = dstwrap(m_dstxaddr); + s16 dstyaddr = dstwrap(m_dstyaddr); + for(int x = xstart; x != xend; x += xdir) + { + u32 src, dst, pat; + if(patmap < 3) + { + pat = read_map_pixel(patxaddr, m_patyaddr & 0xfff, patmap + 1); + patxaddr += xdir; + } + else + pat = 1; //TODO: generate from source mode + if(pat) + src = (((m_pelop >> 28) & 3) == 2) ? read_map_pixel(srcxaddr, m_srcyaddr & 0xfff, srcmap + 1) : m_fcolor; + else + src = (((m_pelop >> 30) & 3) == 2) ? read_map_pixel(srcxaddr, m_srcyaddr & 0xfff, srcmap + 1) : m_bcolor; + srcxaddr += xdir; + dst = read_map_pixel(dstxaddr, dstyaddr, dstmap + 1); + dst = (dst & ~m_pelbmask) | (rop(src, dst, pat ? m_fmix : m_bmix) & m_pelbmask); + write_map_pixel(dstxaddr, dstyaddr, dstmap + 1, dst); // TODO: color compare + dstxaddr = dstwrap(dstxaddr + xdir); + } + m_patyaddr += ydir; + m_srcyaddr += ydir; + m_dstyaddr += ydir; + } +} + +u8 xga_copro_device::xga_read(offs_t offset) +{ + switch(offset) + { + case 0x12: + return m_pelmap; + case 0x14: + return m_pelmap_base[m_pelmap]; + case 0x15: + return m_pelmap_base[m_pelmap] >> 8; + case 0x16: + return m_pelmap_base[m_pelmap] >> 16; + case 0x17: + return m_pelmap_base[m_pelmap] >> 24; + case 0x18: + return m_pelmap_width[m_pelmap]; + case 0x19: + return m_pelmap_width[m_pelmap] >> 8; + case 0x1a: + return m_pelmap_height[m_pelmap]; + case 0x1b: + return m_pelmap_height[m_pelmap] >> 8; + case 0x1c: + return m_pelmap_format[m_pelmap]; + case 0x20: + return m_bresh_err; + case 0x21: + return m_bresh_err >> 8; + case 0x24: + return m_bresh_k1; + case 0x25: + return m_bresh_k1 >> 8; + case 0x28: + return m_bresh_k2; + case 0x29: + return m_bresh_k2 >> 8; + case 0x2c: + return m_dir; + case 0x2d: + return m_dir >> 8; + case 0x2e: + return m_dir >> 16; + case 0x2f: + return m_dir >> 24; + case 0x48: + if(m_var == TYPE::OTI111) + return m_fmix << 4 | m_bmix; + return m_fmix; + case 0x49: + if(m_var == TYPE::OTI111) + return 0; + return m_bmix; + case 0x4a: + return m_destccc; + case 0x4c: + return m_destccv; + case 0x4d: + return m_destccv >> 8; + case 0x4e: + return m_destccv >> 16; + case 0x4f: + return m_destccv >> 24; + case 0x50: + return m_pelbmask; + case 0x51: + return m_pelbmask >> 8; + case 0x52: + return m_pelbmask >> 16; + case 0x53: + return m_pelbmask >> 24; + case 0x54: + return m_carrychain; + case 0x55: + return m_carrychain >> 8; + case 0x56: + return m_carrychain >> 16; + case 0x57: + return m_carrychain >> 24; + case 0x58: + return m_fcolor; + case 0x59: + return m_fcolor >> 8; + case 0x5a: + return m_fcolor >> 16; + case 0x5b: + return m_fcolor >> 24; + case 0x5c: + return m_bcolor; + case 0x5d: + return m_bcolor >> 8; + case 0x5e: + return m_bcolor >> 16; + case 0x5f: + return m_bcolor >> 24; + case 0x60: + return m_opdim1; + case 0x61: + return m_opdim1 >> 8; + case 0x62: + return m_opdim2; + case 0x63: + return m_opdim2 >> 8; + case 0x6c: + return m_maskorigx; + case 0x6d: + return m_maskorigx >> 8; + case 0x6e: + return m_maskorigy; + case 0x6f: + return m_maskorigy >> 8; + case 0x70: + return m_srcxaddr; + case 0x71: + return m_srcxaddr >> 8; + case 0x72: + return m_srcyaddr; + case 0x73: + return m_srcyaddr >> 8; + case 0x74: + return m_patxaddr; + case 0x75: + return m_patxaddr >> 8; + case 0x76: + return m_patyaddr; + case 0x77: + return m_patyaddr >> 8; + case 0x78: + return m_dstxaddr; + case 0x79: + return m_dstxaddr >> 8; + case 0x7a: + return m_dstyaddr; + case 0x7b: + return m_dstyaddr >> 8; + case 0x7c: + return m_pelop; + case 0x7d: + return m_pelop >> 8; + case 0x7e: + return m_pelop >> 16; + case 0x7f: + return m_pelop >> 24; + } + return 0; +} + +void xga_copro_device::xga_write(offs_t offset, u8 data) +{ + switch(offset) + { + case 0x12: + m_pelmap = data & 3; + break; + case 0x14: + m_pelmap_base[m_pelmap] = (m_pelmap_base[m_pelmap] & ~0xff) | data; + break; + case 0x15: + m_pelmap_base[m_pelmap] = (m_pelmap_base[m_pelmap] & ~0xff00) | (data << 8); + break; + case 0x16: + m_pelmap_base[m_pelmap] = (m_pelmap_base[m_pelmap] & ~0xff0000) | (data << 16); + break; + case 0x17: + m_pelmap_base[m_pelmap] = (m_pelmap_base[m_pelmap] & ~0xff000000) | (data << 24); + break; + case 0x18: + m_pelmap_width[m_pelmap] = (m_pelmap_width[m_pelmap] & ~0xff) | data; + break; + case 0x19: + m_pelmap_width[m_pelmap] = (m_pelmap_width[m_pelmap] & ~0xff00) | (data << 8); + break; + case 0x1a: + m_pelmap_height[m_pelmap] = (m_pelmap_height[m_pelmap] & ~0xff) | data; + break; + case 0x1b: + m_pelmap_height[m_pelmap] = (m_pelmap_height[m_pelmap] & ~0xff00) | (data << 8); + break; + case 0x1c: + m_pelmap_format[m_pelmap] = data; + break; + case 0x20: + m_bresh_err = (m_bresh_err & ~0xff) | data; + break; + case 0x21: + m_bresh_err = (m_bresh_err & ~0xff00) | (data << 8); + break; + case 0x24: + m_bresh_k1 = (m_bresh_k1 & ~0xff) | data; + break; + case 0x25: + m_bresh_k1 = (m_bresh_k1 & ~0xff00) | (data << 8); + break; + case 0x28: + m_bresh_k2 = (m_bresh_k2 & ~0xff) | data; + break; + case 0x29: + m_bresh_k2 = (m_bresh_k2 & ~0xff00) | (data << 8); + break; + case 0x2c: + m_dir = (m_dir & ~0xff) | data; + break; + case 0x2d: + m_dir = (m_dir & ~0xff00) | (data << 8); + break; + case 0x2e: + m_dir = (m_dir & ~0xff0000) | (data << 16); + break; + case 0x2f: + m_dir = (m_dir & ~0xff000000) | (data << 24); + break; + case 0x48: + if(m_var == TYPE::OTI111) + { + m_fmix = data >> 4; + m_bmix = data & 0xf; + break; + } + m_fmix = data; + break; + case 0x49: + if(m_var == TYPE::OTI111) + break; + m_bmix = data; + break; + case 0x4a: + m_destccc = data; + break; + case 0x4c: + m_destccv = (m_destccv & ~0xff) | data; + break; + case 0x4d: + m_destccv = (m_destccv & ~0xff00) | (data << 8); + break; + case 0x4e: + m_destccv = (m_destccv & ~0xff0000) | (data << 16); + break; + case 0x4f: + m_destccv = (m_destccv & ~0xff000000) | (data << 24); + break; + case 0x50: + m_pelbmask = (m_pelbmask & ~0xff) | data; + break; + case 0x51: + m_pelbmask = (m_pelbmask & ~0xff00) | (data << 8); + break; + case 0x52: + m_pelbmask = (m_pelbmask & ~0xff0000) | (data << 16); + break; + case 0x53: + m_pelbmask = (m_pelbmask & ~0xff000000) | (data << 24); + break; + case 0x54: + m_carrychain = (m_carrychain & ~0xff) | data; + break; + case 0x55: + m_carrychain = (m_carrychain & ~0xff00) | (data << 8); + break; + case 0x56: + m_carrychain = (m_carrychain & ~0xff0000) | (data << 16); + break; + case 0x57: + m_carrychain = (m_carrychain & ~0xff000000) | (data << 24); + break; + case 0x58: + m_fcolor = (m_fcolor & ~0xff) | data; + break; + case 0x59: + m_fcolor = (m_fcolor & ~0xff00) | (data << 8); + break; + case 0x5a: + m_fcolor = (m_fcolor & ~0xff0000) | (data << 16); + break; + case 0x5b: + m_fcolor = (m_fcolor & ~0xff000000) | (data << 24); + break; + case 0x5c: + m_bcolor = (m_bcolor & ~0xff) | data; + break; + case 0x5d: + m_bcolor = (m_bcolor & ~0xff00) | (data << 8); + break; + case 0x5e: + m_bcolor = (m_bcolor & ~0xff0000) | (data << 16); + break; + case 0x5f: + m_bcolor = (m_bcolor & ~0xff000000) | (data << 24); + break; + case 0x60: + m_opdim1 = (m_opdim1 & ~0xff) | data; + break; + case 0x61: + m_opdim1 = (m_opdim1 & ~0xff00) | (data << 8); + break; + case 0x62: + m_opdim2 = (m_opdim2 & ~0xff) | data; + break; + case 0x63: + m_opdim2 = (m_opdim2 & ~0xff00) | (data << 8); + break; + case 0x6c: + m_maskorigx = (m_maskorigx & ~0xff) | data; + break; + case 0x6d: + m_maskorigx = (m_maskorigx & ~0xff00) | (data << 8); + break; + case 0x6e: + m_maskorigy = (m_maskorigy & ~0xff) | data; + break; + case 0x6f: + m_maskorigy = (m_maskorigy & ~0xff00) | (data << 8); + break; + case 0x70: + m_srcxaddr = (m_srcxaddr & ~0xff) | data; + break; + case 0x71: + m_srcxaddr = (m_srcxaddr & ~0xff00) | (data << 8); + break; + case 0x72: + m_srcyaddr = (m_srcyaddr & ~0xff) | data; + break; + case 0x73: + m_srcyaddr = (m_srcyaddr & ~0xff00) | (data << 8); + break; + case 0x74: + m_patxaddr = (m_patxaddr & ~0xff) | data; + break; + case 0x75: + m_patxaddr = (m_patxaddr & ~0xff00) | (data << 8); + break; + case 0x76: + m_patyaddr = (m_patyaddr & ~0xff) | data; + break; + case 0x77: + m_patyaddr = (m_patyaddr & ~0xff00) | (data << 8); + break; + case 0x78: + m_dstxaddr = (m_dstxaddr & ~0xff) | data; + break; + case 0x79: + m_dstxaddr = (m_dstxaddr & ~0xff00) | (data << 8); + break; + case 0x7a: + m_dstyaddr = (m_dstyaddr & ~0xff) | data; + break; + case 0x7b: + m_dstyaddr = (m_dstyaddr & ~0xff00) | (data << 8); + break; + case 0x7c: + m_pelop = (m_pelop & ~0xff) | data; + break; + case 0x7d: + m_pelop = (m_pelop & ~0xff00) | (data << 8); + break; + case 0x7e: + m_pelop = (m_pelop & ~0xff0000) | (data << 16); + break; + case 0x7f: + m_pelop = (m_pelop & ~0xff000000) | (data << 24); + start_command(); + break; + } +} + +void xga_copro_device::device_start() +{ + m_mem_read_cb.resolve_safe(0); + m_mem_write_cb.resolve_safe(); +} + +void xga_copro_device::device_reset() +{ + m_pelmap = 0; +} + +oak_oti111_vga_device::oak_oti111_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : svga_device(mconfig, OTI111, tag, owner, clock) + , m_xga(*this, "xga") +{ +} + +void oak_oti111_vga_device::device_add_mconfig(machine_config &config) +{ + XGA_COPRO(config, m_xga, 0); + m_xga->mem_read_callback().set(FUNC(oak_oti111_vga_device::mem_linear_r)); + m_xga->mem_write_callback().set(FUNC(oak_oti111_vga_device::mem_linear_w)); + m_xga->set_type(xga_copro_device::TYPE::OTI111); +} + +u8 oak_oti111_vga_device::xga_read(offs_t offset) +{ + switch(offset) + { + case 0x13: //fifo status + return 0xf; + default: + return m_xga->xga_read(offset); + } + return 0; +} + +void oak_oti111_vga_device::xga_write(offs_t offset, u8 data) +{ + m_xga->xga_write(offset, data); +} + +void oak_oti111_vga_device::device_start() +{ + svga_device::device_start(); + std::fill(std::begin(m_oak_regs), std::end(m_oak_regs), 0); +} + +u8 oak_oti111_vga_device::dac_read(offs_t offset) +{ + if(offset >= 6) + return vga_device::port_03c0_r(offset); + return 0; +} + +void oak_oti111_vga_device::dac_write(offs_t offset, u8 data) +{ + if(offset >= 6) + vga_device::port_03c0_w(offset, data); +} + + +u8 oak_oti111_vga_device::port_03d0_r(offs_t offset) +{ + uint8_t res = 0xff; + switch(offset) + { + case 14: + return m_oak_idx; + case 15: + return m_oak_idx <= 0x3a ? m_oak_regs[m_oak_idx] : 0; + default: + if (get_crtc_port() == 0x3d0) + res = vga_device::port_03d0_r(offset); + break; + } + + return res; +} + +void oak_oti111_vga_device::port_03d0_w(offs_t offset, uint8_t data) +{ + switch(offset) + { + case 14: + m_oak_idx = data; + break; + case 15: + if(m_oak_idx > 0x3a) + break; + m_oak_regs[m_oak_idx] = data; + switch(m_oak_idx) + { + case 0x21: + svga.rgb8_en = BIT(data, 2); + break; + case 0x33: + vga.crtc.no_wrap = BIT(data, 0); + break; + } + break; + default: + if (get_crtc_port() == 0x3d0) + vga_device::port_03d0_w(offset,data); + break; + } +} + +uint16_t oak_oti111_vga_device::offset() +{ + uint16_t off = svga_device::offset(); + + if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en) + return vga.crtc.offset << 4; // TODO: there must a register to control this + else + return off; +} diff --git a/src/devices/video/pc_xga.h b/src/devices/video/pc_xga.h new file mode 100644 index 00000000000..370963bee26 --- /dev/null +++ b/src/devices/video/pc_xga.h @@ -0,0 +1,94 @@ +// license:BSD-3-Clause +// copyright-holders: Carl + +#ifndef MAME_VIDEO_PC_XGA_H +#define MAME_VIDEO_PC_XGA_H + +#include "screen.h" +#include "pc_vga.h" + +class xga_copro_device : public device_t +{ +public: + enum class TYPE { + XGA, + OTI111 + }; + + xga_copro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + u8 xga_read(offs_t offset); + void xga_write(offs_t offset, u8 data); + + auto mem_read_callback() { return m_mem_read_cb.bind(); } + auto mem_write_callback() { return m_mem_write_cb.bind(); } + auto set_type(TYPE var) { m_var = var; } +protected: + virtual void device_start() override; + virtual void device_reset() override; +private: + void start_command(); + void do_pxblt(); + u32 read_map_pixel(int x, int y, int map); + void write_map_pixel(int x, int y, int map, u32 pixel); + u32 rop(u32 src, u32 dst, u8 rop); + + u8 m_pelmap; + u32 m_pelmap_base[4]; + u16 m_pelmap_width[4]; + u16 m_pelmap_height[4]; + u8 m_pelmap_format[4]; + s16 m_bresh_err; + s16 m_bresh_k1; + s16 m_bresh_k2; + u32 m_dir; + u8 m_fmix; + u8 m_bmix; + u8 m_destccc; + u32 m_destccv; + u32 m_pelbmask; + u32 m_carrychain; + u32 m_fcolor; + u32 m_bcolor; + u16 m_opdim1; + u16 m_opdim2; + u16 m_maskorigx; + u16 m_maskorigy; + u16 m_srcxaddr; + u16 m_srcyaddr; + u16 m_patxaddr; + u16 m_patyaddr; + u16 m_dstxaddr; + u16 m_dstyaddr; + u32 m_pelop; + TYPE m_var; + devcb_read8 m_mem_read_cb; + devcb_write8 m_mem_write_cb; +}; + +DECLARE_DEVICE_TYPE(XGA_COPRO, xga_copro_device) + +class oak_oti111_vga_device : public svga_device +{ +public: + oak_oti111_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + u8 xga_read(offs_t offset); + void xga_write(offs_t offset, u8 data); + u8 dac_read(offs_t offset); + void dac_write(offs_t offset, u8 data); + virtual u8 port_03d0_r(offs_t offset) override; + virtual void port_03d0_w(offs_t offset, uint8_t data) override; +protected: + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual uint16_t offset() override; +private: + u8 m_oak_regs[0x3b]; + u8 m_oak_idx; + required_device m_xga; +}; + +DECLARE_DEVICE_TYPE(OTI111, oak_oti111_vga_device) + +#endif // MAME_VIDEO_PC_XGA_H diff --git a/src/devices/video/riva128.cpp b/src/devices/video/riva128.cpp new file mode 100644 index 00000000000..5ce8bcb119a --- /dev/null +++ b/src/devices/video/riva128.cpp @@ -0,0 +1,297 @@ +// license:BSD-3-Clause +// copyright-holders: Angelo Salese +// thanks-to: Marcelina Koscielnicka +/************************************************************************************************** + +nVidia NV3/NV3T Riva 128 + +TODO: +- Windows 98 punts device detection by attempting to modify the (supposedly) PMC ID. +\- Maybe the card is supposed to send an INTA trap on the write attempt? + +References: +- https://envytools.readthedocs.io/en/latest/hw/mmio.html?highlight=mmio#nv3-g80-mmio-map + +**************************************************************************************************/ + +#include "emu.h" +#include "riva128.h" + +#define LOG_WARN (1U << 1) +#define LOG_TODO (1U << 2) // log unimplemented registers + +#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_TODO) +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + +#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) +#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__) + + +DEFINE_DEVICE_TYPE(RIVA128, riva128_device, "riva128", "SGS-Thompson/nVidia Riva 128 (NV3)") + +riva128_device::riva128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : pci_device(mconfig, RIVA128, tag, owner, clock) + , m_svga(*this, "svga") + , m_vga_rom(*this, "vga_rom") +{ + // device ID 0x12d2 SGS-Thompson/nVidia joint venture + // 0x0018 RIVA 128 (NV3) + // 0x0019 RIVA 128 ZX (NV3T) + // TODO: STB uses 0x10b4xxxx, unknown for ASUS + set_ids_agp(0x12d20018, 0x00, 0x10921092); +} + +ROM_START( riva128 ) + ROM_REGION32_LE( 0x8000, "vga_rom", ROMREGION_ERASEFF ) + ROM_SYSTEM_BIOS( 0, "diamond", "Diamond Viper V330 1.62-CO 01/14/98" ) + ROMX_LOAD( "diamond_v330_rev-e.vbi", 0x0000, 0x8000, CRC(68686ddc) SHA1(cd2e299acd79624c7d82ce3317004c96bd4e36f7), ROM_BIOS(0) ) + ROM_SYSTEM_BIOS( 1, "asus", "ASUS AGP/3DP-V3000 1.51B 09/06/97" ) + ROMX_LOAD( "riva128_asus.vbi", 0x0000, 0x8000, CRC(cc57586f) SHA1(5e6ec14c66ec38b21013ee6b7582f6b6a4586e2e), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS( 2, "stb", "STB Velocity 128 AGP 1.82 12/17/97" ) + ROMX_LOAD( "riva128_stb.vbi", 0x0000, 0x8000, CRC(80da0245) SHA1(894c855c6d676de0d04d396f7e93a0e6cb98a4b3), ROM_BIOS(2) ) +ROM_END + +const tiny_rom_entry *riva128_device::device_rom_region() const +{ + return ROM_NAME(riva128); +} + +void riva128_device::device_add_mconfig(machine_config &config) +{ + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480); + screen.set_screen_update(m_svga, FUNC(nvidia_nv3_vga_device::screen_update)); + + NVIDIA_NV3_VGA(config, m_svga, 0); + m_svga->set_screen("screen"); + // FIXME: shared RAM + // reports as 4MB in AIDA16 + m_svga->set_vram_size(4*1024*1024); +} + +void riva128_device::device_start() +{ + pci_device::device_start(); + + add_map( 16*1024*1024, M_MEM, FUNC(riva128_device::mmio_map)); + add_map(128*1024*1024, M_MEM, FUNC(riva128_device::vram_aperture_map)); + // indirect memory access I/Os (NV3 only) + add_map(0x100, M_IO, FUNC(riva128_device::indirect_io_map)); + // TODO: Windows 98 expects an extra range mapped at 0x10000000-0x10007fff + + add_rom((u8 *)m_vga_rom->base(), 0x8000); + expansion_rom_base = 0xc0000; + + // INTA# + intr_pin = 1; + save_item(NAME(m_vga_legacy_enable)); +} + +void riva128_device::device_reset() +{ + pci_device::device_reset(); + + // TODO: to be checked + command = 0x0000; + status = 0x0000; + + m_vga_legacy_enable = true; + m_main_scratchpad_id = 0x00030310; + remap_cb(); +} + +// TODO: counter-check everything +void riva128_device::config_map(address_map &map) +{ + pci_device::config_map(map); + map(0x34, 0x34).lr8(NAME([] () { return 0x44; })); + +// map(0x40, 0x43) subsystem ID alias (writeable) +// map(0x44, 0x4f) AGP i/f +// map(0x50, 0x53) ROM shadow enable + map(0x54, 0x57).lrw8( + NAME([this] (offs_t offset) { return m_vga_legacy_enable; }), + NAME([this] (offs_t offset, u32 data, u32 mem_mask) { + if (ACCESSING_BITS_0_7) + { + m_vga_legacy_enable = BIT(data, 0); + remap_cb(); + } + //printf("- %s VGA control %08x & %08x\n", m_vga_legacy_enable ? "Enable" : "Disable", data, mem_mask); + }) + ); + map(0x58, 0x58).lr8(NAME([] () { return 0x00; })); + +} + +void riva128_device::mmio_map(address_map &map) +{ + map(0x00000000, 0x00ffffff).rw(FUNC(riva128_device::unmap_log_r), FUNC(riva128_device::unmap_log_w)); + map(0x00000000, 0x00000003).lrw32( + NAME([this] (offs_t offset) { + machine().debug_break(); + LOGTODO("MMIO ID readback\n"); + return m_main_scratchpad_id; + //return 0x00030310; + }), + NAME([this] (offs_t offset, u32 data, u32 mem_mask) { + COMBINE_DATA(&m_main_scratchpad_id); + }) + ); +// map(0x00000000, 0x00000fff) PMC card master control +// map(0x00001000, 0x00001fff) PBUS bus control +// map(0x00002000, 0x00003fff) PFIFO +// map(0x00007000, 0x00007***) PRMA real mode BAR Access +// map(0x00009000, 0x00009***) PTIMER +// map(0x000a0000, 0x000bffff) PRMFB legacy VGA memory +// map(0x000c0000, 0x000c****) PRMVIO VGA sequencer & VGA gfx regs (multiple on NV40+) +// map(0x00100000, 0x0010*fff) PFB memory interface +// map(0x00110000, 0x0011ffff) PROM ROM access window +// map(0x00120000, 0x0012ffff) PALT External memory access window +// map(0x00400000, 0x00400fff) PGRAPH 2d/3d graphics engine +// map(0x00401000, 0x00401***) PDMA system memory DMA engine (NV3/NV4 only) +// map(0x00600000, 0x00600***) PCRTC CRTC controls (on NV4+ only?) +// map(0x00601000, 0x0060****) PRMCIO VGA CRTC controls +// map(0x00680000, 0x0068****) PRAMDAC +// map(0x00681000, 0x00681***) VGA DAC registers +// map(0x00800000, 0x00******) PFIFO MMIO submission area +} + +void riva128_device::vram_aperture_map(address_map &map) +{ + +} + +void riva128_device::indirect_io_map(address_map &map) +{ + +} + +u32 riva128_device::unmap_log_r(offs_t offset, u32 mem_mask) +{ + LOGTODO("MMIO Unemulated [%08x] & %08x R\n", offset * 4, mem_mask); + return 0; +} + +void riva128_device::unmap_log_w(offs_t offset, u32 data, u32 mem_mask) +{ + LOGTODO("MMIO Unemulated [%08x] %08x & %08x W\n", offset * 4, data, mem_mask); +} + + +// TODO: this should really be a subclass of VGA +void riva128_device::legacy_memory_map(address_map &map) +{ + map(0xa0000, 0xbffff).rw(FUNC(riva128_device::vram_r), FUNC(riva128_device::vram_w)); +} + +void riva128_device::legacy_io_map(address_map &map) +{ + map(0x03b0, 0x03bf).rw(FUNC(riva128_device::vga_3b0_r), FUNC(riva128_device::vga_3b0_w)); + map(0x03c0, 0x03cf).rw(FUNC(riva128_device::vga_3c0_r), FUNC(riva128_device::vga_3c0_w)); + map(0x03d0, 0x03df).rw(FUNC(riva128_device::vga_3d0_r), FUNC(riva128_device::vga_3d0_w)); +} + +uint8_t riva128_device::vram_r(offs_t offset) +{ + return downcast(m_svga.target())->mem_r(offset); +} + +void riva128_device::vram_w(offs_t offset, uint8_t data) +{ + downcast(m_svga.target())->mem_w(offset, data); +} + +u32 riva128_device::vga_3b0_r(offs_t offset, uint32_t mem_mask) +{ + uint32_t result = 0; + if (ACCESSING_BITS_0_7) + result |= downcast(m_svga.target())->port_03b0_r(offset * 4 + 0) << 0; + if (ACCESSING_BITS_8_15) + result |= downcast(m_svga.target())->port_03b0_r(offset * 4 + 1) << 8; + if (ACCESSING_BITS_16_23) + result |= downcast(m_svga.target())->port_03b0_r(offset * 4 + 2) << 16; + if (ACCESSING_BITS_24_31) + result |= downcast(m_svga.target())->port_03b0_r(offset * 4 + 3) << 24; + return result; +} + +void riva128_device::vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + if (ACCESSING_BITS_0_7) + downcast(m_svga.target())->port_03b0_w(offset * 4 + 0, data >> 0); + if (ACCESSING_BITS_8_15) + downcast(m_svga.target())->port_03b0_w(offset * 4 + 1, data >> 8); + if (ACCESSING_BITS_16_23) + downcast(m_svga.target())->port_03b0_w(offset * 4 + 2, data >> 16); + if (ACCESSING_BITS_24_31) + downcast(m_svga.target())->port_03b0_w(offset * 4 + 3, data >> 24); +} + + +u32 riva128_device::vga_3c0_r(offs_t offset, uint32_t mem_mask) +{ + uint32_t result = 0; + if (ACCESSING_BITS_0_7) + result |= downcast(m_svga.target())->port_03c0_r(offset * 4 + 0) << 0; + if (ACCESSING_BITS_8_15) + result |= downcast(m_svga.target())->port_03c0_r(offset * 4 + 1) << 8; + if (ACCESSING_BITS_16_23) + result |= downcast(m_svga.target())->port_03c0_r(offset * 4 + 2) << 16; + if (ACCESSING_BITS_24_31) + result |= downcast(m_svga.target())->port_03c0_r(offset * 4 + 3) << 24; + return result; +} + +void riva128_device::vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + if (ACCESSING_BITS_0_7) + downcast(m_svga.target())->port_03c0_w(offset * 4 + 0, data >> 0); + if (ACCESSING_BITS_8_15) + downcast(m_svga.target())->port_03c0_w(offset * 4 + 1, data >> 8); + if (ACCESSING_BITS_16_23) + downcast(m_svga.target())->port_03c0_w(offset * 4 + 2, data >> 16); + if (ACCESSING_BITS_24_31) + downcast(m_svga.target())->port_03c0_w(offset * 4 + 3, data >> 24); +} + +u32 riva128_device::vga_3d0_r(offs_t offset, uint32_t mem_mask) +{ + uint32_t result = 0; + if (ACCESSING_BITS_0_7) + result |= downcast(m_svga.target())->port_03d0_r(offset * 4 + 0) << 0; + if (ACCESSING_BITS_8_15) + result |= downcast(m_svga.target())->port_03d0_r(offset * 4 + 1) << 8; + if (ACCESSING_BITS_16_23) + result |= downcast(m_svga.target())->port_03d0_r(offset * 4 + 2) << 16; + if (ACCESSING_BITS_24_31) + result |= downcast(m_svga.target())->port_03d0_r(offset * 4 + 3) << 24; + return result; +} + +void riva128_device::vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + if (ACCESSING_BITS_0_7) + downcast(m_svga.target())->port_03d0_w(offset * 4 + 0, data >> 0); + if (ACCESSING_BITS_8_15) + downcast(m_svga.target())->port_03d0_w(offset * 4 + 1, data >> 8); + if (ACCESSING_BITS_16_23) + downcast(m_svga.target())->port_03d0_w(offset * 4 + 2, data >> 16); + if (ACCESSING_BITS_24_31) + downcast(m_svga.target())->port_03d0_w(offset * 4 + 3, data >> 24); +} + +void riva128_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space, + uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) +{ + if (m_vga_legacy_enable) + { + memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(riva128_device::vram_r)), write8sm_delegate(*this, FUNC(riva128_device::vram_w))); + + io_space->install_readwrite_handler(0x3b0, 0x3bf, read32s_delegate(*this, FUNC(riva128_device::vga_3b0_r)), write32s_delegate(*this, FUNC(riva128_device::vga_3b0_w))); + io_space->install_readwrite_handler(0x3c0, 0x3cf, read32s_delegate(*this, FUNC(riva128_device::vga_3c0_r)), write32s_delegate(*this, FUNC(riva128_device::vga_3c0_w))); + io_space->install_readwrite_handler(0x3d0, 0x3df, read32s_delegate(*this, FUNC(riva128_device::vga_3d0_r)), write32s_delegate(*this, FUNC(riva128_device::vga_3d0_w))); + //memory_space->install_rom(0xc0000, 0xcffff, (void *)expansion_rom); + } +} diff --git a/src/devices/video/riva128.h b/src/devices/video/riva128.h new file mode 100644 index 00000000000..9ec1424263a --- /dev/null +++ b/src/devices/video/riva128.h @@ -0,0 +1,57 @@ +// license:BSD-3-Clause +// copyright-holders: Angelo Salese + +#ifndef MAME_VIDEO_RIVA128_H +#define MAME_VIDEO_RIVA128_H + +#pragma once + +#include "machine/pci.h" +#include "video/pc_vga_nvidia.h" + +class riva128_device : public pci_device +{ +public: + riva128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void legacy_memory_map(address_map &map); + void legacy_io_map(address_map &map); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + virtual const tiny_rom_entry *device_rom_region() const override; + + virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space, + uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override; + + virtual void config_map(address_map &map) override; + + virtual void mmio_map(address_map &map); + virtual void vram_aperture_map(address_map &map); + virtual void indirect_io_map(address_map &map); +private: + required_device m_svga; + required_memory_region m_vga_rom; + + u8 vram_r(offs_t offset); + void vram_w(offs_t offset, uint8_t data); + u32 vga_3b0_r(offs_t offset, uint32_t mem_mask = ~0); + void vga_3b0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + u32 vga_3c0_r(offs_t offset, uint32_t mem_mask = ~0); + void vga_3c0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + u32 vga_3d0_r(offs_t offset, uint32_t mem_mask = ~0); + void vga_3d0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + + u32 unmap_log_r(offs_t offset, u32 mem_mask = ~0); + void unmap_log_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + bool m_vga_legacy_enable = false; + u32 m_main_scratchpad_id = 0; +}; + +DECLARE_DEVICE_TYPE(RIVA128, riva128_device) + +#endif // MAME_VIDEO_RIVA128_H diff --git a/src/mame/konami/konmedal020.cpp b/src/mame/konami/konmedal020.cpp index 3c6db27ded4..9fcdaf79d62 100644 --- a/src/mame/konami/konmedal020.cpp +++ b/src/mame/konami/konmedal020.cpp @@ -24,7 +24,7 @@ #include "machine/nvram.h" #include "machine/timer.h" #include "sound/ymz280b.h" -#include "video/pc_vga.h" +#include "video/pc_xga.h" #include "emupal.h" #include "screen.h" #include "speaker.h" @@ -100,7 +100,7 @@ void konmedal020_state::gs471(machine_config &config) /* video hardware */ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480); - screen.set_screen_update(m_vga, FUNC(vga_device::screen_update)); + screen.set_screen_update(m_vga, FUNC(svga_device::screen_update)); screen.screen_vblank().set_inputline(m_maincpu, M68K_IRQ_3); OTI111(config, m_vga, 0); diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 0f87fdccb58..fdd52e884ff 100755 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -35337,6 +35337,7 @@ streetgr3 // (c) 1993 @source:pc/pcipc.cpp pcipc // +pcinv3 // pcipctx // @source:pc/pcxt.cpp diff --git a/src/mame/midway/midqslvr.cpp b/src/mame/midway/midqslvr.cpp index 9eca531aa56..19fdd9133de 100644 --- a/src/mame/midway/midqslvr.cpp +++ b/src/mame/midway/midqslvr.cpp @@ -479,10 +479,6 @@ ROM_START( offrthnd ) ROM_REGION32_LE(0x80000, "pci:07.0", 0) ROM_LOAD( "lh28f004sct.u8b1", 0x000000, 0x080000, CRC(ab04a343) SHA1(ba77933400fe470f45ab187bc0d315922caadb12) ) - ROM_REGION( 0x8000, "video_bios", ROMREGION_ERASEFF ) // TODO: Voodoo 2 has no bios, to be removed once the driver is updated not to look for this region -// ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, BAD_DUMP CRC(1eebde64) SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) -// ROM_CONTINUE( 0x0001, 0x4000 ) - ROM_REGION( 0x2000, "iocpu", 0 ) /* Magicbus board CY7C63513 MCU code */ ROM_LOAD( "magicbus.u18", 0x0000, 0x2000, NO_DUMP ) // 8KB internal EPROM @@ -494,10 +490,6 @@ ROM_START( arctthnd ) ROM_REGION32_LE(0x40000, "bios", ROMREGION_ERASEFF) ROM_LOAD( "m29f002bt.u6", 0x000000, 0x040000, CRC(012c9290) SHA1(cdee6f19d5e5ea5bb1dd6a5ec397ac70b3452790) ) - ROM_REGION( 0x8000, "video_bios", ROMREGION_ERASEFF ) // TODO: Voodoo 2 has no bios, to be removed once the driver is updated not to look for this region -// ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, BAD_DUMP CRC(1eebde64) SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) -// ROM_CONTINUE( 0x0001, 0x4000 ) - ROM_REGION( 0x2000, "iocpu", 0 ) /* Substitute board 87C552 MCU code */ ROM_LOAD( "87c552.bin", 0x0000, 0x2000, NO_DUMP ) // 8KB internal EPROM @@ -509,10 +501,6 @@ ROM_START( ultarctc ) ROM_REGION32_LE(0x40000, "bios", ROMREGION_ERASEFF) ROM_LOAD( "m29f002bt.u6", 0x000000, 0x040000, CRC(012c9290) SHA1(cdee6f19d5e5ea5bb1dd6a5ec397ac70b3452790) ) - ROM_REGION( 0x8000, "video_bios", ROMREGION_ERASEFF ) // TODO: Voodoo 2 has no bios, to be removed once the driver is updated not to look for this region -// ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, BAD_DUMP CRC(1eebde64) SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) -// ROM_CONTINUE( 0x0001, 0x4000 ) - ROM_REGION( 0x2000, "iocpu", 0 ) /* Substitute board 87C552 MCU code */ ROM_LOAD( "87c552.bin", 0x0000, 0x2000, NO_DUMP ) // 8KB internal EPROM @@ -527,10 +515,6 @@ ROM_START( ultarctcup ) ROM_REGION32_LE(0x40000, "bios", ROMREGION_ERASEFF) ROM_LOAD( "m29f002bt.u6", 0x000000, 0x040000, CRC(012c9290) SHA1(cdee6f19d5e5ea5bb1dd6a5ec397ac70b3452790) ) - ROM_REGION( 0x8000, "video_bios", ROMREGION_ERASEFF ) // TODO: Voodoo 2 has no bios, to be removed once the driver is updated not to look for this region -// ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, BAD_DUMP CRC(1eebde64) SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) -// ROM_CONTINUE( 0x0001, 0x4000 ) - ROM_REGION( 0x2000, "iocpu", 0 ) /* Substitute board 87C552 MCU code */ ROM_LOAD( "87c552.bin", 0x0000, 0x2000, NO_DUMP ) // 8KB internal EPROM diff --git a/src/mame/misc/gammagic.cpp b/src/mame/misc/gammagic.cpp index 5048b79f26c..6f27df6b3b5 100644 --- a/src/mame/misc/gammagic.cpp +++ b/src/mame/misc/gammagic.cpp @@ -80,7 +80,7 @@ private: void gammagic_state::gammagic_map(address_map &map) { map(0x00000000, 0x0009ffff).ram(); - map(0x000a0000, 0x000bffff).rw("vga", FUNC(vga_device::mem_r), FUNC(vga_device::mem_w)); +// map(0x000a0000, 0x000bffff).rw("vga", FUNC(vga_device::mem_r), FUNC(vga_device::mem_w)); map(0x000e0000, 0x000fffff).rom().region("isa", 0x20000);/* System BIOS */ map(0x00100000, 0x07ffffff).ram(); map(0x08000000, 0xfffdffff).noprw(); @@ -93,9 +93,9 @@ void gammagic_state::gammagic_io(address_map &map) map(0x00e8, 0x00ef).noprw(); // map(0x00f0, 0x01ef).noprw(); // map(0x01f8, 0x03af).noprw(); - map(0x03b0, 0x03bf).rw("vga", FUNC(vga_device::port_03b0_r), FUNC(vga_device::port_03b0_w)); - map(0x03c0, 0x03cf).rw("vga", FUNC(vga_device::port_03c0_r), FUNC(vga_device::port_03c0_w)); - map(0x03d0, 0x03df).rw("vga", FUNC(vga_device::port_03d0_r), FUNC(vga_device::port_03d0_w)); +// map(0x03b0, 0x03bf).rw("vga", FUNC(vga_device::port_03b0_r), FUNC(vga_device::port_03b0_w)); +// map(0x03c0, 0x03cf).rw("vga", FUNC(vga_device::port_03c0_r), FUNC(vga_device::port_03c0_w)); +// map(0x03d0, 0x03df).rw("vga", FUNC(vga_device::port_03d0_r), FUNC(vga_device::port_03d0_w)); // map(0x03e0, 0x03ef).noprw(); // map(0x0cf8, 0x0cff).rw("pcibus", FUNC(pci_bus_device::read), FUNC(pci_bus_device::write)); // map(0x0400, 0xffff).noprw(); @@ -120,9 +120,6 @@ void gammagic_state::gammagic(machine_config &config) PCI_ROOT(config, "pci", 0); // ... - - /* video hardware */ - pcvideo_vga(config); } @@ -130,11 +127,9 @@ ROM_START( gammagic ) ROM_REGION32_LE(0x40000, "isa", 0) //Original Memory Set //ROM_LOAD("m7s04.rom", 0, 0x40000, CRC(3689f5a9) SHA1(8daacdb0dc6783d2161680564ffe83ac2515f7ef)) + // TODO: add this (needs "OAK SVGA" PCI BIOS hooked up) //ROM_LOAD("otivga_tx2953526.rom", 0x0000, 0x8000, CRC(916491af) SHA1(d64e3a43a035d70ace7a2d0603fc078f22d237e1)) - // TODO: remove this (needs "OAK SVGA" PCI BIOS hooked up) - ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, BAD_DUMP CRC(1eebde64) SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) - ROM_CONTINUE( 0x0001, 0x4000 ) // TODO: specs mentions a m55hipl compatible BIOS, this is 5HX29 ROM_LOAD("5hx29.bin", 0x20000, 0x20000, BAD_DUMP CRC(07719a55) SHA1(b63993fd5186cdb4f28c117428a507cd069e1f68)) @@ -150,11 +145,9 @@ ROM_START( 99bottles ) ROM_REGION32_LE(0x40000, "isa", 0) //Original BIOS/VGA-BIOS Rom Set //ROM_LOAD("m7s04.rom", 0, 0x40000, CRC(3689f5a9) SHA1(8daacdb0dc6783d2161680564ffe83ac2515f7ef)) + // TODO: add this (needs "OAK SVGA" PCI BIOS hooked up) //ROM_LOAD("otivga_tx2953526.rom", 0x0000, 0x8000, CRC(916491af) SHA1(d64e3a43a035d70ace7a2d0603fc078f22d237e1)) - // TODO: remove this (needs "OAK SVGA" PCI BIOS hooked up) - ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, BAD_DUMP CRC(1eebde64) SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) - ROM_CONTINUE( 0x0001, 0x4000 ) // TODO: specs mentions a m55hipl compatible BIOS, this is 5HX29 ROM_LOAD("5hx29.bin", 0x20000, 0x20000, BAD_DUMP CRC(07719a55) SHA1(b63993fd5186cdb4f28c117428a507cd069e1f68)) diff --git a/src/mame/misc/gamtor.cpp b/src/mame/misc/gamtor.cpp index f5305230a7d..e333f626c44 100644 --- a/src/mame/misc/gamtor.cpp +++ b/src/mame/misc/gamtor.cpp @@ -33,6 +33,134 @@ #include "speaker.h" +// TODO: Chips & Technologies 65550 with swapped address lines? +// Needs to be moved to own family file +// 65550 is used by Apple PowerBook 2400c +// 65535 is used by IBM PC-110 + +class gamtor_vga_device : public svga_device +{ +public: + // construction/destruction + gamtor_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + + virtual uint8_t port_03b0_r(offs_t offset) override; + virtual void port_03b0_w(offs_t offset, uint8_t data) override; + virtual uint8_t port_03c0_r(offs_t offset) override; + virtual void port_03c0_w(offs_t offset, uint8_t data) override; + virtual uint8_t port_03d0_r(offs_t offset) override; + virtual void port_03d0_w(offs_t offset, uint8_t data) override; +// virtual uint8_t mem_r(offs_t offset) override; +// virtual void mem_w(offs_t offset, uint8_t data) override; + virtual uint8_t mem_linear_r(offs_t offset) override; + virtual void mem_linear_w(offs_t offset,uint8_t data) override; + +protected: + virtual uint16_t offset() override; +}; + +DEFINE_DEVICE_TYPE(GAMTOR_VGA, gamtor_vga_device, "gamtor_vga", "CT-65550 SVGA") + +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) +{ +} + +uint8_t gamtor_vga_device::mem_linear_r(offs_t offset) +{ + if (!machine().side_effects_disabled()) + logerror("Reading gamtor SVGA memory %08x\n", offset); + return vga.memory[offset]; +} + +void gamtor_vga_device::mem_linear_w(offs_t offset, uint8_t data) +{ + if (offset & 2) + vga.memory[(offset >> 2) + 0x20000] = data; + else + vga.memory[(offset & 1) | (offset >> 1)] = data; +} + + +uint8_t gamtor_vga_device::port_03b0_r(offs_t offset) +{ + uint8_t res; + + switch(offset) + { + default: + res = vga_device::port_03b0_r(offset ^ 3); + break; + } + + return res; +} + +void gamtor_vga_device::port_03b0_w(offs_t offset, uint8_t data) +{ + switch(offset) + { + default: + vga_device::port_03b0_w(offset ^ 3,data); + break; + } +} + +uint8_t gamtor_vga_device::port_03c0_r(offs_t offset) +{ + uint8_t res; + + switch(offset) + { + default: + res = vga_device::port_03c0_r(offset ^ 3); + break; + } + + return res; +} + +void gamtor_vga_device::port_03c0_w(offs_t offset, uint8_t data) +{ + switch(offset) + { + default: + vga_device::port_03c0_w(offset ^ 3,data); + break; + } +} + +uint8_t gamtor_vga_device::port_03d0_r(offs_t offset) +{ + uint8_t res; + + switch(offset) + { + default: + res = vga_device::port_03d0_r(offset ^ 3); + break; + } + + return res; +} + +void gamtor_vga_device::port_03d0_w(offs_t offset, uint8_t data) +{ + switch(offset) + { + default: + vga_device::port_03d0_w(offset ^ 3,data); + break; + } +} + +uint16_t gamtor_vga_device::offset() +{ + // TODO: pinpoint whatever extra register that wants this shifted by 1 + return vga_device::offset() << 1; +} + namespace { class gaminator_state : public driver_device diff --git a/src/mame/misc/magtouch.cpp b/src/mame/misc/magtouch.cpp index b27750ed40e..01ea3e3c644 100644 --- a/src/mame/misc/magtouch.cpp +++ b/src/mame/misc/magtouch.cpp @@ -83,7 +83,7 @@ video card #include "machine/ins8250.h" #include "machine/microtch.h" #include "machine/nvram.h" -#include "bus/isa/trident.h" +#include "video/pc_vga_trident.h" #include "bus/isa/isa.h" #include "bus/isa/sblaster.h" @@ -148,7 +148,7 @@ void magtouch_state::magtouch_io_w(offs_t offset, uint8_t data) void magtouch_state::magtouch_map(address_map &map) { map(0x00000000, 0x0009ffff).ram(); - map(0x000a0000, 0x000bffff).rw("vga", FUNC(trident_vga_device::mem_r), FUNC(trident_vga_device::mem_w)); + map(0x000a0000, 0x000bffff).rw("vga", FUNC(tvga9000_device::mem_r), FUNC(tvga9000_device::mem_w)); map(0x000c0000, 0x000c7fff).rom().region("video_bios", 0); map(0x000d0000, 0x000d1fff).ram().share("nvram"); map(0x000d8000, 0x000dffff).bankr("rombank"); @@ -160,9 +160,9 @@ void magtouch_state::magtouch_io(address_map &map) { pcat32_io_common(map); map(0x02e0, 0x02e7).rw(FUNC(magtouch_state::magtouch_io_r), FUNC(magtouch_state::magtouch_io_w)); - map(0x03b0, 0x03bf).rw("vga", FUNC(trident_vga_device::port_03b0_r), FUNC(trident_vga_device::port_03b0_w)); - map(0x03c0, 0x03cf).rw("vga", FUNC(trident_vga_device::port_03c0_r), FUNC(trident_vga_device::port_03c0_w)); - map(0x03d0, 0x03df).rw("vga", FUNC(trident_vga_device::port_03d0_r), FUNC(trident_vga_device::port_03d0_w)); + map(0x03b0, 0x03bf).rw("vga", FUNC(tvga9000_device::port_03b0_r), FUNC(tvga9000_device::port_03b0_w)); + map(0x03c0, 0x03cf).rw("vga", FUNC(tvga9000_device::port_03c0_r), FUNC(tvga9000_device::port_03c0_w)); + map(0x03d0, 0x03df).rw("vga", FUNC(tvga9000_device::port_03d0_r), FUNC(tvga9000_device::port_03d0_w)); map(0x03f8, 0x03ff).rw("ns16450_0", FUNC(ns16450_device::ins8250_r), FUNC(ns16450_device::ins8250_w)); } @@ -214,8 +214,12 @@ void magtouch_state::magtouch(machine_config &config) m_maincpu->set_irq_acknowledge_callback("pic8259_1", FUNC(pic8259_device::inta_cb)); /* video hardware */ - pcvideo_trident_vga(config); - tvga9000_device &vga(TVGA9000_VGA(config.replace(), "vga", 0)); + // TODO: map to ISA bus + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); + screen.set_screen_update("vga", FUNC(tvga9000_device::screen_update)); + + tvga9000_device &vga(TVGA9000_VGA(config, "vga", 0)); vga.set_screen("screen"); vga.set_vram_size(0x200000); diff --git a/src/mame/misc/pntnpuzl.cpp b/src/mame/misc/pntnpuzl.cpp index 619a637e01c..c11cfb5e46d 100644 --- a/src/mame/misc/pntnpuzl.cpp +++ b/src/mame/misc/pntnpuzl.cpp @@ -138,12 +138,11 @@ CN1 standard DB15 VGA connector (15KHz) */ #include "emu.h" -#include "bus/isa/trident.h" #include "cpu/m68000/m68000.h" #include "cpu/mcs96/i8x9x.h" #include "machine/6522via.h" #include "machine/eepromser.h" -#include "video/pc_vga.h" +#include "video/pc_vga_trident.h" #include "screen.h" diff --git a/src/mame/misc/savquest.cpp b/src/mame/misc/savquest.cpp index 2d8cf4df541..0c67634410c 100644 --- a/src/mame/misc/savquest.cpp +++ b/src/mame/misc/savquest.cpp @@ -77,7 +77,7 @@ #include "machine/idectrl.h" #include "machine/lpci.h" #include "machine/pckeybrd.h" -#include "video/pc_vga.h" +#include "video/pc_vga_s3.h" #include "video/voodoo_2.h" @@ -871,7 +871,14 @@ void savquest_state::savquest(machine_config &config) ISA16_SLOT(config, "isa1", 0, "isa", savquest_isa16_cards, "sb16", false); /* video hardware */ - pcvideo_s3_vga(config); + // TODO: map to ISA bus, make sure that the Voodoo can override s3 in screen update + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); + screen.set_screen_update("vga", FUNC(s3_vga_device::screen_update)); + + s3_vga_device &vga(S3_VGA(config, "vga", 0)); + vga.set_screen("screen"); + vga.set_vram_size(0x100000); VOODOO_2(config, m_voodoo, voodoo_2_device::NOMINAL_CLOCK); m_voodoo->set_fbmem(4); diff --git a/src/mame/misc/su2000.cpp b/src/mame/misc/su2000.cpp index 5a1829bb141..db9d238a528 100644 --- a/src/mame/misc/su2000.cpp +++ b/src/mame/misc/su2000.cpp @@ -168,7 +168,14 @@ void su2000_state::su2000(machine_config &config) #endif /* Video hardware */ - pcvideo_vga(config); + // TODO: Hualon ISA custom + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); + screen.set_screen_update("vga", FUNC(vga_device::screen_update)); + + vga_device &vga(VGA(config, "vga", 0)); + vga.set_screen("screen"); + vga.set_vram_size(0x100000); pcat_common(config); diff --git a/src/mame/misc/voyager.cpp b/src/mame/misc/voyager.cpp index d469f26df18..2d62667a69e 100644 --- a/src/mame/misc/voyager.cpp +++ b/src/mame/misc/voyager.cpp @@ -19,499 +19,58 @@ HDD for stand-up Voyager is a Maxtor D740X-6L 20 GB model. Upright Voyager runs at 15 kHz standard res, sit-down at 24 kHz medium res. -TODO: VIA KT133a chipset support, GeForce 2MX video support, lots of things ;-) +TODO: +- VIA KT133a chipset support, GeForce 2MX video support, lots of things ;-) +- Run this under shutms11 will report an AC'97 error for a Trident 4DWave PCI card. *************************************************************************************/ #include "emu.h" -#include "pcshare.h" - #include "cpu/i386/i386.h" -#include "machine/idectrl.h" -#include "machine/lpci.h" -#include "machine/nvram.h" -#include "machine/pckeybrd.h" -#include "video/pc_vga.h" - -#include "bus/isa/trident.h" +#include "machine/pci.h" -#include "screen.h" -#include "speaker.h" namespace { -class voyager_state : public pcat_base_state +class voyager_state : public driver_device { public: voyager_state(const machine_config &mconfig, device_type type, const char *tag) - : pcat_base_state(mconfig, type, tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") { } void voyager(machine_config &config); - void init_voyager(); - private: - std::unique_ptr m_bios_ram; - std::unique_ptr m_nvram_data; - uint8_t m_mtxc_config_reg[256]; - uint8_t m_piix4_config_reg[4][256]; - - void bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint8_t nvram_r(offs_t offset); - void nvram_w(offs_t offset, uint8_t data); - - virtual void machine_start() override; - virtual void machine_reset() override; - void intel82439tx_init(); - void voyager_io(address_map &map); void voyager_map(address_map &map); - uint8_t mtxc_config_r(int function, int reg); - void mtxc_config_w(int function, int reg, uint8_t data); - uint32_t intel82439tx_pci_r(int function, int reg, uint32_t mem_mask); - void intel82439tx_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask); - uint8_t piix4_config_r(int function, int reg); - void piix4_config_w(int function, int reg, uint8_t data); - uint32_t intel82371ab_pci_r(int function, int reg, uint32_t mem_mask); - void intel82371ab_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask); + required_device m_maincpu; }; -// Intel 82439TX System Controller (MTXC) - -uint8_t voyager_state::mtxc_config_r(int function, int reg) -{ -// osd_printf_debug("MTXC: read %d, %02X\n", function, reg); - - return m_mtxc_config_reg[reg]; -} - -void voyager_state::mtxc_config_w(int function, int reg, uint8_t data) -{ -// osd_printf_debug("%s:MTXC: write %d, %02X, %02X\n", machine().describe_context(), function, reg, data); - - switch(reg) - { - //case 0x59: - case 0x63: // PAM0 - { - //if (data & 0x10) // enable RAM access to region 0xf0000 - 0xfffff - if ((data & 0x50) | (data & 0xA0)) - { - membank("bank1")->set_base(m_bios_ram.get()); - } - else // disable RAM access (reads go to BIOS ROM) - { - //Execution Hack to avoid crash when switch back from Shadow RAM to Bios ROM, since i386 emu haven't yet pipelined execution structure. - //It happens when exit from BIOS SETUP. - #if 0 - if ((m_mtxc_config_reg[0x63] & 0x50) | ( m_mtxc_config_reg[0x63] & 0xA0)) // Only DO if comes a change to disable ROM. - { - if (m_maincpu->pc()==0xff74e) m_maincpu->set_pc(0xff74d); - } - #endif - - membank("bank1")->set_base(memregion("bios")->base() + 0x10000); - membank("bank1")->set_base(memregion("bios")->base()); - } - break; - } - } - - m_mtxc_config_reg[reg] = data; -} - -void voyager_state::intel82439tx_init() -{ - m_mtxc_config_reg[0x60] = 0x02; - m_mtxc_config_reg[0x61] = 0x02; - m_mtxc_config_reg[0x62] = 0x02; - m_mtxc_config_reg[0x63] = 0x02; - m_mtxc_config_reg[0x64] = 0x02; - m_mtxc_config_reg[0x65] = 0x02; -} - -uint32_t voyager_state::intel82439tx_pci_r(int function, int reg, uint32_t mem_mask) -{ - uint32_t r = 0; - - if(reg == 0) - return 0x05851106; // VT82C585VPX, VIA - - if (ACCESSING_BITS_24_31) - { - r |= mtxc_config_r(function, reg + 3) << 24; - } - if (ACCESSING_BITS_16_23) - { - r |= mtxc_config_r(function, reg + 2) << 16; - } - if (ACCESSING_BITS_8_15) - { - r |= mtxc_config_r(function, reg + 1) << 8; - } - if (ACCESSING_BITS_0_7) - { - r |= mtxc_config_r(function, reg + 0) << 0; - } - return r; -} - -void voyager_state::intel82439tx_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask) -{ - if (ACCESSING_BITS_24_31) - { - mtxc_config_w(function, reg + 3, (data >> 24) & 0xff); - } - if (ACCESSING_BITS_16_23) - { - mtxc_config_w(function, reg + 2, (data >> 16) & 0xff); - } - if (ACCESSING_BITS_8_15) - { - mtxc_config_w(function, reg + 1, (data >> 8) & 0xff); - } - if (ACCESSING_BITS_0_7) - { - mtxc_config_w(function, reg + 0, (data >> 0) & 0xff); - } -} - -// Intel 82371AB PCI-to-ISA / IDE bridge (PIIX4) - -uint8_t voyager_state::piix4_config_r(int function, int reg) -{ -// osd_printf_debug("PIIX4: read %d, %02X\n", function, reg); - return m_piix4_config_reg[function][reg]; -} - -void voyager_state::piix4_config_w(int function, int reg, uint8_t data) -{ -// osd_printf_debug("%s:PIIX4: write %d, %02X, %02X\n", machine().describe_context(), function, reg, data); - m_piix4_config_reg[function][reg] = data; -} - -uint32_t voyager_state::intel82371ab_pci_r(int function, int reg, uint32_t mem_mask) -{ - uint32_t r = 0; - - if(reg == 0) - return 0x30401106; // VT82C586B, VIA - - if (ACCESSING_BITS_24_31) - { - r |= piix4_config_r(function, reg + 3) << 24; - } - if (ACCESSING_BITS_16_23) - { - r |= piix4_config_r(function, reg + 2) << 16; - } - if (ACCESSING_BITS_8_15) - { - r |= piix4_config_r(function, reg + 1) << 8; - } - if (ACCESSING_BITS_0_7) - { - r |= piix4_config_r(function, reg + 0) << 0; - } - return r; -} - -void voyager_state::intel82371ab_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask) -{ - if (ACCESSING_BITS_24_31) - { - piix4_config_w(function, reg + 3, (data >> 24) & 0xff); - } - if (ACCESSING_BITS_16_23) - { - piix4_config_w(function, reg + 2, (data >> 16) & 0xff); - } - if (ACCESSING_BITS_8_15) - { - piix4_config_w(function, reg + 1, (data >> 8) & 0xff); - } - if (ACCESSING_BITS_0_7) - { - piix4_config_w(function, reg + 0, (data >> 0) & 0xff); - } -} - -void voyager_state::bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - //if (m_mtxc_config_reg[0x59] & 0x20) // write to RAM if this region is write-enabled - if (m_mtxc_config_reg[0x63] & 0x50) - { - COMBINE_DATA(m_bios_ram.get() + offset); - } -} - -uint8_t voyager_state::nvram_r(offs_t offset) -{ - return m_nvram_data[offset]; -} - -void voyager_state::nvram_w(offs_t offset, uint8_t data) -{ - m_nvram_data[offset] = data; -} - void voyager_state::voyager_map(address_map &map) { map(0x00000000, 0x0009ffff).ram(); - map(0x000a0000, 0x000bffff).rw("vga", FUNC(trident_vga_device::mem_r), FUNC(trident_vga_device::mem_w)); // VGA VRAM - map(0x000c0000, 0x000c7fff).rom().region("video_bios", 0); - map(0x000c8000, 0x000cffff).noprw(); - //map(0x000d0000, 0x000d0003).ram(); // XYLINX - Synchronous serial communication - map(0x000d0008, 0x000d000b).nopw(); // ??? - map(0x000d0800, 0x000d0fff).rw(FUNC(voyager_state::nvram_r), FUNC(voyager_state::nvram_w)); // GAME_CMOS - - //GRULL map(0x000e0000, 0x000effff).ram(); - //GRULL-map(0x000f0000, 0x000fffff).bankr("bank1"); - //GRULL map(0x000f0000, 0x000fffff).w(FUNC(voyager_state::bios_ram_w)); - map(0x000e0000, 0x000fffff).bankr("bank1"); - map(0x000e0000, 0x000fffff).w(FUNC(voyager_state::bios_ram_w)); - map(0x00100000, 0x03ffffff).ram(); // 64MB - map(0x04000000, 0x28ffffff).noprw(); - //map(0x04000000, 0x040001ff).ram(); - //map(0x08000000, 0x080001ff).ram(); - //map(0x0c000000, 0x0c0001ff).ram(); - //map(0x10000000, 0x100001ff).ram(); - //map(0x14000000, 0x140001ff).ram(); - //map(0x18000000, 0x180001ff).ram(); - //map(0x20000000, 0x200001ff).ram(); - //map(0x28000000, 0x280001ff).ram(); - map(0xfffe0000, 0xffffffff).rom().region("bios", 0); /* System BIOS */ -} - -void voyager_state::voyager_io(address_map &map) -{ - pcat32_io_common(map); - - //map(0x00e8, 0x00eb).noprw(); - map(0x00e8, 0x00ef).noprw(); //AMI BIOS write to this ports as delays between I/O ports operations sending al value -> NEWIODELAY - map(0x0170, 0x0177).noprw(); //To debug - map(0x01f0, 0x01f7).rw("ide", FUNC(ide_controller_device::cs0_r), FUNC(ide_controller_device::cs0_w)); - map(0x0200, 0x021f).noprw(); //To debug - map(0x0260, 0x026f).noprw(); //To debug - map(0x0278, 0x027b).nopw();//.w(FUNC(voyager_state::pnp_config_w)); - map(0x0280, 0x0287).noprw(); //To debug - map(0x02a0, 0x02a7).noprw(); //To debug - map(0x02c0, 0x02c7).noprw(); //To debug - map(0x02e0, 0x02ef).noprw(); //To debug - map(0x02f8, 0x02ff).noprw(); //To debug - map(0x0320, 0x038f).noprw(); //To debug - map(0x03a0, 0x03a7).noprw(); //To debug - map(0x03b0, 0x03bf).rw("vga", FUNC(trident_vga_device::port_03b0_r), FUNC(trident_vga_device::port_03b0_w)); - map(0x03c0, 0x03cf).rw("vga", FUNC(trident_vga_device::port_03c0_r), FUNC(trident_vga_device::port_03c0_w)); - map(0x03d0, 0x03df).rw("vga", FUNC(trident_vga_device::port_03d0_r), FUNC(trident_vga_device::port_03d0_w)); - map(0x03e0, 0x03ef).noprw(); //To debug - map(0x0378, 0x037f).noprw(); //To debug - // map(0x0300, 0x03af).noprw(); - // map(0x03b0, 0x03df).noprw(); - map(0x03f0, 0x03f7).rw("ide", FUNC(ide_controller_device::cs1_r), FUNC(ide_controller_device::cs1_w)); - map(0x03f8, 0x03ff).noprw(); // To debug Serial Port COM1: - map(0x0a78, 0x0a7b).nopw();//.w(FUNC(voyager_state::pnp_data_w)); - map(0x0cf8, 0x0cff).rw("pcibus", FUNC(pci_bus_legacy_device::read), FUNC(pci_bus_legacy_device::write)); - map(0x42e8, 0x43ef).noprw(); //To debug - map(0x43c0, 0x43cf).ram().share("share1"); - map(0x46e8, 0x46ef).noprw(); //To debug - map(0x4ae8, 0x4aef).noprw(); //To debug - map(0x83c0, 0x83cf).ram().share("share1"); - map(0x92e8, 0x92ef).noprw(); //To debug - + map(0x000e0000, 0x000fffff).rom().region("bios", 0x20000); + map(0xfffc0000, 0xffffffff).rom().region("bios", 0); } - - static INPUT_PORTS_START( voyager ) - PORT_START("IOCARD1") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_COIN1 ) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_COIN2 ) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_START1 ) - PORT_DIPNAME( 0x0008, 0x0008, "1" ) - PORT_DIPSETTING( 0x0008, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0010, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Accelerator") - PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0080, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_START("IOCARD2") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_SERVICE1 ) // guess - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_SERVICE2 ) PORT_NAME("Reset SW") - PORT_DIPNAME( 0x0004, 0x0004, "2" ) - PORT_DIPSETTING( 0x0004, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0008, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0010, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Turbo") - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNKNOWN ) // returns back to MS-DOS (likely to be unmapped and actually used as a lame protection check) - PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_START("IOCARD3") - PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_VBLANK("screen") - PORT_BIT( 0xdfff, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("IOCARD4") - PORT_DIPNAME( 0x01, 0x01, "DSWA" ) - PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x0100, 0x0100, "DSWA" ) - PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0200, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0400, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0800, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x1000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x2000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_START("IOCARD5") - PORT_DIPNAME( 0x01, 0x01, "DSWA" ) - PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x0100, 0x0100, "DSWA" ) - PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0200, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0400, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0800, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x1000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x2000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) INPUT_PORTS_END -void voyager_state::machine_start() -{ - m_nvram_data = std::make_unique(0x800); - subdevice("nvram")->set_base(m_nvram_data.get(), 0x800); -} - -void voyager_state::machine_reset() -{ - //membank("bank1")->set_base(memregion("bios")->base() + 0x10000); - membank("bank1")->set_base(memregion("bios")->base()); -} - void voyager_state::voyager(machine_config &config) { PENTIUM3(config, m_maincpu, 133000000); // actually AMD Duron CPU of unknown clock m_maincpu->set_addrmap(AS_PROGRAM, &voyager_state::voyager_map); - m_maincpu->set_addrmap(AS_IO, &voyager_state::voyager_io); - m_maincpu->set_irq_acknowledge_callback("pic8259_1", FUNC(pic8259_device::inta_cb)); - - pcat_common(config); - - ide_controller_device &ide(IDE_CONTROLLER(config, "ide").options(ata_devices, "hdd", nullptr, true)); - ide.irq_handler().set("pic8259_2", FUNC(pic8259_device::ir6_w)); - - pci_bus_legacy_device &pcibus(PCI_BUS_LEGACY(config, "pcibus", 0, 0)); - pcibus.set_device(0, FUNC(voyager_state::intel82439tx_pci_r), FUNC(voyager_state::intel82439tx_pci_w)); - pcibus.set_device(7, FUNC(voyager_state::intel82371ab_pci_r), FUNC(voyager_state::intel82371ab_pci_w)); +// m_maincpu->set_addrmap(AS_IO, &voyager_state::voyager_io); +// m_maincpu->set_irq_acknowledge_callback("pic8259_1", FUNC(pic8259_device::inta_cb)); - NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); - - /* video hardware */ - pcvideo_trident_vga(config); - - /* sound hardware */ - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); -} - -void voyager_state::init_voyager() -{ - m_bios_ram = std::make_unique(0x20000/4); - - intel82439tx_init(); + PCI_ROOT(config, "pci", 0); + // ... } // unknown version and cabinet style, but believed to be the deluxe sit-down. @@ -519,10 +78,6 @@ ROM_START( voyager ) ROM_REGION32_LE( 0x40000, "bios", 0 ) ROM_LOAD( "stv.u23", 0x000000, 0x040000, CRC(0bed28b6) SHA1(8e7f17af65ca9d17c5c7ddedb2313507d0ea8181) ) - ROM_REGION32_LE( 0x8000, "video_bios", 0 ) // incorrect, need GeForce 2MX BIOS for 32MB card - ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, CRC(1eebde64) BAD_DUMP SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) - ROM_CONTINUE( 0x0001, 0x4000 ) - ROM_REGION( 0x800, "nvram", ROMREGION_ERASE00 ) DISK_REGION( "ide:0:hdd" ) @@ -534,10 +89,6 @@ ROM_START( voyagers ) ROM_REGION32_LE( 0x40000, "bios", 0 ) ROM_LOAD( "stv.u23", 0x000000, 0x040000, CRC(0bed28b6) SHA1(8e7f17af65ca9d17c5c7ddedb2313507d0ea8181) ) - ROM_REGION32_LE( 0x8000, "video_bios", 0 ) // incorrect, need GeForce 2MX BIOS for 32MB card - ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, CRC(1eebde64) BAD_DUMP SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) - ROM_CONTINUE( 0x0001, 0x4000 ) - ROM_REGION( 0x800, "nvram", ROMREGION_ERASE00 ) DISK_REGION( "ide:0:hdd" ) @@ -548,10 +99,6 @@ ROM_START( policet2 ) ROM_REGION32_LE( 0x40000, "bios", 0 ) ROM_LOAD( "pm29f002t.u22", 0x000000, 0x040000, CRC(eb32ace6) SHA1(1b1eeb07e20822c690d05959077c7ddcc22d1708) ) - ROM_REGION32_LE( 0x8000, "video_bios", 0 ) // incorrect, need GeForce 2MX BIOS for 32MB card - ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, CRC(1eebde64) BAD_DUMP SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) - ROM_CONTINUE( 0x0001, 0x4000 ) - ROM_REGION( 0x800, "nvram", ROMREGION_ERASE00 ) DISK_REGION( "ide:0:hdd" ) @@ -560,6 +107,6 @@ ROM_END } // anonymous namespace -GAME( 2002, voyager, 0, voyager, voyager, voyager_state, init_voyager, ROT0, "Team Play/Game Refuge/Monaco Entertainment", "Star Trek: Voyager", MACHINE_NOT_WORKING|MACHINE_NO_SOUND ) -GAME( 2002, voyagers, voyager, voyager, voyager, voyager_state, init_voyager, ROT0, "Team Play/Game Refuge/Monaco Entertainment", "Star Trek: Voyager (stand-up version 1.002)", MACHINE_NOT_WORKING|MACHINE_NO_SOUND ) -GAME( 2003, policet2, 0, voyager, voyager, voyager_state, init_voyager, ROT0, "Team Play/Phantom Entertainment", "Police Trainer 2", MACHINE_NOT_WORKING|MACHINE_NO_SOUND ) +GAME( 2002, voyager, 0, voyager, voyager, voyager_state, empty_init, ROT0, "Team Play/Game Refuge/Monaco Entertainment", "Star Trek: Voyager", MACHINE_NOT_WORKING|MACHINE_NO_SOUND ) +GAME( 2002, voyagers, voyager, voyager, voyager, voyager_state, empty_init, ROT0, "Team Play/Game Refuge/Monaco Entertainment", "Star Trek: Voyager (stand-up version 1.002)", MACHINE_NOT_WORKING|MACHINE_NO_SOUND ) +GAME( 2003, policet2, 0, voyager, voyager, voyager_state, empty_init, ROT0, "Team Play/Phantom Entertainment", "Police Trainer 2", MACHINE_NOT_WORKING|MACHINE_NO_SOUND ) diff --git a/src/mame/pc/at.cpp b/src/mame/pc/at.cpp index d1395be79e0..14bab36586f 100644 --- a/src/mame/pc/at.cpp +++ b/src/mame/pc/at.cpp @@ -623,7 +623,8 @@ void at_state::at386(machine_config &config) NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // on-board devices - ISA16_SLOT(config, "board1", 0, "mb:isabus", pc_isa16_cards, "fdcsmc", true); // FIXME: deteremine ISA bus clock + // FIXME: determine ISA bus clock + ISA16_SLOT(config, "board1", 0, "mb:isabus", pc_isa16_cards, "fdcsmc", true); ISA16_SLOT(config, "board2", 0, "mb:isabus", pc_isa16_cards, "comat", true); ISA16_SLOT(config, "board3", 0, "mb:isabus", pc_isa16_cards, "ide", true); ISA16_SLOT(config, "board4", 0, "mb:isabus", pc_isa16_cards, "lpt", true); diff --git a/src/mame/pc/calchase.cpp b/src/mame/pc/calchase.cpp index 23f3364d674..2efff9c678a 100644 --- a/src/mame/pc/calchase.cpp +++ b/src/mame/pc/calchase.cpp @@ -23,15 +23,7 @@ TODO: - Various graphics bugs (title screen uses ROZ?); - fix 129 Hz refresh rate bug; - inputs (is there a service mode?) - -I/O Memo (http://bochs.sourceforge.net/techspec/PORTS.LST): -46E8 ---- 8514/A and compatible video cards (e.g. ATI Graphics Ultra) -46E8 w ROM page select -83C0-83CF ---- Compaq QVision - Line Draw Engine -83C4 ---- Compaq Qvision EISA - Virtual Controller Select -83C6-83C9 ---- Compaq Qvision EISA - DAC color registers - -43c4 is a 83c4 mirror? +- hostinv: is an El Torito CD-ROM, can't boot here until PCI section is rewritten; ===================================================================================== @@ -122,8 +114,6 @@ compatible with chipset VIA. something wrong in the disk geometry reported by calchase.chd (20,255,63) since BIOS does not accept 255 heads as parameter. Perhaps a bad dump? - TODO: A lot of work to do yet!!! - - update by peter ferrie: - corrected memory map to 64kb blocks - corrected access to PAM register @@ -134,7 +124,8 @@ something wrong in the disk geometry reported by calchase.chd (20,255,63) since #include "pcshare.h" -#include "bus/isa/trident.h" +#include "bus/isa/isa.h" +#include "bus/isa/svga_trident.h" #include "cpu/i386/i386.h" #include "machine/lpci.h" #include "machine/pckeybrd.h" @@ -148,6 +139,266 @@ something wrong in the disk geometry reported by calchase.chd (20,255,63) since #include "speaker.h" +class isa16_calchase_jamma_if : public device_t, public device_isa16_card_interface +{ +public: + // construction/destruction + isa16_calchase_jamma_if(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + virtual ioport_constructor device_input_ports() const override; + + DECLARE_CUSTOM_INPUT_MEMBER( heartbeat_r ); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + virtual void device_add_mconfig(machine_config &config) override; + +private: + required_ioport_array<5> m_iocard; + std::unique_ptr m_nvram_data; + TIMER_CALLBACK_MEMBER(heartbeat_cb); + emu_timer *m_hb_timer = nullptr; + bool m_hb_state = false; + + void io_map(address_map &map); + + template uint16_t iocard_r(); + uint8_t nvram_r(offs_t offset); + void nvram_w(offs_t offset, uint8_t data); +}; + +DEFINE_DEVICE_TYPE(ISA16_CALCHASE_JAMMA_IF, isa16_calchase_jamma_if, "calchase_jamma_if", "ISA16 AUSCOM System 1 custom JAMMA I/F") + +isa16_calchase_jamma_if::isa16_calchase_jamma_if(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, ISA16_CALCHASE_JAMMA_IF, tag, owner, clock) + , device_isa16_card_interface(mconfig, *this) + , m_iocard(*this, "IOCARD%u", 1U) +{ +} + +void isa16_calchase_jamma_if::device_add_mconfig(machine_config &config) +{ + NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // DS1220Y + + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + DAC_12BIT_R2R(config, "ldac", 0).add_route(ALL_OUTPUTS, "lspeaker", 0.25); // unknown DAC + DAC_12BIT_R2R(config, "rdac", 0).add_route(ALL_OUTPUTS, "rspeaker", 0.25); // unknown DAC +} + +void isa16_calchase_jamma_if::device_start() +{ + set_isa_device(); + + m_nvram_data = std::make_unique(0x800); + subdevice("nvram")->set_base(m_nvram_data.get(), 0x800); + + m_hb_timer = timer_alloc(FUNC(isa16_calchase_jamma_if::heartbeat_cb), this); + + m_isa->install_memory(0x000d0000, 0x000d0fff, *this, &isa16_calchase_jamma_if::io_map); +} + +void isa16_calchase_jamma_if::device_reset() +{ + // TODO: timing and actual source + m_hb_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60)); +} + +template +uint16_t isa16_calchase_jamma_if::iocard_r() +{ + return m_iocard[N]->read(); +} + +uint8_t isa16_calchase_jamma_if::nvram_r(offs_t offset) +{ + return m_nvram_data[offset]; +} + +void isa16_calchase_jamma_if::nvram_w(offs_t offset, uint8_t data) +{ + m_nvram_data[offset] = data; +} + +void isa16_calchase_jamma_if::io_map(address_map &map) +{ +// map(0x0000, 0x0003).ram(); // XYLINX - Sincronus serial communication + map(0x0004, 0x0005).r(FUNC(isa16_calchase_jamma_if::iocard_r<0>)); + map(0x0008, 0x000b).nopw(); // ??? + map(0x000c, 0x000d).r(FUNC(isa16_calchase_jamma_if::iocard_r<1>)); + map(0x0024, 0x0025).w("ldac", FUNC(dac_word_interface::data_w)); + map(0x0028, 0x0029).w("rdac", FUNC(dac_word_interface::data_w)); + map(0x0032, 0x0033).r(FUNC(isa16_calchase_jamma_if::iocard_r<2>)); + map(0x0030, 0x0031).r(FUNC(isa16_calchase_jamma_if::iocard_r<3>)); // These two controls wheel pot or whatever this game uses ... + map(0x0034, 0x0035).r(FUNC(isa16_calchase_jamma_if::iocard_r<4>)); + map(0x0800, 0x0fff).rw(FUNC(isa16_calchase_jamma_if::nvram_r), FUNC(isa16_calchase_jamma_if::nvram_w)); // GAME_CMOS +} + +// bit 13 of IOCARD3 needs to be flipped back and forth for logic to update +// (causing an hang if this is either one of the two states). +// This is either mirrored from PCI VGA card itself (unlikely) or it runs on its own free running timer. +// Also cfr. ice/lethalj.cpp franticf, where they run an analog steering wheel thru a serial pot and an irq +// (which is probably reused here) +TIMER_CALLBACK_MEMBER(isa16_calchase_jamma_if::heartbeat_cb) +{ + m_hb_state ^= 1; +} + +CUSTOM_INPUT_MEMBER(isa16_calchase_jamma_if::heartbeat_r) +{ + return m_hb_state; +} + +static INPUT_PORTS_START( calchase_jamma ) + PORT_START("IOCARD1") + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_START1 ) + PORT_DIPNAME( 0x0008, 0x0008, "1" ) + PORT_DIPSETTING( 0x0008, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0010, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Accelerator") + PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0080, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("IOCARD2") + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_SERVICE1 ) // guess + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_SERVICE2 ) PORT_NAME("Reset SW") + PORT_DIPNAME( 0x0004, 0x0004, "2" ) + PORT_DIPSETTING( 0x0004, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0008, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0010, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Turbo") + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNKNOWN ) // returns back to MS-DOS (likely to be unmapped and actually used as a lame protection check) + PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("IOCARD3") +// PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_VBLANK("isa2:tgui9680:screen") + PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(isa16_calchase_jamma_if, heartbeat_r) + PORT_BIT( 0xdfff, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("IOCARD4") + PORT_DIPNAME( 0x01, 0x01, "DSWA" ) + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x0100, 0x0100, "DSWA" ) + PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0200, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0400, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0800, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x1000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) +// PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_VBLANK("isa2:tgui9680:screen") // eggsplc + PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(isa16_calchase_jamma_if, heartbeat_r) + PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + + PORT_START("IOCARD5") + PORT_DIPNAME( 0x01, 0x01, "DSWA" ) + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x0100, 0x0100, "DSWA" ) + PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0200, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0400, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0800, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x1000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x2000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) +INPUT_PORTS_END + +ioport_constructor isa16_calchase_jamma_if::device_input_ports() const +{ + return INPUT_PORTS_NAME(calchase_jamma); +} + namespace { class calchase_state : public pcat_base_state @@ -155,7 +406,6 @@ class calchase_state : public pcat_base_state public: calchase_state(const machine_config &mconfig, device_type type, const char *tag) : pcat_base_state(mconfig, type, tag) - , m_iocard(*this, "IOCARD%u", 1U) { } @@ -169,21 +419,13 @@ protected: virtual void machine_reset() override; private: - required_ioport_array<5> m_iocard; std::unique_ptr m_bios_ram; std::unique_ptr m_bios_ext_ram; - std::unique_ptr m_nvram_data; uint8_t m_mtxc_config_reg[256]{}; uint8_t m_piix4_config_reg[4][256]{}; - uint32_t m_idle_skip_ram = 0; void bios_ext_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); void bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint8_t nvram_r(offs_t offset); - void nvram_w(offs_t offset, uint8_t data); - template uint16_t iocard_r(); - uint32_t calchase_idle_skip_r(); - void calchase_idle_skip_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); void intel82439tx_init(); void calchase_io(address_map &map); @@ -371,233 +613,35 @@ void calchase_state::bios_ext_ram_w(offs_t offset, uint32_t data, uint32_t mem_m } } -uint8_t calchase_state::nvram_r(offs_t offset) -{ - return m_nvram_data[offset]; -} - -void calchase_state::nvram_w(offs_t offset, uint8_t data) -{ - m_nvram_data[offset] = data; -} - -template -uint16_t calchase_state::iocard_r() -{ - return m_iocard[N]->read(); -} - - void calchase_state::calchase_map(address_map &map) { map(0x00000000, 0x0009ffff).ram(); - map(0x000a0000, 0x000bffff).rw("vga", FUNC(trident_vga_device::mem_r), FUNC(trident_vga_device::mem_w)); // VGA VRAM - map(0x000c0000, 0x000c7fff).rom().region("video_bios", 0); - map(0x000c8000, 0x000cffff).noprw(); - //map(0x000d0000, 0x000d0003).ram(); // XYLINX - Sincronus serial communication - map(0x000d0004, 0x000d0005).r(FUNC(calchase_state::iocard_r<0>)); - map(0x000d000c, 0x000d000d).r(FUNC(calchase_state::iocard_r<1>)); - map(0x000d0032, 0x000d0033).r(FUNC(calchase_state::iocard_r<2>)); - map(0x000d0030, 0x000d0031).r(FUNC(calchase_state::iocard_r<3>)); // These two controls wheel pot or whatever this game uses ... - map(0x000d0034, 0x000d0035).r(FUNC(calchase_state::iocard_r<4>)); - map(0x000d0008, 0x000d000b).nopw(); // ??? - map(0x000d0024, 0x000d0025).w("ldac", FUNC(dac_word_interface::data_w)); - map(0x000d0028, 0x000d0029).w("rdac", FUNC(dac_word_interface::data_w)); - map(0x000d0800, 0x000d0fff).rw(FUNC(calchase_state::nvram_r), FUNC(calchase_state::nvram_w)); // GAME_CMOS - +// map(0x000a0000, 0x000bffff).rw("vga", FUNC(trident_vga_device::mem_r), FUNC(trident_vga_device::mem_w)); // VGA VRAM +// map(0x000c0000, 0x000c7fff).rom().region("video_bios", 0); +// map(0x000c8000, 0x000cffff).noprw(); +// map(0x000d0000, 0x000d0fff) ISA custom JAMMA (above) map(0x000e0000, 0x000effff).bankr("bios_ext").w(FUNC(calchase_state::bios_ext_ram_w)); map(0x000f0000, 0x000fffff).bankr("bios_bank").w(FUNC(calchase_state::bios_ram_w)); map(0x00100000, 0x03ffffff).ram(); // 64MB map(0x04000000, 0x28ffffff).noprw(); - //map(0x04000000, 0x040001ff).ram(); - //map(0x08000000, 0x080001ff).ram(); - //map(0x0c000000, 0x0c0001ff).ram(); - //map(0x10000000, 0x100001ff).ram(); - //map(0x14000000, 0x140001ff).ram(); - //map(0x18000000, 0x180001ff).ram(); - //map(0x20000000, 0x200001ff).ram(); - //map(0x28000000, 0x280001ff).ram(); map(0xfffe0000, 0xffffffff).rom().region("bios", 0); /* System BIOS */ } void calchase_state::calchase_io(address_map &map) { pcat32_io_common(map); - //map(0x00e8, 0x00eb).noprw(); map(0x00e8, 0x00ef).noprw(); //AMI BIOS write to this ports as delays between I/O ports operations sending al value -> NEWIODELAY - map(0x0170, 0x0177).noprw(); //To debug +// map(0x0170, 0x0177).noprw(); //To debug map(0x01f0, 0x01f7).rw("ide", FUNC(ide_controller_32_device::cs0_r), FUNC(ide_controller_32_device::cs0_w)); - map(0x0200, 0x021f).noprw(); //To debug - map(0x0260, 0x026f).noprw(); //To debug - map(0x0278, 0x027b).nopw();//.w(FUNC(calchase_state::pnp_config_w)); - map(0x0280, 0x0287).noprw(); //To debug - map(0x02a0, 0x02a7).noprw(); //To debug - map(0x02c0, 0x02c7).noprw(); //To debug - map(0x02e0, 0x02ef).noprw(); //To debug - map(0x02f8, 0x02ff).noprw(); //To debug - map(0x0320, 0x038f).noprw(); //To debug - map(0x03a0, 0x03a7).noprw(); //To debug - map(0x03b0, 0x03bf).rw("vga", FUNC(trident_vga_device::port_03b0_r), FUNC(trident_vga_device::port_03b0_w)); - map(0x03c0, 0x03cf).rw("vga", FUNC(trident_vga_device::port_03c0_r), FUNC(trident_vga_device::port_03c0_w)); - map(0x03d0, 0x03df).rw("vga", FUNC(trident_vga_device::port_03d0_r), FUNC(trident_vga_device::port_03d0_w)); - map(0x03e0, 0x03ef).noprw(); //To debug - map(0x0378, 0x037f).noprw(); //To debug - // map(0x0300, 0x03af).noprw(); - // map(0x03b0, 0x03df).noprw(); map(0x03f0, 0x03f7).rw("ide", FUNC(ide_controller_32_device::cs1_r), FUNC(ide_controller_32_device::cs1_w)); - map(0x03f8, 0x03ff).noprw(); // To debug Serial Port COM1: - map(0x0a78, 0x0a7b).nopw();//.w(FUNC(calchase_state::pnp_data_w)); +// map(0x03f8, 0x03ff).noprw(); // To debug Serial Port COM1: +// map(0x0a78, 0x0a7b).nopw();//.w(FUNC(calchase_state::pnp_data_w)); map(0x0cf8, 0x0cff).rw("pcibus", FUNC(pci_bus_legacy_device::read), FUNC(pci_bus_legacy_device::write)); - map(0x42e8, 0x43ef).noprw(); //To debug - map(0x43c4, 0x43cb).rw("vga", FUNC(trident_vga_device::port_43c6_r), FUNC(trident_vga_device::port_43c6_w)); // Trident Memory and Video Clock register - map(0x46e8, 0x46ef).noprw(); //To debug - map(0x4ae8, 0x4aef).noprw(); //To debug - map(0x83c4, 0x83cb).rw("vga", FUNC(trident_vga_device::port_83c6_r), FUNC(trident_vga_device::port_83c6_w)); // Trident LUTDAC - map(0x92e8, 0x92ef).noprw(); //To debug +// map(0x43c4, 0x43cb).rw("vga", FUNC(trident_vga_device::port_43c6_r), FUNC(trident_vga_device::port_43c6_w)); // Trident Memory and Video Clock register +// map(0x83c4, 0x83cb).rw("vga", FUNC(trident_vga_device::port_83c6_r), FUNC(trident_vga_device::port_83c6_w)); // Trident LUTDAC } - - static INPUT_PORTS_START( calchase ) - PORT_START("IOCARD1") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_COIN1 ) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_COIN2 ) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_START1 ) - PORT_DIPNAME( 0x0008, 0x0008, "1" ) - PORT_DIPSETTING( 0x0008, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0010, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Accelerator") - PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0080, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("IOCARD2") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_SERVICE1 ) // guess - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_SERVICE2 ) PORT_NAME("Reset SW") - PORT_DIPNAME( 0x0004, 0x0004, "2" ) - PORT_DIPSETTING( 0x0004, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0008, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0010, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Turbo") - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNKNOWN ) // returns back to MS-DOS (likely to be unmapped and actually used as a lame protection check) - PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("IOCARD3") - PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_VBLANK("screen") - PORT_BIT( 0xdfff, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("IOCARD4") - PORT_DIPNAME( 0x01, 0x01, "DSWA" ) - PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x0100, 0x0100, "DSWA" ) - PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0200, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0400, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0800, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x1000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_VBLANK("screen") //eggsplc - PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - - PORT_START("IOCARD5") - PORT_DIPNAME( 0x01, 0x01, "DSWA" ) - PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x0100, 0x0100, "DSWA" ) - PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0200, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0400, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0800, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x1000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x2000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) INPUT_PORTS_END void calchase_state::machine_start() @@ -605,9 +649,6 @@ void calchase_state::machine_start() m_bios_ram = std::make_unique(0x10000/4); m_bios_ext_ram = std::make_unique(0x10000/4); - m_nvram_data = std::make_unique(0x800); - subdevice("nvram")->set_base(m_nvram_data.get(), 0x800); - for (int i = 0; i < 4; i++) std::fill(std::begin(m_piix4_config_reg[i]), std::end(m_piix4_config_reg[i]), 0); } @@ -619,6 +660,12 @@ void calchase_state::machine_reset() membank("bios_ext")->set_base(memregion("bios")->base() + 0); } +void calchase_isa16_cards(device_slot_interface &device) +{ + device.option_add("calchase_jamma_if", ISA16_CALCHASE_JAMMA_IF); + device.option_add("tgui9680", ISA16_SVGA_TGUI9680); +} + void calchase_state::calchase(machine_config &config) { PENTIUM(config, m_maincpu, 133000000); // Cyrix 686MX-PR200 CPU @@ -635,20 +682,18 @@ void calchase_state::calchase(machine_config &config) pcibus.set_device(0, FUNC(calchase_state::intel82439tx_pci_r), FUNC(calchase_state::intel82439tx_pci_w)); pcibus.set_device(7, FUNC(calchase_state::intel82371ab_pci_r), FUNC(calchase_state::intel82371ab_pci_w)); - NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // DS1220Y - - /* video hardware */ - pcvideo_trident_vga(config); + // FIXME: determine ISA bus clock + isa16_device &isa(ISA16(config, "isa", 0)); + isa.set_memspace("maincpu", AS_PROGRAM); + isa.set_iospace("maincpu", AS_IO); + ISA16_SLOT(config, "isa1", 0, "isa", calchase_isa16_cards, "calchase_jamma_if", true); + // TODO: temp, to be converted to PCI slot + ISA16_SLOT(config, "isa2", 0, "isa", calchase_isa16_cards, "tgui9680", true); ds12885_device &rtc(DS12885(config.replace(), "rtc")); rtc.irq().set("pic8259_2", FUNC(pic8259_device::ir0_w)); rtc.set_century_index(0x32); - /* sound hardware */ - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - DAC_12BIT_R2R(config, "ldac", 0).add_route(ALL_OUTPUTS, "lspeaker", 0.25); // unknown DAC - DAC_12BIT_R2R(config, "rdac", 0).add_route(ALL_OUTPUTS, "rspeaker", 0.25); // unknown DAC } void calchase_state::hostinv(machine_config &config) @@ -667,10 +712,13 @@ void calchase_state::hostinv(machine_config &config) pcibus.set_device(0, FUNC(calchase_state::intel82439tx_pci_r), FUNC(calchase_state::intel82439tx_pci_w)); pcibus.set_device(7, FUNC(calchase_state::intel82371ab_pci_r), FUNC(calchase_state::intel82371ab_pci_w)); - NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // DS1220Y - - /* video hardware */ - pcvideo_trident_vga(config); + // TODO: determine isa bus clock + isa16_device &isa(ISA16(config, "isa", 0)); + isa.set_memspace("maincpu", AS_PROGRAM); + isa.set_iospace("maincpu", AS_IO); + ISA16_SLOT(config, "isa1", 0, "isa", calchase_isa16_cards, "calchase_jamma_if", true); + // TODO: temp, to be converted to PCI slot + ISA16_SLOT(config, "isa2", 0, "isa", calchase_isa16_cards, "tgui9680", true); /* sound hardware */ SPEAKER(config, "lspeaker").front_left(); @@ -679,28 +727,11 @@ void calchase_state::hostinv(machine_config &config) DAC_12BIT_R2R(config, "rdac", 0).add_route(ALL_OUTPUTS, "rspeaker", 0.25); // unknown DAC } - -uint32_t calchase_state::calchase_idle_skip_r() -{ - if(m_maincpu->pc()==0x1406f48) - m_maincpu->spin_until_interrupt(); - - return m_idle_skip_ram; -} - -void calchase_state::calchase_idle_skip_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_idle_skip_ram); -} - void calchase_state::init_calchase() { m_bios_ram = std::make_unique(0x20000/4); intel82439tx_init(); - - m_maincpu->space(AS_PROGRAM).install_read_handler(0x3f0b160, 0x3f0b163, read32smo_delegate(*this, FUNC(calchase_state::calchase_idle_skip_r))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0x3f0b160, 0x3f0b163, write32s_delegate(*this, FUNC(calchase_state::calchase_idle_skip_w))); } void calchase_state::init_hostinv() @@ -714,26 +745,18 @@ ROM_START( calchase ) ROM_REGION32_LE( 0x40000, "bios", 0 ) ROM_LOAD( "mb_bios.bin", 0x00000, 0x20000, CRC(dea7a51b) SHA1(e2028c00bfa6d12959fc88866baca8b06a1eab68) ) - ROM_REGION32_LE( 0x8000, "video_bios", 0 ) - ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, CRC(1eebde64) SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) - ROM_CONTINUE( 0x0001, 0x4000 ) - - ROM_REGION( 0x800, "nvram", 0 ) + ROM_REGION( 0x800, "isa1:calchase_jamma_if:nvram", 0 ) ROM_LOAD( "ds1220y_nv.bin", 0x000, 0x800, CRC(7912c070) SHA1(b4c55c7ca76bcd8dad1c4b50297233349ae02ed3) ) DISK_REGION( "ide:0:hdd" ) - DISK_IMAGE_READONLY( "calchase", 0,BAD_DUMP SHA1(6ae51a9b3f31cf4166322328a98c0235b0874eb3) ) + DISK_IMAGE_READONLY( "calchase", 0, BAD_DUMP SHA1(6ae51a9b3f31cf4166322328a98c0235b0874eb3) ) ROM_END ROM_START( hostinv ) ROM_REGION32_LE( 0x40000, "bios", 0 ) ROM_LOAD( "hostinv_bios.bin", 0x000000, 0x020000, CRC(5111e4b8) SHA1(20ab93150b61fd068f269368450734bba5dcb284) ) - ROM_REGION32_LE( 0x8000, "video_bios", 0 ) - ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, CRC(1eebde64) SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) - ROM_CONTINUE( 0x0001, 0x4000 ) - - ROM_REGION( 0x800, "nvram", ROMREGION_ERASEFF ) + ROM_REGION( 0x800, "isa1:calchase_jamma_if:nvram", ROMREGION_ERASEFF ) ROM_LOAD( "ds1220y_hostinv.bin", 0x000, 0x800, NO_DUMP ) DISK_REGION( "ide:0:cdrom" ) @@ -744,11 +767,7 @@ ROM_START( eggsplc ) ROM_REGION32_LE( 0x40000, "bios", 0 ) ROM_LOAD( "hostinv_bios.bin", 0x000000, 0x020000, CRC(5111e4b8) SHA1(20ab93150b61fd068f269368450734bba5dcb284) ) - ROM_REGION32_LE( 0x8000, "video_bios", 0 ) - ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, CRC(1eebde64) SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) - ROM_CONTINUE( 0x0001, 0x4000 ) - - ROM_REGION( 0x800, "nvram", ROMREGION_ERASEFF ) + ROM_REGION( 0x800, "isa1:calchase_jamma_if:nvram", ROMREGION_ERASEFF ) ROM_LOAD( "ds1220y_eggsplc.bin", 0x000, 0x800, NO_DUMP ) DISK_REGION( "ide:0:hdd" ) diff --git a/src/mame/pc/fruitpc.cpp b/src/mame/pc/fruitpc.cpp index acbd8a96d70..639f077233a 100644 --- a/src/mame/pc/fruitpc.cpp +++ b/src/mame/pc/fruitpc.cpp @@ -140,7 +140,14 @@ void fruitpc_state::fruitpc(machine_config &config) ide.irq_handler().set("pic8259_2", FUNC(pic8259_device::ir6_w)); /* video hardware */ - pcvideo_vga(config); + // TODO: custom 1998 Elpin Systems/STMicroeletronics BIOS internal to the SoC, likely PCI + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); + screen.set_screen_update("vga", FUNC(vga_device::screen_update)); + + vga_device &vga(VGA(config, "vga", 0)); + vga.set_screen("screen"); + vga.set_vram_size(0x100000); m_dma8237_1->out_iow_callback<1>().set(FUNC(fruitpc_state::dma8237_1_dack_w)); diff --git a/src/mame/pc/igspc.cpp b/src/mame/pc/igspc.cpp index 0957c4d8eab..30b30ae77cb 100644 --- a/src/mame/pc/igspc.cpp +++ b/src/mame/pc/igspc.cpp @@ -54,8 +54,8 @@ class speeddrv_state : public driver_device { public: speeddrv_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu") + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") { } void speeddrv(machine_config &config); diff --git a/src/mame/pc/pangofun.cpp b/src/mame/pc/pangofun.cpp index 3dfaf4e9843..17e6c547282 100644 --- a/src/mame/pc/pangofun.cpp +++ b/src/mame/pc/pangofun.cpp @@ -163,7 +163,14 @@ void pangofun_state::pangofun(machine_config &config) m_maincpu->set_irq_acknowledge_callback("pic8259_1", FUNC(pic8259_device::inta_cb)); /* video hardware */ - pcvideo_vga(config); + // TODO: map to ISA bus, CLGD5401 + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); + screen.set_screen_update("vga", FUNC(vga_device::screen_update)); + + vga_device &vga(VGA(config, "vga", 0)); + vga.set_screen("screen"); + vga.set_vram_size(0x100000); pcat_common(config); diff --git a/src/mame/pc/paokaipc.cpp b/src/mame/pc/paokaipc.cpp index b9170b49e51..487d0ec765b 100644 --- a/src/mame/pc/paokaipc.cpp +++ b/src/mame/pc/paokaipc.cpp @@ -9,16 +9,12 @@ Some kind of x86 pc-like hardware, exact CPU type etc. unknown hardware is by Paokai, motherboard has logos, large chip with logo too, http://www.paokai.com.tw/ - CF card has a Linux partition, partially bootable with m55hipl driver. - - starts with a "LILO boot", fails with a recoverable "undefined video mode" - (press RETURN or SPACE); + CF card has a Linux partition, partially bootable with shutms11 driver. + - starts with a "LILO boot", loads a proprietary driver TWDrv.o (?) then eventually + crashes not finding sound modules; - Shows being a "gcc 3.2.2 (Red Hat Linux 3.2.2-5)" distro. Notice that latter seems mislabeled, and RedHat is actually version 9 http://rpm.pbone.net/info_idpl_19558085_distro_redhat9_com_gcc-3.2.2-5.i386.rpm.html - - Has pretty verbose terminal log, checks PnP, USB, Pentium f0 0f bug, - assumes "33 MHz system bus" for IDE PIO mode, returns PIIX only during PCI scan - (that's what m55hipl has as default); - - Eventually hangs at a "Setting the clock:" prompt; **************************************************************************************************/ @@ -32,7 +28,6 @@ #include "machine/idectrl.h" #include "machine/pci.h" #include "machine/pckeybrd.h" -#include "video/pc_vga.h" namespace { @@ -58,7 +53,7 @@ private: void paokaipc_state::main_map(address_map &map) { map(0x00000000, 0x0009ffff).ram(); - map(0x000a0000, 0x000bffff).rw("vga", FUNC(vga_device::mem_r), FUNC(vga_device::mem_w)); // VGA VRAM +// map(0x000a0000, 0x000bffff).rw("vga", FUNC(vga_device::mem_r), FUNC(vga_device::mem_w)); // VGA VRAM map(0x000e0000, 0x000fffff).rom().region("bios", 0x20000); map(0x00100000, 0x008fffff).ram(); map(0x02000000, 0x28ffffff).noprw(); @@ -69,9 +64,9 @@ void paokaipc_state::main_io(address_map &map) { pcat32_io_common(map); map(0x01f0, 0x01f7).rw("ide", FUNC(ide_controller_device::cs0_r), FUNC(ide_controller_device::cs0_w)); - map(0x03b0, 0x03bf).rw("vga", FUNC(vga_device::port_03b0_r), FUNC(vga_device::port_03b0_w)); - map(0x03c0, 0x03cf).rw("vga", FUNC(vga_device::port_03c0_r), FUNC(vga_device::port_03c0_w)); - map(0x03d0, 0x03df).rw("vga", FUNC(vga_device::port_03d0_r), FUNC(vga_device::port_03d0_w)); +// map(0x03b0, 0x03bf).rw("vga", FUNC(vga_device::port_03b0_r), FUNC(vga_device::port_03b0_w)); +// map(0x03c0, 0x03cf).rw("vga", FUNC(vga_device::port_03c0_r), FUNC(vga_device::port_03c0_w)); +// map(0x03d0, 0x03df).rw("vga", FUNC(vga_device::port_03d0_r), FUNC(vga_device::port_03d0_w)); map(0x03f0, 0x03f7).rw("ide", FUNC(ide_controller_device::cs1_r), FUNC(ide_controller_device::cs1_w)); // map(0x0880, 0x0880) extensively accessed at POST, hangs if returns wrong values // map(0x0cf8, 0x0cff).rw(m_pcibus, FUNC(pci_bus_device::read), FUNC(pci_bus_device::write)); @@ -93,8 +88,6 @@ void paokaipc_state::paokaipc(machine_config &config) ide_controller_device &ide(IDE_CONTROLLER(config, "ide").options(ata_devices, "hdd", nullptr, true)); ide.irq_handler().set("pic8259_2", FUNC(pic8259_device::ir6_w)); - pcvideo_vga(config); - PCI_ROOT(config, m_pciroot, 0); // ... diff --git a/src/mame/pc/pcat_dyn.cpp b/src/mame/pc/pcat_dyn.cpp index 7958ef893fd..dc9817e699f 100644 --- a/src/mame/pc/pcat_dyn.cpp +++ b/src/mame/pc/pcat_dyn.cpp @@ -32,7 +32,7 @@ If the output isn't satisfactory, it prints "I/O BOARD FAILURE". #include "bus/isa/isa.h" #include "bus/isa/sblaster.h" -#include "bus/isa/trident.h" +#include "video/pc_vga_trident.h" #include "bus/rs232/hlemouse.h" #include "bus/rs232/rs232.h" @@ -103,7 +103,7 @@ void pcat_dyn_state::bank2_w(uint8_t data) void pcat_dyn_state::pcat_map(address_map &map) { map(0x00000000, 0x0009ffff).ram(); - map(0x000a0000, 0x000bffff).rw("vga", FUNC(trident_vga_device::mem_r), FUNC(trident_vga_device::mem_w)); + map(0x000a0000, 0x000bffff).rw("vga", FUNC(tvga9000_device::mem_r), FUNC(tvga9000_device::mem_w)); map(0x000c0000, 0x000c7fff).rom().region("video_bios", 0); map(0x000d0000, 0x000d0fff).rom().region("game_prg", 0x0000).w(FUNC(pcat_dyn_state::bank1_w)); map(0x000d1000, 0x000d1fff).rom().region("game_prg", 0x1000).w(FUNC(pcat_dyn_state::bank2_w)); @@ -118,9 +118,9 @@ void pcat_dyn_state::pcat_map(address_map &map) void pcat_dyn_state::pcat_io(address_map &map) { pcat32_io_common(map); - map(0x03b0, 0x03bf).rw("vga", FUNC(trident_vga_device::port_03b0_r), FUNC(trident_vga_device::port_03b0_w)); - map(0x03c0, 0x03cf).rw("vga", FUNC(trident_vga_device::port_03c0_r), FUNC(trident_vga_device::port_03c0_w)); - map(0x03d0, 0x03df).rw("vga", FUNC(trident_vga_device::port_03d0_r), FUNC(trident_vga_device::port_03d0_w)); + map(0x03b0, 0x03bf).rw("vga", FUNC(tvga9000_device::port_03b0_r), FUNC(tvga9000_device::port_03b0_w)); + map(0x03c0, 0x03cf).rw("vga", FUNC(tvga9000_device::port_03c0_r), FUNC(tvga9000_device::port_03c0_w)); + map(0x03d0, 0x03df).rw("vga", FUNC(tvga9000_device::port_03d0_r), FUNC(tvga9000_device::port_03d0_w)); map(0x03f8, 0x03ff).rw("ns16550", FUNC(ns16550_device::ins8250_r), FUNC(ns16550_device::ins8250_w)); map(0x0530, 0x0533).r(FUNC(pcat_dyn_state::audio_r)); map(0x0534, 0x0537).rw("ad1848", FUNC(ad1848_device::read), FUNC(ad1848_device::write)); @@ -172,9 +172,12 @@ void pcat_dyn_state::pcat_dyn(machine_config &config) m_maincpu->set_irq_acknowledge_callback("pic8259_1", FUNC(pic8259_device::inta_cb)); /* video hardware */ - pcvideo_trident_vga(config); - subdevice("screen")->set_refresh_hz(60); - tvga9000_device &vga(TVGA9000_VGA(config.replace(), "vga", 0)); + // TODO: map to ISA bus + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); + screen.set_screen_update("vga", FUNC(tvga9000_device::screen_update)); + + tvga9000_device &vga(TVGA9000_VGA(config, "vga", 0)); vga.set_screen("screen"); vga.set_vram_size(0x200000); diff --git a/src/mame/pc/pcat_nit.cpp b/src/mame/pc/pcat_nit.cpp index 3191f6ced78..ac24650b42f 100644 --- a/src/mame/pc/pcat_nit.cpp +++ b/src/mame/pc/pcat_nit.cpp @@ -255,7 +255,14 @@ void pcat_nit_state::pcat_nit(machine_config &config) m_maincpu->set_irq_acknowledge_callback("pic8259_1", FUNC(pic8259_device::inta_cb)); /* video hardware */ - pcvideo_vga(config); + // TODO: map to ISA bus, pinpoint what BIOS this refers to + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); + screen.set_screen_update("vga", FUNC(vga_device::screen_update)); + + vga_device &vga(VGA(config, "vga", 0)); + vga.set_screen("screen"); + vga.set_vram_size(0x100000); pcat_common(config); @@ -277,7 +284,14 @@ void pcat_nit_state::bonanza(machine_config &config) m_maincpu->set_irq_acknowledge_callback("pic8259_1", FUNC(pic8259_device::inta_cb)); /* video hardware */ - pcvideo_cirrus_gd5428(config); + // TODO: map to ISA bus + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); + screen.set_screen_update("vga", FUNC(cirrus_gd5428_device::screen_update)); + + cirrus_gd5428_device &vga(CIRRUS_GD5428(config, "vga", 0)); + vga.set_screen("screen"); + vga.set_vram_size(0x200000); pcat_common(config); ns16450_device &uart(NS16450(config, "ns16450_0", XTAL(1'843'200))); diff --git a/src/mame/pc/pcipc.cpp b/src/mame/pc/pcipc.cpp index 56511b545de..b1d564bd106 100644 --- a/src/mame/pc/pcipc.cpp +++ b/src/mame/pc/pcipc.cpp @@ -34,6 +34,7 @@ #include "machine/pci.h" #include "video/mga2064w.h" #include "video/virge_pci.h" +#include "video/riva128.h" namespace { @@ -52,6 +53,7 @@ public: void pcipc(machine_config &config); void pcipctx(machine_config &config); + void pcinv3(machine_config &config); pcipc_state(const machine_config &mconfig, device_type type, const char *tag); @@ -580,6 +582,12 @@ void pcipc_state::pcipctx(machine_config &config) MGA2064W(config, "pci:12.0", 0); } +void pcipc_state::pcinv3(machine_config &config) +{ + pcipc_state::pcipc(config); + RIVA128(config.replace(), "pci:12.0", 0); +} + ROM_START(pcipc) ROM_REGION32_LE(0x40000, "pci:07.0", 0) /* PC bios */ ROM_SYSTEM_BIOS(0, "m55ns04", "m55ns04") // Micronics M55HI-Plus with no sound @@ -603,11 +611,18 @@ ROM_START(pcipctx) ROM_LOAD("ibm-vga.bin", 0x00000, 0x8000, BAD_DUMP CRC(74e3fadb) SHA1(dce6491424f1726203776dfae9a967a98a4ba7b5) ) ROM_END +ROM_START(pcinv3) + ROM_REGION32_LE(0x40000, "pci:07.0", 0) /* PC bios */ + ROM_SYSTEM_BIOS(0, "m55ns04", "m55ns04") // Micronics M55HI-Plus with no sound + ROMX_LOAD("m55-04ns.rom", 0x20000, 0x20000, CRC(0116b2b0) SHA1(19b0203decfd4396695334517488d488aec3ccde), ROM_BIOS(0)) +ROM_END + static INPUT_PORTS_START(pcipc) INPUT_PORTS_END } // anonymous namespace -COMP(1998, pcipc, 0, 0, pcipc, pcipc, pcipc_state, empty_init, "Hack Inc.", "Sandbox PCI PC (430HX)", MACHINE_NO_SOUND) -COMP(1998, pcipctx, 0, 0, pcipctx, pcipc, pcipc_state, empty_init, "Hack Inc.", "Sandbox PCI PC (430TX)", MACHINE_NO_SOUND) +COMP(1998, pcipc, 0, 0, pcipc, pcipc, pcipc_state, empty_init, "Hack Inc.", "Sandbox PCI PC (430HX)", MACHINE_NO_SOUND) +COMP(1998, pcinv3, pcipc, 0, pcinv3,pcipc, pcipc_state, empty_init, "Hack Inc.", "Sandbox PCI PC (430HX with Riva 128)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) +COMP(1998, pcipctx, 0, 0, pcipctx, pcipc, pcipc_state, empty_init, "Hack Inc.", "Sandbox PCI PC (430TX)", MACHINE_NO_SOUND) diff --git a/src/mame/pc/queen.cpp b/src/mame/pc/queen.cpp index c3e28306564..1c60d045be7 100644 --- a/src/mame/pc/queen.cpp +++ b/src/mame/pc/queen.cpp @@ -33,7 +33,7 @@ processor speed is 533MHz <- likely to be a Celeron or a Pentium III class CPU - #include "machine/lpci.h" #include "machine/pckeybrd.h" #include "machine/idectrl.h" -#include "video/pc_vga.h" +//#include "video/pc_vga.h" namespace { @@ -244,7 +244,7 @@ void queen_state::bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask) void queen_state::queen_map(address_map &map) { map(0x00000000, 0x0009ffff).ram(); - map(0x000a0000, 0x000bffff).rw("vga", FUNC(vga_device::mem_r), FUNC(vga_device::mem_w)); +// map(0x000a0000, 0x000bffff).rw("vga", FUNC(vga_device::mem_r), FUNC(vga_device::mem_w)); map(0x000e0000, 0x000effff).bankr("bios_ext").w(FUNC(queen_state::bios_ext_ram_w)); map(0x000f0000, 0x000fffff).bankr("bios_bank").w(FUNC(queen_state::bios_ram_w)); map(0x00100000, 0x01ffffff).ram(); @@ -259,9 +259,9 @@ void queen_state::queen_io(address_map &map) map(0x0170, 0x0177).rw("ide2", FUNC(ide_controller_32_device::cs0_r), FUNC(ide_controller_32_device::cs0_w)); map(0x01f0, 0x01f7).rw("ide", FUNC(ide_controller_device::cs0_r), FUNC(ide_controller_device::cs0_w)); map(0x0370, 0x0377).rw("ide2", FUNC(ide_controller_32_device::cs1_r), FUNC(ide_controller_32_device::cs1_w)); - map(0x03b0, 0x03bf).rw("vga", FUNC(vga_device::port_03b0_r), FUNC(vga_device::port_03b0_w)); - map(0x03c0, 0x03cf).rw("vga", FUNC(vga_device::port_03c0_r), FUNC(vga_device::port_03c0_w)); - map(0x03d0, 0x03df).rw("vga", FUNC(vga_device::port_03d0_r), FUNC(vga_device::port_03d0_w)); +// map(0x03b0, 0x03bf).rw("vga", FUNC(vga_device::port_03b0_r), FUNC(vga_device::port_03b0_w)); +// map(0x03c0, 0x03cf).rw("vga", FUNC(vga_device::port_03c0_r), FUNC(vga_device::port_03c0_w)); +// map(0x03d0, 0x03df).rw("vga", FUNC(vga_device::port_03d0_r), FUNC(vga_device::port_03d0_w)); map(0x03f0, 0x03f7).rw("ide", FUNC(ide_controller_device::cs1_r), FUNC(ide_controller_device::cs1_w)); map(0x0cf8, 0x0cff).rw("pcibus", FUNC(pci_bus_legacy_device::read), FUNC(pci_bus_legacy_device::write)); @@ -299,9 +299,6 @@ void queen_state::queen(machine_config &config) ide_controller_32_device &ide2(IDE_CONTROLLER_32(config, "ide2").options(ata_devices, nullptr, nullptr, true)); ide2.irq_handler().set("pic8259_2", FUNC(pic8259_device::ir7_w)); - - /* video hardware */ - pcvideo_vga(config); } @@ -309,10 +306,6 @@ ROM_START( queen ) ROM_REGION32_LE( 0x40000, "bios", 0 ) ROM_LOAD( "bios-original.bin", 0x00000, 0x40000, CRC(feb542d4) SHA1(3cc5d8aeb0e3b7d9ed33248a4f3dc507d29debd9) ) - ROM_REGION( 0x8000, "video_bios", ROMREGION_ERASEFF ) // TODO: no VGA card is hooked up, to be removed -// ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, BAD_DUMP CRC(1eebde64) SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) -// ROM_CONTINUE( 0x0001, 0x4000 ) - DISK_REGION( "ide:0:hdd" ) DISK_IMAGE( "pqiidediskonmodule", 0,SHA1(a56efcc711b1c5a2e63160b3088001a8c4fb56c2) ) ROM_END diff --git a/src/mame/shared/pcshare.cpp b/src/mame/shared/pcshare.cpp index d9d977c10ef..c0816c20107 100644 --- a/src/mame/shared/pcshare.cpp +++ b/src/mame/shared/pcshare.cpp @@ -15,11 +15,8 @@ #include "emu.h" #include "pcshare.h" + #include "cpu/i86/i286.h" -#include "bus/isa/trident.h" -#include "video/pc_vga.h" -#include "video/clgd542x.h" -#include "screen.h" /****************** DMA8237 Controller @@ -140,65 +137,6 @@ void pcat_base_state::pcat32_io_common(address_map &map) map(0x00c0, 0x00df).rw(m_dma8237_2, FUNC(am9517a_device::read), FUNC(am9517a_device::write)).umask32(0x00ff00ff); } - -void pcat_base_state::pcvideo_vga(machine_config &config) -{ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); - screen.set_screen_update("vga", FUNC(vga_device::screen_update)); - - vga_device &vga(VGA(config, "vga", 0)); - vga.set_screen("screen"); - vga.set_vram_size(0x100000); -} - -void pcat_base_state::pcvideo_trident_vga(machine_config &config) -{ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); - screen.set_screen_update("vga", FUNC(trident_vga_device::screen_update)); - - trident_vga_device &vga(TRIDENT_VGA(config, "vga", 0)); - vga.set_screen("screen"); - vga.set_vram_size(0x200000); -} - -void pcat_base_state::pcvideo_s3_vga(machine_config &config) -{ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); - screen.set_screen_update("vga", FUNC(s3_vga_device::screen_update)); - - s3_vga_device &vga(S3_VGA(config, "vga", 0)); - vga.set_screen("screen"); - vga.set_vram_size(0x100000); -} - - -void pcat_base_state::pcvideo_cirrus_gd5428(machine_config &config) -{ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); - screen.set_screen_update("vga", FUNC(cirrus_gd5428_device::screen_update)); - - cirrus_gd5428_device &vga(CIRRUS_GD5428(config, "vga", 0)); - vga.set_screen("screen"); - vga.set_vram_size(0x200000); - -} - -void pcat_base_state::pcvideo_cirrus_gd5430(machine_config &config) -{ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480); - screen.set_screen_update("vga", FUNC(cirrus_gd5430_device::screen_update)); - - cirrus_gd5430_device &vga(CIRRUS_GD5430(config, "vga", 0)); - vga.set_screen("screen"); - vga.set_vram_size(0x200000); - -} - void pcat_base_state::pcat_common(machine_config &config) { PIC8259(config, m_pic8259_1, 0); diff --git a/src/mame/shared/pcshare.h b/src/mame/shared/pcshare.h index c8a8e440b14..0d618558c41 100644 --- a/src/mame/shared/pcshare.h +++ b/src/mame/shared/pcshare.h @@ -42,11 +42,6 @@ public: protected: void pcat_common(machine_config &config); - void pcvideo_vga(machine_config &config); - void pcvideo_trident_vga(machine_config &config); - void pcvideo_s3_vga(machine_config &config); - void pcvideo_cirrus_gd5428(machine_config &config); - void pcvideo_cirrus_gd5430(machine_config &config); void pcat32_io_common(address_map &map); diff --git a/src/mame/skeleton/indiana.cpp b/src/mame/skeleton/indiana.cpp index 5a624a097a5..09f251cea90 100644 --- a/src/mame/skeleton/indiana.cpp +++ b/src/mame/skeleton/indiana.cpp @@ -7,8 +7,6 @@ 08/12/2009 Skeleton driver. 01/20/2014 Added ISA bus and peripherals - TODO: Text appears in VGA f/b (0x6B8000), but doesn't display? - ****************************************************************************/ #include "emu.h" diff --git a/src/mame/taito/taitowlf.cpp b/src/mame/taito/taitowlf.cpp index 29dc6784e3e..79a040452ed 100644 --- a/src/mame/taito/taitowlf.cpp +++ b/src/mame/taito/taitowlf.cpp @@ -60,16 +60,11 @@ Taito W Rom Board: #include "emu.h" -#define TAITOWLF_ENABLE_VGA 0 - #include "pcshare.h" #include "cpu/i386/i386.h" #include "machine/lpci.h" #include "machine/pckeybrd.h" -#if TAITOWLF_ENABLE_VGA -#include "video/pc_vga.h" -#endif #include "emupal.h" #include "screen.h" @@ -102,9 +97,7 @@ private: void pnp_data_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); void bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); -#if !TAITOWLF_ENABLE_VGA void taitowlf_palette(palette_device &palette) const; -#endif uint32_t screen_update_taitowlf(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); void intel82439tx_init(); void taitowlf_io(address_map &map); @@ -124,7 +117,6 @@ private: uint8_t m_piix4_config_reg[4][256]; }; -#if !TAITOWLF_ENABLE_VGA uint32_t taitowlf_state::screen_update_taitowlf(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { bitmap.fill(m_palette->black_pen(), cliprect); @@ -146,7 +138,6 @@ uint32_t taitowlf_state::screen_update_taitowlf(screen_device &screen, bitmap_rg return 0; } -#endif // Intel 82439TX System Controller (MTXC) @@ -302,16 +293,8 @@ void taitowlf_state::bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask) void taitowlf_state::taitowlf_map(address_map &map) { map(0x00000000, 0x0009ffff).ram(); -#if TAITOWLF_ENABLE_VGA - map(0x000a0000, 0x000bffff).rw("vga", FUNC(vga_device::mem_r), FUNC(vga_device::mem_w)); -#else map(0x000a0000, 0x000bffff).ram(); -#endif -#if TAITOWLF_ENABLE_VGA - map(0x000c0000, 0x000c7fff).ram().region("video_bios", 0); -#else map(0x000c0000, 0x000c7fff).noprw(); -#endif map(0x000e0000, 0x000effff).ram(); map(0x000f0000, 0x000fffff).bankr("bank1"); map(0x000f0000, 0x000fffff).w(FUNC(taitowlf_state::bios_ram_w)); @@ -327,13 +310,7 @@ void taitowlf_state::taitowlf_io(address_map &map) map(0x00e8, 0x00eb).noprw(); map(0x0300, 0x03af).noprw(); map(0x0278, 0x027b).w(FUNC(taitowlf_state::pnp_config_w)); -#if TAITOWLF_ENABLE_VGA - map(0x03b0, 0x03bf).rw("vga", FUNC(vga_device::port_03b0_r), FUNC(vga_device::port_03b0_w)); - map(0x03c0, 0x03cf).rw("vga", FUNC(vga_device::port_03c0_r), FUNC(vga_device::port_03c0_w)); - map(0x03d0, 0x03df).rw("vga", FUNC(vga_device::port_03d0_r), FUNC(vga_device::port_03d0_w)); -#else map(0x03b0, 0x03df).noprw(); -#endif map(0x0a78, 0x0a7b).w(FUNC(taitowlf_state::pnp_data_w)); map(0x0cf8, 0x0cff).rw("pcibus", FUNC(pci_bus_legacy_device::read), FUNC(pci_bus_legacy_device::write)); } @@ -353,7 +330,6 @@ void taitowlf_state::machine_reset() } -#if !TAITOWLF_ENABLE_VGA /* debug purpose*/ void taitowlf_state::taitowlf_palette(palette_device &palette) const { @@ -363,7 +339,6 @@ void taitowlf_state::taitowlf_palette(palette_device &palette) const palette.set_pen_color(0x10, rgb_t(0xaa, 0x00, 0x00)); palette.set_pen_color(0x00, rgb_t(0x00, 0x00, 0x00)); } -#endif void taitowlf_state::taitowlf(machine_config &config) { @@ -381,9 +356,6 @@ void taitowlf_state::taitowlf(machine_config &config) pcat_common(config); /* video hardware */ -#if TAITOWLF_ENABLE_VGA - pcvideo_vga(config); -#else screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); screen.set_refresh_hz(60); screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); @@ -391,7 +363,6 @@ void taitowlf_state::taitowlf(machine_config &config) screen.set_visarea(0, 512-1, 0, 256-1); screen.set_screen_update(FUNC(taitowlf_state::screen_update_taitowlf)); PALETTE(config, m_palette, FUNC(taitowlf_state::taitowlf_palette), 256); -#endif } void taitowlf_state::init_taitowlf() @@ -409,12 +380,6 @@ ROM_START(pf2012) ROM_REGION32_LE(0x40000, "bios", 0) ROM_LOAD("p5tx-la.bin", 0x00000, 0x40000, CRC(072e6d51) SHA1(70414349b37e478fc28ecbaba47ad1033ae583b7)) -#if TAITOWLF_ENABLE_VGA - ROM_REGION( 0x8000, "video_bios", 0 ) // debug - ROM_LOAD16_BYTE( "trident_tgui9680_bios.bin", 0x0000, 0x4000, BAD_DUMP CRC(1eebde64) SHA1(67896a854d43a575037613b3506aea6dae5d6a19) ) - ROM_CONTINUE( 0x0001, 0x4000 ) -#endif - ROM_REGION(0x400000, "user3", 0) // Program ROM (FAT12) ROM_LOAD("u1.bin", 0x000000, 0x200000, CRC(8f4c09cb) SHA1(0969a92fec819868881683c580f9e01cbedf4ad2)) ROM_LOAD("u2.bin", 0x200000, 0x200000, CRC(59881781) SHA1(85ff074ab2a922eac37cf96f0bf153a2dac55aa4)) -- cgit v1.2.3