; ****************************************************************************
; TRDOS386.ASM (TRDOS 386 Kernel) - v2.0.0 - video.s
; ----------------------------------------------------------------------------
; Last Update: 29/04/2016
; ----------------------------------------------------------------------------
; Beginning: 16/01/2016
; ----------------------------------------------------------------------------
; Assembler: NASM version 2.11 (trdos386.s)
; ----------------------------------------------------------------------------
; Turkish Rational DOS
; Operating System Project v2.0 by ERDOGAN TAN (Beginning: 04/01/2016)
;
; Derived from 'Retro UNIX 386 Kernel - v0.2.1.0' source code by Erdogan Tan
; video.inc (13/08/2015)
;
; Derived from 'IBM PC-AT' BIOS source code (1985) 
; ****************************************************************************

; Retro UNIX 386 v1 Kernel - VIDEO.INC
; Last Modification: 13/08/2015
;		  (Video Data is in 'VIDATA.INC')
;
; ///////// VIDEO (CGA) FUNCTIONS ///////////////

; 16/01/2016 (32 bit modifications, TRDOS386 - TRDOS v2.0, video.s)
; INT 32H (TRDOS 386) = INT 10H (IBM PC/AT REAL MODE)

; IBM PC-AT BIOS Source Code
; TITLE VIDEO1 --- 06/10/85  VIDEO DISPLAY BIOS

int10h:
	; 23/03/2016
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	pushfd
	push 	cs
	call 	VIDEO_IO_1
	retn

;--- INT 10 H -------------------------------------------------------------------
; VIDEO_IO									:	
;	THESE ROUTINES PROVIDE THE CRT DISPLAY INTERFACE			:
;	THE FOLLOWING FUNCTIONS ARE PROVIDED:					:
;										:
;    (AH)= 00H	SET MODE (AL) CONTAINS MODE VALUE				:
;		(AL) = 00H  40X25 BW MODE (POWER ON DEFAULT)			:
;		(AL) = 01H  40X25 COLOR						:
;		(AL) = 02H  80X25 BW						:
;		(AL) = 03H  80X25 COLOR						:
;		              GRAPHICS MODES					:
;		(AL) = 04H  320X200 COLOR					:
;		(AL) = 05H  320X200 BW MODE					:
;		(AL) = 06H  640X200 BW MODE					:
;		(AL) = 07H   80X25 MONOCHROME (USED INTERNAL TO VIDEO ONLY)	:
;		*** NOTES -BW MODES OPERATE SAME AS COLOR MODES, BUT COLOR	:
;		           BURST IS NOT ENABLED					:
;		          -CURSOR IS NOT DISPLAYED IN GRAPHICS MODE		:
;    (AH)= 01H	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)= 02H	SET CURSOR POSITION						:
;		(DH,DL) = ROW,COLUMN  (00H,00H) IS UPPER LEFT			:
;		(BH) = A PAGE NUMBER (MUST BE 00H FOR GRAPHICS MODES)		:
;    (AH)= 03H	READ CURSOR POSITION						:
;		(BH) = PAGE NUMBER (MUST BE 00H FOR GRAPHICS MODES)		:
;		ON EXIT (DH,DL) = ROW,COLUMN OF CURRENT CURSOR			:
;		        (CH,CL) = CURSOR MODE CURRENTLY SET			:
;    (AH)= 04H	READ LIGHT PEN POSITION						:
;		ON EXIT:							:
;		(AH) = 00H -- LIGHT PEN SWITCH NOT DOWN/NOT TRIGGERED		:
;		(AH) = 01H -- VALID LIGHT PEN VALUE IN REGISTERS		:
;		        (DH,DL) = ROW,COLUMN OF CHARACTER LP POSITION		:
;		        (CH) = RASTER LINE (0-199)				:
;		        (BX) = PIXEL COLUMN (0-319,639)				:
;    (AH)= 05H	SELECT ACTIVE DISPLAY PAGE (VALID ONLY FOR ALPHA MODES)		:
;		(AL) = NEW PAGE VALUE (0-7 FOR MODES 0&1, 0-3 FOR MODES 2&3)	:
;    (AH)= 06H	SCROLL ACTIVE PAGE UP						:
;		(AL) = NUMBER OF LINES. ( LINES BLANKED AT BOTTOM OF WINDOW )	:
;		        (AL) = 00H 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)= 07H	SCROLL ACTIVE PAGE DOWN						:
;		(AL) = NUMBER OF LINES, INPUT LINES BLANKED AT TOP OF WINDOW	:
;		        (AL) = 00H 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)= 08H	READ ATTRIBUTE/CHARACTER AT CURRENT CURSOR POSITION		:
;		(BH) = DISPLAY PAGE (VALID FOR ALPHA MODES ONLY)		:
;		ON EXIT:							:
;		(AL) = CHAR READ						:
;		(AH) = ATTRIBUTE OF CHARACTER READ (ALPHA MODES ONLY)		:
;    (AH)= 09H	WRITE ATTRIBUTE/CHARACTER AT CURRENT CURSOR POSITION		:
;		(BH) = DISPLAY PAGE (VALID FOR ALPHA MODES ONLY)		:
;		(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) = 0AH	WRITE CHARACTER ONLY AT CURRENT CURSOR POSITION			:
;		(BH) = DISPLAY PAGE (VALID FOR ALPHA MODES ONLY)		:
;		(CX) = COUNT OF CHARACTERS TO WRITE				:
;		(AL) = CHAR TO WRITE						:
;		       NOTE: USE FUNCTION (AH)= 09H IN GRAPHICS MODES		:
;	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 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)= 0BH	SET COLOR PALETTE						:
;		(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)/YELLOW(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)= 0CH	WRITE DOT							:
;		(DX) = ROW NUMBER						:
;		(CX) = COLUMN NUMBER						:
;		(AL) = COLOR VALUE						:
;		        IF BIT 7 OF AL = 1, THEN THE COLOR VALUE IS EXCLUSIVE	:
;		        ORed WITH THE CURRENT CONTENTS OF THE DOT		:
;    (AH)= ODH	READ DOT							:
;		(DX) = ROW NUMBER						:
;		(CX) = COLUMN NUMBER						:
;		(AL) = RETURNS THE DOT READ					:
;										:
;    ASCII TELETYPE ROUTINE FOR OUTPUT						:
;										:
;    (AH)= 0EH	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)= 0FH	CURRENT VIDEO STATE						:
;		RETURNS THE CURRENT VIDEO STATE					:
;		(AL) = MODE CURRENTLY SET ( SEE (AH)=00H FOR EXPLANATION)	:
;		(AH) = NUMBER OR CHARACTER COLUMNS ON SCREEN			:
;		(BH) = CURRENT ACTIVE DISPLAY PAGE				:
;    (AH)= 10H	RESERVED							:
;    (AH)= 11H	RESERVED							:
;    (AH)= 12H	RESERVED							:
;    (AH)= 13H	WRITE STRING							:
;			ES:BP  -  POINTER T0 STRING TO BE WRITTEN		:
;			CX     -  LENGTH OF CHARACTER STRING TO WRITTEN		:
;			DX     -  CURSOR POSITION FOR STRING TO BE WRITTEN	:
;			BH     -  PAGE NUMBER					:
;		(AL)= 00H	WRITE CHARACTER STRING				:
;			BL     -  ATTRIBUTE					:
;			STRING IS  <CHAR,CHAR, ... ,CHAR>			:
;			CURSOR NOT MOVED					:
;		(AL)= 01H	WRITE CHARACTER STRING AND MOVE CURSOR		:
;			BL     -  ATTRIBUTE					:
;			STRING IS  <CHAR,CHAR, ... ,CHAR>			:
;			CURSOR MOVED						:
;		(AL)= 02H	WRITE CHARACTER AND ATTRIBUTE STRING		:
;			       (VALID FOR ALPHA MODES ONLY)			:
;			STRING IS <CHAR,ATTR,CHAR,ATTR ..  ,CHAR,ATTR>		:
;			CURSOR IS NOT MOVED					:
;		(AL)= 03H WRITE CHARACTER AND ATTRIBUTE STRING AND MOVE CURSOR	:
;			       (VALID FOR ALPHA MODES ONLY)			:
;			STRING IS <CHAR,ATTR,CHAR,ATTR ..  ,CHAR,ATTR>		:
;			CURSOR IS MOVED						:
;		 NOTE:  CARRIAGE RETURN, LINE FEED, BACKSPACE, AND BELL ARE	:
;		        TREATED AS COMMANDS RATHER THAN PRINTABLE CHARACTERS.	:
;										:
;	BX,CX,DX,SI,DI,BP,SP,DS,ES,SS PRESERVED DURING CALLS EXCEPT FOR		:
;	BX,CX,DX RETURN VALUES ON FUNCTIONS 03H,04H,0DH AND 0FH. ON ALL CALLS	:
;	AX IS MODIFIED.								:
;--------------------------------------------------------------------------------

