3

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
verbicide
  • 41
  • 3
  • 2
    Have you configured a CGA graphics adapter in DOSBOX? – fuz Sep 05 '16 at 21:46
  • DOSBox is an emulator / virtual machine. Code running inside it will see a whole machine, but its behaviour is entirely determined by the DOSBox software, not by the hardware of the host that DOSBox is running on. The Intel manual may be a useful source of documentation about VGA/CGA, but keep in mind that any Intel-specific features or behaviour it documents won't happen in DOSBox. You could boot your code on the bare hardware if you wanted to program your actual Intel HW. See also the [x86 tag wiki](http://stackoverflow.com/tags/x86/info) for lots of x86 links (none directly relevant). – Peter Cordes Sep 05 '16 at 22:27
  • A simpler way to get a pseudo 160x100 graphics mode might to use the standard 80x50 VGA text mode and a custom font with 2x2 block characters. Another alternative would be to use VGA's 320x200 graphics mode and just double width and height of the pixels when you draw them. – Ross Ridge Sep 05 '16 at 23:22
  • I understand that DOSBox is an emulator. I'm wanting to get this to work in DOSBox because DOSBox is currently configured to run in CGA. Since I don't have access to the actual hardware, I'm resorting to emulators. – verbicide Sep 08 '16 at 00:55

1 Answers1

8

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Ross Ridge
  • 38,414
  • 7
  • 81
  • 112