; Doug's Programming Language  -- DPL, Version 2.22
; Copyright (c) 1988 Douglas S. Cody, All rights reserved.
;----------------------------------------
; V I D W R T  --  Write an ASCIIZ string to the video screen
;
; Entry Conditions:
;	AX holds the function # (see function table below)
;	BX holds the ASCIIZ string offset
;	CX possibly holds the video attribute (only if required)
;	DX possibly holds the starting cursor x,y position (only if required)
; Exit Conditions:
;	Assume AX,BX,CX,DX modified
;	STATUS = 0, good write
;	STATUS = 1, function request out of range
;
SUBPGM	VIDWRT
;
INTEGER	OLD_CURS	; HOLDS THE CURSOR LOCATION BEFORE THE WRITE
INTEGER	RET_ADDR	; HOLDS A SUBROUTINE RETURN ADDRESS
;
	PUBLIC	VIDFLAGS
INTEGER VIDFLAGS	; HOLDS CONTROL FLAGS FOR THE PROPER OUTPUT CONTROL
_FCURS		EQU	0001B	; MOVE THE CURSOR
_FDX		EQU	0010B	; USE DX AS CURSOR ADDR
_FATRB		EQU	0100B	; USE BL FOR ATTRIBUTE
_FSNOW		EQU	1000B	; PERFORM VIDEO HSYNC WAIT
MAXFUNC		EQU	07	; MAX FUNCTION AVAILABLE FOR CALLING PROGRAMS
;
; FUNCTIONS AVAILABLE FOR CALLING PROGRAMS
;
;	CURSOR	CURSOR	ATTRIB
;	MOVED	IN DX	IN BL
;   ----------------------------
;    0	  N	  N	  N	; CURSOR NOT MOVED, USE OLD ATTR
;    1    Y	  N	  N	; CURSOR MOVED, USE OLD ATTR
;    2	  N       Y       N	; CURSOR NOT MOVED, DX HOLDS CURSOR, USE OLD ATTR
;    3	  Y	  Y	  N	; CURSOR MOVE, DX HOLDS CURSOR
;    4	  N	  N	  Y	; CURSOR NOT MOVED, USE NEW ATTR
;    5	  Y	  N	  Y	; CURSOR MOVED, USE NEW ATTR
;    6	  N	  Y	  Y	; CURSOR NOT MOVED, DX HOLDS CURSOR, USE NEW ATTR
;    7	  Y	  Y	  Y	; CURSOR MOVED, DX HOLDS CURSOR, USE NEW ATTR
;
; RESISTER OFFSETS IN THE STACK
;
SBX	EQU	10
SAX	EQU	8
SDI	EQU	6
SSI	EQU	4
SBP	EQU	2
SES	EQU	0
;
; VIDEO HORIZONTAL WAIT ROUTINE
;
WAITSYNC MACRO	VOID
	LOCAL	LAB1,LAB2
	MOV	DX,03DAH		; GET THE VIDEO PORT ADDRESS
	MOV	BL,AL			; WE MUST SAVE THE CHARACTER
	CLI
;
LAB1:
	IN	AL,DX
	SHR	AL,01			; HSYNC IN PROGRESS?
	JC	LAB1			; YES, WAIT TILL STARTED...
;
LAB2:
	IN	AL,DX
	SHR	AL,01			; HSYNC IN PROGRESS?
	JNC	LAB2			; NO, WAIT TILL STARTED...
	MOV	AL,BL			; RESTORE THE CHARACTER QUICKLY...
	ENDM
;
;-----------------------==============================-------------------------
;-----------------------====< START OF EXECUTION >====-------------------------
;-----------------------==============================-------------------------
;
BEGIN	VIDWRT
	MOV	[STATUS],0		; CLEAR THE RETURN STATUS
	XCHG	AX,BX			; USE BX AS AN INDEX
	CMP	BL,00			; CHECK THE RANGE
	JB	VDWT_BAD		; OUT OF RANGE
	CMP	BL,MAXFUNC		; TOO HIGH?
	JA	VDWT_BAD		; YES, EXIT
	CMP	[CRTFLAG],01		; CGA CARD ATTACHED?
	JNZ	VDWT_02			; NO, CONTINUE ON
	OR	BL,_FSNOW		; YES, AVOID THE SNOW
