1

I'm trying to use the int 10h, AH=13h function to print a string in graphic mode, and I get that the value in BL in the high and low bits correspond to the background and foreground colors, but I just can't get it to work.

For example, I'm trying to print a string of black text on a white background so I write mov bl, 11110000b or 0f0h, but it reads it only as a foreground color of 0f0h and not a background of 0fh and a foreground of 0. Does anybody know why this is happening?

zx485
  • 28,498
  • 28
  • 50
  • 59
yaya1711
  • 11
  • 2
  • which graphics/text mode are you in? The 1:3:4 or 4:4 way is for text modes (and actually ah=13h is not common to be used, so who knows how well emu8086 emulates it). [MCVE] ? – Ped7g Jun 09 '18 at 20:55
  • I'm in the 320x200 256 color graphics mode. – yaya1711 Jun 09 '18 at 21:00
  • Then `bl` is foreground colour, 8 bit. What does "Int 10/AH=0Bh/BH=00h - VIDEO - SET BACKGROUND/BORDER COLOR" do? (too lazy to try myself, and I have no experience with 320x200 manipulation through BIOS, as it was damn slow, so we always did use our own draw routines writing directly to `A000:0000`.) – Ped7g Jun 09 '18 at 21:20

1 Answers1

1

The BIOS.DisplayString function 13h cannot display a background color other than black. This is especially true in the 256-color video mode where the attribute in BL can no longer express both a foreground and a background color since the foreground color setting already occupies the whole 8 bits.

I have written a procedure that can display an ASCIIZ string on the 256-color screen using one of 16 foreground colors and one of 16 background colors. The string is unlimited in how long it is or in what it can contain (bell, backspace, tab, linefeed, carriage return).

Eventhough the code uses BIOS for everything, DOSBox paints the whole screen in a jiffy. If this is still not fast enough, then fetch a pointer to the font and write directly to the screen at A000:0000. You would also have to manage the cursor yourself. I'm sure it would be faster but I doubt it would matter...

      ORG     256

      mov     ax, 0013h       ; BIOS.SetVideo 320x200 256-color graphics screen
      int     10h
      mov     si, msg1
      mov     bl, 0E2h        ; GreenOnYellow
      call    WriteStringWithAttributeMode19
      mov     si, msg2
      mov     bl, 0F0h        ; BlackOnWhite
      call    WriteStringWithAttributeMode19
      mov     ah, 00h         ; BIOS.GetKeystroke
      int     16h             ; -> AX
      mov     ax, 0003h       ; BIOS.SetVideo 80x25 16-color text screen
      int     10h
      ret
; ---------------------------
msg1: db      'This is a colourful text', 13, 10
      db      '  written on two lines  ', 13, 10, 0
msg2: db      '------------------------', 13, 10
      db      879 dup 'Q', 0
; ---------------------------
; IN (bl,ds:si) OUT ()
WriteStringWithAttributeMode19:
      pusha
      mov     bh, 0           ; Display page 0
      mov     bp, bx
      jmps    .d
.a:   cmp     al, 9
      je      .Tab
      cmp     al, 13
      ja      .b
      mov     cx, 1101_1010_0111_1111b
      bt      cx, ax
      jnc     .c              ; 7,8,10,13 don't need the color

.b:   mov     bx, bp
      mov     dl, bl
      shr     dl, 4           ; Get background color (high nibble)
      and     bl, 15          ; Get foreground color (low nibble)
      xor     bl, dl
      mov     ah, 0Eh
      int     10h             ; BIOS.Teletype
      mov     ah, 03h
      int     10h             ; BIOS.GetCursor -> CX DX
      dec     dl              ; Column is [0,39]
      jns     :1
      mov     dl, 39
      dec     dh
:1:   movzx   cx, dl          ; Column -> X
      shl     cx, 3
      movzx   dx, dh          ; Row -> Y
      shl     dx, 3

      mov     bx, bp
      shr     bl, 4           ; Get background color (high nibble)
:2:   mov     ah, 0Dh         ; BIOS.ReadPixel
      int     10h             ; -> AL
      xor     al, bl
      mov     ah, 0Ch         ; BIOS.WritePixel
      int     10h
      inc     cx              ; X++
      test    cx, 7
      jnz     :2
      sub     cx, 8
      inc     dx              ; Y++
      test    dx, 7
      jnz     :2
      jmp     .d

.c:   mov     ah, 0Eh
      int     10h             ; BIOS.Teletype
.d:   lodsb
      test    al, al
      jnz     .a
      popa
      ret
.Tab: mov     cx, 1           ; Start displaying colored space(s)
      mov     bx, bp
      shr     bl, 4           ; Get background color
      mov     ax, 0EDBh       ; ASCII DBh is full block character
      int     10h             ; BIOS.Teletype
      mov     ah, 03h
      int     10h             ; BIOS.GetCursor -> CX DX
      test    dl, 7
      jnz     .Tab            ; Column not yet multiple of 8
      jmps    .d
; ----------------------------

You can find a similar code for the 16-color graphics screens in the WriteStringWithAttributeGVM procedure which is part of Displaying characters with DOS or BIOS.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76