bildschirmausgabe.asm

Aus C64-Wiki
Zur Navigation springenZur Suche springen

Quelltext[Bearbeiten | Quelltext bearbeiten]

 ;####################################################################
 ;# Programm:      Sammlung von Funktionen für die Bildschirmausgabe
 ;# Dateiname:     bildschirmausgabe.asm
 ;#
 ;# Assembler:     ACME
 ;# Assemblierung: acme -f cbm -o output.prg bildschirmausgabe.asm
 ;#
 ;# Laden mit:     LOAD"output.prg",8,1
 ;#
 ;# Aufruf mit:    Ab der Adresse $c000 ist eine Sprungtabelle, über
 ;#                die jede Funktion mit jsr aufgerufen werden kann
 ;#
 ;# Quelltext:     * Kleinschreibung (bis auf Kommentare)
 ;#                * nur Leerzeichen, keine Tabulatoren
 ;#                * Labels immer in eigener Zeile
 ;#                * Befehle zwei Zeichen eingerückt
 ;#                * Kommentare i.d.R. nach den Befehlen
 ;#
 ;# Beschreibung:  Eine Sammlung an Funktionen zur Bildschirmausgabe.
 ;#                Sie ermöglicht die Auswahl von fünf verschiedenen
 ;#                festgelegten Bereichen (Fenster), die für die
 ;#                Ausgabe, das Löschen und das Scrolling gelten.
 ;#
 ;#                Die fünf festgelegten Bereiche, die als Fenster
 ;#                ausgewählt werden können, sind der gesamte Bild-
 ;#                schirm, sowie die linke, rechte, obere und untere
 ;#                Hälfte des Bildschirms.
 ;#
 ;#                Im ausgewählten Fenster sind folgende Aktionen
 ;#                möglich:
 ;#                * Löschen des gesamten Fensters
 ;#                * Vert. Scrolling des gesamten Fensters nach oben
 ;#                * Horiz. Scrolling der aktuellen Zeile nach links
 ;#                * Ausgabe einzelner Zeichen (direkt als Bildschirm-
 ;#                  code und ASCII)
 ;#                * Zeilenumbruch (mit vertikalem Scrolling)
 ;#                * Ausgabe eines 8-Bit-Werts in hexadezimaler,
 ;#                  binärer und dezimaler Form
 ;#
 ;#                Die Zeilen bzw. Zeichen, die beim Scrolling aus dem
 ;#                Fenster verschwinden, werden nicht gespeichert.
 ;#                Außerdem unterstützt das Scrolling nicht die
 ;#                Anpassung des Farbspeichers, d.h. die Funktionen
 ;#                sind für eine monochrome Bildausgaben gedacht.
 ;#
 ;####################################################################
 
 
 ; -- Startadresse --
 
   *=$c000
 
 
 ;####################################################################
 ;#
 ;# Speicherstellen
 ;#
 ;####################################################################
 
   !addr param = $0334 ; Temporäre Speicherstelle für Parameter
                       ; (ungenutzte Adresse in der erweiterten
                       ; Zeropage)
 
 ; -- Alle Variablen stehen am Schluss ab $c3f0 --
 
 
 ;####################################################################
 ;#
 ;# Makros
 ;#
 ;####################################################################
 
 ; -- add_line_wlnp --
 
 ;    Addiert #40 zum Zeiger auf die aktuelle Zeile (wlnp) hinzu;
 ;    wird von delwin und newline verwendet
 
   !macro add_line_wlnp {
       clc
       lda wlnp
       adc #40
       sta wlnp
       lda wlnp+1
       adc #$00
       sta wlnp+1
   }
 
 ; -- wsel --
 
 ;    Setzt für das aktuelle Fenster den Zeiger auf die
 ;    aktuelle Zeile, sowie x und y auf die Startwerte;
 ;    wird von wselall, wselleft, wselright, wseltop,
 ;    wselbottom und delwin verwendet
 
   !macro wsel {
       lda #0
       sta wx
       sta wy
       lda wtlp
       sta wlnp
       lda wtlp+1
       sta wlnp+1
   }
 
 
 ;####################################################################
 ;#
 ;# Sprungtabelle
 ;#
 ;####################################################################
 
   jmp winit      ; $c000
   jmp wselall    ; $c003
   jmp wselleft   ; $c006
   jmp wselright  ; $c009
   jmp wseltop    ; $c00c
   jmp wselbottom ; $c00f
   jmp delline    ; $c012
   jmp delwin     ; $c015
   jmp hscroll    ; $c018
   jmp chrout     ; $c01b
   jmp vscroll    ; $c01e
   jmp newline    ; $c021
   jmp hexout     ; $c024
   jmp binout     ; $c027
   jmp decout     ; $c02a
   jmp asciiout   ; $c02d
   jmp wsave      ; $c030
   jmp wswitch    ; $c033
 
 
 ;####################################################################
 ;#
 ;# Funktionen
 ;#
 ;####################################################################
 
 
 ; -- init --
 
 ;    Standardinitialisierung: ein großes Fenster, das gelöscht wird
 
 winit
   jsr wselall
   jsr delwin
   rts
 
 
 ; -- wselall --
 
 ;    Ein großes Fenster auswählen;
 ;    Akku wird überschrieben
 
 wselall
   lda #$00   ; Zeiger auf Bildschirmspeicher: $0400
   sta wtlp
   lda #$04
   sta wtlp+1
   lda #39    ; 40 (-1) Spalten
   sta wcols
   lda #24    ; 25 (-1) Zeilen
   sta wrows
   +wsel
   rts
 
 
 ; -- wselleft --
 
 ;    Ein halbes Fenster links auswählen;
 ;    Akku wird überschrieben
 
 wselleft
   lda #$00   ; Zeiger auf Bildschirmspeicher: $0400
   sta wtlp
   lda #$04
   sta wtlp+1
   lda #19    ; 20 (-1) Spalten
   sta wcols
   lda #24    ; 25 (-1) Zeilen
   sta wrows
   +wsel
   rts
 
 
 ;-- wselright --
 
 ;   Ein halbes Fenster rechts auswählen;
 ;   Akku wird überschrieben
 
 wselright
   lda #$14   ; Zeiger auf Bildschirmspeicher: $0414 (1024 + 20)
   sta wtlp
   lda #$04
   sta wtlp+1
   lda #19    ; 20 (-1) Spalten
   sta wcols
   lda #24    ; 25 (-1) Zeilen
   sta wrows
   +wsel
   rts
 
 
 ; -- wseltop --
 
 ;    Ein halbes Fenster oben auswählen;
 ;    Akku wird überschrieben
 
 wseltop
   lda #$00   ; Zeiger auf Bildschirmspeicher: $0400
   sta wtlp
   lda #$04
   sta wtlp+1
   lda #39    ; 40 (-1) Spalten
   sta wcols
   lda #12    ; 13 (-1) Zeilen
   sta wrows
   +wsel
   rts
 
 
 ; -- wselbottom --
 
 ;    Ein halbes Fenster unten auswählen;
 ;    Akku wird überschrieben
 
 wselbottom
   lda #$08   ; Zeiger auf Bildschirmspeicher: $0608 (1024 + 13*40)
   sta wtlp
   lda #$06
   sta wtlp+1
   lda #39    ; 40 (-1) Spalten
   sta wcols
   lda #11    ; 12 (-1) Zeilen
   sta wrows
   +wsel
   rts
 
 
 ; -- delline --
 
 ;    Löscht die aktuelle Zeile mit Leerzeichen;
 ;    Akku und Y-Register werden überschrieben;
 ;    benutzt die Zeropage-Adressen $61 und $62;
 ;    wird von delwin aufgerufen
 
 delline
   lda wlnp
   sta $61
   lda wlnp+1
   sta $62                
   ldy wcols
   lda #$20
 -
   sta ($61),y
   dey
   bpl -      ; Schleifenabbruch erst bei Y < 0
   rts                
 
 
 ; -- delwin --
 
 ;    Löscht das aktuelle Fenster mit Leerzeichen
 ;    der wlnp, sowie wx und wy werden zurückgesetzt;
 ;    Akku und Y-Register werden überschrieben
 
 delwin
   +wsel      ; Zeilenzeiger, x, y zurücksetzen
 -
   jsr delline
   +add_line_wlnp ; Zeiger auf Zeile erhöhen
   ldy wy
   iny
   sty wy
   cpy wrows
   bcc -      ; Schleife wird bei wy <= wrows fortgesetzt
   beq -
   +wsel      ; Zeilenzeiger, x, y wieder zurücksetzen
   rts
 
 
 ; -- hscroll --
 
 ;    Zeile horizontal um ein Zeichen scrollen:
 ;    Akku und Y-Register werden überschrieben;
 ;    verwendet die Zeropage-Adressen $61 bis $64;
 ;    wird von chrout aufgerufen
 
 hscroll
   sec          ; Addition +1 wird über gesetztes Carry-Bit gemacht
   lda wlnp
   sta $61      ; $61/$62 zeigt auf das erste Zeichen der Zeile
   adc #0       ; eins hinzu addieren (über gesetztes Carry, s.o.)
   sta $63      ; $63/$64 zeigt auf das zweite Zeichen der Zeile
   lda wlnp+1
   sta $62
   adc #0       ; (16-Bit-Addition)
   sta $64
   ldy #$00     ; von links nach rechts die Zeile durchgehen
 -
   lda ($63),y  ; Zeichen nach links verschieben
   sta ($61),y
   iny
   cpy wcols
   bne -        ; Abbruchbedingung: Y = wcols
                ; d.h. Spaltenanzahl-1 Durchgänge
   lda #$20     ; ein Leerzeichen ans Ende der Zeile schreiben
   ldy wcols
   sta ($61),y
   rts
 
 
 ; -- chrout --
 
 ;    Gibt den Wert im Akku (Bildschirmcode) aus. Wenn das
 ;    Zeilenende erreicht ist, wird horizontal gescrollt.
 ;    Y-Register wird überschrieben;
 ;    verwendet die Zeropage-Adressen $61/$62
 ;    (beim Scrolling auch die Adressen $63/$64):
 ;    wird von hexout, binout, decout und asciiout aufgerufen
 
 chrout
   pha         ; Bildschirmcode sichern
   lda wlnp
   sta $61
   lda wlnp+1
   sta $62
   ldy wx
   pla         ; Bidlschirmcode wieder holen
   sta ($61),y
   cpy wcols   ; Wenn Ende der Zeile erreicht ist, Scrolling durchführen
   beq +
   iny         ; ansonsten wx um eins erhöhen
   sty wx
   rts
 +
   jsr hscroll
   ; wlx nicht erhöhen
   rts
 
 
 ; -- vscroll --
 
 ;    Fensterinhalt um eine Zeile nach oben verschieben;
 ;    Akku, X- und Y-Register werden überschrieben;
 ;    die letzte Zeile wird zur aktuellen Zeile;
 ;    verwendet die Zeropageadressen $61-$64;
 ;    wird von newline aufgerufen
 
 vscroll
     clc
     lda wtlp
     sta $61    ; 1. Zeiger zeigt auf die erste Zeile
     adc #40
     sta $63    ; 2. Zeiger auf die zweite Zeile
     lda wtlp+1
     sta $62
     adc #0
     sta $64
 
     ldx wrows
 scroll_loop    ; 1. Schleife: alle Zeilen um eins nach oben verschieben
 
     ldy wcols
 -              ; 2. Schleife: alle Zeichen der Zeile durchgehen
     lda ($63),y
     sta ($61),y
     dey
     bpl -      ; Abbruch 2. Schleife erst bei Y < 0
     dex
     beq +      ; Abbruchbedingung 1. Schleife: X = wrows
                ; d.h. Zeilenanzahl-1 Durchgänge
 
     lda $61    ; 1. Zeiger um eine Zeile erhöhen
     clc
     adc #40
     sta $61
     lda $62
     adc #0
     sta $62
 
     lda $63    ; 2. Zeiger um eine Zeile erhöhen
     clc
     adc #40
     sta $63
     lda $64
     adc #0
     sta $64
     jmp scroll_loop
 +
     lda $63    ; $63/$64 zeigt auf die letzte Zeile
     sta wlnp   ; diese wird zur aktuellen Zeile
     lda $64
     sta wlnp+1
     jsr delline ; und ihr Inhalt gelöscht
     rts
 
 
 ; -- newline --
 
 ;    Zeilenumbruch durchführen
 ;    Wenn die letzte Zeile des Fensters die aktuelle Zeile
 ;    ist, wird ein Scrolling durchgeführt.
 ;    Akku und Y-Register werden überschrieben, beim
 ;    Scrolling auch das X-Register
 
 newline
   lda #$00  ; wx auf 0 setzen
   sta wx
   ldy wy
   cpy wrows ; wenn Ende des Fenster erreicht ist, dann scrollen
   beq +
   iny       ; Zeile um eins erhöhen ...
   sty wy
   +add_line_wlnp ; Zeiger auf Zeile erhöhen
   rts
 +
   jsr vscroll
   rts
 
 
 ; -- hexout --
 
 ;    Gibt den Wert im Akku in hexadezimaler Form aus;
 ;    Akku, X- und Y-Register (von chrout) werden überschrieben
 
 hexout
   pha       ; Wert sichern
   lsr       ; die oberen 4 Bits nach unten holen
   lsr
   lsr
   lsr
   tax       ; passendes Zeichen laden und ausgeben
   lda hex_digits,x
   jsr chrout
   pla       ; Wert wieder holen
   and #$0f  ; die unten 4 Bits isolieren
   tax       ; passendes Zeichen laden und ausgeben
   lda hex_digits,x
   jsr chrout
   rts
 
 hex_digits
   ; Bildschirmcodes Ziffern 0-9
   !by $30, $31, $32, $33, $34, $35, $36, $37, $38, $39
   ; Bildschirmcodes Buchstaben A-F
   !by $01, $02, $03, $04, $05, $06
 
 
 ; -- binout --
 
 ;    Gibt den Wert im Akku in binärer Form aus;
 ;    Akku, X- und Y-Register (von chrout) werden überschrieben;
 ;    die Speicherstelle param wird verändert
 
 binout
   sta param ; Wert ablegen
   ldx #$07  ; Zähler von 7 bis 0
 bin_loop    ; Den Wert bitweise von links nach rechts durchgehen
   txa       ; Zähler sichern
   pha
   lda param ; Das höchste Bit in den Carry-Flag befördern
   asl
   sta param
   bcc +     ; Abhängig vom Ergebnis '0' oder '1' ausgeben
   lda #$31
   bne ++
 +
   lda #$30
 ++
   jsr chrout
   pla       ; Zähler wieder holen
   tax
   cpx #$04  ; nach 4 Bits ein Leerzeichen ausgeben
   bne +
   lda #$20
   jsr chrout
 +
   dex
   bpl bin_loop ; Abbruchbedingung X < 0
   rts
 
 
 ; -- decout --
 
 ;    Gibt den Wert im Akku in dezimaler Form aus;
 ;    bei gesetztem Carry werden Werte > 127 als negative
 ;    Zahlen ausgeben;
 ;    Akku, X- und Y-Register werden überschrieben;  
 ;    die Speicherstelle param wird verwendet  
 
 decout
   sta param ; Wert sichern
   bcc +
   bpl +
 
 ; bei negativem Wert mit Zweier-Komplement in positiven
 ; Wert wandeln und Minuszeichen ausgeben
 
   eor #$ff
   adc #0    ; Carry ist noch gesetzt (+1)
   sta param
   lda #'-'
   jsr chrout
   lda param
 
 +
   cmp #$0a  ; ist der Wert < 10
   bcc dig1  ; weiter mit 1er-Stellen
   cmp #$64  ; ist der Wert < 100
   bcc dig10 ; weiter mit 10er-Stellen
 
 ;    100-Stellen
 
   ldx #$00  ; dargestellte Ziffer (Startwert '0')
   sec
 -
   sbc #$64  ; 100 abziehen
   bcc +     ; Abbruchbedingung: Wert wird negativ
   sta param ; verringerten Wert speichern
   inx       ; dargestellte Ziffer um eins erhöhen
   jmp -
 +
   txa
   ora #$30  ; Bildschirmcode setzen
   jsr chrout
 
 ;    10er-Stellen
 dig10
   ldx #$00  ; dargestellte Ziffer (Startwert '0')
   lda param
   cmp #$0a  ; Restwert < 10
   bcc +     ; '0' ausgeben (X ist noch null)
   sec
 -
   sbc #$0a  ; 10 abziehen
   bcc +     ; Abbruchbedingung: Wert wird negativ
   sta param ; verringerten Wert speichern
   inx       ; dargestellte Ziffer um eins erhöhen
   jmp -
 +
   txa
   ora #$30  ; Bildschirmcode setzen
   jsr chrout
 
 ;    1er-Stellen
 ;    Der Restwert aus der Speicherstelle param kann
 ;    direkt ausgegeben werden.
 dig1
   lda param
   ora #$30  ; Bildschirmcode setzen
   jsr chrout
   rts
 
 
 ; -- asciout --
 
 ;    Gibt das den im Akku enthaltenen ASCII-Wert aus
 ;    Akku, X- und Y-Register werden überschrieben
 
 ;    Es werden folgende ASCII-Werte unterstützt:  
 ;
 ;    - $0a/#10, $0d/#13:  Zeilenumbruch  
 ;    - $20-$3f/#32-#63:   Satzzeichen und Ziffern  
 ;    - $40-$5f/#64-#95:   Groß- (Font 1) bzw. Kleinbuchstaben (Font 2)
 ;    - $90-$7f/#96-#127:  Grafikzeichen 1 (Font 1) bzw. Großbuchstaben
 ;                         (Font 2)  
 ;    - $a0-$bf/#160-#191: Grafikzeichen 2  
 ;    - $93/#147:          Aktuelles Fenster löschen  
 ;
 ;    Bei allen anderen ASCII-Werten wird ein Fragezeichen ausgegeben.
 
 ;    Umwandlungen von ASCII nach Bildschirmcode:  
 ;
 ;    - Satzzeichen und Ziffern (kene Umwandlung)  
 ;      %001 00000 ($20) bis %001 11111 ($3f)  
 ;    - Großbuchstaben (Bit 6 invertieren und dadurch löschen)   
 ;      %010 00000 ($40) bis %010 11111 ($5f)  
 ;      %000 00000 ($00) bis %000 11111 ($1f)  
 ;    - Grafikzeichen 1 (Bit 5 inverieren und dadurch löschen)  
 ;      %011 00000 ($60) bis %011 11111 ($7f)  
 ;      %010 00000 ($40) bis %010 11111 ($5f)  
 ;    - Grafikzeichen 2 (Bits 7 und 6 invertieren)  
 ;      %101 00000 ($a0) bis %101 11111 ($bf)  
 ;      %011 00000 ($60) bis %011 11111 ($7f)  
 
 asciiout
   cmp #$0a   ; Zeilenumbruch
   bne +
   jsr newline
   rts
 +
   cmp #$0d   ; Zeilenumbuch
   bne +
   jsr newline
   rts
 +
   cmp #$93   ; Fenster löschen
   bne +
   jsr delwin
   rts
 +
   pha        ; ASCII-Wert sichern
   lsr        ; die 3 oberen Bits nach unten holen
   lsr
   lsr
   lsr
   lsr
   tax        ; und zur Auswertung ins X-Register schieben
   pla        ; ASCII-Wert wieder holen
   cpx #$01   ; Satzzeichen und Ziffern
   bne +
   jsr chrout
   rts
 +
   cpx #$02   ; Großbuchstaben
   bne +
   eor #$40
   jsr chrout
   rts
 +
   cpx #$03   ; Grafikzeichen 1
   bne +
   eor #$20
   jsr chrout
   rts
 +
   cpx #$05   ; Grafikzeichen 2
   bne +
   eor #$c0
   jsr chrout
   rts
 +
   lda #$3f   ; ansonsten Fragezeichen ausgeben
   jsr chrout
   rts
 
 
 ; -- wsave --
 
 ;    Speichert die Daten des aktuellen Fensters im
 ;    Zwischenspeicher ab
 
 wsave
   lda wtlp
   sta stlp
   lda wtlp+1
   sta stlp+1
   lda wlnp
   sta slnp
   lda wlnp+1
   sta slnp+1
   lda wcols
   sta scols
   lda wrows
   sta srows
   lda wx
   sta sx
   lda wy
   sta sy
   rts
 
 ; -- wswitch --
 
 ;    Tauscht die Daten des aktuellen Fensters mit dem
 ;    Zwischenspeicher aus. So können zwei Fenster im Wechsel
 ;    benutzt werden. Bevor wswitch verwendet werden kann, muss
 ;    vorher einmal wsave benutzt worden sein, damit im
 ;    Zwischenspeicher gültige Werte stehen!
 
 wswitch
   lda stlp    ; wtlp <-> stlp
   pha
   lda wtlp
   sta stlp
   pla
   sta wtlp
   lda stlp+1  ; wtlp+1 <-> stlp+1
   pha
   lda wtlp+1
   sta stlp+1
   pla
   sta wtlp+1
   lda slnp    ; wlnp <-> slnp
   pha
   lda wlnp
   sta slnp
   pla
   sta wlnp
   lda slnp+1  ; wlnp+1 <-> slnp+1
   pha
   lda wlnp+1
   sta slnp+1
   pla
   sta wlnp+1
   lda scols   ; wcols <-> scols
   pha
   lda wcols
   sta scols
   pla
   sta wcols
   lda srows   ; wrows <-> srows
   pha
   lda wrows
   sta srows
   pla
   sta wrows
   lda sx      ; wx <-> sx
   pha
   lda wx
   sta sx
   pla
   sta wx
   lda sy      ; wy <-> sy
   pha
   lda wy
   sta sy
   pla
   sta wy
   rts
 
 
 ;####################################################################
 ;#
 ;# Variablen / Speicherstellen
 ;#
 ;####################################################################
 
   *=$c3e0
 
 ; -- Zeiger für das aktuelle Fenster --
 
 wtlp         ; Zeiger auf das aktuelle Fenster (top/left pointer)
   !by 0, 0
 wlnp         ; Zeiger auf die aktuelle Zeile (line pointer)
   !by 0, 0
 
 ; -- Parameter für das aktuelle Fenster --
 
 ;    Die Anzahl der Spalten und Zeilen variiert je nach Fenstertyp:
 ;
 ;    - ein großes Fenster (40 Spalten, 25 Zeilen) 
 ;    - ein halbes Fenster links (20 Spalten, 25 Zeilen) 
 ;    - ein halbes Fenster rechts (20 Spalten, 25 Zeilen) 
 ;    - ein halbes Fenster oben (40 Spalten, 13 Zeilen) 
 ;    - ein halbes Fenster unten (40 Spalten, 12 Zeilen)
 ;
 ;    Die Werte werden um eins verringert, weil wx und wy bei null
 ;    beginnen.
 
 wcols        ; Anzahl Spalten (cols; 39 oder 19)
   !by 0
 wrows        ; Anzahl Zeilen (rows; 24 oder 12 oder 11)
   !by 0
 wx           ; Aktuelle X-Position (Start mit 0; bis max. wcols)
   !by 0
 wy           ; Aktuelle Y-Position (Start mit 0; bis max. wrows)
   !by 0
 
 ; -- Zwischenspeicherung der Fensterdaten für Fensterwechsel --
 
 stlp         ; Zeiger auf das Fenster
   !by 0, 0
 slnp         ; Zeiger auf die aktuelle Zeile
   !by 0, 0
 scols        ; Anzahl Spalten
   !by 0
 srows        ; Anzahl Zeilen
   !by 0
 sx           ; X-Position
   !by 0
 sy           ; Y-Position
   !by 0