M1:	dd	SET_MODE	; TABLE OF ROUTINES WITHIN VIDEO I/O
	dd	SET_CTYPE
	dd	SET_CPOS
	dd	READ_CURSOR
	dd	VIDEO_RETURN	; READ_LPEN
	dd	ACT_DISP_PAGE
	dd	SCROLL_UP
	dd	SCROLL_DOWN
	dd	READ_AC_CURRENT
	dd	WRITE_AC_CURRENT
	dd	WRITE_C_CURRENT
	dd	VIDEO_RETURN	; SET_COLOR
	dd	VIDEO_RETURN	; WRITE_DOT
	dd	VIDEO_RETURN	; READ_DOT
	dd	WRITE_TTY
	dd	VIDEO_STATE
	dd	VIDEO_RETURN	; RESERVED
	dd	VIDEO_RETURN	; RESERVED
	dd	VIDEO_RETURN	; RESERVED
	dd	VIDEO_RETURN	; WRITE_STRING
M1L	EQU	$ - M1

; 29/04/2016 - TRDOS 386 (TRDOS v2.0)
int31h:  ; Video BIOS

VIDEO_IO_1:
	sti				; INTERRUPTS BACK ON
	cld				; SET DIRECTION FORWARD
	cmp	ah, M1L/4		; TEST FOR WITHIN TABLE RANGE
	jnb	short M4		; BRANCH TO EXIT IF NOT A VALID COMMAND

	push	es
	push	ds			; SAVE WORK AND PARAMETER REGISTERS
	push	edx
	push	ecx
	push	ebx
	push	esi
	push	edi
	push	ebp
	mov	si, KDATA 		; POINT DS: TO DATA SEGMENT
	mov	ds, si
	mov	es, si
	mov	edi, 0B8000h		; GET offset FOR COLOR CARD
	; 23/03/2016
	shl	ah, 2  ; dword		; TIMES 2 FOR WORD TABLE LOOKUP
	movzx	esi, ah			; MOVE OFFSET INTO LOOK UP REGISTER (SI)
	;mov	ah, [CRT_MODE]		; MOVE CURRENT MODE INTO (AH) REGISTER

	JMP	dword [esi+M1]		; GO TO SELECTED FUNCTION

