; Write.asm -- a collection of assembly code display procedures for xm machine ; by Keith Knox last modified September 18, 1979 ; by Paul Lam last modified Feb 23, 1981 ; write -- procedure to write on the display .BEXT newwrite .BEXT magCvrt .BEXT m1 .BEXT m2 .BEXT m3 .BEXT m4 .BEXT BitBlt .BEXTZ MaxStringHeight, HardCopy, ItalicsBuff, Mag, WindowYmin, WindowXmin .BEXTZ SavedAC2,CharDef ,CurrentYpos .BEXTZ DisplayArea, SetBPtr, OnBits, OffBits, SetBMask, MaskTable .SREL newwrite: WRITE magCvrt: MagCvrt m1: ma1 m2: ma2 m3: ma3 m4: ma4 ; write(BBTable, string, font, maxwidth, maxheight,hc,hcwidthvec,rot,magflag,magarea, Yo, type) ; 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)Ź) ; 3--((dcb!1)Ź) ; 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. MagFlag = 11. MagArea = 12. YScanstart = 13. Type=14. Xstart = 15. Ystart = 16. ALHeight = 17. currXposn = 18. Lastlx=19. Displaywidth=20. BoldFlg=21. ; Lastlx 3 is the last x pos ; width 2 is the width used by BitBlt ; Displaywidth 3 is the actual AL char width .NREL Home: ; now time to go home LDA 0 HcWidth ; returns the line width LDA 2 SavedAC2 JSR @366 WRITE: STA 3 1 2 JSR @370 30 JSR @367 ; number arguments is stored in register 0 STA 2 SavedAC2 ; 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 STA 1 Lastlx 3 ; init Lastlx LDA 1 DestBCA 2 STA 1 Ystart 3 SUB 1 1 STA 1 MicaPosn ; init MicaPosn STA 1 ScHeight ; init ScHeight LDA 2 SavedAC2 LDA 1 c377 ; initialize the character mask STA 1 mask LDA 0 hcwidthvec 2 STA 0 WidthVector LDA 0 rot 2 STA 0 rotation LDA 0 @string 2 ; initialize the character mask MOVS 0 0 AND 1 0 SNZ 0 0 JMP Home ; if string is emptythen go home STA 0 charsdone toploop: ; loop over the # of chars in the string ; get a char and leave it in AC0 LDA 2 SavedAC2 ; 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 ; used by HardCopyCal logic writechar: ; write out the character in AC0 ; get the character descriptor STA 0 SaveChar LDA 2 SavedAC2 ; restore stack pointer LDA 1 Type 2 movzr 1 1 SZC; Skip on carry generated 2 instructions back ;jmp DoItalics; ifso go make a "sliced" copy of the character definition MOV 1 1 STA 1 BoldFlg 2 ; init BoldFlg each time LDA 1 font 2 ; get font pointer lda 0 c2 sub 0 1 #61025 ; #61025 ; xmlda -- ac0 _ @ac1 sta 0 ALHeight 2 ; init font height sta 0 MaxStringHeight ; update string height 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 mov 0 1 ; AC1 = xw!1 sta 1 xw1 ; fill in the height, width, displacement and character bitmap address LDA 2 4 2 ; get the BBTable address LDA 0 c377 COM 0 0 ANDS 1 0 STA 0 disp 2 ; displacement = xw!1 rshift 8 LDA 0 c377 AND 1 0 STA 0 height 2 ; height = xw!1 & #377 lda 3 CharBitmapPtr ; get character bitmap pointer SUB 0 3 ; ac3 has font pointer STA 3 bitmap 2 ; bitmap=xw-(xw!1 & #377) JMP DisplayChar 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 rotation: 0 c2: 2 gototoploop: JMP toploop DisplayChar: ;LDA 0 HardCopy ;MOV 0 0 SZR ; always do hardcopy calculations ;JSR HardCopyCal DoSoftCopy: ; check the width, we may want to quit now LDA 1 xw0 MOVZR 1 0 ; AC0 = width SODD 1 1 ; if there is an extension LDA 0 c20 ; then width is 16 LDA 1 rotation MOV 1 1 SNR ; JMP DoSC1 ; no rotation LDA 1 xw1 MOVS 1 0 ; ADD 1 0 ; ac0 has the width LDA 1 c377 AND 1 0 DoSC1: LDA 3 SavedAC2 ; 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 STA 0 Displaywidth 3 ; save the actual AL width INC 0 0 INC 0 0 LDA 1 c20 ; check for overflow 16 bits SUB 0 1 SN 1 1 JMP .+2 LDA 0 c20 STA 0 width 2 ; store width in BBTable ; 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 JSR CkMag ; check magnify JSR R180width ; now actually put the character bitmap in the display using BitBlt DoDisplay: MOV 2 0 LDA 2 SavedAC2 ; restore stack pointer JSRII BitBltProc ; BitBlt(BBTable) 1 LDA 2 4 2 ; get BBTable address LDA 3 SavedAC2 ; restore stack pointer LDA 0 BoldFlg 3 MOVZR 0 0 SZC JMP MkBold JSR RZerowidth ; see if there are extensions nextchar: LDA 1 xw0 ; if odd then no extension MOVZR 1 0 ; AC0 = pseudocharacter SODD 1 1 JMP writechar ; there is an extension, go back and try again ; check if done with string DSZ charsdone JMP gototoploop ; end of the loop alldone: ; now time to go home LDA 0 HcWidth ; returns the line width LDA 2 SavedAC2 JSR @366 ma1: MkBold: sta 0 BoldFlg 3; Bold characters are done by calling Convert again 1 bit to the right LDA 1 Lastlx 3 ; get x offset INC 1 1 STA 1 lx 2 ; update LX entry in BBTable JMP DoDisplay ;MicaPosn = MicaPosn + WidthPointer!char ;Xposn = Xstart + MicvaPosn*1778/50 HardCopyCal: STA 3 HCrtn LDA 1 WidthVector LDA 0 SaveHChar ; 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 JMP @HCrtn R180width: STA 3 R180rtn ; LDA 0 rotation ; MOV 0 0 SNR ; ; JMP @R180rtn ; no rotation ; LDA 3 SavedAC2 ; LDA 0 Displaywidth 3 ; get actual AL width of character just displayed ; LDA 1 lx 2 ; get x offset ; SUB 0 1 ; STA 1 lx 2 ; update LX entry in BBTable ; check for extension ; LDA 1 xw0 ; if odd then no extension ; MOVZR 1 0 ; AC0 = pseudocharacter ; SODD 1 1 ; JMP @R180rtn ; there is an extension, go back ; check if hardcopy mode ; always hardcopy for r90 until fonts can be fixed ;LDA 1 HardCopy ;MOV 1 1 SNR ;JMP @R180rtn ; JSR HardCopyCal ; always do hardcopy calculations ; LDA 3 SavedAC2 ; LDA 1 Xstart 3 ; LDA 0 HcWidth ; SUB 0 1 ; STA 1 lx 2 JMP @R180rtn RZerowidth: STA 3 R0rtn LDA 3 SavedAC2 LDA 0 rotation MOV 0 0 SZR JMP @R0rtn ; rotated font; just return LDA 0 Displaywidth 3 ; get actual AL width of character just displayed ; LDA 1 lx 2 ; get x offset LDA 1 Lastlx 3 ; get x offset ADD 1 0 STA 0 lx 2 ; update LX entry in BBTable STA 0 Lastlx 3 ; check for extension LDA 1 xw0 ; if odd then no extension MOVZR 1 0 ; AC0 = pseudocharacter SODD 1 1 JMP @R0rtn ; there is an extension, go back ; check if hardcopy mode JSR HardCopyCal ; always do hardcopy calculations LDA 1 HardCopy MOV 1 1 SNR JMP @R0rtn LDA 3 SavedAC2 LDA 0 Xstart 3 LDA 1 HcWidth ADD 0 1 LDA 2 4 3 STA 1 lx 2 STA 1 Lastlx 3 JMP @R0rtn R0rtn: 0 R180rtn: 0 HCrtn: 0 Nwrds: 36. CkMag: STA 3 HCrtn LDA 0 rotation MOV 0 0 SZR JMP @HCrtn ; rotated font, no magnify; just return LDA 3 SavedAC2 LDA 0 MagFlag 3 MOV 0 0 SNR JMP @HCrtn ; no magnify; just return LDA 0 MagArea 3 MOV 0 0 SNR JMP @HCrtn ; Error; just return STA 0 DestBCA 2 LDA 1 height 2 ADD 1 0 STA 0 CharDef INC 1 1 INC 1 1 STA 1 height 2 LDA 0 0 2 ; get function code LDA 1 C177776 AND 1 0 STA 0 0 2 ; change function code to replace (00) ; SUB 0 0 STA 0 lx 2 ; lx = 0 STA 0 disp 2 ; disp = 0 INC 0 0 STA 0 DestBMR 2 ; DestBMR = 1 LDA 0 C16 STA 0 width 2 ; width = 16 MOV 2 0 LDA 2 SavedAC2 ; restore stack pointer JSRII BitBltProc2 ; BitBlt(BBTable) 1 ma2: LDA 2 SavedAC2 LDA 1 Lastlx 2 JSR MagCvrt LDA 2 SavedAC2 LDA 0 Lastlx 2 LDA 2 4 2 STA 0 lx 2 LDA 0 0 2 ; get function code INC 0 0 STA 0 0 2 ; change function code to paint (01) JSR RZerowidth JMP nextchar BitBltProc2: BitBlt C177776: 177776 C16: 16. ; * * * * * * * * * * * * * * * * * * * ;The rest of the code implements a Magnified version of the Convert process ;Exit from MagCvrt -- put here for address range placement MagDn: jmp @MagRtn MagCvrt: ma3: sta 3 MagRtn 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 Con177400; CharDef!1 is stall in AC3 ands 3 0; HD IN AC0 lda 1 YScanstart,2 add 1 0 ; ; lda 1 CurrentYpos ; add 1 0 ; lda 1 WindowYmin sub 1 0 lda 1 Mag jsr @343; Multiply lda 0 Nowrds; 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 Nowrds jsr @343; Multiply sta 1 Yinc ;Ymax = DisplayArea + DisplaySize-Yinc lda 0 DisplaySize; 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 Yinc: 0 Ymax: 0 Xpos: 0 Xptr: 0 XH: 0 Cnt: 0 wd1: 0 DisplaySize: 27432.; **As defined by Sil.defs (Nwrds*ScreenYmax) C377: 377 Con177400: 177400 C17: 17 Nowrds: 36.; **As defined in Sil.defs MagRtn: 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 ma4: 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 Nowrds; 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 Nowrds 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 (635)\420v11V1252b4B582b31B1042b203B2063b189B761b44B395b203B502b66i8I9i77I501B132b137B251b53B97b24B184b8B603b8B37b8B968b30B