Demo-Programm[Bearbeiten | Quelltext bearbeiten]

 ;####################################################################
 ;# Programm:      Demo-Programm für Bildschirmausgabe
 ;#                mit Basic-Starter
 ;# Dateiname:     bildschirmdemo.asm
 ;#
 ;# Assembler:     ACME
 ;# Assemblierung: acme -f cbm -o output.bas bildschirmdemo.asm
 ;#
 ;# Laden mit:     NEW
 ;#                LOAD"output.bas",8
 ;#
 ;# Start mit:     RUN
 ;#
 ;# Quelltext:     * Kleinschreibung (bis auf Kommentare)
 ;#                * nur Leerzeichen, keine Tabulatoren
 ;#                * Labels immer in eigener Zeile
 ;#                * Befehle zwei Zeichen eingerückt
 ;#                * Kommentare i.d.R. nach den Befehlen
 ;#
 ;# Beschreibung:  Das Programm gibt nacheinander folgendes aus:
 ;#                - alle ASCII-Werte von 32 bis 127 in Zeilen
 ;#                  zu je 32 Zeichen
 ;#                - alle ASCII-Werte von 32 bis 127 in einer
 ;#                  Zeile mit horizontalem Scrolling
 ;#                - die Wert 0-255 in hexadezimalem Format
 ;#                - die Wert 0-255 in binärem Format
 ;#                - die Wert 0-255 in dezmialem Format
 ;#                - die negativen Werte bis -128 in dezmialem Format
 ;#
 ;####################################################################
 
 
 ;####################################################################
 ;#
 ;# Basic-Starter
 ;#
 ;####################################################################
 
   *=$0801
 
 ; -- Basic-Startzeile erzeugen: 10 SYS 2061 --
 
   !by $0b, $0a           ; Zeiger zur zweiten Zeile
   !by $0a, $00           ; Zeilennummer (10)
   !by $9e                ; Token für SYS
   !by $32, $30, $36, $31 ; 2061 in ASCII
   !by $00                ; Ende der Basic-Zeile
   !by $00, $00           ; Zweite Basic-Zeile und zugleich Ende des
                          ; Basic-Programms
 
 
 ;####################################################################
 ;#
 ;# Hauptprogramm (Start bei $080d/#2061)
 ;#
 ;####################################################################
 
 
 ; -- Speicherstellen --
 
   !addr ptr  = $65       ; $65/$66; Zeiger für Textausgabe
 
   !addr cnt1 = $0335     ; Zähler (ungenutzte Speicherstelle in der
   !addr cnt2 = $0336     ; erweiterten Zeropage)
 
 ; -- Kernal-Routinen --
 
   !addr getin = $ffe4    ; read keyboard buffer
 
 
 ; -- Start --
 
   jsr $c000 ; winit
 
 ; Alle ASCII-Werte von 32 bis 127 in Zeilen zu je 32 Zeichen
 
   ldx #<txt_ascii1
   stx ptr
   ldx #>txt_ascii1
   stx ptr+1
   jsr print_txt
   jsr $c021 ; newline
   ldx #32   ; ASCII-Codes ab 32
 -
   stx cnt1
   txa
   jsr $c02d ; asciiout
 ; nach 32 Zeichen einen Zeilenumbruch einfügen (die
 ; unteren 5 Bits sind bei einem Vielfachen von 32 null)
   ldy cnt1
   iny
   tya
   and #%00011111
   bne +
   jsr $c021 ; newline
 +
   ldx cnt1
   inx
   cpx #127
   bne -
   jsr $c021 ; newline
   jsr $c021 ; newline
 
   jsr press_return
   jsr $c021 ; newline
 
 ; Alle ASCII-Werte von 32 bis 127 in einer Zeile mit
 ; horizontalem Scrolling
 
   ldx #<txt_ascii2
   stx ptr
   ldx #>txt_ascii2
   stx ptr+1
   jsr print_txt
   jsr $c021 ; newline
   ldx #32   ; ab Wert 32
 -
   stx cnt1
   txa
   jsr $c02d ; asciiout
   ldx cnt1
   inx
   cpx #127  ; bis Wert 127
   bne -
   jsr $c021 ; newline
   jsr $c021 ; newline
 
   jsr press_return
   jsr $c021 ; newline
 
 ; linkes und rechtes Fenster einrichten
 
   jsr $c006 ; wselleft
   jsr $c015 ; delwin
   jsr $c030 ; wsave
   jsr $c009 ; wselright
   jsr $c015 ; delwin
   jsr $c033 ; wswitch
 
 ; Alle Hex-Werte von 0-255
 
   ldx #<txt_hex
   stx ptr
   ldx #>txt_hex
   stx ptr+1
   jsr print_txt
 
   jsr $c033 ; wswitch
 
   ldx #0    ; ab Wert 0
 -
   stx cnt1
   lda #$24  ; '$'
   jsr $c01b ; chrout
   txa
   jsr $c024 ; hexout
   jsr $c021 ; newline
   ldx cnt1
   inx
   bne -     ; bis Wert 255 (X springt dann wieder auf null)
 
   jsr $c033 ; wswitch
   jsr press_return
 
 ; Alle Binär-Werte von 0-255
 
   ldx #<txt_bin
   stx ptr
   ldx #>txt_bin
   stx ptr+1
   jsr print_txt
 
   jsr $c033 ; wswitch
 
   ldx #0    ; ab Wert 0
 -
   stx cnt1
   lda #$25  ; '%'
   jsr $c01b ; chrout
   txa
   jsr $c027 ; binout
   jsr $c021 ; newline
   ldx cnt1
   inx
   bne -     ; bis Wert 255 (X springt dann wieder auf null)
 
   jsr $c033 ; wswitch
   jsr press_return
 
 ; Alle Dezimalwerte von 0-255
 
   ldx #<txt_dec1
   stx ptr
   ldx #>txt_dec1
   stx ptr+1
   jsr print_txt
 
   jsr $c033 ; wswitch
   
   ldx #0    ; ab Wert 0
 -
   stx cnt1
   txa
   clc
   jsr $c02a ; decout
   jsr $c021 ; newline
   ldx cnt1
   inx
   bne -     ; bis Wert 255 (X springt dann wieder auf null)
 
   jsr $c033 ; wswitch
   jsr press_return
 
 ; Alle negativen Dezimalwerte
 
   ldx #<txt_dec2
   stx ptr
   ldx #>txt_dec2
   stx ptr+1
   jsr print_txt
 
   jsr $c033 ; wswitch
 
   ldx #255  ; ab Wert -1
 -
   stx cnt1
   txa
   sec
   jsr $c02a ; decout
   jsr $c021 ; newline
   ldx cnt1
   dex
   cpx #127  ; bis Wert -128
   bne -
 
   jsr $c033 ; wswitch
   jsr press_return
 
 ; Ende
 
   jsr $c003 ; wselall
   jsr $c015 ; delwin
 
   ldx #<txt_end
   stx ptr
   ldx #>txt_end
   stx ptr+1
   jsr print_txt
 
 
   rts
 
 press_return
   ldx #<txt_return
   stx ptr
   ldx #>txt_return
   stx ptr+1
   jsr print_txt
 
 ;  rts
 
   ; Tastaturpuffer auf ein Zeichen setzen und
   ; Tastenwiederholung ausschalten
   
   lda $0289
   pha
   lda #1
   sta $0289 ; max size of keyb buffer
   lda $028a
   pha
   lda #127
   sta $028a ; disable key repeat
 
 -
   jsr getin
   cmp #$0d
   bne -
 
   ; Alte Werte für Tastaturpuffer und Tastenwiederholung
   ; wieder herstellen
   
   pla
   sta $028a
   pla
   sta $0289
 
   rts
 
 print_txt
   ldy #0
 -
   sty cnt2
   lda (ptr),y
   beq +
   jsr $c01b ; chrout
   ldy cnt2
   iny
   jmp -
 +
   jsr $c021 ; newline  
   rts
 
 txt_return
   !scr "weiter mit return", 0
 
 txt_ascii1
   !scr "alle ascii-werte von 32 bis 127", 0
 
 txt_ascii2
   !scr "alle ascii-werte mit horiz. scrolling", 0
 
 txt_hex
   !scr "hex-werte 0-255", 0
 
 txt_bin
   !scr "bin-werte 0-255", 0
 
 txt_dec1
   !scr "dez-werte 0-255", 0
 
 txt_dec2
   !scr "neg. dez-werte", 0
 
 txt_end
   !scr "das war's.", 0