;CONVERT A BCPL STRING.
;CALL WITH CVRT(STRING POINTER,Xcoordinate,
;LWA-NWRDS,FONT,MAXWIDTH,MAXHEIGHT,NWRDS)
;RETURNS THE WIDTH OF THE STRING IN BITS, AND STORES ITS MAX
;HEIGHT IN MaxStringHeight

;OFFSETS IN THE FRAME
STRINGPOINTER=4
Xstart=5
Ystart=6
LWA=7
FontPointer=10
Face = 11
;Bit0-13 = position hardcopy, Bit 14 = make Bold, bit 15 = make Italics
WidthPointer = 12
MagFlag = 13
fNwrds = 14
DBA = 15
Xposn=16
MicaPosn=17
currXposn=20
Char=21
CharPointer=22
height=23
MaxHeight=24
BoldFlg=25
OverHang=26
CHARSDONE=27
RET=30

.BEXTZ MaxStringHeight, HardCopy, ItalicsBuff, Mag, WindowYmin, WindowXmin
.BEXTZ DisplayArea, SetBPtr, OnBits, OffBits, SetBMask, MaskTable
.ENT Cvrt
.SREL

Cvrt:
CSTRT
.NREL
CSTRT:
STA 3 1 2
JSR@ 370
40
JSR@ 367
LDA 0 @STRINGPOINTER,2
LDA 1 C177400
ANDS 1 0 SNR
JMP@ 366
STA 0 CHARSDONE,2
lda 1 Xstart,2
sta 1 Xposn,2;Xposn is updated to mica precision

lda 0 ScreenYmax
lda 1 Ystart,2
SUB 1 0
sta 0 MaxHeight,2;save ScreenYmax-Yposn in MaxHeight

SUB 0 0
STA 0 MaxStringHeight
STA 0 MicaPosn,2
STA 0 OverHang,2; set height to zero for non-italics strings
sta 2 SavedAC2

DoRight:
LDA 1 @STRINGPOINTER,2
JSR StartCvrt
ISZ STRINGPOINTER,2
DSZ CHARSDONE,2
JMP DoLeft
JMP DoExit

DoLeft:
LDA 1 @STRINGPOINTER,2
MOVS 1 1
JSR StartCvrt
DSZ CHARSDONE,2
JMP DoRight

;return string length is screen bits
;AC0 ← (Xposn-Xstart) + Overhang/4 + BoldFace? 1,0
DoExit:
lda 0 Xposn,2
lda 1 Xstart,2
sub 1 0
lda 3 Face,2;BoldFace bit is C14
lda 1 OverHang,2
movzr 1 1;divide OverHang by 2
add 3 1;add 2 to width calculation if boldface
movzr 1 1;divide (OverHang + boldface) by 2 to set true overhang
add 1 0
JMP@ 366

StartCvrt:
STA 3 RET,2
LDA 3 C177;Mask the character code in AC1
AND 3 1
lda 0 HardCopy;check for hardcopy mode
mov 0 0 SNR
jmp DoCvrt

;MicaPosn = MicaPosn + WidthPointer!char
;Xposn = Xstart + MicaPosn*1778/50
SetBitPsn:
STA 1 Char,2;save Char since I need the AC
lda 3 WidthPointer,2
ADD 1 3
lda 0 0,3;get with from WidthPointer!char
lda 1 MicaPosn,2
ADD 1 0
sta 0 MicaPosn,2;MicaPosn is 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
lda 2 SavedAC2; ***AC2 restored
lda 0 Xstart,2;
add 0 1
sta 1 Xposn,2; jam mica computed value into Xposn
lda 1 Char,2


DoCvrt:
lda 0 Face,2;First check if Italics conversion is required and save BoldFlag
movzr 0 0 SZC;Skip on carry generated 2 instructions back
jmp DoItalics;ifso go make a "sliced" copy of the character definition
sta 0 BoldFlg,2;save original bit 14 as the Bold Flag bit

ContCvrt:
LDA 3 FontPointer,2;assumes AC1 has character code in it
ADD 1 3
STA 3 CharPointer,2;Save pointer to character pointer in font vor Convert
LDA 0 0 3
ADD 0 3;NOW POINTS TO 2*WIDTH+1 OR PSEUDOCHAR
STA 3 CharDef;Save pointer to character entry in font
LDA 0 0 3;2*WIDTH OR PSEUDO
MOVZR 0 0 SNC
LDA 0 C20;PSEUDO-CHAR. THIS PART’S WIDTH IS 16
LDA 1 Xposn,2
ADD 1 0
STA 0 Xposn,2;UPDATE WIDTH Save Xposn for current char in AC1


LDA 0 1 3;XH,HD FOR THIS CHARACTER
MOVS 0 3
ADD 3 0
LDA 3 C377
AND 3 0;TOTAL HEIGHT BELOW ORIGIN
LDA 3 MaxStringHeight; MAX HEIGHT SO FAR
SGT 3 0
STA 0 MaxStringHeight; CURRENT IS BIGGER
LDA 3 MaxHeight,2;MAXIMUM ALLOWED HEIGHT
SGT 3 0
JMP MagCvrt;MagCvrt will clip at the screen boundaries
LDA 3 ScreenXmax;See if part of the character lies to the right of the screen
LDA 0 Xposn,2
SGT 3 0
JMP MagCvrt;MagCvrt will clip at the screen boundaries

