; 13 May 85 ;** ;** 80 COLUMN FUNCTION CODE ;** fixed$8563 equ false ;* ;* Write character in D to current cursor address ;* Advance cursor next position ;* wr$char$80: lhld char$adr call write$char$80 lda char$col ; get cursor column number cpi 80-1 jrz do$crlf inr a sta char$col ; update column number lhld char$adr ; get cursor address inx h shld char$adr ; update cursor address ; ; input: ; HL=current cursor address ; set$cursor: mvi a,14 ; call wait ; outp h mvi a,15 ; call wait ; outp l ret page ;* ;* Set current ROW and COL (supplied in DE) ;* ;* crs$pos$80: mov a,d cpi 25 rnc mov a,e cpi 80 rnc xchg ; cursor row # in D,column # in C shld char$col ; ; returns with cursor set and current ROW, COLUMN in BC ; and character screen address in HL ; compute$adr: lhld char$col call cur$adr$hl ; HL=cursor address on return shld char$adr jr set$cursor ; call/ret page ;* ;* Move cursor up one line; do nothing if on the ;* top line ;* crs$up$80: lda char$row ora a rz dcr a set$row$80: sta char$row jr compute$adr do$crlf: xra a sta char$col ;* ;* ;* ;* crs$down$80: lda char$row cpi lines-1 ; on bottom line ? jrz scroll$up ; yes, scroll the screen jrnc set$24$80 ; past it, set it to line 24 inr a jr set$row$80 ;* ;* ;* ;* crs$left$80: lda char$col ora a rz dcr a set$col$80: sta char$col jr compute$adr page ;* ;* ;* ;* crs$rt$80: lda char$col inr a cpi 80 jrnz set$col$80 ret ;* ;* ;* ;* crs$cr$80: xra a jr set$col$80 page ; ; ; set$24$80: mvi a,lines-1 sta char$row ; ; ; scroll$up: lxi h,80 lxi d,0 lxi b,80*(lines-1) call block$move$80 ; ; ; clear$bottom$line: lxi h,80*(lines-1) lxi b,80 call block$fill$space$80 jr compute$adr page ;* ;* B= bit position to set or clear ;* C= new bit value ;* ;* attr byte def. (in B and C) ;* bit 7-alternate char set (uper case set) ;* bit 6-reverse video ;* bit 5-underline ;* bit 4-blink ;* bit 0-full intensity ;* ;* set$attr$80: lda current$atr cma ; invert A ora b ; force new bit to 1 cma ; restore A ora c sta current$atr ret page ;* ;* ASCII codes(B) 20h to 2Fh set character color ;* 30h to 3Fh set background color ;* 50h to 5Fh set logical character color ;* 60h to 6Fh set logical background color ;* all others code do nothing ;* ;* set$color$80: mov a,b ; get color to A sui 20h ; remove the BIAS cpi 20h ; physical color ? (00h-1Fh) jrc ?col$80 ; yes, go set it mvi c,20h ; max color value+1 (00h-1Fh) call lookup$color$1 ; convert char in A to color (ret in A) ; C=max color character rc ; return if error mov a,m ; get color bytes ani 0fh ; LSB is 80 column color add b ; Add color offset back ; 0-f set forground color ; 10-1f set background color page ; ; set color in A (00-0F sets the character color) ; (10-1F sets the background color) ; ; This routine first calls lookup color to convert the 40 column ; color (normal color) to the 80 column RGBI color ; ?col$80: sta temp1 mvi c,20h ; max color value+1 (00h-1Fh) adi 30h ; restore a bias lxi h,color$convert$tbl ; table to use call lookup$color$2 ; convert to same color as 40 Column mov a,m ; get character color add b ; add color offset back cpi 10h ; character color? (0-f) jrc chr$col$80 ; yes, go do it ; no, fall thru and set background ; ; set background color (10-1F) ; ani 0Fh ; get value of 0 to F sta bg$color$80 push psw mvi a,26 ; color register call wait pop psw outp a ret ;* ;* ;* rd$color$80: lda bg$color$80 mov b,a lda current$atr mov d,a lda char$color$80 ret page ; ; set character color ; chr$col$80: mov b,a lda current$atr ani 0f0h ; remove old color ora b ; merge new color sta current$atr ; save new attr lda temp1 sta char$color$80 ; ; set current char position color to new color ; lhld char$adr ; get current cursor adr lxi d,800h ; offset to attr dad d ; pointing to current char attr call set$update$adr ; point to attr byte lda current$atr outp a ret page ;* ;* ;* ;* CEL$80: call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 inx b ; 1 to 80 to fill jr cont$space$fill ;* ;* ;* ;* CES$80: call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 xchg ; cursor address in DE lxi h,lines*80 xra a ; clear the carry dsbc DE ; count will be minus if on status line rm ; return if on status line mov b,h mov c,l ; count to BC xchg ; cursor address back to HL cont$space$fill: jmp block$fill$space$80 page ;* ;* ;* char$ins$80: call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 (1-80) lxi h,80-1 dad d ; point to end of line dcr a ; A=1 if at end of line jrz char$ins$80$end mov d,h mov e,l ; HL=DE= end of line address dcx h ; [HL--] -> [DE--] count BC push b push h push d call insert$low lxi b,800h ; attribute offset pop h dad b xchg pop h dad b pop b insert$low: push b call set$update$adr inp a xchg push psw call set$update$adr pop psw outp a xchg pop b dcx h dcx d dcx b mov a,b ora c jrnz insert$low lhld char$adr char$ins$80$end: jmp write$space$80 page ;* ;* ;* ;* char$del$80: call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 push d ; save line start address mov d,h mov e,l ; DE=HL=cursor address inx h ; [HL++]->[DE++] count BC call block$move$80 ; DE points to last position pop h ; recover line start address lxi d,80-1 dad d ; point to end of line jmp write$space$80 page ;* ;* ;* Moves one line at a time, down one line, starting with the next ;* to the bottom line. Once the cursor line is moved down, the ;* cursor line is cleared. ;* line$ins$80: lxi d,new$offset mvi a,lines-1 ; cursor on or past the last line ? lhld char$col cmp h jz clear$bottom$line ; no bottom, clear bottom line jrc line$ins$cont ; past, lxi h,(lines-2)*80 lxi d,(lines-1)*80 mvi b,lines move$next$down: call move$line$down lda char$row cmp b jrnz move$next$down call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 xchg ; get line start adr lxi b,80 jr block$fill$space$80 ; ; ; line$ins$cont: inr a cmp l rnz jmp update$it page ; ; INPUT: ; HL=source ; DE=dest ; B=line number ; OUTPUT: ; HL=source-80 ; DE=dest-80 ; B=line number - 1 ; move$line$down: push b push h push d lxi b,80 call block$move$80 lxi b,-80 pop h dad b xchg pop h dad b pop b dcr b ret page ;* ;* ;* line$del$80: lda char$row cpi lines ; is the cursor past the bottom line ? rnc ; yes, exit call cur$adr$80$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 lxi h,80 ; line length dad d ; HL=start of next line xchg ; move from address in DE push h ; save TO address lxi h,lines*80 xra a ; clear the carry dsbc DE mov b,h mov c,l ; count to BC pop h ; recover TO address xchg ; move from address back to HL call block$move$80 ; DE points to last position jmp clear$bottom$line page ; ; user interface point ; blk$fill: pop h ; get the return addres xthl ; get HL, ret adr to stack. jr block$fill$80 ; ; INPUT: ; HL=start address ; BC=count ; block$fill$space$80: lda current$atr mov e,a mvi d,' ' ; ; 80 block fill ; ; INPUT: ; HL=start address ; BC=count ; D=fill character, E=attribute ; block$fill$80: mov a,b ; get MSB of count to A ana a ; is it zero jrz fill$less$256 ; yes, move less than 256 bytes block$fill$cont$80: push h push d push b xra a call fill$data$80 pop b pop d pop h inr h djnz block$fill$cont$80 page ; ; ; fill$less$256: mov a,c ; get LSB of count to A ana a ; is it zero ? rz ; yes, none left to fill, return ; ; count in A (1 to 256) (0=256) ; HL=fill adr ; DE=fill character, and attribute ; fill$data$80: push psw ; save count push h ; save adr push d ; save fill character call fill$half$80 pop d ; recover fill character lxi b,800h ; offset to attributes pop h ; recover adr dad b ; HL=attr adr call do$twice? pop psw ; recover count mov d,e ; get the attr to D page ; ; fill$half$80: push psw ; save the count call set$update$adr ; write address to chip R18,R19 outp d ; write update data (R31) pop psw dcr a ; already wrote one above rz ; return if only one required push psw mvi a,24 call wait inp a ; get old value in reg 24 ani 7fh outp a ; clear R24(7), enabling block writes mvi a,30 call wait pop psw ; recover the count outp a ; write count to R30 if fixed$8563 ret else mvi b,0 mov c,a inx b ; add back the one removed above dad b push d ; save fill char (in D) push h ; HL=end address mvi a,18 call wait inp h mvi a,19 call wait inp l ; HL=current pointer pop d ; DE=end adr pop b ; get fill char (to B) finish$fill: call cmp$HL$DE ; compare dest with chip dest ; HL [DE--] count BC push b push d lddr ; DE=cursor position xchg call write$space$40 ; write a space at the cursor adr pop h lxi b,800h ; now move the attributes dad b pop b mov d,h mov e,l ; HL=DE= end of line address dcx h ; [HL--] -> [DE--] count BC lddr ; DE=cursor position ret ; ; ; write$space$40: lda rev$40 adi ' ' ; clear character, enable cursor mov m,a ret page ;* ;* ;* ;* char$del$40: lxi h,line$paint push h call cur$adr$40$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 lxi d,screen$40 dad d ; point to screen memory location dcr a ; at end of line ? jrz write$space$40 ; yes, then just erase cursor pos mov d,h mov e,l ; DE=HL=cursor address push b push h inx h ; [HL++]->[DE++] count BC ldir ; DE points to last position xchg call write$space$40 ; place a space at the end of line pop h lxi b,800h+1 ; now move the attributes dad b pop b mov d,h mov e,l ; HL=DE= cursor attr address inx h ; [HL++] -> [DE++] count BC ldir ; ret page ;* ;* ;* ;* line$ins$40: lxi h,screen$paint push h lda char$row$40 cpi lines-1 jrz clear$bottom$line$40 rnc ; return if on status line call cur$adr$40$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 lxi h,screen$40 dad d ; point to line start memory location push h ; save start address lxi d,80 dad d ; point to start of next line xchg ; cursor line(+1) start address in DE lxi h,screen$40+80*lines ; end of screen address xra a ; clear the carry bit (and A) dsbc DE ; HL=HL-DE mov b,h mov c,l ; count in lxi h,screen$40+80*(lines-1)-1 ; HL=end of screen-80 lxi d,screen$40+80*lines-1 ; DE=end of screen push b lddr page pop b lxi h,screen$40+80*(lines-1)-1+800h lxi d,screen$40+80*lines-1+800h lddr ; scroll the attributes pop h ; get cursor line start address mov d,h mov e,l inx d lxi b,80-1 jr space$fill$40 ; ; ; clear$bottom$line$40: lxi h,screen$40+(lines-1)*80 lxi d,screen$40+(lines-1)*80+1 lxi b,80-1 space$fill$40: lda rev$40 adi ' ' mov m,a ldir ret page ;* ;* ;* ;* line$del$40: lxi h,screen$paint push h lda char$row$40 cpi lines-1 ; on or past last line ? jrz clear$bottom$line$40 ; on, just clear it rnc ; past it, return call cur$adr$40$hl$sz$a ; HL=cur adr, DE=line start adr ; BC=count to move, A=BC+1 lxi h,screen$40 dad d ; point to line start memory location push h ; save cursor line start adr lxi d,80 dad d ; point to start of next line xchg ; cursor line(+1) start address in DE lxi h,screen$40+80*lines ; end of screen address xra a ; clear the carry bit (and A) dsbc DE ; HL=HL-DE mov b,h mov c,l ; count in xchg ; HL=start of line after cursor line pop d ; start of cursor line push b ; save count push h ; save source push d ; save dest ldir lxi b,800h ; get attribute offset pop h ; recover dest dad b ; attr dest xchg ; dest belongs in DE pop h ; recover source dad b ; attr source pop b ; recover count ldir jr clear$bottom$line$40 page ;* ;* B=bits to set or clear ;* C=bits new value ;* ;* attr byte def. (in B) ;* bit 7- ;* bit 6-reverse video * ;* bit 5-underline ;* bit 4-blink ;* bit 0-full intensity (masked off) ;* ;* set$attr$40: mov a,b ani 070h mov b,a mov a,c ani 070h mov c,a lda attr$40 cma ora b cma ; bits in B cleared A ora c ; add new value sta attr$40 ral ; get reverse attr in bit 7 ani 80h sta rev$40 ret page ;* ;* ASCII codes 20h to 2Fh set character color ;* 30h to 3Fh set background color ;* 40h to 4Fh set border color ;* 50h to 5Fh set locical character color ;* 60h to 6Fh set logical background color ;* 70h to 7Fh set logical border color ;* all others code do nothing ;* ;* All colors are assigned from color lookup table ;* set$color$40: mov a,b sui 20h cpi 30h jrc ?col$40 mvi c,30h ; max color value+1 (00h-2Fh) call lookup$color$1 ; HL points to table entry on ret rc ; exit if error mov a,m ; get table value again rrc rrc rrc rrc ; get upper 4 bits to lower ani 0fh add b ; get old MSB ?col$40: cpi 10h ; character color? (0-f) jrc char$color$40 ; yes, go do it ; no, fall thru test background, border cpi 20h ; background color? (10-1f) jrc back$color$40 ; yes, go do it ; no, fall thru and set border color ; ; set border color ; ani 0fh ; color from 0-f sta bd$color$40 lxi b,VIC+32 outp a ret page ; ; set background color (10-1F) ; back$color$40: ani 0Fh ; get value of 0 to F sta bg$color$40 lxi b,VIC+33 outp a ret ;* ;* ;* rd$color$40: lda bg$color$40 mov b,a lda bd$color$40 mov c,a lda attr$40 mov d,a ani 0fh ret ; ; set character color ; char$color$40: mov b,a lda attr$40 ani 0f0h ora b sta attr$40 lhld char$adr$40 lxi d,800h dad d mov m,a ; jmp line$paint page ; ; ; line$paint: lda old$offset mov b,a ora a cm trk$40 lda @off40 ; cmp b sta old$offset jrnz screen$paint call cur$adr$40$hl$sz$a ; DE=start of row adr (REL) lxi h,screen$40 ; get start of screen dad d ; HL=row start address (ABS) xchg ; save in DE lhld @off40 ; get current screen offset (0-39) dad d ; screen source adr in HL push h ; save for later lda char$row$40 ; get current row # mov l,a ; HL=row # (H=0) call Lx40$plus$VIC xchg ; place screen adr (25X40) in DE pop h ; recover logical screen adr (25X80) push h ; save for attr move push d mvi a,1 ; one line only call update$window$fun pop h ; recover screen pointer (25X40) lxi b,vic$color-vic$screen dad b ; point to Vic color memory xchg ; DE=color memory pointer pop h ; recover screen pointer (25X80) lxi b,800h ; offset to attributes dad b mvi a,1 ; one line only jr update$window$fun ; page ; ; hl=offset (0 to 39) ; screen$paint: lhld @off40 lda paint$size ; number of lines to move push h push psw ; save the count lxi d,screen$40 dad d ; point to start of visible screen lxi d,vic$screen ; place to move it to call update$window$fun pop psw pop h lxi d,screen$40+800h dad d ; add the screen offset lxi d,vic$color ; ; Always called from bank 0, Placed in common so that IO ; will not overlay this code. Can go in ROM ; update$window$fun: sta io$0 update$window$loop: lxi b,40 ; number of bytes to move ldir push d lxi d,80-40 ; advance pointer to next line dad d pop d dcr a jrnz update$window$loop sta bank$0 ret page ; ; ; trk$40: lda char$col$40 ; get the current column number sui 40-8 ; remove 1st 32 columns jrnc use$offset ; if pass column 32, set an offset xra a use$offset: ani 0f8h ; move sta @off40 ret page ; ; ; set$cursor$40: call no$cursor call line$paint ; will do a screen paint if required lda @off40 ; get screen offset mov b,a ; save offset (0 to 39) lhld char$col$40 ; H=row, L=col mov a,l ; get col # in A sub b ; remove offset jrc no$cursor cpi 40 jrnc no$cursor mov c,a mvi b,0 ; BC=cursor column # mov l,h ; get row # in L call Lx40$plus$VIC dad b jr set$flash ; no$cursor: lxi h,0 ; if H=0 (L=xx) then cursor off ; set$flash: shld flash$pos ret page ; ; ; Lx40$plus$VIC: mvi h,0 dad h ; 2X dad h ; 4X dad h ; 8X mov d,h mov e,l ; DE=8X dad h ; 16X dad h ; 32X dad d ; 8X+32X=40X lxi d,vic$screen dad d ; point to screen area ret page ; ; input: ; range 20h to 7fh in B ; output: ; in A ; ascii$to$petascii: mov a,b cpi 40h jrz is40 ; get at sign rc ; ret if code was 20h - 3fh cpi 'Z'+1 ; is it an upper case letter ? rc ; yes, code was 41h - 5Ah sui 40h cpi 60h-40h jrz was$60 ; 60h converted to 27h jrc was$5b$to$5f sui 20h cpi 'z'+1-60h rc ; code was 61h - 7Ah cpi '{'-60h jrz is$left$brace cpi '|'-60h jrz is$vert$bar cpi '}'-60h jrz isright$brace cpi '~'-60h rnz mvi a,64 ; commodore horz bar ret was$60: mvi a,126 ; solid upper left corner ret is$left$brace: mvi a,115 ; ret is$vert$bar: mvi a,93 ; commodore vertical bar ret is$right$brace: mvi a,107 ; ret was$5b$to$5f: cpi '\'-40h jrz is$back$slash cpi '_'-40h rnz mvi a,100 ; commodore under line ret is$back$slash: mvi a,127 ; upper left and lower right corners ret is40: xra a ret page ; ; ; cur$adr$40$hl$sz$a: lhld char$col$40 jr cur$adr$hl$sz$a ; ; ; cur$adr$80$hl$sz$a: lhld char$col ; ; INPUT: ; H=row L=col ; ; OUTPUT: ; HL=cursor address ; DE=cursor line start address ; BC=# character to end of line ( <80 ) ; (not counting the cursor position) ; A=BC+1 ; cur$adr$hl$sz$a: mvi a,80-1 ; get line length sub l ; A= mov c,a cur$adr$hl: mov b,l ; save column # mov l,h mvi h,0 ; HL=row # dad h ; 2x dad h ; 4x dad h ; 8x dad h ; 16x mov d,h mov e,l ; save 16x dad h ; 32x dad h ; 64x dad d ; 64x+16x=80x xchg ; DE=row start address mov l,b ; get saved column # mvi h,0 ; HL=column # dad d ; HL=cursor address mvi b,0 ; BC= count (if call to cur$adr$hl$sz$a:) inr a ; number of bytes to end of line (1-80) ret page ; ; destroys DE,HL,B,A ; lookup$color: mov a,b ; color supplied in B lookup$color$1: lhld color$tbl$ptr ; ; HL=table adr ; A= color input ; C= max allowable color value ; lookup$color$2: sui 30h ; remove bias rc cmp c ; above limit cmc rc ; yes, return input out-of-range mov b,a ; save adjusted color # ani 0fh ; get only the color # mov e,a mvi d,0 dad d ; get converted color address mov a,b ; get the ASCII char back ani 30h ; keep only char/background/borber bits mov b,a ; save char/background bit ret page ; ; ; bell: lxi b,sid+24 lhld sound$1 outp h mvi c,5 outp l lhld sound$2 inr c outp h mvi c,1 outp l lhld sound$3 mvi c,4 outp h outp l ret