VOGONS


CGA pseudo-graphic modes

Topic actions

Reply 80 of 97, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote on 2025-06-24, 21:37:

So you push the horizontal retrace past the horizontal total? Won't that just increase the scanline counter too soon? Or is that exactly the target? Thus increasing the scanline counter without retrace, increasing it twice each scanline to skip the unwanted character row?
So basically let it trigger retrace start, moving total down to create a short period, retrace out of bounds to prevent triggering it... But active display will occur for one character clock, unless I'm missing something?

Yes, that all sounds correct. The active display does indeed occur for one character clock, but it's hidden in the part of the overscan area that's behind the monitor's bezel. It can be seen if the monitor's horizontal size control is set too small, though.

Reply 81 of 97, by SoftCat

User metadata
Rank Member
Rank
Member
reenigne wrote on 2025-06-16, 13:04:

4148 per frame. Or 4266 with DRAM refresh disabled (115.2 hdots per iteration and 112 hdots per iteration respectively). The answer is the same no matter what the video mode is (the CGA wait states are not dependent on mode).

And how many bytes can be transferred in 1 second to video RAM on EGA and VGA? If you just transfer bytes, without bothering with the color mask and bit mask.

Reply 82 of 97, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2025-06-24, 21:56:

And how many bytes can be transferred in 1 second to video RAM on EGA and VGA? If you just transfer bytes, without bothering with the color mask and bit mask.

That's more difficult to answer. What machine, and what EGA or VGA card? I can test my IBM VGA card in my 5160 if you like, but I'm fairly sure that it can saturate the bus (or very nearly) so about 356kB/s with REP MOVSW. But most EGA and VGA cards are in faster machines.

Reply 83 of 97, by SoftCat

User metadata
Rank Member
Rank
Member
reenigne wrote on 2025-06-25, 11:35:

That's more difficult to answer. What machine, and what EGA or VGA card? I can test my IBM VGA card in my 5160 if you like, but I'm fairly sure that it can saturate the bus (or very nearly) so about 356kB/s with REP MOVSW. But most EGA and VGA cards are in faster machines.

Thank you for the information and your desire to help!
I think there is no need to check. It is more or less clear to me that the entire screen cannot be updated in one frame.

I have another question. What if R9 = 2 or 3 is set in CGA graphics mode? Am I correct in understanding that with R9 = 2, lines with numbers 3*k and 3*k + 2 will be the same? And with R9 = 3, lines with numbers 4*k and 4*k + 2 will be the same, as well as lines with numbers 4*k + 1 and 4*k + 3?

Reply 84 of 97, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2025-06-25, 19:02:

I have another question. What if R9 = 2 or 3 is set in CGA graphics mode? Am I correct in understanding that with R9 = 2, lines with numbers 3*k and 3*k + 2 will be the same? And with R9 = 3, lines with numbers 4*k and 4*k + 2 will be the same, as well as lines with numbers 4*k + 1 and 4*k + 3?

Yes, that's correct. The RA0 (lowest bit of scanline number within row) is used to select between the 0xb8000-0xb9fff and 0xba000-0xbbfff pages in graphics modes. The RA1 and RA2 bits are only used in text mode, and the RA3 and RA4 bits are disconnected completely.

Reply 85 of 97, by SoftCat

User metadata
Rank Member
Rank
Member
reenigne wrote on 2025-06-25, 23:27:

Yes, that's correct. The RA0 (lowest bit of scanline number within row) is used to select between the 0xb8000-0xb9fff and 0xba000-0xbbfff pages in graphics modes. The RA1 and RA2 bits are only used in text mode, and the RA3 and RA4 bits are disconnected completely.

Got it, thanks.
So if you set R9 = 15 in text mode, the characters will be duplicated vertically?

Reply 86 of 97, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2025-06-26, 19:41:

So if you set R9 = 15 in text mode, the characters will be duplicated vertically?

They will!

Reply 87 of 97, by SoftCat

User metadata
Rank Member
Rank
Member
reenigne wrote on 2025-06-26, 19:44:

They will!

Thank you for your reply!
This site stopped opening for me, so I didn't reply for a long time. Now I'm logged in via VPN.

Reply 89 of 97, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2025-08-19, 20:34:
reenigne wrote on 2025-06-26, 19:44:

They will!

Here you change the Start Address when the electron beam is at the beginning of the visible part of scanline 0. Isn't it too late?
https://github.com/reenigne/reenigne/blob/mas … 00line/l100.asm

Well, it's too late for the scanline that's already started drawing. The change of start address will take effect at the start of the following CRTC frame.

Reply 90 of 97, by SoftCat

User metadata
Rank Member
Rank
Member
reenigne wrote on 2025-08-19, 21:22:

Well, it's too late for the scanline that's already started drawing. The change of start address will take effect at the start of the following CRTC frame.

Got it, thank you!

Reply 91 of 97, by SoftCat

User metadata
Rank Member
Rank
Member
reenigne wrote on 2025-08-19, 21:22:

Well, it's too late for the scanline that's already started drawing. The change of start address will take effect at the start of the following CRTC frame.

Can you tell me what parameters will come into effect in the current CRTC frame? I already know about R9.

Reply 92 of 97, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2025-08-20, 23:26:
reenigne wrote on 2025-08-19, 21:22:

Well, it's too late for the scanline that's already started drawing. The change of start address will take effect at the start of the following CRTC frame.

Can you tell me what parameters will come into effect in the current CRTC frame? I already know about R9.

