;*****************************************************************************
;
;			   TERMINAL I/O ROUTINES
;			     FOR IBM PC VERSION
;			      OF PERFECT CALC
;
; These functions serve as the interface between PerfectCalc and the IBM PC
; to perform the terminal I/O required by PerfectCalc.
;
; Assembled 	using: MASM pcterm pcterm nul.lst nul.crf
;
; Modified By	Reason
;
; 3/3/83   rbw	Altered BDOS to add 200 octal to key codes beginning in null.
;
; 12/13/82 jam	Altered TINIT to use only BDOS calls to determine if color
;		and number of columns.  This fix allows this package to run
;		on IBM PC compatible machines.  NOTE: The routines that are
;		commented out have not been fixed to follow this last
;		alteration.
;
; 11/2/82  jam	Altered PUTCH to turn on reverse video if a CTRL-B is passed
;		and to return to normal video if CTRL-A is passed.
;
; 11/3/82  rbw	Broke up SC_CARR into SC_NL and SC_CARR to perform related
;		functions.  Also added function BDOS to perform keyboard I/O
;		as needed.
;
; 11/3/82  jam	Added SND_BEL to sound a special bell whenever CTRL-G is to
;		be printed instead of the normal offending bell.
;
; 11/5/82  jam	TCLEOS, TCLEOL, TPOSN modified to do nothing
;		if FINFP != 0 (zero)
;
;*****************************************************************************
;
        SUBTTL  IBM DOS ENTRY DEFINITIONS
	PAGE
;
;  LOCATION OF PORTS
;
PORT_B	EQU	61H			;8255 port B addr
TIMER	EQU	40H			;8253 timer port addr
;
;       IBM DOS INTERRUPT CODES
;
VIDEO	EQU	10H			;VIDEO PROCESSOR
I_BDOS  EQU     21H                     ;BIOS INTERRUPT FUNCTION
DIRIO   EQU     06H                     ;DIRECT I/O FROM KEYBOARD
;	
;	VIDEO CONTROL EQUATES
;
BLHI_ATTR EQU	88H			;BLINK AND HI ATTR MASK
BW_SEG	EQU	0B000H			;SEGMENT FOR BW CARD
COLOR_ATTR EQU	77H			;BACKGROUND AND FOREGROUND MASK
COLOR_SEG EQU	0B800H			;SEGMENT FOR COLOR CARD
NORM_ATTR EQU	7H			;NORMAL, BLACK ON WHITE
NORM_BLANK EQU	0720H			;NORMAL BLANK
;
;	EQUATES FOR BELL SOUND
;;			delay -- number of times through main loop
;			pitch -- pitch of sound, usually around 181 to 183
;			note  -- note to play, number from 0 to 65535
;			wait  -- used to determine length of sound
DELAY	EQU	02H			;Amt delay before turning off bell02H
NOTE	EQU	2710H			;Divisor0DACH
PITCH	EQU	0B6H			;Value to set the timer mode register0B6H
WAIT	EQU	2710H			;Amt to wait2710H
;
;	VIDEO INTERRUPTS
;
CURR_STATE EQU	15			;INTERRUPT TO RETURN CURRENT STATE
;
;	CRT CONTROL COMMAND DEFINITIONS
;
CTRLA	EQU	1
CTRLB	EQU	2
ESC     EQU     27
FALSE	EQU	0
TRUE	EQU	1
CR      EQU     13
NL      EQU     10
LF      EQU     10
BS      EQU     8
BELL    EQU     7
DEL     EQU     127
;
;	VARIABLES
;
COLOR	EQU	TINNUL
;
;	CONSOLE PARMS
;
	EXTRN	FINFP:WORD		;IF ZERO, THEN I/O REDIRECTED
	EXTRN	TINNUL:WORD		;0 FOR B&W, 1 FOR COLOR
DGROUP	GROUP	DATA
DATA	SEGMENT WORD PUBLIC 'DATA'
	ASSUME	DS:DGROUP
	PUBLIC	CRTWIDTH