M4:					;	COMMAND NOT VALID
	iret				; DO NOTHING IF NOT IN VALID RANGE


; 02/09/2014 (Retro UNIX 386 v1)
;
; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS

set_mode_3:  	; will be called from 'write_tty' 
	push	ebx
	push	edx
	push	eax
	push	edi
	push	ecx
	call	set_txt_mode
	pop	ecx
	pop	edi
	pop	eax
	pop	edx
	pop	ebx
	retn

VIDEO_STATE:
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)

;---------------------------------------------------
; VIDEO STATE
;  RETURNS THE CURRENT VIDEO STATE IN AX
;  AH = NUMBER OF COLUMNS ON THE SCREEN
;  AL = CURRENT VIDEO MODE
;  BH = CURRENT ACTIVE PAGE
;---------------------------------------------------

	;mov	ah, [CRT_COLS]	; GET NUMBER OF COLUMNS
	mov	ah, 80h
	mov	al, [CRT_MODE]	; CURRENT MODE
	;movzx	esi, al
	;mov	ah, [esi+M6] 
	; BL = active page (not BH!)
	mov	bl, [ACTIVE_PAGE] ; GET CURRENT ACTIVE PAGE
	pop	ebp		; RECOVER REGISTERS
	pop	edi
	pop	esi
	pop	ecx	; DISCARD SAVED BX
	jmp	short M15	; RETURN TO CALLER

SET_MODE:
	; For 32 bit TRDOS and Retro UNIX 386:
	;	valid video mode: 03h only!
	;	(VGA modes will be selected with another routine)
	;
	; set_txt_mode ; 80*25 (16 fore colors, 8 back colors)

;------------------------------------------------------
; SET MODE					      :
;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
; INPUT						      :
;	(AL) - MODE SELECTED (RANGE 0-7)	      :
; OUTPUT					      :
;	NONE					      :
;------------------------------------------------------

	call	set_txt_mode

; 16/01/2016 (TRDOS 386 = TRDOS v2.0)

;-----	NORMAL RETURN FROM ALL VIDEO RETURNS

VIDEO_RETURN:
	pop	ebp
	pop	edi
	pop	esi
	pop	ebx
M15:			; VIDEO_RETURN_C
	pop	ecx
	pop	edx
	pop	ds
	pop	es	; RECOVER SEGMENTS
	iret		; ALL DONE

; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
set_txt_mode:
	;mov	dx, 03D4h 	; address of color card
	mov	al, 3
;M8:
	mov	[CRT_MODE], al  ; save mode in global variable
	mov	al, 29h
	;mov	[CRT_MODE_SET], al ; save the mode set value
	and	al, 037h	; video off, save high resolution bit	
	;push	dx  		; save port value
	;add	dx, 4		; point to control register
	mov	dx, 3D8h
	out	dx, al		; reset video to off to suppress rolling
	;pop	dx
;M9:
	mov	ebx, video_params ; initialization table
	mov	ax, [ebx+10]      ; get the cursor mode from the table	
	xchg 	ah, al
	mov	[CURSOR_MODE], ax ; save cursor mode
	xor	ah, ah		  ; ah is register number during loop 
	
;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
	mov	ecx, 16 ; 16/01/2016
M10:			;  initialization loop
	mov	al, ah 	; get 6845 register number
	out	dx, al
	inc	dx      ; point to data port
	inc	ah	; next register value
	mov	al, [ebx] ; get table value
	out	dx, al	; out to chip
	inc	ebx	; next in table
	dec	dx	; back to pointer register
	loop	M10	; do the whole table

;-----	FILL REGEN AREA WITH BLANK
	;xor	ax, ax  
	;mov	[CRT_START], ax  ; start address saved in global
	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
	;mov	ecx, 8192 ; number of words in color card
	; black background, light gray characeter color, space character
	;mov	ax, 0720h ; fill char for alpha - attribute
;M13:			  ; clear buffer
	;add	edi, 0B8000h ; [crt_base]
	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS

;-----	ENABLE VIDEO AND CORRECT PORT SETTING
	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
			 ; prepare to output to video enable port
	;add	dx,4	 ; point to the mode control gerister
	mov	dx, 3D8h
	;mov	al, [CRT_MODE_SET] ; get the mode set value
	mov	al, 29h
	out	dx, al	 ; set video enable port

;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
	;
	;mov	byte [CRT_COLS], 80h ; initialize number of columns count
	;
;-----	SET CURSOR POSITIONS
	;mov	word [CRT_LEN], 80*25*2
	mov	edi, CURSOR_POSN
	mov	ecx, 4	; clear all cursor positions (16 bytes)
	xor	eax, eax
	rep 	stosd	; fill with zeroes

;-----	SET UP OVERSCAN REGISTER
	inc	dx	; set overscan port to a default
	mov	al, 30h	; 30H value for all modes except 640X200 bw
