VOGONS


VGA's undocumented latching?

Topic actions

Reply 20 of 25, by mkarcher

User metadata
Rank l33t
Rank
l33t
superfury wrote on 2020-12-14, 11:48:

One thing I still see happening, though, is that when scrolling the display left/right, the display jerks left/right for 1 frame every few frames somehow?

If the jerking is by 8 pixels, it looks like the timing for either latching the start address or evaluating the pixel panning register is off. The working approach I got from my VGA book is to update the start address during the display period (because it is latched at display end), and update the pixel panning register during the subsequent blanking period (I assume it's unlatched, didn't test that yet). So horizontal soft-scrolling should look like this

  • frame 0, during display: do nothing
  • frame 0, during blanking: set pixel panning to 6 (applies to frame 1)
  • frame 1, during display: do nothing
  • frame 1, during blanking: set pixel panning to 7 (applies to frame 2)
  • frame 2, during display: increase start address (applies to frame 3)
  • frame 2, during blanking: set pixel panning to 0 (applies to frame 3, too)
  • frame 3, during display: do nothing
  • frame 3, during blanking: set pixel panning to 1

You get the effect you describe if only one of the two register changes performed during frame 2 is applied to frame 3. This could happen if you latch pixel panning at the beginning of the blanking period. In that case, frame 3 would be drawn with the new start address, but still the old panning value (7 = maximal panning). I got a similar effect (on actual hardware) when I treated byte panning as unlatched and updated it during the blanking period while the correct point in time to update byte panning is in the preceding display period, just like the start address.

Reply 21 of 25, by mkarcher

User metadata
Rank l33t
Rank
l33t
superfury wrote on 2020-12-14, 11:48:

One thing I still see happening, though, is that when scrolling the display left/right, the display jerks left/right for 1 frame every few frames somehow?

You didn't specify what mode you got this problem with. Any mode? Just text modes (maybe an issue with 9-pixel character support)? Just graphics modes?

Reply 22 of 25, by mkarcher

User metadata
Rank l33t
Rank
l33t

I played around with the byte panning value in plain 16-color mode. On the ET4000/W32i, setting the byte panning value to 1, the frame is indeed shifted to the left as if the start address is incremented by one, but with a major difference: The last pixels are not rendered correctly. It seems that the effect of the byte panning register is that the CRTC does 8 dummy shift cycles per byte panning increment before display starts. If these dummy shifts trigger reloads (every 8th or 16th pixel, or every 4th in ET4000 high-color mode, I guess), these reloads also happen. This explains why setting the byte panning to 1 in 16-color mode, it looks as if the start address is incremented by 1: The CRTC throws away the first 8 pixels, and triggers a shift register reload of the next address before scanning out the first pixel.

But there seems to be a catch: The maximum number of reloads seems to be limited, so if reloads happened before the first displayed pixel, they are skipped near the end of the scanline. Normal 640x480 modes needs 80 reloads of the shift register if not scrolled and 81 if scrolled. If you use byte panning to scroll even further than 8 pixels, you would need a 82nd reload to fetch the last pixels of the line, but this reload doesn't seem to happen on the ET4000/W32. So you better don't over-byte-pan (use byte panning values other than 0 in 16-color modes or byte panning values above 1 in 4-color modes).

Reply 23 of 25, by superfury

User metadata
Rank l33t++
Rank
l33t++
mkarcher wrote on 2020-12-14, 22:49:

I played around with the byte panning value in plain 16-color mode. On the ET4000/W32i, setting the byte panning value to 1, the frame is indeed shifted to the left as if the start address is incremented by one, but with a major difference: The last pixels are not rendered correctly. It seems that the effect of the byte panning register is that the CRTC does 8 dummy shift cycles per byte panning increment before display starts. If these dummy shifts trigger reloads (every 8th or 16th pixel, or every 4th in ET4000 high-color mode, I guess), these reloads also happen. This explains why setting the byte panning to 1 in 16-color mode, it looks as if the start address is incremented by 1: The CRTC throws away the first 8 pixels, and triggers a shift register reload of the next address before scanning out the first pixel.

But there seems to be a catch: The maximum number of reloads seems to be limited, so if reloads happened before the first displayed pixel, they are skipped near the end of the scanline. Normal 640x480 modes needs 80 reloads of the shift register if not scrolled and 81 if scrolled. If you use byte panning to scroll even further than 8 pixels, you would need a 82nd reload to fetch the last pixels of the line, but this reload doesn't seem to happen on the ET4000/W32. So you better don't over-byte-pan (use byte panning values other than 0 in 16-color modes or byte panning values above 1 in 4-color modes).

