; WriteR90asm -- a collection of assembly code display procedures for xm machine
; by Keith Knox  last modified  September 18, 1979
; by Paul Lam    last modified  January 15, 1981  


; write -- procedure to write on the display

	.BEXT		writeR90
	.BEXT		BitBlt
	.BEXTZ 	MaxStringHeight
	.BEXTZ 	HardCopy

	.SREL
writeR90:		WRITE1
R90Bk1:		ZZZ

; write(BBTable, string, font, maxwidth, maxheight,hcwidthvec,rot)
; uses BitBlt to write a horizontal string from AL fonts
; It may be possible that this code and the BitBlt code are on separate overlays.
; If so, this procedure must have a stack so that its overlay will not be freed
; when the BitBlt overlay is read into memory.  

; BitBlt table should (start on an even address and) be initialized as follows:
; 0--function	// source=block, dest=alt or norm bank, fn=replace,paint,invert,erase
; 1--unused
; 2--dcb!2+TY*((dcb!1)&#377)
; 3--((dcb!1)&#377)
; 4--LX		// updated with width of each character
; 5--0
; 6--0
; 7--0
; 8--0
; 9--1
; 10--0
; 11--0

; if xw=font+char+font!char then BBTable is changed as follows:
; 4--BBTable!4+((xw!0)/2 or 16)
; 5--(xw!1) rshift 8
; 6--(xw!0)/2 or 16
; 7--xw!1 & #377
; 8--xw-(xw!1 & #377)

; Displacements from BBTable
DestBCA = 2
DestBMR = 3
lx=4
disp=5
width=6
height=7
bitmap=8.

; Displacements from stack pointer
string=5
font=6
maxwidth=7
maxheight=8.
hcwidthvec=9.
rot=10.
Xstart = 11.
Ystart = 12.
ALHeight = 13.


	.NREL
Home: 					; now time to go home
	LDA 2 SaveAC2
	LDA 0 RotatedHeight
	JSR @366

WRITE1:	STA 3 1 2
	JSR @370
	30
	JSR @367				; number arguments is stored in register 0

	STA 2 SaveAC2	; don't use BBTable!1 because BitBlt(BBTable) may use it
	MOV 2 3
	LDA 2 4 2			; get BBTable address
	LDA 1 lx 2
	STA 1 Xstart 3		; init xstart
	LDA 1 DestBCA 2
	STA 1 Ystart 3
	SUB 1 1	
	STA 1 MicaPosn	; init MicaPosn
	STA 1 ScHeight	; init ScHeight
	LDA  2 SaveAC2	

	LDA 1 c377		; initialize the character mask
	STA 1 mask
	LDA 0 hcwidthvec 2
	STA 0 WidthVector

	LDA 0 @string 2	; initialize the character mask
	MOVS 0 0
	AND 1 0
	SNZ 0 0
	JMP Home			; if string is empty then go home
	STA 0 charsdone

CalHeight:
	LDA 2 SaveAC2		; restore stack pointer
	LDA 1 font 2			; get font pointer
	lda 0 c1		
	sub 0 1
	#61025				;  #61025			; xmlda -- ac0 ← @ac1
	lda 1 c377
	and 1 0
	inc 0 0
	sta 0 ALHeight 2		; init font height
	sta 0 MaxStringHeight	; update string height

toploop:			; loop over the # of chars in the string

	; get a char and leave it in AC0
	LDA 2 SaveAC2		; restore stack pointer
	LDA 3 string 2		; get address of word in string
	LDA 0 0 3			; get word in string
	LDA 1 mask
	AND 1 0				; mask out the character
	SODD 1 1
	MOVS 0 0			; if necessary, right justify character
	INC 3 3
	SKEVEN 1 1
	STA 3 string 2		; if necessary, increment string pointer
	COM 1 1
	STA 1 mask			; switch mask between left and right byte
	STA 0 SaveHChar	; save char code for hardcopy width calculation

writechar:					; write out the character in AC0

	; get the character descriptor
	STA 0 SaveChar
	LDA 2 SaveAC2		; restore stack pointer
	LDA 1 font 2			; get font pointer
	LDA 3 font 2			; get font pointer in ac3 to be used later
	lda 0 SaveChar
	add 0 1
	#61025				; #61025		; xmlda -- ac0 ← @ac1
	add 0 1
	#61025				; #61025		; xmlda -- ac0 ← @ac1; AC0 now contains xw!0
	sta 0 xw0				; ac0 contains xw!0; save it
	sta 1 CharBitmapPtr	; save character bitmap pointer
	inc 1 1
	#61025				; #61025		; xmlda -- ac0 ← @ac1; AC1 now contains xw!1
	sta 0 xw1				; AC0 = xw!1
	LDA 1 c377
	AND 0 1
	LDA 3 CharBitmapPtr	; get character bitmap pointer
	SUB 1 3				; ac3 has font pointer
	LDA 2 4 2				; get the BBTable address
	STA 3 bitmap 2		; bitmap=xw-(xw!1 & #377)

	; fill in the height, width, displacement and character bitmap address
	LDA 1 c377
	AND 0 1
	STA 1 height 2		; height = xw!1 & #377 + disp
	JMP  DoSoftCopy

BitBltProc:	BitBlt
charsdone: 0
mask:	377
CharBitmapPtr: 0
xw0: 0
xw1: 0
c377:	377
c20:	20
SaveChar: 0
SaveHChar: 0
WidthVector: 0
C50: 50.
C1778:	1778.
MicaPosn: 0
ScHeight: 0
HcWidth: 0
SaveAC2: 0
c1:			1
c4:			4
RotatedHeight:	0
Top:	JMP toploop

DoSoftCopy:
	; check the width, we may want to quit now
	LDA 1 xw1			; xw!1 
	MOVS 1 0				; 
	ADD 1 0				; aco has the width
	LDA 1 c377
	AND 1 0				;TOTAL HEIGHT BELOW ORIGIN
	INC 0 0
	INC 0 0
	STA 0 width 2		; store width in BBTable

; check for width greater then 16
	LDA 1 c20
	SUB 1 0
	SN 0 0					; skip if width less then 16
	STA 1 width 2	
	LDA  0 width 2		

	LDA 3 SaveAC2		; restore stack pointer
	STA 3 StackPtr
	JSR  CmaxWidth		; check if exceed max width

	; check the height, we may want to limit this character
	LDA 0 disp 2		; number of lines to skip
	LDA 1 maxheight 3	; get limiting height
	SGT 1 0				; see if displacement is equal to maxheight
	JMP nextchar		; don't bother to display this char
	SUB 0 1				; subtract the disp from the limiting height
	LDA 0 height 2		; AC0 = height of character
	SGT 1 0				; is this character too high?
	MOV 1 0				; height becomes maxheight
	STA 0 height 2		; update maxheight
; finish soft display setup
	JSR  UpdateWidth
; now actually put the character bitmap in the display using BitBlt
	MOV 2 0
	LDA 2 SaveAC2		; restore stack pointer
	JSRII BitBltProc		; BitBlt(BBTable)
	1
	LDA 2 4 2			; get BBTable address

	; see if there are extensions
nextchar:
	LDA 1 xw0			; if odd then no extension
	MOVZR 1 0			; AC0 = pseudocharacter
	SODD 1 1
	JMP  DoExtension	; there is an extension, go back and try again
	SUB 1 1
	STA 1 extension		; mark extension false
	; check if done with string
	DSZ charsdone
	JMP 	Top		; end of the loop

alldone:				; now time to go home
	LDA 2 SaveAC2
	LDA 0 RotatedHeight
	JSR @366

DoExtension:
	LDA 1 c1
	STA 1 extension		; mark extension true
	JMP writechar



; 90 degrees rotation, therefore move backward in the y direction
UpdateWidth:
	STA 3 Rrtn
	LDA 0 HardCopy
	MOV 0 0 szr
	JMP NewYpos				; hard copy
	LDA 1 ScHeight				; soft copy
	LDA 0 extension
	MOV 0 0 SZR				; AC0 = 0 ->  not extension pseudo char
	JMP NewYpos2
	LDA 0 height 2
	MOV 0 0 snr
	LDA 0 c4						; space
	ADD 0 1
	STA 1 ScHeight
	JMP  NewYpos2
NewYpos:
	LDA 0 extension
	MOV 0 0 SNR				; AC0 = 1 ->  extension pseudo char
	JSR  HardCopyCal			; 
	LDA 1 HcWidth				; init to hardcopy width
NewYpos2:
	STA 1 RotatedHeight
	JSR  WriteWidth
	JMP  @Rrtn


WriteWidth:					; ac1 has the rotated width
	STA 3 Wrtn
	LDA 3 SaveAC2			; restore stack pointer
	LDA 0 extension
	MOV 0 0 SZR				; AC0 = 0 ->  not extension pseudo char
	JMP  WriteWidth1			; always cal hardcopy width
;	STA 1 RotatedHeight
ZZZ:
	SUB 0 0
; ac0 = 0; ac1 = width/height
	LDA 2 Nwrds
	MUL							; 1*2 + 0  -> 1
	LDA 0 Ystart 3					; ac0 now has the ystart
	SUB 1 0						; ystart - length
	LDA 2 SaveAC2				; restore stack pointer
	LDA 2 4 2						; get BBTable address
	STA 0 DestBCA 2

WriteWidth1:
	LDA 2 SaveAC2			; restore stack pointer
	LDA 2 4 2						; get BBTable address
	LDA 1 extension				; if this extension char ?
	MOV 1 1 SZR				; AC1 = 0 ->  not extension pseudo char
	JMP  BackX				; there is an extension
	LDA 0 Xstart 3			; always restore lx in case changed by extended char image
	STA 0 lx 2
	JMP  @Wrtn
BackX:
	LDA 0 lx 2
	LDA 1 c20
	ADD 1 0
	STA 0 lx 2
	JMP  @Wrtn
Wrtn: 0
Rrtn: 0
extension: 0

;MicaPosn = MicaPosn + WidthPointer!char
;Xposn = Xstart + MicvaPosn*1778/50

HardCopyCal:
	STA 3 Hrtn
	STA 2 tempac2
	LDA 1 WidthVector
	LDA 0 SaveChar		; get Char code
	ADD 0 1
	#61025				; #61025		; xmlda -- ac0 ← @ac1
	LDA 1 MicaPosn
	ADD 0 1
	STA 1 MicaPosn		;MicaPosn updated to the new coordinate
	LDA 2 C50		;Now scale MicaPosn to required Alto Xposn value
	LDA 0 C1778
	MOVZR 0 0  
	MUL
	LDA 2 C1778
	DIV
	MOV# 0,0		;noop return for negative result
	STA 1 HcWidth		
	LDA 2 tempac2
	JMP  @Hrtn


; check if exceed max width
CmaxWidth:
	STA 3 Rrtn
	LDA 1 extension
	MOV 1 1 SZR				; AC1 = 0 ->  not extension pseudo char
	JMP   @Rrtn
	LDA 3 SaveAC2		; restore stack pointer
	LDA 1 maxwidth 3	; don't go beyond this limit
	SNZ 1 1				; see when maxwidth becomes zero
	JMP alldone			; no more to do
	SUB 0 1				; decrement the maxwidth limit
	SN 1 1					; is this character too wide?
	JMP .+3
	ADD 1 0				; make width equal to former maxwidth
	SUB 1 1				; make maxwidth zero
	STA 1 maxwidth 3	; update maxwidth
	JMP  @Rrtn

Hrtn: 0
tempac1: 0
tempac2: 0
StackPtr: 0
Nwrds: 36.

	.END