Reply 60 of 87, by SoftCat
Could you please write in more detail what will happen if 0x18 and 0x19 are written to port 0x3d8?
And I am also wondering, to which output was the monochrome CGA monitor connected?
Could you please write in more detail what will happen if 0x18 and 0x19 are written to port 0x3d8?
And I am also wondering, to which output was the monochrome CGA monitor connected?
SoftCat wrote on 2025-06-21, 16:19:Could you please write in more detail what will happen if 0x18 and 0x19 are written to port 0x3d8?
0x18 is +1BPP-GRPH-HRES. The -GRPH part (i.e. bit 1 not set) means that this acts as a text mode. It's 40-column text mode since the +HRES bit isn't set. However, +1BPP being active also means that the mechanism for generating the 640x200x2 screen is also active, which causes pixels that would be black in the 640x200x2 screen to be black on this screen - the VRAM bytes that the CGA card reads are interpreted both as a character+attribute pair and as a 16-bit mask (set pixels in the mask allow the text mode screen to be displayed). The VRAM addressing is as for text mode, so all scanlines within a character row will have the same pixels masked out (unlike in graphics modes where even scanlines are read from 0xb8000-0xb9fff and odd scanlines are read from addresses 0xba000-0xbbfff).
0x19 is +1BPP-GRPH+HRES - the equivalent but in 80-column text mode. In this case the +1BPP screen would be 1280x200 but the CGA can't output pixels that fast so only every other bit of the mask is used (I forget offhand whether it's the even bits or the odd bits).
SoftCat wrote on 2025-06-21, 16:19:And I am also wondering, to which output was the monochrome CGA monitor connected?
Either. There were both TTL monochrome CGA monitors and composite monochrome CGA monitors. The internal monitor in the IBM 5155 portable computer was a composite monochrome monitor.
reenigne wrote on 2025-06-21, 16:40:0x18 is +1BPP-GRPH-HRES. The -GRPH part (i.e. bit 1 not set) means that this acts as a text mode. It's 40-column text mode since the +HRES bit isn't set. However, +1BPP being active also means that the mechanism for generating the 640x200x2 screen is also active, which causes pixels that would be black in the 640x200x2 screen to be black on this screen - the VRAM bytes that the CGA card reads are interpreted both as a character+attribute pair and as a 16-bit mask (set pixels in the mask allow the text mode screen to be displayed). The VRAM addressing is as for text mode, so all scanlines within a character row will have the same pixels masked out (unlike in graphics modes where even scanlines are read from 0xb8000-0xb9fff and odd scanlines are read from addresses 0xba000-0xbbfff).
0x19 is +1BPP-GRPH+HRES - the equivalent but in 80-column text mode. In this case the +1BPP screen would be 1280x200 but the CGA can't output pixels that fast so only every other bit of the mask is used (I forget offhand whether it's the even bits or the odd bits).
A bit complicated. But these are probably useless modes.
reenigne wrote on 2025-06-21, 16:40:Either. There were both TTL monochrome CGA monitors and composite monochrome CGA monitors. The internal monitor in the IBM 5155 portable computer was a composite monochrome monitor.
Got it, thanks.
SoftCat wrote on 2025-06-21, 19:29:A bit complicated. But these are probably useless modes.
Yeah. I think +HRES+GRPH-1BPP is more useful, particularly with composite output. It sort of gives you a 640x200x4 mode, which translates into something like a 160x200x256 mode with 1 byte per pixel. Of course, there is only enough VRAM for 100 rows but there should be a way to make it 160x100x256 which would be very nice for a lot of things. However, the other complication is that in +HRES the attribute bytes are latched at the wrong times for +GRPH and if you write bytes ABCDEFGHIJ into VRAM they come out as CDEDGHIH. If horizontal total is odd (i.e. R0 is even) then the odd lines would be CBEFGFIJ so each byte of VRAM covers the same screen area but some are "moved" from where you'd really want them to be. But it could still be useful. I've been trying to get it to work today (inspired by this conversation) but getting the scanlines in the right order and getting a stable image is tricky.
reenigne wrote on 2025-06-21, 20:36:Yeah. I think +HRES+GRPH-1BPP is more useful, particularly with composite output. It sort of gives you a 640x200x4 mode, which translates into something like a 160x200x256 mode with 1 byte per pixel. Of course, there is only enough VRAM for 100 rows but there should be a way to make it 160x100x256 which would be very nice for a lot of things. However, the other complication is that in +HRES the attribute bytes are latched at the wrong times for +GRPH and if you write bytes ABCDEFGHIJ into VRAM they come out as CDEDGHIH. If horizontal total is odd (i.e. R0 is even) then the odd lines would be CBEFGFIJ so each byte of VRAM covers the same screen area but some are "moved" from where you'd really want them to be. But it could still be useful. I've been trying to get it to work today (inspired by this conversation) but getting the scanlines in the right order and getting a stable image is tricky.
Maybe it would be better to do 512x128x4 or 128x128x256? In case of 640 columns, there is enough memory for 102 lines: 640x102x4 or 160x102x256.
There is +HRES and snow suppression. Will there be snow?
SoftCat wrote on 2025-06-22, 11:37:Maybe it would be better to do 512x128x4 or 128x128x256? In case of 640 columns, there is enough memory for 102 lines: 640x102x4 or 160x102x256.
Yes, all of those are possible (although with the duplicated columns problem).
SoftCat wrote on 2025-06-22, 11:37:There is +HRES and snow suppression. Will there be snow?
No, there is no snow - the CPU updates happen in the repeated columns.
If R6 = 102 (or 100) and R9 = 1, will there be duplication of lines? To occupy the whole screen.
SoftCat wrote on 2025-06-22, 13:25:If R6 = 102 (or 100) and R9 = 1, will there be duplication of lines? To occupy the whole screen.
Vertical-wise it works like a graphics mode. So if you do that then the even lines will come from 0xb8000-0xbafff and the odd lines will come from 0xbb000-0xbcfff. There's only enough VRAM for ~102 lines like that so the graphics from the top half of the screen would be repeated in the bottom half.
reenigne wrote on 2025-06-22, 13:32:Vertical-wise it works like a graphics mode. So if you do that then the even lines will come from 0xb8000-0xbafff and the odd lines will come from 0xbb000-0xbcfff. There's only enough VRAM for ~102 lines like that so the graphics from the top half of the screen would be repeated in the bottom half.
Got it, thanks for the explanation.
Or maybe by changing the border color you can change the "composite palette"? If, for example, you set a color for synchronization that is different from brown.
SoftCat wrote on 2025-06-22, 18:57:Or maybe by changing the border color you can change the "composite palette"? If, for example, you set a color for synchronization that is different from brown.
Yes, that's something that's always possible in composite modes. By putting text characters (8088 MPH style) in the space where the monitor looks for the color burst it should be possible to have quite fine control over the phase and do some interesting hue-shifting effects. Though the results might be somewhat monitor-dependent. It's another CGA trick I've had in mind for a future demo.
SoftCat wrote on 2025-06-11, 22:02:reenigne wrote on 2025-06-10, 10:53:The clock used by the CGA card is the one on the motherboard, so you'd have to overclock the entire system (or make more extensive hardware modifications). It will work as long as every part of the system can cope with the higher clock rate. In an IBM PC 5150 or 5160, for example, the CPU is normally rated for 5MHz but you'd be driving it at 5.333MHz which may or may not work. It may work for a while but be unstable executing certain operations or be temperature dependent. Early PCs also pushed the DRAM technologies of the day close to their limits. Most other parts are likely to work but not guaranteed.
If you'd like to play with a CGA-esque system that has a 16MHz pixel clock, you could try getting hold of a BBC Micro. That also has a video subsystem based on the 6845 but uses a 16MHz crystal (character clock of 2MHz, 1MHz or 500kHz and pixel clock of 16MHz, 8MHz, 4MHz or 2MHz). Then you'd know the system would be stable, and other people could run any games or demos you made that way!
By the way, there is a CGA-like video card Compaq CNT75M525, which has a quartz crystal at 18.981 MHz. Photo here:
https://drive.google.com/drive/folders/11x0_- … ?usp=drive_link
18.981 MHz reminds me of the 19 MHz oscillator that the Hercules InColor card uses to trivially change the timings of MDA and Hercules modes to something an EGA monitor accepts as input.
Since the Compaq Portable had a CGA+MDA hybrid card, this could be something similar that runs both, CGA and MDA modes with a 60 Hz vertical refresh rate.
What I can contribute to the main topic of this thread is the tweaked text mode I added to the Planet X3 engine, along with the converter programs that take low-res Tandy artwork as input:
What you see here is a 40x100 text mode with 8x2 character cells. Everything but the font is the unaltered output of the automated conversion process.
All relevant code, namely engine and converters, is on GitHub: https://github.com/planet-x3
reenigne wrote on 2025-06-22, 19:58:Yes, that's something that's always possible in composite modes. By putting text characters (8088 MPH style) in the space where the monitor looks for the color burst it should be possible to have quite fine control over the phase and do some interesting hue-shifting effects. Though the results might be somewhat monitor-dependent. It's another CGA trick I've had in mind for a future demo.
Okay, I'll watch this demo.
Benedikt wrote on 2025-06-22, 19:59:18.981 MHz reminds me of the 19 MHz oscillator that the Hercules InColor card uses to trivially change the timings of MDA and Hercules modes to something an EGA monitor accepts as input.
Since the Compaq Portable had a CGA+MDA hybrid card, this could be something similar that runs both, CGA and MDA modes with a 60 Hz vertical refresh rate.
This is interesting.
Benedikt wrote on 2025-06-22, 19:59:What you see here is a 40x100 text mode with 8x2 character cells. Everything but the font is the unaltered output of the automated conversion process.
All relevant code, namely engine and converters, is on GitHub: https://github.com/planet-x3
Thank you for the link.
On CGA you can set the text mode to 40x200 with the character size 8x1. This will be pseudo-graphics 160x200 with 16 colors. But only in this case the CRTC trick is used, which not all PC emulators understand. For example, DOSBox does not understand.
I've been thinking a bit. Usually people do vertical scanline tricks to get more scanlines on the screen. Do people do the same horizontally too? Like pushing horizontal retrace past horizontal total temporarily, if a card allows it?
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io
superfury wrote on 2025-06-23, 00:22:I've been thinking a bit. Usually people do vertical scanline tricks to get more scanlines on the screen. Do people do the same horizontally too? Like pushing horizontal retrace past horizontal total temporarily, if a card allows it?
I have already suggested using a 16.257 MHz quartz crystal on EGA in all 200-line modes without changing the horizontal and vertical synchronization frequencies. The corresponding 768x200 mode has been tested, but not everyone believes me yet. I think that it is even possible to make 800x240.
Similarly, a 28.322 MHz quartz crystal can be used on VGA in all modes where a 25.175 MHz quartz crystal is used. In this case, the horizontal resolution will increase by 9/8 times.
And Trixter also has a video where 720 columns fit on CGA without changing the horizontal frequency.
superfury wrote on 2025-06-23, 00:22:I've been thinking a bit. Usually people do vertical scanline tricks to get more scanlines on the screen. Do people do the same horizontally too? Like pushing horizontal retrace past horizontal total temporarily, if a card allows it?
The question doesn't make sense to me. If you "push horizontal retrace past horizontal total", you will not get a sync pulse at all, because at horizontal total the card will stop counting and restart at 0, so it will not get to the character count that starts the retrace. You can convert the overscan area (aka border) into more content, as long as you have enough video RAM left. You might need to fine-tune the retrace position to get the image to the exact center of the screen if you want to max out to the left and right edge of the viewable area.
You are not supposed to change the horizontal frequency significantly on a fixed-frequency monitor, so just adding "more pixels" to the scan line, dropping horizontal frequency and possibly have the user re-tune horizontal hold and horizontal size is not a valid option. You can do similar things for vertical, though.
SoftCat wrote on 2025-06-23, 00:50:I have already suggested using a 16.257 MHz quartz crystal on EGA in all 200-line modes
This is a valid option, though: If you make pixels smaller (higher pixel clock, so more pixels at the same scan rate), you get more pixels into the same area. This requires you to have a video card that offeres different pixel clocks (i.e. not an MDA or a CGA card).
SoftCat wrote on 2025-06-23, 00:50:Similarly, a 28.322 MHz quartz crystal can be used on VGA in all modes where a 25.175 MHz quartz crystal is used. In this case, the horizontal resolution will increase by 9/8 times.
This is actually not that uncommon, e.g. the highest non-SVGA video mode in Quake is 360x480.
In the CGA that would effectively resolve to:
1. Wait for horizontal retrace
2. Program horizontal retrace start past horizontal total to prevent it
3. Wait known time manually to when horizontal total just occurred, but before the second horizontal retrace start.
4. Restore horizontal retrace to be within range again (clocks past programmed horizontal total)
5. Back to step 1
Unless horizontal total affects memory address counters, this would result in more clocks. Basically it's done the same way as the vertical 8088 MPH trick used with it's 1-row font (getting rid of the second row) 1024 color modes to obtain the limited output, but with interrupt (or cycle counted) timing to do that horizontally instead?
At least that should work on EGA/(S)VGA, don't remember if CGA horizontal total allows that.
If it can't work with a CGA monitor, perhaps with a VGA converter added?
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io
superfury wrote on 2025-06-23, 00:22:I've been thinking a bit. Usually people do vertical scanline tricks to get more scanlines on the screen. Do people do the same horizontally too? Like pushing horizontal retrace past horizontal total temporarily, if a card allows it?
Area 5150 does this in order to get a new start address on every CRT scanline. The minimum CRTC frame size on MC6845 is two CRTC scanlines so I needed to fit them both on one CRT scanline, which involves 8 CRTC writes per scanline in a fairly precisely-timed dance.
reenigne wrote on 2025-06-24, 13:35:superfury wrote on 2025-06-23, 00:22:I've been thinking a bit. Usually people do vertical scanline tricks to get more scanlines on the screen. Do people do the same horizontally too? Like pushing horizontal retrace past horizontal total temporarily, if a card allows it?
Area 5150 does this in order to get a new start address on every CRT scanline. The minimum CRTC frame size on MC6845 is two CRTC scanlines so I needed to fit them both on one CRT scanline, which involves 8 CRTC writes per scanline in a fairly precisely-timed dance.
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?
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io
mkarcher wrote on 2025-06-23, 21:55:This is actually not that uncommon, e.g. the highest non-SVGA video mode in Quake is 360x480.
On VGA, the maximum 256-color mode is 360x512 and the maximum 16-color mode is 720x512.