seg_b segment at 40h
; ŰßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŰ
; Ű VIDEO DATA Ű
; ŰÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŰ
video_mode db 3 ; Present display mode(see int 10h)
; xref F000:85A7, F000:8720
; F000:872E, F000:874E
; F000:87C9, F000:8807
; F000:8919, F000:894A
; F000:8951, F000:899A
; F000:8A03, F000:8A36
; F000:8A3D, F000:8A79
; F000:8AAA, F000:8AB1
; F000:8B0D, F000:8C36
; F000:8CBD, F000:8CC4
; F000:8CFC, F000:9D4D
video_columns dw 50h ; Number of columns
; xref F000:85D5, F000:869B
; F000:873B, F000:87F7
; F000:881D, F000:8833
; F000:8933, F000:898D
; F000:8A20, F000:8A94
; F000:8AFD, F000:8C39
; F000:8CAC, F000:8CD5
video_buf_siz dw 10A0h ; Video buffer size in bytes
; Note: size may be rounded up to
; the nearest 2K boundary. For
; example, 80x25 mode=4000 bytes,
; but value may be 4096.
; xref F000:85F0, F000:8797
; F000:8940, F000:8A2D
; F000:8AA1
video_segment dw 0 ; Segment of active video memory
; MDA=0B000h, CGA=0B800h, etc.
; xref F000:85F5, F000:86A3
; F000:8719, F000:879B
; F000:8827
vid_curs_pos0 dw 184Fh ; Cursor position page 0
; bits 15-8=row, bits 7-0=column
; xref F000:8987, F000:8AF7
vid_curs_pos1 dw 0 ; Cursor position page 1
; bits 15-8=row, bits 7-0=column
vid_curs_pos2 dw 0 ; Cursor position page 2
; bits 15-8=row, bits 7-0=column
vid_curs_pos3 dw 0 ; Cursor position page 3
; bits 15-8=row, bits 7-0=column
vid_curs_pos4 dw 0 ; Cursor position page 4
; bits 15-8=row, bits 7-0=column
vid_curs_pos5 dw 0 ; Cursor position page 5
; bits 15-8=row, bits 7-0=column
vid_curs_pos6 dw 0 ; Cursor position page 6
; bits 15-8=row, bits 7-0=column
vid_curs_pos7 dw 0 ; Cursor position page 7
; bits 15-8=row, bits 7-0=column
vid_curs_mode dw 2000h ; Active cursor, start & end lines
; bits 12 to 8 for starting line
; bits 4 to 0 for ending line
; xref F000:863B, F000:866B
; F000:86D8
video_page db 0 ; Present page
; xref F000:85F8, F000:868A
; F000:8791, F000:8BFA
; F000:8C42
@video_port dw 3D4h ; Video controller base I/O address
; xref F000:85A3, F000:86AD
; F000:86E1, F000:8958
; F000:8A52, F000:8AC4
; F000:8BBC
video_mode_reg db 29h ; Hardware mode register bits
; xref F000:85BD, F000:865C
; F000:9D54
video_color db 30h ; Color set in CGA modes
; xref F000:85B2, F000:8665
; F000:8BA0, F000:8BB9
; ŰßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŰ
; Ű MORE ADVANCED VIDEO DATA Ű
; ŰÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŰ
@video_sav_tbls dd 0C80E3CB8h ; Pointer to a save table of more
; pointers for the video system
; SAVE TABLE
; offset type pointer to
; ÄÄÄÄÄÄ ÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; 0 dd Video parameters
; 4 dd Parms save area
; 8 dd Alpha char set
; 0Ch dd Graphics char set
; 10h dd 2nd save ptr table
; 14h dd reserved (0:0)
; 18h dd reserved (0:0)
;
; 2ND SAVE TABLE (from ptr above)
; offset type functions & pointers
; ÄÄÄÄÄÄ ÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; 0 dw Bytes in this table
; 2 dd Combination code tbl
; 6 dd 2nd alpha char set
; 0Ah dd user palette tbl
; 0Eh dd reserved (0:0)
; 12h dd reserved (0:0)
; 16h dd reserved (0:0)
equip_bits dw 4661h
data_72 dw offset sub_2
seg_b ends
seg_c segment at 50h
prn_scrn_stat db 0 ; Print screen status
; 00h = Print screen ready
; 01h = Print screen in progress
; FFh = Error occurred
; xref F000:EC63, F000:ECCC
db 0
seg_c ends
video_rows db 18h
video_hdw_off equ 74h
; ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± int 10h ±±±±±
;
; VIDEO DISPLAY SERVICES
;
; Called with: ah = primary function number
;
; Returns: (unless otherwise indicated)
; ax - altered (some systems may not alter ax)
;
; Functions:
; ah = 0 Set video display mode in al.
; ah = 1 Set cursor size
; Call with: ch = top line, 0-32
; cl = bottom line, 0-32
; ah = 2 Set cursor location
; Call with: bh = page number, 0 = 1st page
; dh = row (0 for top row)
; dl = column (0 for leftmost)
; ah = 3 Get cursor location
; Call with: bh = page number, 0 = 1st page
; Returns: ch/cl = cursor size (top & bottom)
; dh/dl = row and column of cursor
; ah = 4 Get light pen location
; Returns: ah = 0 not on/unsupported & bx,cx,dx changed
; 1 status valid
; bx = pixel column
; cx = horizontal line number
; dh/dl = row and column
; ah = 5 Set Page number al, 0 = 1st page
; ah = 6 Up scroll screen
; Call with: al = # bottom lines to clear, set 0 for all
; bh = attribute to fill cleared lines
; ch/cl = row/column of top left scroll corner
; dh/dl = row/column of bottom right scroll corner
; ah = 7 Down scroll screen
; Call with: al = # top lines to clear, set 0 for all
; bh = attribute to fill cleared lines
; ch/cl = row/column of top left scroll corner
; dh/dl = row/column of bottom right scroll corner
; ah = 8 Get character & attribute at cursor
; Call with: bh = page number, 0 = 1st page
; Returns: ah/al = attribute/character
; ah = 9 Write character & attribute at cursor (graphics modes)
; Call with: al = character
; bh = page number, 0 = 1st page
; bl = attribute, bit 7 = 1 to xor with old color
; cx = Number of same characters to write
; ah = 0Ah Write character at cursor (graphics modes)
; Call with: al = character
; bh = page number, 0 = 1st page
; cx = Number of same characters to write
; ah = 0Bh Set colors (typically in low res modes)
; Call with: bh = 0, bl = color low res background, border
; bh = 1, bl = 0/1 for low res color group 0/1
; ah = 0Ch Write graphics dot
; Call with: al = color, bit 7 = 1 to xor bit with old color
; cx/dx = pixel row/pixel column
; ah = 0Dh Read graphics dot
; Call with: cx/dx = pixel row/pixel column
; ah = 0Eh Write in ASCII mode (cr, lf, bell, and bs as operators)
; Call with: al/bl = character/color
; ah = 0Fh Get video info
; Returns: ah = columns active
; al = active video mode
; bh = active page, 0 = 1st page
; ah = 10h Colors (EGA/VGA) Called with al = subfunction
; al = 1 bl = color register (0-15) bh = color to set
; al = 2 es:dx = ptr to change all 16 colors & overscan #
; al = 3 bl = color high bit as: 0-intensity, 1-blink
; For VGA equipped systems only
; al = 7 bl = color register to get in bh
; al = 8 bh = returned overscan value
; al = 9 es:dx = ptr where to put all 16 colors & overscan
; al = 10h bx = color register to set; ch/cl/dl = grn/blu/red
; al = 12h es:dx = ptr to change color registers
; bx = 1st register to set, cx = # of registers
; al = 13h bl = 0, set color page mode in bh
; bl = 1, set page; bh = page number
; al = 15h bx = color reg to read; ch/cl/dl = grn/blu/red
; al = 17h es:dx = ptr where to load color regs
; bx = 1st register to get, cx = # of registers
; al = 1Ah get color page info; bl = mode; bh = page #
; ah = 11h Reset mode with new character set (leave memory as-is)
; al = 0 Character set load
; es:bp = ptr to table of chars
; bl/bh = which block/bytes per char
; cx/dx = # of characters/where to start in block
; al = 1 bl = block to load the mono character set
; al = 2 bl = block to load the double wide character set
; al = 3 bl = block select related to attribute
; al = 4 bl = block to load the 8 by 16 set (VGA)
; al = 10h - 14h same as 0 - 4, must occur after setting mode
; al = 20h es:bp = ptr to table of char, using int 1Fh ptr
; al = 21h es:bp = ptr to table of char, using int 43h ptr
; bl = 0-dl=# rows; 1-14 rows; 2-25 rows; 3-43 rows
; cx = number of bytes per character in table
; al = 22h use 8 by 14 char set, bl=rows (see al=21h)
; al = 23h use double wide char set, bl=rows (see al=21h)
; al = 24h use 8 by 16 char set, bl=rows (see al=21h)
; Get table pointer and info
; al = 30h es:bp = ptr returned; cx=bytes per char; dl=rows
; bh = 0, get int 1Fh bh = 4, get double wide
; bh = 1, get int 43h bh = 5, get mono 9 by 14
; bh = 2, get 8 by 14 bh = 6, get 8 by 16 (VGA)
; bh = 3, get double wide bh = 7, get 9 by 16 (VGA)
; ah = 12h Miscellaneous functions, bl = sub-function
; bl = 10h Get info, bh = 0-now color, 1-now mono
; ch/cl = info bits/switches
; bl = 20h Set print screen to work with EGA/VGA
; Functions for VGA only (bl = 30-34h return al = 12h)
; bl = 30h Set # of scan lines, 0-200, 1-350, 2-400
; activates after mode change
; bl = 31h ax = 0/1 allow/prevent palette load with new mode
; bl = 32h al = 0/1 video off/on
; bl = 33h al = 0/1 gray scale summing off/on
; bl = 34h al = 0/1 scale cursor size to font off/on
; bl = 35h switch between adapter and motherboard video
; al = 0, adapter off, es:dx = save state area
; al = 1, motherboard on
; al = 2, active video off, es:dx = save area
; al = 3, inactive video on, es:dx = save area
; bl = 36h al = 0/1 screen off/on
; ah = 13h Write character string (cr, lf, bell, and bs as operators)
; Call with: al = 0/1 write characters, cursor not/is moved
; bl = attribute of all characters
; = 2/3 write characters, cursor not/is moved
; string alternates character & attribute
; bh = page number, 0 = 1st page
; cx = number of characters
; dh/dl = row and column to start
; es:bp = ptr to character string
; ah = 14h LCD display support, al = sub-function
; al = 0, es:di = ptr to font table to load
; bl/bh = which block/bytes per char
; cx/dx = # of characters/where to start in block
; al = 1, bl = block # of ROM font to load
; al = 2, bl = how to support high intensity
; ah = 15h LCD info table ptr returned in es:di
; ax = 0 there is no alternate adapter
; ax = 5140h LCD is the alternate
; ax = 5153h CGA is alternate
; ax = 5151h MDA is alternate
;
; **** VGA SUPPORT ONLY ****
; ah = 1Ah Get/Set types of displays which are operating
; al = 0, get displays, returns al = 1Ah
; bl = in use display code
; bh = alternate display code
; al = 1, set codes, returns al = 1Ah
; bl = in use display code
; bh = alternate display code
; codes: 0 = no display
; 1 = mono display
; 2 = CGA
; 4 = EGA, color
; 5 = EGA, mono
; 6 = PGA
; 7 = VGA, mono (PS/2 MCA only)
; 8 = VGA, color (PS/2 MCA only)
; Bh = VGA, mono (PS/2 non MCA)
; Ch = VGA, color (PS/2 non MCA)
; FFh = display type not known
; ah = 1Bh Get video system information
; call with: bx = 0
; es:di = ptr to buffer where to put info
; ah = 1Ch Video system save & restore, al = sub-function
; call with: al = 0, get buffer size
; = 1, save system, buffer at es:bx
; = 2, restore system, buffer at es:bx
; cx bit 0 = 1 for hardware registers
; bit 1 = 1 for software states
; bit 2 = 1 for colors & DAC registers
int_10h_video proc near ; xref F000:F065
sti ; Enable interrupts
cld ; Clear direction
cmp ah,0Eh
je short loc_88 ; Jump if equal
cmp ah,2
je short loc_89 ; Jump if equal
cmp ah,3
je short loc_90 ; Jump if equal
cmp ah,5
je short loc_91 ; Jump if equal
pusha ; Save all regs
push ds
push es
cmp ah,13h
ja short loc_87 ; Jump if above
push ax
mov al,ah
cbw ; Convrt byte to word
mov di,ax
mov ax,seg_b
mov ds,ax
jz short loc_86 ; Jump if zero
assume ds:seg_b
Mov al,byte ptr equip_bits ; (0040:0010=61h)
and al,30h ; '0'
cmp al,30h ; '0'
mov ax,0B000h
jz short loc_85 ; Jump if zero
mov ah,0B8h
loc_85: ; xref F000:8571
mov es,ax
loc_86: ; xref F000:8565
pop ax
shl di,1 ; Shift w/zeros fill
call word ptr cs:data_72[di] ;*(F000:8514=858Fh) 20 entries
loc_87: ; xref F000:8558
pop es
pop ds
popa ; Restore all regs
iret ; Interrupt return
int_10h_video endp
loc_88: ; xref F000:8541
jmp loc_197 ; (8BED)
loc_89: ; xref F000:8546
jmp loc_103 ; (8674)
loc_90: ; xref F000:854B
jmp loc_109 ; (86C7)
loc_91: ; xref F000:8550
jmp loc_127 ; (8787)
sub_2 proc near
mov video_rows,18h ; (0040:0084=18h)
mov dx,es
cmp dh,0B0h
mov dx,3D4h
jnz short loc_92 ; Jump if not zero
mov dx,3B4h
mov al,7
loc_92: ; xref F000:859C
mov @video_port,dx ; (0040:0063=3D4h)
mov video_mode,al ; (0040:0049=3)
mov ah,3Fh ; '?'
cmp al,6
je short loc_93 ; Jump if equal
mov ah,30h ; '0'
loc_93: ; xref F000:85AE
mov video_color,ah ; (0040:0066=30h)
mov ah,al
mov bx,0F0F4h
xlat cs:[bx] ; al=[al+[bx]] table
mov video_mode_reg,al ; (0040:0065=29h)
and al,37h ; '7'
add dx,4
out dx,al ; port 3B8h, MDA video control
sub dx,4
mov al,28h ; '('
test ah,2
jz short loc_94 ; Jump if zero
mov al,50h ; 'P'
loc_94: ; xref F000:85CE
mov bl,ah
cbw ; Convrt byte to word
mov video_columns,ax ; (0040:004A=50h)
mov ax,800h
cmp bl,1
jbe short loc_95 ; Jump if below or =
mov ax,1000h
cmp bl,3
jbe short loc_95 ; Jump if below or =
cmp bl,7
je short loc_95 ; Jump if equal
mov ax,4000h
loc_95: ; xref F000:85DE, 85E6, 85EB
mov video_buf_siz,ax ; (0040:004C=10A0h)
xor ax,ax ; Zero register
mov video_segment,ax ; (0040:004E=0)
mov video_page,al ; (0040:0062=0)
mov di,seg seg_c
mov cx,8
locloop_96: ; xref F000:8605
mov [di],ax
inc di
inc di
loop locloop_96 ; Loop if cx > 0
push bx
push es
mov es,cx
les si,dword ptr es:video_hdw_off ; (0000:0074=0F0A4h) Load 32 bit ptr
cmp bl,6
jne short loc_97 ; Jump if not equal
dec bl
loc_97: ; xref F000:8613
shr bl,1 ; Shift w/zeros fill
shl bl,4 ; Shift w/zeros fill
xor bh,bh ; Zero register
add si,bx
mov cx,10h
locloop_98: ; xref F000:8633
mov al,bh
out dx,al ; port 3B4h, MDA/EGA reg index
; al = 0, horiz char total
jmp short loc_99 ; (8628)
loc_99: ; xref F000:8626
inc dx
mov al,es:[si]
inc si
out dx,al ; port 3B5h, MDA/EGA indxd data
jmp short loc_100 ; (8630)
loc_100: ; xref F000:862E
inc bh
dec dx
loop locloop_98 ; Loop if cx > 0
mov ax,es:[si-6]
xchg al,ah
mov vid_curs_mode,ax ; (0040:0060=2000h)
pop es
pop bx
mov cx,800h
mov ax,720h
cmp bl,7
je short loc_101 ; Jump if equal
mov cx,2000h
cmp bl,3
jbe short loc_101 ; Jump if below or =
xor ax,ax ; Zero register
loc_101: ; xref F000:8649, 8651
xor di,di ; Zero register
cli ; Disable interrupts
cld ; Clear direction
rep stosw ; Rep when cx >0 Store ax to es:[di]
sti ; Enable interrupts
mov al,video_mode_reg ; (0040:0065=29h)
add dx,4
out dx,al ; port 3B8h, MDA video control
jmp short loc_102 ; (8665)
loc_102: ; xref F000:8663
mov al,video_color ; (0040:0066=30h)
inc dx
out dx,al ; port 3B9h, CGA color(port3D9)
retn
sub_2 endp
loc_197: ; xref F000:8583
push ds
push ax
push bx
push cx
push dx
push ax
mov ax,seg_b
mov ds,ax
mov ah,3
mov bh,video_page ; (0040:0062=0)
loc_103: ; xref F000:8586
push ds
push ax
push bx
push cx
push dx
mov ax,seg_b
mov ds,ax
mov al,bh
mov bl,bh
xor bh,bh ; Zero register
shl bx,1 ; Shift w/zeros fill
mov [bx+50h],dx
nop ;*Fixup for MASM (M)
cmp al,video_page ; (0040:0062=0)
jne short loc_104 ; Jump if not equal
call sub_5 ; (8699) int 10h ; Video display ah=functn 03h
; get cursor loc in dx, mode cx
loc_104: ; xref F000:868E
pop dx
pop cx
pop bx
pop ax
pop ds
iret
sub_7 proc near
loc_109: ; xref F000:8589
push ds
push bx
mov bl,bh
xor bh,bh ; Zero register
shl bx,1 ; Shift w/zeros fill
mov dx,seg seg_b
mov ds,dx
mov dx,[bx+50h]
nop ;*Fixup for MASM (M)
mov cx,vid_curs_mode ; (0040:0060=2000h)
pop bx
pop ds
iret ; Interrupt return
sub_7 endp
sub_9 proc near
loc_127: ; xref F000:858C
push ds
push ax
push bx
push cx
push dx
mov dx,seg seg_b
mov ds,dx
mov video_page,al ; (0040:0062=0)
cbw ; Convrt byte to word
mov bx,ax
mul video_buf_siz ; (0040:004C=10A0h) ax = data * ax
mov video_segment,ax ; (0040:004E=0)
shr ax,1 ; Shift w/zeros fill
mov cx,ax
mov al,0Ch
call sub_6 ; (86AD)
shl bx,1 ; Shift w/zeros fill
mov dx,[bx+50h]
nop ;*Fixup for MASM (M)
call sub_5 ; (8699)
pop dx
pop cx
pop bx
pop ax
pop ds
iret ; Interrupt return
sub_9 endp
sub_5:
mov al,dh
mul byte ptr video_columns ; (0040:004A=50h) ax = data * al
xor dh,dh ; Zero register
add ax,dx
mov cx,video_segment ; (0040:004E=0)
shr cx,1 ; Shift w/zeros fill
add cx,ax
sub_6 proc near
loc_105: ; xref F000:8671
mov dx,@video_port ; (0040:0063=3D4h)
out dx,al ; port 3D4h, CGA/EGA reg index
; al = 0Ch, start address high
jmp short loc_106 ; (86B4)
loc_106: ; xref F000:86B2
inc dx
xchg al,ch
out dx,al ; port 3D5h, CGA/EGA indxd data
inc ch
jmp short loc_107 ; (86BC)
loc_107: ; xref F000:86BA
dec dx
xchg al,ch
out dx,al ; port 3D4h, CGA/EGA reg index
; al = 0Dh, start address low
jmp short loc_108 ; (86C2)
loc_108: ; xref F000:86C0
inc dx
xchg al,cl
out dx,al ; port 3D5h, CGA/EGA indxd data
retn
sub_6 endp