video/pc_vga_s3: add interlace mode, fix offset behaviour

* fixes 800x600 and 1024x768 basic drawing
This commit is contained in:
angelosa 2024-01-20 06:46:05 +01:00
parent 9e9539fb59
commit d78adb6a7c
4 changed files with 30 additions and 36 deletions

View File

@ -134,6 +134,16 @@ void s3_vga_device::s3_define_video_mode()
recompute_params_clock(divisor, xtal);
}
void s3_vga_device::refresh_pitch_offset()
{
// bit 2 = bit 8 of offset register, but only if bits 4-5 of CR51 are 00h.
vga.crtc.offset &= 0xff;
if((s3.cr51 & 0x30) == 0)
vga.crtc.offset |= (s3.cr43 & 0x04) << 6;
else
vga.crtc.offset |= (s3.cr51 & 0x30) << 4;
}
void s3_vga_device::crtc_map(address_map &map)
{
svga_device::crtc_map(map);
@ -236,13 +246,12 @@ void s3_vga_device::crtc_map(address_map &map)
// CR42 Mode Control
map(0x42, 0x42).lrw8(
NAME([this] (offs_t offset) {
// bit 5 set if interlaced, leave it unset for now.
return s3.cr42 & 0x0f;
return s3.cr42;
}),
NAME([this] (offs_t offset, u8 data) {
// bit 5 = interlace, bits 0-3 = dot clock (seems to be undocumented)
// TODO: interlace used by modes 116h / 117h at least (1024x768)
s3.cr42 = data;
s3_define_video_mode();
})
);
map(0x43, 0x43).lrw8(
@ -251,7 +260,7 @@ void s3_vga_device::crtc_map(address_map &map)
}),
NAME([this] (offs_t offset, u8 data) {
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);
refresh_pitch_offset();
s3_define_video_mode();
})
);
@ -456,18 +465,17 @@ bit 0-5 Pattern Display Start Y-Pixel Position.
NAME([this] (offs_t offset) {
u8 res = (vga.crtc.start_addr_latch & 0x0c0000) >> 18;
res |= ((svga.bank_w & 0x30) >> 2);
res |= ((vga.crtc.offset & 0x0300) >> 4);
// res |= ((vga.crtc.offset & 0x0300) >> 4);
res |= (s3.cr51 & 0x30);
return res;
}),
NAME([this] (offs_t offset, u8 data) {
s3.cr51 = data;
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);
refresh_pitch_offset();
s3_define_video_mode();
})
);

View File

@ -90,9 +90,11 @@ protected:
virtual uint16_t offset() override;
virtual void s3_define_video_mode(void);
virtual bool get_interlace_mode() override { return BIT(s3.cr42, 5); }
private:
ibm8514a_device* m_8514;
void refresh_pitch_offset();
};
// device type definition

View File

@ -5,11 +5,6 @@
*
* Implementation of the S3 Virge series of video card
*
* Current status:
* - Working on getting VESA video modes working better - 800x600 and higher skip every other line at
* 8-bit depth, but are fine at 15/16-bit depth.
* - S3D is not implemented at all, so no 2D/3D acceleration yet.
*
* TODO:
* - Proper FIFOs;
* - Implement 3d commands;
@ -19,7 +14,12 @@
* - DMAs;
* - interrupts;
* - big endian support for non-x86 machines;
* - DDC/I2C i/f, cfr. serial port on MMFF20
* - DDC/I2C i/f, cfr. serial port on MMFF20;
* - Fix PLL calculation for 1k+ width VESA modes (tends to either be too fast or too slow);
* - Fix interlace mode line compare downstream (1600x1200 res);
* - xubuntu: black screen after booting into GNOME,
* tries to setup linear address with new MMIO disabled,
* kernel driver has DDC checks around that ...
* - win98se: doesn't show transparent layer on shut down screen;
*
*/
@ -187,8 +187,10 @@ void s3virgedx_rev1_vga_device::device_reset()
uint16_t s3virge_vga_device::offset()
{
// win98se expects 24bpp packed mode with x6 boundaries
// this breaks VBETest, which detects these VESA modes as 32bpp.
if(svga.rgb24_en)
return vga.crtc.offset * 6; // special handling for 24bpp packed mode
return vga.crtc.offset * 6;
return s3_vga_device::offset();
}
@ -208,17 +210,6 @@ void s3virge_vga_device::crtc_map(address_map &map)
s3.enable_s3d = data & 0x01;
})
);
map(0x43, 0x43).lw8(
NAME([this] (offs_t offset, u8 data) {
// bit 2 = bit 8 of offset register, but only if bits 4-5 of CR51 are 00h.
s3.cr43 = data;
if((s3.cr51 & 0x30) == 0)
vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x04) << 6);
else
vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((s3.cr51 & 0x30) << 4);
s3_define_video_mode();
})
);
map(0x45, 0x45).lrw8(
NAME([this] (offs_t offset) {
return s3.cursor_mode;
@ -241,14 +232,6 @@ void s3virge_vga_device::crtc_map(address_map &map)
return res;
})
);
map(0x51, 0x51).lr8(
NAME([this] (offs_t offset) {
u8 res = (vga.crtc.start_addr_latch & 0x0c0000) >> 18;
res |= ((svga.bank_w & 0x30) >> 2);
//res |= ((vga.crtc.offset & 0x0300) >> 4);
return res;
})
);
map(0x53, 0x53).lrw8(
NAME([this] (offs_t offset) {
return s3.cr53;
@ -430,7 +413,7 @@ void s3virge_vga_device::mem_w(offs_t offset, uint8_t data)
// TODO
}
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en)
if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_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)

View File

@ -194,6 +194,7 @@ protected:
devcb_write_line m_linear_config_changed_cb;
virtual void s3_define_video_mode(void) override;
// has no 8514/A device
private:
emu_timer* m_draw_timer;