PAGE,120 TITLE ENHANCED GRAPHICS ADAPTER BIOS EXTRN CGMN:NEAR, CGDDOT:NEAR, INT_1F_1:NEAR, CGMN_FDG:NEAR EXTRN END_ADDRESS:NEAR ;---------------------------------------------------------------- ; THE BIOS ROUTINES ARE MEANT TO BE ACCESSED THROUGH : ; SOFTWARE INTERRUPTS ONLY. ANY ADDRESSES PRESENT IN : ; THE LISTINGS ARE INCLUDED ONLY FOR COMPLETENESS, : ; NOT FOR REFERENCE. APPLICATIONS WHICH REFERENCE : ; ABSOLUTE ADDRESSES WITHIN THE CODE SEGMENT : ; VIOLATE THE STRUCTURE AND DESIGN OF BIOS. : ;---------------------------------------------------------------- .LIST ;;; INCLUDE VFRONT.INC SUBTTL VFRONT.INC PAGE ;--- INT 10 ------------------------------------------------------------- ; VIDEO_IO : ; THESE ROUTINES PROVIDE THE CRT INTERFACE : ; THE FOLLOWING FUNCTIONS ARE PROVIDED: : ; (AH)=0 SET MODE (AL) CONTAINS MODE VALUE : ; : ; AL AD TYPE RES NOTES DF-DIM DISPLAY MAX PGS : ; ------------------------------------------------------------- : ; * 0 B8 ALPHA 640X200 40X25 COLOR - BW 8 : ; 1 B8 ALPHA 640X200 40X25 COLOR 8 : ; * 2 B8 ALPHA 640X200 80X25 COLOR - BW 8 : ; 3 B8 ALPHA 640X200 80X25 COLOR 8 : ; 4 B8 GRPHX 320X200 40X25 COLOR 1 : ; 5 B8 GRPHX 320X200 40X25 COLOR - BW 1 : ; 6 B8 GRPHX 640X200 80X25 COLOR - BW 1 : ; * 7 B0 ALPHA 720X350 80X25 MONOCHROME 8 : ; : ; 8 RESERVED : ; 9 RESERVED : ; A RESERVED : ; B RESERVED - INTERNAL USE : ; C RESERVED - INTERNAL USE : ; : ; D A0 GRPHX 320X200 40X25 COLOR 8 : ; E A0 GRPHX 640X200 80X25 COLOR 4 : ; F A0 GRPHX 640X350 80X25 MONOCHROME 2 : ; 10 A0 GRPHX 640X350 80X25 HI RES 2 : ; : ; NOTE : HIGH BIT AL SET PREVENTS REGEN BUFFER CLEAR ON : ; MODES RUNNING ON THE COMBO VIDEO ADAPTER : ; : ; *** NOTE BW MODES OPERATE SAME AS COLOR MODES, BUT : ; COLOR BURST IS NOT ENABLED : ; (AH)=1 SET CURSOR TYPE : ; (CH) = BITS 4-0 = START LINE FOR CURSOR : ; ** HARDWARE WILL ALWAYS CAUSE BLINK : ; ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC : ; BLINKING OR NO CURSOR AT ALL : ; (CL) = BITS 4-0 = END LINE FOR CURSOR : ; (AH)=2 SET CURSOR POSITION : ; (DH,DL) = ROW,COLUMN (0,0) IS UPPER LEFT : ; (BH) = PAGE NUMBER : ; (AH)=3 READ CURSOR POSITION : ; (BH) = PAGE NUMBER : ; ON EXIT (DH,DL) = ROW,COLUMN OF CURRENT CURSOR : ; (CH,CL) = CURSOR MODE CURRENTLY SET : ; (AH)=4 READ LIGHT PEN POSITION : ; ON EXIT: : ; (AH) = 0 -- LIGHT PEN SWITCH NOT DOWN/NOT TRIGGERED : ; (AH) = 1 -- VALID LIGHT PEN VALUE IN REGISTERS : ; (DH,DL) = ROW,COLUMN OF CHARACTER LP POSN : ; (CH) = RASTER LINE (0-199) : ; (CX) = RASTER LINE (0-NNN) NEW GRAPHICS MODES : ; (BX) = PIXEL COLUMN (0-319,639) : ; (AH)=5 SELECT ACTIVE DISPLAY PAGE : ; (AL) = NEW PAGE VALUE, SEE AH=0 FOR PAGE INFO : ; (AH)=6 SCROLL ACTIVE PAGE UP : ; (AL) = NUMBER OF LINES, INPUT LINES BLANKED AT BOTTOM : ; OF WINDOW : ; AL = 0 MEANS BLANK ENTIRE WINDOW : ; (CH,CL) = ROW,COLUMN OF UPPER LEFT CORNER OF SCROLL : ; (DH,DL) = ROW,COLUMN OF LOWER RIGHT CORNER OF SCROLL : ; (BH) = ATTRIBUTE TO BE USED ON BLANK LINE : ; (AH)=7 SCROLL ACTIVE PAGE DOWN : ; (AL) = NUMBER OF LINES, INPUT LINES BLANKED AT TOP : ; OF WINDOW : ; AL = 0 MEANS BLANK ENTIRE WINDOW : ; (CH,CL) = ROW,COLUMN OF UPPER LEFT CORNER OF SCROLL : ; (DH,DL) = ROW,COLUMN OF LOWER RIGHT CORNER OF SCROLL : ; (BH) = ATTRIBUTE TO BE USED ON BLANK LINE : ; : ; CHARACTER HANDLING ROUTINES : ; : ; (AH) = 8 READ ATTRIBUTE/CHARACTER AT CURRENT CURSOR POSITION : ; (BH) = DISPLAY PAGE : ; ON EXIT: : ; (AL) = CHAR READ : ; (AH) = ATTRIBUTE OF CHARACTER READ (ALPHA MODES ONLY) : ; (AH) = 9 WRITE ATTRIBUTE/CHARACTER AT CURRENT CURSOR POSITION : ; (BH) = DISPLAY PAGE : ; (CX) = COUNT OF CHARACTERS TO WRITE : ; (AL) = CHAR TO WRITE : ; (BL) = ATTRIBUTE OF CHARACTER (ALPHA)/COLOR OF CHAR : ; (GRAPHICS) : ; SEE NOTE ON WRITE DOT FOR BIT 7 OF BL = 1. : ; (AH) = A WRITE CHARACTER ONLY AT CURRENT CURSOR POSITION : ; (BH) = DISPLAY PAGE : ; (CX) = COUNT OF CHARACTERS TO WRITE : ; (AL) = CHAR TO WRITE : ; FOR READ/WRITE CHARACTER INTERFACE WHILE IN GRAPHICS MODE, THE : ; CHARACTERS ARE FORMED FROM A CHARACTER GENERATOR IMAGE : ; MAINTAINED IN THE SYSTEM ROM. ONLY THE 1ST 128 CHARS : ; ARE CONTAINED THERE. TO READ/WRITE THE SECOND 128 : ; CHARS, THE USER MUST INITIALIZE THE POINTER AT : ; INTERRUPT 1FH (LOCATION 0007CH) TO POINT TO THE 1K BYTE : ; TABLE CONTAINING THE CODE POINTS FOR THE SECOND : ; 128 CHARS (128-255). : ; : ; FOR THE NEW GRAPHICS MODES 256 GRAPHICS CHARS ARE : ; SUPPLIED IN THE SYSTEM ROM. : ; : ; FOR WRITE CHARACTER INTERFACE IN GRAPHICS MODE, THE REPLICATION : ; FACTOR CONTAINED IN (CX) ON ENTRY WILL PRODUCE VALID : ; RESULTS ONLY FOR CHARACTERS CONTAINED ON THE SAME ROW. : ; CONTINUATION TO SUCCEEDING LINES WILL NOT PRODUCE : ; CORRECTLY. : ; : ; GRAPHICS INTERFACE : ; (AH) = B SET COLOR PALETTE : ; FOR USE IN COMPATIBILITY MODES : ; (BH) = PALETTE COLOR ID BEING SET (0-127) : ; (BL) = COLOR VALUE TO BE USED WITH THAT COLOR ID : ; NOTE: FOR THE CURRENT COLOR CARD, THIS ENTRY POINT : ; HAS MEANING ONLY FOR 320X200 GRAPHICS. : ; COLOR ID = 0 SELECTS THE BACKGROUND COLOR (0-15): ; COLOR ID = 1 SELECTS THE PALETTE TO BE USED: : ; 0 = GREEN(1)/RED(2)/BROWN(3) : ; 1 = CYAN(1)/MAGENTA(2)/WHITE(3) : ; IN 40X25 OR 80X25 ALPHA MODES, THE VALUE SET : ; FOR PALETTE COLOR 0 INDICATES THE : ; BORDER COLOR TO BE USED (VALUES 0-31, : ; WHERE 16-31 SELECT THE HIGH INTENSITY : ; BACKGROUND SET). : ; (AH) = C WRITE DOT : ; (BH) = PAGE : ; (DX) = ROW NUMBER : ; (CX) = COLUMN NUMBER : ; (AL) = COLOR VALUE : ; IF BIT 7 OF AL = 1, THEN THE COLOR VALUE IS : ; EXCLUSIVE OR'D WITH THE CURRENT CONTENTS OF : ; THE DOT : ; (AH) = D READ DOT : ; (BH) = PAGE : ; (DX) = ROW NUMBER : ; (CX) = COLUMN NUMBER : ; (AL) RETURNS THE DOT READ : ; : ; ASCII TELETYPE ROUTINE FOR OUTPUT : ; : ; (AH) = E WRITE TELETYPE TO ACTIVE PAGE : ; (AL) = CHAR TO WRITE : ; (BL) = FOREGROUND COLOR IN GRAPHICS MODE : ; NOTE -- SCREEN WIDTH IS CONTROLLED BY PREVIOUS MODE SET : ; : ; (AH) = F CURRENT VIDEO STATE : ; RETURNS THE CURRENT VIDEO STATE : ; (AL) = MODE CURRENTLY SET (SEE AH=0 FOR EXPLANATION) : ; (AH) = NUMBER OF CHARACTER COLUMNS ON SCREEN : ; (BH) = CURRENT ACTIVE DISPLAY PAGE : ; : ; (AH) = 10 SET PALETTE REGISTERS : ; : ; (AL) = 0 SET INDIVIDUAL PALETTE REGISTER : ; BL = PALETTE REGISTER TO BE SET : ; BH = VALUE TO SET : ; : ; AL = 1 SET OVERSCAN REGISTER : ; BH = VALUE TO SET : ; : ; AL = 2 SET ALL PALETTE REGISTERS AND OVERSCAN : ; ES:DX POINTS TO A 17 BYTE TABLE : ; BYTES 0 - 15 ARE THE PALETTE VALUES, RESPECTIVELY : ; BYTE 16 IS THE OVERSCAN VALUE : ; : ; AL= 3 TOGGLE INTENSIFY/BLINKING BIT : ; BL - 0 ENABLE INTENSIFY : ; BL - 1 ENABLE BLINKING : ; : ; (AH) = 11 CHARACTER GENERATOR ROUTINE : ; NOTE : THIS CALL WILL INITIATE A MODE SET, COMPLETELY : ; RESETTING THE VIDEO ENVIRONMENT BUT MAINTAINING : ; THE REGEN BUFFER. : ; : ; AL = 00 USER ALPHA LOAD : ; ES:BP - POINTER TO USER TABLE : ; CX - COUNT TO STORE : ; DX - CHARACTER OFFSET INTO TABLE : ; BL - BLOCK TO LOAD : ; BH - NUMBER OF BYTES PER CHARACTER : ; AL = 01 ROM MONOCHROME SET : ; BL - BLOCK TO LOAD : ; AL = 02 ROM 8X8 DOUBLE DOT : ; BL - BLOCK TO LOAD : ; AL = 03 SET BLOCK SPECIFIER : ; BL - CHAR GEN BLOCK SPECIFIER : ; D3-D2 ATTR BIT 3 ONE, CHAR GEN 0-3 : ; D1-D0 ATTR BIT 3 ZERO, CHAR GEN 0-3 : ; NOTE : WHEN USING AL = 03 A FUNCTION CALL : ; AX = 1000H : ; BX = 0712H : ; IS RECOMMENDED TO SET THE COLOR PLANES : ; RESULTING IN 512 CHARACTERS AND EIGHT : ; CONSISTENT COLORS. : ; : ; NOTE : THE FOLLOWING INTERFACE (AL=1X) IS SIMILAR IN FUNCTION : ; TO (AL=0X) EXCEPT THAT : : ; - PAGE ZERO MUST BE ACTIVE : ; - POINTS (BYTES/CHAR) WILL BE RECALCULATED : ; - ROWS WILL BE CALCULATED FROM THE FOLLOWING: : ; INT[(200 OR 350) / POINTS] - 1 : ; - CRT LEN WILL BE CALCULATED FROM : : ; (ROWS + 1) * CRT_COLS * 2 : ; - THE CRTC WILL BE REPROGRAMMED AS FOLLOWS : : ; R09H = POINTS - 1 MAX SCAN LINE : ; R09H DONE ONLY IN MODE 7 : ; R0AH = POINTS - 2 CURSOR START : ; R0BH = 0 CURSOR END : ; R12H = VERT DISP END : ; [(ROWS + 1) * POINTS] - 1 : ; R14H = POINTS UNDERLINE LOC : ; : ; THE ABOVE REGISTER CALCULATIONS MUST BE CLOSE TO THE : ; ORIGINAL TABLE VALUES OR UNDETERMINED RESULTS WILL : ; OCCUR. : ; : ; NOTE : THE FOLLOWING INTERFACE IS DESIGNED TO BE : ; CALLED ONLY IMMEDIATELY AFTER A MODE SET HAS : ; BEEN ISSUED. FAILURE TO ADHERE TO THIS PRACTICE : ; MAY CAUSE UNDETERMINED RESULTS. : ; : ; AL = 10 USER ALPHA LOAD : ; ES:BP - POINTER TO USER TABLE : ; CX - COUNT TO STORE : ; DX - CHARACTER OFFSET INTO TABLE : ; BL - BLOCK TO LOAD : ; BH - NUMBER OF BYTES PER CHARACTER : ; AL = 11 ROM MONOCHROME SET : ; BL - BLOCK TO LOAD : ; AL = 12 ROM 8X8 DOUBLE DOT : ; BL - BLOCK TO LOAD : ; : ; : ; NOTE : THE FOLLOWING INTERFACE IS DESIGNED TO BE : ; CALLED ONLY IMMEDIATELY AFTER A MODE SET HAS : ; BEEN ISSUED. FAILURE TO ADHERE TO THIS PRACTICE : ; MAY CAUSE UNDETERMINED RESULTS. : ; : ; AL = 20 USER GRAPHICS CHARS INT 01FH (8X8) : ; ES:BP - POINTER TO USER TABLE : ; AL = 21 USER GRAPHICS CHARS : ; ES:BP - POINTER TO USER TABLE : ; CX - POINTS (BYTES PER CHARACTER) : ; BL - ROW SPECIFIER : ; : ; BL = 0 USER : ; DL - ROWS : ; BL = 1 14 (0EH) : ; BL = 2 25 (19H) : ; BL = 3 43 (2BH) : ; : ; AL = 22 ROM 8 X 14 SET : ; BL - ROW SPECIFIER : ; AL = 23 ROM 8 X 8 DOUBLE DOT : ; BL - ROW SPECIFIER : ; : ; : ; AL = 30 INFORMATION : ; CX - POINTS : ; DL - ROWS : ; BH - 0 RETURN CURRENT INT 1FH PTR : ; ES:BP - PTR TO TABLE : ; BH - 1 RETURN CURRENT INT 44H PTR : ; ES:BP - PTR TO TABLE : ; BH - 2 RETURN ROM 8 X 14 PTR : ; ES:BP - PTR TO TABLE : ; BH - 3 RETURN ROM DOUBLE DOT PTR : ; ES:BP - PTR TO TABLE : ; BH - 4 RETURN ROM DOUBLE DOT PTR (TOP) : ; ES:BP - PTR TO TABLE : ; BH - 5 RETURN ROM ALPHA ALTERNATE 9X14 : ; ES:BP - PTR TO TABLE : ; : ; (AH) = 12 ALTERNATE SELECT : ; : ; BL = 10 RETURN EGA INFORMATION : ; BH = 0 - COLOR MODE IN EFFECT <3> : ; 1 - MONOC MODE IN EFFECT <3> : ; BL = MEMORY VALUE : ; 0 0 - 064K 0 1 - 128K : ; 1 0 - 192K 1 1 - 256K : ; CH = FEATURE BITS : ; CL = SWITCH SETTING : ; : ; BL = 20 SELECT ALTERNATE PRINT SCREEN ROUTINE : ; : ; (AH) = 13 WRITE STRING : ; ES:BP - POINTER TO STRING TO BE WRITTEN : ; CX - CHARACTER ONLY COUNT : ; DX - POSITION TO BEGIN STRING, IN CURSOR : ; TERMS : ; BH - PAGE NUMBER : ; : ; AL = 0 : ; BL - ATTRIBUTE : ; STRING - (CHAR, CHAR, CHAR, ...) : ; CURSOR NOT MOVED : ; AL = 1 : ; BL - ATTRIBUTE : ; STRING - (CHAR, CHAR, CHAR, ...) : ; CURSOR IS MOVED : ; AL = 2 : ; STRING - (CHAR, ATTR, CHAR, ATTR, ...) : ; CURSOR NOT MOVED : ; AL = 3 : ; STRING - (CHAR, ATTR, CHAR, ATTR, ...) : ; CURSOR IS MOVED : ; : ; NOTE : CHAR RET, LINE FEED, BACKSPACE, AND BELL ARE : ; TREATED AS COMMANDS RATHER THAN PRINTABLE : ; CHARACTERS. : ; : ;------------------------------------------------------------------------ SRLOAD MACRO SEGREG,VALUE IFNB IFIDN ,<0> SUB DX,DX ELSE MOV DX,VALUE ENDIF ENDIF MOV SEGREG,DX ENDM ;----- LOW MEMORY SEGMENT ABS0 SEGMENT AT 0 ORG 005H*4 ; PRINT SCREEN VECTOR INT5_PTR LABEL DWORD ORG 010H*4 ; VIDEO I/O VECTOR VIDEO LABEL DWORD ORG 01FH*4 ; GRAPHIC CHARS 128-255 EXT_PTR LABEL DWORD ORG 042H*4 ; REVECTORED 10H*4 PLANAR_VIDEO LABEL DWORD ORG 043H*4 ; GRAPHIC CHARS 0-255 GRX_SET LABEL DWORD ORG 0410H EQUIP_LOW LABEL BYTE EQUIP_FLAG DW ? ;----- REUSE RAM FROM PLANAR BIOS ORG 449H CRT_MODE DB ? CRT_COLS DW ? CRT_LEN DW ? CRT_START DW ? CURSOR_POSN DW 8 DUP(?) CURSOR_MODE DW ? ACTIVE_PAGE DB ? ADDR_6845 DW ? CRT_MODE_SET DB ? CRT_PALETTE DB ? ORG 0472H RESET_FLAG DW ? ORG 0484H ROWS DB ? ; ROWS ON THE SCREEN POINTS DW ? ; BYTES PER CHARACTER INFO DB ? ; INFO ; D7 - HIGH BIT OF MODE SET, CLEAR/NOT CLEAR REGEN ; D6 - MEMORY D6 D5 = 0 0 - 064K 0 1 - 128K ; D5 - MEMORY 1 0 - 192K 1 1 - 256K ; D4 - RESERVED ; D3 - EGA ACTIVE MONITOR (0), EGA NOT ACTIVE (1) ; D2 - WAIT FOR DISPLAY ENABLE (1) ; D1 - EGA HAS A MONOCHROME ATTACHED (1) ; D0 - SET C_TYPE EMULATE ACTIVE (0) INFO_3 DB ? ; INFO_3 ; D7-D4 FEATURE BITS ; D3-D0 SWITCHES ORG 04A8H SAVE_PTR LABEL DWORD ;----- SAVE_PTR ; ; SAVE_PTR IS A POINTER TO A TABLE AS DESCRIBED AS FOLLOWS : ; ; DWORD_1 VIDEO PARAMETER TABLE POINTER ; DWORD_2 DYNAMIC SAVE AREA POINTER ; DWORD_3 ALPHA MODE AUXILIARY CHAR GEN POINTER ; DWORD_4 GRAPHICS MODE AUXILIARY CHAR GEN POINTER ; DWORD_5 RESERVED ; DWORD_6 RESERVED ; DWORD_7 RESERVED ; ; DWORD_1 PARAMETER TABLE POINTER ; INITIALIZED TO BIOS EGA PARAMETER TABLE. ; THIS VALUE MUST EXIST. ; ; DWORD_2 PARAMETER SAVE AREA POINTER ; INITIALIZED TO 0000:0000, THIS VALUE IS OPTIONAL. ; WHEN NON-ZERO, THIS POINTER WILL BE USED AS POINTER ; TO A RAM AREA WHERE CERTAIN DYNAMIC VALUES ARE TO ; BE SAVED. WHEN IN EGA OPERATION THIS RAM AREA WILL ; HOLD THE 16 EGA PALETTE REGISTER VALUES PLUS ; THE OVERSCAN VALUE IN BYTES 0-16D RESPECTIVELY. ; AT LEAST 256 BYTES MUST BE ALLOCATED FOR THIS AREA. ; ; DWORD_3 ALPHA MODE AUXILIARY POINTER ; INITIALIZED TO 0000:0000, THIS VALUE IS OPTIONAL. ; WHEN NON-ZERO, THIS POINTER IS USED AS A POINTER ; TO A TABLES DESCRIBED AS FOLLOWS : ; ; BYTE BYTES/CHARACTER ; BYTE BLOCK TO LOAD, SHOULD BE ZERO FOR NORMAL ; OPERATION ; WORD COUNT TO STORE, SHOULO BE 256D FOR NORMAL ; OPERATION ; WORD CHARACTER OFFSET, SHOULD BE ZERO FOR NORMAL ; OPERATION ; DWORD POINTER TO A FONT TABLE ; BYTE DISPLAYABLE ROWS ; IF 'FF' THE MAXIMUM CALCULATED VALUE WILL BE ; USED, ELSE THIS VALUE WILL BE USED. ; BYTE CONSECUTIVE BYTES OF MODE VALUES FOR WHICH ; THIS FONT DESCRIPTION IS TO BE USED. ; THE END OF THIS STREAM IS INDICATED BY A ; BYTE CODE OF 'FF' ; ; NOTE : USE OF THIS POINTER MAY CAUSE UNEXPECTED ; CURSOR TYPE OPERATION. FOR AN EXPLANATION ; OF CURSOR TYPE SEE AH = 01 IN THE INTERFACE ; SECTION. ; ; DWORD_4 GRAPHICS MODE AUXILIARY POINTER ; INITIALIZED TO 0000:0000, THIS VALUE IS OPTIONAL. ; WHEN NON-ZERO, THIS POINTER IS USED AS A POINTER ; TO A TABLES DESCRIBED AS FOLLOWS : ; ; BYTE DISPLAYABLE ROWS ; WORD BYTES PER CHARACTER ; DWORD POINTER TO A FONT TABLE ; BYTE CONSECUTIVE BYTES OF MODE VALUES FOR WHICH ; THIS FONT DESCRIPTION IS TO BE USED. ; THE END OF THIS STREAM IS INDICATED BY A ; BYTE CODE OF 'FF' ; ; DWORD_5 THRU DWORD_7 ; RESERVED AND SET TO 0000:0000. ; ORG 0500H STATUS_BYTE DB ? ABS0 ENDS PORT_B EQU 61H ; 8255 PORT B ADDR TIMER EQU 40H ;----- EQUATES FOR CARD PORT ADDRESSES SEQ_ADDR EQU 0C4H SEQ_DATA EQU 0C5H CRTC_ADDR EQU 0D4H CRTC_ADDR_B EQU 0B4H CRTC_DATA EQU 0D5H ; OR 0B5H GRAPH_1_POS EQU 0CCH GRAPH_2_POS EQU 0CAH GRAPH_ADDR EQU 0CEH GRAPH_DATA EQU 0CFH MISC_OUTPUT EQU 0C2H IN_STAT_0 EQU 0C2H INPUT_STATUS_B EQU 0BAH INPUT_STATUS EQU 0DAH ATTR_READ EQU 0DAH ATTR_WRITE EQU 0C0H ;----- EQUATES FOR ADDRESS REGISTER VALUES S_RESET EQU 00H S_CLOCK EQU 01H S_MAP EQU 02H S_CGEN EQU 03H S_MEM EQU 04H C_HRZ_TOT EQU 00H C_HRZ_DSP EQU 01H C_STRT_HRZ_BLK EQU 02H C_END_HRZ_BLK EQU 03H C_STRT_HRZ_SYN EQU 04H C_END_HRZ_SYN EQU 05H C_VRT_TOT EQU 06H C_OVERFLOW EQU 07H C_PRE_ROW EQU 08H C_MAX_SCAN_LN EQU 09H C_CRSR_START EQU 0AH C_CRSR_ENO EQU 0BH C_STRT_HGH EQU 0CH C_STRT_LOW EQU 0DH C_CRSR_LOC_HGH EQU 0EH C_CRSR_LOC_LOW EQU 0FH C_VRT_SYN_STRT EQU 10H ; WRITE ONLY C_LGHT_PEN_HGH EQU 10H ; READ ONLY C_VRT_SYN_END EQU 11H ; WRITE ONLY C_LGHT_PEN_LOW EQU 11H ; READ ONLY C_VRT_DSP_END EQU 12H C_OFFSET EQU 13H C_UNDERLN_LOC EQU 14H C_STRT_VRT_BLK EQU 15H C_END_VRT_BLK EQU 16H C_MODE_CNTL EQU 17H C_LN_COMP EQU 18H G_SET_RESET EQU 00H G_ENBL_SET EQU 01H G_CLR_COMP EQU 02H G_DATA_ROT EQU 03H G_READ_MAP EQU 04H G_MODC EQU 05H G_MISC EQU 06H G_COLOR EQU 07H G_BIT_MASK EQU 08H P_MODE EQU 10H P_OVERSC EQU 11H P_CPLANE EQU 12H P_HPEL EQU 13H SUBTTL ;----- CODE SEGMENT CODE SEGMENT PUBLIC ;;; INCLUDE VPOST INC SUBTTL VPOST.INC PAGE ;----- POST ASSUME CS:CODE,DS:ABS0 ORG 0H DB 055H ; SIGNATURE DB 0AAH ; BYTES DB 020H ; LENGTH INDICATOR ;----- NOTE : DO NOT USE THE SIGNATURE BYTES AS A PRESENCE TEST ; PLANAR VIDEO SWITCH SETTINGS ; 0 0 - UNUSED ; 0 1 - 40 X 25 COLOR ; 1 0 - 80 X 25 COLOR ; 1 1 - 80 X 25 MONOCHROME ; NOTE : 0 0 MUST BE SET WHEN THIS ADAPTER IS INSTALLED. ; VIDEO ADAPTER SWITCH SETTINGS ; 0 0 0 0 - MONOC PRIMARY, EGA COLOR, 40X25 ; 0 0 0 1 - MONOC PRIMARY, EGA COLOR, 80X25 ; 0 0 1 0 - MONOC PRIMARY, EGA HI RES EMULATE (SAME AS 0001) ; 0 0 1 1 - MONOC PRIMARY, EGA HI RES ENHANCED ; 0 1 0 0 - COLOR 40 PRIMARY, EGA MONOCHROME ; 0 1 0 1 - COLOR 80 PRIMARY, EGA MONOCHROME ; 0 1 1 0 - MONOC SECONDARY, EGA COLOR, 40X25 ; 0 1 1 1 - MONOC SECONDARY, EGA COLOR, 80X25 ; 1 0 0 0 - MONOC SECONDARY, EGA HI RES EMULATE (SAME AS 0111) ; 1 0 0 1 - MONOC SECONDARY, EGA HI RES ENHANCED ; 1 0 1 0 - COLOR 40 SECONDARY, EGA MONOCHROME ; 1 0 1 1 - COLOR 80 SECONDARY, EGA MONOCHROME ; 1 1 0 0 - RESERVED ; 1 1 0 1 - RESERVED ; 1 1 1 0 - RESERVED ; 1 1 1 1 - RESERVED ;----- SETUP ROUTINE FOR THIS MODULE VIDEO_SETUP PROC FAR JMP SHORT L1 DB '2400' DB '6277356 (C)COPYRIGHT IBM 1984' DB '9/13/84' ;----- SET UP VIDEO VECTORS L1: MOV DH,3 MOV DL,INPUT_STATUS IN AL,DX MOV DL,INPUT_STATUS_B IN AL,DX MOV DL,ATTR_WRITE MOV AL,0 OUT DX,AL SRLOAD DS,0 ;;;SUB DX,DX ;;;MOV DS,DX CLI MOV WORD PTR VIDEO,OFFSET COMBO_VIDEO MOV WORD PTR VIDEO+2, CS MOV WORD PTR PLANAR_VIDEO,0F065H MOV WORD PTR PLANAR_VIDEO+2,0F000H MOV WORD PTR SAVE_PTR,OFFSET SAVE_TBL MOV WORD PTR SAVE_PTR+2, CS MOV WORD PTR EXT_PTR, OFFSET INT_1F_1 MOV WORD PTR EXT_PTR+2, CS MOV WORD PTR GRX_SET, OFFSET CGDDOT MOV WORD PTR GRX_SET+2, CS STI ;----- POST FOR COMBO VIDEO CARD MOV INFO,00000100B CALL RD_SWS MOV INFO_3,BL CALL F_BTS OR INFO_3,AL MOV BL,INFO_3 CALL MK_ENV JMP POST SKIP: RET VIDEO_SETUP ENDP POR_1 PROC NEAR OUT DX,AL PUSH AX POP AX IN AL,DX AND AL,010H SHR AL,1 RET POR_1 ENDP ;----- READ THE SWITCH SETTINGS ON THE CARD RD_SWS PROC NEAR ASSUME DS:ABS0 MOV DH,3 MOV DL,MISC_OUTPUT MOV AL,1 OUT DX,AL ;----- COULD BE 0,4,8,C MOV AL,0DH CALL POR_1 SHR AL,1 SHR AL,1 SHR AL,1 MOV BL,AL MOV AL,9 CALL POR_1 SHR AL,1 SHR AL,1 OR BL,AL MOV AL,5 CALL POR_1 SHR AL,1 OR BL,AL MOV AL,1 CALL POR_1 OR BL,AL AND BL,0FH RET RD_SWS ENDP ;----- OBTAIN THE FEATURE BITS FROM DAUGHTER CARD F_BTS PROC NEAR MOV DH,3 MOV DL,0BAH MOV AL,1 OUT DX,AL MOV DL,0DAH OUT DX,AL MOV DL,IN_STAT_0 IN AL,DX ; READ FEATURE BITS AND AL,060H SHR AL,1 MOV BL,AL MOV DL,0BAH MOV AL,2 OUT DX,AL MOV DL,0DAH OUT DX,AL MOV DL,IN_STAT_0 IN AL,DX ; READ FEATURE BITS AND AL,060H SHL AL,1 OR AL,BL RET F_BTS ENDP ;----- ESTABLISH THE VIDEO ENVIRONMENT, KEYED OFF OF THE SWITCHES MK_ENV PROC NEAR ASSUME DS:ABS0 SUB BH,BH AND BL,0FH SAL BX,1 PUSH DX MOV DH,3 MOV AH,DH POP DX AND AH,1 INC AH NOT AH JMP WORD PTR CS:[BX + OFFSET T5] SAVE_TBL LABEL DWORD DW OFFSET VIDEO_PARMS ; PARMS DW 0C000H ; PARMS DW 0 ; PAL SAVE AREA DW 0 ; PAL SAVE AREA DW 0 ; ALPHA TABLES DW 0 ; ALPHA TABLES DW 0 ; GRAPHICS TABLES DW 0 ; GRAPHICS TABLES DW 0 DW 0 DW 0 DW 0 DW 0 DW 0 T5 LABEL WORD DW OFFSET PST_0 DW OFFSET PST_1 DW OFFSET PST_2 DW OFFSET PST_3 DW OFFSET PST_4 DW OFFSET PST_5 DW OFFSET PST_6 DW OFFSET PST_7 DW OFFSET PST_8 DW OFFSET PST_9 DW OFFSET PST_A DW OFFSET PST_B DW OFFSET PST_OUT DW OFFSET PST_OUT DW OFFSET PST_OUT DW OFFSET PST_OUT ENV_X PROC NEAR ; SET 40X25 COLOR ALPHA AND EQUIP_LOW,0CFH OR EQUIP_LOW,010H MOV AX,1H INT 10H RET ENV_X ENDP ENV_0 PROC NEAR ; SET 80X25 COLOR ALPHA AND EQUIP_LOW,0CFH OR EQUIP_LOW,020H MOV AX,03H INT 10H RET ENV_0 ENDP ENV_3 PROC NEAR ; SET MONOCHROME ALPHA OR EQUIP_LOW,030H MOV AX,07H INT 10H RET ENV_3 ENDP PST_0: AND INFO,AH CALL ENV_X CALL ENV_3 RET PST_1: PST_2: AND INFO,AH CALL ENV_0 CALL ENV_3 RET PST_3: AND INFO,AH CALL ENV_0 CALL ENV_3 RET PST_4: MOV DH,3 MOV DL,MISC_OUTPUT MOV AL,0 OUT DX,AL NOT AH OR INFO,AH CALL ENV_3 CALL ENV_X RET PST_5: MOV DH,3 MOV DL,MISC_OUTPUT MOV AL,0 OUT DX,AL NOT AH OR INFO,AH CALL ENV_3 CALL ENV_0 RET PST_6: AND INFO,AH CALL ENV_3 CALL ENV_X RET PST_7: PST_8: AND INFO,AH CALL ENV_3 CALL ENV_0 RET PST_9: AND INFO,AH CALL ENV_3 CALL ENV_0 RET PST_A: MOV DH,3 MOV DL,MISC_OUTPUT MOV AL,0 OUT DX,AL NOT AH OR INFO,AH CALL ENV_X CALL ENV_3 RET PST_B: MOV DH,3 MOV DL,MISC_OUTPUT MOV AL,0 OUT DX,AL NOT AH OR INFO,AH CALL ENV_0 CALL ENV_3 PST_OUT: RET MK_ENV ENDP ;------------------------------------------------------------------------ ; THIS ROUTINE TESTS THE CRT CARD INTERNAL DATA BUS AND IN A LIMITED : ; WAY TESTS THE CRTC VIDEO CHIP BY WRITING/READING FROM CURSOR REGISTER : ; CARRY IS SET IF AN ERROR IS FOUND : ; : ; REGISTERS BX,SI,ES,DS ARE PRESERVED. : ; REGISTERS AX,CX,DX ARE MODIFYED. : ;------------------------------------------------------------------------ CD_PRESENCE_TST PROC NEAR PUSH BX ; SAVE BX MOV BX,07FH ; INITIAL WORD PATTERN BYTE MOV DI,BX PUSH AX ; SAVE PORT ADDRESS CALL RD_CURSOR ; MOV SI,AX ; SAVE ORIGINAL VALUE POP AX ; RECOVER PORT ADDRESS PUSH AX ; SAVE PORT ADDRESS CALL WR_CURSOR ; WRITE CURSOR POP AX ; RECOVER PORT ADDRESS PUSH AX ; SAVE PORT ADDRESS CALL RD_CURSOR ; READ IT BACK CMP AX,DI ; SAME? POP AX JNZ NOT_PRESENT ; EXIT IF NOT EQUAL JMP TST_EX NOT_PRESENT: XOR AX,AX ; SET NOT PRESENT POP BX RET TST_EX: MOV AX,1 ; SET PRESENT ON EXIT POP BX ; RESTORE BX RET CD_PRESENCE_TST ENDP ;------------------------------------------------------------------------ ; MODULE NAME RD_CURSOR : ; READ CURSOR POSITION [ADDRESS] (FROM CRTC) TO AX : ; : ; REGISTER AX IS MODIFIED. : ;------------------------------------------------------------------------ RD_CURSOR PROC NEAR PUSH DX ; SAVE REGS USED MOV DX,AX MOV AL,C_CRSR_LOC_HGH OUT DX,AL INC DX IN AL,DX ; RETURN WITH CURSOR POS IN AX ; RESTORE REGS USED POP DX RET RD_CURSOR ENDP ;------------------------------------------------------------------------ ; MODULE NAME WR_CURSOR : ; WRITE CURSOR POSITION [ADDRESS] (TO CRTC) WITH CONTENTS OF AX : ; : ; ALL REGISTERS PRESERVED : ;------------------------------------------------------------------------ WR_CURSOR PROC NEAR ; SAVE REGS USED PUSH AX PUSH DX MOV DX,AX MOV AH,C_CRSR_LOC_HGH ; CURSOR LOCATION HIGH INDEX MOV AL,07FH ; TEST VALUE CALL OUT_DX ; RETURN WITH CURSOR POS IN AX ; RESTORE REGS USED POP DX POP AX RET WR_CURSOR ENDP POST: ;-------------------------------------------------------- ; INITIALIZE AND START CRT CONTROLLER (6845) : ; ON COLOR GRAPHICS AND MONOCHROME CARDS : ; TEST VIDEO READ/WRITE STORAGE. : ; DESCRIPTION : ; RESET THE VIDEO ENABLE SIGNAL. : ; SELECT ALPHANUMERIC MODE, 40 * 25, B & W. : ; READ/WRITE DATA PATTERNS TO STG. CHECK STG : ; ADDRESSABILITY. : ;-------------------------------------------------------- ASSUME DS:ABS0,ES:ABS0 CALL DDS TEST INFO,2 JNZ COLOR_PRESENCE_TST MOV AX,03B4H CALL CD_PRESENCE_TST CMP AX,1 JE CONT1 JMP POD14 CONT1: MOV AH,30H ; MONOCHROME CARD INSTALLED JMP SHORT OVER COLOR_PRESENCE_TST: MOV AX,03D4H CALL CD_PRESENCE_TST CMP AX,1 JE CONT2 JMP POD14 CONT2: MOV AH,20H ; COLOR GRAPHICS CARD INSTALLED OVER: PUSH AX ; RESAVE VALUE MOV BX,0B000H ; BEG VIDEO RAM ADDR B/W CD MOV DX,3B8H ; MODE CONTROL B/W MOV CX,4096 ; RAM BYTE CNT FOR B/W CD MOV AL,1 ; SET MODE FOR BW CARD CMP AH,30H ; B/W VIDEO CARD ATTACHED? JE E9 ; GO TEST VIDEO STG MOV BH,0B8H ; BEG VIDEO RAM ADDR COLOR CD MOV DL,0D8H ; MODE CONTROL COLOR MOV CH,40H ; RAM BYTE CNT FOR COLOR CD DEC AL ; SET MODE TO 0 FOR COLOR CD E9: ; TEST_VIDEO_STG: OUT DX,AL ; DISABLE VIDEO FOR COLOR CD MOV BP,DS:RESET_FLAG ; POD INITIALIZED BY KBD RESET CMP BP,1234H ; POD INITIATED BY KBD RESET? MOV ES,BX ; POINT ES TO VIDEO RAM STG JE E10 ; YES - SKIP VIDEO RAM TEST MOV DS,BX ; POINT DS TO VIDEO RAM STG ASSUME DS:NOTHING,ES:NOTHING CALL STGTST_CNT ; GO TEST VIDEO R/W STG JNE E17 ; R/W STG FAILURE - BEEP SPK ;---------------------------------------------------------------- ; SETUP VIDEO DATA ON SCREEN FOR VIDEO LINE TEST. : ; DESCRIPTION : ; ENABLE VIDEO SIGNAL AND SET MODE. : ; DISPLAY A HORIZONTAL BAR ON SCREEN. : ;---------------------------------------------------------------- E10: POP AX ; GET VIDEO SENSE SWS (AH) PUSH AX ; SAVE IT MOV AX,7020H ; WRT BLANKS IN REVERSE VIDEO SUB DI,DI ; SETUP STARTING LOC MOV CX,40 ; NO. OF BLANKS TO DISPLAY REP STOSW ; WRITE VIDEO STORAGE ;-------------------------------------------------------- ; CRT INTERFACE LINES TEST : ; DESCRIPTION : ; SENSE ON/OFF TRANSITION OF THE VIDEO ENABLE : ; AND HORIZONTAL SYNC LINES. : ;-------------------------------------------------------- POP AX ; GET VIDEO SENSE SW INFO PUSH AX ; SAVE IT CMP AH,30H ; B/W CARD ATTACHED? MOV DX,03BAH ; SETUP ADDR OF B/W STATUS PORT JE E11 ; YES - GO TEST LINES MOV DL,0DAH ; COLOR CARD IS ATTACHED E11: ; LINE_TST: MOV AH,8 E12: ; OFLOOP_CNT SUB CX,CX E13: IN AL,DX ; READ CRT STATUS PORT AND AL,AH ; CHECK VIDEO/HORZ LINE JNZ E14 ; ITS ON - CHECK IF IT GOES OFF LOOP E13 ; LOOP TILL ON OR TIMEOUT JMP SHORT E17 ; GO PRINT ERROR MSG E14: SUB CX,CX E15: IN AL,DX ; READ CRT STATUS PORT AND AL,AH ; CHECK VIDEO/HORZ LINE JZ E16 ; ITS ON - CHECK NEXT LINE LOOP E15 ; LOOP IF OFF TILL IT GOES ON E17: ; CRT_ERR MOV DX,102H CALL ERR_BEEP ; GO BEEP SPEAKER JMP SHORT E18 E16: ; NXT_LINE MOV CL,3 ; GET NEXT BIT TO CHECK SHR AH,CL JNZ E12 ; GO CHECK HORIZONTAL LINE E18: ; DISPLAY_CURSOR: POP AX ; GET VIDEO SENSE SWS (AH) JMP SHORT POD14 ;------------------------------------------------------------------------ ; THIS SUBROUTINE PERFORMS A READ/WRITE STORAGE TEST ON : ; A 16K BLOCK OF STORAGE. : ; ENTRY REQUIREMENTS: : ; ES = ADDRESS OF STORAGE SEGMENT BEING TESTED : ; DS = ADDRESS OF STORAGE SEGMENT BEING TESTED : ; WHEN ENTERING AT STGTST_CNT, CX MUST BE LOADED WITH : ; THE BYTE COUNT. : ; EXIT PARAMETERS: : ; ZERO FLAG = 0 IF STORAGE ERROR (DATA COMPARE OR PARITY CHECK. : ; AL = 0 DENOTES A PARITY CHECK. ELSE AL=XOR'ED BIT : ; PATTERN OF THE EXPECTED DATA PATTERN VS THE : ; ACTUAL DATA READ. : ; AX,BX,CX,DX,DI, AND SI ARE ALL DESTROYED. : ;------------------------------------------------------------------------ STGTST PROC NEAR MOV CX,4000H ; SETUP CNT TO TEST A 16K BLK STGTST_CNT: CLD ; SET DIR FLAG TO INCREMENT MOV BX,CX ; SAVE CNT (4K FOR VIDEO OR 16K) MOV AX,0AAAAH ; GET DATA PATTERN TO WRITE MOV DX,0FF55H ; SETUP OTHER DATA PATTERNS TO USE SUB DI,DI ; DI = OFFSET 0 RELATIVE TO ES REG REP STOSB ; WRITE STORAGE LOCATIONS C3: ; STG01 DEC DI ; POINT TO LAST BYTE JUST WRITTEN STD ; SET DIR FLAG TO GO BACKWARDS C4: MOV SI,DI MOV CX,BX ; SETUP BYTE CNT C5: ; INNER TEST LOOP LODSB ; LOAD OLD TEST BYTE [SI]+ XOR AL,AH ; DATA READ AS EXPECTED ? JNE C7 ; NO - GO TO ERROR ROUTINE MOV AL,DL ; GET NEXT DATA PATTERN TO WRITE STOSB ; WRITE INTO LOCATION JUST READ LOOP C5 ; DECREMENT COUNT AND LOOP CX AND AH,AH ; ENDING 0 PATTERN WRITTEN TO STG? JZ C6X ; YES - RETURN TO CALLER WITH AL=0 MOV AH,AL ; SETUP NEW VALUE FOR COMPARE XCHG DH,DL ; MOVE NEXT DATA PATTERN TO DL AND AH,AH ; READING ZERO PATTERN THIS PASS ? JNZ C6 ; CONTINUE TEST SEQUENCE TILL 0 MOV DL,AH ; ELSE SET 0 FOR END READ PATTERN JMP C3 ; AND MAKE FINAL BACKWARDS PASS C6: CLD ; SET DIR FLAG TO GO FORWARD INC DI ; SET POINTER TO BEG LOCATION JZ C4 ; READ/WRITE FORWARD IN STG DEC DI ; ADJUST POINTER JMP C3 ; READ/WRITE BACKWARD IN STG C6X: MOV AL,000H ; AL=0 DATA COMPARE OK C7: CLD ; SET DIRECTION FLAG BACK TO INC RET STGTST ENDP ;-------------------------------------------------------- ; EGA CRT ATTACHMENT TEST : ; : ; 1. INIT CRT TO 40X25 - BW ****SET TO MODE**** : ; 2. CHECK FOR VERTICAL AND VIDEO ENABLES, AND CHECK : ; TIMING OF SAME : ; 3. CHECK VERTICAL INTERRUPT : ; 4. CHECK RED, BLUE, GREEN, AND INTENSIFY DOTS : ; 5. INIT TO 40X25 - COLOR/MONO ****SET TO MODE**** : ;-------------------------------------------------------- ;----- NOMINAL TIME IS B286H FOR 60 HZ. ;----- NOMINAL TIME IS A2FEH FOR 50 HZ. MAX_VERT_COLOR EQU 0A0ACH ; MAX TIME FOR VERT/VERT ; (NOMINAL + 10%) MIN_VERT_COLOR EQU 0C460H ; MIN TIME FOR VERT/VERT ; (NOMINAL - 10%) CENAB_PER_FRAME EQU 200 ; NUM OF ENABLES PER FRAME MAX_VERT_MONO EQU 08D99H ; MAX TIME FOR VERT/VERT ; (NOMINAL + 10%) MIN_VERT_MONO EQU 0B862H ; MIN TIME FOR VERT /VERT ; (NOMINAL - 10%) EENAB_PER_FRAME EQU 350 ; ENHANCED ENABLES PER FRAME MENAB_PER_FRAME EQU 350 ; NUM OF ENABLES PER FRAME TIM_CTL EQU 043H ; 8253 TIMER CONTROL PORT TIMER0 EQU 040H ; 8253 TIMER/CNTER 0 PORT POD14 PROC NEAR SUB SP,0AH ; RESERVE 5 WORDS ON STACK MOV BP,SP ; INIT SCRATCH PAD POINTER ASSUME DS:ABS0,ES:ABS0 CALL DDS MOV AL,00110000B ; SET TIMER 0 TO MODE 0 OUT TIM_CTL,AL MOV AL,00H OUT TIMER0,AL ; SEND FIRST BYTE TO TIMER TEST INFO,2 JZ COLOR_EGA_V CALL ENV_3 ; SET UP IN MONOCHROME MOV WORD PTR[BP][2],MENAB_PER_FRAME ; NUM. OF FRAMES FOR MONO MOV WORD PTR[BP][4],MAX_VERT_MONO ; MAX TIME FOR VERT/VERT MOV WORD PTR[BP][6],MIN_VERT_MONO ; MIN TIME FOR VERT/VERT MOV DL,CRTC_ADDR_B ; MONO CRTC REG MOV AH,C_HRZ_DSP ; HORIZ. TOTAL DIPLAY MOV AL,27H ; TO 40 COL CALL OUT_DX MOV DL,INPUT_STATUS_B ; 3BA JMP SHORT COMMON COLOR_EGA_V: CALL ENV_X ; SET UP IN 40X25 COLOR CALL BRST_DET ; ENHANCED MODE JNC COLOR_V ; NO,40X25 MOV DL,CRTC_ADDR ; BRST MODE ONLY! MOV AH,1 ; HRZ DSP END MOV AL,20 ; MODIFY FOR TEST ONLY CALL OUT_DX MOV WORD PTR[BP][2],EENAB_PER_FRAME ; NUM. OF FRAMES FOR COLOR JMP BRST_COLOR_V COLOR_V: MOV WORD PTR[BP][2],CENAB_PER_FRAME ; NUM. OF FRAMES FOR COLOR BRST_COLOR_V: MOV WORD PTR[BP][4],MAX_VERT_COLOR ; MAX TIME FOR VERT/VERT MOV WORD PTR[BP][6],MIN_VERT_COLOR ; MIN TIME FOR VERT /VERT MOV DL,INPUT_STATUS ; SET ADDRESSING TO VIDEO ; ATTR STATUS COMMON: MOV AX,0500H ; SET TO VIDEO PAGE 0 INT 10H SUB CX,CX ;----- LOOK FOR VERTICAL POD14_1: IN AL,DX ; GET STATUS TEST AL,00001000B ; VERTICAL THERE YET? JNE POD14_2 ; CONTINUE IF IT IS LOOP POD14_1 ; KEEP LOOKING TILL COUNT MOV BL,00 ; EXHAUSTED JMP POD14_ERR ; NO VERTICAL ;----- GOT VERTICAL - START TIMER POD14_2: MOV AL,0 OUT TIMER0,AL ; SEND 2ND BYTE TO TIMER TO ; START IT SUB BX,BX ; INIT. ENABLE COUNTER ;----- WAIT FOR VERTICAL TO GO AWAY XOR CX,CX POD14_25: IN AL,DX ; GET STATUS TEST AL,00001000B ; VERTICAL STILL THERE JZ POD14_3 ; CONTINUE IF IT'S GONE LOOP POD14_25 ; KEEP LOOKING TILL COUNT MOV BL,01H ; EXHAUSTED JMP POD14_ERR ; VERTICAL STUCK ON ;----- NOW START LOOKING FOR ENABLE TRANSITIONS POD14_3: SUB CX,CX POD14_4: IN AL,DX ; GET STATUS TEST AL,00000001B ; ENABLE ON YET? JE POD14_5 ; GO ON IF IT IS TEST AL,00001000B ; VERTICAL ON AGAIN? JNE POD14_75 ; CONTINUE IF IT IS LOOP POD14_4 ; KEEP LOOKING IF NOT MOV BL,02H JMP POD14_ERR ; ENABLE STUCK OFF POD14_4A: MOV BL,03H JMP POD14_ERR ; VERTICAL STUCK ON POD14_4B: MOV BL,04H JMP POD14_ERR ; ENABLE STUCK ON ;----- MAKE SURE VERTICAL WENT OFF WITH ENABLE GOING ON POD14_5: TEST AL,00001000B ; VERTICAL OFF? JNZ POD14_4A ; GO ON IF IT IS ;----- NOW WAIT FOR ENABLE TO GO OFF ; (ERROR IF NOT) POD14_6: IN AL,DX ; GET STATUS TEST AL,00000001B ; ENABLE OFF YET? LOOPE POD14_6 ; KEEP LOOKING IF NOT JCXZ POD14_4B ; YET LOW ;----- ENABLE HAS TOGGLED, BUMP COUNTER AND TEST FOR NEXT VERTICAL POD14_7: INC BX ; BUMP ENABLE COUNTER JZ POD14_75 ; IF COUNTER WRAPS, ; SOMETHING IS WRONG TEST AL,00001000B ; DID ENABLE GO LOW ; BECAUSE OF VERTICAL JZ POD14_3 ; IF NOT, LOOK FOR ANOTHER ; ENABLE TOGGLE ;----- HAVE HAD COMPLETE VERTICAL-VERTICAL CYCLE, NOW TEST RESULTS POD14_75: MOV AL,00 ; LATCH TIMER0 OUT TIM_CTL,AL CMP BX,WORD PTR[BP][2] ; NUMBER OF ENABLES BETWEEN ; VERTICALS O.K.? JE POD14_8 MOV BL,05H JMP SHORT POD14_ERR POD14_8: IN AL,TIMER0 ; GET TIMER VALUE LOW MOV AH,AL ; SAVE IT NOP IN AL,TIMER0 ; GET TIMER HIGH XCHG AH,AL NOP NOP CMP AX,WORD PTR[BP][4] ; MAXIMUM VERTICAL TIMING JGE POD14_9 MOV BL,06H JMP SHORT POD14_ERR POD14_9: CMP AX,WORD PTR[BP][6] ; MINIMUM VERTICAL TIMING JLE POD14_10 MOV BL,07H JMP SHORT POD14_ERR ;----- SEE IF RED, GREEN, BLUE AND INTENSIFY DOTS WORK ;----- FIRST, SET A LINE OF REVERSE VIDEO, INTENSIFIED BLANKS INTO BUFFER POD14_10: MOV AX,09DBH ; WRITE CHARS, BLANKS MOV BX,000FH ; PAGE 0, REVERSE VIDEO, ; HIGH INTENSITY MOV CX,80 ; 80 CHARACTERS INT 10H IN AL,DX PUSH DX ; SAVE INPUT STATUS MOV DL,ATTR_WRITE ; ATTRIBUTE ADDRESSS MOV AH,0FH ; PALETTE REG 'F' MOV AL,03FH ; TEST VALUE CALL OUT_DX ; VIDEO STATUS MUX MOV AX,0FH ; START WITH BLUE DOTS POP DX POD14_13: PUSH AX ; SAVE PUSH DX ; SAVE INPUT STATUS MOV DL,ATTR_WRITE ; ATTRIBUTE ADDRESSS MOV AH,32H ; COLOR PLANE ENABLE CALL OUT_DX ; VIDEO STATUS MUX POP DX ; RECOVER INPUT STATUS POP AX SUB CX,CX ;----- SEE IF DOT COMES ON POD14_14: IN AL,DX ; GET STATUS TEST AL,00110000B ; DOT THERE? JNZ POD14_15 ; LOOK FOR DOT TO TURN OFF LOOP POD14_14 ; CONTINUE TEST FOR DOT ON MOV BL,10H OR BL,AH ; OR IN DOT BEING TESTED JMP POD14_ERR ; DOT NOT COMING ON ;----- SEE IF DOT GOES OFF POD14_15: SUB CX,CX POD14_16: IN AL,DX ; GET STATUS TEST AL,00110000B ; IS DOT STILL ON? JE POD14_17 ; GO ON IF DOT OFF LOOP POD14_16 ; ELSE, KEEP WAITING FOR ; DOT TO GO OFF MOV BL,20H OR BL,AH ; OR IN DOT BEING TESTED JMP SHORT POD14_ERR ;----- ADJUST TO POINT TO NEXT DOT POD14_17: INC AH CMP AH,030H ; ALL 3 DOTS DONE? JE POD14_18 ; GO END OR AH,0FH ; MAKE 0F,1F,2F MOV AL,AH JMP POD14_13 ; GO LOOK FOR ANOTHER DOT POD14_ERR: MOV CX,6 MOV DX,0103H ; ONE LONG AND THREE SHORT CALL ERR_BEEP ADD SP,0AH ; BALANCE STACK MOV AL,00110110B ; RE-INIT TIMER 0 OUT TIM_CTL,AL SUB AL,AL OUT TIMER0,AL NOP NOP OUT TIMER0,AL MOV BP,1 JMP SKIP ASSUME DS:ABS0 POD14_18: CALL DDS MOV AX,0500H ; SET TO VIDEO PAGE 0 INT 10H MOV AL,00110110B ; RE-INIT TIMER 0 OUT TIM_CTL,AL SUB AL,AL OUT TIMER0,AL NOP NOP OUT TIMER0,AL ADD SP,0AH ; REMOVE SCRATCH PAD MOV BP,0 ; MAKE BP NON ZERO POD14 ENDP ;----- TEST STORAGE MEM_TEST: PUSH DS CALL DDS ASSUME DS:ABS0 TEST INFO,2 JZ D_COLOR_M OR EQUIP_LOW,030H MOV AX,0FH OR INFO,060H MOV AX,0FH JMP SHORT D_OUT_M D_COLOR_M: AND EQUIP_LOW,0CFH OR EQUIP_LOW,020H MOV AX,0EH ; INTERNAL COLOR MODE D_OUT_M: ; TEST IN COLOR INT 10H SUB SP,6 ; RESERVE 3 WORDS ON STACK MOV BP,SP ; SET BP MOV AX,0A000H ; PUT BUFFER ADDRESS IN AX ASSUME DS:NOTHING,ES:NOTHING MOV DS,AX ; SET UP SEG REGS TO POINT MOV ES,AX ; TO BUFFER AREA MOV WORD PTR[BP][2],0 ; INITIALIZE MOV WORD PTR[BP][4],0 ; INITIALIZE MOV DH,3 MOV DL,SEQ_ADDR MOV AX,0201H CALL OUT_DX MOV DL,GRAPH_ADDR ; ADDRESS READ MAP SELECT MOV AX,0400H CALL OUT_DX PUSH DX MOV DL,ATTR_READ ; SET UP ATTRIBUTE IN AL,DX MOV DL,ATTR_WRITE ; ATTRIBUTE WRITE ADDRESS MOV AX,3200H CALL OUT_DX CALL HOW_BIG ; GO FIND AMOUNT OF MEMORY CMP AH,0 JZ AA1 JMP EGA_MEM_ERROR AA1: CALL MEMORY_OK ; GO TEST IT CMP AH,0 JZ AA2 JMP EGA_MEM_ERROR AA2: POP DX MOV DL,SEQ_ADDR MOV AX,0202H CALL OUT_DX MOV DL,GRAPH_ADDR ; ADDRESS OF READ MAP MOV AX,0401H CALL OUT_DX PUSH DX MOV DL,ATTR_READ ; SET UP ATTRIBUTE IN AL,DX MOV DL,ATTR_WRITE ; ATTRIBUTE WRITE ADDRESS MOV AX,3200H CALL OUT_DX MOV WORD PTR [BP][4],0 ; INITIALIZE CALL HOW_BIG ; GO FIND AMOUNT OF MEMORY CMP AH,0 JZ AA3 JMP EGA_MEM_ERROR AA3: CALL MEMORY_OK ; GO TEST IT CMP AH,0 JZ AA4 JMP EGA_MEM_ERROR AA4: POP DX MOV DL,SEQ_ADDR MOV AX,0204H CALL OUT_DX PUSH DX MOV DL,GRAPH_ADDR ; ADDRESS OF READ MAP MOV AX,0402H CALL OUT_DX MOV DL,ATTR_READ ; SET UP ATTRIBUTE IN AL,DX MOV DL,ATTR_WRITE ; ATTRIBUTE WRITE ADDRESS MOV AX,3200H CALL OUT_DX MOV WORD PTR[BP][4],0 ; INITIALIZE CALL HOW_BIG ; GO FIND AMOUNT OF MEMORY CMP AH,0 JZ AA5 JMP EGA_MEM_ERROR AA5: CALL MEMORY_OK ; GO TEST IT CMP AH,0 JZ AA6 JMP EGA_MEM_ERROR AA6: POP DX MOV DL,SEQ_ADDR MOV AX,0208H CALL OUT_DX MOV DL,GRAPH_ADDR ; ADDRESS OF READ MAP MOV AX,0403H CALL OUT_DX PUSH DX MOV DL,ATTR_READ ; SET UP ATTRIBUTE IN AL,DX MOV DL,ATTR_WRITE ; ATTRIBUTE WRITE ADDRESS MOV AX,3200H CALL OUT_DX MOV WORD PTR[BP][4],0 ; INITIALIZE CALL HOW_BIG ; GO FIND AMOUNT OF MEMORY CMP AH,0 JNZ EGA_MEM_ERROR CALL MEMORY_OK ; GO TEST IT CMP AH,0 JNZ EGA_MEM_ERROR PUSH BP ; SAVE SCRATCH PAD POINTER MOV BP,0 ; RESET BP FOR XT EGA_MEM_EXIT: POP SI ; RESTORE POP DX CALL DDS ; SET DATA SEGMENT ASSUME DS:ABS0 MOV BX,WORD PTR SS:[SI][2] ; GET EGA MEMORY SIZE MOV CL,06H ; DIVIDE BY 64 TO GET SHR BX,CL ; NUMBER OF 64KB BLOCKS DEC BX MOV CL,05H SHL BX,CL AND BL,01100000B ; ISOLATE BITS 5 AND 6 AND INFO,10011111B OR INFO,BL OR INFO,00000100B ; 04H SET 3XX ACTIVE MOV BL,INFO_3 CALL MK_ENV ADD SP,6 ; RESTORE STACK POP DS JMP SKIP ; GO TO END EGA_MEM_ERROR: MOV DX,0103H ; ONE LONG AND THREE SHORT CALL ERR_BEEP PUSH BP ; SAVE SCRATCH PAD POINTER MOV BP,1 ; INDICATE ERROR FOR XT JMP EGA_MEM_EXIT ;----- THIS ROUTINE FINDS AMOUNT OF MEMORY GOOD MEMORY_OK PROC NEAR MOV BX,0A000H ; SET PTR. TO BUFFER SEG MOV DS,BX ; SET SEG. REG. MOV ES,BX MOV AX,WORD PTR[BP][4] ; SET COUNT FOR 32K WORDS MOV CH,AL ; SET AMOUNT OF BUFFER SUB CL,CL ; TO BE TESTED SHL CX,1 ; MULTIPLY BY TWO CALL PODSTG CMP AH,0 ; TEST FOR ERROR JNZ MEMORY_OK_ERR ; IF ERROR GO PRINT IT MEMORY_OK_EX: MOV AX,WORD PTR[BP][4] ; AMOUNT OF MEMORY FOUND ADD WORD PTR[BP][2],AX ; AMOUNT OF MEMORY GOOD MOV AX,0 MEMORY_OK_ERR: RET MEMORY_OK ENDP ;---------------------------------------------------------------- ; THIS ROUTINE PERFORMS A READ/WRITE TEST ON A BLOCK OF STORAGE : ; (MAX SIZE = 32KW). IF "WARM START", FILL BLOCK WITH 0000 AND : ; RETURN. : ; ON ENTRY: : ; ES = ADDRESS OF STORAGE TO BE TESTED : ; DS = ADDRESS OF STORAGE TO BE TESTED : ; CX = WORD COUNT OF STORAGE BLOCK TO BE TESTED : ; (MAX. = 8000H (32K WORDS)) : ; ON EXIT: : ; ZERO FLAG = OFF IF STORAGE ERROR : ; AX,BX,CX,DX,DI,SI ARE ALL DESTROYED. : ;---------------------------------------------------------------- PODSTG PROC NEAR PUSH BP CLD ; SET DIR TO INCREMENT SUB DI,DI ; SET DI=0000 REL TO START ; OF SEGMENT SUB AX,AX ; INITIAL DATA PATTERN FOR ; 00-FF TEST CALL DDS ASSUME DS:ABS0 MOV BX,DS:RESET_FLAG ; WARM START? CMP BX,1234H MOV DX,ES MOV DS,DX ; RESTORE DS JE PODSTG_5 ; GO DO FILL WITH 0000 ; IF WARM START CMP BX,4321H ; DCP WARM START? JE PODSTG_5 ; DO FILL IF SO PODSTG_1: MOV [DI],AL ; WRITE TEST DATA MOV AL,[DI] ; GET IT BACK XOR AL,AH ; COMPARE TO EXPECTED JNZ PODSTG_ERRO ; ERROR EXIT IF MISCOMPARE INC AH ; FORM NEW DATA PATTERN MOV AL,AH JNZ PODSTG_1 ; LOOP TILL ALL 256 DATA ; PATTERNS DONE MOV BP,CX ; SAVE WORD COUNT MOV AX,0AA55H ; LOAD DATA PATTERN MOV BX,AX MOV DX,055AAH ; LOAD OTHER DATA PATTERN REP STOSW ; FILL WORDS FROM LOW TO ; HIGH WITH AAAA DEC DI ; POINT TO LAST WORD DEC DI ; WRITTEN STD ; SET DIR FLAG TO GO DOWN MOV SI,DI ; SET INDEX REGS. EQUAL MOV CX,BP ; RECOVER WORD COUNT PODSTG_2: ; GO FROM HIGH TO LOW LODSW ; GET WORD FROM MEMORY XOR AX,BX ; EQUAL WHAT S/B THERE? JNZ PODSTG_ERRO ; GO ERROR EX IT IF NOT MOV AX,DX ; GET 55 DATA PATTERN AND STOSW ; STORE IN LOC JUST READ LOOP PODSTG_2 ; LOOP TILL ALL BYTES DONE MOV CX,BP ; RECOVER WORD COUNT CLD ; BACK TO INCREMENT INC SI ; ADJUST PTRS INC SI MOV DI,SI PODSTG_3: ; LOW TO HIGH DOING WORDS LODSW ; GET A WORD XOR AX,DX ; SHOULD COMPARE TO DX JNZ PODSTG_ERRO ; GO ERROR IF NOT STOSW ; WRITE 0000 BACK TO LOC ; JUST READ LOOP PODSTG_3 ; LOOP TILL DONE STD ; BACK TO DECREMENT DEC SI ; ADJUST POINTER DOWN TO ; LAST WORD WRITTEN DEC SI MOV CX,BP ; GET WORD COUNT PODSTG_4: LODSW ; GET WORD OR AX,AX ; = TO 0000 JNZ PODSTG_ERRO ; ERROR IF NOT LOOP PODSTG_4 ; LOOP TILL DONE JMP SHORT PODSTG_ERR2 PODSTG_ERRO: MOV CX,AX ; SAVE BITS IN ERROR XOR AH,AH OR CH,CH ; HIGH BYTE ERROR? JZ PODSTG_ERR1 MOV AH,1 ; SET HIGH BYTE ERROR PODSTG_ERR1: OR CL,CL ; LOW BYTE ERROR? JZ PODSTG_ERR2 ADD AH,2 PODSTG_ERR2: POP BP CLD ; SET DIR FLAG BACK TO INC RET ; RETURN TO CALLER PODSTG_5: ; SIMPLE FILL WITH 0000 ON ; WARM-START PUSH AX ; SAVE PUSH DX ; SAVE VALUE MOV DH,3 MOV DL,SEQ_ADDR ; SEQ_ADDR REGISTER MOV AX,020FH CALL OUT_DX ; DO IT POP DX ; RESTORE POP AX ; RESTORE REP STOSW CALL DDS ASSUME DS:ABS0 MOV DS:RESET_FLAG,BX MOV DS,DX ; RESTORE DS JMP PODSTG_ERR2 ; AND EXIT PODSTG ENDP ;----- DETERMINE SIZE OF BUFFER HOW_BIG PROC NEAR MOV DX,DS ; SET PNTR TO BUFFER LOC SUB BX,BX ; BASIC COUNT OF 00K FILL_LOOP: MOV ES,DX ; SET SEG. REG SUB DI ,DI MOV AX,0AA55H ; TEST PATTERN MOV CX,AX MOV ES:[DI],AX ; SEND TO MEMORY MOV AL,0FH ; PUT SOMETHING IN AL MOV AX,ES:[DI] ; GET PATTERN FROM MEMORY XOR AX,CX ; COMPARE PATTERNS JNZ HOW_BIG_END ; GO END IF NO COMPARE MOV CX,2000H ; SET COUNT FOR 8K WORDS REP STOSW ; FILL 8K WORDS ADD DX,0400H ; POINT TO NEXT 16K BLOCK ADD BX,16 ; BUMP COUNT BY 16KB CMP DH,0B0H JNZ FILL_LOOP ; AREA YET ?(B0000H) JMP HOW_BIG_END HOW_BIG_END: CMP DH,0A0H ; 1ST 16KB OK JZ HB_ERROR_EXIT RESUME: ADD WORD PTR[BP][4],BX ; SAVE BUFFER FOUND MOV AX,0 HB_ERROR_EXIT: RET HOW_BIG ENDP ;--------------------------------------- ;SUBROUTINES FOR POWER ON DIAGNOSTICS : ;----------------------------------------------------------------- ;THIS PROCEDURE WILL ISSUE ONE LONG TONE (3 SEC) AND ONE OR : ;MORE SHORT TONES (1 SEC) TO INDICATE A FAILURE ON THE PLANAR : ;BOARD ,A BAD RAM MODULE,OR A PROBLEM WITH THE CRT. : ;ENTRY REQUIREMENTS: : ; DH=NUMBER OF LONG TONES TO BEEP : ; DL=NUMBER OF SHORT TONES TO BEEP. : ;----------------------------------------------------------------- ERR_BEEP PROC NEAR PUSHF ; SAVE FLAGS CLI ; DISABLE SYSTEM INTS PUSH DS CALL DDS ASSUME DS:ABS0 OR DH,DH ; ANY LONG TONES TO BEEP JZ G3 ; NO, DO THE SHORT ONES G1: ; LONG BEEP MOV BL,6 ; COUNTER FOR BEEPS CALL BEEP ; DO THE BEEP G2: LOOP G2 ; DELAY BETWEEN BEEPS DEC DH ; ANY MORE TO DO JNZ G1 ; DO IT G3: MOV BL,1 ; COUNTER FOR A SHORT BEEP CALL BEEP ; DO IT G4: LOOP G4 ; DELAY BETWEEN BEEPS DEC DL ; DONE WITH SHORT BEEPS JNZ G3 ; DO MORE G5: LOOP G5 ; DELAY BEFORE RETURN G6: LOOP G6 POP DS ; RESTORE CONTENTS OF DS POPF ; RESTORE FLAGS RET ERR_BEEP ENDP SUBTTL T2 LABEL WORD DW OFFSET AH0 ; MODE SET DW OFFSET AH1 ; SET CURSOR TYPE DW OFFSET AH2 ; SET CURSOR POSITION DW OFFSET AH3 ; READ CURSOR POSITION DW OFFSET AH4 ; READ LIGHT PEN POSITION DW OFFSET AH5 ; ACTIVE DISPLAY PAGE DW OFFSET AH6 ; SCROLL DOWN DW OFFSET AH7 ; SCROLL UP DW OFFSET AH8 ; READ CHAR/ATTRIBUTE DW OFFSET AH9 ; WRITE CHAR/ATTRIBUTE DW OFFSET AHA ; WRITE CHARACTER ONLY DW OFFSET AHB ; SET COLOR PALETTE DW OFFSET AHC ; WRITE DOT DW OFFSET AHD ; READ DOT DW OFFSET AHE ; WRITE TTY DW OFFSET AHF ; CURRENT VIDEO STATE DW OFFSET AH10 ; SET PALETTE REGISTERS DW OFFSET AH11 ; CHAR GENERATOR ROUTINE DW OFFSET AH12 ; ALTERNATE SELECT DW OFFSET AH13 ; WRITE STRING T2L EQU $-T2 ;;; INCLUDE VPARMS.INC SUBTTL VPARMS.INC PAGE VIDEO_PARMS LABEL BYTE ; STRUCTURE OF THIS TABLE ; ; COLUMNS, ROWS, PELS PER CHARACTER ; PAGE LENGTH ; SEQUENCER PARAMETERS ; MISCELLANEOUS REGISTER ; CRTC PARAMETERS ; ATTRIBUTE PARAMETERS ; GRAPHICS PARAMETERS BASE_1 EQU $ - VIDEO_PARMS BASE_1_L LABEL BYTE ;----- DEFAULT MODES ;--0-- DB 40D,24D,08D DW 00800H TFS_LEN EQU $ - BASE_1_L SEQ_PARMS LABEL BYTE DB 00BH,003H,000H,003H M1 EQU $ - SEQ_PARMS DB 023H CRT_PARMS LABEL BYTE DB 037H,027H,02DH,037H,031H,015H DB 004H,011H,000H,007H,006H,007H DB 000H,000H,000H,000H,0E1H,024H DB 0C7H,014H,008H,0E0H,0F0H,0A3H DB 0FFH M4 EQU $-CRT_PARMS LN_4 EQU $ - BASE_1_L ATTR_PARMS LABEL BYTE DB 000H,001H,002H,003H,004H,005H DB 006H,007H,010H,011H,012H,013H DB 014H,015H,016H,017H,008H,000H DB 00FH,000H M5 EQU $-ATTR_PARMS LN_2 EQU $ - BASE_1_L GRAPH_PARMS LABEL BYTE DB 000H,000H,000H,000H,000H,010H DB 00EH,000H,0FFH M6 EQU $-GRAPH_PARMS M_TBL_LEN EQU $ - BASE_1_L ;--1-- DB 40D,24D,08D DW 00800H DB 00BH,003H,000H,003H DB 023H DB 037H,027H,02DH,037H,031H,015H DB 004H,011H,000H,007H,006H,007H DB 000H,000H,000H,000H,0E1H,024H DB 0C7H,014H,008H,0E0H,0F0H,0A3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 006H,007H,010H,011H,012H,013H DB 014H,015H,016H,017H,008H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,010H DB 00EH,000H,0FFH ;--2-- DB 80D,24D,08D DW 01000H DB 001H,003H,000H,003H DB 023H DB 070H,04FH,05CH,02FH,05FH,007H DB 004H,011H,000H,007H,006H,007H DB 000H,000H,000H,000H,0E1H,024H DB 0C7H,028H,008H,0E0H,0F0H,0A3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 006H,007H,010H,011H,012H,013H DB 014H,015H,016H,017H,008H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,010H DB 00EH,000H,0FFH ;--3-- DB 80D,24D,08D DW 01000H DB 001H,003H,000H,003H DB 023H DB 070H,04FH,05CH,02FH,05FH,007H DB 004H,011H,000H,007H,006H,007H DB 000H,000H,000H,000H,0E1H,024H DB 0C7H,028H,008H,0E0H,0F0H,0A3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 006H,007H,010H,011H,012H,013H DB 014H,015H,016H,017H,008H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,010H DB 00EH,000H,0FFH ;--4-- DB 40D,24D,08D DW 04000H DB 00BH,003H,000H,002H DB 023H DB 037H,027H,02DH,037H,030H,014H DB 004H,011H,000H,001H,000H,000H DB 000H,000H,000H,000H,0E1H,024H DB 0C7H,014H,000H,0E0H,0F0H,0A2H DB 0FFH DB 000H,013H,015H,017H,002H,004H DB 006H,007H,010H,011H,012H,013H DB 014H,015H,016H,017H,001H,000H DB 003H,000H DB 000H,000H,000H,000H,000H,030H DB 00FH,000H,0FFH ;--5-- DB 40D,24D,08D DW 04000H DB 00BH,003H,000H,002H DB 023H DB 037H,027H,02DH,037H,030H,014H DB 004H,011H,000H,001H,000H,000H DB 000H,000H,000H,000H,0E1H,024H DB 0C7H,014H,000H,0E0H,0F0H,0A2H DB 0FFH DB 000H,013H,015H,017H,002H,004H DB 006H,007H,010H,011H,012H,013H DB 014H,015H,016H,017H,001H,000H DB 003H,000H DB 000H,000H,000H,000H,000H,030H DB 00FH,000H,0FFH ;--6-- DB 80D,24D,08D DW 04000H DB 001H,001H,000H,006H DB 023H DB 070H,04FH,059H,02DH,05EH,006H DB 004H,011H,000H,001H,000H,000H DB 000H,000H,000H,000H,0E0H,023H DB 0C7H,028H,000H,0DFH,0EFH,0C2H DB 0FFH DB 000H,017H,017H,017H,017H,017H DB 017H,017H,017H,017H,017H,017H DB 017H,017H,017H,017H,001H,000H DB 001H,000H DB 000H,000H,000H,000H,000H,000H DB 00DH,000H,0FFH ;--7-- DB 80D,24D,14D DW 01000H DB 000H,003H,000H,003H DB 0A6H DB 060H,04FH,056H,03AH,051H,060H DB 070H,01FH,000H,00DH,00BH,00CH DB 000H,000H,000H,000H,05EH,02EH DB 05DH,028H,00DH,05EH,06EH,0A3H DB 0FFH DB 000H,008H,008H,008H,008H,008H DB 008H,008H,010H,018H,018H,018H DB 018H,018H,018H,018H,00EH,000H DB 00FH,008H DB 000H,000H,000H,000H,000H,010H DB 00AH,000H,0FFH ;--8-- DB 40D,24D,08D DW 04000H DB 000H,000H,000H,003H DB 023H DB 037H,027H,02DH,037H,031H,015H DB 004H,011H,000H,007H,006H,007H DB 000H,000H,000H,000H,0E1H,024H DB 0C7H,014H,008H,0E0H,0F0H,0A3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 006H,007H,010H,011H,012H,013H DB 014H,015H,016H,017H,008H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,010H DB 00EH,000H,0FFH ;--9-- DB 40D,24D,08D DW 04000H DB 000H,000H,000H,003H DB 023H DB 037H,027H,02DH,037H,031H,015H DB 004H,011H,000H,007H,006H,007H DB 000H,000H,000H,000H,0E1H,024H DB 0C7H,014H,008H,0E0H,0F0H,0A3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 006H,007H,010H,011H,012H,013H DB 014H,015H,016H,017H,008H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,010H DB 00EH,000H,0FFH ;--A-- DB 40D,24D,08D DW 04000H DB 000H,000H,000H,003H DB 023H DB 037H,027H,02DH,037H,031H,015H DB 004H,011H,000H,007H,006H,007H DB 000H,000H,000H,000H,0E1H,024H DB 0C7H,014H,008H,0E0H,0F0H,0A3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 006H,007H,010H,011H,012H,013H DB 014H,015H,016H,017H,008H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,010H DB 00EH,000H,0FFH ;--B-- DB 80D,24D,08D DW 01000H DB 001H,004H,000H,007H DB 023H DB 070H,04FH,05CH,02FH,05FH,007H DB 004H,011H,000H,007H,006H,007H DB 000H,000H,000H,000H,0E1H,024H DB 0C7H,028H,008H,0E0H,0F0H,0A3H DB 0FFH DB 000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,000H DB 004H,000H,0FFH ;--C-- DB 80D,24D,14D DW 01000H DB 000H,004H,000H,007H DB 0A6H DB 060H,04FH,056H,03AH,051H,060H DB 070H,01FH,000H,00DH,00BH,00CH DB 000H,000H,000H,000H,05EH,02EH DB 05DH,028H,00DH,05EH,06EH,0A3H DB 0FFH DB 000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,00EH,000H DB 00FH,008H DB 000H,000H,000H,000H,000H,000H DB 004H,000H,0FFH ;--D-- DB 40D,24D,08D DW 02000H DB 00BH,00FH,000H,006H DB 023H DB 037H,027H,02DH,037H,030H,014H DB 004H,011H,000H,000H,000H,000H DB 000H,000H,000H,000H,0E1H,024H DB 0C7H,014H,000H,0E0H,0F0H,0E3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 006H,007H,010H,011H,012H,013H DB 014H,015H,016H,017H,001H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,000H DB 005H,00FH,0FFH ;--E-- DB 80D,24D,08D DW 04000H DB 001H,00FH,000H,006H DB 023H DB 070H,04FH,059H,02DH,05EH,006H DB 004H,011H,000H,000H,000H,000H DB 000H,000H,000H,000H,0E0H,023H DB 0C7H,028H,000H,0DFH,0EFH,0E3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 006H,007H,010H,011H,012H,013H DB 014H,015H,016H,017H,001H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,000H DB 005H,00FH,0FFH ;--F-- DB 80D,24D,14D DW 08000H DB 005H,00FH,000H,000H DB 0A2H DB 060H,04FH,056H,01AH,050H,0E0H DB 070H,01FH,000H,000H,000H,000H DB 000H,000H,000H,000H,05EH,02EH DB 05DH,014H,00DH,05EH,06EH,08BH DB 0FFH DB 000H,008H,000H,000H,018H,018H DB 000H,000H,000H,008H,000H,000H DB 000H,018H,000H,000H,00BH,000H DB 005H,000H DB 000H,000H,000H,000H,000H,010H DB 007H,00FH,0FFH ;-10-- DB 80D,24D,14D DW 08000H DB 005H,00FH,000H,000H DB 0A7H DB 05BH,04FH,053H,017H,050H,0BAH DB 06CH,01FH,000H,000H,000H,000H DB 000H,000H,000H,000H,05EH,02BH DB 05DH,014H,00FH,05FH,00AH,08BH DB 0FFH DB 000H,001H,000H,000H,004H,007H DB 000H,000H,000H,001H,000H,000H DB 004H,007H,000H,000H,001H,000H DB 005H,000H DB 000H,000H,000H,000H,000H,010H DB 007H,00FH,0FFH BASE_2 EQU $ - VIDEO_PARMS ;----- > 16K MODE VALUES ;--F-- DB 80D,24D,14D DW 08000H DB 001H,00FH,000H,006H DB 0A2H DB 060H,04FH,056H,03AH,050H,060H DB 070H,01FH,000H,000H,000H,000H DB 000H,000H,000H,000H,05EH,02EH DB 05DH,028H,00DH,05EH,06EH,0E3H DB 0FFH DB 000H,008H,000H,000H,018H,018H DB 000H,000H,000H,008H,000H,000H DB 000H,018H,000H,000H,00BH,000H DB 005H,000H DB 000H,000H,000H,000H,000H,000H DB 005H,00FH,0FFH ;-10-- DB 80D,24D,14D DW 08000H DB 001H,00FH,000H,006H DB 0A7H DB 05BH,04FH,053H,037H,052H,000H DB 06CH,01FH,000H,000H,000H,000H DB 000H,000H,000H,000H,05EH,02BH DB 05DH,028H,00FH,05FH,00AH,0E3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 014H,007H,038H,039H,03AH,03BH DB 03CH,03DH,03EH,03FH,001H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,000H DB 005H,00FH,0FFH BASE_3 EQU $ - VIDEO_PARMS ;----- HI RES ALTERNATE VALUES ;--0-- DB 40D,24D,14D DW 00800H DB 00BH,003H,000H,003H DB 0A7H DB 02DH,027H,02BH,02DH,028H,06DH DB 06CH,01FH,000H,00DH,006H,007H DB 000H,000H,000H,000H,05EH,02BH DB 05DH,014H,00FH,05EH,00AH,0A3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 014H,007H,038H,039H,03AH,03BH DB 03CH,03DH,03EH,03FH,008H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,010H DB 00EH,000H,0FFH ;--1-- DB 40D,24D,14D DW 00800H DB 00BH,003H,000H,003H DB 0A7H DB 02DH,027H,02BH,02DH,028H,06DH DB 06CH,01FH,000H,00DH,006H,007H DB 000H,000H,000H,000H,05EH,02BH DB 05DH,014H,00FH,05EH,00AH,0A3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 014H,007H,038H,039H,03AH,03BH DB 03CH,03DH,03EH,03FH,008H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,010H DB 00EH,000H,0FFH ;--2-- DB 80D,24D,14D DW 01000H DB 001H,003H,000H,003H DB 0A7H DB 05BH,04FH,053H,037H,051H,05BH DB 06CH,01FH,000H,00DH,006H,007H DB 000H,000H,000H,000H,05EH,02BH DB 05DH,028H,00FH,05EH,00AH,0A3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 014H,007H,038H,039H,03AH,03BH DB 03CH,03DH,03EH,03FH,008H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,010H DB 00EH,000H,0FFH ;--3-- DB 80D,24D,14D DW 01000H DB 001H,003H,000H,003H DB 0A7H DB 05BH,04FH,053H,037H,051H,05BH DB 06CH,01FH,000H,00DH,006H,007H DB 000H,000H,000H,000H,05EH,02BH DB 05DH,028H,00FH,05EH,00AH,0A3H DB 0FFH DB 000H,001H,002H,003H,004H,005H DB 014H,007H,038H,039H,03AH,03BH DB 03CH,03DH,03EH,03FH,008H,000H DB 00FH,000H DB 000H,000H,000H,000H,000H,010H DB 00EH,000H,0FFH SUBTTL ;----- VECTOR INTO SPECIFIED FUNCTION COMBO_VIDEO PROC NEAR STI ; INTERRUPTS ON CLD ; SET DIRECTION FORWARD PUSH BP ; SAVE THE REGISTER SET PUSH ES PUSH DS PUSH DX PUSH CX PUSH BX PUSH SI PUSH DI PUSH AX ; SAVE AX VALUE MOV AL,AH ; GET INTO LOW BYTE XOR AH,AH ; ZERO TO HIGH BYTE SAL AX,1 ; * 2 FOR TABLE LOOKUP MOV SI,AX ; PUT INTO SI FOR BRANCH CMP AX,T2L ; TEST FOR WITHIN RANGE JB M2 ; BRANCH AROUND BRANCH POP AX ; RECOVER REGISTER INT 42H ; PASS UNRECOGNIZED CALL JMP V_RET ; RETURN TO CALLER M2: ASSUME DS:ABS0 CALL DDS POP AX ; RECOVER JMP WORD PTR CS:[SI + OFFSET T2] ; JMP TO AH=0 THRU AH=XX ;----- UTILITY ROUTINES ;----- SET DS TO THE DATA SEGMENT DDS PROC NEAR PUSH AX ; SAVE REGISTER SUB AX,AX MOV DS,AX POP AX ; RESTORE REGISTER RET DDS ENDP WHAT_BASE PROC NEAR ASSUME DS:ABS0 PUSH DS ; SAVE DATA SEGMENT CALL DDS ; GET LOW MEMORY SEGMENT MOV DX,ADDR_6845 ; GET CRTC ADDRESS AND DL,0F0H ; STRIP OFF LOW NIBBLE OR DL,0AH ; SET TO STATUS REGISTER POP DS RET WHAT_BASE ENDP OUT_DX PROC NEAR ; AH=INDEX,AL=DATA,DX=PORT XCHG AL,AH ; GET INDEX VALUE OUT DX,AL ; SET INDEX REG INC DX ; SET DX TO DATA REG XCHG AL,AH ; GET DATA VALUE OUT DX,AL ; SET DATA REG DEC DX ; SET DX BACK TO INDEX RET OUT_DX ENDP ;----- ROUTINE TO SOUND BEEPER BP_1 PROC NEAR OUT DX,AL RET BP_1 ENDP BEEP PROC NEAR PUSH DX MOV DX,TIMER+3 MOV AL,10110110B ; SEL TIM 2,LSB,MSB,BINARY CALL BP_1 ; WRITE THE TIMER MODE REG MOV AX,533H ; DIVISOR FOR 1000 HZ DEC DX CALL BP_1 ; WRITE TIMER 2 CNT - LSB MOV AL,AH CALL BP_1 ; WRITE TIMER 2 CNT - MSB MOV DX,PORT_B IN AL,DX ; GET SETTING OF PORT MOV AH,AL ; SAVE THAT SETTING OR AL,03 ; TURN SPEAKER ON CALL BP_1 SUB CX,CX ; SET CNT TO WAIT 500 MS G7: LOOP G7 ; DELAY BEFORE TURNING OFF DEC BL ; DELAY CNT EXPIRED? JNZ G7 ; NO-CONTINUE BEEPING SPK MOV AL,AH ; RECOVER VALUE OF PORT CALL BP_1 POP DX RET ; RETURN TO CALLER BEEP ENDP ;----- FIND THE PARAMETER TABLE VECTOR IN THE SAVE TABLE SET_BASE PROC NEAR ASSUME DS:ABS0 CALL DDS LES BX,SAVE_PTR ; GET PTR TP PTR TABLE LES BX,DWORD PTR ES:[BX] ; GET PARAMETER PTR RET SET_BASE ENDP ;----- ESTABLISH ADDRESSING TO THE CORRECT MODE TABLE ENTRY MAKE_BASE PROC NEAR ASSUME DS:ABS0 PUSH CX PUSH DX CALL SET_BASE ; GET PARM TBL PTR MOV AH,CRT_MODE TEST INFO,060H ; TEST FOR BASE CARD JZ B_M_1 ; MIN MEMORY ;----- WE HAVE A MEMORY EXPANSION OPTION HERE CMP AH,0FH JNE B_M_2 ADD BX,BASE_2 - BASE_1 JMP B_M_OUT B_M_2: CMP AH,010H JNE B_M_1 ADD BX,BASE_2 + M_TBL_LEN - BASE_1 JMP B_M_OUT B_M_1: CMP AH,03H JA B_M_3 ; SKIP ENHANCED PORTION ;----- CHECK THE SWITCH SETTING FOR ENHANCEMENT MOV AL,INFO_3 AND AL,0FH CMP AL,03H ; SECONDARY EMULATE SETTING JE BRS CMP AL,09H ; PRIMARY EMULATE SETTING JE BRS JMP B_M_3 ;----- WE WILL PERFORM ENHANCEMENT BRS: ADD BX,BASE_3 - BASE_1 ; VECTOR TO ENHANCEMENT TBL B_M_3: MOV CL,CRT_MODE SUB CH,CH JCXZ B_M_4 ;----- THIS LOOP WILL MOVE THE PTR TO THE INDIVIDUAL MODE ENTRY B_M_5: ADD BX,M_TBL_LEN ; LENGTH OF ONE MODE ENTRY LOOP B_M_5 B_M_4: B_M_OUT: POP DX POP CX RET MAKE_BASE ENDP ;----- PROGRAM THE EGA REGISTERS FROM THE PARAMETER TABLE SET_REGS PROC NEAR ASSUME DS:ABS0,ES:NOTHING ;----- PROGRAM THE SEQUENCER CALL MAKE_BASE ; GET TABLE PTR ADD BX,TFS_LEN ; MODE TO SEQUENCER PARMS MOV DH,3 MOV DL,SEQ_ADDR MOV AX,0001H ; RESET SEQUENCER CLI ; DISABLE INTERRUPTS CALL OUT_DX MOV AL,ES:[BX] ; GET SEQUENCER VALUE INC AH ; NEXT INDEX CALL OUT_DX ; SET IT D1: INC AH ; NEXT INDEX REGISTER INC BX ; NEXT TABLE ENTRY MOV AL,ES:[BX] CALL OUT_DX CMP AH,M1+1 JB D1 MOV AL,ES:[BX] INC BX MOV DL,MISC_OUTPUT OUT DX,AL MOV DL,SEQ_ADDR MOV AX,0003H CALL OUT_DX ; START SEQUENCER STI ; ENABLE INTERRUPTS ;----- PROGRAM THE CRT CONTROLLER MOV DX,ADDR_6845 ; CRTC INDEX REGISTER SUB AH,AH ; COUNTER X1: MOV AL,ES:[BX] ; GET VALUE FROM TABLE CALL OUT_DX ; SET CRTC REGISTER INC BX ; NEXT TABLE ENTRY INC AH ; NEXT INDEX VALUE CMP AH,M4 ; TEST REGISTER COUNT JB X1 ; DO THE REST MOV AX,ES:[BX][-0FH] ; GET CURSOR MODE XCHG AH,AL MOV CURSOR_MODE,AX ; SET LOW RAM VALUE ;----- PROGRAM THE ATTRIBUTE CHIP MOV SI ,BX CALL WHAT_BASE IN AL,DX MOV DL,ATTR_WRITE SUB AH,AH ; INDEX COUNTER D3: MOV AL,ES:[BX] ; GET DATA VALUE XCHG AH,AL OUT DX,AL XCHG AH,AL OUT DX,AL INC BX ; NEXT DATA VALUE INC AH ; NEXT INDEX VALUE CMP AH,M5 ; TEST REGISTER COUNT JB D3 ; DO THE REST MOV AL,0 OUT DX,AL ;----- CHECK IF PALETTE REGISTER VALUES ARE TO BE SAVED PUSH DS PUSH ES LES DI,SAVE_PTR ; GET TABLE PTR LES DI,DWORD PTR ES:[DI][4] ; GET PALETTE PTR MOV AX,ES OR AX,DI JZ SAVE_OUT ; IF ZERO, NO SAVE OCCURS ;----- STORE AWAY THE PALETTE VALUES IN RAM SAVE AREA POP DS PUSH DS MOV CX,16D REP MOVSB ; SAVE THE PALETTE REGS INC SI MOVSB ; SAVE THE OVERSCAN REG SAVE_OUT: POP ES POP DS ;----- PROGRAM THE GRAPHICS CHIPS MOV DL,GRAPH_1_POS MOV AL,0 OUT DX,AL MOV DL, GRAPH_2_POS MOV AL,1 OUT DX,AL MOV DL, GRAPH_ADDR SUB AH,AH D4: MOV AL,ES:[BX] ; PARAMETER BYTE CALL OUT_DX ; SET IT INC BX ; NEXT BYTE INC AH ; NEXT REGISTER CMP AH,M6 JB D4 ; CONTINUE RET SET_REGS ENDP ;----- MODE SET REGEN CLEAR ROUTINE BLANK PROC NEAR ; FILL REGEN WITH BLANKS ASSUME DS:ABS0,ES:NOTHING MOV AL,INFO ; SEE IF BLANK IS TO OCCUR TEST AL,080H ; MODE SET HIGH BIT JNZ OUT_1 ; SKIP BLANK FOR REGEN MOV DX,0B800H ; COLOR MODE REGEN ADDRESS MOV AL,CRT_MODE ; CURRENT MODE SET CMP AL,6 ; 0-6 ARE COLOR MODES JBE CGO MOV DX,0B000H ; MONOCHROME REGEN ADDRESS CMP AL,7 ; MONOCHROME MODE JE CGO MOV DX,0A000H ; REMAINING MODES CGO: MOV BX,0720H ; ALPHA BLANK VALUE CMP AL,4 ; ALPHAMODES 0-3 JB WW1 CMP AL,7 ; ALPHA MODE JE WW1 SUB BX,BX ; GRAPHICS BLANK VALUE WW1: SRLOAD ES ; SET THE REGEN SEGMENT ;;; MOV ES,DX MOV CX,CRT_LEN JCXZ OUT_1 MOV CX,08000H CMP DH,0A0H JE N_BA MOV CH,040H N_BA: MOV AX,BX ; BLANK VALUE SUB DI,DI ; CLEAR POINTER REP STOSW ; CLEAR THE PAGE OUT_1: RET ; RETURN TO CALLER BLANK ENDP PH_5 PROC NEAR CALL PAL_ON RET PH_5 ENDP ;----- SEE IF WE ARE TO SUPPORT 640 X 350 ON A 640 X 200 MODE BRST_DET PROC NEAR ASSUME DS:ABS0 PUSH AX PUSH DS CALL DDS MOV AL,INFO_3 POP DS AND AL,0FH CMP AL,03H ; EMULATE MODE JE B_YES CMP AL,09H ; EMULATE MODE JE B_YES POP AX CLC RET B_YES: POP AX STC RET BRST_DET ENDP ;----- MODE SET AH0: ASSUME DS:ABS0 CLI MOV WORD PTR GRX_SET, OFFSET CGDDOT MOV WORD PTR GRX_SET+2, CS STI AND INFO,11110011B ; TURN OFF RETRACE BIT ; EGA ACTIVE BIT PUSH AX ; SAVE TEST INFO,2 JZ ST_1 ; THERE IS NO MONOCHROME MOV AX,EQUIP_FLAG ; THERE IS A MONOCHROME AND AL,030H ; CHECK THE EQUIPMENT FLAG CMP AL,030H ; FOR MONOCHROME CALL JE ST_2 ; IT IS A MONOCHROME CALL ;----- FALL THROUGH => REGULAR COLOR CARD SETUP MOV ROWS,024D MOV POINTS,8 POP AX ; RECOVER OR INFO,00001000B ; EGA NOT ACTIVE CMP AL,1 JBE ST_7 ; WAIT FOR RETRACE ON CMP AL,4 ; MODES 2,3 ONLY JAE ST_7 OR INFO,00000100B ; DO RETRACE ST_7: INT 42H ; OTHER ADAPTER MODE CALL JMP V_RET ; BACK TO CALLER ;----- AT THIS POINT THERE IS NO MONOCHROME ATTACHED TO THE ADAPTER ST_1: MOV AX,EQUIP_FLAG ; TEST THE EQUIPMENT FLAG AND AL,030H ; TO SEE IF THIS IS A CMP AL,030H ; MONOCHROME SETUP CALL JNE ST_3 ; MUST BE COLOR TO CARD ;----- FALL THROUGH => REGULAR MONOCHROME CARD SETUP MOV ROWS,024D MOV POINTS,014D POP AX ; RECOVER INT 42H ; OTHER ADAPTER MODE CALL MOV CURSOR_MODE,0B0CH ; FIX PLANAR VALUE OR INFO,8 ; THE EGA IS NOT ACTIVE JMP V_RET ; BACK TO CALLER ;----- MONOCHROME SETUP TO THE ADAPTER ST_2: POP AX ; RECOVER PUSH AX ; SAVE MOV DH,3 AND AL,080H ; PICK OFF THE CLEAR BIT AND INFO,07FH ; MASK OFF THE OTHER BITS OR INFO,AL ; SAVE REGEN CLEAR BIT POP AX ; RECOVER TRUE CALL VALUE AND AL,07FH ; ALREADY DEALT WITH D7 CMP AL,0FH ; A MONOCHROME MODE JE ST_2A ; DO THIS MODE MOV AL,7 ; REGULAR MONOCHROME ST_2A: MOV CRT_MODE,AL ; SAVE MODE VALUE MOV DL,CRTC_ADDR_B ; IT IS 3-B-X MOV ADDR_6845,DX ; SAVE CRTC ADDRESS JMP QQ1 ; CONTINUE THE MODE SET ;----- COLOR SETUP TO THE ADAPTER ST_3: POP AX ; RECOVER PARAMETER VALUE PUSH AX ; SAVE IT MOV DH,3 AND AL,080H ; ISOLATE REGEN CLEAR BIT AND INFO,07FH ; PREPARE INFO BYTE OR INFO,AL ; SET IT, OR NOT POP AX ; RECOVER TRUE MODE CALL AND AL,07FH ; DONE WITH D7 MOV CRT_MODE,AL ; SAVE THIS MODE MOV DL,CRTC_ADDR ; 3-D-X MOV ADDR_6845,DX ; SAVE CRTC ADDRESS QQ1: MOV CRT_START,0 ; SAVE START ADDRESS MOV ACTIVE_PAGE,0 ; RESET PAGE VALUE TO ZERO ASSUME ES:NOTHING MOV CX,8 ; 8 PAGES OF CURSOR VALUES MOV DI,OFFSET CURSOR_POSN ; OFFSET PUSH DS ; ESTABLISH POP ES ; ADDRESSING SUB AX,AX ; 0 THOSE CURSOR LOCATIONS REP STOSW ; CLEAR OUT SAVED VALUES CALL MAKE_BASE MOV AL,ES:[BX] ; GET COLUMN COUNT SUB AH,AH ; ZERO HIGH BYTE MOV CRT_COLS,AX ; STORE COLUMN VALUE MOV AL,ES:[BX][1] ; GET ROW VALUE MOV ROWS,AL ; STORE ROW VALUE MOV AL,ES:[BX][2] ; GET THE BYTES/CHAR SUB AH,AH ; ZERO HIGH BYTE MOV POINTS,AX ; STORE BYTES/CHAR MOV AX,ES:[BX][3] ; GET PAGE SIZE MOV CRT_LEN,AX ; STORE PAGE LENGTH SUB BX,BX ; ZERO MOV AL,1 ; MONOCHROME ALPHA CHAR GEN MOV AH,CRT_MODE ; GET CURRENT MODE CMP AH,7 ; IS IT MONOCHROME JE ENTRY_2 ; 9X14 FONT CMP AH,03H JA ENTRY_1 CALL BRST_DET JC ENTRY_2 MOV AL,2 ; COLOR ALPHA CHAR GEN ENTRY_2: CALL CH_GEN ; LOAD ALPHA CHAR GEN CALL DDS MOV AH,CRT_MODE ; GET CURRENT MODE CMP AH,7 ; IS IT MONOCHROME JE FDG_IT ; 9X14 FONT JMP ENTRY_1 FDG_IT: MOV BP,OFFSET CGMN_FDG ; TABLE POINTER MOV BX,0E00H ; 14 BYTES PER CHAR FDG: PUSH CS ; GET THE ROM SEGMENT POP ES ; INTO ES MOV DX,ES:[BP] ; GET THE CHAR HEX CODE OR DX,DX ; ZERO = NO MORE CHARS JZ ENTRY_1 ; NO MORE MOV CX,1 ; DO ONE CHAR AT A TIME INC BP ; MOVE TO FIRST CODE POINT CALL DO_MAP2 ; STORE THE CODE POINT ADD BP,014D ; ADJUST BP TO NEXT CODE JMP FDG ; DO ANOTHER ENTRY_1: CALL SET_REGS CALL BLANK ; CLEAR OUT THE BUFFER CALL PH_5 ASSUME DS:ABS0 CALL DDS CMP CRT_MODE,0FH JB MS_1 MOV WORD PTR GRX_SET , OFFSET CGMN MS_1: CMP CRT_MODE,7 JA SAVE_GRPH JE SAVE_ALPH CMP CRT_MODE,3 JBE SAVE_ALPH SAVE_GRPH: LES BX,SAVE_PTR ADD BX,0CH LES BX,DWORD PTR ES:[BX] MOV AX,ES OR AX,BX JZ J4J ; JMP AH0_DONE MOV SI,07H SG_1: MOV AL,ES:[BX][SI] CMP AL,0FFH JE AH0_DONE CMP AL,CRT_MODE JE SG_2 INC SI JMP SG_1 SG_2: CLI MOV AL,BYTE PTR ES:[BX] DEC AL MOV ROWS,AL MOV AX,WORD PTR ES:[BX][1] MOV POINTS,AX MOV AX,WORD PTR ES:[BX][3] MOV WORD PTR GRX_SET,AX MOV AX,WORD PTR ES:[BX][5] MOV WORD PTR GRX_SET + 2,AX STI J4J: JMP SHORT AH0_DONE SAVE_ALPH: LES BX,SAVE_PTR ADD BX,08H LES BX,DWORD PTR ES:[BX] MOV AX,ES OR AX,BX JZ AH0_DONE MOV SI,0BH SA_1: MOV AL,ES:[BX][SI] CMP AL,0FFH JE AH0_DONE CMP AL,CRT_MODE JE SA_2 INC SI JMP SA_1 SA_2: MOV AH,ES:[BX] MOV AL,ES:[BX][1] MOV CX,ES:[BX][2] MOV DX,ES:[BX][4] MOV BP,ES:[BX][6] MOV ES,ES:[BX][8] PUSH BX MOV BX,AX MOV AX,1110H INT 10H POP BX MOV AL,ES:[BX][0AH] CMP AL,0FFH JE AH0_DONE DEC AL MOV ROWS,AL ;----- SET THE LOW RAM VALUES FOR COMPATIBILITY (3D8 AND 3D9 SAVE BYTES) AH0_DONE: CALL DDS CMP CRT_MODE,7 JA DNDCS MOV BX,OFFSET COMPAT_MODE MOV AL,CRT_MODE SUB AH,AH ADD BX,AX MOV AL,CS:[BX] MOV CRT_MODE_SET,AL MOV AL,030H CMP CRT_MODE,6 JNE DO_PAL MOV AL,03FH DO_PAL: MOV CRT_PALETTE,AL DNDCS: MOV CX,CURSOR_MODE JMP AH1 COMPAT_MODE LABEL BYTE DB 02CH,028H,02DH,029H,02AH,02EH DB 01EH,029H ;;; INCLUDE V1-5.INC SUBTTL V1-5.INC PAGE CALC_CURSOR PROC NEAR ASSUME DS:ABS0 CMP CH,0 ; CHECK FOR FULL HEIGHT JNE CC_1 ; NORMAL CHECK INC CL ; ADJUST END VALUE JMP SHORT CALC_OUT CC_1: INC CL ; ADJUST FOR EGA REGISTERS CMP CL,BYTE PTR POINTS ; WILL IT WRAP JB CALC_OUT ; NO, ITS OK SUB CL,CL ; EGA METHOD FOR CURSOR END CALC_OUT: PUSH CX ; SAVE CURSOR TYPE VALUE SUB CL,CH ; END - START CMP CL,010H ; LOW NIBBLE EQUAL POP CX ; RESTORE JNE COMP_4 INC CL ; ADD 1 FOR CORRECT CURSOR COMP_4: RET ; BACK TO CALLER CALC_CURSOR ENDP ;---------------------------------------------------------------- ; SET CTYPE SET CURSOR TYPE : ; THIS ROUTINE SETS THE CURSOR VALUE : ; INPUT : ; (CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE : ; OUTPUT : ; NONE : ;---------------------------------------------------------------- CUT_OFF EQU 4 AH1: ASSUME DS:ABS0 MOV AH,C_CRSR_START ; CRTC REG FOR CURSOR SET MOV CURSOR_MODE,CX ; SAVE IN DATA AREA TEST INFO,8 ; EGA ACTIVE BIT JNZ DO_SET ; 0=EGA, 1=OLD CARDS ;----- THIS SECTION WILL EMULATE CURSOR OFF ON THE EGA MOV AL,CH ; GET START VALUE AND AL,060H ; TURN OFF CURSOR ? CMP AL,020H ; TEST THE BITS JNE AH1_A ; SKIP CURSOR OFF MOV CX,01E00H ; EMULATE CURSOR OFF JMP SHORT DO_SET ;----- THIS SECTION : ADJUST THE CURSOR AND TEST FOR ENHANCED OPERATION AH1_A: TEST INFO,1 ; CURSOR EMULATE BIT JNZ DO_SET ; 0=EMULATE, 1==VALUE AS-IS CMP CRT_MODE,3 ; POSSIBLE EMULATION JA AH1_S ; NO, SET THE CURSOR TYPE CALL BRST_DET ; SEE IF EMULATE MODE JNC AH1_S ; NOT EMULATING CMP CH,CUT_OFF ; TEST START JBE AH1_B ; SKIP ADJUST ADD CH,5 ; ADJUST AH1_B: CMP CL,CUT_OFF ; TEST END JBE AH1_S ; SKIP ADJUST ADD CL,5 AH1_S: CALL CALC_CURSOR ; ADJUST END REGISTER DO_SET: CALL M16 ; OUTPUT CX REG JMP V_RET ; RETURN TO CALLER ;----- THIS ROUTINE OUTPUTS THE CX REGISTER TO THE CRTC REGS NAMED IN AH M16: MOV DX,ADDR_6845 ; ADDRESS REGISTER MOV AL,CH ; DATA CALL OUT_DX ; OUTPUT THE VALUE INC AH ; NEXT REGISTER MOV AL,CL ; SECOND DATA VALUE CALL OUT_DX ; OUTPUT THE VALUE RET ; ALL DONE ;---------------------------------------------------------------- ; POSITION : ; THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER : ; ADDRESS OF A CHARACTER IN THE ALPHA MODE : ; INPUT : ; AX = ROW, COLUMN POSITION : ; OUTPUT : ; AX = OFFSET OF CHAR POSITION IN REGEN BUFFER : ;---------------------------------------------------------------- POSITION PROC NEAR PUSH BX ; SAVE REGISTER MOV BX,AX MOV AL,AH ; ROWS TO AL MUL BYTE PTR CRT_COLS ; DETERMINE BYTES TO ROW XOR BH,BH ; ZERO OUT ADD AX,BX ; ADD IN COLUMN VALUE SAL AX,1 ; * 2 FOR ATTRIBUTE BYTES POP BX ; RESTORE REGISTER RET POSITION ENDP ;---------------------------------------------------------------- ; SET_CPOS SET CURSOR POSITION : ; THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE : ; NEW X-Y VALUES PASSED : ; INPUT : ; DX - ROW,COLUMN OF NEW CURSOR : ; BH - DISPLAY PAGE OF CURSOR : ; OUTPUT : ; CURSOR IS SET AT CRTC IF DISPLAY PAGE IS CURRENT : ; DISPLAY : ;---------------------------------------------------------------- AH2: CALL SET_CPOS JMP V_RET SET_CPOS: MOV CL,BH XOR CH,CH ; ESTABLISH LOOP COUNT SAL CX,1 ; WORD OFFSET MOV SI,CX ; USE INDEX REGISTER MOV [SI+OFFSET CURSOR_POSN],DX ; SAVE THE POINTER CMP ACTIVE_PAGE,BH JNZ M17 ; SET_CPOS_RETURN MOV AX,DX ; GET ROW/COLUMN TO AX CALL M18 ; CURSOR_SET M17: ; SET_CPOS_RETURN RET ;----- SET CURSOR POSITION, AX HAS ROW/COLUMN FOR CURSOR M18 PROC NEAR CALL POSITION ; DETERMINE LOC IN REGEN MOV CX,AX ADD CX,CRT_START ; ADD IN THE START ADDR ; FOR THIS PAGE SAR CX,1 ; / 2 FOR CHAR ONLY COUNT MOV AH,C_CRSR_LOC_HGH ; REGISTER NUMBER FOR CURSOR CALL M16 ; SET VALUE TO CRTC RET M18 ENDP ;---------------------------------------------------------------- ; READ_CURSOR : ; THIS ROUTINE READS THE CURRENT CURSOR VALUE FROM : ; MEMORY AND SENDS IT BACK TO THE CALLER : ; INPUT : ; BH - PAGE OF CURSOR : ; OUTPUT : ; DX - SET CURSOR POSITION, AX HAS ROW/COLUMN FOR CURSOR : ; CX - RCURRENT CURSOR POSITION : ;---------------------------------------------------------------- AH3: MOV BL,BH ; PAGE VALUE XOR BH,BH ; ZERO UPPER BYTE SAL BX,1 ; WORD OFFSET MOV DX,[BX + OFFSET CURSOR_POSN] ; GET CURSOR FOR THIS PAGE MOV CX,CURSOR_MODE ; GET THE CURSOR MODE POP DI POP SI POP BX POP AX ; DISCARD CX POP AX ; DISCARD DX POP DS POP ES POP BP IRET ;----- READ LIGHT PEN POSITION AH4: MOV AL,CRT_MODE CMP AL,07H JA READ_LPEN TEST INFO,2 JZ EGA_IS_COLOR ;----- MONOCHROME HERE ( MONOC BIT 1) CMP AL,07H JE READ_LPEN JMP OLD_LP ;----- EGA IS COLOR HERE (MONOC BIT 0) EGA_IS_COLOR: CMP AL,06H JBE READ_LPEN OLD_LP: INT 42H ; CALL EXISTING CODE POP DI POP SI ADD SP,6 ; DISCARD SAVED BX,CX,DX POP DS POP ES POP BP IRET ;---------------------------------------------------------------- ; LIGHT PEN : ; THIS ROUTINE TESTS THE LIGHT PEN SWITCH AND THE LIGHT : ; PEN TRIGGER. IF BOTH ARE SET, THE LOCATION OF THE LIGHT : ; PEN IS DETERMINED. OTHERWISE, A RETURN WITH NO : ; INFORMATION IS MADE. : ; ON EXIT : ; (AH) = 0 IF NO LIGHT PEN INFORMATION IS AVAILABLE : ; BX,CX,DX ARE DESTROYED : ; (AH) = 1 IF LIGHT PEN IS AVAILABLE : ; (DH,DL) = ROW,COLUMN OF CURRENT LIGHT PEN : ; POSITION : ; (CH) = RASTER POSITION (OLD MODES) : ; (CX) = RASTER POSITION (NEW MODES) : ; (BX) = BEST GUESS AT PIXEL HORIZONTAL POSITION : ;---------------------------------------------------------------- ASSUME CS:CODE,DS:ABS0 ;----- SUBTRACT_TABLE V1 LABEL BYTE DB 006H,006H,007H,007H,005H,005H ; 0-5 DB 004H,005H,000H,000H,000H,000H ; 6-B DB 000H,005H,006H,004H,004H,004H ; C-11 DB 004H,006H,006H,004H,007H,004H ; 12-17 DB 007H,004H ; 18-19 READ_LPEN PROC NEAR ;----- WAIT FOR LIGHT PEN TO BE DEPRESSED MOV DX,ADDR_6845 ; GET BASE ADDRESS OF 6845 ADD DX,6 ; POINT TO STATUS REGISTER IN AL,DX ; GET STATUS REGISTER TEST AL,4 ; TEST LIGHT PEN SWITCH MOV AH,0 ; SET NO LIGHT PEN RETURN JZ V9 ; CODE JMP V6 ; NOT SET, RETURN ;----- NOW TEST FOR LIGHT PEN TRIGGER V9: TEST AL,2 ; TEST LIGHT PEN TRIGGER JNZ V7A ; RETURN WITHOUT RESETTING ; TRIGGER JMP V7 ; EXIT LIGHT PEN ROUTINE ;----- TRIGGER HAS BEEN SET, READ THE VALUE IN V7A: MOV AH,16 ; LIGHT PEN REGISTERS ;----- INPUT REGS POINTED TO BY AH, AND CONVERT TO ROW COLUMN IN DX MOV DX,ADDR_6845 ; ADDRESS REGISTER MOV AL,AH ; REGISTER TO READ OUT DX,AL ; SET IT UP INC DX ; DATA REGISTER PUSH AX IN AL,DX ; GET THE VALUE MOV CH,AL ; SAVE IN CX POP AX DEC DX ; ADDRESS REGISTER INC AH MOV AL,AH ; SECOND DATA REGISTER OUT DX,AL INC DX ; POINT TO DATA REGISTER IN AL,DX ; GET THE 2ND DATA VALUE MOV AH,CH ; AX HAS INPUT VALUE ;----- AX HAS THE VALUE READ IN FROM THE 6845 MOV BL,CRT_MODE SUB BH,BH ; MODE VALUE TO BX MOV BL,CS:V1[BX] ; AMOUNT TO SUBTRACT SUB AX,BX ; TAKE IT AWAY MOV BX,CRT_START ; SCREEN ADDRESS SHR BX,1 ; DIVIDE BY 2 SUB AX,BX ; ADJUST TO ZERO START JNS V2 ; IF POSITIVE, GET MODE SUB AX,AX ; <0 PLAYS AS 0 ;----- DETERMINE MODE OF OPERATION V2: ; DETERMINE_MODE MOV CL,3 ; SET *8 SHIFT COUNT CMP CRT_MODE,4 ; GRAPHICS OR ALPHA JB V4 ; ALPHA_PEN CMP CRT_MODE,7 JE V4 ; ALPHA_PEN CMP CRT_MODE,06H JA V8 JNE V8X SHR AX,1 ;----- OLD GRAPHICS MODES V8X: MOV DL,40 ; DIVISOR FOR GRAPHICS DIV DL ; ROW(AL) AND COLUMN(AH) ; AL RANGE 0-99, ; AH RANGE 0-39 ;----- DETERMINE GRAPHIC ROW POSITION MOV CH,AL ; SAVE ROW VALUE IN CH ADD CH,CH ; *2 FOR EVEN/ODD FIELD MOV BL,AH ; COLUMN VALUE TO BX SUB BH,BH ; *8 FOR MEDIUM RES CMP CRT_MODE,6 ; MEDIUM OR HIGH RES JNE V3 ; NOT_HIGH_RES MOV CL,4 ; SHIFT VALUE FOR HIGH RES SAL AH,1 ; COLUMN VALUE *2 FOR HIGH RES V3: ; NOT_HIGH_RES SHL BX,CL ; *16 FOR HIGH RES ;----- DETERMINE ALPHA CHAR POSITION MOV DL,AH ; COLUMN VALUE FOR RETURN MOV DH,AL ; ROW VALUE SHR DH,1 ; DIVIDE BY 4 SHR DH,1 ; FOR VALUE IN 0-24 RANGE JMP V5 ; LIGHT_PEN_RETURN_SET V8: ;----- NEW GRAPHICS MODES CWD ; PREPARE TO DIVIDE DIV CRT_COLS ; AX = ROW, DX = COLUMN MOV BX,DX ; SAVIE REMAINDER SAL BX,CL ; PEL COLUMN MOV CX,AX ; PEL ROW PUSH DX ; SAVE FROM DIVIDE CWD ; PREPARE TO DIVIDE DIV POINTS ; DIVIDE BY BYTES/CHAR POP DX ; RECOVER MOV DH,AL ; CHARACTER ROW JMP V5 ;----- ALPHA MODE ON LIGHT PEN V4: ; ALPHA PEN DIV BYTE PTR CRT_COLS ; ROW,COLUMN VALUE MOV DH,AL ; ROWS TO DH MOV DL,AH ; COLS TO DL MOV BL,AH ; COLUMN VALUE XOR BH,BH ; TO BX SAL BX,CL MUL BYTE PTR POINTS MOV CX,AX V5: ; LIGHT_PEN_RETURN_SET MOV AH,1 ; INDICATE EVERTHING SET V6: ; LIGHT_PEN_RETURN PUSH DX ; SAVE RETURN VALUE ; (IN CASE) MOV DX,ADDR_6845 ; GET BASE ADDRESS ADD DX,7 ; POINT TO RESET PARM OUT DX,AL ; ADDRESS, NOT DATA, ; IS IMPORTANT POP DX ; RECOVER VALUE V7: ; RETURN_NO_RESET POP DI POP SI ADD SP,6 ; DISCARD SAVED BX,CX,DX POP DS POP ES POP BP IRET READ_LPEN ENDP ;---------------------------------------------------------------- ; ACT_DISP_PAGE SELECT ACTIVE DISPLAY PAGE : ; THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING : ; FOR MULTIPLE PAGES OF DISPLAYED VIDEO. : ; INPUT : ; AL HAS THE NEW ACTIVE DISPLAY PAGE : ; OUTPUT : ; THE CRTC IS RESET TO DISPLAY THAT PAGE : ;---------------------------------------------------------------- AH5: MOV ACTIVE_PAGE,AL ; SAVE ACTIVE PAGE VALUE MOV CX,CRT_LEN ; GET SAVED LENGTH OF ; REGEN BUFFER CBW ; CONVERT AL TO WORD PUSH AX ; SAVE PAGE VALUE MUL CX ; DISPLAY PAGE TIMES ; REGEN LENGTH MOV CRT_START,AX ; SAVE START ADDRESS FOR ; LATER REQUIREMENTS MOV CX,AX ; START ADDRESS TO CX MOV BL,CRT_MODE CMP BL,7 ; DO NOT DIVIDE BY TWO JA ADP_1 ADP_2: SAR CX,1 ; / 2 FOR CRTC HANDLING ADP_1: MOV AH,C_STRT_HGH ; REG FOR START ADDRESS CALL M16 POP BX ; RECOVER PAGE VALUE SAL BX,1 ; *2 FOR WORD OFFSET MOV AX,[BX + OFFSET CURSOR_POSN] ; GET CURSOR FOR THIS PAGE CALL M18 ; SET THE CURSOR POSITION JMP V_RET SUBTTL ;;; INCLUDE VSCROLL.INC SUBTTL VSCROLL.INC PAGE FLTA PROC NEAR ; CHECK FOR SCROLL COUNT PUSH AX MOV AH,DH ; LOWER ROW SUB AH,CH ; UPPER ROW INC AH ; NUMBER TO SCROLL CMP AH,AL ; SAME AS REQUESTED POP AX JNE LTA SUB AL,AL ; YES, SET TO 0 FOR BLANK LTA: RET FLTA ENDP CRANK PROC NEAR ; MOVE ROWS OF PELS UP PUSH BX ASSUME DS:ABS0 PUSH DS ; SAVE DATA SEGMENT CALL DDS ; SET DATA SEGMENT MOV BX,CRT_COLS POP DS CRANK_A: PUSH CX ; SAVE MOVE COUNT MOV CL,DL ; COLUMN COUNT SUB CH,CH ; CLEAR HIGH BYTE PUSH SI ; SAVE POINTERS PUSH DI REP MOVSB ; MOVE THAT ROW POP DI ; RECOVER POINTERS POP SI ADD SI,BX ; NEXT ROW ADD DI,BX ; NEXT ROW POP CX ; RECOVER ROW COUNT LOOP CRANK_A ; DO MORE POP BX RET ; RETURN TO CALLER CRANK ENDP CRANK_4 PROC NEAR ; MOVE ROWS OF PELS DOWN PUSH BX ASSUME DS:ABS0 PUSH DS ; SAVE DATA SEGMENT CALL DDS ; SET DATA SEGMENT MOV BX,CRT_COLS POP DS CRANK_8: PUSH CX ; SAVE MOVE COUNT MOV CL,DL ; COLUMN COUNT SUB CH,CH ; CLEAR HIGH BYTE PUSH SI ; SAVE POINTERS PUSH DI REP MOVSB ; MOVE THAT ROW POP DI ; RECOVER POINTERS POP SI SUB SI,BX ; NEXT ROW SUB DI,BX ; NEXT ROW POP CX ; RECOVER ROW COUNT LOOP CRANK_8 ; DO MORE POP BX RET ; RETURN TO CALLER CRANK_4 ENDP PART_1 PROC NEAR ; FILL ROW AFTER SCROLL PUSH DX MOV DH,3 MOV DL,SEQ_ADDR ; SEQUENCER MOV AX,020FH ; MAP MASK CALL OUT_DX ; ALL MAPS ON POP DX SUB AX,AX ; ZERO MOV CL,DL ; COLUMN COUNT SUB CH,CH PUSH DI ; SAVE POINTER REP STOSB ; CLEAR ONE ROW OF PELS POP DI ; RECOVER POINTER MOV AL,DH ; GET COLOR VALUE PUSH DX MOV DH,3 MOV DL,SEQ_ADDR ; SEQUENCER MOV AH,02H ; MAP MASK CALL OUT_DX ; SET THE COLOR POP DX MOV AL,0FFH ; ALL BITS ON MOV CL,DL ; COLUMN COUNT PUSH DI ; SAVE POINTER REP STOSB ; TURN ON THOSE BITS IN ; ENABLED PLANES POP DI ; RECOVER POINTER RET PART_1 ENDP PART_2 PROC NEAR MOV DH,3 MOV DL,SEQ_ADDR ; SEQUENCER MOV AX,020FH ; MAP MASK, ALL MAPS CALL OUT_DX ; ENABLE THE MAPS RET ; RETURN TO CALLER PART_2 ENDP BLNK_3 PROC NEAR ; BLANK FOR SCROLL UP PUSH DS ; SAVE DATA SEGMENT ASSUME DS:ABS0 CALL DDS ; GET LOW MEMORY SEGMENT MOV DH,BH ; ATTRIBUTE FOR BLANK LINE SUB BH,BH ; CLEAR HIGH BYTE PUSH AX ; SAVE PUSH DX ; SAVE BECAUSE OF MULTIPLY MOV AX,BX ; ROW COUNT MUL POINTS ; CHARACTER HEIGHT MOV BX,AX ; NET VALUE TO BX POP DX ; RECOVER POP AX POP DS ASSUME DS:NOTHING S13: CALL PART_1 ; BLANK OUT ROW WITH COLOR ASSUME DS:ABS0 PUSH DS ; SAVE SEGMENT CALL DDS ; LOW MEMORY SEGMENT ADD DI,CRT_COLS ; NEXT ROW POP DS ; RECOVER DEC BX ; NEXT JNZ S13 ; DO MORE CALL PART_2 RET ; RETURN TO CALLER BLNK_3 ENDP BLNK_4 PROC NEAR ; BLANK FOR SCROLL DOWN PUSH DS ; SAVE DATA SEGMENT ASSUME DS:ABS0 CALL DDS ; GET LOW MEMORY SEGMENT MOV DH,BH ; ATTRIBUTE FOR BLANK LINE SUB BH,BH ; CLEAR HIGH BYTE PUSH AX ; SAVE PUSH DX ; SAVE BECAUSE OF MULTIPLY MOV AX,BX ; ROW COUNT MUL POINTS ; CHARACTER HEIGHT MOV BX,AX ; NET VALUE TO BX POP DX ; RECOVER POP AX POP DS ASSUME DS:NOTHING S13_4: CALL PART_1 ; BLANK OUT ROW WITH COLOR ASSUME DS:ABS0 PUSH DS ; SAVE SEGMENT CALL DDS ; LOW MEMORY SEGMENT SUB DI,CRT_COLS ; NEXT ROW POP DS ; RECOVER DEC BX ; NEXT JNZ S13_4 ; DO MORE CALL PART_2 RET ; RETURN TO CALLER BLNK_4 ENDP ;-------------------------------------------------------- ; SCROLL UP : ; THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP : ; ON THE SCREEN : ; INPUT : ; (AH) = CURRENT CRT MODE : ; (AL) = NUMBER OF ROWS TO SCROLL : ; (CX) = ROW/COLUMN OF UPPER LEFT CORNER : ; (DX) = ROW/COLUMN OF LOWER RIGHT CORNER : ; (BH) = ATTRIBUTE TO BE USED ON BLANKED LINE : ; (DS) = DATA SEGMENT : ; (ES) = REGEN BUFFER SEGMENT : ; OUTPUT : ; NONE -- THE REGEN BUFFER IS MODIFIED : ;-------------------------------------------------------- ASSUME CS:CODE,DS:ABS0,ES:NOTHING SCROLL_UP PROC NEAR MOV BL,AL ; SAVE LINE COUNT IN BL CALL MK_ES CMP AH,4 ; TEST FOR GRAPHICS MODE JB N1 ; HANDLE SEPERATELY CMP AH,7 ; TEST FOR BW CARD JE N1 JMP GRAPHICS_UP N1: ; UP_CONTINUE PUSH BX ; SAVE FILL ATTR IN BH MOV AX,CX ; UPPER LEFT POSITION CALL SCROLL_POSITION ; DO SETUP FOR SCROLL JZ N7 ; BLANK_FIELD ADD SI,AX ; FROM ADDRESS MOV AH,DH ; # ROWS IN BLOCK SUB AH,BL ; # ROWS TO BE MOVED N2: ; ROW_LOOP CALL N10 ; MOVE ONE ROW ADD SI,BP ADD DI,BP ; NEXT LINE IN BLOCK DEC AH ; COUNT OF LINES TO MOVE JNZ N2 ; ROW_LOOP N3: ; CLEAR_ENTRY POP AX ; RECOVER ATTRIBUTE IN AH MOV AL,' ' ; FILL WITH BLANKS N4: ; CLEAR_LOOP CALL N11 ; CLEAR THE ROW ADD DI,BP ; POINT TO THE NEXT LINE DEC BL ; LINES TO SCROLL JNZ N4 ; SCROLL_END N5: CALL DDS CMP CRT_MODE,7 ; IS THIS THE B/W CARD JE N6 ; SKIP THE MODE RESET MOV AL,CRT_MODE_SET ; GET THE MODE SET MOV DX,03D8H ; ALWAYS SET COLOR CARD OUT DX,AL N6: ; VIDEO_RET_HERE JMP V_RET N7: ; BLANK_FIELD MOV BL,DH ; GET ROW COUNT JMP N3 ; GO CLEAR THAT AREA SCROLL_UP ENDP ;----- HANDLE COMMON SCROLL SET UP HERE SCROLL_POSITION PROC NEAR TEST INFO,4 JZ N9 ;----- 80X25 COLOR CARD SCROLL PUSH DX MOV DH,3 MOV DL,0DAH ; COLOR CARD HERE PUSH AX N8: ; WAIT_DISP_ENABLE IN AL,DX TEST AL,8 ; WAIT FOR VERT RETRACE JZ N8 ; WAIT_DISP_ENABLE MOV AL,25H MOV DL,0D8H ; DX=3D8 OUT DX,AL ; TURN OFF VIDEO POP AX ; DURING VERTICAL RETRACE POP DX N9: CALL POSITION ; CONVERT TO REGEN POINTER ADD AX,CRT_START ; OFFSET OF ACTIVE PAGE MOV DI ,AX ; TO ADDRESS FOR SCROLL MOV SI ,AX ; FROM ADDRESS FOR SCROLL SUB DX,CX ; DX = #ROWS, #COLS INC DH INC DL ; INCREMENT FOR 0 ORIGIN XOR CH,CH ; ZERO HIGH BYTE OF COUNT MOV BP,CRT_COLS ; NUM OF COLS IN DISPLAY ADD BP,BP ; TIMES 2 FOR ATTR BYTE MOV AL,BL ; GET LINE COUNT MUL BYTE PTR CRT_COLS ; OFFSET TO FROM ADDRESS ADD AX,AX ; *2 FOR ATTRIBUTE BYTE PUSH ES ; ESTABLISH ADDRESSING POP DS ; FOR BOTH POINTERS CMP BL,0 ; 0 MEANS BLANK FIELD RET ; RETURN WITH FLAGS SET SCROLL_POSITION ENDP ;----- MOVE_ROW N10 PROC NEAR MOV CL,DL ; GET # OF COLS TO MOVE PUSH SI PUSH DI ; SAVE START ADDRESS REP MOVSW ; MOVE THAT LINE ON SCREEN POP DI POP SI ; RECOVER ADDRESSES RET N10 ENDP ;----- CLEAR_ROW N11 PROC NEAR MOV CL,DL ; GET # COLUMNS TO CLEAR PUSH DI REP STOSW ; STORE THE FILL CHARACTER POP DI RET N11 ENDP ;-------------------------------------------------------- ; SCROLL_DOWN : ; THIS ROUTINE MOVES THE CHARACTERS WITHIN A : ; DEFINED BLOCK DOWN ON THE SCREEN, FILLING THE : ; TOP LINES WITH A DEFINED CHARACTER : ; INPUT : ; (AH) = CURRENT CRT MODE : ; (AL) = NUMBER OF LINES TO SCROLL : ; (CX) = UPPER LEFT CORNER OF REGION : ; (DX) = LOWER RIGHT CORNER OF REGION : ; (BH) FILL CHARACTER : ; (DS) DATA SEGMENT : ; (ES) REGEN SEGMENT : ; OUTPUT : ; NONE -- SCREEN IS SCROLLED : ;-------------------------------------------------------- SCROLL_DOWN PROC NEAR STD ; SCROLL DOWN MOV BL,AL ; LINE COUNT TO BL CALL MK_ES PUSH BX ; SAVE ATTRIBUTE IN BH MOV AX,DX ; LOWER RIGHT CORNER CALL SCROLL_POSITION ; GET REGEN LOCATION JZ N16 SUB SI,AX ; SI IS FROM ADDRESS MOV AH,DH ; GET TOTAL # ROWS SUB AH,BL ; COUNT TO MOVE IN SCROLL N13: CALL N10 ; MOVE ONE ROW SUB SI,BP SUB DI,BP DEC AH JNZ N13 N14: POP AX ; RECOVER ATTRIBUTE IN AH MOV AL,' ' N15: CALL N11 ; CLEAR ONE ROW SUB DI,BP ; GO TO NEXT ROW DEC BL JNZ N15 JMP N5 ; SCROLL_END N16: MOV BL,DH JMP N14 SCROLL_DOWN ENDP ;---------------------------------------------------------------- ; SCROLL_UP : ; THIS ROUTINE SCROLLS UP THE INFORMATION ON THE CRT : ; ENTRY : ; CH,CL = UPPER LEFT CORNER OF REGION TO SCROLL : ; DH,DL = LOWER RIGHT CORNER OF REGION TO SCROLL : ; BOTH OF THE ABOVE ARE IN CHARACTER POSITIONS : ; BH = FILL VALUE FOR BLANKED LINES : ; AL = # LINES TO SCROLL (AL=0 MEANS BLANK THE ENTIRE : ; FIELD) : ; DS = DATA SEGMENT : ; ES = REGEN SEGMENT : ; EXIT : ; NOTHING, THE SCREEN IS SCROLLED : ;---------------------------------------------------------------- GRAPHICS_UP PROC NEAR MOV BL,AL ; SAVE LINE COUNT IN BL MOV AX,CX ; GET UPPER LEFT POSITION ; INTO AX REG ;----- USE CHARACTER SUBROUTINE FOR POSITIONING ;----- ADDRESS RETURNED IS MULTIPLIED BY 2 FROM CORRECT VALUE CALL GRAPH_POSN MOV DI,AX ; SAVE RESULT AS ; DESTINATION ADDRESS ;----- DETERMINE SIZE OF WINDOW SUB DX,CX ADD DX,101H ; ADJUST VALUES SAL DH,1 ; MULTIPLY # ROWS BY 4 ; SINCE 8 VERT DOTS/CHAR SAL DH,1 ; AND EVEN/ODD ROWS ;----- DETERMINE CRT MODE CMP CRT_MODE,6 ; TEST FOR MEDIUM RES JNC R7 ; FIND_SOURCE ;----- MEDIUM RES UP SAL DL,1 ; * 2 SAL DI,1 ; SINCE 2 BYTES/CHAR ;----- DETERMINE THE SOURCE ADDRESS IN THE BUFFER R7: ; FIND_SOURCE PUSH ES ; GET SEGMENTS BOTH POP DS ; POINTING TO REGEN SUB CH,CH ; 0 TO HIGH OF COUNT REG SAL BL,1 ; NUMBER OF LINES *4 SAL BL,1 JZ R11 ; IF 0, BLANK ENTIRE FIELD MOV AL,BL ; NUMBER OF LINES IN AL MOV AH,80 ; 80 BYTES/ROW MUL AH ; OFFSET TO SOURCE MOV SI,DI ; SET UP SOURCE ADD SI,AX ; ADD IN OFFSET TO IT MOV AH,DH ; NUMBER OF ROWS IN FIELD SUB AH,BL ; DETERMINE NUMBER TO MOVE ;---- LOOP THROUGH, MOVING ONE ROW AT A TIME, BOTH EVEN AND ODD FIELDS R8: ; ROW_LOOP CALL R17 ; MOVE ONE ROW SUB SI,2000H-80 ; MOVE TO NEXT ROW SUB DI,2000H-80 DEC AH ; NUMBER OF ROWS TO MOVE JNZ R8 ; CONTINUE TILL ALL MOVED ;----- FILL IN THE VACATED LINE(S) R9: ; CLEAR_ENTRY MOV AL,BH ; ATTRIBUTE TO FILL WITH R10: CALL R18 ; CLEAR THAT ROW SUB DI,2000H-80 ; POINT TO NEXT LINE DEC BL ; NUMBER OF LINES TO FILL JNZ R10 ; CLEAR_LOOP JMP V_RET R11: ; BLANK_FIELD MOV BL,DH ; SET BLANK COUNT TO ; EVERYTHING IN FIELD JMP R9 ; CLEAR THE FIELD GRAPHICS_UP ENDP ;----- ROUTINE TO MOVE ONE ROW OF INFORMATION R17 PROC NEAR MOV CL,DL ; NUM OF BYTES IN THE ROW PUSH SI PUSH DI ; SAVE POINTERS REP MOVSB ; MOVE THE EVEN FIELD POP DI POP SI ADD SI,2000H ADD DI,2000H ; POINT TO THE ODD FIELD PUSH SI PUSH DI ; SAVE THE POINTERS MOV CL,DL ; COUNT BACK REP MOVSB ; MOVE THE ODD FIELD POP DI POP SI ; POINTERS BACK RET ; RETURN TO CALLER R17 ENDP ;----- CLEAR A SINGLE ROW R18 PROC NEAR MOV CL,DL ; NUMBER OF BYTES IN FIELD PUSH DI ; SAVE POINTER REP STOSB ; STORE THE NEW VALUE POP DI ; POINTER BACK ADD DI,2000H ; POINT TO ODD FIELD PUSH DI MOV CL,DL REP STOSB ; FILL THE ODD FIELD POP DI RET ; RETURN TO CALLER R18 ENDP MEM_DET PROC NEAR ASSUME DS:ABS0 PUSH AX PUSH DS CALL DDS MOV AH,INFO AND AH,060H POP DS POP AX JZ MIN STC RET MIN: CLC RET MEM_DET ENDP ;----- SCROLL ACTIVE PAGE UP SC_2: JMP SCROLL_UP AH6: ASSUME DS:ABS0 CALL FLTA MOV AH,CRT_MODE ; GET CURRENT MODE CMP AH,07H JBE SC_2 ; ANY OF THE OLD MODES CMP AH,0DH JAE GRAPHICS_UP_2 ; NEW GRAPHICS MODES JMP V_RET ; NOT A RECOGNIZED MODE GR_ST_1 PROC NEAR MOV DX,0A000H ; REGEN BUFFER MOV BP,0511H ; GRAPHICS WRITE MODE CMP AH,0FH JB VV1 CALL MEM_DET JNC VV1 MOV BP,0501H ; GRAPHICS WRITE MODE VV1: RET GR_ST_1 ENDP GRAPHICS_UP_2 PROC NEAR ASSUME DS:ABS0 PUSH DX CALL GR_ST_1 ; SET SEGMENT, WRITE MODE SRLOAD ES ; SET REGEN ;;; MOV ES,DX POP DX MOV BL,AL ; NUMBER OF LINES MOV AX,CX ; UPPER LEFT CORNER PUSH BX MOV BH,ACTIVE_PAGE ; ACTIVE PAGE FOR SCROLL CALL GRX_PSN ; ADDRESS IN REGEN POP BX MOV DI,AX ; SEG POINTER SUB DX,CX ; DETERMINE WINDOW ADD DX,0101H ; ADJUST SUB AH,AH ; ZERO HIGH BYTE MOV AL,BL ; LINE COUNT PUSH DX MUL POINTS ; BYTES PER CHARACTER MUL CRT_COLS ; COLUMNS MOV SI,DI ; SET UP SOURCE INDEX ADD SI,AX ; ADJUST ASSUME DS:NOTHING PUSH ES POP DS POP DX OR BL,BL ; LINE COUNT JZ AR9 MOV CL,DH SUB CL,BL SUB CH,CH ASSUME DS:ABS0 PUSH DS CALL DDS ; LOW MEMORY SEGMENT PUSH AX PUSH DX MOV AX,CX MUL POINTS ; BYTES PER CHAR MOV CX,AX ; SET THE COUNT POP DX POP AX ASSUME DS:NOTHING POP DS PUSH DX MOV AX,BP MOV DH,3 MOV DL,GRAPH_ADDR ; GRAPHICS CALL OUT_DX MOV DL,SEQ_ADDR ; SEQUENCER MOV AX,020FH ; ENABLE ALL MAPS CALL OUT_DX POP DX CALL CRANK ; SCROLL THE SCREEN PUSH DX DEC BP MOV AX,BP MOV DH,3 MOV DL,GRAPH_ADDR CALL OUT_DX POP DX AR10: CALL BLNK_3 JMP V_RET AR9: MOV BL,DH ; BLANK ENTIRE WINDOW JMP AR10 GRAPHICS_UP_2 ENDP ;----- SCROLL ACTIVE DISPLAY PAGE DOWN SC_3: JMP SCROLL_DOWN AH7: ASSUME DS:ABS0 CALL FLTA MOV AH,CRT_MODE CMP AH,03H ; OLD COLOR ALPHA JBE SC_3 CMP AH,07H ; MONOCHROME ALPHA JE SC_3 CMP AH,0DH ; NEW GRAPHICS MODES JAE GRAPHICS_DN_2 CMP AH,06H ; OLD GRAPHICS MODES JA M_O MOV AH,07H INT 42H M_O: JMP V_RET GRAPHICS_DN_2 PROC NEAR STD ; DIRECTION TO DECREMENT MOV BL,AL ; LINE COUNT PUSH DX ; SAVE LOWER RIGHT CALL GR_ST_1 ; SET REGEN SEGMENT SRLOAD ES ;;; MOV ES,DX POP DX MOV AX,DX INC AH ; MOV CHAR ROW UP BY ONE PUSH BX MOV BH,ACTIVE_PAGE CALL GRX_PSN ; ADDRESS IN REGEN POP BX SUB AX,CRT_COLS ; ONE SCAN OVERSHOOT MOV DI,AX SUB DX,CX ; CALCULATE WINDOW ADD DX,0101H ; ADJUST COUNT SUB AH,AH MOV AL,BL PUSH DX MUL POINTS ; BYTES PER CHAR MUL CRT_COLS ; BYTES PER ROW MOV SI,DI SUB SI,AX ASSUME DS:NOTHING PUSH ES ; SET DS TO POP DS ; THE REGEN SEGMENT POP DX OR BL,BL ; SCROLL COUNT JZ DXR9 ; BLANK ENTIRE WINDOW MOV CL,DH SUB CL,BL SUB CH,CH ASSUME DS:ABS0 PUSH DS CALL DDS PUSH AX PUSH DX MOV AX,CX MUL POINTS ; BYTES PER CHAR MOV CX,AX POP DX POP AX ASSUME DS:NOTHING POP DS PUSH DX MOV AX,BP MOV DH,3 MOV DL,GRAPH_ADDR ; GRAPHICS CALL OUT_DX MOV DL,SEQ_ADDR ; SEQUENCER MOV AX,020FH ; ENABLE ALL MAPS CALL OUT_DX POP DX CALL CRANK_4 ; SCROLL THE SCREEN PUSH DX DEC BP MOV AX,BP MOV DH,3 MOV DL,GRAPH_ADDR CALL OUT_DX POP DX DXR10: CALL BLNK_4 CLD JMP V_RET DXR9: MOV BL,DH ; BLANK ENTIRE WINDOW JMP DXR10 GRAPHICS_DN_2 ENDP SUBTTL ;;; INCLUDE VGRW.INC SUBTTL VGRW.INC PAGE ASSUME DS:ABS0 FIND_POSITION PROC NEAR MOV CL,BH ; DISPLAY PAGE TO CX XOR CH,CH MOV SI,CX ; MOVE TO SI FOR INDEX SAL SI,1 ; * 2 FOR WORD OFFSET MOV AX,[SI+ OFFSET CURSOR_POSN] ; ROW/COLUMN OF THAT PAGE XOR BX,BX ; SET START ADDRESS TO 0 JCXZ P5 ; NO_PAGE P4: ; PAGE_LOOP ADD BX,CRT_LEN ; LENGTH OF BUFFER LOOP P4 P5: ; NO_PAGE CALL POSITION ; DETERMINE LOC IN REGEN ADD BX,AX ; ADD TO START OF REGEN RET FIND_POSITION ENDP ;-------------------------------------------------------- ; EXPAND_MED_COLOR : ; THIS ROUTINE EXPANDS THE LOW 2 BITS IN BL TO : ; FILL THE ENTIRE BX REGISTER : ; ENTRY : ; BL = COLOR TO BE USED ( LOW 2 BITS ) : ; EXIT : ; BX = COLOR TO BE USED ( 8 REPLICATIONS OF THE : ; 2 COLOR BITS ) : ;-------------------------------------------------------- S19 PROC NEAR AND BL,3 ; ISOLATE THE COLOR BITS MOV AL,BL ; COPY TO AL PUSH CX ; SAVE REGISTER MOV CX,3 ; NUMBER OF TIMES S20: SAL AL,1 SAL AL,1 ; LEFT SHIFT BY 2 OR BL,AL ; ANOTHER COLOR VERSION ; INTO BL LOOP S20 ; FILL ALL OF BL MOV BH,BL ; FILL UPPER PORTION POP CX ; REGISTER BACK RET ; ALL DONE S19 ENDP ;-------------------------------------------------------- ; EXPAND_BYTE : ; THIS ROUTINE TAKES THE BYET IN AL AND DOUBLES : ; ALL OF THE BITS, TURNING THE 8 BITS INTO : ; 16 BITS. THE RESULT IS LEFT IN AX : ;-------------------------------------------------------- S21 PROC NEAR PUSH DX ; SAVE REGISTERS PUSH CX PUSH BX SUB DX,DX ; RESULT REGISTER MOV CX,1 ; MASK REGISTER S22: MOV BX,AX ; BASE INTO TEMP AND BX,CX ; USE MASK TO EXTRACT BIT OR DX,BX ; PUT INTO RESULT RECISTER SHL AX,1 SHL CX,1 ; SHIFT BASE AND MASK BY 1 MOV BX,AX ; BASE TO TEMP AND BX,CX ; EXTRACT THE SAME BIT OR DX,BX ; PUT INTO RESULT SHL CX,1 ; SHIFT ONLY MASK NOW, ; MOVING TO NEXT BASE JNC S22 ; USE MASK BIT COMING OUT ; TO TERMINATE MOV AX,DX ; RESULT TO PARM REGISTER POP BX POP CX ; RECOVER REGISTERS POP DX RET ; ALL DONE S21 ENDP S26 PROC NEAR MOV AX,CURSOR_POSN ; GET CURRENT CURSOR GRAPH_POSN LABEL NEAR PUSH BX ; SAVE REGISTER MOV BX,AX ; SAVE A COPY OF CURSOR MOV AL,AH ; GET ROWS TO AL MUL BYTE PTR CRT_COLS ; MULTIPLY BY BYTES/COLUMN SHL AX,1 ; *4 SINCE 4 ROWS/BYTE SHL AX,1 SUB BH,BH ; ISOLATE COLUMN VALUE ADD AX,BX ; DETERMINE OFFSET POP BX ; RECOVER POINTER RET ; ALL DONE S26 ENDP ;---------------------------------------------------------------- ; GR_CUR : ; ENTRY : ; BH = DISPLAY PAGE : ; EXIT : ; AX = CURSOR POSITION FOR REQUESTED PAGE : ;---------------------------------------------------------------- GR_CUR: ASSUME DS:ABS0 PUSH BX ; SAVE REGISTER MOV BL,BH ; GET TO LOW BYTE SUB BH,BH ; ZERO HIGH BYTE SAL BX,1 ; *2 FOR WORD COUNT MOV AX,[BX + OFFSET CURSOR_POSN] ; CURSOR, REQUESTED PAGE POP BX ; RECOVER REGISTER ;---------------------------------------------------------------- ; GRX_PSN : ; ENTRY : ; AX = CURSOR POSITION IN DESIRED PAGE : ; BH = DESIRED PAGE : ; EXIT : ; AX = BYTE OFFSET INTO REGEN : ;---------------------------------------------------------------- GRX_PSN PROC NEAR PUSH BX ; SAVE PUSH CX ; SAVE PUSH DX ; SAVE SUB CH,CH ; ZERO MOV CL,BH ; PAGE NUMBER MOV BX,AX ; ROW, COLUMN MOV AL,AH ; ROW MUL BYTE PTR CRT_COLS ; ROW * COLUMNS/ROW MUL POINTS ; BYTES PER ROW SUB BH,BH ; ZERO TO LEAVE COL VALUE ADD AX,BX ; ADD IN COLUMN MOV BX,CRT_LEN ; PAGE LENGTH JCXZ GP_2 ; NO PAGE OFFSET GP_3: ADD AX,BX ; ADD IN THE PAGE LENGTH LOOP GP_3 ; DO FOR NUMBER OF PAGES GP_2: POP DX ; RECOVER POP CX ; RECOVER POP BX ; RECOVER RET GRX_PSN ENDP MK_ES: MOV SI,0B800H MOV DI,EQUIP_FLAG AND DI,030H CMP DI,030H JNE P6_A MOV SI,0B000H P6_A: MOV ES,SI RET ;-------------------------------------------------------- ; READ_AC_CURRENT : ; THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER : ; AT THE CURRENT CURSOR POSITION AND RETURNS THEM : ; TO THE CALLER : ; INPUT : ; (AH) = CURRENT CRT MODE : ; (BH) = DISPLAY PAGE ( ALPHA MODES ONLY ) : ; (DS) = DATA SEGMENT : ; (ES) = REGEN SEGMENT : ; OUTPUT : ; (AL) = CHAR READ : ; (AH) = ATTRIBUTE READ : ;-------------------------------------------------------- ASSUME CS:CODE,DS:ABS0,ES:NOTHING READ_AC_CURRENT PROC NEAR CALL MK_ES CALL FIND_POSITION MOV SI,BX ; ADDRESSING IN SI MOV DX,ADDR_6845 ; GET BASE ADDRESS ADD DX,6 ; POINT AT STATUS PORT TEST INFO,4 PUSH ES POP DS ; SEGMENT FOR QUICK ACCESS JZ P3A ;----- WAIT FOR HORIZONTAL RETRACE P2: ; WAIT FOR RETRACE LOW IN AL,DX ; GET STATUS TEST AL,1 ; IS HORZ RETRACE LOW JNZ P2 ; WAIT UNTIL IT IS CLI ; NO MORE INTERRUPTS P3: ; WAIT FOR RETRACE HIGH IN AL,DX ; GET STATUS TEST AL,1 ; IS IT HIGH JZ P3 ; WAIT UNTIL IT IS P3A: LODSW ; GET THE CHAR/ATTR JMP V_RET READ_AC_CURRENT ENDP ;-------------------------------------------------------- ; MED_READ_BYTE : ; THIS ROUTINE WILL TAKE 2 BYTES FROM THE REGEN : ; BUFFER, COMPARE AGAINST THE CURRENT FOREGROUND : ; COLOR, AND PLACE THE CORRESPONDING ON/OFF BIT : ; PATTERN INTO THE CURRENT POSITION IN THE SAVE : ; AREA : ; ENTRY : ; SI,DS = POINTER TO REGEN AREA OF INTEREST : ; BX = EXPANDED FOREGROUND COLOR : ; BP = POINTER TO SAVE AREA : ; EXIT : ; BP IS INCREMENT AFTER SAVE : ;-------------------------------------------------------- S23 PROC NEAR MOV AH,[SI] ; GET FIRST BYTE MOV AL,[SI+1] ; GET SECOND BYTE MOV CX,0C000H ; 2 BIT MASK TO TEST ; THE ENTRIES MOV DL,0 ; RESULT REGISTER S24: TEST AX,CX ; IS THIS BACKGROUND? CLC ; CLEAR CARRY IN HOPES ; THAT IT IS JZ S25 ; IF 0, IT IS BACKGROUND STC ; WASN'T, SO SET CARRY S25: RCL DL,1 ; MOVE THAT BIT INTO THE SHR CX,1 ; RESULT SHR CX,1 ; MOVE THE MASK TO THE ; RIGHT BY 2 BITS JNC S24 ; DO IT AGAIN IF MASK ; DIDN'T FALL OUT MOV [BP],DL ; STORE RESULT IN SAVE INC BP ; ADJUST POINTER RET ; ALL DONE S23 ENDP GRAPHICS_READ PROC NEAR CALL MK_ES CALL S26 ; CONVERTED TO OFFSET MOV SI,AX ; SAVE IN SI SUB SP,8 ; ALLOCATE SPACE TO SAVE ; THE READ CODE POINT MOV BP,SP ; POINTER TO SAVE AREA ;----- DETERMINE GRAPHICS MODES CMP CRT_MODE,6 PUSH ES POP DS ; POINT TO REGEN SEGMENT JC S13P ; MEDIUM RESOLUTION ;----- HIGH RESOLUTION READ ;----- GET VALUES FROM REGEN BUFFER AND CONVERT TO CODE POINT MOV DH,4 ; NUMBER OF PASSES S12P: MOV AL,[SI] ; GET FIRST BYTE MOV [BP],AL ; SAVE IN STORAGE AREA INC BP ; NEXT LOCATION MOV AL,[SI+2000H] ; GET LOWER REGION BYTE MOV [BP],AL ; ADJUST AND STORE INC BP ADD SI,80 ; POINTER INTO REGEN DEC DH ; LOOP CONTROL JNZ S12P ; DO IT SOME MORE JMP S15P ; GO MATCH THE SAVED CODE ; POINTS ;----- MEDIUM RESOLUTION READ S13P: ; MED_RES_READ SAL SI,1 ; OFF5ET*2, 2 BYTES/CHAR MOV DH,4 ; NUMBER OF PASSES S14P: CALL S23 ; GET PAIR BYTES ; INTO SINGLE SAVE ADD SI,2000H ; GO TO LOWER REGION CALL S23 ; GET THIS PAIR INTO SAVE SUB SI,2000H-80 ; ADJUST POINTER BACK INTO DEC DH ; UPPER JNZ S14P ; KEEP GOING UNTIL 8 DONE ;----- SAVE AREA HAS CHARACTER IN IT, MATCH IT S15P: ; FIND_CHAR PUSH DS CALL DDS LES DI,GRX_SET ; ESTABLISH ADDRESSING POP DS SUB BP,8 ; ADJUST POINTER TO ; BEGINNING OF SAVE AREA MOV SI,BP CLD ; ENSURE DIRECTION MOV AL,0 ; CURRENT CODE POINT BEING S16P: ; MATCHED PUSH SS ; ADDRESSING TO STACK POP DS ; FOR THE STRING COMPARE MOV DX,128 ; NUMBER TO TEST AGAINST S17P: PUSH SI ; SAVE SAVE AREA POINTER PUSH DI ; SAVE CODE POINTER MOV CX,8 ; NUMBER OF BYTES TO MATCH REPE CMPSB ; COMPARE THE 8 BYTES POP DI ; RECOVER THE POINTERS POP SI JZ S18P ; IF ZERO FLAG SET, ; THEN MATCH OCCURRED INC AL ; NO MATCH, MOVE TO NEXT ADD DI,8 ; NEXT CODE POINT DEC DX ; LOOP CONTROL JNZ S17P ; DO ALL OF THEM ;----- CHAR NOT MATCHED, MIGHT BE IN USER SUPPLIED SECOND HALF CMP AL,0 ; AL <> 0 IF ONLY 1ST ; HALF SCANNED JE S18P ; IF = 0, THEN ALL HAS ; BEEN SCANNED ASSUME DS:ABS0 CALL DDS LES DI,EXT_PTR ; GET POINTER MOV AX,ES ; SEE IF THE PNTR EXISTS OR AX,DI ; IF ALL 0, DOESN'T EXIST JZ S18P ; NO SENSE LOOKING MOV AL,128 ; ORIGIN FOR SECOND HALF JMP S16P ; GO BACK AND TRY FOR IT ;----- CHARACTER IS FOUND ( AL=0 IF NOT FOUND ) S18P: ADD SP,8 ; READJUST THE STACK, ; THROW AWAY SAVE JMP V_RET ; ALL DONE GRAPHICS_READ ENDP ;----- READ CHARACTER/ATTRIBUTE AT CURRENT CURSOR POSITION AH8S: JMP READ_AC_CURRENT AH8: ASSUME DS:ABS0 MOV AH,CRT_MODE ; GET THE CURRENT MODE CMP AH,07H JE AH8S CMP AH,03H JBE AH8S CMP AH,06H JA Z_1 JMP GRAPHICS_READ Z_1: CMP AH,0FH JB GRX_RD2 CALL MEM_DET JC GRX_RD2 JMP SHORT GRX_RD1 CMP AH,0DH ; RANGE TEST JAE GRX_RD2 ; FOUR MAP READ MOV AL,0 JMP V_RET GRX_RD1 PROC NEAR ASSUME DS:ABS0 SRLOAD ES,0A000H ; REGEN SEGEMNT ;;; MOV DX,0A000H ;;; MOV ES,DX CALL GR_CUR ; BYTE OFFSET INTO REGEN MOV SI,AX ; SAVE IN SI MOV BX,POINTS ; BYTES PER CHARACTER SUB SP,BX ; ALLOCATE SPACE TO SAVE ; THE READ CODE POINT MOV BP,SP ; POINTER TO SAVE AREA ;----- GET VALUES FROM REGEN BUFFER AND CONVERT TO CODE POINT PUSH BX ; SAVE BYTES PER CHARACTER AND AL,1 ; ODD OR EVEN BYTE MOV CL,AL ; USE FOR SHIFT MOV AL,5 ; COLOR COMP VALUE (C0-C2) SHL AL,CL ; (C1-C3) IF ODD BYTE MOV AH,G_COLOR ; COLOR COMPARE REGISTER MOV DH,3 MOV DL,GRAPH_ADDR CALL OUT_DX ; SET GRAPHICS CHIP MOV AX,518H ; READ MODE CALL OUT_DX ; SET GRAPHICS CHIP S12_1: MOV AL,ES:[SI] ; GET FIRST BYTE NOT AL MOV SS:[BP],AL ; SAVE IN STORAGE AREA INC BP ; NEXT LOCATION ADD SI,CRT_COLS ; POINTER INTO REGEN DEC BX ; LOOP CONTROL JNZ S12_1 ; DO IT SOME MORE POP BX ; RECOVER BYTES PER CHAR MOV AX,510H ; UNDO READ MODE JMP GRX_RECG ; CHAR REGONTION ROUTINE GRX_RD1 ENDP GRX_RD2 PROC NEAR ASSUME DS:ABS0 SRLOAD ES,0A000H ; REGEN SEGMENT ;;; MOV DX,0A000H ;;; MOV ES,DX CALL GR_CUR ; BYTE OFFSET INTO REGEN MOV SI,AX ; SAVE IN SI MOV BX,POINTS ; BYTES PER CHARACTER SUB SP,BX ; ALLOCATE SPACE TO SAVE ; THE READ CODE POINT MOV BP,SP ; POINTER TO SAVE AREA ;----- GET VALUES FROM REGEN BUFFER AND CONVERT TO CODE POINT MOV DH,3 MOV DL,GRAPH_ADDR ; GRAPHICS CHIP MOV AX,508H ; COLOR COMPARE CALL OUT_DX ; SET THE REGISTER PUSH BX ; SAVE BYTES PER CHARACTER S12: MOV AL,ES:[SI] ; GET COLOR COMPARED BYTE NOT AL ; ADJUST MOV SS:[BP],AL ; SAVE IN STORAGE AREA INC BP ; NEXT LOCATION ADD SI,CRT_COLS ; POINTER INTO REGEN DEC BX ; LOOP CONTROL JNZ S12 ; DO IT SOME MORE POP BX ; RECOVER BYTES PER CHAR MOV AX,500H ; UNDO READ MODE GRX_RD2 ENDP GRX_RECG: ;----- SAVE AREA HAS CHARACTER IN IT, MATCH IT CALL OUT_DX ; SET READ MODE BACK LES DI,GRX_SET ; GET FONT DEFINITIONS SUB BP,BX ; ADJUST POINTER TO ; BEGINNING OF SAVE AREA MOV SI,BP CLD ; ENSURE DIRECTION MOV AL,0 ; CODE POINT BEING MATCHED PUSH SS ; ADDRESSING TO STACK POP DS ; FOR THE STRING COMPARE MOV DX,256D ; NUMBER TO TEST AGAINST S17_5: PUSH SI ; SAVE SAVE AREA POINTER PUSH DI ; SAVE CODE POINTER MOV CX,BX ; NUMBER OF BYTES TO MATCH REPE CMPSB ; COMPARE THE 8 BYTES POP DI ; RECOVER THE POINTERS POP SI JZ S18_5 ; IF ZFL SET, THEN MATCH ; OCCURRED INC AL ; NO MATCH, ON TO NEXT ADD DI,BX ; NEXT CODE POINT DEC DX ; LOOP CONTROL JNZ S17_5 ; DO ALL OF THEM S18_5: ; AL=CHAR, 0 IF NOT FOUND ADD SP,BX ; READJUST THE STACK JMP V_RET ;----- WRITE CHARACTER/ATTRIBUTE AT CURRENT CURSOR POSITION ;------------------------------------------------ ; WRITE_AC_CURRENT : ; THIS ROUTINE WRITES THE ATTRIBUTE : ; AND CHARACTER AT THE CURRENT CURSOR : ; POSITION : ; INPUT : ; (AH) = CURRENT CRT MODE : ; (BH) = DISPLAY PAGE : ; (CX) = COUNT OF CHARACTERS TO WRITE : ; (AL) = CHAR TO WRITE : ; (BL) = ATTRIBUTE OF CHAR TO WRITE : ; (DS) = DATA SEGMENT : ; (ES) = REGEN SEGMENT : ; OUTPUT : ; NONE : ;------------------------------------------------ AH9: ASSUME DS:ABS0 CALL DDS MOV AH,CRT_MODE CMP AH,4 ; IS THIS GRAPHICS JC P6 CMP AH,7 ; IS THIS BW CARD JE P6 JMP GRAPHICS_WRITE P6: ; WRITE_AC_CONTINUE CALL MK_ES MOV AH,BL ; GET ATTRIBUTE TO AH PUSH AX ; SAVE ON STACK PUSH CX ; SAVE WRITE COUNT CALL FIND_POSITION MOV DI,BX ; ADDRESS TO DI REGISTER POP CX ; WRITE COUNT POP BX ; CHARACTER IN BX REG MOV DX,ADDR_6845 ; GET BASE ADDRESS ADD DX,6 ; POINT AT STATUS PORT ;----- WAIT FOR HORIZONTAL RETRACE P7: TEST INFO,4 JZ P9A P8: IN AL,DX ; GET STATUS TEST AL,1 ; IS IT LOW JNZ P8 ; WAIT UNTIL IT IS CLI ; NO MORE INTERRUPTS P9: IN AL,DX ; GET STATUS TEST AL,1 ; IS IT HIGH JZ P9 ; WAIT UNTIL IT IS P9A: MOV AX,BX ; RECOVER THE CHAR/ATTR STOSW ; PUT THE CHAR/ATTR STI ; INTERRUPTS BACK ON LOOP P7 ; AS MANY TIMES JMP V_RET ;----- WRITE CHARACTER ONLY AT CURRENT CURSOR POSITION ;------------------------------------------------ ; WRITE_C_CURRENT : ; THIS ROUTINE WRITES THE CHARACTER AT : ; THE CURRENT CURSOR POSITION, ATTRIBUTE : ; UNCHANGED : ; INPUT : ; (AH) = CURRENT CRT MODE : ; (BH) = DISPLAY PAGE : ; (CX) = COUNT OF CHARACTERS TO WRITE : ; (AL) = CHAR TO WRITE : ; (DS) = DATA SEGMENT : ; (ES) = REGEN SEGMENT : ; OUTPUT : ; NONE : ;------------------------------------------------ AHA: ASSUME DS:ABS0 CALL DDS MOV AH,CRT_MODE CMP AH,4 ; IS THIS GRAPHICS JC P10 CMP AH,7 ; IS THIS BW CARD JE P10 JMP GRAPHICS_WRITE P10: CALL MK_ES PUSH AX ; SAVE ON STACK PUSH CX ; SAVE WRITE COUNT CALL FIND_POSITION MOV DI,BX ; ADDRESS TO DI POP CX ; WRITE COUNT POP BX ; BL HAS CHAR TO WRITE ;----- WAIT FOR HORIZONTAL RETRACE MOV DX,ADDR_6845 ; GET BASE ADDRESS ADD DX,6 ; POINT AT STATUS PORT P11: TEST INFO,4 JZ P13A P12: IN AL,DX ; GET STATUS TEST AL,1 ; IS IT LOW JNZ P12 ; WAIT UNTIL IT IS CLI ; NO MORE INTERRUPTS P13: IN AL,DX ; GET STATUS TEST AL,1 ; IS IT HIGH JZ P13 ; WAIT UNTIL IT IS P13A: MOV AL,BL ; RECOVER CHAR STOSB ; PUT THE CHAR/ATTR STI ; INTERRUPTS BACK ON INC DI ; BUMP POINTER PAST ATTR LOOP P11 ; AS REQUESTED JMP V_RET ;---------------------------------------------------------------- ; GRAPHICS WRITE : ; THIS ROUTINE WRITES THE ASCII CHARACTER TO THE : ; CURRENT POSITION ON THE SCREEN. : ; ENTRY : ; AL = CHARACTER TO WRITE : ; BL = COLOR ATTRIBUTE TO BE USED FOR FOREGROUND COLOR : ; IF BIT 7 IS SET, THE CHAR IS XOR'D INTO THE REGEN : ; BUFFER (0 IS USED FOR THE BACKGROUND COLOR) : ; CX = NUMBER OF CHARS TO WRITE : ; DS = DATA SEGMENT : ; ES = REGEN SEGMENT : ; EXIT : ; NOTHING IS RETURNED : ; : ; GRAPHICS READ : ; THIS ROUTINE READS THE ASCII CHARACTER AT THE CURRENT : ; CURSOR POSITION ON THE SCREEN BY MATCHING THE DOTS ON : ; THE SCREEN TO THE CHARACTER GENERATOR CODE POINTS : ; ENTRY : ; NONE (0 IS ASSUMED AS THE BACKGROUND COLOR) : ; EXIT : ; AL = CHARACTER READ AT THAT POSITION (0 RETURNED IF : ; NONE FOUND) : ; : ; FOR COMPATIBILITY ROUTINES, THE IMAGES USED TO FORM CHARS ARE : ; CONTAINED IN ROM FOR THE 1ST 128 CHARS. TO ACCESS CHARS : ; IN THE SECOND HALF, THE USER MUST INITIALIZE THE VECTOR AT : ; INTERRUPT 1FH (LOCATION 0007CH) TO POINT TO THE USER : ; SUPPLIED TABLE OF GRAPHIC IMAGES (8X8 BOXES). : ; FAILURE TD DO SO WILL CAUSE IN STRANGE RESULTS : ;---------------------------------------------------------------- ASSUME CS:CODE,DS:ABS0,ES:NOTHING GRAPHICS_WRITE PROC NEAR CMP AH,7 JB S1_A JMP GRX_WRT S1_A: CALL MK_ES MOV AH,0 ; 0 TO HIGH OF CODE POINT PUSH AX ; SAVE CODE POINT VALUE ;----- DETERMINE POSITION IN REGEN BUFFER TO PUT CODE POINTS CALL S26 ; LOC IN REGEN BUFFER MOV DI,AX ; REGEN POINTER IN DI ;----- DETERMINE REGION TO GET CODE POINTS FROM POP AX ; RECOVER CODE POINT CMP AL,80H ; IS IT IN SECOND HALF JAE S1 ; YES ;----- IMAGE IS IN FIRST HALF, CONTAINED IN ROM LDS SI,GRX_SET JMP SHORT S2 ; DETERMINE_MODE ;----- IMAGE IS IN SECOND HALF, IN USER RAM S1: ; EXTEND_CHAR SUB AL,80H ; 0 ORIGIN FOR SECOND HALF LDS SI,EXT_PTR ;----- DETERMINE GRAPHICS MODE IN OPERATION S2: ; DETERMINE_MODE SAL AX,1 ; MULTIPLY CODE POINT SAL AX,1 ; VALUE BY 8 SAL AX,1 ADD SI,AX ; SI HAS OFFSET OF PUSH DS ; DESIRES CODES CALL DDS CMP CRT_MODE,6 POP DS JC S7 ; TEST FOR MEDIUM RES MODE ;----- HIGH RESOLUTION MODE S3: ; HIGH_CHAR PUSH DI ; SAVE REGEN POINTER PUSH SI ; SAVE CODE POINTER MOV DH,4 ; NUMBER OF TIMES THROUGH S4: ; LOOP LODSB ; GET BYTE FROM CODE POINT TEST BL,80H ; SHOULD WE USE THE JNZ S6 ; FUNCTION TO PUT CHAR IN STOSB ; STORE IN REGEN BUFFER LODSB S5: MOV ES:[DI+2000H-1],AL ; STORE IN SECOND HALF ADD DI,79 ; MOVE TO NEXT ROW IN REGEN DEC DH ; DONE WITH LOOP JNZ S4 POP SI POP DI ; RECOVER REGEN POINTER INC DI ; POINT TO NEXT CHAR POS LOOP S3 ; MORE CHARS TO WRITE JMP V_RET S6: XOR AL,ES:[DI] ; XOR WITH CURRENT STOSB ; STORE THE CODE POINT LODSB ; AGAIN FOR ODD FIELD XOR AL,ES:[DI+2000H-1] JMP S5 ; BACK TO MAINSTREAM ;----- MEDIUM RESOLUTION WRITE S7: ; MED_RES_WRITE MOV DL,BL ; SAVE HIGH COLOR BIT SAL DI,1 ; OFFSET*2, 2 BYTES/CHAR CALL S19 ; EXPAND BL TO FULL WORD S8: ; OF COLOR PUSH DI ; SAVE REGEN POINTER PUSH SI ; SAVE THE CODE POINTER MOV DH,4 ; NUMBER OF LOOPS S9: LODSB ; GET CODE POINT CALL S21 ; DOUBLE UP ALL THE BITS AND AX,BX ; CONVERT THEM TO FORE- ; GROUND COLOR (0 BACK) TEST DL,80H ; IS THIS XOR FUNCTION JZ S10 ; NO, STORE IT IN AS IT IS XOR AH,ES:[DI] ; DO FUNCTION WITH HALF XOR AL,ES:[DI+1] ; AND WITH OTHER HALF S10: MOV ES:[DI],AH ; STORE FIRST BYTE MOV ES:[DI+1],AL ; STORE SECOND BYTE LODSB ; GET CODE POINT CALL S21 AND AX,BX ; CONVERT TO COLOR TEST DL,80H ; IS THIS XOR FUNCTION JZ S11 ; NO, JUST STORE THE VALUE XOR AH,ES:[DI+2000H] ; FUNCTION WITH FIRST HALF XOR AL,ES:[DI+2001H] ; AND WITH SECOND HALF S11: MOV ES:[DI+2000H],AH MOV ES:[DI+2000H+1],AL ; STORE IN SECOND PORTION ADD DI,80 ; POINT TO NEXT LOCATION DEC DH JNZ S9 ; KEEP GOING POP SI ; RECOVER CODE PONTER POP DI ; RECOVER REGEN POINTER INC DI ; POINT TO NEXT CHAR INC DI LOOP S8 ; MORE TO WRITE JMP V_RET GRAPHICS_WRITE ENDP ;---------------------------------------------------------------- ; ENTRY : ; AL = CHAR TO WRITE : ; BH = DISPLAY PAGE : ; BL = ATTRIBUTE/COLOR : ; CX = COUNT OF CHARS TO WRITE : ;---------------------------------------------------------------- GRX_WRT PROC NEAR ASSUME DS:ABS0, ES:NOTHING CMP AH,0FH ; 640X350 GRAPHICS JB NO_ADJ1 CALL MEM_DET ; BASE CARD JC NO_ADJ1 AND BL,10000101B ; 85H, XOR C2 C0 MASK MOV AH,BL SHL AH,1 ; EXPAND C0 TO C1, C2 TO C3 OR BL,AH ; BUILD ?(80H) + (0,3,C,F) NO_ADJ1: SUB AH,AH ; ZERO MUL POINTS ; OFFSET FONT TABLE BASE PUSH AX ; FONT TABLE DISPLACEMENT CALL GR_CUR ; GET OFFSET INTO REGEN MOV DI,AX ; INTO DESTINATION MOV BP,POINTS ; BYTES PER CHAR SRLOAD ES,0A000H ; REGEN SEGEMNT ;;; MOV DX,0A000H ;;; MOV ES,DX LDS SI,GRX_SET ; ADDRESSING TO FONTS POP AX ; RECOVER OFFSET ADD SI,AX ; CHARACTER IN TABLE MOV DH,3 S20A: TEST BL,080H ; TEST FOR XOR JZ NO_XOR ; NO XOR MOV DL,GRAPH_ADDR MOV AX,0318H ; GRAPHICS CHIP XOR CALL OUT_DX ; SET REGISTER JMP F_2 ; SKIP BLANK NO_XOR: ; BLANK BOX FOR CHAR PUSH DI ; SAVE REGEN POINTER MOV DL,SEQ_ADDR MOV AX,020FH ; ENABLE ALL MAPS CALL OUT_DX SUB AX,AX ; STORE ZERO PUSH CX ; SAVE CHARACTER COUNT MOV CX,BP ; GET BYTE COUNT PUSH DS CALL DDS S13A: STOSB ; ZERO REGEN BYTE ADD DI,CRT_COLS ; NEXT BYTE OF BOX DEC DI ; ADJUST LOOP S13A ; NEXT BYTE POP DS POP CX ; RECOVER CHARACTER COUNT POP DI ; RECOVER REGEN POINTER F_2: MOV DL,SEQ_ADDR MOV AH,02H ; SET MAP MASK MOV AL,BL ; FOR COLOR CALL OUT_DX ; SET THE CHIP PUSH DI ; SAVE OFFSET IN REGEN PUSH BX ; SAVE COLOR VALUE PUSH CX ; SAVE CHACTER COUNT MOV BX,BP ; LOOP CONTROL, BYTES/CHAR PUSH DS ; SAVE FONT SEGMENT CALL DDS ; SET LOW RAM SEGMENT ASSUME DS:ABS0 MOV CX,CRT_COLS ; GET COLUMN COUNT POP DS ; RESTORE FONT SEGMENT ASSUME DS:NOTHING S1K: ; WRITE OUT THE CHARACTER MOV AL,DS:[SI] ; CODE POINT MOV AH,ES:[DI] ; LATCH DATA MOV ES:[DI],AL ; WRITE ONE BYTE OF FONT INC SI ; NEXT FONT POINT ADD DI,CX ; ONE ROW BELOW LAST POINT DEC BX ; BYTES PER CHAR COUNTER JNZ S1K ; DO NEXT ROW OF CHARACTER POP CX ; CHARACTER COUNT POP BX ; COLOR VALUE SUB SI,BP ; ADJUST PTR TO FONT TABLE POP DI ; REGEN POINTER INC DI ; NEXT CHAR POSN IN REGEN LOOP S20A ; WRITE ANOTHER CHARACTER MOV DL,GRAPH_ADDR MOV AX,0300H ; NORMAL WRITE, NO ROTATE CALL OUT_DX ; SET THE CHIP MOV DL,SEQ_ADDR MOV AX,020FH ; ENABLE ALL MAPS CALL OUT_DX ; SET THE CHIP JMP V_RET GRX_WRT ENDP SUBTTL ;----- SET COLOR PALETTE AHB: ASSUME DS:ABS0 CMP BYTE PTR ADDR_6845,0B4H JE M21_B ; CALL VALID ONLY FOR COLOR TEST INFO,2 ; SEE IF ITS THE OLD COLOR CARD JZ M21_A ; IF NOT, HANDLE IT HERE INT 42H ; OLD CODE CALL M21_B: JMP V_RET ; BACK TO CALLER M21_A: SUB AX,AX MOV BP,AX LES DI,SAVE_PTR ADD DI,4 LES DI,DWORD PTR ES:[DI] MOV AX,ES OR AX,DI JZ NOT4AHB INC BP NOT4AHB: CALL PAL_INIT OR BH,BH JNZ M20 ;----- HANDLE BH = 0 HERE ; ALPHA MODES => BL = OVERSCAN COLOR ; GRAPHICS => BL = OVERSCAN AND BACKGROUND COLOR ;----- MOVE INTENSITY BIT FROM D3 TO D4 FOR COMPATIBILITY MOV BH,BL MOV AL,CRT_PALETTE AND AL,0E0H AND BL,01FH OR AL,BL MOV CRT_PALETTE,AL MOV BL,BH AND BH,08H SHL BH,1 MOV CH,AL AND CH,0EFH OR CH,CH AND BL,0FH MOV BH,BL SHL BL,1 AND BL,010H AND BH,07H OR BL,BH MOV AL,CRT_MODE CMP AL,3 JBE M21 ;----- GRAPHICS MODE DONE HERE (SET PALETTE 0 AND OVERSCAN) MOV AH,0 MOV AL,BL CALL PAL_SET OR BP,BP JZ M21 MOV ES:[DI],BL ;----- ALPHA MODE DONE HERE (SET OVERSCAN REGISTER) M21: CMP CRT_MODE,3 ; CHECK FOR AN ENHANCED MODE JA SET_OVRSC ; NO CHANCE CALL BRST_DET ; SEE IF WE ARE ENHANCED JC SKIP_OVRSC ; THERE IS NO BORDER SET_OVRSC: MOV AH,011H ; OVERSCAN REGISTER MOV AL,BL CALL PAL_SET ; SET THE BORDER SKIP_OVRSC: OR BP,BP JZ M21Y MOV ES:[DI][16D],BL M21Y: MOV BL,CH AND BL,020H MOV CL,5 SHR BL,CL ;----- HANDLE BH = 1 HERE ; ALPHA MODES => NO EFFECT ; GRAPHICS => LOW BIT OF BL = 0 ; PALETTE 0 = BACKGROUND ; PALETTE 1 = GREEN ; PALETTE 2 = RED ; PALETTE 3 = BROWN ; => LOW BIT OF BL = 1 ; PALETTE 0 = BACKGROUND ; PALETTE 1 = CYAN ; PALETTE 2 = MAGENTA ; PALETTE 3 = WHITE ; M20: CMP CRT_MODE,3 JBE M80 MOV AL,CRT_PALETTE AND AL,0DFH AND BL,1 JZ M22 OR AL,020H M22: MOV CRT_PALETTE,AL AND AL,010H OR AL,2 OR BL,AL MOV AH,1 MOV AL,BL CALL PAL_SET OR BP,BP JZ M22Y MOV ES:[DI][1],BL M22Y: INC BL INC BL MOV AH,2 MOV AL,BL CALL PAL_SET OR BP,BP JZ M27Y MOV ES:[DI][2],BL M27Y: INC BL INC BL MOV AH,3 MOV AL,BL CALL PAL_SET OR BP,BP JZ M80 MOV ES:[DI][3],BL M80: CALL PAL_ON JMP V_RET ;;; INCLUDE VDOT.INC SUBTTL VDOT.INC PAGE ;------------------------------------------------ ; ENTRY : ; DX = ROW : ; CX = COLUMN : ; BH = PAGE : ; EXIT : ; BX = OFFSET INTO REGEN : ; AL = BIT MASK FOR COLUMN BYTE : ;------------------------------------------------ DOT_SUP_1 PROC NEAR ;----- OFFSET = PAGE OFFSET + ROW * BYTES/ROW + COLUMN/8 MUL WORD PTR CRT_COLS ; ROW * BYTES/ROW PUSH CX ; SAVE COLUMN VALUE SHR CX,1 ; DIVIDE BY EIGHT TO SHR CX,1 ; DETERMINE THE BYTE THAT SHR CX,1 ; THIS DOT IS IN ; (8 BITS/BYTE) ADD AX,CX ; BYTE OFFSET INTO PAGE MOV BL,BH ; GET PAGE INTO BL SUB BH,BH ; ZERO MOV CX,BX ; COUNT VALUE MOV BX,CRT_LEN ; LENGTH OF ONE PAGE JCXZ DS_2 ; PAGE ZERO DS_3: ADD AX,BX ; BUMP TO NEXT PAGE LOOP DS_3 ; DO FOR THE REST DS_2: POP CX ; RECOVER COLUMN VALUE MOV BX,AX ; REGEN OFFSET AND CL,07H ; SHIFT COUNT FOR BIT MASK MOV AL,080H ; MASK BIT SHR AL,CL ; POSITION MASK BIT RET DOT_SUP_1 ENDP ;-------------------------------------------------------- ; THIS SUBROUTINE DETERMINES THE REGEN BYTE LOCATION : ; OF THE INDICATED ROW COLUMN VALUE IN GRAPHICS MODE. : ; ENTRY -- : ; DX = ROW VALUE (0-199) : ; CX = COLUMN VALUE (0-639) : ; EXIT -- : ; SI = OFFSET INTO REGEN BUFFER FOR BYTE OF INTEREST : ; AH = MASK TO STRIP OFF THE BITS OF INTEREST : ; CL = BITS TO SHIFT TO RIGHT JUSTIFY THE MASK IN AH : ; DH = # BITS IN RESULT : ;-------------------------------------------------------- R3 PROC NEAR PUSH BX ; SAVE BX DURING OPERATION PUSH AX ; WILL SAVE AL DURING OPERATION ;----- DETERMINE 1ST BYTE IN IDICATED ROW BY MULTIPLYING ROW VALUE BY 40 ;----- ( LOW BIT OF ROW DETERMINES EVFN/ODD, 80 BYTES/ROW MOV AL,40 PUSH DX ; SAVE ROW VALUE AND DL,0FEH ; STRIP OFF ODD/EVEN BIT MUL DL ; AX HAS ADDRESS OF 1ST BYTE ; OF INDICATED ROW POP DX ; RECOVER IT TEST DL,1 ; TEST FOR EVEN/ODD JZ R4 ; JUMP IF EVEN ROW ADD AX,2000H ; OFFSET TO LOCATION OF ODD ROWS R4: ; EVEN_ROW MOV SI,AX ; MOVE POINTER TO SI POP AX ; RECOVER AL VALUE MOV DX,CX ; COLUMN VALUE TO DX ;----- DETERMINE GRAPHICS MODE CURRENTLY IN EFFECT ;---------------------------------------------------------------- ; SET UP THE REGISTERS ACCORDING TO THE MODE : ; CH = MASK FOR LOW OF COLUMN ADDRESS ( 7/3 FOR HIGH/MED RES) : ; CL = # OF ADDRESS BITS IN COLUMN VALUE ( 3/2 FOR H/M) : ; BL = MASK TO SELECT BITS FROM POINTED BYTE (80H/C0H FOR H/M) : ; BH = NUMBER OF VALID BITS IN POINTED BYTE ( 1/2 FOR H/M) : ;---------------------------------------------------------------- MOV BX,2C0H MOV CX,302H ; SET PARMS FOR MED RES CMP CRT_MODE,6 JC R5 ; HANDLE IF MED ARES MOV BX,180H MOV CX,703H ; SET PARMS FOR HIGH RES ;----- DETERMINE BIT OFFSET IN BYTE FROM COLUMN MASK R5: AND CH,DL ; ADDRESS OF PEL WITHIN BYTE TO CH ;----- DETERMINE BYTE OFFSET FOR THIS LOCATION IN COLUMN SHR DX,CL ; SHIFT BY CORRECT AMOUNT ADD SI,DX ; INCREMENT THE POINTER MOV DH,BH ; GET THE # OF BITS IN RESULT TO DH ;----- MULTIPLY BH (VALID BITS IN BYTE) BY CH (BIT OFFSET) SUB CL,CL ; ZERO INTO STORAGE LOCATION R6: ROR AL,1 ; LEFT JUSTIFY THE VALUE ; IN AL (FOR WRITE) ADD CL,CH ; ADD IN THE BIT OFFSET VALUE DEC BH ; LOOP CONTROL JNZ R6 ; ON EXIT, CL HAS SHIFT COUNT ; TO RESTORE BITS MOV AH,BL ; GET MASK TO AH SHR AH,CL ; MOVE THE MASK TO CORRECT LOCATION POP BX ; RECOVER REG RET ; RETURN WITH EVERYTHING SET UP R3 ENDP ;---------------------------------------------------------------- ; READ DOT -- WRITE DOT : ; THESE ROUTINES WILL WRITE A DOT, OR READ THE DOT AT : ; THE INDICATED LOCATION : ; ENTRY -- : ; DX = ROW (0-199) (THE ACTUAL VALUE DEPENDS ON THE MODE) : ; CX = COLUMN ( 0-639) ( THE VALUES ARE NOT RANGE CHECKED ) : ; AL = DOT VALUE TO WRITE (1,2 OR 4 BITS DEPENDING ON MODE, : ; REQ'D FOR WRITE DOT ONLY, RIGHT JUSTIFIED) : ; BIT 7 OF AL=1 INDICATES XOR THE VALUE INTO THE LOCATION : ; DS = DATA SEGMENT : ; ES = REGEN SEGMENT : ; : ; EXIT : ; AL = DOT VALUE READ, RIGHT JUSTIFIED, READ ONLY : ;---------------------------------------------------------------- ;----- WRITE DOT AHC: ASSUME DS:ABS0 CMP CRT_MODE,7 JA WRITE_DOT_2 WRITE_DOT PROC NEAR ASSUME DS:ABS0,ES:NOTHING PUSH DX SRLOAD ES,0B800H ;;; MOV DX,0B800H ;;; MOV ES,DX POP DX PUSH AX ; SAVE DOT VALUE PUSH AX ; TWICE CALL R3 ; DETERMINE BYTE POSITION OF THE DOT SHR AL,CL ; SHIFT TO SET UP THE BITS FOR OUTPUT AND AL,AH ; STRIP OFF THE OTHER BITS MOV CL,ES:[SI] ; GET THE CURRENT BYTE POP BX ; RECOVER XOR FLAG TEST BL,80H ; IS IT ON JNZ R2 ; YES, XOR THE DOT NOT AH ; SET THE MASK TO REMOVE THE AND CL,AH ; INDICATED BITS OR AL,CL ; OR IN THE NEW VALUE OF THOSE BITS R1: ; FINISH_DOT MOV ES:[SI],AL ; RESTORE THE BYTE IN MEMORY POP AX JMP V_RET R2: ; XOR_DOT XOR AL,CL ; EXCLUSIVE OR THE DOTS JMP R1 ; FINISH UP THE WRITING WRITE_DOT ENDP WRITE_DOT_2 PROC NEAR CMP CRT_MODE,0FH JB NO_ADJ2 CALL MEM_DET ; BASE CARD JC NO_ADJ2 AND AL,10000101B ; 85H, XOR C2 C0 MASK MOV AH,AL SHL AH,1 ; EXPAND C0 TO C1, C2 TO C3 OR AL,AH ; BUILD ?(80H) + (0,3,C,F) NO_ADJ2: PUSH AX MOV AX,DX ; ROW VALUE CALL DOT_SUP_1 ; BX=OFFSET, AL=BIT MASK MOV DH,3 MOV DL,GRAPH_ADDR ; GRAPHICS CHIP MOV AH,G_BIT_MASK ; BIT MASK REGISTER CALL OUT_DX ; SET BIT MASK PUSH DX SRLOAD ES,0A000H ; REGEN SEGMENT ;;; MOV DX,0A000H ;;; MOV ES,DX POP DX POP AX ; RECOVER COLOR MOV CH,AL ; SAVE COLOR TEST CH,080H ; SEE IF XOR JZ WD_A ; NO XOR MOV AH,G_DATA_ROT ; DO XOR MOV AL,018H ; XOR FUNCTION CALL OUT_DX ; SET THE REGISTER JMP WD_B ; SKIP THE BLANK WD_A: ; BLANK THE DOT MOV DL,SEQ_ADDR ; SEQUENCER MOV AH,S_MAP ; MAP MASK MOV AL,0FFH ; ENABLE ALL MAPS CALL OUT_DX ; SET THE REGISTER MOV AL,ES:[BX] ; LATCH DATA SUB AL,AL ; ZERO MOV ES:[BX],AL ; BLANK THE DOT WD_B: ; SET THE COLOR MAP MASK MOV DL,SEQ_ADDR ; SEQUENCER MOV AH,S_MAP ; MAP MASK REGISTER MOV AL,CH ; COLOR VALUE AND AL,0FH ; VALUES 0-15 CALL OUT_DX ; SET IT MOV AL,ES:[BX] ; LATCH DATA MOV AL,0FFH ; WRITE VALUE MOV ES:[BX],AL ; SET THE DOT ;----- NORMALIZE THE ENVIRONMENT CALL OUT_DX ; ALL MAPS ON MOV DL,GRAPH_ADDR ; GRAPHICS CHIPS MOV AH,G_DATA_ROT ; XOR REGISTER SUB AL,AL ; NORMAL WRITES CALL OUT_DX ; SET IT MOV AH,G_BIT_MASK ; BIT MASK MOV AL,0FFH ; ALL BITS ON CALL OUT_DX ; SET IT JMP V_RET ; WRITE DOT DONE WRITE_DOT_2 ENDP RD_S PROC NEAR ASSUME DS:ABS0 PUSH AX PUSH DX SRLOAD ES,0A000H ;;; MOV DX,0A000H ;;; MOV ES,DX POP DX POP AX MOV AX,DX CALL DOT_SUP_1 MOV CH,7 SUB CH,CL SUB DX,DX MOV AL,0 RET RD_S ENDP RD_1S PROC NEAR MOV CL,CH MOV AH,4 PUSH DX MOV DH,3 MOV DL,GRAPH_ADDR CALL OUT_DX POP DX MOV AH,ES:[BX] SHR AH,CL AND AH,1 RET RD_1S ENDP ;----- READ DOT AHD: ASSUME DS:ABS0 CMP CRT_MODE,7 JA R_1 READ_DOT PROC NEAR ASSUME DS:ABS0,ES:NOTHING PUSH DX SRLOAD ES,0B800H ;;; MOV DX,0B800H ;;; MOV ES,DX POP DX CALL R3 ; DETERMINE BYTE POSITION OF DOT MOV AL,ES:[SI] ; GET THE BYTE AND AL,AH ; MASK OFF THE OTHER BITS IN THE BYTE SHL AL,CL ; LEFT JUSTIFY THE VALUE MOV CL,DH ; GET NUMBER OF BITS IN RESULT ROL AL,CL ; RIGHT JUSTIFY THE RESULT JMP V_RET READ_DOT ENDP R_1: CMP CRT_MODE,0FH JB READ_DOT_2 CALL MEM_DET JC READ_DOT_2 READ_DOT_1 PROC NEAR ; 2 MAPS ASSUME DS:ABS0, ES:NOTHING CALL RD_S CALL RD_1S OR DL,AH SHL AH,1 OR DL,AH MOV AL,2 CALL RD_1S SHL AH,1 SHL AH,1 OR DL,AH SHL AH,1 OR DL,AH MOV AL,DL JMP V_RET READ_DOT_1 ENDP READ_DOT_2 PROC NEAR ; 4 MAPS ASSUME DS:ABS0, ES:NOTHING CALL RD_S RD_2A: CALL RD_1S MOV CL,AL SHL AH,CL OR DL,AH INC AL CMP AL,3 JBE RD_2A MOV AL,DL JMP V_RET READ_DOT_2 ENDP ;------------------------------------------------------------------------ ; WRITE_TTY WRITE TELETYPE TO ACTIVE PAGE : ; THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE VIDEO : ; CARD. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT CURSOR : ; POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION. IF THE : ; CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN IS SET : ; TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW VALUE : ; LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW, FIRST : ; COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE. WHEN : ; THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE NEWLY : ; BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS : ; LINE BEFORE THE SCROLL, IN CHARACTER MODE, IN GRAPHICS MODE, : ; THE 0 COLOR IS USED. : ; ENTRY : ; (AH) = CURRENT CRT MODE : ; (AL) = CHARACTER TO BE WRITTEN : ; NOTE THAT BACK SPACE, CAR RET, BELL AND LINE FEED ARE HANDLED : ; AS COMMANDS RATHER THAN AS DISPLAYABLE GRAPHICS : ; (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A : ; GRAPHICS MODE : ; EXIT : ; ALL REGISTERS SAVED : ;------------------------------------------------------------------------ AHE: ASSUME CS:CODE,DS:ABS0 PUSH AX ; SAVE REGISTERS MOV BH,ACTIVE_PAGE ; GET THE ACTIVE PAGE PUSH BX ; SAVE MOV BL,BH ; GET PAGE TO BL XOR BH,BH ; CLEAR HIGH BYTE SAL BX,1 ; *2 FOR WORD OFFSET MOV DX,[BX + OFFSET CURSOR_POSN] ; CURSOR, ACTIVE PAGE POP BX ; RECOVER ;----- DX NOW HAS THE CURRENT CURSOR POSITION CMP AL,0DH ; IS IT CARRIAGE RETURN JE U9 ; CAR_RET CMP AL,0AH ; IS IT A LINE FEED JE U10 ; LINE_FEED CMP AL,08H ; IS IT A BACKSPACE JE U8 ; BACK_SPACE CMP AL,07H ; IS IT A BELL JE U11 ; BELL ;----- WRITE THE CHAR TO THE SCREEN MOV AH,10 ; WRITE CHAR ONLY MOV CX,1 ; ONLY ONE CHAR INT 10H ; WRITE THE CHAR ;----- POSITION THE CURSOR FOR NEXT CHAR INC DL CMP DL,BYTE PTR CRT_COLS ; TEST FOR COLUMN OVERFLOW JNZ U7 ; SET_CURSOR SUB DL,DL ; COLUMN FOR CURSOR CMP DH,ROWS JNZ U6 ; SET_CURSOR_INC ;----- SCROLL REQUIRED U1: CALL SET_CPOS ; SET THE CURSOR ;----- DETERMINE VALUE TO FILL WITH DURING SCROLL MOV AL,CRT_MODE ; GET THE CURRENT MODE CMP AL,4 JB U2 ; READ-CURSOR SUB BH,BH ; FILL WITH BACKGROUND CMP AL,7 JNE U3 ; SCROLL-UP U2: ; READ-CURSOR MOV AH,8 INT 10H ; READ CHAR/ATTR MOV BH,AH ; STORE IN BH U3: ; SCROLL-UP MOV AX,601H ; SCROLL ONE LINE SUB CX,CX ; UPPER LEFT CORNER MOV DH,ROWS ; LOWER RIGHT ROW MOV DL,BYTE PTR CRT_COLS ; LOWER RIGHT COLUMN DEC DL U4: ; VIDEO-CALL-RETURN INT 10H ; SCROLL UP THE SCREEN U5: ; TTY-RETURN POP AX ; RESTORE THE CHARACTER JMP V_RET ; RETURN TO CALLER U6: ; SET-CURSOR-INC INC DH ; NEXT ROW U7: ; SET-CURSOR MOV AH,2 JMP U4 ; ESTABLISH THE NEW CURSOR ;----- BACK SPACE FOUND U8: OR DL,DL ; ALREADY AT END OF LINE JZ U7 ; SET CURSOR DEC DL ; NO -- JUST MOVE IT BACK JMP U7 ; SET_CURSOR ;----- CARRIAGE RETURN FOUND U9: SUB DL,DL ; MOVE TO FIRST COLUMN JMP U7 ; SET_CURSOR ;----- LINE FEED FOUND U10: CMP DH,ROWS ; BOTTOM OF SCREEN JNE U6 ; YES, SCROLL THE SCREEN JMP U1 ; NO, JUST SET THE CURSOR ;----- BELL FOUND U11: MOV BL,2 ; SET UP COUNT FOR BEEP CALL BEEP ; SOUND THE POD BELL JMP U5 ; TTY_RETURN ;----- CURRENT VIDEO STATE AHF: ASSUME DS:ABS0 MOV AH,BYTE PTR CRT_COLS ; GET NUMBER OF COLUMNS MOV BH,ACTIVE_PAGE MOV AL,INFO AND AL,080H OR AL,CRT_MODE POP DI POP SI POP CX ; DISCARD BX POP CX POP DX POP DS POP ES POP BP IRET SUBTTL PAL_SET PROC NEAR PUSH AX CALL WHAT_BASE CLI VR: IN AL,DX TEST AL,08H ; VERTICAL RETRACE JZ VR POP AX MOV DL,ATTR_WRITE XCHG AL,AH OUT DX,AL XCHG AL,AH OUT DX,AL MOV AL,020H OUT DX,AL STI RET PAL_SET ENDP PAL_ON PROC NEAR CALL PAL_INIT MOV DL,ATTR_WRITE MOV AL,020H OUT DX,AL RET PAL_ON ENDP PAL_INIT PROC NEAR CALL WHAT_BASE IN AL,DX RET PAL_INIT ENDP ;----- SET PALETTE REGISTERS AH10: ASSUME DS:ABS0 TEST INFO,2 JNZ BM_OK ; IN MONOCHROME MODE ;----- HERE THE EGA IS IN A COLOR MODE CMP BYTE PTR ADDR_6845,0B4H JE BM_OUT BM_OK: MOV AH,AL OR AH,AH JNZ BM_1 ;----- SET INDIVIDUAL REGISTER SUB BP,BP LES DI,SAVE_PTR ADD DI,4 LES DI,DWORD PTR ES:[DI] MOV AX,ES OR AX,DI JZ TLO_1 INC BP TLO_1: CALL PAL_INIT MOV AH,BL MOV AL,BH CALL PAL_SET CALL PAL_ON OR BP,BP JZ BM_OUT MOV AL,BH SUB BH,BH ADD DI,BX MOV ES:[DI],AL BM_OUT: JMP V_RET BM_1: DEC AH JNZ BM_2 SUB BP,BP LES DI,SAVE_PTR ADD DI,4 LES DI,DWORD PTR ES:[DI] MOV AX,ES OR AX,DI JZ TLO_2 INC BP TLO_2: ;----- SET OVERSCAN REGISTER CALL PAL_INIT MOV AH,011H MOV AL,BH CALL PAL_SET CALL PAL_ON OR BP,BP JZ BM_OUT ADD DI,011H MOV ES:[DI],BH JMP V_RET BM_2: DEC AH JNZ BM_3 ;----- SET 16 PALETTE REGISTERS AND OVERSCAN REGISTER PUSH DS PUSH ES LES DI,SAVE_PTR ADD DI,4 LES DI,DWORD PTR ES:[DI] ; ES:DI PTR TO PAL SAVE AREA MOV AX,ES OR AX,DI JZ TLO_3 POP DS ; PARAMETER ES PUSH DS MOV SI,DX ; PARAMETER OFFSET MOV CX,17D REP MOVSB TLO_3: POP ES POP DS MOV BX,DX CALL PAL_INIT SUB AH,AH BM_2A: MOV AL,ES:[BX] CALL PAL_SET INC AH INC BX CMP AH,010H JB BM_2A INC AH MOV AL,ES:[BX] CALL PAL_SET CALL PAL_ON JMP V_RET BM_3: DEC AH JNZ BM_4 ;----- TOGGLE INTENSIFY/BLINKING BIT PUSH BX CALL MAKE_BASE ADD BX,010H + LN_4 MOV AL,ES:[BX] POP BX OR BL,BL JNZ BM_6 ;----- ENABLE INTENSIFY AND CRT_MODE_SET,11011111B AND AL,0F7H JMP BM_7 BM_6: DEC BL JNZ BM_7 ;----- ENABLE BLINK OR CRT_MODE_SET,020H OR AL,08H BM_7: MOV AH,P_MODE CALL PAL_SET BM_4: JMP V_RET ;;; INCLUDE VCHGEN.INC SUBTTL VCHGEN.INC PAGE ;------------------------------------------------ ; ENTRY : ; AL = 0 USER SPECIFIED FONT : ; 1 8 X 14 FONT : ; 2 8 X 8 DOUBLE DOT : ; BL = BLOCK TO LOAD : ;------------------------------------------------ CH_GEN: PUSH AX ; SAVE THE INVOLVED REGS PUSH BP PUSH BX PUSH CX PUSH DX PUSH ES ASSUME DS:ABS0 CALL DDS ; SET DATA SEGMENT MOV AL,CRT_MODE ; GET THE CURRENT MODE PUSH AX ; SAVE IT CMP AL,7 ; IS THIS MONOCHROME JE H14 ; MONOCHROME VALUES MOV CRT_MODE,0BH ; COLOR VALUES JMP SHORT H15 ; SKIP H14: MOV CRT_MODE,0CH ; MONOCHROME VALUES H15: CALL SET_REGS CALL DDS ; RESET THE DATA SEGMENT POP AX ; RECOVER OLD MODE VALUE MOV CRT_MODE,AL ; RETURN TO LOW MEMORY POP ES ; RESTORE REGS THAT WERE POP DX ; USED BY THE MODE SET POP CX ; ROUTINES POP BX POP BP POP AX OR AL,AL ; SET FLAGS JZ DO_MAP2 ; USER SPECIFIED FONT PUSH CS ; SET SEGMENT TO POP ES ; THIS MODULE SUB DX,DX ; ZERO OUT START OFFSET MOV CX,0256D ; CHAR COUNT (FULL SET) DEC AL ; WHICH PARAMETER JNZ H7 ; MUST BE ONE MOV BH,014D ; BYTES PER CHARACTER MOV BP,OFFSET CGMN ; 8 X 14 TABLE OFFSET JMP SHORT DO_MAP2 ; STORE IT H7: MOV BH,8 ; 8 X 8 FONT MOV BP,OFFSET CGDDOT ; ROM 8 X 8 DOUBLE DOT ;------------------------------------------------ ; ALPHA CHARACTER GENERATOR LOAD : ; : ; ENTRY : ; ES:BP - POINTER TO TABLE : ; CX - COUNT OF CHARS : ; DX - CHAR COUNT OFFSET INTO MAP 2 : ; BH - BYTES PER CHARACTER : ; BL - MAP 2 BLOCK TO LOAD : ;------------------------------------------------ DO_MAP2: PUSH ES ; FONT TABLE SEGMENT POP DS ; ADDRESSING TO TABLE PUSH DX ; SAVE REGISTER SRLOAD ES,0A000H ; ADDRESSING TO MAP 2 ;;; MOV DX,0A000H ;;; MOV ES,DX POP DX ; RECOVER REGISTER PUSH CX ; MULTIPLY BY 020H SINCE MOV CL,5 ; MAXIMUM BYTES PER SHL DX,CL ; CHARACTER IS 32D=020H POP CX ; RECOVER OR BL,BL ; WHICH 16K BLOCK TO LOAD JZ H3 ; BLOCK ZERO H4: ADD DX,04000H ; INCREMENT TO NEXT BLOCK DEC BL ; ANY MORE JNZ H4 ; DO ANOTHER H3: MOV AL,BH ; BYTES PER CHARACTER SUB AH,AH ; ZERO MOV DI,DX ; OFFSET INTO MAP MOV SI,BP ; OFFSET INTO TABLE JCXZ LD_OVER ; CHARACTER COUNT LD: PUSH CX ; SAVE CHARACTER COUNT MOV CX,AX ; ONE ENTIRE CHARACTER REP MOVSB ; AT A TIME SUB DI,AX ; ADJUST OFFSET ADD DI,020H ; NEXT CHARACTER POSITION POP CX ; RECOVER CHARACTER COUNT LOOP LD ; DO THE REST LD_OVER: RET BRK_1: ASSUME DS:ABS0 CALL DDS ; SET LOW MEMORY SEGMENT MOV POINTS,AX ; GET BYTES/CHARACTER MOV DX,ADDR_6845 ; CRTC REGISTER CMP CRT_MODE,7 JNE H11A MOV AH,C_UNDERLN_LOC ; R14H CALL OUT_DX ; SET THE UNDERLINE LOC H11A: DEC AL ; POINTS - 1 MOV AH,C_MAX_SCAN_LN ; R09H CALL OUT_DX ; SET THE CHARACTER HEIGHT DEC AL ; POINTS - 2 MOV CH,AL ; CURSOR START MOV CL,AL ; CURSOR END INC CL ; ADJUST END MOV AH,1 ; SET C_TYPE BIOS CALL INT 10H ; SET THE CURSOR MOV BL,CRT_MODE ; GET THE CURRENT MODE MOV AX,350D ; MAX SCANS ON SCREEN CMP BL,3 ; 640X200 ALPHA MODES JA H11 ; MUST BE 350 CALL BRST_DET JC H11 MOV AX,200D ; SET FOR 200 H11: CWD ; PREPARE TO DIVIDE DIV POINTS ; MAX ROWS ON SCREEN DEC AX ; ADJUST MOV ROWS,AL ; SAVE ROWS INC AL ; READJUST SUB AH,AH ; CLEAR MUL POINTS ; ROWS*BYTES/CHAR DEC AX ; ADJUST MOV DX,ADDR_6845 ; CRTC ADDRESS MOV AH,C_VRT_DSP_END ; SCANS DISPLAYED CALL OUT_DX ; SET IT MOV AL,ROWS ; GET CHARACTER ROWS INC AL ; ADJUST MUL BYTE PTR CRT_COLS ; ROWS*COLUMNS SHL AX,1 ; *2 FOR ALPHA MODE ADD AX,256D ; SPACE BETWEEN PAGES MOV CRT_LEN,AX ; BYTES PER PAGE CALL PH_5 ; VIDEO ON JMP V_RET ; RETURN TO CALLER ;----- LOADABLE CHARACTER GENERATOR ROUTINES AH11: CMP AL,010H ; CHECK PARAMETER JAE AH11_ALPHA1 ; NEXT STAGE ;----- ALPHA MODE ACTIVITY HERE CMP AL,03H ; RANGE CHECK JAE H1 ; NEXT STAGE CALL CH_GEN ; SET THE CHAR GEN CALL SET_REGS CALL PH_5 ; VIDEO ON ASSUME DS:ABS0 CALL DDS ; SET THE DATA SEGMENT MOV CX,CURSOR_MODE ; GET THE MODE MOV AH,1 ; SET C_TYPE INT 10H ; EMULATE CORRECT CURSOR JMP V_RET ; RETURN TO CALLER ;----- SET THE CHARACTER GENERATOR BLOCK SELECT REGISTER H1: JNE H2 ; NOT IN RANGE MOV DH,3 MOV DL,SEQ_ADDR ; SEQUENCER MOV AX,1 ; AH=S_RESET, AL=1 CALL OUT_DX MOV AH,S_CGEN ; CHAR BLOCK REGISTER MOV AL,BL ; GET THE VALUE CALL OUT_DX ; SET IT MOV AX,3 ; AH=S_RESET, AL=3 CALL OUT_DX H2: JMP V_RET ; RETURN TO CALLER AH11_ALPHA1: ASSUME DS:ABS0 CMP AL,020H JAE AH11_GRAPHICS ;----- ALPHA MODE ACTIVITY HERE SUB AL,010H ; ADJUST TO 0 - N CMP AL,02H ; RANGE CHECK JA H2 ; INVALID CALL PUSH AX ; SAVE PUSH BX CALL CH_GEN ; LOAD THE CHAR GEN CALL SET_REGS POP BX POP AX ; RESTORE MOV AH,AL ; CALLING PARAMETER OR AH,AH ; USER MODE MOV AL,BH JZ H13 ; DO NOT SET BYTES/CHAR MOV AL,8 ; 8 X 8 FONT CMP AH,1 ; IS THIS CALL FOR MONOC JNE H13 ; NO, LEAVE IT AT 8 MOV AL,14D ; MONOC SET H13: SUB AH,AH ; CLEAR UPPER BYTE JMP BRK_1 ; CONTINUE ;----- GRAPHICS MODE ACTIVITY HERE AH11_GRAPHICS: ASSUME DS:ABS0 CMP AL,030H JAE AH11_INFORM SUB AL,020H JNZ F10 ;----- COMPATIBILITY, UPPER HALF GRAPHICS CHARACTER SET ASSUME DS:ABS0 SRLOAD DS,0 ;;; SUB DX,DX ;;; MOV DS,DX CLI MOV WORD PTR EXT_PTR , BP MOV WORD PTR EXT_PTR + 2 , ES STI F11: JMP V_RET F10: ASSUME DS:ABS0 PUSH DX SRLOAD DS,0 ;;; SUB DX,DX ;;; MOV DS,DX POP DX CMP AL,03H ; RANGE CHECK JA F11 DEC AL JZ F19 PUSH CS POP ES DEC AL JNZ F13 MOV CX,14D MOV BP,OFFSET CGMN ; ROM 8 X 14 CHARACTER SET JMP SHORT F19 F13: MOV CX,8 MOV BP,OFFSET CGDDOT ; ROM 8 X 8 DOUBLE DOT F19: CLI MOV WORD PTR GRX_SET , BP MOV WORD PTR GRX_SET + 2 , ES STI ASSUME DS:ABS0 CALL DDS MOV POINTS,CX MOV AL,BL MOV BX,OFFSET RT OR AL,AL JNZ DR_3 MOV AL,DL JMP DR_1 DR_3: CMP AL,3 JBE DR_2 MOV AL,2 DR_2: XLAT CS:RT DR_1: DEC AL MOV ROWS,AL JMP V_RET RT LABEL BYTE DB 00D,14D,25D,43D ;----- INFORMATION RETURN DONE HERE AH11_INFORM: ASSUME DS:ABS0 CMP AL,030H JE F6 F5: JMP V_RET F6: MOV CX,POINTS MOV DL,ROWS CMP BH,7 JA F5 CMP BH,1 JA F7 ASSUME DS:ABS0 PUSH DX SRLOAD DS,0 ;;; SUB DX,DX ;;; MOV DS,DX POP DX OR BH,BH JNZ F9 LES BP,EXT_PTR JMP INFORM_OUT F9: LES BP,GRX_SET JMP INFORM_OUT ;----- HANDLE BH = 2 THRU BH = 5 HERE RETURN ROM TABLE POINTERS F7: ASSUME DS:ABS0 SUB BH,2 MOV BL,BH SUB BH,BH SAL BX,1 ADD BX,OFFSET TBL_5 MOV BP,CS:[BX] PUSH CS POP ES INFORM_OUT: POP DI POP SI POP BX POP AX ; DISCARD SAVED CX POP AX ; DISCARD SAVED DX POP DS POP AX ; DISCARD SAVED ES POP AX ; DISCARD SAVED BP IRET ;----- TABLE OF CHARACTER GENERATOR OFFSETS TBL_5 LABEL WORD DW OFFSET CGMN DW OFFSET CGDDOT DW OFFSET INT_1F_1 DW OFFSET CGMN_FDG SUBTTL ;----- ALTERNATE SELECT AH12: ASSUME DS:ABS0 CMP BL,010H ; RETURN ACTIVE CALL JB ACT_1 JE ACT_3 CMP BL,020H ; ALTERNATE PRINT SCREEN JE ACT_2 JMP V_RET ; INVALID CALL ACT_2: ; NEW PRINT SCREEN SRLOAD DS,0 ;;; SUB DX,DX ;;; MOV DS,DX CLI MOV WORD PTR INT5_PTR, OFFSET PRINT_SCREEN MOV WORD PTR INT5_PTR+2, CS STI JMP V_RET ACT_3: MOV BH,INFO ; LOOKING FOR MONOC BIT AND BH,2 ; ISOLATE SHR BH,1 ; ADJUST MOV AL,INFO ; LOOKING FOR MEMORY AND AL,01100000B ; MEMORY BITS MOV CL,5 ; SHIFT COUNT SHR AL,CL ; ADJUST MEM VALUE MOV BL,AL ; RETURN REGISTER MOV CL,INFO_3 ; FEATURE/SWITCH MOV CH,CL ; DUPLICATE IN CH AND CL,0FH ; MASK OFF SWITCH VALUE SHR CH,1 ; MOVE FEATURE VALUE SHR CH,1 SHR CH,1 SHR CH,1 AND CH,0FH ; MASK IT POP DI POP SI POP DX ; DISCARD BX POP DX ; DISCARD CX POP DX POP DS POP ES POP BP IRET AH12_X: JMP V_RET ; RETURN TO CALLER ACT_1: STR_OUTZ: JMP V_RET ; RETURN TO CALLER ;----- WRITE STRING AH13: CMP AL,04 ; RANGE CHECK JAE STR_OUTZ ; INVALID PARAMETER JCXZ STR_OUTZ PUSH BX ; SAVE REGISTER MOV BL,BH ; GET PAGE TO LOW BYTE SUB BH,BH SAL BX,1 ; *2 FOR WORD OFFSET MOV SI,[BX + OFFSET CURSOR_POSN] ; GET CURSOR POSITION POP BX ; RESTORE PUSH SI ; CURRENT VALUE ON STACK PUSH AX MOV AX,0200H ; SET THE CURSOR POSITION INT 10H POP AX STR_1: PUSH CX PUSH BX PUSH AX XCHG AH,AL MOV AL,ES:[BP] ; GET THE CHAR TO WRITE INC BP CMP AL,0DH ; CARRIAGE RETURN JE STR_CR_LF CMP AL,0AH ; LINE FEED JE STR_CR_LF CMP AL,08H ; BACKSPACE JE STR_CR_LF CMP AL,07H ; BELL JE STR_CR_LF MOV CX,1 ; COUNT OF CHARACTERS CMP AH,2 ; CHECK WHERE ATTR IS JB DO_STR ; NOT IN THE STRING MOV BL,ES:[BP] ; GET THE ATTRIBUTE INC BP ; NEXT ITEM IN STRING DO_STR: MOV AH,09H ; WRITE THE CHAR/ATTR INT 10H INC DL ; NEXT CURSOR POSITION CMP DL,BYTE PTR CRT_COLS ; COLUMN OVERFLOW JB STR_2 ; NOT YET CMP DH,ROWS JNE STR_3 MOV AX,0E0AH INT 10H DEC DH STR_3: INC DH ; NEXT ROW SUB DL,DL ; COLUMN ZERO STR_2: MOV AX,0200H ; SET THE CURSOR INT 10H JMP SHORT STR_4 STR_CR_LF: MOV AH,0EH INT 10H MOV BL,BH SUB BH,BH SAL BX,1 ; *2 FOR WORD OFFSET MOV DX,[BX + OFFSET CURSOR_POSN] ; GET CURSOR POSITION STR_4: POP AX POP BX POP CX LOOP STR_1 POP DX ; RECOVER CURSOR POSITION ; FROM PUSH SI ABOVE CMP AL,1 JE STR_OUT CMP AL,3 JE STR_OUT MOV AX,0200H ; SET CURSOR POSITION INT 10H STR_OUT: ; ALLOW FALL THROUGH V_RET PROC NEAR ; VIDEO BIOS RETURN POP DI POP SI POP BX POP CX POP DX POP DS POP ES POP BP IRET V_RET ENDP COMBO_VIDEO ENDP ;;; INCLUDE VPRSC.INC SUBTTL VPRSC.INC PAGE ;------------------------------------------------------------------------ ; INTERRUPT 5 : ; THIS LOGIC WILL BE INVOKED BY INTERRUPT 05H TO PRINT THE : ; SCREEN. THE CURSOR POSITION AT THE TIME THIS ROUTINE IS INVOKED : ; WILL BE SAVED AND RESTORED UPON COMPLETION. THE ROUTINE IS : ; INTENDED TO RUN WITH INTERRUPTS ENABLED. IF A SUBSEQUENT : ; 'PRINT SCREEN' KEY IS DEPRESSED DURING THE TIME THIS ROUTINE : ; IS PRINTING IT WILL BE IGNORED. : ; ADDRESS 50:0 CONTAINS THE STATUS OF THE PRINT SCREEN: : ; : ; 50:0 =0 EITHER PRINT SCREEN HAS NOT BEEN CALLED : ; OR UPON RETURN FROM A CALL THIS INDICATES : ; A SUCCESSFUL OPERATION. : ; =1 PRINT SCREEN IS IN PROGRESS : ; =255 ERROR ENCOUNTERED DURING PRINTING : ;------------------------------------------------------------------------ ASSUME CS:CODE,DS:ABS0 PRINT_SCREEN PROC FAR STI ; MUST RUN WITH INTS ENABLED PUSH DS ; MUST USE 50:0 FOR DATA PUSH AX ; AREA STORAGE PUSH BX PUSH CX ; USE THIS LATER FOR CURSOR LIMITS PUSH DX ; WILL HOLD CURRENT CURSOR POS CALL DDS CMP STATUS_BYTE,1 ; SEE IF PRINT ALREADY IN PROGRESS JZ EXIT ; JUMP IF PRINT IN PROGRESS MOV STATUS_BYTE,1 ; INDICATE PRINT NOW IN PROGRESS MOV AH,15 ; WILL REQUEST THE CURRENT MODE INT 10H ; [AL]=MODE NOT USED) ; [AH]=NUMBER COLUMNS/LINE ; [BH]=VISUAL PAGE ;---------------------------------------------------------------- ; AT THIS POINT WE KNOW THE COLUMNS/LINE ARE IN : ; [AX] AND THE PAGE IF APPLICABLE IS IN [BH]. THE STACK : ; HAS DS,AX,BX,CX,DX PUSHED. [AL] HAS VIDEO MODE : ;---------------------------------------------------------------- MOV CL,AH ; WILL MAKE USE OF [CX] REG TO MOV CH,ROWS ; CONTROL ROW & COLUMNS INC CH ; ADJUST CALL CRLF ; CAR RETURN LINE FEED ROUTINE PUSH CX ; SAVE SCREEN BOUNDS MOV AH,3 ; WILL NOW READ THE CURSOR. INT 10H ; AND PRESERVE THE POSITION POP CX ; RECALL SCREEN BOUNDS PUSH DX ; RECALL [BH]=VISUAL PAGE XOR DX,DX ; SET CURSOR POSITION TO [0,0] ;---------------------------------------------------------------- ; THE LOOP FROM PRI10 TO THE INSTRUCTION PRIOR TO PRI20 : ; IS THE LOOP TO READ EACH CURSOR POSITION FROM THE : ; SCREEN AND PRINT. : ;---------------------------------------------------------------- PRI10: MOV AH,2 ; TO INDICATE CURSOR SET REQUEST INT 10H ; NEW CURSOR POS ESTABLISHED MOV AH,8 ; TO INDICATE READ CHARACTER INT 10H ; CHARACTER NOW IN [AL] OR AL,AL ; SEE IF VALID CHAR JNZ PRI15 ; JUMP IF VALID CHAR MOV AL,' ' ; MAKE A BLANK PRI15: PUSH DX ; SAVE CURSOR POSITION XOR DX,DX ; INDICATE PRINTER 1 XOR AH,AH ; TO INDICATE PRINT CHAR IN [AL] INT 17H ; PRINT THE CHARACTER POP DX ; RECALL CURSOR POSITION TEST AH,029H ; TEST FOR PRINTER ERROR JNZ ERR10 ; JUMP IF ERROR DETECTED INC DL ; ADVANCE TO NEXT COLUMN CMP CL,DL ; SEE IF AT END OF LINE JNZ PRI10 ; IF NOT PROCEED XOR DL,DL ; BACK TO COLUMN 0 MOV AH,DL ; [AH]=0 PUSH DX ; SAVE NEW CURSOR POSITION CALL CRLF ; LINE FEED CARRIAGE RETURN POP DX ; RECALL CURSOR POSITION INC DH ; ADVANCE TO NEXT LINE CMP CH,DH ; FINISHED? JNZ PRI10 ; IF NOT CONTINUE POP DX ; RECALL CURSOR POSITION MOV AH,2 ; TO INDICATE CURSOR SET REQUEST INT 10H ; CURSOR POSITION RESTORED MOV STATUS_BYTE,0 ; INDICATE FINISHED JMP SHORT EXIT ; EXIT THE ROUTINE ERR10: POP DX ; GET CURSOR POSITION MOV AH,2 ; TO REQUEST CURSOR SET INT 10H ; CURSOR POSITION RESTORED MOV STATUS_BYTE,0FFH ; INDICATE ERROR EXIT: POP DX ; RESTORE ALL THE REGISTERS USED POP CX POP BX POP AX POP DS IRET PRINT_SCREEN ENDP ;------ CARRIAGE RETURN, LINE FEED SUBROUTINE CRLF PROC NEAR XOR DX,DX ; PRINTER 0 XOR AH,AH ; WILL NOW SEND INITIAL CR, LF ; TO PRINTER MOV AL,0DH ; CR INT 17H ; SEND THE LINE FEED XOR AH,AH ; NOW FOR THE CR MOV AL,0AH ; LF INT 17H ; SEND THE CARRIAGE RETURN RET CRLF ENDP SUBTTL CODE ENDS END