Other than the start address, all of the registers can have an effect in the current frame. The CRTC compares its internal column, hsync column, scanline, vsync scanline, row, and address counters against the most recently programmed values in the programmable registers. So each one has a certain window in which it takes effect in the current CRTC frame (i.e. the value hasn't been hit yet and the programmed register value is not lower than the current counter value).

Reply 93 of 97, by superfury

User metadata
Rank l33t++
Rank
l33t++
reenigne wrote on 2025-08-21, 09:00:
SoftCat wrote on 2025-08-20, 23:26:
reenigne wrote on 2025-08-19, 21:22:

Well, it's too late for the scanline that's already started drawing. The change of start address will take effect at the start of the following CRTC frame.

Can you tell me what parameters will come into effect in the current CRTC frame? I already know about R9.

Other than the start address, all of the registers can have an effect in the current frame. The CRTC compares its internal column, hsync column, scanline, vsync scanline, row, and address counters against the most recently programmed values in the programmable registers. So each one has a certain window in which it takes effect in the current CRTC frame (i.e. the value hasn't been hit yet and the programmed register value is not lower than the current counter value).

So basically, all the values are 'live'. They are applied as soon as a match occurs (so mostly during each character clock).

It makes me wonder, what if you change video mode (text/graphics etc.) that affects sub-character clock pixels? Does the controller flush it's caches and immediately starts parsing it's now-to-fill buffers? Or incorrectly parse partially buffered data from the current 16-bit latched memory data (assuming latches work roughly like the VGA shift registers)?

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

Reply 94 of 97, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote on 2025-08-21, 09:26:

It makes me wonder, what if you change video mode (text/graphics etc.) that affects sub-character clock pixels? Does the controller flush it's caches and immediately starts parsing it's now-to-fill buffers? Or incorrectly parse partially buffered data from the current 16-bit latched memory data (assuming latches work roughly like the VGA shift registers)?

There's no cache to flush, but yes - the mode change will take place immediately and generally that means the fetched data is interpreted partly as text and partly as graphics.

Reply 95 of 97, by mkarcher

User metadata
Rank l33t
Rank
l33t
superfury wrote on 2025-08-21, 09:26:

Or incorrectly parse partially buffered data from the current 16-bit latched memory data (assuming latches work roughly like the VGA shift registers)?

The 6845 does not notice whether the CGA card is in text or graphics mode. The 6845 also doesn't care about pixels, just about characters. It doesn't even know the pixel clock (i.e. the 6845 doesn't notice that the MDA card has a 9-pixel character cell, but the CGA card has an 8-pixel character cell). The logic on the CGA card on the other hand does care about all this stuff, and if you re-program the mode register, the logic on the CGA card immediately changes behaviour, so this will include treating the state prepared for the old mode in a way that fits the new mode. As this is all dedicated logic, the CGA circuit diagrams are the primary documentation to find out what happens if you do creative stuff.

The circuit diagrams are fine until the moment propagation delays through the chips are no longer negligible. This is the point in which one should resort to experimenting with real hardware. This has been done for 8088 MPH, as the actual artifact colors generated by the CGA card depend on the exact timing produced by the multiplexers that switch between different phase-shifted variants of the color carrier clock.

Reply 96 of 97, by superfury

User metadata
Rank l33t++
Rank
l33t++

So in my implementation the MDA/CGA text mode and CGA/VGA graphics modes behave identically. The only difference is the parsing of the VRAM data, which happens at the character clock (every 4 or 8 pixels). At this point in time, on the MDA/CGA 2 bytes are fetched from VRAM (4 on EGA/VGA). This also applies memory behaviour (CPU overwriting the data).
It then, depending on the mode, splits it into 8 attribute input pixels and font/background selection bits, which depends on the video mode using 8 bit shifts.
For the next 8 clocks (can be 16/32 on the VGA) it starts sending the latched and predecoded(in text or graphic mode) data to the attribute controller (or CGA hardcoded version) one pixel at a time. The data sent is two things: the raw color(attribute) byte and font/background status (and req'd attribute status, like the current character line for underline and blink status(which is toggled each frame, as per hardware specs for the emulated card)). All the VGA attribute registers (still emulated on the CGA/MDA) are fully functional, just driven (written into deending on the used mode) by the CGA/MDA mode control and CGA color register. The attribute controller output is then either parsed by a DAC lookup(EGA/VGA) or the display mode (Simple CGA old/new color lookup(no difference though) or Reengine's NTSC routine. Both which caches the entire CGA/MDA scanline and renders the 4-bit pixels appropriately). The only difference is that graphics modes force the font bit on. The stuff that's sent is what's between the VGA sequencer and attribute controller (it's input pins. See the Tseng datasheets for the exact data sent). All else is determined by the emulated attribute controller (which is no more than a precalculated LUT (for it's inputs) and a toggle to merge multiple nibbles, bytes or words to create an 8 or 16-bit DAC index).
Vertical retrace also flips the double buffer in my GPU routines to write to a new zeroed screen buffer. If scanlines aren't rendered completely the same on all scanlines (the widest one detected applies), shorter scanlines will display black.

So in short, the memory data is latched at the character clock and split into font bits and attribute color to use. Then it does NOPs for 7 pixel clocks afterwards, as it shifts out the latched values one pixel at a time into the attribute controller, which handles the color logic. It's output is on the CGA/MDA written to a single scanline buffer (1 byte per pixel), which at horizontal retrace is rendered onto the display buffer in either direct colors or NTSC mode. All other basic display handling is the same as in my EGA/(S)VGA implementation (only differences being some slight CGA adjustments, but it's mostly intact).

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

Reply 97 of 97, by SoftCat

User metadata
Rank Member
Rank
Member
reenigne wrote on 2025-08-21, 09:00:

Other than the start address, all of the registers can have an effect in the current frame. The CRTC compares its internal column, hsync column, scanline, vsync scanline, row, and address counters against the most recently programmed values in the programmable registers. So each one has a certain window in which it takes effect in the current CRTC frame (i.e. the value hasn't been hit yet and the programmed register value is not lower than the current counter value).

Got it, thanks!
And on PCjr and Tandy in 320x200 16 colors and 640x200 4 colors modes, the 6845 controller generates addresses for 16-bit data with a frequency of ~1.79 MHz? That is, if you do not use bit planes, then even with a VRAM size of 64 KB it will not handle the 640x200 16 color mode? Since for this, the 6845 will have to work at a frequency of ~3.58 MHz.