ATTR_FLAG DB	NORM_ATTR  		;ATTRIBUTE BYTE
CRTWIDTH DW	?			;NUMBER OF COLUMNS ON CRT
REV_FLAG DB	FALSE			;TRUE IF TREV CALLED BEFORE TNORM
VIDEO_RAM DW	BW_SEG			;ADDRESS OF VIDEO RAM AREA
DATA	ENDS
;
;
;
PGROUP	GROUP	PROG
;
; Dynamic storage layout for user callable functions from Lattice C
;
DYNS	STRUC
OLD_BP	DW	?			;Caller's BP save
RETN	DW	?			;Return address from call
ARG1	DW	?			;First argument
ARG2	DW	?			;Second argument
DYNS	ENDS
PROG	SEGMENT	BYTE PUBLIC 'PROG'
	ASSUME	CS:PGROUP
;
;=============================================================================
;		EXTERNAL ROUTINES TO BE CALLED FROM C
;=============================================================================
;
        SUBTTL  BDOS CALL
        PAGE
;
; name		BDOS() -- direct BDOS call from C
;
; synopsis	BDOS(function, param);
;
; description	Performs the indicated BDOS function and returns 0-padded AX
;		as its value.  Special handling for two-char keystrokes
;		like IBM PC arrow keys.  Replaces Lattice bdos() call.
;
	PUBLIC	BDOS
BDOS	PROC    NEAR
	PUSH	BP
	MOV	BP,SP
	MOV	AX,[BP].ARG1		;GET FUNCTION NUMBER
	MOV	AH,AL			;PUT FUNCTION NUMBER IN AH
	MOV	DX,[BP].ARG2		;GET PARAMETER
	CMP	AH,6
	JZ	BD_DIO			;WAS DIRECT I/O CALL
	INT	I_BDOS			;DO THE BDOS CALL
BD_EX:	MOV	AH,0			;PAD ANSWER WITH 0
	JMP	BD_EXR
BD_DIO:	INT	I_BDOS			;DO THE DIRECT I/O CALL
	JZ	BD_EX			;NOT READY YET -- RETURN 0
	CMP	AL,0			;ZERO ==> NEED ANOTHER CALL
	JNZ	BD_EX			;NO -- RETURN WHAT YOU GOT
	MOV	AH,7
	INT	I_BDOS			;GET NEXT CHAR OF 2-FUNCTION CODE
	MOV	AH,0			;ADD 0200 TO IT
	OR	AL,80H
BD_EXR:	POP	BP
	RET
BDOS	ENDP
        SUBTTL  ERASE TO END OF LINE
        PAGE
;
; name		TCLEOL -- clear to the end of the line
;
; synopsis	TCLEOL();
;
; description	Clears the line beginning from the cursor position to the end
;		of the line.
;
	PUBLIC	TCLEOL
TCLEOL	PROC    NEAR
	PUSH	BP
	MOV	BP,SP
	CMP	FINFP,0			;CHK IF I/O REDIRECTED
	JNE	SC_ELX			;IF SO, RETURN
        MOV     AH,3                    ;READ CURSOR POSITION
	MOV	BH,0			;PAGE 0
        INT     VIDEO                   ;GET CURSOR POSITION
	MOV	CX,DX			;COPY CURRENT CURSOR
        MOV     AX,CRTWIDTH	        ;GET # COLS,  DS POINTS TO MAIN'S DATA
	MOV	DL,AL			;GET BYTES ON ROW
	DEC	DL			;REDUCE
	CMP	DX,CX			;CHK IF SAME
	JZ	SC_ELX			;IF SO, DONT ERASE
        CALL    VID_CLR                 ;CLEAR SCREEN
SC_ELX:	POP	BP
	RET
TCLEOL	ENDP
        SUBTTL  ERASE TO END OF PAGE
        PAGE
;
; name		TCLEOS -- clear to end of screen
;
; synopsis	TCLEOS();
;
; description	Clears the screen beginning from the cursor position to the
;		end of the screen.
;
	PUBLIC	TCLEOS
TCLEOS	PROC    NEAR
	PUSH	BP
	MOV	BP,SP
	CMP	FINFP,0			;CHK IF I/O REDIRECTED
	JNE	CLEOS_EX		;IF SO, RETURN
        MOV     AH,3                    ;READ CURSOR POSITION
	MOV	BH,0			;PAGE 0
        INT     VIDEO                   ;GET CURSOR POSITION
	MOV	CX,DX			;COPY CURRENT POSITION
	MOV	DX,CRTWIDTH		;GET TOTAL BYTE/ROW
	MOV	DH,24			;LAST ROW
	DEC	DL			;REDUCE COL BY 1
        CALL    VID_CLR                 ;CLEAR SCREEN
