COMMENT *

			     CLUBware  (tm)

	  XREP repeates an input character some number of times.
		  The string starts at the current cursor position
		  and after the string is written to the screen
		  the cursor position is updated to just after the
		  string.

		   Copyright 1984 Rayhawk Automation N.W. Inc
				  P.O. Box 1427
				  Beaverton, Oregon   97075

	  Algorithm:
		  1) load type of crt display from 0000:463
		  2) load current position from 0000:0450
		  3) load count of characters to write
		  4) load character to write
		  5) address the screen segment
		  6) move string to screen segment while synchronizing
		      with horizontal retrace
		  7) update cursor position


	  CALL	XREP ( FLAG% , CHARACTER$ , COUNT% , ATTRIBUTE% )

		  FLAG%       environment flag
			      = 0 means under basic interpreter
			      = 1 means under compiled basic not /O
			      = 2 means under compiled basic with /O
			      = 3 means under compiled business basic

		  COUNT%  number of times to repeat the character

		  CHARACTER$  character to write to screen

		  ATTRIBUTE%  attribute for character


									      *

;______________________________________________________________________________

;  Normal assembly directives

CODE	  SEGMENT PARA PUBLIC 'CODE'

	  ASSUME  CS:CODE

	  EXTRN   $PUTCPOS:FAR

	  PUBLIC  XREP

ATTRIBUTE	  EQU  WORD PTR [BP+6] ; address of string descriptor on stack

CHAR_COUNT	  EQU  WORD PTR [BP+8] ; address of character count on stack

STRING_DESC	  EQU  WORD PTR [BP+10] ; address of string descriptor on stack

ENV_FLAG	  EQU  WORD PTR [BP+12] ; address of environment flag on stack

;______________________________________________________________________________

XREP	  PROC	  FAR

	  PUSH	  BP		       ; address parameters on stack
	  MOV	  BP,SP

	  PUSH	  AX		       ; save all registers used,
	  PUSH	  BX
	  PUSH	  CX
	  PUSH	  DX
	  PUSH	  SI
	  PUSH	  DI
	  PUSH	  ES


;	  ...	  0) load environment flag showing compiled or interpreted

	  MOV	  SI,ENV_FLAG	       ; load address of environment flag
	  MOV	  SI,WORD PTR [SI]     ; load flag itself



;	  ...	  1) load type of crt display from 0000:463

	  SUB	  AX,AX 		     ; address system area
	  MOV	  ES,AX

	  MOV	  DX,WORD PTR ES:[463h]      ; load address of display adapter
	  ADD	  DX,6			     ; address crt status port



;	  ...	  2) load current position from 0000:0450 if compiled
;		      or from DS:[0056h] if interpreted

	  CMP	  SI,0			   ; check environment flag
	  JNE	  COMPILED

	  MOV	  CX,WORD PTR DS:[0056h]   ; load from basic space
	  XCHG	  CL,CH 		   ; basic has it reversed
	  DEC	  CL			   ; basic starts count from 1
	  DEC	  CH			   ;  instead of zero
	  JMP	  SHORT CALC_POSITION

COMPILED:
	  MOV	  CX,WORD PTR ES:[450h]    ; load current position
					   ;  from system space
CALC_POSITION:
	  SUB	  AH,AH 	       ; isolate row number in AX
	  MOV	  AL,CH
	  MOV	  BL,80 	       ; multiply row by 80 bytes per row
	  MUL	  BL
	  SUB	  CH,CH 	       ; add in column number
	  ADD	  AX,CX

	  MOV	  DI,AX
	  SHL	  DI,1		       ; multiply by 2 to account
				       ;  for attribute bytes



;	  ...	  3) load count of characters to write

	  MOV	  BX,CHAR_COUNT        ; load address of character count
	  MOV	  CX,WORD PTR DS:[BX]


;	  ...	  4) load character to write
;		       note that each of the modes supported has their
;		       own format for the string descriptor

	  MOV	  BX,STRING_DESC       ; load address of string descriptor
	  CMP	  SI,0		       ; running compiled?
	  JNE	  IS_COMPILED
	  MOV	  BX,WORD PTR [BX+1]   ; load offset of string
	  JMP	  SHORT LOAD_CHAR

