; Copyright : ZDS Corporation 1992 ; Proprietary information. ; For use by ZDS Corporation employees only. ; System : ZDS Text User Interface ; Module : VIDEO.ASM ; ; Function : Low-Level Input/Output Assembly Language Routines ; ; Author : Dave Goodall ; History : DD MMM YY By Ver Description ; 01 Jul 92 Dave Goodall 1.00 Base Code ; 09 Jul 92 Dave Goodall 1.01 - drawbox routine ; 11 Jul 92 Dave Goodall 1.02 + drawwin routine ; 12 Jul 92 Dave Goodall 1.03 draw_wborder (part) SA compliant ; 13 Jul 92 Dave Goodall 1.04 rename printstring -> display ; 29 Jul 92 Dave Goodall 1.05 Waitkey documentation ; 10 Aug 92 Dave Goodall 1.06 Add cpu_detect and modify ; other rtns to use cputype ; 22 Sep 92 Dave Goodall 1.07 Revise settext80 ; Adapt from SA get_adapter ; get_dmode, is_compaq ; 23 Sep 92 Dave Goodall 1.08 Add get_vmode, set_vmode ; set_bios_ef_mono ; 25 Sep 92 Dave Goodall 1.09 Mod-Document enable-disable_cga ; ; Notes : Zortech Register Usage compatibility: ; Functions may change : AX BX CX DX or ES. ; Functions MUST preserve : SI DI BP SP SS CS DS. ; The direction flag must always be set to forward. ; ;---------------------------------------------------------------------------- ; include console.inc ; SA console constants-macros ; ; Set BIGCODE and BIGDATA as follows: ; ; Memory Model BIGCODE BIGDATA ; ; Small 0 0 ; Medium 1 0 ; Compact 0 1 ; Large 1 1 BIGCODE equ 0 BIGDATA equ 0 .286 ;Enable real mode 80286-287 assembly ; ; ROM BIOS Locations ; bios_data equ 40h DGROUP group _DATA _DATA segment word public 'DATA' assume ds:DGROUP ; Snow control: public __ibmcga __ibmcga dw 1 ;1=Not an IBM CGA 0=An IBM CGA public __cputype __cputype dw 1 ;Default 80286 displayseg dw 0b800h ;Default BW80, CO80 _DATA ends if bigcode VIDEO_TEXT segment word public 'CODE' assume cs:VIDEO_TEXT extrn _show_mouse:far, _hide_mouse:far else _TEXT segment word public 'CODE' assume cs:_TEXT extrn _show_mouse:near, _hide_mouse:near endif public _is_compaq public _get_dmode public _get_vmode public _set_vmode public _set_bios_ef_mono public _get_adapter public _cpu_detect public _settext80 public _fillscreen, public _setattrib public _savescreen, public _restorescreen, public _draw_wborder public _display, public _waitkey ; --------------------------------------------------------------------- ; Module : is_compaq ; Function : Returns ; ..h JE if the host computer is a COMPAQ ; ..h JNE if the host computer is not a COMPAQ computer ; ; Called as : int is_compaq(void); ; ; Notes : This function adapted from file MHCOMPAQ.ASM (mishard.src) ; Spontaneous Assembly 2.0 Library Source Code ; Copyright (c) 1989-90 Acclaim Technologies, Inc. ; All Rights Reserved ; This source code may not be redistributed in any form. if bigcode _is_compaq proc far else _is_compaq proc near endif push ax ; Save the registers push ds mov ax,0F000h mov ds,ax ;DS -> rom bios segment cmp word ptr ds:0FFEAh,"OC" ;compaq machine? jne is_compaq_060 ; no cmp word ptr ds:0FFECh,"PM" ; maybe jne is_compaq_060 ; no cmp word ptr ds:0FFEEh,"QA" ; maybe jne is_compaq_060 ; no is_compaq_060: pop ds pop ax ; Restore the registers ret ; Return _is_compaq endp ; --------------------------------------------------------------------- ; Module : get_dmode ; Function : Returns value in AL depending on the display mode: ; 00h MONO2 Monochrome , blink enabled ; 01h MONO4 Monochrome , hi-intensity bg, no blink ; 02h BW2 Black/white, blink enabled ; 03h BW4 Black/white, hi-intensity bg, no blink ; 04h COLOR8 Color, 8 bg colors, blink enabled ; 05h COLOR16 Color, 16 bg colors, no blink ; 06h GRAY8 Gray scale, 8 shades, blink enabled ; 07h GRAY16 Gray scale, 16 shades, no blink ; ; CGA adaptors in COMPAQ computers usually operate in gray ; scale mode. The routine enforces this assumption. ; ; Called as : int get_dmode(void); ; ; Notes : This function adapted from file CIOGDMOD.ASM ; Spontaneous Assembly 2.0 Library Source Code ; Copyright (c) 1989-90 Acclaim Technologies, Inc. ; All Rights Reserved ; This source code may not be redistributed in any form. if bigcode _get_dmode proc far else _get_dmode proc near endif push bx ; Save the registers push cx push dx push si push di push bp push ds mov dh,ah ;DH holds original AH xor bx,bx mov ds,bx ;DS -> segment at 0000h mov ah,0Fh int 10h ;get video mode and al,7Fh ;strip off NOCLEAR bit mov dl,MONO2 ;assume MONO2/MONO4 cmp al,7 ;monochrome mode? je get_dmode_080 ; y: MONO2 or MONO4 cmp al,15 ;monochrome mode? je get_dmode_080 ; y: MONO2/MONO4 xchg cx,ax ;CL = video mode mov ax,1A00h ; ** VGA/MCGA check ** int 10h ;check for a VGA cmp al,1Ah ;is VGA/MCGA supported? jne get_dmode_040 ; n: go check for an EGA xchg ax,bx ; y: move active code to AL mov dl,GRAY8 ;assume GRAY8/GRAY16 cmp al,11 ;MCGA mono? je get_dmode_080 ; y: GRAY8/GRAY16 cmp al,7 ;VGA mono? je get_dmode_080 ; y: GRAY8/GRAY16 cmp al,8 ;VGA color? je get_dmode_070 ; y: COLOR8/COLOR16 cmp al,10 ;MCGA color? je get_dmode_070 ; y: COLOR8/COLOR16 cmp al,12 ;MCGA color? je get_dmode_070 ; y: COLOR8/COLOR16 get_dmode_040: mov ah,12h ; ** EGA check ** mov bl,10h ;get EGA configuration push cx ;preserve video mode int 10h pop ax ;AL = video mode cmp bl,10h ;valid EGA mem size? jae get_dmode_060 ; n: must be CGA mov cl,ds:[488h] ;get configuration bits byte and cl,0Fh ;isolate EGA sense switch bits cmp cl,0Ah ;EGA color monitor? jbe get_dmode_070 ; y: COLOR8/COLOR16 jmp short get_dmode_080 ; n: GRAY8/GRAY16 get_dmode_060: mov dl,BW2 ; ** CGA check ** cmp al,BW40 ;CGA in BW40 mode? je get_dmode_080 ; y: BW8/BW16 cmp al,BW80 ;CGA in BW80 mode? je get_dmode_080 ; y: BW8/BW16 get_dmode_070: mov dl,COLOR8 ; n: assume COLOR8 get_dmode_080: test byte ptr ds:[465h],20h ;is blink/intensity bit set? jnz get_dmode_090 ; y: blink inc dl ; n: high intensity bckgrnd get_dmode_090: xchg ax,dx ;return AL; restore AH pop ds pop bp pop di pop si pop dx pop cx pop bx ; Restore the registers ; Enforce Compaq cga gray scale assumption ; xchg ah,al ;save display mode in AH ; call _get_adapter ;determine adapter type ; xchg ah,al ;AL= display mode AH= adapter ; cmp ah,CGA ;is the active adapter a cga? ; jne get_dmode_100 ;n: display mode is correct ; call _is_compaq ;running on a COMPAQ? ; jne get_dmode_100 ;n: display mode is correct ; or al,02h ;y; if COLOR, then assume GRAY get_dmode_100: xor ah,ah ; Clean out msbyte of int ret ; Return AL = display mode _get_dmode endp ; --------------------------------------------------------------------- ; Module : get_vmode ; Function : Returns the current video mode in AL : ; 00h BW40 40x25 text mode, color burst off ; 01h CO40 40x25 text mode ; 02h BW80 80x25 text mode, color burst off ; 03h CO80 80x25 text mode ; 04h CG_320x200_4 320x200 graphics mode 4 color ; 05h BW_320x200_4 320x200 graphics mode 4 color ; 06h CG_640x200_2 640x200 graphics mode 2 color ; 07h MONO 80x25 text mode 2 color ; 08h CG_160x200_16jr 160x200 graphics mode 16 color PCjr ; 09h CG_320x200_16jr 320x200 graphics mode 16 color PCjr ; 0ah CG_640x200_4jr 640x200 graphics mode 2 color PCjr ; 0dh CG_320x200_16 320x200 graphics mode 16 color ; 0eh CG_640x200_16 640x200 graphics mode 16 color ; 0fh MG_640x350 640x350 graphics mode monochrome ; 10h CG_640x350_16 640x350 graphics mode 16 color ; 11h CG_640x480_2 640x480 graphics mode 2 color ; 12h CG_640x480_16 640x480 graphics mode 16 color ; 13h CG_320x200_256 320x200 graphics mode 256 color ; ; Reference : Non-IBM display adaptors support and return enhanced modes ; PC Interrupts, Ralf Brown & Jim Kyle, Chapter 5 pp 5-1+ ; Called as : int get_vmode(void); ; ; Notes 1. : Compatible in name and function with SA function ; which can directly replace it. ; ; 2. : If mode was set with bit 7 set (no blanking), the ; mode returned by Int 10 - Function 0fh will also ; return AL with bit 7 set. if bigcode _get_vmode proc far else _get_vmode proc near endif push bx ; Save the registers push cx push dx push si push di push bp push es mov ah,0fh ; int 10h ; xor ah,ah ; Clean out msbyte of int pop es pop bp pop di pop si pop dx pop cx pop bx ; Restore the registers ret ; Return AL = current video mode _get_vmode endp ; --------------------------------------------------------------------- ; Module : set_vmode ; Function : Sets the current video mode : ; 00h BW40 40x25 text mode, color burst off ; 01h CO40 40x25 text mode ; 02h BW80 80x25 text mode, color burst off ; 03h CO80 80x25 text mode ; 04h CG_320x200_4 320x200 graphics mode 4 color ; 05h BW_320x200_4 320x200 graphics mode 4 color ; 06h CG_640x200_2 640x200 graphics mode 2 color ; 07h MONO 80x25 text mode 2 color ; 08h CG_160x200_16jr 160x200 graphics mode 16 color PCjr ; 09h CG_320x200_16jr 320x200 graphics mode 16 color PCjr ; 0ah CG_640x200_4jr 640x200 graphics mode 2 color PCjr ; 0dh CG_320x200_16 320x200 graphics mode 16 color ; 0eh CG_640x200_16 640x200 graphics mode 16 color ; 0fh MG_640x350 640x350 graphics mode monochrome ; 10h CG_640x350_16 640x350 graphics mode 16 color ; 11h CG_640x480_2 640x480 graphics mode 2 color ; 12h CG_640x480_16 640x480 graphics mode 16 color ; 13h CG_320x200_256 320x200 graphics mode 256 color ; ; Reference : Non-IBM display adaptors support enhanced modes ; PC Interrupts, Ralf Brown & Jim Kyle, Chapter 5 pp 5-1+ ; Called as : void set_vmode(int); ; ; Notes 1. : Compatible in name and function with SA function ; which can directly replace it. ; ; 2 : If the requested mode argument is bitwise OR'd with 80h ; before the call then the mode change will take place ; without the screen being cleared. ; This option is ignored on XT-class machines unless an ; EGA compatible adapter is present. ; if bigcode _set_vmode proc far vmode equ <6[bp]> else _set_vmode proc near vmode equ <4[bp]> endif cmp __cputype,0 ;Check cpu type je set_vmode_8086 ; enter 4,0 ;Set up the stack frame jmp short set_vmode_000 set_vmode_8086: push bp ;Save BP registers mov bp,sp ;Point it to the stack sub sp,4 ;Reserve local space set_vmode_000: mov ah,00h ;AH = 00h mov al,vmode ;AL = Required video mode int 10h ;Set video mode cmp __cputype,0 ;Check cpu type je set_vmode_8086x leave ;Restore the stack jmp short set_vmode_ret set_vmode_8086x: pop bp ;Restore BP set_vmode_ret: ret ;Return _set_vmode endp ; --------------------------------------------------------------------- ; Module : set_bios_ef_mono ; Function : Forces both bits 4 & 5 of the bios equipment flag word ; to 1 causing the bios to support the monochrome display ; adapter. ; Called as : void set_bios_ef_mono(void); ; if bigcode _set_bios_ef_mono proc far else _set_bios_ef_mono proc near endif push ax ; Save the registers push bx push ds mov ah,bios_data ; mov ds,ax mov bx,10h or WORD PTR [bx],0030h pop ds pop bx pop ax ; Restore the registers ret _set_bios_ef_mono endp ; --------------------------------------------------------------------- ; Module : get_adapter ; Function : Returns value in AL depending on the adaptor type: ; 00h MDA Monochrome display adaptor ; 01h CGA Color graphics adaptor ; 02h EGA Enhanced graphics adaptor ; 03h MCGA Multi-color graphics adaptor ; 04h VGA Video graphics array ; ; Called as : int get_adapter(void); ; ; Notes : This function adapted from file CIOGADP.ASM ; Spontaneous Assembly 2.0 Library Source Code ; Copyright (c) 1989-90 Acclaim Technologies, Inc. ; All Rights Reserved ; This source code may not be redistributed in any form. if bigcode _get_adapter proc far else _get_adapter proc near endif push bx ; Save the registers push cx push dx push si push di push bp push es mov dh,ah ;DH holds original AH xor bx,bx mov es,bx ;ES -> segment at 0000h mov dl,VGA ;assume VGA (04h) mov ax,1A00h ; ** VGA check ** int 10h ;check for a VGA cmp al,1Ah ;is VGA/MCGA supported? jne get_adap_020 ; n: go check for an EGA xchg ax,bx ; y: move active code to AL cmp al,08h ;is active monitor a VGA color? je get_adap_060 ; y: VGA return cmp al,07h ;is active monitor a VGA mono? je get_adap_060 ; y: VGA return dec dx ;assume MCGA (03h) cmp al,0Ah ; ** MCGA check ** jb get_adap_020 ;is active monitor a MCGA? cmp al,0Ch ; n: fall through to EGA jbe get_adap_060 ; y: MCGA return get_adap_020: mov dl,EGA ;assume EGA (02h) mov ah,12h ; ** EGA check ** mov bl,10h ;get EGA configuration int 10h cmp bl,10h ;valid EGA mem size? jb get_adap_060 ; y: EGA return dec dx ;assume CGA (01h) cmp word ptr es:[463h],3B4h jne get_adap_060 ;CGA return if not MDA dec dx ;MDA (00h) get_adap_060: xchg ax,dx ;return AL; restore AH pop es pop bp pop di pop si pop dx pop cx pop bx ; Restore the registers xor ah,ah ; Clean out msbyte of int ret ; Return AH=00 AL=Adapter type _get_adapter endp ; --------------------------------------------------------------------- ; Module : cpu_detect ; Function : Returns value in AL depending on the cpu type: ; 0 if 8088/V20 or compatible ; 1 if 80286 ; 2 if 80386 or better ; The routine also sets cputype for all the other routines. ; ; References : PC Techniques : Feb/Mar 91 - Nicholas Wilt ; PC Techniques : Aug/Sep 92 - Greg Ryan ; ; Called as : int cpu_detect(void); ; ; Notes : if bigcode _cpu_detect proc far else _cpu_detect proc near endif xor dx,dx ; Assume 8086 for now push dx ; flags <- 0 popf ; pushf ; Get flags back pop ax ; and ax,0f000h ; If the top four bits are set cmp ax,0f000h ; je cpu_detect2 ; Return. It's an 8086 inc dx ; It's at least an 80286 push 0f000h ; flags <- 0f000h popf ; pushf ; Get flags back pop ax ; and ax,0f000h ; If the top 4 bits are'nt set jz cpu_detect2 ; It's an 80286 inc dx ; It's an 80386 or better cpu_detect2: xchg ax,dx ; Return value in ax mov __cputype,ax ; Save for other routines xor ah,ah ; Clean out msbyte of int ret ; Return AH=00 AL=Cpu type _cpu_detect endp ; --------------------------------------------------------------------- ; Set to 80 x 25 text mode ; Module : settext80 ; Function : Determine the cpu type. Set cpu286 variable to control ; enter/leave (286+) or 8086 stack frame setup. ; ; : Determine the adaptor type. If it's a CGA, then set ; the snow control variable. ; ; : Determine the video mode. ; If the mode is not one of the three 80 x 25 text modes ; ie 2, 3, 7 set it to whichever of these modes is most ; compatible with the original mode. ; ; : Set the display segment address to correspond ie ; mode 2 (BW80) 3 (CO80) - 0b800h ; mode 3 (MONO) - 0b000h ; ; : Set page to 0 ; ; Returns : value in AL depending on the mode set: ; 2 80x25 BW80 (Color burst off) ; 3 80x25 C080 Color ; 7 80x25 MONO ; ; Called as : int settext80(void); ; ; Notes : Portions of this function adapted from SET_80COLS ; Spontaneous Assembly 2.0 Library Source Code ; Copyright (c) 1989-90 Acclaim Technologies, Inc. ; All Rights Reserved ; This source code may not be redistributed in any form. if bigcode _settext80 proc far else _settext80 proc near endif push bx ; Save the registers push cx push dx push si push di push bp push es call _cpu_detect ;Get the cpu type call _get_adapter ;Get the adaptor type cmp al,CGA ;If it's an IBM CGA adaptor (01h) jne settext80_010 ;Not an IBM CGA adaptor mov __ibmcga,0 ;Set the snow control variable settext80_010: mov ax,0500h ;Set the int 10h ; active display page to 0 mov ah,0Fh int 10h ;get current video mode and al,7Fh ;strip off NOCLEAR mode bit mov ah,MONO ;** assume MONO video80 mode cmp al,0Fh ;mono graphics mode? je settext80_050 ; y: use MONO mode cmp al,7 ;monochrome mode? je settext80_050 ; y: use MONO mode mov ah,BW80 ;** assume BW80 video80 mode cmp al,5 ;BW graphics mode? je settext80_050 ; y: use BW80 mode cmp al,2 ;BW80 mode? je settext80_050 ; y: use BW80 mode cmp al,0 ;BW40 mode? je settext80_050 ; y: use BW80 mode mov ah,CO80 ;** assume CO80 video80 mode settext80_050: cmp al,ah ;are we already in the proper mode? je settext80_090 ; y: don't change modes mov al,ah ;select the new mode (AL=mode) mov ah,00h ;set video mode to mode in AL push ax ;save the new video mode int 10h pop ax ;restore new video mode settext80_090: cmp al,MONO ;Use the default segment address jne settext80_100 ;if we're in BW80 or CO80 modes mov displayseg,0b000h ;Set mono display segment address settext80_100: pop es pop bp pop di pop si pop dx pop cx pop bx ; Restore the registers ret ; Return : AL= 02, 03, 07 _settext80 endp ; --------------------------------------------------------------------- ; Fill text window ; if bigcode _fillscreen proc far row1 equ <6[bp]> col1 equ <8[bp]> row2 equ <10[bp]> col2 equ <12[bp]> char equ <14[bp]> att equ <16[bp]> else _fillscreen proc near row1 equ <4[bp]> col1 equ <6[bp]> row2 equ <8[bp]> col2 equ <10[bp]> char equ <12[bp]> att equ <14[bp]> endif rows equ <-2[bp]> cols equ <-4[bp]> call _hide_mouse ;Hide the mouse pointer cmp __cputype,0 ;Check cpu type je fillscreen_8086 ; enter 4,0 ;Set up the stack frame jmp short fillscreen_000 fillscreen_8086: push bp ;Save BP registers mov bp,sp ;Point it to the stack sub sp,4 ;Reserve local space fillscreen_000: push di ;Save push es ; the registers mov ax,row1 ;Figure mov bx,col1 ; the call fig_vid_off ; video offset mov di,ax ;DI=Video offset mov es,displayseg ;ES=Video Segment mov ax,row2 ;Figure the sub ax,row1 ; the number inc ax ; of rows mov rows,ax ;Save it mov ax,col2 ;Figure the sub ax,col1 ; the number inc ax ; of columns mov cols,ax ;Save it cld ;Flag increment mov al,byte ptr char ;AL=Display character mov ah,byte ptr att ;AH=Display attribute call disable_cga ;Disable the CGA if necessary fillscreen1: push di ;Save the video offset mov cx,cols ;CX=Number of columns rep stosw ;Display the row pop di ;Restore the video offset add di,160 ;Point it to the next row dec word ptr rows ;Loop jnz fillscreen1 ; till done call enable_cga ;Enable the CGA if necessary pop es ;Restore pop di ; the registers call _show_mouse ;Restore the Mouse pointer cmp __cputype,0 ;Check cpu type je fillscreen_8086x leave ;Restore the stack jmp short fillscreenret fillscreen_8086x: mov sp,bp ;Reset the stack pointer pop bp ;Restore BP fillscreenret: ret ;Return _fillscreen endp ; --------------------------------------------------------------------- ; Set attributes ; if bigcode _setattrib proc far row1 equ <6[bp]> col1 equ <8[bp]> row2 equ <10[bp]> col2 equ <12[bp]> att equ <14[bp]> else _setattrib proc near row1 equ <4[bp]> col1 equ <6[bp]> row2 equ <8[bp]> col2 equ <10[bp]> att equ <12[bp]> endif rows equ <-2[bp]> cols equ <-4[bp]> call _hide_mouse ;Hide the mouse pointer cmp __cputype,0 ;Check cpu type je setattrib_8086 ; enter 4,0 ;Set up the stack frame jmp short setattrib_000 setattrib_8086: push bp ;Save BP registers mov bp,sp ;Point it to the stack sub sp,4 ;Reserve local space setattrib_000: push di ;Save push es ; the registers mov ax,row1 ;Figure mov bx,col1 ; the call fig_vid_off ; video offset mov di,ax ;DI=Video offset inc di ;Bump it to the first attribute mov es,displayseg ;ES=Video Segment mov ax,row2 ;Figure the sub ax,row1 ; the number inc ax ; of rows mov rows,ax ;Save it mov ax,col2 ;Figure the sub ax,col1 ; the number inc ax ; of columns mov cols,ax ;Save it cld ;Flag increment mov al,byte ptr char ;AL=Display attribute call disable_cga ;Disable the CGA if necessary setattrib1: push di ;Save the video offset mov cx,cols ;CX=Number of columns setattrib2: stosb ;Set the attribute byte inc di ;Bump the video pointer loop setattrib2 ;Loop till done pop di ;Restore the video offset add di,160 ;Point it to the next row dec word ptr rows ;Loop jnz setattrib1 ; till done call enable_cga ;Enable the CGA if necessary pop es ;Restore pop di ; the registers call _show_mouse ;Restore the Mouse pointer cmp __cputype,0 ;Check cpu type je setattrib_8086x leave ;Restore the stack jmp short setattribret setattrib_8086x: mov sp,bp ;Reset the stack pointer pop bp ;Restore BP setattribret: ret ;Return _setattrib endp ; --------------------------------------------------------------------- ; Save Screen ; if bigcode _savescreen proc far row1 equ <6[bp]> col1 equ <8[bp]> row2 equ <10[bp]> col2 equ <12[bp]> array equ <14[bp]> else _savescreen proc near row1 equ <4[bp]> col1 equ <6[bp]> row2 equ <8[bp]> col2 equ <10[bp]> array equ <12[bp]> endif rows equ <-2[bp]> cols equ <-4[bp]> call _hide_mouse ;Hide the mouse pointer cmp __cputype,0 ;Check cpu type je savescreen_8086 ; enter 4,0 ;Set up the stack frame jmp short savescreen_000 savescreen_8086: push bp ;Save BP registers mov bp,sp ;Point it to the stack sub sp,4 ;Reserve local space savescreen_000: push di ;Save push si ; the push es ; registers mov ax,row1 ;Figure mov bx,col1 ; the call fig_vid_off ; video offset mov si,ax ;SI=Video offset mov ax,row2 ;Figure the sub ax,row1 ; the number inc ax ; of rows mov rows,ax ;Save it mov ax,col2 ;Figure the sub ax,col1 ; the number inc ax ; of columns mov cols,ax ;Save it cld ;Flag increment call disable_cga ;Disable the CGA if necessary push ds ;Save DS if bigdata les di,array ;ES:DI=Array pointer else push ds ;Point ES pop es ; to the data segment mov di,array ;ES:DI=Array pointer endif mov ds,displayseg ;DS:SI=Video pointer ; Loop rows (25) times, saving each line (80 x char+att byte pairs) savescreen1: push si ;Save the video offset mov cx,cols ;CX=Number of columns rep movsw ;Save the row pop si ;Restore the video offset add si,160 ;Point it to the next row dec word ptr rows ;Loop jnz savescreen1 ; till done ; Note no conditional bigcode test (see restorescreen below) pop ds ;Restore DS call enable_cga ;Enable the CGA if necessary pop es ; Restore pop si ; the pop di ; registers call _show_mouse ;Restore the Mouse pointer cmp __cputype,0 ;Check cpu type je savescreen_8086x leave ;Restore the stack jmp short savescreenret savescreen_8086x: mov sp,bp ;Reset the stack pointer pop bp ;Restore BP savescreenret: ret ;Return _savescreen endp ; --------------------------------------------------------------------- ; Restore screen ; if bigcode _restorescreen proc far row1 equ <6[bp]> col1 equ <8[bp]> row2 equ <10[bp]> col2 equ <12[bp]> array equ <14[bp]> else _restorescreen proc near row1 equ <4[bp]> col1 equ <6[bp]> row2 equ <8[bp]> col2 equ <10[bp]> array equ <12[bp]> endif rows equ <-2[bp]> cols equ <-4[bp]> call _hide_mouse ;Hide the mouse pointer cmp __cputype,0 ;Check cpu type je rest_screen_8086 enter 4,0 ;Set up the stack frame jmp short rest_screen_000 rest_screen_8086: push bp ;Save BP registers mov bp,sp ;Point it to the stack sub sp,4 ;Reserve local space rest_screen_000: push di ;Save push si ; the push es ; registers mov ax,row1 ;Figure mov bx,col1 ; the call fig_vid_off ; video offset mov di,ax ;DI=Video offset mov es,displayseg ;ES=Video Segment mov ax,row2 ;Figure the sub ax,row1 ; the number inc ax ; of rows mov rows,ax ;Save it mov ax,col2 ;Figure the sub ax,col1 ; the number inc ax ; of columns mov cols,ax ;Save it cld ;Flag increment call disable_cga ;Disable the CGA if necessary if bigdata push ds ;Save DS lds si,array ;DS:SI=Array pointer else mov si,array ;DS:SI=Array pointer endif rest_screen_10: push di ;Save the video offset mov cx,cols ;CX=Number of columns rep movsw ;Save the row pop di ;Restore the video offset add di,160 ;Point it to the next row dec word ptr rows ;Loop jnz rest_screen_10 ; till done if bigdata pop ds ;Restore DS endif call enable_cga ;Enable the CGA if necessary pop es ; Restore pop si ; the pop di ; registers call _show_mouse ;Restore the Mouse pointer cmp __cputype,0 ;Check cpu type je rest_screen_8086x leave ;Restore the stack jmp short rest_screen_ret rest_screen_8086x: mov sp,bp ;Reset the stack pointer pop bp ;Restore BP rest_screen_ret: ret ;Return _restorescreen endp ; --------------------------------------------------------------------- ; Module : draw_wborder ; Function : Draw window border. ; Called as : void draw_wborder(int row1, int col1, int row2, int col2, ; int w_battr, char * w_bd_descriptor); ; ; static char BORDER_SINGLE[9] = "ÚÄ¿³ÙÄÀ³"; ; static char BORDER_DOUBLE[9] = "ÉÍ»º¼ÍȺ"; ; static char BORDER_ACTDLG[9] = "³ß³³ÙÄÀ³"; ; ; Notes : w_border parm is consistent with SA draw_border routine. ; The row2 and col2 parms must be changed if the SA routine ; is to replace this routine. ; if bigcode _draw_wborder proc far w_left equ <6[bp]> ; window left margin w_top equ <8[bp]> ; window top margin row2 equ <10[bp]> ; window bottom row col2 equ <12[bp]> ; window bottom col w_battr equ <14[bp]> ; border bg-fg attribute w_border equ <16[bp]> ; border descriptor DS:SI pointer else _draw_wborder proc near row1 equ <4[bp]> col1 equ <6[bp]> row2 equ <8[bp]> col2 equ <10[bp]> w_battr equ <12[bp]> ; border bg-fg attribute w_border equ <14[bp]> ; border descriptor DS:SI pointer endif rows equ <-2[bp]> ; row2 - row1 cols equ <-4[bp]> ; col2 - col1 - 2 w_bd_tlhc equ <-5[bp]> ; upper left corner border character w_bd_tline equ <-6[bp]> ; top row border character w_bd_trhc equ <-7[bp]> ; upper right corner border character w_bd_rside equ <-8[bp]> ; right side border character w_bd_brhc equ <-9[bp]> ; bottom right corner border character w_bd_bline equ <-10[bp]> ; bottom row border character w_bd_blhc equ <-11[bp]> ; bottom left corner border character w_bd_lside equ <-12[bp]> ; left side border character call _hide_mouse ;Hide the mouse pointer ; ; Set up the stack frame ; cmp __cputype,0 ;Check cpu type je draw_wborder_8086 enter 12,0 ;Set up the stack frame jmp short draw_wborder_000 draw_wborder_8086: push bp ;Save BP registers mov bp,sp ;Point it to the stack sub sp,12 ;Reserve local space draw_wborder_000: push di ;Save push es ; the push si ; registers ; ; Setup video variables ; mov ax,row1 ;Figure mov bx,col1 ; the call fig_vid_off ; video offset mov di,ax ;DI=Video offset mov es,displayseg ;ES=Video Segment mov ax,row2 ;Figure the difference sub ax,row1 ; of row2 - row1 mov rows,ax ;Save it mov ax,col2 ;Figure the sub ax,col1 ; the number dec ax ; of columns - 2 mov cols,ax ;Save it ; ; Save ds and point at the border descriptor struct ; if bigdata push ds ;Save DS lds si,w_border ;DS:SI=String pointer else mov si,w_border ;DS:SI=String pointer endif ; ; Unpack border descriptor ; cld ;Set the direction flag forward lodsb ;Get the next character mov w_bd_tlhc,al lodsb ;Get the next character mov w_bd_tline,al lodsb ;Get the next character mov w_bd_trhc,al lodsb ;Get the next character mov w_bd_rside,al lodsb ;Get the next character mov w_bd_brhc,al lodsb ;Get the next character mov w_bd_bline,al lodsb ;Get the next character mov w_bd_blhc,al lodsb ;Get the next character mov w_bd_lside,al ; ; Draw the border ; mov ah,att ;Set AH=Display attribute call disable_cga ;Disable the CGA if necessary push di ;Save the video offset mov al,w_bd_tlhc ;Set AL=tlhc character stosw ;Save the character/attribute pair ;Display the top line mov al,w_bd_tline ;Set AL=Top line character mov cx,cols ;CX=Line length rep stosw ;Repeat ah:al save till cx = 0 mov al,w_bd_trhc ;Set AL=trhc character stosw ;Save the character/attribute pair draw_wborder1: pop di ;Restore the video pointer add di,160 ;Point it to the next row dec word ptr rows ;Loop till the jz draw_wborder2 ; sides are complete push di ;Save the video pointer mov al,w_bd_lside ;Al=left side character stosw ;Save the left hand side add di,cols ;Point to the add di,cols ; right hand side mov al,w_bd_rside ;Al=right side character stosw ;Save the right hand side jmp draw_wborder1 ;Next line draw_wborder2: mov al,w_bd_blhc ;Set Al=blhc character stosw ;Save the video pointer ;Display the bottom line mov al,w_bd_bline ;Set AL=Bot line character mov cx,cols ;CX=Line length rep stosw ;Repeat ah:al save till cx = 0 mov al,W_bd_brhc ;Set AL=brhc character stosw ;Save the character/attribute pair call enable_cga ;Enable the cga if necessary if bigdata pop ds ;Restore DS endif pop si ;Restore pop es ; the other pop di ; registers call _show_mouse ;Restore the Mouse pointer cmp __cputype,0 ;Check cpu type je draw_wborder_8086x leave ;Restore the stack jmp short draw_wborder_ret draw_wborder_8086x: mov sp,bp ;Reset the stack pointer pop bp ;Restore BP draw_wborder_ret: ret ;Return _draw_wborder endp ; --------------------------------------------------------------------- ; Module : display ; Function : Display string ; Called as : void display(int row, int col, char* string); ; Notes : ; if bigcode _display proc far row equ <6[bp]> col equ <8[bp]> string equ <10[bp]> else _display proc near row equ <4[bp]> col equ <6[bp]> string equ <8[bp]> endif call _hide_mouse ;Hide the mouse pointer cmp __cputype,0 ;Check cpu type je display_8086 enter 0,0 ;Set up the stack frame jmp short display_000 display_8086: push bp ;Save BP registers mov bp,sp ;Point it to the stack display_000: push si ;Save push di ; the push es ; registers mov ax,row ;Figure mov bx,col ; the call fig_vid_off ; video offset mov di,ax ;DI=Video offset mov es,displayseg ;ES=Video Segment cld ;Flag increment cmp __ibmcga,0 ;IBM CGA? if bigdata push ds ;Save DS lds si,string ;DS:SI=String pointer else mov si,string ;DS:SI=String pointer endif je display2 ;Jump if IBM CGA display1: lodsb ;Get the next character or al,al ;Jump jz display6 ; if done stosb ;Display the character inc di ;Bump the video pointer jmp display1 ;Loop till done display2: mov dx,03dah ;DX=Video status register display3: lodsb ;Get the next character or al,al ;Jump jz display6 ; if done mov ah,al ;Put it in AH cli ;Disable the interrupts display4: in al,dx ;Loop and al,1 ; if in jnz display4 ; Horizontal Retrace display5: in al,dx ;Loop and al,1 ; if not in jz display5 ; Horizontal Retrace mov es:[di],ah ;Display the character sti ;Reenable interrupts inc di ;Bump the inc di ; video pointer jmp display3 ;Loop till done display6: if bigdata pop ds ;Restore DS endif pop es ;Restore pop di ; the pop si ; registers call _show_mouse ;Restore the Mouse pointer cmp __cputype,0 ;Check cpu type je display_8086x leave ;Restore the stack jmp short display_ret display_8086x: pop bp ;Restore BP display_ret: ret ;Return _display endp ; --------------------------------------------------------------------- ; Module : waitkey ; Function : Return (basically decimal) code values for a key. ; Called as : void waitkey(void); ; ; Notes : Key Plain +Ctrl +Alt ; ; Enter/GE 13 10 10 ; ESC 27 27 - ; ; Space 32 32 32 ; +/G+ 43 ; 0 48 ; 9 57 ; ? 63 - - ; ; A 65 1 286 Alt Q - Alt P 272 - 281 ; M 77 13 306 Alt A - Alt L 286 - 294 ; Z 90 26 300 Alt Z - Alt M 300 - 306 ; ; \ 92 ; a 97 1 286 ; m 109 13 306 ; z 122 26 300 ; | 124 ; ~ 126 ; ; F1 315 ; F10 324 ; F11 - ; F12 - ; ; Home 327 ; UpArrow 328 ; PgUp 329 ; LeftArrow 331 ; Numeric5 - ; RightArrow 333 ; End 335 ; DnArrow 336 ; PgDown 337 ; ; INS 338 ; DEL 339 ; ; Numlock - ; ; ; Get a Key ; 29 Jul 92 Dave Goodall 1.05 Waitkey documentation ; if bigcode _waitkey proc far else _waitkey proc near endif mov ah,01h ;Has a key int 16h ; been pressed? jz _waitkey ;Loop if not mov ah,0 ;Get int 16h ; the key or al,al ;Jump if jz wait_key1 ; extended key xor ah,ah ;Erase the scan code jmp short wait_key2 ;Jump wait_key1: xchg ah,al ;AX=Scan code inc ah ;AX=Scan code + 256 wait_key2: ret ;Return _waitkey endp ; --------------------------------------------------------------------- ; Module : fig_vid_off ; Function : Figure the video offset. ; Called as : fig_vid_off; ; ; Notes : Registers at call: ; fig_vid_off proc near push dx ;Save DX push bx ;Save the column dec ax ;Decrement the row mov bx,160 ;Figure the mul bx ; row offset pop bx ;Restore the column dec bx ;Decrement it sal bx,1 ;Figure the column pair offset add ax,bx ;AX=Video offset pop dx ;Restore DX ret ;Return fig_vid_off endp ; --------------------------------------------------------------------- ; Module : disable_cga ; Function : Disable the cga adapter during the vertical retrace period ; so that the calling routine can update the display memory ; without causing snow. ; References : IBM Technical Reference Personal Computer XT 6936808 ; pp 1-99 .. 1-101 ; PC Magazine Aug 21 1984 pp 225-230 ; Called as : call disable_cga ; ; Notes : Registers at call: None ; disable_cga proc near cmp __ibmcga,0 ;Jump if it jne disable_cga_2 ; isn't an IBM CGA push ax ;Save the push dx ; registers mov dx,3dah ;DX=Address of CRT Status register disable_cga_1: in al,dx ;Wait till status register bit 3 and al,8 ; goes active to indicate jz disable_cga_1 ; start of vertical retrace ;Vertical retrace period start: 1.2ms mov dx,3d8h ;DX=Address of CRT Mode-select register ; Bit 0 1=80x25 Alpha 0=40x25 Alpha ; Bit 1 1=320x200 Gr 0=Alpha ; Bit 2 1=B/W 0=Color ; Bit 3 1=Enable video 0=Disable video ; Bit 4 1=640x200 Gr 0=Alpha ; Bit 5 1=Blink 0=16 Bg colors ; Bit 6 0=Not used ; Bit 7 0=Not used mov al,1h ;AL=Set 80x25 alpha. Disable Video etc. out dx,al ;Execute disable pop dx ;Restore pop ax ; the registers disable_cga_2: ret ;Return disable_cga endp ; --------------------------------------------------------------------- ; Module : enable_cga ; Function : Re-enable the cga adapter video status register ; after the calling routine has updated display memory ; so that the updated memory will be displayed again. ; References : IBM Technical Reference Personal Computer XT 6936808 ; pp 1-99 .. 1-101 ; PC Magazine Aug 21 1984 pp 225-230 ; Called as : call enable_cga ; ; Notes : Registers at call: None ; enable_cga proc near cmp __ibmcga,0 ;Jump if it jne enable_cga_2 ; isn't an IBM CGA push ax ;Save push dx ; the push ds ; registers mov ax,bios_data ;Set the mov ds,ax ; data segment mov dx,3d8h ;DX=Address of CRT Mode-select register mov al,9h; ;Bits 7-0 = 00001001 out dx,al ;Set 80x25 alpha. Enable video. pop ds ;Restore pop dx ; the pop ax ; registers enable_cga_2: ret ;Return enable_cga endp if bigcode VIDEO_TEXT ends else _TEXT ends endif end ; End video.asm module ;