CLEOS_EX: POP	BP
        RET
TCLEOS	ENDP
        SUBTTL  SET COLOR
        PAGE
;
; name		TCOLOR -- set color
;
; synopsis	TCOLOR(c);
;
;		int c;  color combination to print characters.
;
; description	Sets the color to display characters.  Nothing is done if
;		the monochrome is being used.  The external COLOR is set to
;		zero if the B & W monochrome is being used, otherwise it is 
;		non-zero.
;
	PUBLIC	TCOLOR
TCOLOR	PROC	NEAR
	PUSH	BP
	MOV	BP,SP
	CMP	COLOR,FALSE		;CHK FOR COLOR DISPLAY
	JE	COLOR_EX		;IF NOT, RETURN
	MOV	AX,[BP].ARG1		;CHANGE COLOR
	MOV	ATTR_FLAG,AL
	CMP	REV_FLAG,TRUE		;CHK IF IN REVERSE MODE
	JNE	COLOR_EX		;IF NOT, RETURN
	CALL	SC_EXCH
COLOR_EX: POP	BP
	RET
TCOLOR	ENDP
COMMENT	|
	***********************************************************
	******** FOLLOWING FUNCTIONS ARE COMMENTED OUT!!!! ********
	***********************************************************
	SUBTTL	DELETE COLUMN AT CURSOR POSITION
	PAGE
;
; name		TDCOL -- delete column at cursor position
;
; synopsis	TDCOL(n,m);
;
;		int n;
;		int m;
;
; description	Deletes n blanks on each line from the cursor for m lines.  The
;		cursor is not moved.
;
	PUBLIC	TDCOL
TDCOL	PROC	NEAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DI			;SAVE THE
	PUSH	ES			;	REGISTERS
	PUSH	SI			;		USED
	MOV	BH,0			;PAGE 0
	MOV	AH,3			;READ CURSOR 
	INT	VIDEO			;	POSITION
	MOV	BX,[BP].ARG1		;SET NUMBER OF CHARS TO INSERT
	MOV	CX,CRTWIDTH		;CALC # TIMES 
	SUB	CL,DL			;	TO SHIFT
	SUB	CL,BL			;		OVER
	CALL	SC_POS
	MOV	DX,AX			;SET TARGET LOCATION
	SAL	BX,1			;CALC SECOND
	ADD	BX,AX			;	LOCATION
	CLD				;FLAG FOR DELETE
	CALL	SC_MOVE
	POP	SI			;RESTORE
	POP	ES			;	THE
	POP	DI			;		REGISTERS
	POP	BP
	RET
TDCOL	ENDP
	SUBTTL	DELETE LINE AT CURSOR
	PAGE
;
; name		TDL -- delete line at the cursor
;
; synopsis	TDL();
;
; description	Deletes the current line, i.e. the line the cursor is on.  The
;		lines following the current line are moved up one line.  The
;		cursor is not moved.
;
	PUBLIC	TDL
TDL	PROC	NEAR
	PUSH	BP
	MOV	BP,SP
	MOV	BH,0			;PAGE 0
	MOV	AH,3			;READ CURSOR
	INT	VIDEO			;	POSITION
	MOV	CX,DX			;SET UPPER LEFT OF SCROLL
	MOV	CL,0			;START AT BEGINNING OF LINE
	MOV	DX,CRTWIDTH		;SET BOTTOM
	DEC	DL			;	RIGHT OF
	MOV	DH,24			;		SCROLL
	MOV	BH,NORM_ATTR		;USE NORMAL ATTRIBUTE
	MOV	AL,1			;NUMBER OF LINES TO DELETE
	MOV	AH,6			;SCROLL ACTIVE
	INT	VIDEO			;	PAGE UP
	POP	BP
	RET
TDL	ENDP
	SUBTTL	INSERT CHARACTER AT CURSOR POSITION
	PAGE
;
; name		TICOL -- insert character at cursor
;
; synopsis	TICOL(n, m);
;
;		int n;
;		int m;
;
; description	Inserts n blanks on each line from the cursor for m lines.  The
;		cursor is not moved.
;
;
	PUBLIC	TICOL