IS_COMPILED:
	  MOV	  BX,WORD PTR [BX+2]   ; load offset of string

	  CMP	  SI,3
	  JNE	  LOAD_CHAR

	  ADD	  BX,3		       ;  Support BBC String format

LOAD_CHAR:

	  MOV	  AL,BYTE PTR [BX]     ; load the character itself


;	  ...	  4) load attribute for character

	  MOV	  BX,ATTRIBUTE	       ; load address of attribute
	  MOV	  BH,BYTE PTR DS:[BX]  ; load the attribute itself
	  MOV	  BL,AL 	       ; move in the character


;	  ...	  5) address the screen segment

	  MOV	  AX,0B000h	       ; screen seg for monochrome card
	  CMP	  DX,03DAh	       ; is this a graphic card?
	  JNE	  MONOCHROME

	  MOV	  AX,0B800h	       ; load screen seg for graphic card

MONOCHROME:

	  MOV	  ES,AX 	       ; address the screen buffer


;	  ...	  6) move string to screen while synchronizing
;		      with horizontal retrace

DISPLAY_LOOP:

	  CLI
HSYNC_WAIT1:
	  IN	  AL,DX 	       ; check for horizontal retrace
	  TEST	  AL,1
	  JNZ	  HSYNC_WAIT1	       ; wait for retrace
HSYNC_WAIT2:
	  IN	  AL,DX 	       ; check for horizontal retrace
	  TEST	  AL,1
	  JZ	  HSYNC_WAIT2	       ; wait for retrace

	  MOV	  AX,BX
	  STOSW 		       ; store character and attribute
	  STI

	  CMP	  DI,4000
	  JL	  NOT_OFF_PAGE
	  MOV	  DI,0		       ; start at top again
NOT_OFF_PAGE:

	  LOOP	  DISPLAY_LOOP	       ; repeat cx times


;	  ...	  7) update cursor position

	  MOV	  AX,DI 	       ; load current position
	  SHR	  AX,1		       ; discount attribute bytes
	  SUB	  DX,DX 	       ; no sign in this division
	  MOV	  BX,80 	       ; divide by nmbr of chars per row
	  DIV	  BX
	  MOV	  DH,AL 	       ; store row number
				       ; column number already in DL
	  MOV	  BH,0		       ; assume page 0
	  MOV	  AH,2		       ; request new position
	  INT	  10h

	  XCHG	  DH,DL 	       ; basic likes it reversed
	  INC	  DL		       ; basic starts count from 1
	  INC	  DH		       ;  instead of zero

	  MOV	  SI,ENV_FLAG	       ; load address of environment flag
	  CMP	  WORD PTR DS:[SI],0   ; examine flag
	  JE	  NOT_COMPILED

	  CMP	  WORD PTR DS:[SI],3   ; business basic?
	  JE	  RET_TO_BASIC

	  CMP	  WORD PTR DS:[SI],2   ; compiled with /O?
	  JE	  WITH_SLASH_O

								    ; FLAG = 1
	  MOV	  WORD PTR DS:[87h],DX ; store screen address
	  JMP	  SHORT RET_TO_BASIC


WITH_SLASH_O:							    ; FLAG = 2
	  MOV	  DI,SEG $PUTCPOS	 ; address put cursor routine
	  MOV	  ES,DI
	  MOV	  DI,OFFSET $PUTCPOS
	  MOV	  DI,WORD PTR ES:[DI+2]  ; load offset of cursor storage
	  MOV	  WORD PTR DS:[DI],DX	 ; store new cursor position
	  JMP	  SHORT RET_TO_BASIC


NOT_COMPILED:							    ; FLAG = 0
	  MOV	  WORD PTR DS:[0056h],DX ; store new cursor position


RET_TO_BASIC:							    ; FLAG = 3




	  POP	  ES
	  POP	  DI
	  POP	  SI
	  POP	  DX
	  POP	  CX
	  POP	  BX
	  POP	  AX
	  POP	  BP
	  RET	  8


XREP	  ENDP

;______________________________________________________________________________

CODE	  ENDS

	  END
