;====================================================================== ; Character/Attribute Memory Routines (12_Nov_84) ;================================================ ; ; Copyright 1984 ; Morrow Designs, Inc. ; San Leandro, Ca. ; ;---------------------------------------------------------------------- ; Index (12_Nov_84) ;------------------ ; ; SETCUR Set the Cursor Position ; LINBAS Calculate the Line Base ; CLRLIN Clear Line Primitive ; OUTCHR Output a Character to the Screen ; WRATT Write an Attribute ; ; CALCD Calculate Destination Address ; CALCATT Calculate Attribute ; CALCS Calculate Source Address ; CALCATT2 Calculate Attribute 2 ; DELL99 Clear the Last Line ; SETSD Set the Source and Destination Pointers ; ; INSMOVE Move characters, and attribute nibbles for Char/Line Insert ; DELMOVE Move characters, and attribute nibbles for Char/Line Delete ; MVCHAR Move a character and an attribute ; DECXFR Decrement the Transfer Address PAGE ;---------------------------------------------------------------------- ; Set the Cursor Position ;------------------------ ; SETCUR: LDA ROW JSR LINBAS ;calculate cursor offset-to be indexed by (),ch ; figure the screen position SETPOS: CLC ; set cursor position register of CRTC LDA LB ADC COLMN LDX #15 STX CRTC STA CRTC+1 LDA TEMP ADC #0 DEX STX CRTC STA CRTC+1 RTS ;---------------------------------------------------------------------- ; Calculate the Line Base ;------------------------ ; LINBAS: ASL A ;compute index into line table TAX LDA LINES,X ;16 bit add of line multiplier..... CLC ;and Screen base ADC SCBASE STA LB ;low byte the same for CRAM and ARAM LDA LINES+1,X ADC SCBASE+1 STA TEMP ;high byte of 16 bit add AND #%111 ;make sure not more than 2K ORA #HIGH CRAM ;compute high byte of CRAM Line base STA LB+1 ;save it RTS PAGE ;---------------------------------------------------------------------- ; Clear Line Primitive ;--------------------- ; CLRLIN: LDX #80 ; now, clear last line BNE CLLSK1 CLEOLA: EOR #$FF SEC ADC #80 TAX CLLSK1: LDY #79 CLLP1: LDA #' ' STA (LB),Y LDA ATTTAB+0 JSR WRATT DEY DEX BNE CLLP1 RTS ;---------------------------------------------------------------------- ; Output a Character to the Screen ;--------------------------------- ; 1) on entry, X = current attribute being set & A = character to display ; OUTCHR: JSR XLTIN ; translate input char if req'd LDY COLMN STA (LB),Y ; put char on screen TXA JSR WRATT ; set it's attribute INY CPY #80 ; see if auto LF req'd BNE OUTSK1 ; if not, just set column for next char LDA #0 ; else, set column 0 STA COLMN JMP LF ; and perform a line feed OUTSK1: STY COLMN RTS PAGE ;---------------------------------------------------------------------- ; Write an Attribute ;------------------- ; WRATT: STA TEMPATT ; save attribute value TYA PHA ; save character index JSR CALCATT ; calculate address for attribute LDY #0 LDA TEMPATT ; get back attribute STA (NEWAB),Y ; write attribute back out PLA TAY RTS ;---------------------------------------------------------------------- ; Calculate Destination Address ;------------------------------ ; CALCD: PHA CLC ; calculate destination address for character move ADC LB STA CHARD LDA #0 ADC LB+1 AND #%00110111 ; wrap around for 2000 - 27FF address range STA CHARD+1 PLA ; JMP CALCATT ; Calculate Attribute ;-------------------- ; CALCATT:CLC ; 16 bit add of LB and Y reg ADC LB STA NEWAB ; save pointer LDA #0 ADC LB+1 SEC ; subtract CRAM base address SBC #$20 AND #%00000111 ; Mask for 2K wrap around CLC ; NEWAB = absolute addr in 0 - 2K for att. ; now, make NEWAB actual address ADC #$08 ; add 800H offset to attribute address STA NEWAB+1 RTS PAGE ;---------------------------------------------------------------------- ; Calculate Source Address ;------------------------- ; CALCS: PHA CLC ; calculate source address for character move ADC LB2 STA CHARS LDA #0 ADC LB2+1 AND #%00110111 ; wrap around for 2000 - 27FF address range STA CHARS+1 PLA ; JMP CALCATT2 ; Calculate Attribute 2 ;---------------------- ; CALCATT2: CLC ; 16 bit add of LB and Y reg ADC LB2 STA NEWAB2 ; save pointer LDA #0 ADC LB2+1 SEC ; subtract CRAM base address SBC #$20 AND #%00000111 ; Mask for 2K wrap around CLC ; NEWAB = absolute addr in 0 - 2K for att. ; now, make NEWAB actual address ADC #$08 ; add 800H offset to attribute address STA NEWAB2+1 RTS PAGE ;---------------------------------------------------------------------- ; Clear the Last Line ;-------------------- ; DELL99: LDY #0 STY COLMN LDY #79 DLLP1: LDA #' ' STA (LB),Y LDA ATTTAB+0 JSR WRATT DEY BPL DLLP1 RTS ;---------------------------------------------------------------------- ; Set the Source and Destination Pointers ;---------------------------------------- ; SETSD: LDA LB ; set up character destination pointer STA CHARD LDA LB+1 STA CHARD+1 LDA LB2 ; and source pointer STA CHARS LDA LB2+1 STA CHARS+1 RTS PAGE ;---------------------------------------------------------------------- ; Move characters, and attribute nibbles for Char/Line Insert ;------------------------------------------------------------ ; on entry, NEWAB2 = absolute address in ARAM of source ; NEWAB = absolute address in ARAM of destination ; TRANSFR = count of number of attributes to move ; ; CHARS = absolute address in CRAM of source ; CHARD = absolute address in CRAM of destination ; INSMOVE:JSR MVCHAR ; move a character and attribute JSR DECXFR ; adjust number of bytes to be transferred BNE MORINS ; if ( no more chars to insert) RTS ; then return MORINS: DEC NEWAB2 ; adjust source pointer for move LDA #$FF ; see if time to adjust upper nibble CMP NEWAB2 BNE ADJTO ; if not, then adjust destination pointer DEC NEWAB2+1 LDA #07H ; see if ARAM needs wrapping CMP NEWAB2+1 BNE ADJTO ; if ARAM ok, adjust dest. pointer LDA #0FH ; else, put at top of ARAM STA NEWAB2+1 ADJTO: DEC NEWAB ; adjust destination pointer for move LDA #$FF ; see if time to adjust upper nibble CMP NEWAB BNE ADJCHAR ; if not, then move another attribute DEC NEWAB+1 LDA #07H ; see if ARAM needs wrapping CMP NEWAB+1 BNE ADJCHAR ; if ARAM ok, move another byte LDA #0FH ; else, put at top of ARAM STA NEWAB+1 ADJCHAR:DEC CHARS ; adjust source for character move LDA #$FF ; see if time to adjust high byte CMP CHARS BNE NXTADJ ; if not, adjust destination DEC CHARS+1 LDA #$1F ; see if time to put at top of CRAM CMP CHARS+1 BNE NXTADJ LDA #$27 ; if so , then set top page of CRAM STA CHARS+1 NXTADJ: DEC CHARD ; adjust destination for character move LDA #$FF ; see if time to adjust high byte CMP CHARD BNE ANOTHER ; if not, move another character DEC CHARD+1 LDA #$1F ; see if time to put at top of CRAM CMP CHARD+1 BNE ANOTHER LDA #$27 ; if so , then set top page of CRAM STA CHARD+1 ANOTHER:JMP INSMOVE PAGE ;---------------------------------------------------------------------- ; Move characters, and attribute nibbles for Char/Line Delete ;------------------------------------------------------------ ; on entry, NEWAB2 = absolute address in ARAM of source ; NEWAB = absolute address in ARAM of destination ; TRANSFR = count of number of attributes to move ; ; CHARS = absolute address in CRAM of source ; CHARD = absolute address in CRAM of destination ; DELMOVE:JSR MVCHAR ; move a character and attribute JSR DECXFR ; adjust number of bytes to move BNE MOREDEL ; if non-zero, then more characters to delete RTS MOREDEL:INC NEWAB2 ; adjust source pointer for move BNE ADJTOD ; if not, then adjust destination pointer INC NEWAB2+1 LDA #10H ; see if ARAM needs wrapping CMP NEWAB2+1 BNE ADJTOD ; if ARAM ok, adjust dest. pointer LDA #08H ; else, put at top of ARAM STA NEWAB2+1 ADJTOD: INC NEWAB ; adjust destination pointer for move BNE ADJCHARD ; if not, then move another attribute INC NEWAB+1 LDA #10H ; see if ARAM needs wrapping CMP NEWAB+1 BNE ADJCHARD ; if ARAM ok, move another byte LDA #08H ; else, put at top of ARAM STA NEWAB+1 ADJCHARD: INC CHARS ; adjust source for character move BNE NXTADJD ; if not, adjust destination INC CHARS+1 LDA #$28 ; see if time to put at top of CRAM CMP CHARS+1 BNE NXTADJD LDA #$20 ; if so , then set top page of CRAM STA CHARS+1 NXTADJD:INC CHARD ; adjust destination for character move BNE ANOTHERD ; if not, move another character INC CHARD+1 LDA #$28 ; see if time to put at top of CRAM CMP CHARD+1 BNE ANOTHERD LDA #$20 ; if so , then set top page of CRAM STA CHARD+1 ANOTHERD: JMP DELMOVE PAGE ;---------------------------------------------------------------------- ; Move a character and an attribute ;---------------------------------- ; MVCHAR: LDY #0 ; set y to zero for absolute indirect addr. LDA (NEWAB2),Y ; get an attribute STA (NEWAB),Y ; write new attribute byte LDA (CHARS),Y ; get a character STA (CHARD),Y ; put character in new position RTS ;---------------------------------------------------------------------- ; Decrement the Transfer Address ;------------------------------- ; DECXFR: LDX #0 ; to be used later, so set up now DEC TRANSFR ; adjust low byte of transfer count BNE CHKFF ; if non zero, then check if FF CPX TRANSFR+1 ; see if high byte of transfer count is 0 too RTS ; if zero, then done, else more to XFR CHKFF: DEX CPX TRANSFR ; if transfr count = ff, then dec transfr+1 BNE NOTFF ; else, adjust source pointer DEC TRANSFR+1 LDA TRANSFR ; set flags for<>0 (won't be here if =0) NOTFF: RTS PAGE END