TICOL	PROC	NEAR
	PUSH	BP
	MOV	BP,SP
	PUSH	DI			;SAVE THE
	PUSH	ES			;	REGISTERS
	PUSH	SI			;		USED
	MOV	BH,0			;PAGE 0
	MOV	AH,3			;READ CURSOR 
	INT	VIDEO			;	POSITION
	MOV	BX,[BP].ARG1		;SET NUMBER OF CHARS TO INSERT
	MOV	CX,CRTWIDTH		;CALC # TIMES 
	SUB	CL,DL			;	TO SHIFT
	SUB	CL,BL			;		OVER
	MOV	AX,CRTWIDTH
	MOV	DL,AL			;START AT END OF LINE
	DEC	DL			;	FOR TARGET
	CALL	SC_POS
	MOV	DX,AX			;SET TARGET LOCATION
	SAL	BX,1			;CALC SECOND
	SUB	AX,BX			;	LOCATION
	MOV	BX,AX			;SET SOURCE LOCATION
	STD				;FLAG FOR INSERT
	CALL	SC_MOVE
	POP	SI			;RESTORE
	POP	ES			;	THE
	POP	DI			;		REGISTERS
	POP	BP
	RET
TICOL	ENDP
	SUBTTL	INSERT LINE AT CURSOR
	PAGE
;
; name		TIL -- insert a line at the cursor
;
; synopsis	TIL();
;
; description	Inserts a line where the cursor is, moving the current line
;		and the following lines down one line (or row).  The cursor
;		stays in the same position it was before the call.
;
	PUBLIC	TIL
TIL	PROC	NEAR
	PUSH	BP
	MOV	BP,SP
	MOV	BH,0			;PAGE 0
	MOV	AH,3			;READ CURSOR
	INT	VIDEO			;	POSITION
	MOV	CX,DX			;SET UPPER LEFT OF SCROLL
	MOV	CL,0			;START AT BEGINNING OF LINE
	MOV	DX,CRTWIDTH		;SET BOTTOM
	DEC	DL			;	RIGHT OF
	MOV	DH,24			;		SCROLL
	MOV	BH,NORM_ATTR		;USE NORMAL ATTRIBUTE
	MOV	AL,1			;NUMBER OF LINES TO INSERT
	MOV	AH,7			;SCROLL ACTIVE
	INT	VIDEO			;	PAGE DOWN
	POP	BP
	RET
TIL	ENDP
	***********************************************************
	************** END OF COMMENTED OUT FUNCTIONS *************
	***********************************************************
|
	SUBTTL	SET NORMAL ATTRIBUTES
	PAGE
;
; name		TNORM -- enter reverse video
;
; synopsis	TNORM();
;
; description	Turns the display attribute to normal so that characters
;		displayed using PUTCH are normal.  Just reverses the color
;		combination.
;
; caution	This routine does nothing if TREV was not called before it.
;
	PUBLIC	TNORM
TNORM	PROC	NEAR
	PUSH	BP
	MOV	BP,SP
	CMP	REV_FLAG,FALSE		;CHK IF TREV WAS CALLED
	JE	NORM_EX			;IF NOT, RETURN
	CALL	SC_EXCH
	MOV	REV_FLAG,FALSE		;RESET REVERSE FLAG
NORM_EX: POP	BP
	RET
TNORM	ENDP
        SUBTTL  DIRECT CURSOR ADDRESSING
        PAGE
;
; name		TPOSN -- position the cursor
;
; synopsis	TPOSN(row, col);
;
;		int col;	1 is the first column.
;		int row;	1 is the first row (or line).
;
; description	Positions the cursor to the column and row passed.
;
	PUBLIC	TPOSN	
TPOSN	PROC    NEAR
	PUSH	BP
	MOV	BP,SP
	CMP	FINFP,0			;CHK IF I/O REDIRECTED
	JNE	TPOSN_EX		;IF SO, RETURN
	MOV	AX,[BP].ARG1		;GET ROW ADDRESS
	MOV	DH,AL			;SET THE ROW
	MOV	AX,[BP].ARG2		;GET COL ADDRESS
	MOV	DL,AL			;SET THE COL
	DEC	DH			;DECREMENT ROW
	DEC	DL			;DECREMENT COL
        MOV     AH,2                    ;INDICATE CURSOR POSITION
	MOV	BH,0			;PAGE 0
        INT     VIDEO                   ;USE DOS VIDEO HANDLER
