bananaboy wrote on 2022-12-30, 13:42:
Sorry for necroing an old post but I was digging through this IBM VGA BIOS code and I think I understand a bit about what it's d […]
GloriousCow wrote on 2022-09-12, 20:30:
I've encountered a bit of a puzzling roadblock during the IBM VGA BIOS expansion POST.
The VGA BIOS sets up a 720x400 resolution and then proceeds to check for 400 scanlines (Rather any value between 390 and 410) between VSYNC periods as measured by the Vertical Retrace bit of Input Status Register #1. Check is at C200:024A.
This doesn't make sense to me. VerticalTotal is set to 447, so there will be more than 400 lines between vertical retraces. We have the Vertical Blank period (lines 406-441) and the Vertical Retrace period itself doesn't start until scanline 412. Setting the vertical retrace bit only between scanlines Vertical Retrace Start to End produces a count of 432, which the BIOS rejects and goes to one long, three short beeps.
Sorry for necroing an old post but I was digging through this IBM VGA BIOS code and I think I understand a bit about what it's doing here. I think your summary isn't quite right. It's counting the number of scanlines in the active display area, not the number of scanlines between vsync periods. It looks like this in pseudocode:
1. Wait for any active vertical retrace to end.
2. Wait for the next vertical retrace to start.
3. Wait for the vertical retrace to end and the display to be re-enabled (bit 0 of Input Status Register 1 = 0 means the display is enabled). This means we're now at the top of the active display area.
4. Wait for horizontal retrace to start (i.e. the first scanline has been shown).
5. Wait for the horizontal retrace to finish (goto 6), or for vertical retrace to start (goto 7).
6. Horizontal retrace is finished, so increment the scanline counter in `bx` and go back to 4.
7. Vertical retrace has started, so we're out of the active display area.
Now `bx` contains the number of scanlines. However this count also includes both the bottom border and display blanked areas (which occur before the vertical retrace starts). It seems to me this would push the count up to 412 (i.e. the scanline where vertical retrace starts) which would then fail the "greater than 410" test so it's still a little confusing to me how it can work! Btw it looks like bits of the VGA BIOS code are similar to the EGA BIOS code (available https://www.os2museum.com/wp/reconstructing-the-ega-bios/).
One error there:
DD -- Display Disabled
"When set to 1, this bit indicates a horizontal or vertical retrace interval. This bit is the real-time status of the inverted 'display enable' signal. Programs have used this status bit to restrict screen updates to the inactive display intervals in order to reduce screen flicker. The video subsystem is designed to eliminate this software requirement; screen updates may be made at any time without screen degradation."
So bit 0 isn't indicating horizontal retrace only. Vertical retrace affects it as well (basically OR-ed).
So anything past the last active display scanline keeps it the same as during retracing horizontally, because it's an inverted display-enable(active display) signal output, which is always true past the last scanline.
So it's set after the last scanline until the next frame starts it's display enable again, thus no extra scanlines in BX, with vertical retrace somewhere within it's timing usually.
Basically just keep a flag that indicates active display is rendering (from active display skew to horizontal retrace, cleared at horizontal display end until the next frame starts active display).
Then just report it inverted to the app(XOR 1) in the input status 1 register.
The vertical retrace works much in the same way, from vertical retrace start until a scanline matches after it (but not the same scanline it starts!).
Anything of course after horizontal&vertical retrace is plain active display (you can put retrace anywhere after all), only affected by blanking otherwise (which basically masks VRAM generated output). That's how the image gets centered on the screen with extra borders.
https://wiki.osdev.org/Video_Signals_And_Timing displays it correctly. Although the overscan before scanline counter 0 (previous iteration) is missing from the rendering output timings, it's archieved by adding overscan to the right and bottom combined with blanking to clear a part of it to create the centered image with black borders.
Past active display doesn't toggle display enable. So when it reaches horizontal retrace of vertical display end, it doesn't flip back until the next frame starts with horizontal&vertical counters reset and horizontal display skew clocks after that.
So with 640x400 active display, what software sees:
1. 400 times horizontal retrace. The 400th 'retrace' gets stuck a long time.
2. During that long time being stuck, vertical retrace flips on and off (usually, can happen anytime though).
3. Bit 0 clears and a new frame is rendering at horizontal display skew.
4. Back to step 1.
And yes, you can trigger retrace in the middle of active display to create a weird split screen at the cost of VRAM. Retracing forces blanking essentially.
The same with blanking start/end.
You can even prevent blank/retrace from occurring by placing it past/at the total register. 8088MPH did this if I remember correctly, for odd/even double scanline rendering tricks?