VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

Looking at the blanking affecting horizontal and vertical clocks, I see something strange.

The final range of vertical/horizontal blanking has some weird side effects? Since most, if not all, VGA modes have some extra space after horizontal retrace until a new scanline (from EGA/VGA pov) starts (indicated by horizontal total), there's a few clocks that are rendered on the next scanline instead of the same scanline? But the VGA spews out those clocks of the running (before horizontal retrace) scanline on the next scanline instead, with appropriate blanking if applied?

So that results in a scanline effectively rendering the following clocks (simple representation of character clocks) for the f)ront porch, b)ack porch and r)etrace outputs (some a)ctive display and b)lanking as well added for completeness)? Simplified ofc.

BBaaaaaaaaafffrrrrrr
bbAAAAAAAA...

The first B's belonging to the previous VGA scanline, the small b's being the back porch of said scanline and A's being the start of the new scanline (movable in EGA/VGA using the horizontal display skew adding overscan character clocks) before it.
Since the r clocks is breaking up the scanline on the monitor, the b clocks display the backporch not on the scanline it belongs to (which might be blanked for the scanline before blanking ends) or being the opposite (active instead of blanked) for the CRT scanline where the vertical blanking starts?

Does that happen on a real CRT as well? Or is there some unknown logic at play here?

Anyone knows something about this? The FreeVGA CRT example breaks down for example on this problem? Since scanlines display their back porch on the next scanline before display (from VGA pov).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 1 of 13, by superfury

User metadata
Rank l33t++
Rank
l33t++

I'm just thinking... Are the VGA's internal timing (think character clocks but for scanlines instead, affecting rendering like the MA counters etc.) and memory vertical scanline counters increased by reaching horizontal total(this is done atm for VGA internally, horizontal retrace drives the CRT instead) or is it (like CGA/MDA) triggered by horizontal retrace (HSYNC to be exact) instead (the CRTC Mode Control register bit 2 SLDIV calls it to be triggered by something called 'horizontal retrace clock')?

What happens if no HSYNC is triggered on a VGA card (wrt to the vertical counters and address reloads for new scanlines)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 2 of 13, by superfury

User metadata
Rank l33t++
Rank
l33t++

Does anyone know what the 'horizontal retrace clock' is? Is it just HSYNC (the output from start horizontal retrace making it 1 to trigger the 'horizontal retrace clock')? Or is it something else? Can't find anything but said CRTC register of mode control's SLDIV bit.