TPOSN_EX: POP	BP
	RET
TPOSN	ENDP
	SUBTTL	PUT CHARACTER ON SCREEN
	PAGE
;
; name		PUTCH -- put character
;
; synopsis	PUTCH(c);
;
;		char c;
;
; description	Outputs the character c on the screen at the cursor position,
;		using the current attribute then moves the cursor to the right
;		one position.  If c is a BELL, BS, CR, ESC, or NL, then the
;		cursor does not move.
;
	PUBLIC	PUTCH
PUTCH	PROC	NEAR
	PUSH	BP
	MOV	BP,SP
	MOV	DX,[BP].ARG1		;LOAD THE CHARACTER TO OUTPUT
	CMP	DL,CTRLA		;Chk for CTRL-A
	JE	PUTNORM			;If so, go to normal video
	CMP	DL,CTRLB		;Chk for CTRL-B
	JE	PUTREV			;If so,turn on reverse video
	CALL	SC_SCH			;PROCESS SPECIAL CHARACTER
PUT_EX:	MOV	AX,[BP].ARG1		;RETURN CHARACTER WRITTEN
	POP	BP
	RET
PUTNORM: CALL	TNORM
	JMP	PUT_EX
PUTREV:	CALL	TREV
	JMP	PUT_EX
PUTCH	ENDP
	SUBTTL	INITIALIZE SCREEN ROUTINES
	PAGE
;
; name		TINIT -- initialize the screen routines
;
; synopsis	TINIT();
;
; description	Initializes the screen routines, i.e. setting the correct
;		base address for the video RAM and CRTWIDTH to the number of 
;		columns for main.  This procedure should be called first,
;		before any of the other video routines.
;
	PUBLIC	TINIT
TINIT	PROC	NEAR
	PUSH	BP
	MOV	BP,SP
	MOV	AH,CURR_STATE			;GET CURRENT STATE OF VIDEO
	INT	VIDEO
	XOR	CX,CX
	MOV	CL,AH				;SET NUMBER COLUMNS ON SCREEN
	MOV	CRTWIDTH,CX
	CMP	AL,1				;CHECK FOR COLOR
	JE	COLORON
	CMP	AL,3				;OTHER COLOR POSSIBILITY
	JE	COLORON				;IF SO, RESET RAM FOR COLOR
	MOV	COLOR,FALSE			;SET FOR B&W
	JMP	TINIT_EX
COLORON: MOV	COLOR,TRUE			;SET FOR COLOR
	MOV	VIDEO_RAM,COLOR_SEG		;ACCESS GRAPHICS VIDEO RAM
TINIT_EX: POP	BP
	RET
TINIT	ENDP
	SUBTTL	DEINITIALIZE SCREEN ROUTINES
	PAGE
;
; name		TDEINIT -- deinitialize screen routines
;
; synopsis	TDEINIT();
;
; description	Homes the cursor then calls TCLEOS to clear the screen
;
	PUBLIC	TDEINIT
TDEINIT	PROC	NEAR
	PUSH	BP
	MOV	BP,SP
	MOV	DH,0			;Home cursor
        MOV     AH,2                    ;INDICATE CURSOR POSITION
	MOV	BH,0			;PAGE 0
        INT     VIDEO                   ;USE DOS VIDEO HANDLER
	MOV	CX,DX			;COPY CURRENT POSITION
	MOV	DX,CRTWIDTH		;GET TOTAL BYTE/ROW
	MOV	DH,25			;LAST ROW
	DEC	DL			;REDUCE COL BY 1
        CALL    VID_CLR                 ;CLEAR SCREEN
	POP	BP
	RET
TDEINIT	ENDP
	SUBTTL	PAD WITH NULLS
	PAGE
;
; name		TPAD -- pad with nulls
;
; synopsis	TPAD();
;
; description	Null routine, required by PerfectCalc.
;
	PUBLIC	TPAD
TPAD	PROC	NEAR
	RET
TPAD	ENDP
	SUBTTL	ENTER REVERSE VIDEO
	PAGE