LDA 3 MagFlag,2;See if we need to do a Magnified Convert
MOVZR 3 3 SZR
JMP MagCvrt


MOVZR 1 0;Now set up the required parameters ofe Convert
MOVZR 0 0
MOVZR 0 0
MOVZR 0 0
LDA 3 LWA,2
ADD 3 0;WAD in AC0 for CONVERT
LDA 3 C17;compute Xposn into DWA and DBA
AND 3 1
SUB 1 3;DBA ← 15 - (BitPosn & #17)

RpCONV:
STA 3 DBA,2
LDA 3 CharPointer,2
CONVERT fNwrds
JMP DoExtn;CHARACTER HAS AN EXTENSION
DnCVRT:
lda 3 BoldFlg,2
movzr 3 3 SNC
JMP@ RET,2
MkBold:
sta 3 BoldFlg,2;Bold characters are done by calling Convert again 1 bit to the right
adc 3 3
addz 1 3 SZC
jmp RpCONV
inc 0 0
lda 1 C20
add 1 3
jmp RpCONV

ScreenXmax:
576.;**As defined in Sil.defs (Nwrds*16)
ScreenYmax:
762.;**As defined in Sil.defs
DsiplaySize:
27432.;**As defined by Sil.defs (Nwrds*ScreenYmax)
C177400:
177400
C377:
377
C237:
237
C177:
177
C20:
20
C17:
17
C50:
50.;This value must match SilPress.bcpl for screen to mica conversion
C1778:
1778.;This value must match SilPress.bcpl for screen to mica conversion
SavedAC2:
0
CharDef:
0


;copy the entire character definition from the font to the ItalicsBuff
DoItalics:
sta 0 BoldFlg,2;save original bit 14 as the Bold Flag bit
LDA 3 FontPointer,2;assumes AC1 has character code in it
ADD 1 3
LDA 0 0 3
ADD 0 3;NOW POINTS TO 2*WIDTH+1 OR PSEUDOCHAR
LDA 0 1,3;get the height
LDA 1 C377
AND 0 1;mask to just the height and check for zero height
sta 1 height,2
sta 1 OverHang,2;save max shift in OverHang
inc 1 1;AC1 now has height+1
sub 1 3
mov 3 0
com 1 3;AC3 now has -(height+2)
lda 1 ItalicsBuff
inc 1 1;AC1 now points to ItalicsBuff+1
BLT
lda 1 height,2
lda 3 ItalicsBuff
sub 1 3
sta 3 Char,2

;let height = XH
;[
;ItalicsBuff!height = ItalicsBuff!height rshift (height/4)
;height = height-1
;if height ls 4 then break
;] repeat
ItalicsL:
movzr 1 1
movzr 1 1 SNR;divide ht by 4
jmp exitItalics
lda 0 @Char,2
jsr @347;rshift AC0 AC1 times
sta 0 @Char,2
isz Char,2
dsz height,2
lda 1 height,2;set AC0 to -1
jmp ItalicsL

exitItalics:
lda 1 C237;put Dummmy char pointer into AC1
jmp ContCvrt

DoExtn:
sta 3 CharDef;save extended char in CharDef (CharDef is not used now)
lda 3 BoldFlg,2
movzr 3 3 SZC
JMP MkBold
lda 1 CharDef
jmp DoCvrt



; * * * * * * * * * * * * * * * * * * *
;The rest of the code implements a Magnified version of the Convert process

;Exit from MagCvrt -- put here for address range placement
MagDn:
lda 2 SavedAC2
lda 1 @CharDef
movzr 1 1 szc
jmp@ RET,2
jmp DoCvrt

MagCvrt:
sta 1 currXposn,2

;let XH = -(CharDef!1 & #377) //number of scanlines to Convert
lda 3 CharDef
lda 3 1,3;CharDef!1
lda 1 C377;CharDef!1 is stIll in AC3
and 3 1
sub 0 0
sub 1 0 SNR;Nothing to do on zero height (space) characters
jmp MagDn
sta 0 XH

;let HD = CharDef!1 rshift 8 //number of scanlines to skip
;let y = (Ystart+HD-WindowYmin)*Mag //not really saved
;SetBPtr = DisplayArea + (y*Nwrds)
lda 0 C177400;CharDef!1 is stall in AC3
ands 3 0;HD IN AC0
lda 1 Ystart,2
add 1 0
lda 1 WindowYmin
sub 1 0
lda 1 Mag
jsr @343;Multiply
lda 0 Nwrds;y is now in AC1
jsr @343;Multiply
lda 0 DisplayArea
add 0 1
sta 1 SetBPtr

;Yinc = Nwrds*Mag
lda 1 Mag
lda 0 Nwrds
jsr @343;Multiply
sta 1 Yinc

;Ymax = DisplayArea + DsiplaySize-Yinc
lda 0 DsiplaySize;Yinc is in AC1
sub 1 0
lda 1 DisplayArea
add 1 0
sta 0 Ymax

;OnBits = MaskTable!( Mag+ (BoldFlg? Mag/2, 0) )
lda 0 Mag
movzr 0 1
lda 3 BoldFlg,2
mov 3 3 szr
add 1 0
lda 3 MaskTable
add 0 3
lda 0 0,3
com 0 0
sta 0 OnBits

;let Xpos= (currXposn-WindowXmin)*Mag
lda 0 currXposn,2
lda 1 WindowXmin
sub 1 0
lda 1 Mag
jsr @343; Mul
lda 3 C17
com 3 0;put the constant C177760 in AC0

and 1 0
movl# 0 0 SZC
add 3 0
cycle 14
sta 0 Xpos
; OnBits,,OffBits = (OnBits,,OffBits) rshift (Xposn)
and 1 3
sub 2 2
sub 3 2;leave (-xposn) in AC2
lda 0 OnBits
adc 1 1
jsr MaskSh
sta 0 OnBits
sta 1 OffBits
jmp Yloop

Nwrds:
36.;**As defined in Sil.defs
Yinc:
0
Ymax:
0
Xpos:
0
Xptr:
0
XH:
0
Cnt:
0
wd1:
0

;now set up outside loop
;for sl = -XH to -1 do
Yloop:
lda 2 SetBPtr;check for y to small: ifso skip to next scan line
lda 3 DisplayArea
subo# 3 2 SZC
jmp Ydn
lda 3 Ymax;check for y to big: ifso done with conversion
SGT 3 2
jmp MagDn
lda 0 Xpos
sta 0 Xptr
lda 0 OnBits
lda 1 OffBits
sta 1 wd1
lda 1 CharDef
lda 3 XH
add 1 3
lda 1 0,3;lda AC1 with Bits from CharDef!-XH
lda 2 Mag
jmp NxtBit

;now the end of the loop
Ydn:
lda 2 Yinc
lda 3 SetBPtr
add 2 3
sta 3 SetBPtr
isz XH;test for all scan lines converted
jmp Yloop
jmp MagDn

;Now drop into the main bit per scanline loop
;[ //find the next "on"bit in the font and shift the mask bits accordingly
;ShiftCnt = ShiftCnt-Mag
;if FontBits = 0 then break
;let GotBit = (FontBits𘚠) ne 0
;FontBits = FontBits lshift 1
;unless GotBit then loop
;] repeat
;MaskSh(onBits,OffBits,ShiftCnt)
NxtBit:
lda 3 Mag
NxtBitL:
sub 3 2;assumes initial shift cnt in AC3, inc
mov 1,1 SNR;expects Bits to be in AC1
jmp Ydn
movzl 1,1 SNC
jmp NxtBitL
sta 1 SetBMask
lda 1 wd1; restore AC1 with word 1
jsr MaskSh

Bounds:
lda 3 Xptr
movl# 3 3 SZC;skip is Xptr is ls 0
jmp BitDn
lda 2 Nwrds;return is Xptr gr Nwrds
subz 3,2 SBN
jmp Ydn
com# 1 1 SNR;skip if (word 1 ne 0) & (Xptr eq Nwrds)
jmp SetBit
movzr 2 2 SNR
jmp Ydn

SetBit:
lda 3 Mag;find the first memory word address to be modified
sta 3 Cnt
lda 3 SetBPtr
lda 2 Xptr
add 2,3
SetBitL:
lda 2 0,3;get word from screen
and 0 2
adc 0 2;result in AC2 and AC0 is left complemented
sta 2 0,3
com# 1 1 SNR;skip if wd1 is all zero
jmp xitL0
lda 2 1,3;get word from screen
and 1 2
adc 1 2;result in AC2 and AC1 is left complemented
sta 2 1,3
xitL0:
lda 2 Nwrds
add 2 3;increment mem pointer by one scan line
dsz Cnt
jmp SetBitL
BitDn:
sub 2 2
sta 1 wd1
lda 1 SetBMask
jmp NxtBit

;right shift the 32 bit quantity "OnBits,OffBits"
;if OnBits is all zero, then swap words and increment Xptr
;NOTE the content of OnBits,OffBits are to be or’d into the bit map,
;and for convenience of the "OR" algorithm are complements of the bits to be or’d.
MaskSh:
sta 3 Cnt;Cnt is a handy unused register at this point
mov 2 2 SNR;AC2 contains toe quantity to be shifted
jmp@ Cnt;skip if we don’t have any count
shiftL:
movor 0,0;now shift the bit pattern
movr 1,1
com 0,3 SZR;swap words and increment Xptr if all bits are in OffBits
jmp ShiftDn
mov 1 0
com 3 1
isz Xptr
ShiftDn:
inc 2,2 SZR;test for all bits shifted
jmp shiftL
jmp@ Cnt

.end
;