Edit: Hmmm...
http://6502.org/users/andre/hwinfo/crtc/internals/index.html
That seems to suggest that the MC6845 (CGA/MDA) perform increasing of the scanline counter on horizontal total (as it's connected to that).

But the VGA performs this during horizontal retrace instead (according to documentation)? Perhaps the EGA as well?
Edit: EGA documentation seems to agree the vertical counter to be clocked by 'Horizontal retrace' or 'HRTC' and names the CRTC mode control register 'Horizontal Retrace Select'. Don't know about the other counters though?
Edit: Hmmm... MartyPC seems to agree on it being the activation of HSYNC that triggers it?
https://github.com/dbalsom/martypc/blob/versi … ces/ega/crtc.rs
'hslc' seems to be the counter at least, that's one source confirming it.
Though that only suggests that the counter (and effects without memory stuff) and obvious scanline is increased on HSYNC. All other effects that are not directly CRTC driving outputs (not active display related other than start address) are at vertical total instead (and thus at the first clock of the new frame).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 3 of 13, by GloriousCow

User metadata
Rank Member
Rank
Member
superfury wrote on 2024-01-21, 22:21:
Edit: Hmmm... MartyPC seems to agree on it being the activation of HSYNC that triggers it? https://github.com/dbalsom/martypc/bl […]
Show full quote

Edit: Hmmm... MartyPC seems to agree on it being the activation of HSYNC that triggers it?
https://github.com/dbalsom/martypc/blob/versi … ces/ega/crtc.rs
'hslc' seems to be the counter at least, that's one source confirming it.
Though that only suggests that the counter (and effects without memory stuff) and obvious scanline is increased on HSYNC. All other effects that are not directly CRTC driving outputs (not active display related other than start address) are at vertical total instead (and thus at the first clock of the new frame).

I wouldn't use my EGA as an example for anything, at least not yet. It's still only about 65% done, and a lot of the logic in there is currently a guess instead of anything concrete or tested.

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 4 of 13, by superfury

User metadata
Rank l33t++
Rank
l33t++
GloriousCow wrote on 2024-01-22, 13:05:
superfury wrote on 2024-01-21, 22:21:
Edit: Hmmm... MartyPC seems to agree on it being the activation of HSYNC that triggers it? https://github.com/dbalsom/martypc/bl […]
Show full quote

Edit: Hmmm... MartyPC seems to agree on it being the activation of HSYNC that triggers it?
https://github.com/dbalsom/martypc/blob/versi … ces/ega/crtc.rs
'hslc' seems to be the counter at least, that's one source confirming it.
Though that only suggests that the counter (and effects without memory stuff) and obvious scanline is increased on HSYNC. All other effects that are not directly CRTC driving outputs (not active display related other than start address) are at vertical total instead (and thus at the first clock of the new frame).

I wouldn't use my EGA as an example for anything, at least not yet. It's still only about 65% done, and a lot of the logic in there is currently a guess instead of anything concrete or tested.

Well, at least on the VGA, fixing the horizontal retrace to increase the counter (as documented by you and the official documentation if interpreted literally (EGA and FreeVGA/IBM VGA documentation)), it fixes the issues I had with the scanlines rendering incorrect at least! 😁

Need to run the Copper demo to double check though, but it looks fine during boot now at least! 😁

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 5 of 13, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm... The Intel Open-Source HD Graphics and Intel Iris graphics Programmer's Reference manual Volume 11: Display, Revision 1.2 (Google "intel-gfx-prm-osrc-bdw-vol-11-display.pdf") says the same (page 54, the CRT mode control bit 2:

... 'vertical timing counter is (* or 'to be' before bit description) clocked by the horizontal retrace clock', followed by 'divided by 2' for the bit being set to 1.

Said 'horizontal retrace clock' is never mentioned anywhere else, but there's something else:

Horizontal sync end (CR05 register) mentions:
'at which time the horizontal retrace signal becomes inactive (logical 0)'.

So if it's active, it's logical 1 (as logical means binary)? And what do we get if it toggles to and from 0-1? A clock signal!
So when it toggles to 1(Horizontal retrace starting due to counter match), it's effectively said clock! That's the very 'clock' (looking at it's output being binary) that horizontal retrace starts!

So that seems to confirm horizontal retrace triggers the increment of the scanline counter (or every 2 with the mode control register being set)?

Edit: Also the IBM PS/2 says (at the preset row scan register start row scan count (the lower bits)):

the row scan counter is incremented every horizontal retrace time until the maximum row scan occurs.

So that pretty much confirms at least the 'row scan counter' is ticked by 'horizontal retrace time'? Could this be the same thing that's mentioned in the CRTC mode control register?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 6 of 13, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm... The 'CL-GD5446 Technical Reference Manual' VGA card documentation literally says it's clocked by HSYNC:
'2 Multiply vertical registers by two: if this bit is '1', the scanline counter is clocked with HSYNC divided by two. (...) If this bit is '0', the scanline counter is clocked with HSYNC.'

That pretty much confirms it afaik.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 7 of 13, by GloriousCow

User metadata
Rank Member
Rank
Member

I've just gotten around to doing proper VGA emulation and now I have a question about this myself.

In 640x480 we get set up with
R6==523
R12==479
R15==487
End vertical blank == 4

Unless I'm doing my math wrong, End vertical blank won't match until we roll back around to scanline 4.
This would extend the vblank period through the top 4 scanlines, which doesn't seem correct?

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 8 of 13, by superfury

User metadata
Rank l33t++
Rank
l33t++
GloriousCow wrote on 2025-04-20, 15:46:
I've just gotten around to doing proper VGA emulation and now I have a question about this myself. […]
Show full quote

I've just gotten around to doing proper VGA emulation and now I have a question about this myself.

In 640x480 we get set up with
R6==523
R12==479
R15==487
End vertical blank == 4

Unless I'm doing my math wrong, End vertical blank won't match until we roll back around to scanline 4.
This would extend the vblank period through the top 4 scanlines, which doesn't seem correct?

Can't you simply refer to them by their names, instead of R[n]? Like vertical retrace end etc. Seeing as the actual values are a combination of multiple registers?

The (S)VGA's limited 'modulo' on matching counters against registers is also more bits (in some cases) than EGA btw. Did you take all 3 registers for the extra bits into account?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 9 of 13, by GloriousCow

User metadata
Rank Member
Rank
Member
superfury wrote on 2025-04-20, 16:51:

Can't you simply refer to them by their names, instead of R[n]? Like vertical retrace end etc. Seeing as the actual values are a combination of multiple registers?

whatever you prefer.

superfury wrote on 2025-04-20, 16:51:

The (S)VGA's limited 'modulo' on matching counters against registers is also more bits (in some cases) than EGA btw. Did you take all 3 registers for the extra bits into account?

I don't think the EndVerticalBlank bits are scattered around in any fashion. It's a single 7-bit register (Ferraro says 7-bits, i've seen other sources that say 8, not sure what's up with that)

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 10 of 13, by GloriousCow

User metadata
Rank Member
Rank
Member

Staring right at an obvious bug but I'm not sure where its lurking.

Using a 7-bit comparator basically makes it a modulo 128 check, so we can end blanking every 128 scanlines + the value of EndVerticalBlank

If StartVerticalBlank is 487 and EndVerticalBlank is 4, that makes the next "test" 512 + 4 or scanline 516. For some reason I'm missing that and triggering on scanline 4 after we wrap, which is clearly incorrect.

EDIT: Problem was an old mask value inherited from EGA used to wrap the scanline counter. VGA extends this to 10 bits. the old 9 bit mask meant we wrapped at 512 and never hit scanline 516 to trigger the end of vertical blank. doh.

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 11 of 13, by superfury

User metadata
Rank l33t++
Rank
l33t++
GloriousCow wrote on 2025-04-20, 18:14:
Staring right at an obvious bug but I'm not sure where its lurking. […]
Show full quote

Staring right at an obvious bug but I'm not sure where its lurking.

Using a 7-bit comparator basically makes it a modulo 128 check, so we can end blanking every 128 scanlines + the value of EndVerticalBlank

If StartVerticalBlank is 487 and EndVerticalBlank is 4, that makes the next "test" 512 + 4 or scanline 516. For some reason I'm missing that and triggering on scanline 4 after we wrap, which is clearly incorrect.

EDIT: Problem was an old mask value inherited from EGA used to wrap the scanline counter. VGA extends this to 10 bits. the old 9 bit mask meant we wrapped at 512 and never hit scanline 516 to trigger the end of vertical blank. doh.

Wait till you get to SVGA, like ET3000/ET4000(/W32[i/p]). Those extend stuff, like overflow register, even further. Rn my emulator is still the only one with CRT emulation (although not trimming borders) for those chipsets (and with various accurate SVGA DACs 8/16/24-bit supported too). Tho my emulator does compress those 2/3-clock outputs into 1-clock outputs to concerve memory (otherwise you'd need huge 2K/4K wide buffers for even low resolutions like 640x480 or 320x200x24.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 12 of 13, by GloriousCow

User metadata
Rank Member
Rank
Member
superfury wrote on 2025-04-21, 10:05:

Wait till you get to SVGA, like ET3000/ET4000(/W32[i/p]). Those extend stuff, like overflow register, even further. Rn my emulator is still the only one with CRT emulation (although not trimming borders) for those chipsets (and with various accurate SVGA DACs 8/16/24-bit supported too). Tho my emulator does compress those 2/3-clock outputs into 1-clock outputs to concerve memory (otherwise you'd need huge 2K/4K wide buffers for even low resolutions like 640x480 or 320x200x24.

I think SVGA is a ways away, I need to do AT / 286 first. But what SVGA card would you recommend implementing first?

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 13 of 13, by superfury

User metadata
Rank l33t++
Rank
l33t++
GloriousCow wrote on 2025-04-21, 23:08:
superfury wrote on 2025-04-21, 10:05:

Wait till you get to SVGA, like ET3000/ET4000(/W32[i/p]). Those extend stuff, like overflow register, even further. Rn my emulator is still the only one with CRT emulation (although not trimming borders) for those chipsets (and with various accurate SVGA DACs 8/16/24-bit supported too). Tho my emulator does compress those 2/3-clock outputs into 1-clock outputs to concerve memory (otherwise you'd need huge 2K/4K wide buffers for even low resolutions like 640x480 or 320x200x24.

I think SVGA is a ways away, I need to do AT / 286 first. But what SVGA card would you recommend implementing first?

Like I said, from what I know the Tseng cards (ET3000/ET4000AX) are basically the easiest to implement from what I know (though still tricky to implement, as it performs weird combinations with horizontal clocking, requiring various timings to be parallelized (based on the base clock), like UniPCemu does). They're almost 100% VGA-compatible (except the 8-bit shift control bit working slightly different and the attribute controller 8-bit mode working differently (controlling pixel doubling instead)). And it only adds a few extra registers. Then it also supports various relatively easy to implement and extend 16/24-bit DACs (which WhatVGA documents pretty well, combining it's (pascal) source code and it's documentation). The ET4000 chips and it's extentions (W32i, W32P) documentation are also easily found everywhere. Although, interestingly enough, Tseng's W32 extensions aren't 100% compatible with AX registers (changing a few extension bits). The same being the case with W32P vs W32i (mostly PCI related).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io