From 89faea406b7b183c3406664dc6e7df96d1fcf65d Mon Sep 17 00:00:00 2001 From: angelosa Date: Tue, 11 Jul 2023 01:59:37 +0200 Subject: video/pc_vga_paradise.cpp: add WD90C30 video/pc_vga.cpp: preliminary implementation of an interlace_mode virtual getter --- src/devices/bus/isa/isa_cards.cpp | 1 + src/devices/bus/isa/svga_paradise.cpp | 55 +++++++++++++++++++- src/devices/bus/isa/svga_paradise.h | 25 +++++++++- src/devices/video/pc_vga.cpp | 13 +++-- src/devices/video/pc_vga.h | 1 + src/devices/video/pc_vga_paradise.cpp | 94 +++++++++++++++++++++++++++++++++-- src/devices/video/pc_vga_paradise.h | 24 ++++++++- 7 files changed, 200 insertions(+), 13 deletions(-) diff --git a/src/devices/bus/isa/isa_cards.cpp b/src/devices/bus/isa/isa_cards.cpp index f5cc89841ff..461fdc97d31 100644 --- a/src/devices/bus/isa/isa_cards.cpp +++ b/src/devices/bus/isa/isa_cards.cpp @@ -224,6 +224,7 @@ void pc_isa16_cards(device_slot_interface &device) device.option_add("pvga1a_jk", ISA16_PVGA1A_JK); device.option_add("wd90c00_jk", ISA16_WD90C00_JK); device.option_add("wd90c11_lr", ISA16_WD90C11_LR); + device.option_add("wd90c30_lr", ISA16_WD90C30_LR); 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/svga_paradise.cpp b/src/devices/bus/isa/svga_paradise.cpp index 2c90d634bdd..abccda6ca06 100644 --- a/src/devices/bus/isa/svga_paradise.cpp +++ b/src/devices/bus/isa/svga_paradise.cpp @@ -31,6 +31,7 @@ DEFINE_DEVICE_TYPE(ISA16_PVGA1A_JK, isa16_pvga1a_jk_device, "pvga1a_jk", "Para DEFINE_DEVICE_TYPE(ISA8_WD90C90_JK, isa8_wd90c90_jk_device, "wd90c90_jk", "Western Digital WD90C90-JK Graphics Card") DEFINE_DEVICE_TYPE(ISA16_WD90C00_JK, isa16_wd90c00_jk_device, "wd90c00_jk", "Western Digital WD90C00-JK Graphics Card") DEFINE_DEVICE_TYPE(ISA16_WD90C11_LR, isa16_wd90c11_lr_device, "wd90c11_lr", "Western Digital WD90C11-LR Graphics Card \"1024 CX\"") +DEFINE_DEVICE_TYPE(ISA16_WD90C30_LR, isa16_wd90c30_lr_device, "wd90c30_lr", "Western Digital WD90C30-LR Graphics Card \"1024 DX\"") isa16_pvga1a_device::isa16_pvga1a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : @@ -290,7 +291,6 @@ void isa16_wd90c11_lr_device::device_add_mconfig(machine_config &config) screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480); screen.set_screen_update("vga", FUNC(wd90c00_vga_device::screen_update)); - // TODO: bump to WD90C11A WD90C11A(config, m_vga, 0); m_vga->set_screen("screen"); // 512KB (+ option for 1MB? Verify with interlace) @@ -299,7 +299,7 @@ void isa16_wd90c11_lr_device::device_add_mconfig(machine_config &config) void isa16_wd90c11_lr_device::io_isa_map(address_map &map) { - map(0x00, 0x2f).m(m_vga, FUNC(wd90c00_vga_device::io_map)); + map(0x00, 0x2f).m(m_vga, FUNC(wd90c11a_vga_device::io_map)); } void isa16_wd90c11_lr_device::device_start() @@ -311,3 +311,54 @@ void isa16_wd90c11_lr_device::device_start() m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(wd90c00_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(wd90c00_vga_device::mem_w))); m_isa->install_device(0x03b0, 0x03df, *this, &isa16_wd90c11_lr_device::io_isa_map); } + +/****************** + * + * WD90C30-LR + * + *****************/ + +isa16_wd90c30_lr_device::isa16_wd90c30_lr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, ISA16_WD90C30_LR, tag, owner, clock), + device_isa16_card_interface(mconfig, *this), + m_vga(*this, "vga") +{ +} + +ROM_START( wd90c30_lr ) + ROM_REGION(0x8000,"vga_rom", ROMREGION_ERASE00) + ROM_SYSTEM_BIOS(0, "wd90c30_lr", "Western Digital WD90C30-LR") + ROMX_LOAD( "90c30-lr.vbi", 0x000000, 0x008000, CRC(3356ad43) SHA1(6cd56cf274b3c9262b7ca12d49bae63afc331c58), ROM_BIOS(0) ) +ROM_END + +const tiny_rom_entry *isa16_wd90c30_lr_device::device_rom_region() const +{ + return ROM_NAME( wd90c30_lr ); +} + +void isa16_wd90c30_lr_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("vga", FUNC(wd90c00_vga_device::screen_update)); + + WD90C30(config, m_vga, 0); + m_vga->set_screen("screen"); + // 512KB, 1MB + m_vga->set_vram_size(0x100000); +} + +void isa16_wd90c30_lr_device::io_isa_map(address_map &map) +{ + map(0x00, 0x2f).m(m_vga, FUNC(wd90c30_vga_device::io_map)); +} + +void isa16_wd90c30_lr_device::device_start() +{ + set_isa_device(); + + m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom"); + + m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(wd90c30_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(wd90c30_vga_device::mem_w))); + m_isa->install_device(0x03b0, 0x03df, *this, &isa16_wd90c30_lr_device::io_isa_map); +} diff --git a/src/devices/bus/isa/svga_paradise.h b/src/devices/bus/isa/svga_paradise.h index e3c374b050e..7e34e1d2389 100644 --- a/src/devices/bus/isa/svga_paradise.h +++ b/src/devices/bus/isa/svga_paradise.h @@ -120,7 +120,29 @@ protected: void io_isa_map(address_map &map); private: - required_device m_vga; + required_device m_vga; +}; + +class isa16_wd90c30_lr_device : + public device_t, + public device_isa16_card_interface +{ +public: + // construction/destruction + isa16_wd90c30_lr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +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; + + void io_isa_map(address_map &map); + +private: + required_device m_vga; }; // device type definition @@ -129,6 +151,7 @@ DECLARE_DEVICE_TYPE(ISA16_PVGA1A_JK, isa16_pvga1a_jk_device) DECLARE_DEVICE_TYPE(ISA8_WD90C90_JK, isa8_wd90c90_jk_device) DECLARE_DEVICE_TYPE(ISA16_WD90C00_JK, isa16_wd90c00_jk_device) DECLARE_DEVICE_TYPE(ISA16_WD90C11_LR, isa16_wd90c11_lr_device) +DECLARE_DEVICE_TYPE(ISA16_WD90C30_LR, isa16_wd90c30_lr_device) #endif // MAME_BUS_ISA_SVGA_PARADISE_H diff --git a/src/devices/video/pc_vga.cpp b/src/devices/video/pc_vga.cpp index 2caa993854d..f4e543bf480 100644 --- a/src/devices/video/pc_vga.cpp +++ b/src/devices/video/pc_vga.cpp @@ -73,7 +73,7 @@ ***************************************************************************/ //#define TEXT_LINES (LINES_HELPER) -#define LINES (vga.crtc.vert_disp_end+1) +#define LINES ((vga.crtc.vert_disp_end + 1) * (get_interlace_mode() + 1)) #define TEXT_LINES (vga.crtc.vert_disp_end+1) #define GRAPHIC_MODE (vga.gc.alpha_dis) /* else text mode */ @@ -1541,7 +1541,7 @@ uint32_t vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, void vga_device::recompute_params_clock(int divisor, int xtal) { - int vblank_period,hblank_period; + int vblank_period, hblank_period; attoseconds_t refresh; uint8_t hclock_m = (!GRAPHIC_MODE) ? VGA_CH_WIDTH : 8; int pixel_clock; @@ -1550,12 +1550,15 @@ void vga_device::recompute_params_clock(int divisor, int xtal) if(!vga.crtc.horz_disp_end || !vga.crtc.vert_disp_end || !vga.crtc.horz_total || !vga.crtc.vert_total) return; - rectangle visarea(0, ((vga.crtc.horz_disp_end + 1) * ((float)(hclock_m)/divisor))-1, 0, vga.crtc.vert_disp_end); + const u8 is_interlace_mode = get_interlace_mode() + 1; + const int display_lines = vga.crtc.vert_disp_end * is_interlace_mode; - vblank_period = (vga.crtc.vert_total + 2); + rectangle visarea(0, ((vga.crtc.horz_disp_end + 1) * ((float)(hclock_m)/divisor))-1, 0, display_lines); + + vblank_period = (vga.crtc.vert_total + 2) * is_interlace_mode; hblank_period = ((vga.crtc.horz_total + 5) * ((float)(hclock_m)/divisor)); - /* TODO: 10b and 11b settings aren't known */ + // TODO: improve/complete clocking modes pixel_clock = xtal / (((vga.sequencer.data[1]&8) >> 3) + 1); refresh = HZ_TO_ATTOSECONDS(pixel_clock) * (hblank_period) * vblank_period; diff --git a/src/devices/video/pc_vga.h b/src/devices/video/pc_vga.h index a23e004da8e..d066b5d874d 100644 --- a/src/devices/video/pc_vga.h +++ b/src/devices/video/pc_vga.h @@ -151,6 +151,7 @@ protected: return res; } + virtual bool get_interlace_mode() { return false; } struct vga_t { diff --git a/src/devices/video/pc_vga_paradise.cpp b/src/devices/video/pc_vga_paradise.cpp index dec074160b1..14e4e2f7305 100644 --- a/src/devices/video/pc_vga_paradise.cpp +++ b/src/devices/video/pc_vga_paradise.cpp @@ -42,8 +42,8 @@ TODO: DEFINE_DEVICE_TYPE(PVGA1A, pvga1a_vga_device, "pvga1a_vga", "Paradise Systems PVGA1A") DEFINE_DEVICE_TYPE(WD90C00, wd90c00_vga_device, "wd90c00_vga", "Western Digital WD90C00 \"PVGA1B\" VGA Controller") -DEFINE_DEVICE_TYPE(WD90C11A, wd90c11a_vga_device, "wd90c11a_vga", "Western Digital WD90C11A \"PVGA1M\" VGA Controller") -//DEFINE_DEVICE_TYPE(WD90C30, wd90c30_vga_device, "wd90c30_vga", "Western Digital WD90C30 \"PVGA1D\" VGA Controller") +DEFINE_DEVICE_TYPE(WD90C11A, wd90c11a_vga_device, "wd90c11a_vga", "Western Digital WD90C11A \"PVGA1C\" VGA Controller") +DEFINE_DEVICE_TYPE(WD90C30, wd90c30_vga_device, "wd90c30_vga", "Western Digital WD90C30 \"PVGA1D\" VGA Controller") pvga1a_vga_device::pvga1a_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) @@ -330,10 +330,12 @@ void wd90c00_vga_device::recompute_params() { u8 xtal_select = (vga.miscellaneous_output & 0x0c) >> 2; int xtal; - // TODO: VTB disables video select bit 1 for 1024x768 mode (with no interlace mode setup) + // TODO: wd90c11a VTB disables video select bit 1 for 1024x768 mode (with interlace mode = false) // Uses VCLK1, without the bump will select 26.43 Hz as refresh rate const u8 multiplier = BIT(m_video_select, 1) ? 1 : 2; + //printf("%d %d %02x\n", m_interlace_mode, xtal_select, m_video_select); + switch(xtal_select & 3) { // VCLK0 @@ -342,6 +344,7 @@ void wd90c00_vga_device::recompute_params() case 1: xtal = XTAL(28'636'363).value() * multiplier; break; // VCLK2, selected in 800x600 modes case 2: + // TODO: wd90c30 selects this for 1024x768 interlace mode (~40 Hz) default: xtal = XTAL(42'000'000).value(); break; @@ -569,4 +572,87 @@ void wd90c11a_vga_device::sys_if_control_w(offs_t offset, u8 data) { LOG("PR31 System Interface Control W %02x\n", data); m_pr31 = data; -} \ No newline at end of file +} + +/************************************** + * + * Western Digital WD90C30 + * + *************************************/ + +wd90c30_vga_device::wd90c30_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : wd90c11a_vga_device(mconfig, type, tag, owner, clock) +{ + m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(wd90c30_vga_device::crtc_map), this)); + m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(wd90c30_vga_device::sequencer_map), this)); +} + +wd90c30_vga_device::wd90c30_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : wd90c30_vga_device(mconfig, WD90C30, tag, owner, clock) +{ +} + +void wd90c30_vga_device::device_reset() +{ + wd90c11a_vga_device::device_reset(); + + m_pr18 = 0; +} + +void wd90c30_vga_device::crtc_map(address_map &map) +{ + wd90c11a_vga_device::crtc_map(map); +// m_ext_crtc_view[1](0x20, 0x21) Signature read data +// m_ext_crtc_view[1](0x3d, 0x3d) PR1A CRTC Shadow Register Control + m_ext_crtc_view[1](0x3e, 0x3e).rw(FUNC(wd90c30_vga_device::vert_timing_overflow_r), FUNC(wd90c30_vga_device::vert_timing_overflow_w)); +// m_ext_crtc_view[1](0x3f, 0x3f) PR19 Signature Analyzer Control +} + +void wd90c30_vga_device::sequencer_map(address_map &map) +{ + wd90c11a_vga_device::sequencer_map(map); +// m_ext_seq_view[1](0x13, 0x13) PR33 DRAM Timing and zero Wait State Control +// m_ext_seq_view[1](0x14, 0x14) PR34 Video Memory Mapping +// m_ext_seq_view[1](0x15, 0x15) PR35 USR0, USR1 Output Select +} + +/* + * [0x3e] PR18 CRTC Vertical Timing Overflow + * + * xxx- ---- + * ---x ---- Line Compare bit 10 + * ---- x--- Start vertical blank bit 10 + * ---- -x-- Start vertical retrace bit 10 + * ---- --x- Vertical display enable end bit 10 + * ---- ---x Vertical total bit 10 + */ +u8 wd90c30_vga_device::vert_timing_overflow_r(offs_t offset) +{ + LOG("PR18 CRTC Vertical Timing Overflow R (%02x)\n", m_pr18); + return m_pr18; +} + +void wd90c30_vga_device::vert_timing_overflow_w(offs_t offset, u8 data) +{ + LOG("PR18 CRTC Vertical Timing Overflow W %02x\n", data); + if (!BIT(m_crtc_lock, 1) && !vga.crtc.protect_enable) + { + vga.crtc.vert_disp_end = (vga.crtc.vert_disp_end & 0x03ff) | ((BIT(data, 1) << 10)); + m_pr18 &= ~2; + m_pr18 |= (data & 2); + } + + if (!BIT(m_crtc_lock, 0) || !vga.crtc.protect_enable) + { + vga.crtc.vert_blank_start = (vga.crtc.vert_blank_start & 0x03ff) | ((BIT(data, 3) << 10)); + //vga.crtc.vert_retrace = (vga.crtc.vert_retrace & 0x03ff) | ((BIT(data, 2) << 10)); + vga.crtc.vert_total = (vga.crtc.vert_total & 0x03ff) | ((BIT(data, 0) << 10)); + m_pr18 &= ~0x0d; + m_pr18 |= (data & 0xd); + } + + vga.crtc.line_compare = (vga.crtc.line_compare & 0x03ff) | ((BIT(data, 4) << 10)); + m_pr18 &= ~0xf0; + m_pr18 |= data & 0xf0; + recompute_params(); +} diff --git a/src/devices/video/pc_vga_paradise.h b/src/devices/video/pc_vga_paradise.h index 80dd6e95863..1686ce7721c 100644 --- a/src/devices/video/pc_vga_paradise.h +++ b/src/devices/video/pc_vga_paradise.h @@ -27,6 +27,7 @@ protected: memory_view m_ext_gc_view; u8 m_video_select = 0; + u8 m_crtc_lock = 0; private: u8 address_offset_r(offs_t offset); void address_offset_w(offs_t offset, u8 data); @@ -44,7 +45,6 @@ private: u8 m_memory_size = 0; u8 m_video_control = 0; bool m_ext_gc_unlock = false; - u8 m_crtc_lock = 0; }; class wd90c00_vga_device : public pvga1a_vga_device @@ -60,6 +60,8 @@ protected: virtual void crtc_map(address_map &map) override; virtual void recompute_params() override; + virtual bool get_interlace_mode() override { return m_interlace_mode; } + memory_view m_ext_crtc_view; private: u8 ext_crtc_status_r(offs_t offset); @@ -105,8 +107,28 @@ private: u8 m_pr31 = 0; }; +class wd90c30_vga_device : public wd90c11a_vga_device +{ +public: + wd90c30_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + wd90c30_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void crtc_map(address_map &map) override; + virtual void sequencer_map(address_map &map) override; + + virtual void device_reset() override; +private: + u8 vert_timing_overflow_r(offs_t offset); + void vert_timing_overflow_w(offs_t offset, u8 data); + + u8 m_pr18 = 0; +}; + DECLARE_DEVICE_TYPE(PVGA1A, pvga1a_vga_device) DECLARE_DEVICE_TYPE(WD90C00, wd90c00_vga_device) DECLARE_DEVICE_TYPE(WD90C11A, wd90c11a_vga_device) +DECLARE_DEVICE_TYPE(WD90C30, wd90c30_vga_device) #endif // MAME_VIDEO_PC_VGA_PARADISE_H -- cgit v1.2.3