I've known for a while that it is possible to achieve a pseudo 160 by 100 graphics mode on the IBM CGA by using the CRTC to change line height to two pixels. I've been trying to accomplish this for a few days now, coming to a dead end.
The Intel® Open Source HD Graphics and Intel Iris™ Graphics Programmer's Reference Manual claims I can do this on page 45 (or page 59 in the PDF) by writing to the Maximum Scanline Register, or that's what I interpret from it.
I've tried writing directly to memory address 3B5 with a value of 00000001b, or the code for 2 scanlines, I believe. This did nothing at all when I tested it in DOSBox.
If you want to see the code I wrote which will assemble in NASM:
BITS 16
xor bx,bx
mov ax, 3b5h
mov es, ax
mov ah, 00000001b
mov BYTE [es:bx], ah ; write 00000001b to 0x03b5:0000, right?
cli
hlt
I am not yet very confident with low-level stuff like this, and any help would be appreciated.
You're not writing to address 3b5h, you're writing to address 3b50h. If you wanted to write address 3b5h you'd load ES with 0 and then do something like mov BYTE [es:3b5h], 01
, but that's not what you want to do either. The address 3b5h given in the manual you linked is an "I/O address", meaning that it lives in a completely different address space, one that you need to use the specialized IN and OUT instruction to access.
To write the value 01 to I/O address 3b5h you'd use code like this:
mov dx, 3b5h
mov al, 01
out dx, al
Note that is the only form of the OUT instruction you can use here. You must use the DX register to specify the address and the AL register to provide the data to write to that I/O address.
Except that's not right either. As the manual you linked explains, the I/O address 3b5h is the MDA data port, the CGA data port is at I/O address 3d5h. Finally, the "Maximum Scanline Register" isn't the only register accessed through I/O address 3d5h. There are several different registers that use this address. To select which register you want to write to you first need to selet it by writing its index value to the CGA CRT Controller Index Register at I/O address 3d4h. This means your code needs to look like this:
mov dx, 3d4h ; CGA CRTC Index Register
mov al, 09h ; Maximum Scan Line Reigster
out dx, al
mov dx, 3d5h ; CGA CRTC Data Port
mov al, 01 ; 2 scan lines
out dx, al
Note that this still may not be right, as VGA adds other parameters to the Maximum Scan Line Register. You may need to preserve these values, though on actual CGA hardware that's not possible since the register is read-only. It may depend on how accurately whatever you're running your code under emulates a real CGA video card.