; *********************************************************************
;  Module: STRING.ASM
;  Author: Scott Teresi, www.teresi.us
;  Created: October 25, 1995	 Last modified: November 19, 1995
;  Description: This module contains several basic string functions.
; *********************************************************************

;       Procedures available in this module:

	PUBLIC BLANK_LINE
	PUBLIC CLEAR_SCREEN
	PUBLIC SCROLL_SCREEN
	PUBLIC INPUT_ROUTINE
	PUBLIC OUTPUT_STRING


; *********************************************************************
;       "Constant" Declarations
; *********************************************************************

	LF  EQU 0AH	 ; line feed ASCII value
	CR  EQU 0DH	 ; carriage return ASCII value


; *********************************************************************
;	Procedures
; *********************************************************************

CODESEG SEGMENT PARA PUBLIC 'CODE'


BLANK_LINE PROC FAR

; Moves cursor to next line.
; On entry: nothing
; On exit:  nothing

	PUSH AX 	; save affected registers
	PUSH DX

	MOV AH, 02	; specify DOS service to print a character
	MOV DL, CR	; get ready to print a carriage return
	INT 21H 	; call DOS service
	MOV DL, LF	; get ready to print a line feed
	INT 21H 	; call DOS service

	POP DX		; restore affected registers
	POP AX

	RET

BLANK_LINE ENDP



CLEAR_SCREEN PROC FAR

; Clear the screen.
; On entry: <nothing>
; On exit:  <nothing>

	PUSH AX 	; save registers
	PUSH BX
	PUSH CX
	PUSH DX

	MOV AH, 6	; select service to clear the screen
	MOV AL, 0	; select all lines on the screen
	MOV BH, 7	; select attribute of a black background
	MOV CX, 0	; select upper left corner
	MOV DX, 25*256+80   ; select lower right corner (25 x 80)
	INT 10H 	; call interrupt routine

	POP DX		; restore registers
	POP CX
	POP BX
	POP AX

	RET

CLEAR_SCREEN ENDP



SCROLL_SCREEN PROC FAR

; Clear the screen by scrolling the window up.
; On entry: <nothing>
; On exit:  <nothing>

	PUSH AX 	; save registers
	PUSH BX
	PUSH CX
	PUSH DX

	MOV CX, 30	; height of screen, plus a little more

SCROLL_A_LINE:
	MOV AH, 6	; select service to clear the screen
	MOV AL, 1	; specify to do one line at a time
	MOV BH, 7	; select attribute of a black background
	PUSH CX
	MOV CX, 0	; select upper left corner
	MOV DX, 25*256+80   ; select lower right corner (25 x 80)
	INT 10H 	; call interrupt routine
	POP CX

	PUSH CX
	MOV CX, 0FFFFH
	SLOW_DOWN:
	PUSH CX
	MOV CX, 1
	SLOW_DOWN_MORE:
	LOOP SLOW_DOWN_MORE
	POP CX
	LOOP SLOW_DOWN
	POP CX

	LOOP SCROLL_A_LINE

	POP DX		; restore registers
	POP CX
	POP BX
	POP AX

	RET

SCROLL_SCREEN ENDP



INPUT_ROUTINE PROC FAR

; Displays the prompt string whose memory address is pointed to by
;	DI register and then inputs a string storing it at address SI.
; On entry: SI = future string info start address
;           DI = prompt string start address
; On exit:  SI = actual string start address (previous SI plus 2)
;           DI = length of string

	PUSH AX                 ; save registers to be affected by procedure
	PUSH DX
	
	PUSH SI
	MOV SI, DI		; specify start address of string to print
	CALL OUTPUT_STRING	; call module function to output the string
	POP SI

	MOV DX, SI		; specify where input string will be stored
	MOV AH, 0AH		; specify DOS service to input a string
	INT 21H                 ; call DOS service

	CALL BLANK_LINE 	; output a carriage return
	
	INC SI			; set to address storing string length
	MOV AL, [SI]            ; get input string length
	MOV AH, 0		; clear out upper byte of AX
	MOV DI, AX              ; place input string length into DI
	INC SI                  ; set SI to point to start of input string

	POP DX                  ; restore affected registers
	POP AX
	
	RET

INPUT_ROUTINE ENDP



OUTPUT_STRING PROC FAR

; Outputs ASCII values stored in memory until reaching a null character.
; On entry: SI = string start address
;	    DL = x coordinate of cursor
;	    DH = y coordinate of cursor
;	    BL = color attribute
; On exit:  DL = new x coordinate of cursor

	PUSH AX 	    ; save affected registers
	PUSH BX
	PUSH CX

	;MOV BL, 7	    ; set the color (passed to procedure)
	MOV BH, 0	    ; set the page
	MOV CX, BX	    ; store contents of BX in CX
	MOV BX, 0	    ; start string pointer index at zero offset

NEXT_CHAR:
	MOV AL, [SI][BX]    ; get a character, offset BX bytes from SI
	CMP AL, 0	    ; see if character is null yet
	JE TERMINATE	    ; if so, function is done

	PUSH BX 	    ; save BX
	MOV BX, CX	    ; load BX with attribute and page parameters
	MOV CX, 1	    ; specify to only output one character
	MOV AH, 2	    ; specify cursor position
	INT 10H 	    ; call DOS service
	MOV AH, 9	    ; specify output character and attribute
	INT 10H 	    ; call DOS service
	MOV CX, BX	    ; store BX again
	POP BX		    ; restore BX as offset counter

	INC BX		    ; update the offset counter
	INC DL		    ; go to next x position
	JMP NEXT_CHAR	    ; do it again

TERMINATE:
	MOV AH, 2	    ; specify cursor position service
	MOV AL, 0	    ; specify null character
	MOV BX, CX	    ; load BX with attribute and page parameters
	MOV CX, 1	    ; print only once
	PUSH DX
	MOV DL, 1	    ; cursor x position
	MOV DH, 25	    ; cursor y position (off screen)
	INT 10H 	    ; call DOS service
	POP DX

	POP CX		    ; restore affected registers
	POP BX
	POP AX

	RET

OUTPUT_STRING ENDP

CODESEG ENDS
	END

