; (in Klammern ist die Nutzung in den original Kernalroutinen
; angegeben)
!addr tptr1 = $ac ; $ac/$ad (Tape Buffer/Screen scrolling)
!addr tptr2 = $ae ; $ae/$af (Tape End Address/End of Program)
!addr invers = $c7 ; $c7 (Reverse flag)
!addr wlnp = $d1 ; $d1/$d2 (Current Screen Line Address)
!addr wx = $d3 ; (Cursor Column on current Line)
; $d4 (Flag: Editor in Quote Mode)
; $d5 (Current logical Line length)
!addr wy = $d6 ; (Current Screen Line number of Cursor)
!addr crnt = $d7 ; (Current Input Character / Last
; Character Output)
; $d8 (Count of number of inserts outstanding)
; $d9-$f2 (Screen Line Link Table)
!addr wrows = $d9 ; Fensterhoehe
!addr wptrs = $da ; $da/$db Zeiger auf eigene Link Table
; Zwischenspeicher
!addr sptrs = $dc ; $dc/$dd wptrs des zweiten Fensters
!addr srows = $de ; wrows des zweiten Fensters
!addr sx = $df ; wx des zweiten Fensters
!addr sy = $e0 ; wy des zweiten Fensters
; $e1 bis $f2 noch frei
!addr wclnp = $f3 ; $f3/$f4 (Current Color RAM Location)
!addr crnt_color = $0286 ; Current color code
;####################################################################
;#
;# Verwendete BASIC- und Kernalroutinen
;#
;####################################################################
;####################################################################
;#
;# Makros zum Sichern von Registern und Zeigern
;#
;####################################################################
!macro rsttptr {
pla
sta tptr2+1
pla
sta tptr2
pla
sta tptr1+1
pla
sta tptr1
}
;####################################################################
;#
;# Routinen zur Sicherung der Originaldaten
;#
;####################################################################
; -- save_orig --
; Sichert die Originaldaten des Betriebssystems, die fuer
; die Bildschirmaugabe relevant sind.
save_orig
; Zeiger auf Ausgaberoutine sichern
lda $0326
sta sav_outptr
lda $0327
sta sav_outptr+1
; Aktuelle Farbe sichern
lda crnt_color
sta sav_color
; Reverse-Flag sichern
lda invers
sta sav_invers
; Speicherbereich $d1 bis $f4 sichern
ldx #$f4-$d1 ; Zaehler festlegen
-
lda $d1,x
sta sav_scrzp,x
dex
bpl - ; Abbruchbedingung X < 0
rts
; -- restore_orig --
; Stellt die Originaldaten des Betriebssystems, die fuer
; die Bildschirmausgabe relevant sind, wieder her.
restore_orig
; Speicherbereich $d1 bis $f4 wieder herstellen
ldx #$f4-$d1 ; Zaehler festlegen
-
lda sav_scrzp,x
sta $d1,x
dex
bpl - ; Abbruchbedingung X < 0
; Reverse-Flag wieder herstellen
lda sav_invers
sta invers
; Aktuelle Farbei wieder herstellen
lda sav_color
sta crnt_color
; Zeiger auf Ausgaberoutine wieder herstellen
lda sav_outptr
sta $0326
lda sav_outptr+1
sta $0327
; Setzt die aktuelle Zeile und Spalte;
; das X-Reg enthaelt die Zeile, das Y-Reg die Spalte
; das Carry-Flag wird nicht als Parameter benutzt
; (analog zu Kernalroutine $e50a; die Routine get_row_col
; wird nicht verwendet)
; Bildschirmausgabe durchfuehren (inkl. Invers-Darstellung
; und Cursor weiter bewegen)
; (analog zu Kernalroutine ab $e693; der ORA-Befehl in $e691
; wird von der Routine shifted_chars uebernommen; $d1/$d2
; muss vorher mit set_start_of_line gesetzt werden)
setup_screen_print
ldy invers
beq +
ora #$80 ; Invers-Darstellung
+
ldx crnt_color
jsr print_to_scr
jsr advance_cursor
; Wiederherstellung von Registern (ab $6a8) siehe output_end
rts
; -- advance_cursor / retreat_cursor --
; Cursor ein Zeichen weiter bewegen
; (analog zu Kernalroutine $e6b6, jedoch ohne Zwei-Zeile-Modus)
advance_cursor
inc wx
lda #COLS ; COLS >= wx (Zeilenende noch nicht ueberschritten)
cmp wx
bcs +
; Cursor zuruecksetzen
; (analog zu Kernalroutine ab $e6f7)
; retreat_cursor (Sprungmarke wird nicht benutzt)
jsr go_to_next_line
lda #0
sta wx
+
rts
; -- back_cursor --
; Cursur ein Zeichen zurueck bewegen
; (neue Routine)
back_cursor
dec wx ; setzt N-Flag
bpl + ; wx >= 0
jsr go_to_prev_line
lda #COLS
sta wx
+
rts
; -- delete_char --
; Zeichen links vom Cursor loeschen
; (analog zu Code ab $e74c in der Kernalroutine
; unshifted_chars; back_into_prev_line wird nicht
; verwendet; $d1/$d2 muss vorher mit set_start_of_line
; gesetzt werden)
delete_char
; if wx > 0 then
ldy wx
beq +
; wx := wx - 1
; y := wx
; sync_color_ptr()
dey
sty wx
jsr sync_color_ptr
; repeat
; mem[wlnp+y] := mem[wlnp+y+1]
; mem[wclnp+y] := mem[wclnp+y+1]
; y := y + 1
; until y = COLS
-
iny
lda (wlnp),y
dey
sta (wlnp),y
iny
lda (wclnp),y
dey
sta (wclnp),y
iny ; y := y + 1
cpy #COLS
bne - ; Abbruchbedingung: y = COLS
lda #32
sta (wlnp),y
lda crnt_color
sta (wclnp),y
+
rts
; -- insert_char --
; An der Cursorposition Platz fuer ein Zeichen schaffen
; (analog zu Code ab $e805 in der Kernalroutine
; shifted_chars; im Gegensatz zum Original wird
; das letzte Zeichen der Zeile verworfen; $d1/$d2
; muss vorher mit set_start_of_line gesetzt werden)
insert_char
; sync_color_ptr()
; if wx < COLS then
jsr sync_color_ptr
ldy wx
cpy #COLS
bcs +
; y := COLS
ldy #COLS
; repeat
; y := y - 1
; mem[wlnp+y+1] := mem[wlnp+y]
; mem[wclnp+y+1] := mem[wclnp+y]
; until y = wx
-
dey ; y := y - 1
lda (wlnp),y
iny
sta (wlnp),y
dey
lda (wclnp),y
iny
sta (wclnp),y
dey
cpy wx
bne - ; Abbruchbedingung: y = wx
; mem[wlnp+y] := 32
; mem[wclnp+y] := mem[crnt_color]
+
lda #32
sta (wlnp),y
lda crnt_color
sta (wclnp),y
rts
; -- output_to_screen --
; Bildschirmausgabe
; (analog zu Kernalroutine $e716)
; Umwandlung von ASCII 160-191 nach Bildschirmcode:
; ($d1/$d2 muss gesetzt sein)
; - Grafikzeichen 2 (Bit 6 setzen, Bit 7 ist schon geloescht):
; von
; %1010 0000 ($a0) bis %1011 1111 ($bf)
; nach
; %0110 0000 ($60) bis %0111 1111 ($7f)
; - Implizite Umwandlung von ASCII ab 192 durch Loeschen von
; Bit 7 und Setzen von Bit 6 (die ASCII-Codes enden bei 191):
; von
; %1100 0000 ($c0) bis %1111 0000 ($ff)
; nach
; %0100 xxxx ($40) bis %0111 1111 ($7f)
ora #%01000000
jsr setup_screen_print
jmp output_end
; letzte Zeile loeschen (wy zeigt bereits darauf)
+
jsr clear_screen_line
pla ; wy wieder herstellen
sta wy
+rsttptr
rts
; -- backscroll_screen --
; Fensterinhalt um eine Zeile nach unten verschieben
; (neue Routine)
backscroll_screen
+savtptr
lda wy ; wy auf dem Stack sichern
pha
; wy := wrows
ldy wrows
sty wy
; if wrows > 0 then
ldy wrows
beq + ; bei wrows = 0 Scrolling ueberspringen
; set_start_of_line()
; tptr := wlnp
jsr set_start_of_line
jsr wlnp_to_tptr ; tptr zeigt auf die erste Zeile
; repeat
; wy := wy - 1
; set_start_of_line()
; move_a_screen_line()
; tptr := wlnp
; until wy = 0
-
dec wy
jsr set_start_of_line ; wlnp zeigt auf die Folgezeile
jsr move_a_screen_line ; Zeile (wlnp) => Zeile (tptr)
jsr wlnp_to_tptr ; tptr zeigt jetzt auf die Zeile von wlnp
ldy wy
bne - ; Abbruchbedingung: wy = 0
; erste Zeile loeschen (wy zeigt bereits darauf)
+
jsr clear_screen_line
pla ; wy wieder herstellen
sta wy
+rsttptr
rts
; -- move_a_screen_line --
; Kopiert eine Fensterzeile
; (analog zu Kernalroutine $e9c8, jedoch mit umgekehrten Transfer:
; ($d1/$d2) => ($ac/$ad) und ($f3/$f4) => ($ae/$af)
; wlnp => tptr1 und wclnp => tptr2
; anstatt
; ($ac/$ad) => ($d1/$d2) und ($ae/$af) => ($f3/$f4)
; und:
; $d1/$d2 muss vorher mit set_start_of_line gesetzt werden
; $ac/$ad muss vorher gesetzt werden
; $f3/$f4 und $ae/$af wird von sync_color_transfer gesetzt
; )
move_a_screen_line
jsr sync_color_transfer
; for y:= 39 downto 0 do
; mem[tptr1+y] := mem[wlnp+y]
; mem[tptr2+y] := mem[wclnp+y]
ldy #COLS
-
lda (wlnp),y
sta (tptr1),y
lda (wclnp),y
sta (tptr2),y
dey
bpl - ; Abbruchbedingung: Y < 0
rts
; -- sync_color_transfer --
; Aktualisiert temporaeren Zeiger fuer das Farb-RAM
; (Kernalroutine $e9e0 wird verwendet)
!addr sync_color_transfer = $e9e0
; -- set_start_of_line --
; Setzt wlnp auf die aktuelle Zeile
; (analog zu Kernalroutine $e9f0)
set_start_of_line
lda wy
asl ; Index = Zeile * 2
tay
lda (wptrs),y
sta wlnp
iny
lda (wptrs),y
ora $0288
sta wlnp+1
rts
; -- clear_screen_line --
; Loescht die aktuelle Bildschirmzeile
; (analog zu Kernalroutine $e9ff)
; for y:= 39 downto 0 do
; mem[wlnp+y] := 32
; mem[wclnp+y] := mem[crnt_color]
ldy #COLS
-
lda #32
sta (wlnp),y
lda crnt_color ; ananlog zu reset_char_color ($e4da)
sta (wclnp),y
dey
bpl -
rts
; -- print_to_scr --
; Gibt den im A-Register enthaltenen Bildschirmcode
; mit der im X-Register gesetzten Farbe aus
; (Kernalroutine $ea13 wird verwendet)
!addr print_to_scr = $ea13
; -- sync_color_ptr --
; Setzt wclnp auf die aktuelle Zeile
; (Kernalroutine $ea24 wird verwendet)
!addr sync_color_ptr = $ea24
; -- output_one_chr --
; Ein Zeichen auf dem Ausgabegeraet ausgeben;
; ASCII-Wert steht im A-Reg;
; Zieladresse fuer $0326/$0327 und Aufruf durch $ffd2
; (analog zu Kernalroutine $f1ca)
output_one_chr
pha ; ASCII-Wert sichern
lda $9a
cmp #3 ; Ausgabegeraet Bildschirm ?
bne + ; falls nein -> weiter mit anderen Geraeten
pla ; ASCII-Wert wieder holen
; Setzt wptrs anhand der angegebenen Zeile und legt damit
; den Start des Fensters fest.
; A-Reg enhaelt die (Start)Zeile (beginnend mit null)
set_wptrs
; Die Adresse aus der Tabelle der Bildschirmzeiger in
; wptrs ablegen, die den Zeiger fuer die uebergebene
; erste Zeile des Fensters enthaelt; die Nummer der
; Zeile wird im A-Reg uebergen
; wptrs wird von set_start_of_line verarbeitet und dort
; noch mit dem Wert aus $0288 ergaenzt
asl ; Offset := Zeile * 2
clc ; wptrs := Offset + wptrs_scr (16 Bit)
adc #<wptrs_scr
sta wptrs
lda #>wptrs_scr
adc #0
sta wptrs+1
rts
; -- set_default --
; Standardkonfiguration mit einem Fenster ueber den gesamten
; Bildschirm; der Zwischenspeicher wird identisch gesetzt,
; damit er gueltige Werte hat; wlnp, wx und wy muessen durch
; die aufrufende Routine gesetzt werden
set_default
lda #0
jsr set_wptrs
lda wptrs ; sptrs := wptrs (16 Bit)
sta sptrs
lda wptrs+1
sta sptrs+1
lda #24 ; wrows := 25 - 1 Zeilen
sta wrows
sta srows ; srows := wrows
lda #0
sta sx ; sx := 0
sta sy ; sy := 0
rts
;####################################################################
;#
;# Funktionen zum Aufruf aus Assembler (und BASIC) heraus
;#
;####################################################################
; -- winit --
; Originaldaten sichern, Ausgaberoutine umstellen und ein
; grosses Fenster ueber den gesamten Bildschirm anlegen
; und loescht diesen
winit
jsr save_orig
; Ausgaberoutine setzen
lda #<output_one_chr
sta $0326
lda #>output_one_chr
sta $0327
; ein grosses Fenster einrichten und loeschen
jsr set_default
jsr clear_screen
rts
; -- wquit --
; Urspruengliche Werte wieder herstellen;
; Spalte steht im X-Reg, Zeile im Y-Reg
wquit
jsr restore_orig
rts
; -- wswitch --
; Tauscht die Daten des aktuellen Fensters mit dem
; Zwischenspeicher aus
wswitch
lda sptrs ; wptrs <-> sptrs
pha
lda wptrs
sta sptrs
pla
sta wptrs
lda sptrs+1 ; wptrs+1 <-> sptrs+1
pha
lda wptrs+1
sta sptrs+1
pla
sta wptrs+1
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
jsr set_screen_pointers
rts
; -- wsplit --
; Bildschirm an der Zeile wy in zwei Fenster
; horizontal aufteilen und diese jeweils loeschen
; (das obere Fenster ist danach das aktulle Fenster)
; Zeiger auf die Zeilen im Bildschirmspeicher
; high bytes analog zu $d9-$f2 im Original; das high
; byte muss aber immer mit ora $0288 noch auf die
; eigentliche Speicherseite gesetzt werden; low bytes
; identisch mit $ecf0-$ed08 im ROM
wptrs_scr
!wo $0000, $0028, $0050, $0078, $00a0, $00c8, $00f0, $0118
!wo $0140, $0168, $0190, $01b8, $01e0, $0208, $0230, $0258
!wo $0280, $02a8, $02d0, $02f8, $0320, $0348, $0370, $0398
!wo $03c0
;####################################################################
;#
;# Sciherung der Originaldaten
;#
;####################################################################