view EGABIG.ASM @ 7:ad2c0d320f08 default tip

Moved comments that were shifted down by a line.
author Michal Necasek <mnecasek@yahoo.com>
date Tue, 24 Oct 2023 15:39:00 +0200
parents 5920c9f0ddb6
children
line wrap: on
line source

	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><D><X>		:
;			     1 - MONOC MODE IN EFFECT <3><B><X>		:
;			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	<VALUE>
	IFIDN	<VALUE>,<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 <AH> 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