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