;M14:
	out	dx, al	; output the correct value to 3D9 port
	;mov	[CRT_PALETTE], al ; save the value for future use

;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
	retn

SET_CTYPE:
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	call	_set_ctype
	jmp	short VIDEO_RETURN

_set_ctype:
	; 02/09/2014 (Retro UNIX 386 v1)
	;
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS

	; (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

;------------------------------------------------
; SET_CTYPE
;	THIS ROUTINE SETS THE CURSOR VALUE
; INPUT
;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
; OUTPUT	
;	NONE
;------------------------------------------------

	mov	ah, 10	; 6845 register for cursor set
	mov	[CURSOR_MODE], cx ; save in data area
	;call	m16	; output cx register
	;retn
        jmp     m16

SET_CPOS:
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	call	_set_cpos
	jmp	short VIDEO_RETURN

READ_CURSOR:
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	;
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS

;------------------------------------------------------
; READ_CURSOR
;	THIS ROUTINE READS THE CURRENT CURSOR VALUE FROM THE
;	845, FORMATS IT, AND SENDS IT BACK TO THE CALLER
; INPUT
;	BH - PAGE OF CURSOR
; OUTPUT
;	DX - ROW, COLUMN OF THE CURRENT CURSOR POSITION
;	CX - CURRENT CURSOR MODE
;------------------------------------------------------

	; BL = Video page number (0 to 7)
	

	call	get_cpos
	movzx	ecx, word [CURSOR_MODE]

	pop	ebp
	pop	edi
	pop	esi
	pop	ebx
	pop	eax	; DISCARD SAVED CX AND DX
	pop	eax
	pop	ds
	pop	es
	iret

get_cpos:
	; 16/01/2016
	; BL = Video page number (0 to 7)
	;
	shl	bl, 1 ; WORD OFFSET
	movzx	esi, bl 
	movzx	edx, word [esi+CURSOR_POSN]
	retn

ACT_DISP_PAGE:
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	;
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
	;
;-----------------------------------------------------
; ACT_DISP_PAGE
;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
; INPUT
;	AL HAS THE NEW ACTIVE DISPLAY PAGE
; OUTPUT
;	THE 6845 IS RESET TO DISPLAY THAT PAGE
;-----------------------------------------------------

	call	set_active_page
        jmp     VIDEO_RETURN

set_active_page:   ; tty_sw
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 30/06/2015
	; 04/03/2014  (act_disp_page --> tty_sw)
	; 10/12/2013
	; 04/12/2013
	;
	mov	[ACTIVE_PAGE], al ; save active page value ; [ptty]
	;mov	cx, [CRT_LEN] ; get saved length of regen buffer
	mov	cx, 25*80*2
	; 27/06/2015
	movzx	ebx, al
	;
	cbw	; 07/09/2014 (ah=0)
	mul 	cx	; display page times regen length
	; 10/12/2013
	mov	[CRT_START], ax ; save start address for later
	mov	cx, ax ; start address to cx
	;sar	cx, 1
	shr	cx, 1	; divide by 2 for 6845 handling
	mov	ah, 12	; 6845 register for start address
	call	m16
	;sal	bx, 1
	; 01/09/2014
	shl	bl, 1	; *2 for word offset
	add	ebx, CURSOR_POSN
	mov	dx, [ebx] ; get cursor for this page
	; 16/01/2016
	;call	m18
	;retn
	jmp	m18

position:
	; 27/06/2015
	; 02/09/2014
	; 30/08/2014 (Retro UNIX 386 v1)
	; 04/12/2013 (Retro UNIX 8086 v1)
	;
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
	;
;-----------------------------------------
; 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
;-----------------------------------------

		; DX = ROW, COLUMN POSITION
	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
	xor	eax, eax ; 02/09/2014
	mov	al, 80   ; determine bytes to row	
	mul	dh	 ; row value
	xor	dh, dh   ; 0	
	add	ax, dx	 ; add column value to the result
	shl	ax, 1	; * 2 for attribute bytes
		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
	retn

find_position:
	; 27/06/2015
	; 07/09/2014
	; 02/09/2014
	; 30/08/2014 (Retro UNIX 386 v1)
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
	mov	esi, ecx
	shl	si, 1
	mov	dx, [esi + CURSOR_POSN]
	jz	short p21
	xor	si, si
p20:
	;add	si, [CRT_LEN]
	add	si, 80*25*2 ; add length of buffer for one page		
	loop	p20
p21:
	and	dx, dx
	jz	short p22
	call 	position ; determine location in regen in page
	add	esi, eax ; add location to start of regen page
p22:	
	;mov	dx, [addr_6845] ; get base address of active display			
	;mov	dx, 03D4h ; I/O address of color card
	;add	dx, 6	; point at status port
	mov	dx, 03DAh ; status port
	; cx = 0
	retn

SCROLL_UP:
	; 30/01/2016
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 07/09/2014
	; 02/09/2014
	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
	; 04/04/2014
	; 04/12/2013
	;
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
	;
;----------------------------------------------
; 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
;--------------------------------------------

	call	_scroll_up
        jmp     VIDEO_RETURN

_scroll_up:  ; from 'write_tty'
	;
	; ((ah = 3))
	; cl = left upper column
	; ch = left upper row
	; dl = right lower column
	; dh = right lower row
	;
	; al = line count 
	; ah = attribute to be used on blanked line	
	; bl = video page number (0 to 7)
	; 

	call	test_line_count ; 16/01/2016

	;mov	bh, [CRT_MODE] ; current video mode	
	;cmp	bh, 4
 	;jb	short n1

	;cmp	bh, 7 ; TEST FOR BW CARD
	;jne	GRAPHICS_UP
n1:
	xor	bh, bh	; 0
	push	ax ; *
	;mov 	esi, [CRT_BASE]
        mov     esi, 0B8000h  
        cmp     bl, [ACTIVE_PAGE]
	jne	short n2
	;
        mov     ax, [CRT_START]
        add     si, ax
        jmp     short n4
n2:
        and     bl, bl
	jz	short n4
	mov	al, bl
n3:
        ;add    si, [CRT_LEN]
        ;add    esi, 80*25*2 
        add     si, 80*25*2
        dec	al
	jnz	short n3
n4:	
	call	scroll_position ; 16/01/2016
        jz      short n6 

        add     esi, ecx ; from address for scroll
	mov	bh, dh  ; #rows in block
	sub	bh, al	; #rows to be moved
n5:
	call	n10 ; 16/01/2016
	
        ;mov    cl, [CRT_COLS] 
	;add	cl, cl
        ;mov    ecx, 80*2
        mov     cx, 80*2
        add     esi, ecx  ; next line
        add     edi, ecx
	dec	bh	 ; count of lines to move
	jnz	short n5 ; row loop
	; bh = 0
	mov	dh, al	 ; #rows	
n6:
	; attribute in ah
	mov	al, ' '	 ; fill with blanks
n7:
	call	n11 ; 16/01/2016

	;mov	cl, [CRT_COLS]
	;add	cl, cl
        ;mov    ecx, 80*2
        mov	cx, 80*2
        add     edi, ecx
	dec	dh
	jnz	short n7
	;
	cmp	bl, [ACTIVE_PAGE]
	jne	short n8
	;mov	al, [CRT_MODE_SET] ; get the value of mode set
	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3	
	mov	dx, 03D8h ; always set color card port
	out	dx, al
n8:
	retn


test_line_count:
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 07/09/2014 (scroll_up)
	or	al, al
	jz	short al_set
	mov	bh, dh	; subtract lower row from upper row
	sub	bh, ch
	inc	bh	; adjust difference by 1
	cmp	bh, al 	; line count = amount of rows in window?
	jne	short al_set ; if not the we're all set
	xor	al, al	; otherwise set al to zero
al_set:
	retn

scroll_position:
	; 30/01/2016
        ; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 07/09/2014 (scroll_up)

	push	dx
	mov	dx, cx	; now, upper left position in DX
	call	position
	add	esi, eax
	mov	edi, esi
	pop	dx	; lower right position in DX
	sub	dx, cx
	inc	dh	; dh = #rows 
	inc	dl	; dl = #cols in block
	pop	ecx 	; return address
	pop	ax	; * ; al = line count, ah = attribute
	push	ecx	; return address
	movzx	ecx, ax
	;mov	ah, [CRT_COLS]
	mov	ah, 80
	mul	ah	; determine offset to from address
	add	ax, ax  ; *2 for attribute byte
	;
	push	ax	; offset 
	push	dx
	;
	; 04/04/2014
	mov	dx, 3DAh ; guaranteed to be color card here	
n9:                      ; wait_display_enable
        in      al, dx   ; get port
	test	al, RVRT ; wait for vertical retrace	
	jz	short n9 ; wait_display_enable
	mov	al, 25h
	mov	dl, 0D8h ; address control port
	out	dx, al	; turn off video during vertical retrace
	pop	dx	; #rows, #cols
       	pop	ax	; offset
	xchg	ax, cx	; 
	; ecx = offset, al = line count, ah = attribute
	;
	or	al, al
	retn

n10:
	; Move rows
	mov	cl, dl	; get # of cols to move
	push	esi
	push	edi	; save start address
n10r:
	movsw		; move that line on screen
	dec	cl
        jnz     short n10r
	pop	edi
	pop	esi	; recover addresses
	retn
n11:
	; Clear rows
                ; dh =  #rows
        mov	cl, dl	; get # of cols to clear
        push    edi     ; save address
n11r:
        stosw           ; store fill character
	dec	cl
        jnz     short n11r
        pop     edi     ; recover address
	retn

SCROLL_DOWN:
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	;
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS

;------------------------------------------
; 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 RECION
;	(DX) = LOWER RIGHT CORNER OF REGION
;	(BH) = FILL CHARACTER
;	(DS) = DATA SEGMENT
;	(ES) = REGEN SEGMENT
; OUTPUT
;	NONE -- SCREEN IS SCROLLED
;------------------------------------------

	; ((ah = 3))
	; cl = left upper column
	; ch = left upper row
	; dl = right lower column
	; dh = right lower row
	;
	; al = line count 
	; ah = attribute to be used on blanked line	
	; bl = video page number (0 to 7)
	; 

	; !!!!
	std		; DIRECTION FOR SCROLL DOWN
	; !!!!
	call	test_line_count ; 16/01/2016
	
	;mov	bh, [CRT_MODE] ; current video mode
	;cmp	bh, 4
 	;jb	short n12

	;cmp	bh, 7 ; TEST FOR BW CARD
	;jne	GRAPHICS_DOWN

n12:			; CONTINUE_DOWN
	push	ax	; * ; save attribute in ah
	mov	ax, dx	; LOWER RIGHT CORNER
	call	scroll_position	; GET REGEN LOCATION
	jz	short n14
	sub	esi, ecx  ; SI IS FROM ADDRESS
	mov	bh, dh  ; #rows in block
	sub	bh, al	; #rows to be moved
n13:
	call	n10	; MOVE ONE ROW

	;mov    cl, [CRT_COLS] 
	;add	cl, cl
        ;mov    ecx, 80*2
        mov     cx, 80*2
        sub     esi, ecx  ; next line
        sub     edi, ecx
	dec	bh	 ; count of lines to move
	jnz	short n13 ; row loop
	; bh = 0
	mov	dh, al	 ; #rows
n14:
	; attribute in ah
	mov	al, ' '	 ; fill with blanks
n15:
	call	n11 ; 16/01/2016

	;mov	cl, [CRT_COLS]
	;add	cl, cl
        ;mov    ecx, 80*2
        mov	cl, 80*2
        sub     edi, ecx
	dec	dh
	jnz	short n15
	;
	cmp	bl, [ACTIVE_PAGE]
	jne	short n16
	;mov	al, [CRT_MODE_SET] ; get the value of mode set
	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3	
	mov	dx, 03D8h ; always set color card port
	out	dx, al
n16:
	; !!!!
	cld		; Clear direction flag !
	; !!!!
	retn

READ_AC_CURRENT:
	; 18/01/2016
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	;
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
	;

	call	_read_ac_current
        jmp     VIDEO_RETURN

;------------------------------------------------------------------------
; 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) = CHARACTER READ						:
;	(AH) = ATTRIBUTE READ						:
;------------------------------------------------------------------------