;
; name		TREV -- enter reverse video
;
; synopsis	TREV();
;
; description	Turns on the reverse video so that any characters sent to
;		PUTCH are displayed in reverse video.
;
; cautions	Any other attributes turned on before using TREV, i.e.
;		blinking, highlight, etc. should be cleared before calling
;		this routine.  Highlighting will become blinking and blinking
;		will become highlighting.
;
	PUBLIC	TREV
TREV	PROC	NEAR
	PUSH	BP
	MOV	BP,SP
	CMP	REV_FLAG,TRUE		;CHK IF REVERSE ALREADY CALLED
	JE	REV_EX			;IF SO, RETURN
	CALL	SC_EXCH
	MOV	REV_FLAG,TRUE		;FLAG FOR REVERSE BEGING CALLED
REV_EX:	POP	BP
	RET		
TREV	ENDP
;
; ============================================================================
; 		      INTERNAL PROCEDURES
; ============================================================================
;
        SUBTTL  BACKSPACE 1 CHARACTER
        PAGE
;
; name		SC_BS -- backspace one character
;
; synopsis	CALL SC_BS
;
; description	Backspaces one character, not across lines.  Deletes one char
;		to the left.
;
SC_BS   PROC    NEAR
        MOV     AH,3                    ;READ CURSOR POSITION
	MOV	BH,0			;PAGE 0
        INT     VIDEO                   ;GET CURSOR
        CMP     DX,0                    ;CHECK IF HOME
        JZ      SC_BSE                  ;IF SO, EXIT
        CMP     DL,0                    ;ELSE CHECK IF COL 0
        JZ      SC_BSE                  ;IF SO, CANT BACKSPACE
	MOV	CX,DX			;COPY
	DEC	CL			;BACK UP 1
	PUSH	CX			;SAVE NEW POSITION
        CALL    VID_CLR                 ;ON SCREEN
	POP	DX			;GET NEW POSITON
	MOV	BH,0			;PAGE 0
        MOV     AH,2                    ;RE-LOCATE
        INT     VIDEO                   ;CURSOR AGAIN
SC_BSE: RET
SC_BS   ENDP
	SUBTTL	PROCESSING CARRIAGE RETURN
	PAGE
;
; name		SC_CARR -- process carriage return
;
; synopsis	CALL SC_CARR
;
; description	Performs the necessary functions to process a carriage return.
;
SC_CARR	PROC	NEAR
	MOV	AH,3			;READ
	MOV	BH,0			;PAGE 0
	INT	VIDEO			;CURRENT CURSOR
	MOV	DL,0			;CLEAR COL NBR
	MOV	AH,2			;UPDATE CURSOR
	MOV	BH,0			;PAGE 0
	INT	VIDEO			;POSITION
	RET
SC_CARR	ENDP
	SUBTTL	PROCESSING NEWLINE
	PAGE
;
; name		SC_NL -- process newline
;
; synopsis	CALL SC_NL
;
; description	Performs the necessary functions to process a newline.
;
SC_NL	PROC	NEAR
	MOV	AH,3			;READ
	MOV	BH,0			;PAGE 0
	INT	VIDEO			;CURRENT CURSOR
	CMP	DH,24			;CHK IF AT END OF PAGE
	JZ	SC_SUP			;IF SO, MUST SCROLL UP
	INC	DH			;ELSE BUMP ROW BY 1
SC_NUP:	MOV	AH,2			;UPDATE CURSOR
	MOV	BH,0			;PAGE 0
	INT	VIDEO			;POSITION
	JMP	SC_NLEX			;GOTO EXIT
SC_SUP: MOV	CX,0			;HOME POSITION
	MOV	DX,CRTWIDTH		;LENGTH OF LINE
	MOV	DH,24			;25TH LINE
	MOV	AL,1 			;SCROLL UP 1 LINE
	MOV	BH,NORM_ATTR		;USE NORMAL ATTRIB
	MOV	AH,6			;SCROLL UP FUNCTION
	INT	VIDEO			;SCROLL UP PAGE
	MOV	DH,24			;LAST ROW
	JMP	SC_NUP			;GOTO UPDATE CURSOR
SC_NLEX: RET
SC_NL	ENDP
	SUBTTL	EXCHANGE BACKGROUNG AND FOREGROUND ATTRIBUTES
	PAGE
