VOGONS


CGA pseudo-graphic modes

Topic actions

First post, by SoftCat

User metadata
Rank Member
Rank
Member

Is it possible to make a pseudo-graphic mode 128x128 (with R9 = 0) on CGA? How should CRTC be programmed? Everything is clear with horizontal parameters. What about vertical parameters? There will probably be more than one area.

Reply 1 of 37, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2025-06-04, 14:11:
reenigne wrote on 2025-06-04, 13:28:

The easy way is to read the CGA status register in a tight loop. Or rather several tight loops: one to find the vsync pulse, then one to find the start of the active area, then as many as you need to find the scanline that you want. Once you've synchronised the CPU with the CRTC you can reprogram CRTC registers on particular scanlines to set up the sequence of CRTC frames that you want. For example, you might set up a 127 scanline frame, then a 135 scanline frame. You'll need to program the vertical sync position register differently in the different CRTC frames as well as vertical total adjust and vertical displayed. You might also want to change the start address registers if you don't want to display the same thing in both frames. https://github.com/reenigne/reenigne/blob/mas … 00line/l100.asm is the source for the portraits effect in 8088 MPH so you can study that as an example and play around with it.

That way involves the CPU spending a lot of time reading the CGA status register, so the more advanced way is to set up the PIT to fire IRQ0 at appropriate times in the frame. By programming new periods into port 0x40 (without resetting the PIT by writing to port 0x43) you can have IRQ0s occurring at irregular intervals (e.g. scanline 0 and 100). We used that trick in some places in 8088 MPH and Area 5150. It leaves more CPU time free for other things, but is more complicated to set up, and one must be aware that interrupts being disabled for too long might lead to the effect breaking.

Thank you very much for your detailed answer!
Please tell me, is it necessary to add 1 to registers R2, R3 and R7 to get the corresponding values? That is, if, for example, R3 = 15, then horizontal sync width = 15 or 16? Otherwise, they write differently everywhere.

No, none of these registers have a +1 (only R9 and the "total" registers R0 and R4). If R3 is programmed to 15 then the horizontal sync width will be 15 characters. However, there is a difference between CRTCs with R3=0: some give a horizontal sync pulse 16 characters wide and some give no horizontal sync pulse at all.

What do you mean by "They write differently everywhere"?

Reply 3 of 37, by SoftCat

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

No, none of these registers have a +1 (only R9 and the "total" registers R0 and R4). If R3 is programmed to 15 then the horizontal sync width will be 15 characters. However, there is a difference between CRTCs with R3=0: some give a horizontal sync pulse 16 characters wide and some give no horizontal sync pulse at all.

Can you tell me if the total number of lines in EGA in 200-line modes is 260 or if you need to add 2 and it will be like on CGA, also 262?

Reply 4 of 37, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2025-06-04, 14:52:
Got it, thank you very much! Here in this documentation for Hercules (there is also 6845) it is written differently. Pages 9-10, […]
Show full quote
reenigne wrote on 2025-06-04, 14:16:

What do you mean by "They write differently everywhere"?

Got it, thank you very much!
Here in this documentation for Hercules (there is also 6845) it is written differently. Pages 9-10, in PDF 7-8.
https://minuszerodegrees.net/manuals/He ... Manual.pdf

I don't know why it would be different there. Perhaps the Hercules card has hardware which changes the position and width of the sync pulse - I don't have a schematic to hand to check. But in terms of when CRTC writes need to happen to have the desired effect, it will work the same as on a CGA card (assuming that it's the same CRTC chip).

Reply 5 of 37, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2025-06-04, 15:26:
reenigne wrote on 2025-06-04, 14:16:

No, none of these registers have a +1 (only R9 and the "total" registers R0 and R4). If R3 is programmed to 15 then the horizontal sync width will be 15 characters. However, there is a difference between CRTCs with R3=0: some give a horizontal sync pulse 16 characters wide and some give no horizontal sync pulse at all.

Can you tell me if the total number of lines in EGA in 200-line modes is 260 or if you need to add 2 and it will be like on CGA, also 262?

Yes, that's my understanding too - it's -2 for EGA instead of -1 for CGA because of an additional layer of latching in the EGA's CRTC.

Reply 6 of 37, by SoftCat

User metadata
Rank Member
Rank
Member
reenigne wrote on 2025-06-06, 12:46:

Yes, that's my understanding too - it's -2 for EGA instead of -1 for CGA because of an additional layer of latching in the EGA's CRTC.

Thank you for your answer!
And what if on CGA we do this: R4 = 127, R5 = 31 and R9 = 0? The frame rate will be approximately 98.74 Hz. Was this checked on a real CGA monitor?
And it’s also interesting: with R4 = 0 (with R9 = 0) will there be one line or 129 lines?

Reply 7 of 37, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2025-06-06, 13:07:
reenigne wrote on 2025-06-06, 12:46:

Yes, that's my understanding too - it's -2 for EGA instead of -1 for CGA because of an additional layer of latching in the EGA's CRTC.

Thank you for your answer!
And what if on CGA we do this: R4 = 127, R5 = 31 and R9 = 0? The frame rate will be approximately 98.74 Hz. Was this checked on a real CGA monitor?

As far I know nobody has checked this but I don't think there's any need to - CGA monitors will only have a stable image if the vertical sync rate is close to 60Hz. I can try it if you like but I'd be amazed if the result was anything other than a vertically rolling image (such as you'd see on a TV or monitor with incorrectly adjusted vertical hold control).

SoftCat wrote on 2025-06-06, 13:07:

And it’s also interesting: with R4 = 0 (with R9 = 0) will there be one line or 129 lines?