_read_ac_current: ; 18/01/2016

p10:
	call	find_position	; GET REGEN LOCATION AND PORT ADDRESS
	;
	; esi = regen location
	; dx = status port
	;
	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
	;
p11:			; wait for horizontal retrace is low or vertical
	sti		; enable interrupts first
        cmp     bl, [ACTIVE_PAGE]
	jne	short p14 
	cli 		; block interrupts for single loop
	in	al, dx	; get status from the adapter
	test	al, RHRZ ; is horizontal retrace low
	jnz	short p11 ; wait until it is
p12:			;  wait for either retrace high
	in	al, dx ; get status again
	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
	jz	short p12 ; wait until either retrace active
	sti
p14:
	add	esi, 0B8000h 
	mov	ax, [esi]

	retn	; 18/01/2016


WRITE_AC_CURRENT:
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	;
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
	;
;----------------------------------------------------------------
; WRITE_AC_CURRENT						:
;	THTS 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							:
;	DISPLAY REGEN BUFFER UPDATED				:
;----------------------------------------------------------------

	call	_write_c_current

	movzx	esi, bl ; video page number (0 to 7)	
	mov	[esi+chr_attrib], ah ; color/attribute

        jmp     VIDEO_RETURN

WRITE_C_CURRENT:
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	;
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
	;

	;and	bl, 7 ; video page number (<= 7)
	movzx	esi, bl	
	mov	ah, [esi+chr_attrib]

	call	_write_c_current
        jmp     VIDEO_RETURN