;
; name		SC_EXCH -- exchange background and foreground color attributes
;
; synopsis	CALL SC_EXCH
;
; description	Exchanges the background and foreground bits in ATTR_FLAG,
;		leaving the blinking and highlighting bits intact.
;
SC_EXCH	PROC	NEAR
	MOV	AL,BLHI_ATTR		;GET THE
	AND	AL,ATTR_FLAG		;	BLINK AND HI ATTRIBUTES
	MOV	AH,COLOR_ATTR		;GET THE
	AND	AH,ATTR_FLAG		;	COLOR ATTRIBUTES
	MOV	CL,4			;NUMBER OF BITS TO SHIFT
	ROL	AH,CL			;EXCHANGE BACKGROUND AND FOREGROUND
	OR	AH,AL			;RESTORE ORIGINAL BLINK AND HI BITS
	MOV	ATTR_FLAG,AH		;SAVE IT
	RET
SC_EXCH	ENDP
COMMENT	|
	***********************************************************
	******** FOLLOWING FUNCTIONS ARE COMMENTED OUT!!!! ********
	***********************************************************
	SUBTTL	PERFORM MOVE OF COLUMN FOR CX LINES
	PAGE
;
; name		SC_MOVE -- insert/delete characters for CX lines
;
; synopsis	CALL SC_MOVE
;
; description	Inserts or deletes characters between BX and DX for CX
;		lines.  The number of characters to delete must be in COUNT.
;
SC_MOVE	PROC	NEAR
	PUSH	DS
	MOV	AX,CRTWIDTH		;GET NUMBER OF COLUMNS
	SAL	AX,1			;* 2 FOR ATTRIB AND CHAR
	PUSH	AX			;SAVE FOR LINE INCREMENTS
	MOV	AX,VIDEO_RAM		;SET UP TO 
	MOV	DS,AX			;	ACCESS THE
	MOV	ES,AX			;		VIDEO RAM
NEW_LN: MOV	SI,BX			;RESTORE SOURCE LOCATION
	MOV	DI,DX			;RESTORE TARGET LOCATION
	PUSH	CX			;SAVE NUMBER OF CHARS TO SHIFT
	REP	MOVSW
	MOV	AX,NORM_BLANK		;PUT SPACE W/ NORMAL ATTRIBUTE AS FILL
	MOV	CX,[BP].ARG1		;SET NUMBER OF CHARACTERS TO DELETE
	REP	STOSW
	POP	CX			;RESTORE NUMBER OF CHARACTERS TO SHIFT
	POP	AX			;GET AMOUNT TO INCREMENT
	PUSH	AX			;RE-SAVE IT
	ADD	BX,AX			;INCREMENT SOURCE TO NEXT LINE
	ADD	DX,AX			;INCREMENT TARGET TO NEXT LINE
	DEC	[BP].ARG2		;DECREMENT COUNT
	CMP	[BP].ARG2,0		;SEE IF DONE SHIFTING COLUMNS
	JG	NEW_LN			;IF NOT, DO IT AGAIN
	POP	AX			;GET LINE INCREMENT
	POP	DS			;RESTORE DATA SEGMENT
	RET
SC_MOVE	ENDP
	SUBTTL	CALCULATE ADDRESS IN VIDEO BUFFER OF POSITION
	PAGE
;
; name		SC_POS  -- determines address in video RAM of position passed
;
; synopsis	on entry:
;		(DX) = row/col of position, (0,0) is home.
;		on exit:
;		(AX) = address in video RAM of position.
;
; description	Calculates the address of the video RAM that is associated with
;		the posiotion passed in the DX register.  The resulting address
;		is passed in the AX register.
;
SC_POS	PROC	NEAR
	PUSH	BX
	PUSH	DX
	MOV	AX,0			;CLEAR REGISTER
	MOV	AL,DH
	MOV	BX,CRTWIDTH		;MULTIPLY BY
	MUL	BX			;	NUMBER OF COLUMNS
	POP	DX
	PUSH	DX
	MOV	DH,0
	ADD	AX,DX			;ADD COLUMN
	SAL	AX,1			;* 2 FOR ATTRIBUTE
	POP	DX
	POP	BX
	RET