;
VDWT_02:
	MOV	[VIDFLAGS],BX		; SAVE THE CONTROL FLAGS
;
	MOV	BX,CX			; PLACE THE VIDEO ATTRIBUTE IN BL
	CALL	SAVE_REG
;
	MOV	BH,[VIDPAGE]		; GET THE CURRENT VIDEO PAGE
;
	TEST	[VIDFLAGS],_FDX		; USE DX AS CURSOR POSITION?
	JNZ	VDWT_05			; YES, CONTINUE ON...
;
	MOV	AH,03			; NO, GET THE CURRRENT CURSOR LOCATION
	INT	10H			; FROM THE BIOS
;
VDWT_05:
	CALL	CALC_ABS		; CALCULATE THE ABSOLUTE ADDRESS 
;
	MOV	SI,[BP+SAX]		; GET THE STRING OFFSET
;
	TEST	[VIDFLAGS],_FATRB	; SET ATTRIBUTES
	JNZ	VDWT_10			; YES, GO DO IT
	CALL	WRTSA			; PERFORM THE STRING WRITE
	JMP	SHORT VDWT_15		; SKIP NEXT
;
VDWT_10:
	MOV	BX,[BP+SBX]		; GET THE ATTRIBUTE
	CALL	WRTS			; GO WRITE TEXT
;
VDWT_15:
	TEST	[VIDFLAGS],_FCURS	; MOVE THE CURSOR?
	JZ	VDWT_20			; NO, EXIT HOME
	CALL	MOVEC
;
VDWT_20:
	CALL	REST_REG		; RESTORE THE REGISTERS
	RETURN
;
VDWT_BAD:
	MOV	[STATUS],01		; SEND AN ERROR MESSAGE BACK
	RET
;
;
;=====================
;  ROUTINE SECTION
;	LEVEL 1
;=====================
;
;
; C A L C _ A B S  --  CALCULATE THE ABSOLUTE VIDEO RAM LOCATION
;
; Entry conditions:
;	DX hold the row (DH), & column (DL)
; Exit conditions:
;	ES holds the video segment
;	DI holds the video offset
;
CALC_ABS PROC	NEAR
	MOV	[OLD_CURS],DX		; SAVE THE X,Y
	SUB	AH,AH
	MOV	AL,DH			; AX HOLDS THE ROW #
	MOV	BX,0080
	MUL	BL			; AX HOLDS THE MAX LINEAR LESS COLUMN
	SUB	DH,DH
	ADD	DX,AX			; DX HOLDS ADDRESS WITHIN A PAGE
	MOV	AX,800H			; CALC THE PAGE OFFSET
	MOV	BL,[VIDPAGE]
	PUSH	DX			; DO NOT DISTURB...
	MUL	BX
	POP	DX
	ADD	DX,AX			; DX HOLDS THE ABSOLUTE ADDRESS
	MOV	DI,DX			; MOVE TO DESTINATION REGISTER
	SHL	DI,1			; ADJUST FOR ATTRIBUTES
	MOV	AX,0B000H		; MONO SEGMENT
	TEST	[CRTFLAG],01		; MONOCHROME MONITOR?
	JZ	CLCABS_05		; YES, CONTINUE ON...
	MOV	AX,0B800H		; NO, SETUP FOR CGA
;
CLCABS_05:
	MOV	ES,AX
	RETURN