;----------------------------------------------------------------
; 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							:
;	DISPLAY REGEN BUFFER UPDATED				:
;----------------------------------------------------------------

_write_c_current:  ; from 'write_tty'
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 30/08/2014 (Retro UNIX 386 v1)
	; 18/01/2014
	; 04/12/2013
	;
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
	;

	cli		
	; bl = video page
	; al = character
	; ah = color/attribute
	push	dx
	push	ax	; save character & attribute/color
	call 	find_position  ; get regen location and port address
	; esi = regen location
	; dx = status port
	;
	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
	;
p41:			; wait for horizontal retrace is low or vertical
	sti		; enable interrupts first
        cmp     bl, [ACTIVE_PAGE]
	jne	short p44 
	cli 		; block interrupts for single loop
	in	al, dx	; get status from the adapter
	test	al, RVRT ; check for vertical retrace first
	jnz	short p43 ; Do fast write now if vertical retrace
	test	al, RHRZ ; is horizontal retrace low
	jnz	short p41 ; wait until it is
p42:			;  wait for either retrace high
	in	al, dx ; get status again
	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
	jz	short p42 ; wait until either retrace active
p43:	
	sti
p44:
	pop	ax	; restore the character (al) & attribute (ah)
	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
				; Retro UNIX 386 v1 feature only!
	mov	[esi], ax
	pop	dx
	retn

; 18/01/2016
; 16/01/2016
; 30/06/2015
; 27/06/2015
; 11/03/2015
; 02/09/2014
; 30/08/2014
; VIDEO FUNCTIONS
; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)

WRITE_TTY:
	; 30/01/2016
	; 18/01/2016
	; 16/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 13/08/2015
	; 02/09/2014
	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
	;
	; INPUT -> AH = Color (Forecolor, Backcolor)
	;	   AL = Character to be written
	;	   EBX = Video Page (0 to 7)
	;	   (BH = 0 --> Video Mode 3)

RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT

; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
;
; 06/10/85  VIDEO DISPLAY BIOS
;
;--- WRITE_TTY ------------------------------------------------------------------
;										:
;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
;   VIDEO CARDS. 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		:
;   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, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
;   EXIT -- 									:
;     ALL REGISTERS SAVED							:
;--------------------------------------------------------------------------------

	cli
	;
	; READ CURSOR (04/12/2013)
	; Retro UNIX 386 v1 Modifications: 30/08/2014
	or	bh, bh
	jnz	beeper
	; 01/09/2014
	cmp	byte [CRT_MODE], 3
	je	short m3
	;
	call	set_mode_3 ; 16/01/2016
m3:
	mov 	esi, ebx ; 13/08/2015 (0 to 7)
	shl	si, 1
	add	esi, CURSOR_POSN
	mov	dx, [esi]
	;
	; dx now has the current cursor position
	;
	cmp	al, 0Dh		; is it carriage return or control character
	jbe	short u8
	;
	; write the char to the screen
u0:	
	; ah = attribute/color
	; al = character
	; bl = video page number (0 to 7)
	; bh = 0
	;
	call	_write_c_current ; 16/01/2015
	;
	; position the cursor for next char
	inc	dl		; next column
	;cmp	dl, [CRT_COLS]
	cmp	dl, 80		; test for column overflow 
        jne     _set_cpos
	mov	dl, 0		; column = 0
u10:				; (line feed found)
	cmp	dh, 25-1 	; check for last row
	jb 	short u6
	;
	; scroll required
u1:	
	; SET CURSOR POSITION (04/12/2013)
	call	_set_cpos
	;
	; determine value to fill with during scroll
u2:
	; bl = video page number
	;
	call _read_ac_current ; 18/01/2016
	;
	; al = character, ah = attribute
	; bl = video page number 	
u3:
	;;mov	ax, 0601h 	; scroll one line
	;;sub	cx, cx		; upper left corner
	;;mov	dh, 25-1 	; lower right row
	;;;mov	dl, [CRT_COLS]
	;mov	dl, 80		; lower right column	
	;;dec	dl
	;;mov	dl, 79

	;;call	scroll_up	; 04/12/2013
	;;; 11/03/2015
	; 02/09/2014
	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
	; 11/03/2015
	sub	cx, cx
	mov	dx, 184Fh ; dl = 79 (column), dh = 24 (row)
	;
	mov	al, 1		; scroll 1 line up
		; ah = attribute
	jmp	_scroll_up	; 16/01/2016
;u4:
	;;int	10h		; video-call return
				; scroll up the screen
				; tty return
;u5:
	;retn			; return to the caller

u6:				; set-cursor-inc
	inc	dh		; next row
				; set cursor
;u7:					
	;;mov	ah, 02h
	;;jmp	short u4 	; establish the new cursor
	;call	_set_cpos
	;jmp 	short u5
	jmp     _set_cpos

	; check for control characters
u8:
	je	short u9
	cmp	al, 0Ah		; is it a line feed (0Ah)
	je	short u10
	cmp	al, 07h 	; is it a bell
	je	short u11
	cmp	al, 08h		; is it a backspace
	;jne	short u0
	je	short bs	; 12/12/2013
	; 12/12/2013 (tab stop)
	cmp	al, 09h		; is it a tab stop
	jne	short u0
	mov	al, dl
	cbw
	mov	cl, 8
	div	cl
	sub	cl, ah
ts:
	; 02/09/2014
	; 01/09/2014
	mov	al, 20h
tsloop:
	push	cx
	push	ax
	xor 	bh, bh
	;mov	bl, [ACTIVE_PAGE]
	call	m3
	pop	ax  ; ah = attribute/color
	pop	cx
	dec	cl
	jnz	short tsloop
	retn
bs:	
	; back space found

	or	dl, dl 		; is it already at start of line
	;je	short u7 	; set_cursor
	jz	short _set_cpos
	dec	dx     		; no -- just move it back
	;jmp	short u7
	jmp	short _set_cpos

	; carriage return found
u9:
	mov	dl, 0 		; move to first column
	;jmp	short u7
	;jmp	short _set_cpos ; 30/01/2016

	; line feed found
;u10:
;	cmp	dh, 25-1 	; bottom of screen
;	jne	short u6 	; no, just set the cursor
;       jmp     u1              ; yes, scroll the screen

_set_cpos:
	; 27/06/2015
	; 01/09/2014
	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
	;
	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
	;
	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
	;
;----------------------------------------------
; SET_CPOS
;	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 ID SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
;----------------------------------------------
	;
	mov	esi, CURSOR_POSN
        movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
;	or	al, al
;	jz	short _set_cpos_0
        shl     al, 1   ; word offset
        add     esi, eax
;_set_cpos_0:
	mov	[esi], dx ; save the pointer
	cmp	[ACTIVE_PAGE], bl
	jne	short m17
	;call	m18	; CURSOR SET
;m17:			; SET_CPOS_RETURN
	; 01/09/2014
;	retn
		; DX  = row/column
m18:
	call	position ; determine location in regen buffer	
	mov	cx, [CRT_START]
	add	cx, ax  ; add char position in regen buffer
			; to the start address (offset) for this page
	shr	cx, 1	; divide by 2 for char only count
	mov	ah, 14	; register number for cursor
	;call	m16	; output value to the 6845	
	;retn

	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
	;	TO THE 6845 REGISTERS NAMED IN (AH)