SC_POS	ENDP
	***********************************************************
	************** END OF COMMENTED OUT FUNCTIONS *************
	***********************************************************
|
	SUBTTL	PUT SPECIAL CHARACTER ON SCREEN
	PAGE
;
; name		SC_SCH -- determine character and put on screen
;
; synopsis	on entry:
;		(DL) = character to display
;
; description	Put the character on the screen and, if needed, advance the
;		cursor.
;
SC_SCH	PROC	NEAR
	CMP	DL,0			; CHK IF NULL
	JZ	SCH_EX			;IF SO, DISCARD
        CMP     DL,BS                   ;CHECK IF BACKSPACE
        JNZ     SC_BELL                 ;IF NOT, CHK IF BELL
        CALL    SC_BS                   ;ELSE BACK SPACE
        JMP     SCH_EX                  ;GOTO EXIT
SC_BELL: CMP    DL,BELL                 ;CHECK IF BELL
        JNZ     SC_LF			;IF NOT, CHK IF NL
	CALL	SND_BEL			;SOUND THE BELL
        JMP     SCH_EX                  ;GOTO EXIT
SC_LF:	CMP	DL,NL			;CHK IF NEW LINE
	JZ	SC_NL			;IF SO, PROCESS
SC_CR:	CMP	DL,CR			;CHK IF CR
	JNZ	SC_OUT			;IF NOT, OUTPUT CHARACTER
	CALL	SC_CARR			;ELSE PROCESS
	JMP	SCH_EX			;GOTO EXIT
SC_OUT:	MOV	BH,0			;OUTPUT CHAR, SET CURRENT PAGE
	MOV	BL,ATTR_FLAG		;GET CURRENT ATTRIB
	MOV	CX,1			;NBR OF CHARACTERS
	MOV	AL,DL			;CHAR TO WRITE
	MOV	AH,9			;WRITE CHAR/ATTRIB
	INT	VIDEO			;WRITE
	MOV	AH,3			;READ CURSOR
	MOV	BH,0			;PAGE 0
	INT	VIDEO			;FOR NEXT CHARACTER
	MOV	AX,CRTWIDTH		;LINE LENGTH
	INC	DL			;BUMP COL NBR
	CMP	DL,AL			;CHK IF PASS EOL
	JGE	SCH_EX			;IF AT EOL, LEAVE IT THERE
	MOV	AH,2			;ELSE UPDATE CURSOR
	INT	VIDEO			;POSITION
SCH_EX: RET
SC_SCH	ENDP
	SUBTTL	SOUND BELL
	PAGE
;
; name		SND_BEL
;
; synopsis	CALL SND_BEL
;
; description	Sounds the speaker according to values of EQU's used
;
SND_BEL	PROC	NEAR
	MOV	BX,DELAY		;Set delay count
	MOV	AX,PITCH		;Select TIMER 2,LSB,MSB
	OUT	TIMER+3,AL		;Write the timer mode register
	MOV	AX,NOTE
	OUT	TIMER+2,AL		;Write timer 2 cnt - LSB
	MOV	AL,AH
	OUT	TIMER+2,AL		;Write timer 2 cnt - MSB
	IN	AL,PORT_B		;Get current setting of port
	MOV	AH,AL			;Save the setting
	OR	AL,03			;Turn speaker on
	OUT	PORT_B,AL
	MOV	CX,WAIT			;Set cnt to wait
SOUND:	LOOP	SOUND			;Sound bell for desired length
	DEC	BL			;Chk if delay cnt expired
	JNE	SOUND			;If not, continue beeping speaker
	MOV	AL,AH			;Recover value of port
	OUT	PORT_B,AL
	RET
SND_BEL	ENDP
        SUBTTL  PERFORM VIDEO CLEAR
        PAGE
;
; name		VID_CLR
;
; synopsis	on entry:
;		(CX) = beginning row col
;		(DX) = ending row col
;		CALL VID_CLR
;
; description	Clears the area defined in the boundry by CX and DX.
;
VID_CLR PROC    NEAR
        MOV     BH,NORM_ATTR            ;USE NORMAL ATTRIB
	MOV	AX,600H			;SCROLL W/CLEAR WINDOW
        INT     VIDEO                   ;CLEAR SCREEN
        RET
VID_CLR ENDP
PROG	ENDS
	END
