summaryrefslogtreecommitdiff
path: root/system/shard-z80-ruc-64180/1.5/src/GRAFIK65.MAC
diff options
context:
space:
mode:
Diffstat (limited to 'system/shard-z80-ruc-64180/1.5/src/GRAFIK65.MAC')
-rw-r--r--system/shard-z80-ruc-64180/1.5/src/GRAFIK65.MAC1636
1 files changed, 1636 insertions, 0 deletions
diff --git a/system/shard-z80-ruc-64180/1.5/src/GRAFIK65.MAC b/system/shard-z80-ruc-64180/1.5/src/GRAFIK65.MAC
new file mode 100644
index 0000000..fa89db3
--- /dev/null
+++ b/system/shard-z80-ruc-64180/1.5/src/GRAFIK65.MAC
@@ -0,0 +1,1636 @@
+;
+;****************************************************************
+;
+; 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'
+ \ No newline at end of file