; ;**************************************************************** ; ; EUMEL-SHard Graphikroutinen fuer 6502-Teil. ; Anfang: 20.05.86, Michael Staubermann ; Version 1.2, Mit Incremental-Fill, dicke Striche, COPY-Modus ; Stand: 12.01.87 ; .printx 'GRAFIK65.MAC' ;---------------------------------------------------------------------------- ; V A R I A B L E ;---------------------------------------------------------------------------- ; ; Konstante bit_a EQU 2C ; Skip 2 Bytes ; Switches graphic_mode EQU $C050 text_mode EQU $C051 full_graphics EQU $C052 page_1 EQU $C054 hires_mode EQU $C057 lc_00 EQU $C083 lc_01 EQU $C08B ;---------------------------------------------------------------------------- ; ; G R A P H I K Einsprung fuer alle Graphiksubtasks ; ; Eingang: $81 Subtasknummer ; 0 = Move (x, y) ; 1 = Draw (x, y) ; 2 = Testbit (x, y) --> $81 ; 3 = Control (on/off, bank, page, or/and/xor, ; patternsource, colour, pattern) ; 4 = Clear (page) ; 5 = Fill (muster) ; 6 = Trans (page a) to (page b) ; ; Ausgang: $81 (Nur bei Testbit) ; ;---------------------------------------------------------------------------- GRAFIK: lda subtask ; 0 - 6 cmp #7 bcc grafik1 rts ; unerlaubt grafik1: asl a tax lda gfunct,x sta 1 lda gfunct+1,x sta 2 ; 1/2 Sprungadressen jmp (1) ; Funktion aurufen gfunct: dw gmove, gdraw, gtest, gctrl, gclr, gfill, gtrans ;--------------------------------------------------------------------- ; ; G M O V E ; Graphikcursor auf Position (x, y) setzen ; ; Eingang: param1 = xpos ; param2 = ypos ; GMOVE: lda param1 sta xpos ; LOW xpos lda param1+1 sta xpos+1 ; HIGH xpos lda param2 sta ypos ; LOW ypos lda param2+1 sta ypos+1 ; HIGH ypos move_x: lda savepattern sta pattern lda savepattern+1 sta pattern+1 ; Linetypepattern auf Anfangswert rts ;--------------------------------------------------------------------- ; ; G D R A W ; Linie zur Position (x, y) zeichen ; ; Eingang: param1 = xpos ; param2 = ypos ; GDRAW: IF 0 lda param1 pha ; 'to' Parameter retten lda param1+1 pha lda param2 pha lda param2+1 pha ENDIF jsr draw ; draw (xpos,ypos TO param1,param2) IF 0 pla sta ypos+1 pla sta ypos pla sta xpos+1 pla sta xpos ENDIF rts ;--------------------------------------------------------------------- ; ; G T E S T ; Punkt (x, y) testen ; ; Eingang: param1 = xpos ; param2 = ypos ; Ausgang: param = result = Flags ; GTEST: lda param2+1 ; HIGH y bne ytohigh ; Carry is set lda param1+1 ; HIGH x ldx param1 ; LOW x ldy param2 ; LOW y jsr calcaddr ; Byteaddresse des Punktes berechnen ytohigh: lda #$FF ; 255 = Falsche Punktposition bcs testrts ; Return mit Ergebnis ldy #00 lda (address),y php ; Farbbit merken and bitmask,x ; Pixel ausmaskieren beq testcolor lda #01 ; Bit 0 : Zustand des gesuchten Pixels testcolor: plp bpl testrts ora #80 ; Bit 7 : Farbe testrts: sta result rts ;--------------------------------------------------------------------- ; ; G C T R L ; Verschiede Steuerfunktionen ; ; Eingang: param1 s.u. ; Steuerbits: ; 0: 0 = graphik off ; 1 = graphik on ; 1: 0 = Sichtbare Seite 0 ; 1 = Sichtbare Seite 1 ; 2: 0 = Bearbeitete Seite 0 (2000..3FFF) ; 1 = Bearbeitete Seite 1 (4000..5FFF) ; 3,4: 0 = OR (Setzen) ; 1 = AND (Loeschen) ; 2 = XOR (Invertieren) ; 3 = COPY (kopieren = loeschen/setzen) ; 5: 0 = Full Graphics display ; 1 = Mixed Graphics display (4 Zeilen Text) ; 6: 0 = param2 ist Linetypepattern ; 1 = savepattern ist Linetypepatt. ; 7: 0 = Violett ; 1 = Gelb ; 8..11 = Strichdicke ; ; param2 ist 16Bit Pattern (falls Bit 6 = 0) ; GCTRL: lda param1 ; Steuerbits and #80 ; Bit 7 = Farbe sta colormask lsr param1 ; Bit 0 = Graphik on/off bcs graphon lda text_mode lda page_1 bcc bit12 graphon: lda graphic_mode lda hires_mode lda param1 ; Bit 2 = Page and #01 tax sta page_1,x ; Page Select bit12: lsr param1 ; Bit 1 ins Carry lsr param1 ; Bit 2 ins Carry bcs page2sel lda #20 db bit_a page2sel: lda #40 sta pagebase lda param1 and #03 ; Bit 3,4 = Bitmode sta bitmode lsr param1 ; Bit 3 ins Carry lsr param1 ; Bit 4 ins Carry lda param1+1 and #0F bne setthick lda #1 ; Default 0: 1 Strich setthick: sta thick ; Strichdicke in 8..11 lda param1 ; Bit 5 = full (0) or mixed (1) Graph. and #01 tax sta full_graphics,x lsr param1 ; Bit 5 ins Carry lsr param1 ; Bit 6 ins Carry bcs saved lda param2 ; Parameter 2 (Word) Pattern sta pattern ; in interne Linepattern kopieren sta savepattern lda param2+1 sta pattern+1 sta savepattern+1 bcc ctrlret saved: lda pattern ; Internes Savepattern als Workpattern sta savepattern ; benutzen lda pattern+1 sta savepattern+1 ctrlret: rts ;--------------------------------------------------------------------- ; ; G C L R ; Graphikseite loeschen, bzw. mit einem Bitmuster fuellen ; ; Eingang: param1 = Seite (0..3) ; param2 = Byte (0..255) ; GCLR: lda param1 jsr page_addr ; Anfangsaddresse der Page --> A ; y := 0 sta address+1 sty address ldx #20 ; 32 Pages lda param2 gclr1: sta (address),y iny bne gclr1 inc address+1 dex bne gclr1 rts page_addr: and #3 asl a asl a asl a asl a asl a adc #20 ; + Offset fuer erste Grafikseite ldy #0 rts ;--------------------------------------------------------------------- ; ; G F I L L ; Umrandete Flaeche Fuellen ; ; Eingang: param1 = Nummer des Fuellmusters ; GFILL: lda lc_01 lda lc_01 ; Select Page 1 D000..DFFF (Stack) lda param1 jsr fill lda lc_00 lda lc_00 ; Select Page 0 D000..DFFF (Spooler) rts ;--------------------------------------------------------------------- ; ; G T R A N S ; Graphikseite in eine andere Grafikseite kopieren ; ; Eingang: param1 = 'from'-Page (0..3) ; param2 = 'to'-Page (0..3) ; GTRANS: lda param1 jsr page_addr sta address+1 ; 'from' - Pagebase sty address lda param2 jsr page_addr sta param1+1 sty param ; 'to' - Pagebase ldx #20 ; 32 Pages gtrans1: lda (address),y sta (param1),y iny bne gtrans1 inc address+1 inc param1+1 dex bne gtrans1 rts ;-------------------------------------------------------------------------- ; Umrandete Graphikflaeche (xpos, ypos) ausfuellen ; Musternummer in A FILL: and #0F ; 16 Muster a 64 Bit asl a ; *8 (8 Bytes pro Muster) asl a asl a ; Offset auf Muster sta olderror+1 lda pagebase sta olderror ; Merken lda #wrkpage ; Workpage (alter Inhalt geloescht!) sta pagebase jsr fill1 ; ggf POP Returnaddress lda olderror sta pagebase ; restoren rts fill1: lda bitmode and #1 sta creg lda #2 sta areg+1 ; stackpointer lda ypos+1 bne fill1d ; Out of Window ldx xpos stx xa ; xpos low (fuer Muster) lda xpos+1 sta xb ldy ypos sty ya ; yposlow (fuer Muster) jsr startxy bcc fill1c fill1d: rts ; Ausserhalb oder auf Punkt fill1c: ldx #wrkpage stx address+1 ldx olderror ; Echte Seite stx link+1 ldx #20 ; 8k ldy #0 sty address sty link fill1b: lda (link),y ; Echte Seite in Arbeitsseite kopieren sta (address),y ; Arbeitsseite loeschen iny bne fill1b inc address+1 inc link+1 dex bne fill1b lda xpos+1 ldx xpos ldy ypos jsr startxy fill2: ldy creg+1 ; Byte Offset ldx breg+1 ; Bit Offset jsr testquick ; Bei (x,y) Punkt gesetzt ? bcc fill2h ; Punkt gesetzt jsr poppos jmp fill2 ; (x-1, y) testen fill2h: lda breg+1 sta dx lda creg+1 sta dx+1 lda xa sta xa+1 ; Save xpos lda xb sta xb+1 lda xa bne fill2d2 dec xb fill2d2: dec xa jsr decx ; x-1, y bleibt bcs fill2d jsr testquick bcc fill2h fill2d: lda dx ; Altes x wiederherstellen sta breg+1 ; (Der letzte Punkt vorm linken lda dx+1 ; Rand) sta creg+1 lda xa+1 sta xa lda xb+1 sta xb fill4: ; (x, y-1) testen lda address ; ypos retten sta dy lda address+1 sta dy+1 lda breg sta yb lda ya ; ypos low sta ya+1 dec ya jsr decy ; y-1 bcs fill2a jsr testquick bcs fill2a jsr clrstack ; Hier auch 'pushpos' fill2a: ; (x, y+1) testen jsr incy bcs fill2e jsr incy bcs fill2e inc ya inc ya jsr testquick bcs fill2e jsr clrstack ; Hier auch 'pushpos' fill2e: ; Altes y wiederherstellen lda dy sta address ; ypos widerherstellen lda dy+1 sta address+1 lda yb sta breg lda ya+1 sta ya jsr pointquick inc xa bne fill2g inc xb fill2g: jsr incx bcs fill2i jsr testquick bcc fill4 ; Punkt bei (x+1, y) ? fill2i: jsr poppos ; Gerettete x/y Pos vom Stack jmp fill2 ; Damit nochmal (pseudorekursion) ;-------------------------------------------------------------------------- ; Hilfsroutinen fuer 'GFILL' testquick: lda (address),y and bitmask,x beq testquick1 ; Kein Punkt gesetzt lda #1 testquick1: eor creg ; umdrehen, falls AND/COPY lsr a ; SEC/CLC rts pointquick: lda ya ; ypos low and #7 ora olderror+1 ; Offset auf Muster tay lda xa and #7 tax lda bitmask,x ; xpos Bit and muster,y ; ypos Byte sta yb+1 ; 0, wenn kein Punkt gesetzt ldx breg+1 ldy creg+1 lda (address),y eor bitmask,x ; Bei OR loeschen, bei AND setzen! sta (address),y ; Zum Merken in Workpage ; Test, ob auch in echter Seite Punkt lda yb+1 beq pointquick1 ; Nicht mehr in echter Seite setzen lda address+1 pha and #$1F ; Nur 8k Bits ora olderror ; Echte pagebase sta address+1 lda (address),y and #$7F ora colormask eor bitmask,x sta (address),y ; In echter Seite setzen pla sta address+1 pointquick1: rts poppos: ; x/y Pos vom Stack holen ldx areg+1 ; stackpointer cpx #2 beq poppos1 dex ; ? ggf beq poppos1 beq poppos1 lda stack+000,x ; xpos sta breg+1 lda stack+100,x sta creg+1 lda stack+200,x ; ypos sta address lda stack+300,x sta address+1 lda stack+400,x sta breg lda stack+500,x ; xpos low sta xa lda stack+600,x ; xpos high sta xb lda stack+700,x ; ypos low sta ya stx areg+1 ; stackpointer rts poppos1: pla pla rts ; Fill verlassen clrstack: ; Stack aufraeumen und pushpos ldx #$FE ; creg+1, da Neues startxy gegeben wird stx yb+1 ; Flag, ob zweites mal clrstack ldx areg+1 ; stackpointer clrstack4: dex lda stack+700,x cmp ya bne clrstack3 lda stack+600,x ; (stack)+1 --> temp (in A/Y) ldy stack+500,x iny bne clrstack2 clc adc #1 clrstack2: cmp xb ; Stacktop = xpos-1 ? bne clrstack3 cpy xa bne clrstack3 lda breg+1 ; xpos replacen sta stack+000,x lda creg+1 sta stack+100,x lda xa sta stack+500,x lda xb sta stack+600,x rts clrstack3: inc yb+1 ; Flag fuer 2. Durchlauf bne clrstack4 pushpos: ; xpos/ypos auf Stack bringen ldx areg+1 ; stackpointer lda breg+1 sta stack+000,x lda creg+1 sta stack+100,x lda address sta stack+200,x lda address+1 sta stack+300,x lda breg sta stack+400,x lda xa sta stack+500,x lda xb sta stack+600,x lda ya sta stack+700,x inx beq pushpos1 ; Stackoverflow stx areg+1 ; stackpointer pushpos1: rts ;=========================================================================== ; Incremental Adresses ; Belegt breg = rowstartoffset, breg+1 = x-reg = bitoffset ; creg+1 = y-reg = xbyte offset, ; address/address+1 = Byteaddresse ; ; Fuer jede Routine gilt: ; Ausgang: X = Bitoffset, Y = Byteoffset, SEC = Out of Window ; Trat SEC auf, ist die aktuelle Position unveraendert (!) ; Beispiel: jsr incy ; bcs fehler ; lda (address),y ; and bitmask,x ;--------------------------------------------------------------------------- ; Start Scan ; ; Eingang: A: HIGH xpos ; X: LOW xpos ; Y: LOW ypos STARTXY: cmp #02 ; xpos >= 512 ? bcc startxy1 startxy2: rts ; Carry is Set startxy1: cmp #01 bne startxy3 ; xpos < 256 cpx #18 ; xpos >= 280 ? bcs startxy2 ; Bereichsfehler startxy3: cpy #$C0 ; ypos >= 192 ? bcs startxy2 pha ; xpos (HIGH) retten tya pha ; adr := rowstart [ypos DIV 8] + (ypos MOD 8) * 1024 + xpos DIV 7 lsr a ; ypos DIV 8 lsr a lsr a asl a ; Fuer Tabellenzugriff * 2 (Bit 0 = 0) tay sty breg ; rowstart Offset lda rowstart,y ; Tabelle der Zeilenanfaenge sta address lda rowstart+1,y clc adc pagebase sta address+1 pla ; ypos and #07 ; MOD 8 eor #07 ; y = 0 ist unten links asl a ; * 4 (* 256) asl ; Carry is cleared adc address+1 ; Mikrozeile addieren sta address+1 pla ; xpos (HIGH) --> Y tay txa ; xpos (LOW) --> A jsr divide7 ; A/Y --> A (Quotient), X (Remainder) sta creg+1 tay ; y-reg = Byteoffset stx breg+1 ; Bitoffset clc ; Carry cleared = ok rts ;------------------------------------------------------------------------- ; Increment actual y INCY: lda address+1 and #1C beq incy1 ; naechste Mikrozeile lda address+1 sec sbc #4 sta address+1 clc ; ok incy2: ldy creg+1 ldx breg+1 rts incy1: ldy breg iny iny ; naechste Makrozeile cpy #30 ; tabellenende ? bcs incy2 ; Fehler, nichts veraendert sty breg lda rowstart,y sta address ; Carry war cleared lda rowstart+1,y adc pagebase adc #1C ; 7. Mikrozeile sta address+1 bcc incy2 ; Always ;-------------------------------------------------------------------------- ; Decrement actual y DECY: lda address+1 and #1C cmp #1C ; 7. Mikrozeile ? beq decy1 ; naechste Mikrozeile lda address+1 adc #4 sta address+1 decy2: ldy creg+1 ldx breg+1 rts decy1: ldy breg ; naechste Makrozeile sec beq decy2 ; Out of Window ? dey dey sty breg lda rowstart,y sta address clc lda rowstart+1,y adc pagebase sta address+1 bcc decy2 ; Always ;------------------------------------------------------------------------- ; Increment actual x INCX: ldy creg+1 ldx breg+1 cpx #6 bcs incx1 inx clc incx2: stx breg+1 ; y schon = creg+1 rts incx1: inc creg+1 iny ldx creg+1 cpx #28 ; Out of Window ? ldx #0 bcc incx2 ; CLC: ok dec creg+1 ; Wieder Rueckgaengig rts ;----------------------------------------------------------------------- ; Decrement actual x DECX: ldy creg+1 ldx breg+1 beq decx1 dex decx2: stx breg+1 ; y schon creg+1 rts decx1: ldx #6 dec creg+1 dey clc bpl decx2 ; < 0 ? sec ; Out of Window ! inc creg+1 ; Alter Zustand rts ;========================================================================== ; Absolute Adresses ;-------------------------------------------------------------------------- ; ; C A L C A D D R ; Berechnet die Addresse eines Pixels ; ; Eingang: A: HIGH xpos ; X: LOW xpos ; Y: ypos ; Ausgang: address,address+1: Addresse des Bytes mit Pixel ; Carry: Set = Pixelpos ausserhalb des Fensters ; X: Bitnummer im addressierten Byte (0..6) ;--------------------------------------------------------------------------- CALCADDR: cmp #02 ; xpos >= 512 ? bcc less512 rangeerr: rts ; Carry is Set less512: cmp #01 bne xposok ; xpos < 256 cpx #18 ; xpos >= 280 ? bcs rangeerr ; Bereichsfehler xposok: cpy #$C0 ; ypos >= 192 ? bcs rangeerr pha ; xpos (HIGH) retten tya pha ; adr := rowstart [ypos DIV 8] + (ypos MOD 8) * 1024 + xpos DIV 7 lsr ; ypos DIV 8 lsr lsr asl ; Fuer Tabellenzugriff * 2 (Bit 0 = 0) tay lda rowstart,y ; Tabelle der Zeilenanfaenge sta address lda rowstart+1,y clc adc pagebase sta address+1 pla ; ypos and #07 ; MOD 8 eor #07 ; y = 0 ist unten links asl ; * 4 (* 256) asl ; Carry is cleared adc address+1 sta address+1 pla ; xpos (HIGH) --> Y tay txa ; xpos (LOW) --> A jsr divide7 ; A/Y --> A (Quotient), X (Remainder) clc adc address sta address bcc calcret inc address+1 clc ; Carry cleared = ok calcret: rts ;----------------------------------------------------------------------------- ; ; N E G ; Vorzeichenwechsel ; Eingang/Ausgang: A/X (HIGH/LOW) ;----------------------------------------------------------------------------- NEG: pha txa eor #$FF clc adc #01 tax pla eor #$FF adc #00 rts ;--------------------------------------------------------------------------- ; ; D I V I D E 7 ; Division durch 7 mit Rest ; Eingang: A: Low, Y: High (Nur 0 oder 1) ; Ausgang: A: Quotient (Auch in quotient) ; X: Rest ;-------------------------------------------------------------------------- DIVIDE7: ldx #00 ; Quotient Schieberegister loeschen stx quotient ldx #$E0 ; 224 = 7 * 2^5 als Startwert stx divmask ldx #06 ; Anzahl Verschiebungen cpy #01 ; Zahl > 255 ? bne shiftloop ; Carry is set inc quotient adc #1F ; (Zahl MOD 256) + 32 bne shift2loop ; Erste Subtraktion ueberspringen shiftloop: sec sbc divmask ; Probeweise subtrahieren php ; Borrow merken rol quotient ; Borrow in quotient rotieren plp bcs shift2loop adc divmask ; Falls zuviel subtrahiert wieder add. shift2loop: lsr divmask ; Dann nur noch die Haelfte subtr. dex bne shiftloop tax ; Rest der Division lda quotient ; Quotient rts ;---------------------------------------------------------------------------- ; ; P O I N T ; Setzt/Loescht Punkt an bestimmter Position ; Eingang: Position in xpos/ypos ; Linepattern in pattern ; Farbmaske in colormask ; Bitmodus in bitmode ;--------------------------------------------------------------------------- ;DOPOINT: ; ldy bitmode ; bpl patternres ; Always POINT: ldy bitmode asl pattern rol pattern+1 bcs patternset cpy #03 ; Copymodus bne pointret ; Keine Aktion ldy #01 ; Loeschen bne patternres ; Always patternset: inc pattern ; 1 links im pattern setzen patternres: sty tempmode lda ypos+1 bne pointret lda xpos+1 ldx xpos ldy ypos ;MAKEDOT: jsr calcaddr ; Punktaddresse berechnen bcs pointret ; Ausserhalb des Bildschirms ldy #00 lda (address),y ldy tempmode bne mode1 mode0: ora bitmask,x ; Modus 0 = setzen bcc setcolor mode1: dey bne mode2 and notbitmask,x ; Modus 1 = loeschen bcc setcolor mode2: dey bne mode0 ; Modus 3 (copy) wie Modus 0 eor bitmask,x ; Modus 2 = invertieren bcc setcolor setcolor: ldy #00 and #7F ; Altes Farbbit loeschen ora colormask ; Farbbit neu setzen sta (address),y ; Graphikbyte zurueckschreiben pointret: rts ;----------------------------------------------------------------------------- ; Drawthick zeichnet eine dicke Linie drawthick: lda param1 pha lda param1+1 pha ; to-pos retten lda param2 pha lda param2+1 pha lda savepattern pha lda savepattern+1 pha lda pattern ; Linetype auf Startwert sta savepattern lda pattern+1 sta savepattern+1 dec thick ; x- oder y- Richtung feststellen: ; x direction := abs (xto - xfrom) > abs (yto - yfrom) lda param1 sec sbc xpos tax lda param1+1 sbc xpos+1 bcs drawthick1 jsr NEG ; Absolutwert (A/X) drawthick1: sta dx+1 stx dx lda param2 sec sbc ypos tax lda param2+1 sbc ypos+1 bcs drawthick2 jsr NEG ; Absolutwert (A/X) drawthick2: pha txa sec sbc dx pla sbc dx+1 ; Nur das Vorzeichen wichtig pha ; xdirection, wenn A < 0 ; Start- und Endpunkt der mittleren Linie berechnen bpl drawthick3 ; y direction ; start.x := xfrom - thick x ; to.x := xto + thick x ; start.y := yfrom ; to.y := yto ; thick x : IF xto < xfrom THEN -thick ELSE +thick FI lda param1 sec sbc xpos ; xto - xfrom lda param1+1 sbc xpos+1 bcs drawthick4 ; xto >= xfrom (xto-xfrom >= 0) ; xto < xfrom lda xpos ; Carry is cleared adc thick sta xa ; start.x lda xpos+1 adc #0 sta xa+1 lda param1 ; to.x sec sbc thick sta xb lda param1+1 sbc #0 sta xb+1 jmp drawthick5 drawthick4: lda xpos ; Carry is set sbc thick sta xa lda xpos+1 sbc #0 sta xa+1 lda param1 clc adc thick sta xb lda param1+1 adc #0 sta xb+1 drawthick5: ; start.y := ypos ; to.y := param2 lda ypos sta ya lda ypos+1 sta ya+1 lda param2 sta yb lda param2+1 sta yb+1 jmp drawthick8 drawthick3: ; x direction ; start.x := xfrom ; to.x := xto ; start.y := yfrom - thick y ; to.y := yto + thick y ; thick y : IF yto < yfrom THEN -thick ELSE +thick FI lda param2 sec sbc ypos ; yto - yfrom lda param2+1 sbc ypos+1 bcs drawthick6 ; yto >= yfrom (yto-yfrom >= 0) ; yto < yfrom lda ypos ; Carry is cleared adc thick sta ya ; start.y lda ypos+1 adc #0 sta ya+1 lda param2 ; to.y sec sbc thick sta yb lda param2+1 sbc #0 sta yb+1 jmp drawthick7 drawthick6: lda ypos ; Carry is set sbc thick sta ya lda ypos+1 sbc #0 sta ya+1 lda param2 clc adc thick sta yb lda param2+1 adc #0 sta yb+1 drawthick7: ; start.x := xpos ; to.x := param1 lda xpos sta xa lda xpos+1 sta xa+1 lda param1 sta xb lda param1+1 sta xb+1 ;------ ; FOR diff FROM -thick TO thick REP drawsingl PER drawthick8: ldx thick lda #0 jsr NEG ; -thick sta areg+1 stx areg ; = diff drawthick11: ldx areg lda areg+1 bne drawthick9 cpx thick ; > +thick ? beq drawthick9 bcc drawthick9 ; PER ; restore pattern pla ; x direction inc thick pla sta savepattern+1 sta pattern+1 pla sta savepattern sta pattern pla sta param2+1 ; To-Pos restoren pla sta param2 pla sta param1+1 pla sta param1 lda param1 sta xpos lda param1+1 sta xpos+1 lda param2 sta ypos lda param2+1 sta ypos+1 rts ; singlevector: drawthick9: pla pha ; xdirection ? bpl drawthick10 ; y direction ; move (start.x, start.y-diff) ; ; draw (to.x, to.y-diff) ; lda xa sta xpos lda xa+1 sta xpos+1 ; xpos := start.x lda ya sec sbc areg sta ypos lda ya+1 sbc areg+1 sta ypos+1 ; ypos := start.y - diff jsr move_x lda xb ; xto := to.x sta param1 lda xb+1 sta param1+1 lda yb ; yto := to.y - diff sec sbc areg sta param2 lda yb+1 sbc areg+1 sta param2+1 jsr drawsglvec ; Linie von x/ypos nach param1/2 jmp drawthick12 drawthick10: ; move (start.x + diff, start.y) ; ; draw (to.x + diff, to.y) ; lda xa clc adc areg sta xpos ; xpos := start.x + diff lda xa+1 adc areg+1 sta xpos+1 lda ya ; ypos := start.y sta ypos lda ya+1 sta ypos+1 jsr move_x lda xb clc adc areg ; xto := to.x + diff sta param1 lda xb+1 adc areg+1 sta param1+1 lda yb sta param2 lda yb+1 ; yto := to.y sta param2+1 jsr drawsglvec ; Linie von x/ypos nach param1/2 ; NEXT diff drawthick12: inc areg bne drawthick13 inc areg+1 drawthick13: jmp drawthick11 ; diff INCR 1 ;----------------------------------------------------------------------------- ; ; D R A W ; Linie zwischen zwei Punkten zeichnen ; Eingang: FROM-Position in xpos/ypos ; TO-Position in param1/param2 ; Attribute in bitmode,pattern,colormask ;----------------------------------------------------------------------------- DRAW: ; X-Vektorrichtung bestimmen ; dx := xto - xfrom ; right := sign (dx) ; dx := ABS dx lda thick bne draw1 rts ; Unsichtbare Linie draw1: cmp #1 beq drawsglvec ; Eine Linie Zeichnen jmp drawthick drawsglvec: ldy #00 ; Vorzeichen fuer right: positiv lda param1 ; xto (LOW) sec sbc xpos ; xfrom (LOW) tax lda param1+1 ; xto (HIGH) sbc xpos+1 ; xfrom (HIGH) bpl dxpositiv jsr NEG ; dx := -dx dey ; Vorzeichen fuer right: negativ dxpositiv: sta dx+1 stx dx sty right ; Y-Vektorrichtung bestimmen ; dy := yto - yfrom ; up := sign (dy) ; dy := ABS dy ldy #00 ; Vorzeichen fuer up: positiv lda param2 ; yto sec sbc ypos ; yfrom tax lda param2+1 sbc ypos+1 bpl dypositiv jsr NEG ; dy := -dy dey ; Vorzeichen fuer up: negativ dypositiv: sta dy+1 stx dy sty up ; init vectorloop ldx #00 stx olderror stx olderror+1 ; olderror := 0 ldx #xpos ; xpointer zeigt auf xpos stx xpointer ldx #ypos stx ypointer ; ypointer zeigt auf ypos ; dy > dx ==> dx - dy < 0 ==> Parameter vertauschen lda dx sec sbc dy ; Ergebnis unwichtig, nur Carry lda dx+1 ; dx (HIGH) sbc dy+1 ; dy (HIGH) bpl dy_lsequal_dx ; Parameter vertauschen lda xpointer ; xpointer und ypointer vertauschen ldx ypointer stx xpointer sta ypointer lda up ; up und right vertauschen ldx right stx up sta right lda dx ; dx (LOW) und dy (LOW) vertauschen ldx dy stx dx sta dy lda dx+1 ; dx (HIGH) und dy (HIGH) vertauschen ldx dy+1 stx dx+1 sta dy+1 dy_lsequal_dx: ; vector(xpos, ypos, dx, dy, right, up) ; uprighterror := dy - dx ; righterror = dy lda dy sec sbc dx sta uprighterror lda dy+1 sbc dx+1 sta uprighterror+1 ; Schleife: dx DECR 1 nextpixel: jsr POINT ; POINT (xpos, ypos) lda dx ; dx = counter = 0 ? ora dx+1 bne do_one_step rts ; Ende der Vektorloop do_one_step: ldx xpointer ; Referenz auf xpos oder ypos bit right ; right < 0 ? bpl rightstep ; sonst leftstep ;leftstep: lda 0,x ; xpos-Referenz DEC 1 bne xposdec1 dec 1,x ; Highbyte von xpos xposdec1: dec 0,x ; Lowbyte von xpos jmp detdirection rightstep: inc 0,x bne detdirection inc 1,x detdirection: ; IF abs (olderror + righterror) < abs (olderror + uprighterror) ; THEN do_right_step ELSE do_upright_step FI ; abs (olderror + uprighterror) = abs1 lda olderror clc adc uprighterror tax lda olderror+1 adc uprighterror+1 bpl abs1positiv jsr NEG ; abs1 := -abs1 (A=HIGH, Y=LOW) abs1positiv: stx temporary ; Fuer spaetere Subtraktion merken sta temporary+1 ; abs (olderror + righterror) = abs2 lda olderror clc adc righterror tax lda olderror+1 adc righterror+1 bpl abs2positiv jsr NEG ; abs2 := -abs2 (A=HIGH, X=LOW) abs2positiv: tay ; abs2 (HIGH) retten txa ; abs2 (LOW) --> A sec sbc temporary ; abs1 (LOW) tya ; Nur Carrybit wesentlich sbc temporary+1 ; abs1 (HIGH) bmi do_right_step ;do_upright_step: ; ypos INCR up ldx ypointer bit up ; Vorzeichen von up bpl yposinc1 lda 0,x ; ypointer enthaelt Offset ab xpos bne yposdec1 dec 1,x yposdec1: dec 0,x jmp xyerror yposinc1: inc 0,x bne xyerror inc 1,x xyerror: ; olderror INCR uprighterror lda olderror clc adc uprighterror sta olderror lda olderror+1 adc uprighterror+1 sta olderror+1 jmp dxdec1 do_right_step: ; olderror INCR righterror lda olderror clc adc righterror sta olderror lda olderror+1 adc righterror+1 sta olderror+1 dxdec1: lda dx bne dxdec dec dx+1 dxdec: dec dx jmp nextpixel ; zum Schleifenanfang ;-------------------------------------------------------------------------- ; Muster fuer GFILL: muster: .RADIX 2 DB 11111111 ; 0: gefuellt DB 11111111 DB 11111111 DB 11111111 DB 11111111 DB 11111111 DB 11111111 DB 11111111 DB 10101010 ; 1: Halb DB 01010101 DB 10101010 DB 01010101 DB 10101010 DB 01010101 DB 10101010 DB 01010101 DB 11111111 ; 2: Waagerecht (grob) DB 00000000 DB 00000000 DB 00000000 DB 11111111 DB 00000000 DB 00000000 DB 00000000 DB 11111111 ; 3: Waagerecht (fein) DB 00000000 DB 11111111 DB 00000000 DB 11111111 DB 00000000 DB 11111111 DB 00000000 DB 10001000 ; 4: Senkrecht (grob) DB 10001000 DB 10001000 DB 10001000 DB 10001000 DB 10001000 DB 10001000 DB 10001000 DB 10101010 ; 5: Senkrecht (fein) DB 10101010 DB 10101010 DB 10101010 DB 10101010 DB 10101010 DB 10101010 DB 10101010 DB 11111111 ; 6: Gerades Raster (grob) DB 10001000 DB 10001000 DB 10001000 DB 11111111 DB 10001000 DB 10001000 DB 10001000 DB 11111111 ; 7: Gerades Raster (fein) DB 10101010 DB 11111111 DB 10101010 DB 11111111 DB 10101010 DB 11111111 DB 10101010 DB 10001000 ; 8: Links Schraffur DB 00010001 DB 00100010 DB 01000100 DB 10001000 DB 00010001 DB 00100010 DB 01000100 DB 10001000 ; 9: Rechts Schraffur DB 01000100 DB 00100010 DB 00010001 DB 10001000 DB 01000100 DB 00100010 DB 00010001 DB 10001000 ; 10: Schraeges Gitter DB 01010101 DB 00100010 DB 01010101 DB 10001000 DB 01010101 DB 00100010 DB 01010101 DB 10101010 ; 11: Punktraster DB 00000000 DB 10101010 DB 00000000 DB 10101010 DB 00000000 DB 10101010 DB 00000000 DB 11111111 ; 12: Mauer DB 01000000 DB 01000000 DB 01000000 DB 11111111 DB 00000100 DB 00000100 DB 00000100 DB 00100010 ; 13: Korb DB 01010101 DB 10001000 DB 10001000 DB 10001000 DB 01010101 DB 00100010 DB 00100010 DB 00000000 ; 14: Wellenlinie DB 00100010 DB 01010101 DB 10001000 DB 00000000 DB 00100010 DB 01010101 DB 10001000 ;usermuster: DB 10000000 ; 15: User (Default: Zickzack) DB 01000001 DB 00100010 DB 00010100 DB 00001000 DB 00000000 DB 00000000 DB 00000000 .RADIX 16 ;---------------------------------------------------------------------------- ; T A B E L L E N ;---------------------------------------------------------------------------- bitmask: db $01, $02, $04, $08, $10, $20, $40, $80 notbitmask: db $FE, $FD, $FB, $F7, $EF, $DF, $BF, $7F ; Graphikzeilenanfaenge, Ypos 0 ist unten rowstart: dw 03D0, 0350, 02D0, 0250 dw 01D0, 0150, 00D0, 0050 dw 03A8, 0328, 02A8, 0228 dw 01A8, 0128, 00A8, 0028 dw 0380, 0300, 0280, 0200 dw 0180, 0100, 0080, 0000 .printx 'Ende'