This is another one that depends on the CRTC make/model involved. On the MC6845 on my CGA card, it gives a high number of lines (probably 129 as you say but I didn't actually count them). This is why I had to do the trick described in https://martypc.blogspot.com/2025/05/emulator … 5150s-lake.html (two CRTC lines per CRT scanline) to be able to choose a new start address on each scanline. But many Amstrad CPC demos use R4=R9=0 to change the address on every scanline - those don't work on MC6845 but do work on the Amstrads that use other CRTC types.

Reply 8 of 37, by SoftCat

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

I can try it if you like but I'd be amazed if the result was anything other than a vertically rolling image (such as you'd see on a TV or monitor with incorrectly adjusted vertical hold control).

I see, thanks for the information.
If it's not too much trouble, please try it whith R4 = 127, R4 = 0 and R5 = 31.

Reply 9 of 37, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2025-06-06, 14:16:
reenigne wrote on 2025-06-06, 13:53:

I can try it if you like but I'd be amazed if the result was anything other than a vertically rolling image (such as you'd see on a TV or monitor with incorrectly adjusted vertical hold control).

I see, thanks for the information.
If it's not too much trouble, please try it whith R4 = 127, R4 = 0 and R5 = 31.

Here you go (R9 = 0): http://reenigne.mooo.com:8088/20250606_154043.mp4

Reply 13 of 37, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie

Yes, looks like the right one to me.

Reply 14 of 37, by SoftCat

User metadata
Rank Member
Rank
Member
reenigne wrote on 2025-06-07, 21:12:

Yes, looks like the right one to me.

Got it, thanks for watching.
I found an amazing thing on CGA. It is quite possible that this has been known for a long time. It turns out that using the first line of the first 128 characters and their inversions (when the colors of the character and background change places) you can implement all 16 combinations with doubled pixels:
00000000
00000011
00001100
00001111
00110000
...
11111111
And this means that you can make a full-fledged pseudo-graphic mode 256x128 (or 320x102) with 16 colors and with R9 = 0.
By the way, DOSBox does not understand CRTC reprogramming on the fly, but it does not care what the total number of lines is and what the frame rate is.

Reply 15 of 37, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie

I have known this myself for a while, but haven't used it in a demo effect yet. I did put it into my CGAArt matcher (as "attribute clash" mode).

Reply 16 of 37, by SoftCat

User metadata
Rank Member
Rank
Member
reenigne wrote on 2025-06-08, 16:21:

I have known this myself for a while, but haven't used it in a demo effect yet. I did put it into my CGAArt matcher (as "attribute clash" mode).

And if I want to do it on CGA like this:
---------------------
1 character line - 8 scan lines (R9 = 7);
64 character lines - 3 scan lines (R9 = 2);
1 character line - 8 scan lines (R9 = 7).
---------------------
Total visible 8 + 64*3 + 8 = 208 scan lines.
Will I need to make 3 areas, and the first two will be without vertical sync pulse? Or will it be possible to do it some other way?

Reply 17 of 37, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie

You can change R9 at any point and it will take effect the next time that current row address equals R9 (probably at some specific point on the scanline - I'm not sure which one offhand). So you don't need a full CRTC restart like you do if you're making more than 128 rows or want to change the start address independently on different areas of the screen. Instead you just need to change R9 on the correct scanlines (I suggest doing it on scanline 0 of the rows that you want to be a different height from the row above). So for this arrangement you'd want 6 scanlines of adjust, 64 scanlines of 8-scanline rows, and 192 scanlines of 3-scanline rows. So that's a vertical total of 8+64 = 72 (R4 = 0x47). The vertical sync position should be on scanline 224 but that is now row 68 so R7 = 0x44. Everything else remains the same except that you set R9 = 2 on scanline 8 and R9 = 7 on scanline 200.

Reply 18 of 37, by VileR

User metadata
Rank l33t
Rank
l33t
reenigne wrote on 2025-06-08, 16:21:

I have known this myself for a while, but haven't used it in a demo effect yet. I did put it into my CGAArt matcher (as "attribute clash" mode).

I'd say that pretty much describes what's happening in Area 5150's intro. The text especially, i.e. arbitrary 40-column character patterns pieced together from 80-column glyph sections: the fact that first scanlines of the ROM patterns contain those 16 possible double-pixel sequences is just what this relies on.

That kinda goes for the Keen sprites too (since the originals also have double the dot width), except that the attribute clash is inevitably visible there. IIRC I had to try all the animation frames at different offsets within the character cell, and just picked the one that made it less apparent...

[ WEB ] - [ BLOG ] - [ TUBE ] - [ CODE ]

Reply 19 of 37, by SoftCat

User metadata
Rank Member
Rank
Member
reenigne wrote on 2025-06-09, 18:40:

You can change R9 at any point and it will take effect the next time that current row address equals R9 (probably at some specific point on the scanline - I'm not sure which one offhand). So you don't need a full CRTC restart like you do if you're making more than 128 rows or want to change the start address independently on different areas of the screen. Instead you just need to change R9 on the correct scanlines (I suggest doing it on scanline 0 of the rows that you want to be a different height from the row above). So for this arrangement you'd want 6 scanlines of adjust, 64 scanlines of 8-scanline rows, and 192 scanlines of 3-scanline rows. So that's a vertical total of 8+64 = 72 (R4 = 0x47). The vertical sync position should be on scanline 224 but that is now row 68 so R7 = 0x44. Everything else remains the same except that you set R9 = 2 on scanline 8 and R9 = 7 on scanline 200.

Thank you very much for the detailed explanation!
I am also wondering if it is possible to install a 16.000 MHz quartz oscillator on a CGA video card (or 16.000 MHz quartz crystal on a motherboard instead of a 14.318 MHz quartz crystal)? In this case, set R0 = 0x7F, R1 = 0x60, etc. Of course, composite colors should not be used.