Such discarding of pixels is what UniPCemu does already for the horizontal pixel panning and byte panning(number of pixels to skip(reloading every 8 pixels)=(horizontalpixelpanning+((bytepanning)*(9 for 9 pixel modes, 8 for all other modes)))). Don't know what happens with the custom widths, though(5 through 16 pixel wide character clock modes).
The number of pixels to skip is simply applied like this(at vertical total and horizontal total): for each pixel to skip, perform the first step of rendering only(basically all steps until it reaches the attribute controller translation step).
So everything until the attribute byte translation is started is executed, nothing being rendered afterwards.

This is what UniPCemu currently latches during the various clocks in the frame:
CGA/MDA: start address latched during vertical total
EGA and up: start address latched during vertical retrace starting
EGA and up: byte panning latched during vertical retrace starting
All graphics cards:
preset row scan latched during vertical total
character height latched during vertical total. This is only used for determining the latched preset row scan to apply(it's supposed to be cleared when said value exceeds the character height latched).
Active start map(to be cleared when performing top window) is loaded during vertical total from the latched value.

Vertical total execution also raises a flag for latching remaining values when active display starts again after vertical total:
- Pixel shift count requiring to be cleared for the frame(for top window clearing of said parameter).
- Line compare register is latched.

Is that behaviour correct? Do you know why those single frames of mismatched horizontal scrolling (8 pixel multiple) occurs?
Looking at the text that's printed during the demo(" Mode 10, page 1"), I see the jump to the next 8 pixels to the right happen each time the next character is fully scrolled left. So when the next character clock starts at clock 0, the entire display is shifted back to the location it had before scrolling out(during the start of the demo) or in(towards the end of the demo, latter half) using the horizontal pel panning register?
So could it be that the demo is actually performing the start address modification during vertical retrace instead of before it?
Edit: Yup. It's performing the reloading of the start address and byte panning registers DURING vertical retrace instead of before it!

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

Reply 24 of 25, by superfury

User metadata
Rank l33t++
Rank
l33t++

About the panning start pixel issue: The latching is as mentioned in my last post describing the latching in UniPCemu.

Since the panning issue only happens when increasing/decreasing the VGA start address(which is latched at the start of vertical retrace), perhaps the issue is with the live horizontal pel panning register applying itself?
UniPCemu now doesn't latch it at all. It's using the live version when reaching horizontal total to skip n pixels(effectively combined with the latched version of the byte panning register(used at the start of the frame only, when reaching horizontal total).

byte panning (latched during vertical retrace starting, like the start address registers) is applied during each scanline(combined with the live horizontal PEL panning register).
Preset row scan(latched during vertical total) and start address(latched during vertical retrace starting) are applied during vertical total(where they are affecting the new row(at the start of the new frame to render)). The latching of the character height(for preset row scan applying once) is also done during vertical total.
Vertical total also loads the initial start map from the latched value for the next frame to render properly.

Edit: Looking at the scrolling effect running in vgatest 2, I see something interesting:
It increases/decreases both the start address register (every 8 pixels) and the horizontal PEL panning register (every pixels, modulo 8 ) between vertical retrace and vertical total!
Does that mean that the demo is defective?

Edit: Interesting, the program mentioned ( https://youtu.be/IFueAukNyxk ) at http://www.vcfed.org/forum/showthread.php?669 … or-MS-DOS/page6 , also loads both the start address and horizontal pel panning register during vertical retrace?

But the demo I originally tested with (the PGAME demo (https://pcem-emulator.co.uk/phpBB3/viewtopic.php?t=3089 ) waits for vertical blank to start again after writing the start address(documented), then performs the horizontal pel panning register to match it's selected pixel during the vertical retrace?

So is the pel panning register latched before the the vertical retrace starts or at vertical total?
Edit: According to the current Dosbox version, it's latched during vertical retrace ending?
Edit: And according to PCem-X, it's latched during vertical total instead ( https://github.com/OBattler/PCem-X/blob/maste … /PCem/vid_ega.c and https://github.com/sarah-walker-pcem/pcem/blo … /src/vid_svga.c, look for references to scrollcache)?
Edit: Jazz Jackrabbit uses both panning registers(at least for double buffering frames and for scrolling in the game world), and still works properly(with fine pixel tuning on horizontal scrolling). So does the PGAME test program and the VGATEST 2 program! 😁

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

Reply 25 of 25, by superfury

User metadata
Rank l33t++
Rank
l33t++

Also, the ET4000 extended text modes are:
TS register 7, bits 1-2: extend bit 0 of the sequencer mode control register. New values(0/1 are compatibility):
7: 16
4: 12
3: 11
2: 10
1: 8
0: 9

Attribute controller register 16h, bit 6: 2-byte character code(ET4000 rev E).
Edit: Also, the said changes and bugfixes are now out in the latest UniPCemu release! 😁
So Jazz Jackrabbit is playable again!

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