• Please review our updated Terms and Rules here

CGA Mode 4 colours --- working on CGA, failing on EGA?

stepleton

Veteran Member
Joined
Jan 1, 2020
Messages
535
Location
London, UK
I've swapped my (IBM original) CGA card for an (IBM) EGA card in my 5170. It's set up to drive a 5153 for now --- the 5154 still needs fixing.

A while ago I wrote my first x86 assembly program, which does a bit of CGA graphics in Mode 4 (and also Mode 5). The code successfully sets the Mode 4 palette on the CGA card, but it doesn't work for the EGA card. I'm not sure why this is; I was hoping someone here might know.

The code I use to set the options for the video mode runs after the video mode is chosen via an INT 10h call. It writes directly to the CGA colour control register and looks like this:

Code:
    ; Setting flags in the CGA colour control register
    xor   al,al           ; Clear al --- no options yet
    mov   ah,2[bx]        ; Copy intense colours choice to ah
    test  ah,ah           ; Is it zero?
    jz    .f2             ; Skip ahead
    or    al,10h          ; Wasn't zero, set bit 4: want intense colours
.f2 mov   ah,3[bx]        ; Copy palette choice to ah
    test  ah,ah           ; Is it zero?
    jz    .f3             ; Skip ahead
    or    al,20h          ; Wasn't zero, set bit 5: want cyan/magenta/white
.f3 mov   dx,kCgaCcrPort  ; Address of the colour control register (03d9h)
    out   dx,al           ; Push config to the colour control register

    ; Copy the flags to the BIOS CGA colour control register value mirror
    mov   bx,0040h        ; Set ES segment base address to $40, home of...
    mov   es,bx           ; ...DOS bios variables
    mov   es:066h,al      ; Copy flags to the colour control register mirror

The bx register points at a four-byte data structure like this one:

Code:
    db 0    ; Unused
    db 0    ; Boolean: enter mode 5 instead of mode 4?
    db 1    ; Boolean: intense colours instead of dim ones?
    db 1    ; Boolean: cyan/magenta/white instead of red/yellow/green?

I hate to ask folks to debug my work, but is there a reason this shouldn't switch the colour palette and intensity in Mode 4 for my EGA card? I know my EGA card is capable of switching Mode 4 colour palettes because I see other programs pulling it off (e.g. CheckIT's video tests). All I get, though, is the classic, dull CGA cyan/magenta/white pallete. I think even my attempts to select Mode 5 result in original-palette Mode 4. Is there something else I should be doing?
 
What passes for CGA compatibility on the EGA is only on the BIOS level - the registers aren't all there. In particular EGA doesn't have Color and Mode Control registers at 03d8/9h, so the code at .f3 will have no effect.

EGA has other registers to set the palette (here's one reference: https://pdos.csail.mit.edu/6.828/2018/readings/hardware/vgadoc/EGAREGS.TXT). But if you don't want to end up adding new code for each card you support, you should probably use BIOS calls whenever possible:

Int 10/AH=00h - VIDEO - SET VIDEO MODE
Int 10/AH=0Bh/BH=01h - VIDEO - SET PALETTE

However... since you mention the cyan/red/white palette - it's not available through the second BIOS service, and only CGA will get you that palette when you set mode 5 (it's a bit of a side-effect of the Mode Control register implementation).
That's why mode 5 games generally have the standard cyan/mag/white color set when they're run on an EGA/VGA. On the other hand, this too can be fixed using BIOS services:

Int 10/AX=1000h - VIDEO - SET SINGLE PALETTE REGISTER (PCjr,Tandy,EGA,MCGA,VGA)
Int 10/AX=1002h - VIDEO - SET ALL PALETTE REGISTERS (PCjr,Tandy,EGA,VGA)

So for a cyan/red/white palette that's compatible with CGA as well as EGA, you want to set mode 5, then use one of the above to set palette index #2 to red. The latter will do nothing on a CGA card except fail silently, IIRC.
 
you should probably use BIOS calls whenever possible
Thanks again for this insight. Looking through the INT 10h options: it seems there's no way to change the mode 4 palette intensity setting (colour control register bit 4) with BIOS services. Is this correct, or do you think I've missed something?

ETA: I guess I could just set the colours manually using those last two BIOS calls you mentioned!
 
Last edited:
Thanks again for this insight. Looking through the INT 10h options: it seems there's no way to change the mode 4 palette intensity setting (colour control register bit 4) with BIOS services. Is this correct, or do you think I've missed something?

ETA: I guess I could just set the colours manually using those last two BIOS calls you mentioned!

Ah, right - forgot to mention this one: Int 10/AH=0Bh/BH=00h - VIDEO - SET BACKGROUND/BORDER COLOR
Surprisingly Ralf Brown's Interrupt List doesn't mention this, but here BL controls palette intensity as well as the background color. Intensity is set by bit 4, so you set BL=0...15 for the low-intensity variant, and 16..31 for high intensity.
Found an example program here: https://retrocomputing.stackexchang...rker-cga-palette-using-x86-assembly/8656#8656.

Seems like this should work on EGA/VGA too, so if you only want to modify the intensity, those other two calls aren't needed!
 
Back
Top