CALC_ABS	ENDP
;
;
; M O V E C  -- MOVE THE CURSOR TO THE END OF THE LINE
;
; Entry conditions:
;	DI points to the absolute screen location
;	AX points to the head of the string
; Exit conditions:
;	Assume AX,BX,CX,DX modified
;
MOVEC	PROC	NEAR
	MOV	AX,1000H	; GET THE PAGE SIZE
	MOV	BL,[VIDPAGE]
	MOV	CL,BL		; SAVE TEMPORARILY
	SUB	BH,BH
	MUL	BX		; AX=STARTING PAGE ADDRESS
	SUB	DI,AX		; DI=INTRA PAGE RAM PTR
	MOV	AX,DI		; AX=DOES NOW...
	SHR	AX,1		; ALLOW FOR ATTRIBUTES
	MOV	BL,80		; GET THE COLUMN SIZE
	DIV	BL		; AL=ROW,AH=COL
	XCHG	AH,AL
	MOV	DX,AX		; DX HOLDS ROW(DH), & COL(DL)
	MOV	AH,02H		; GO MOVE THE CURSOR
	MOV	BH,CL		; GET THE VIDEO PAGE BACK
	INT	10H
	RETURN

MOVEC	ENDP
;
;
; REST_REG  -- RESTORE THE REGISTERS & STACK
;
; Entry conditions:
;	BP holds the stack frame
; Exit conditions:
;	Most registers restored
;
REST_REG PROC	NEAR
	POP	[RET_ADDR]
	POP	ES
	POP	BP
	POP	SI
	POP	DI
	POP	AX
	POP	BX
	JMP	[RET_ADDR]

REST_REG ENDP
;
;
; SAVE_REG  -- SAVE SOME CRITICALS & THE NECESSARY DATA
;
; Entry conditions:
;	None
; Exit conditions:
;	Most registers saved in a stack frame
;
SAVE_REG PROC	NEAR
	POP	[RET_ADDR]
	PUSH	BX		; + 10
	PUSH	AX		; + 8
	PUSH	DI		; + 6
	PUSH	SI		; + 4
	PUSH	BP		; + 2
	PUSH	ES		; + 0
	MOV	BP,SP		; FRAME IT UP...
	JMP	[RET_ADDR]	; & RETURN

SAVE_REG ENDP
;
;
; W R T S  -- WRITE THE STRING & CHANGE ATTRIBUTES
;
; Entry conditions:
;	SI points to the string
;	BL holds the attribute
;	ES:DI point to the screen memory
; Exit Conditions:
;	Assume AX,BX,CX,DX modified
;
WRTS	PROC	NEAR
	MOV	AH,BL			; AH HOLDS THE ATTRIBUTE
	MOV	CX,[VIDFLAGS]		; GET THE BIT FLAGS FOR SPEED
;
WRT05:
	LODSB				; GET THE NEXT CHARACTER
	OR	AL,AL			; DONE?
	JZ	WRTXIT			; YES, EXIT HOME
	TEST	CX,_FSNOW		; CHECK FOR SNOW?
	JZ	WRT10			; NO, JUST WRITE THE DATA
;
	WAITSYNC			; BX & DX ARE MODIFIED HERE
;
WRT10:
	STOSW				; DISPLAY THE BYTES
	STI				; START INTERRUPTS IF DISABLED ABOVE
	JMP	SHORT WRT05		; CONTINUE DISPLAYING
;
WRTXIT:
	RETURN

WRTS	ENDP
;
;
; W R T S A  -- WRITE THE STRING W/O CHANGING ATTRIBUTES
;
; Entry conditions:
;	SI points to the string
;	ES:DI point to the screen memory
; Exit Conditions:
;	Assume AX,BX,CX,DX modified
;
WRTSA	PROC	NEAR
	MOV	CX,[VIDFLAGS]		; GET THE BIT FLAGS FOR SPEED
;
WRTSA05:
	LODSB				; GET THE NEXT CHARACTER
	OR	AL,AL			; DONE?
	JZ	WRTSAXIT		; YES, EXIT HOME
	TEST	CX,_FSNOW		; CHECK FOR SNOW?
	JZ	WRTSA10			; NO, JUST WRITE THE DATA
;
	WAITSYNC			; BX & DX ARE MODIFIED HERE
;
WRTSA10:
	STOSB				; DISPLAY THE TEXT BYTE
	STI				; START INTERRUPTS IF DISABLED ABOVE
	INC	DI			; MOVE PAST THE ATTRIBUTE
	JMP	SHORT WRTSA05		; CONTINUE DISPLAYING
;
WRTSAXIT:
	RETURN

WRTSA	ENDP
;
ENDPGM	VIDWRT
;