m16:
	cli
	;mov	dx, [addr_6845] ; address register
	mov 	dx, 03D4h ; I/O address of color card
	mov	al, ah	; get value
	out	dx, al	; register set
	inc	dx	; data register
	jmp	$+2	; i/o delay
	mov	al, ch	; data
	out	dx, al	
	dec	dx	
	mov	al, ah
	inc	al	; point to other data register
	out	dx, al	; set for second register
	inc	dx
	jmp	$+2	; i/o delay
	mov	al, cl	; second data value
	out	dx, al
	sti
m17:
	retn

beeper: 
	; 30/08/2014 (Retro UNIX 386 v1)
	; 18/01/2014
	; 03/12/2013
	; bell found
u11:
	sti
	cmp	bl, [ACTIVE_PAGE]
	jne	short u12	; Do not sound the beep 
				; if it is not written on the active page
	mov	cx, 1331 	; divisor for 896 hz tone
	mov	bl, 31		; set count for 31/64 second for beep
	;call	beep		; sound the pod bell
	;jmp	short u5 	; tty_return
	;retn
	
TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT

beep:
	; 07/02/2015
	; 30/08/2014 (Retro UNIX 386 v1)
	; 18/01/2014
	; 03/12/2013
	;
	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
	;
	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
	;
	; ENTRY:
	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
	; EXIT:				:
	;    (AX),(BL),(CX) MODIFIED.

	pushf  ; 18/01/2014	; save interrupt status
	cli			; block interrupts during update
	mov	al, 10110110b	; select timer 2, lsb, msb binary
	out	TIMER+3, al 	; write timer mode register
	jmp	$+2		; I/O delay
	mov	al, cl		; divisor for hz (low)
	out	TIMER+2,AL	; write timer 2 count - lsb
	jmp	$+2		; I/O delay
	mov	al, ch		; divisor for hz (high)
	out	TIMER+2, al	; write timer 2 count - msb
	in	al, PORT_B	; get current setting of port
	mov	ah, al		; save that setting
	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
	out	PORT_B, al	; and restore interrupt status
	;popf	; 18/01/2014
	sti
g7:				; 1/64 second per count (bl)
	mov	ecx, 1035	; delay count for 1/64 of a second	
	call	waitf		; go to beep delay 1/64 count
	dec	bl		; (bl) length count expired?
	jnz	short g7	; no - continue beeping speaker
	;
	;pushf			; save interrupt status
	cli  	; 18/01/2014	; block interrupts during update
	in	al, PORT_B	; get current port value
        ;or      al, not (GATE2+SPK2) ; isolate current speaker bits in case
        or      al, ~(GATE2+SPK2)
        and	ah, al		; someone turned them off during beep
	mov	al, ah		; recover value of port
        ;or      al, not (GATE2+SPK2) ; force speaker data off
	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
	out	PORT_B, al	; and stop speaker timer
	;popf			; restore interrupt flag state
	sti
	mov	ecx, 1035	; force 1/64 second delay (short)
	call	waitf		; minimum delay between all beeps
	;pushf			; save interrupt status
	cli			; block interrupts during update
	in	al, PORT_B	; get current port value in case	
	and	al, GATE2+SPK2	; someone turned them on
	or	al, ah		; recover value of port_b
	out	PORT_B, al	; restore speaker status
	popf			; restore interrupt flag state
u12:	
	retn

REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT

WAITF:
waitf:
	; 30/08/2014 (Retro UNIX 386 v1)
	; 03/12/2013
	;
;	push ax			; save work register (ah)	
;waitf1:
				; use timer 1 output bits
;	in	al, PORT_B	; read current counter output status
;	and	al, REFRESH_BIT	; mask for refresh determine bit
;	cmp	al, ah		; did it just change
;	je	short waitf1	; wait for a change in output line
;	;
;	mov	ah, al		; save new lflag state
;	loop	waitf1		; decrement half cycles till count end		
;	;
;	pop	ax		; restore (ah)
;	retn			; return (cx)=0

; 06/02/2015 (unix386.s <-- dsectrm2.s)
; 17/12/2014 (dsectrm2.s)
; WAITF
; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
;
;---WAITF-----------------------------------------------------------------------
;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
; ENTRY:
;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
; EXIT:
;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
;	(CX) = 0	
;-------------------------------------------------------------------------------

; Refresh period: 30 micro seconds (15-80 us)
; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)

;WAITF:					; DELAY FOR (CX)*15.085737 US
	PUSH	AX			; SAVE WORK REGISTER (AH)
	; 16/12/2014
	;shr	cx, 1			; convert to count of 30 micro seconds
	shr	ecx, 1	; 21/02/2015
;17/12/2014	
;WAITF1:
;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
;	CMP	AL, AH			; DID IT JUST CHANGE
;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
;	MOV	AH, AL			; SAVE NEW FLAG STATE
;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
	;
	; 17/12/2014
	;
	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
	;
;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
;   	INPUT:  CX = number of refresh periods to wait
;     	       (refresh periods = 1 per 30 microseconds on most machines)
WR_STATE_0:
	IN	AL,PORT_B		; IN AL,SYS1
	TEST	AL,010H
	JZ	SHORT WR_STATE_0
WR_STATE_1:
	IN	AL,PORT_B		; IN AL,SYS1
	TEST	AL,010H
	JNZ	SHORT WR_STATE_1
        LOOP    WR_STATE_0
	;
	POP	AX			; RESTORE (AH)
	RETn				; (CX) = 0

; % include 'vidata.s' ; VIDEO DATA

; /// End Of VIDEO FUNCTIONS ///
