;####################################################################
;#
;# Konstanten / Variablen / Speicherstellen
;#
;####################################################################

 COLS = 39          ; Anzahl der Spalten minus eins

 ; (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
;#
;####################################################################

 !addr fopen =  $ffc0
 !addr fclose = $ffc3
 !addr chkout = $ffc9
 !addr clrchn = $ffcc
 !addr chrout = $ffd2


;####################################################################
;#
;# Makros zum Sichern von Registern und Zeigern
;#
;####################################################################

 !macro phx {
   txa
   pha
 }

 !macro phy {
   tya
   pha
 }

 !macro plx {
   pla
   tax
 }

 !macro ply {
   pla
   tay
 }

 !macro savtptr {
   lda tptr1
   pha
   lda tptr1+1
   pha
   lda tptr2
   pha
   lda tptr2+1
   pha
 }

 !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

 rts


;####################################################################
;#
;# Ersatz fuer Kernalroutinen
;#
;####################################################################


; -- put_row_col --

;    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)

put_row_col
 stx wy
 sty wx
 jsr set_screen_pointers
 rts


; -- clear_screen / home_cursor / set_screen_pointers --

;    Loescht das Fenster
;    (analog zu Kernalroutine $e544, jedoch ohne Erstellung
;    der screen link table)

clear_screen
 ldy wrows
 sty wy
-
 jsr clear_screen_line
 dec wy
 bpl -

;    Setzt den Cursor nach oben/links
;    (analog zu Kernalroutine $e566)

home_cursor
 ldy #0
 sty wx
 sty wy

;    Aktualisiert die Zeiger
;    (analog zu Kernalroutine $e56c, jedoch ohne Zwei-Zeilen-Modus)

set_screen_pointers
 jsr set_start_of_line
 jsr sync_color_ptr

 rts


; -- setup_screen_print --

;    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

 ;   mem[wlnp+y] := 32
 ;   mem[wclnp+y] := mem[crnt_color]

 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)

output_to_screen
 pha
 sta crnt        ; ASCII-Wert sichern (wegen phx/phy)
 +phx
 +phy

 lda crnt        ; ASCII-Wert wieder holen
 bpl unshifted_chars
 jmp shifted_chars


; -- unshifted_chars --

;    Zeichen ohne Umschalttaste
;    (analog zu Kernalroutine ab $e72a)

unshifted_chars
 cmp #$20        ; ASCII-Wert < 32 -> Steuerzeichen
 bcc unshifted_ctrl_chars

;    Umwandlung von ASCII 32-127 nach Bildschirmcode
;    ($d1/$d2 muss gesetzt sein)

 cmp #$60        ; ASCII-Wert < 96 -> Satzzeichen, Ziffern usw.
 bcc +

;    - Grafikzeichen 1 (Bit 5 loeschen):
;      von
;        %0110 0000 ($60) bis %0111 1111 ($7f)
;      nach
;        %0100 0000 ($40) bis %0101 1111 ($5f)

 and #%11011111
 jsr setup_screen_print
 jmp output_end

;    - Satzzeichen und Ziffern (keine Umwandlung):
;        %0010 0000 ($20) bis %0011 1111 ($3f)

;    - Grossbuchstaben (Bit 6 loeschen):
;      von
;        %0100 0000 ($40) bis %0101 1111 ($5f)
;      nach
;        %0000 0000 ($00) bis %0001 1111 ($1f)
+
 and #%00111111
 jsr setup_screen_print
 jmp output_end

;    Steuerzeichen

unshifted_ctrl_chars

 cmp #13         ; RETURN
 bne +
 jsr perform_return
 jmp output_end
+
 cmp #17         ; CRSR DOWN
 bne +
 jsr go_to_next_line
 jmp output_end
+
 cmp #18         ; RVS ON
 bne +
 lda #1
 sta invers
 jmp output_end
+
 cmp #19         ; HOME
 bne +
 jsr home_cursor
 jmp output_end
+
 cmp #20         ; DEL
 bne +
 jsr delete_char
 jmp output_end
+
 cmp #29         ; CRSR RIGHT
 bne +
 jsr advance_cursor
 jmp output_end
+
 ; Farbwert setzen, falls ASCII-Wert korrekt,
 ; ansonsten nichts tun (unbekannter Wert)
 jsr set_color_code
 jmp output_end


; -- shifted_chars --

;    Zeichen ohne Umschalttaste
;    (analog zu Kernalroutine ab $e7d4)

shifted_chars
 and #%01111111  ; Bit 7 loeschen

 cmp #$20        ; ASCII-Wert < 160 -> Steuerzeichen
 bcc shifted_ctrl_chars

;    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

; Steuerzeichen
shifted_ctrl_chars

 cmp #13         ; Shift-RETURN (ASCII 141)
 bne +
 jsr perform_backreturn
 jmp output_end
+
 cmp #17         ; CRSR UP (ASCII 145)
 bne +
 jsr go_to_prev_line
 jmp output_end
+
 cmp #18         ; RVS OFF (ASCII 146)
 bne +
 lda #0
 sta invers
 jmp output_end
+
 cmp #19         ; CLR (ASCII 147)
 bne +
 jsr clear_screen
 jmp output_end
+
 cmp #20         ; INS (ASCII 148)
 bne +
 jsr insert_char
 jmp output_end
+
 cmp #29         ; CRSR LEFT (ASCII 157)
 bne +
 jsr back_cursor
 jmp output_end
+
 ; Farbwert setzen, falls ASCII-Wert korrekt,
 ; ansonsten nichts tun (unbekannter Wert)
 ora #$80        ; Bit 7 wieder setzen
 jsr set_color_code

; -- output_end --

; Wiederherstellung der Register nach Aufruf von output_to_screen
; (im Original oft durch Sprung nach $e6a8 realisiert)

output_end
 +ply
 +plx
 pla
 rts


; -- go_to_next_line --

;    Cursor eine Zeile weiter bewegen
;    (analog zu Kernalroutine $e87c)

go_to_next_line
 ldy wy
 cpy wrows       ; wenn wy = wrows, dann Fenster scrollen
 beq +

 iny             ; wy um eins erhoehen
 sty wy
 jsr set_screen_pointers
 rts
+
 jsr scroll_screen
 jsr set_screen_pointers
 rts


; -- perform_return --

;    Zeilenumbruch durchfuehren
;    (analog zu Kernalroutine $e891)

perform_return
 lda #0
 sta wx
 jsr go_to_next_line
 rts


; -- go_to_prev_line --

;    Cursor eine Zeile zurueck bewegen
;    (neue Routine)

go_to_prev_line
 ldy wy
 beq +           ; wenn wy = 0, dann Fenster scrollen

 dey             ; wy um eins verringern
 sty wy
 jsr set_screen_pointers
 rts
+
 jsr backscroll_screen
 jsr set_screen_pointers
 rts


; -- perform_backreturn --

;    Zeilenumbruch rueckwaerts durchfuehren
;    (neue Routine)

perform_backreturn
 lda #0
 sta wx
 jsr go_to_prev_line
 rts


; -- set_color_code --

;    Farbcode aus dem im A-Register enthaltenen ASCII-Wert
;    ermitteln
;    (Kernalroutine $e8cb wird verwendet)

 !addr set_color_code = $e8cb


; -- wlnp_to_tptr --

;    Hilfsroutine fuer scroll_screen

wlnp_to_tptr
       lda wlnp
       sta tptr1
       lda wlnp+1
       sta tptr1+1
 rts


; -- scroll_screen --

;    Fensterinhalt um eine Zeile nach oben verschieben
;    (analog zur Kernalroutine $e8ea)

scroll_screen
       +savtptr
       lda wy          ; wy auf dem Stack sichern
       pha

 ; wy := 0
       ldy #0
       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 >= wrots
-
       inc 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
 cpy wrows
       bcc -           ; Abbruchbedingung: wy >= wrows

       ; 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)

clear_screen_line
 jsr set_start_of_line
 jsr sync_color_ptr

       ; 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

 jsr output_to_screen ; Bildschirmausgabe

 clc
 ; cli
 rts
+
 jmp $f1d5       ; Sprung zur Originalroutine


;####################################################################
;#
;# Hilfsunktionen
;#
;####################################################################

; -- set_wptrs --

;    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

 ; Zeile   | Adresse in der | Bildschirm-
 ; (A-Reg) | der Tabelle    | zeiger
 ; --------+----------------+------------
 ;  0      | wptrs_scr      | $0000
 ;  1      | wptrs_scr + 2  | $0028
 ;           ...
 ; 23      | wptrs_scr + 46 | $0398
 ; 24      | wptrs_scr + 48 | $03c0

 ; 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)

;       |     oben     |     unten
;    wy | start | rows | start | rows
;    ---+-------+------+-------+-----
;     0 |       |      |   1   |  23   (ungueltig)
;     1 |   0   |   0  |   2   |  22
;     2 |   0   |   1  |   3   |  21
;     3 |   0   |   2  |   4   |  20
;                  ...
;    22 |   0   |  21  |  23   |   1
;    23 |   0   |  22  |  24   |   0
;    24 |   0   |  23  |       |       (ungueltig)
;
;    oben start:=  0
;    oben rows:=   wy - 1
;    unten start:= wy + 1
;    unten rows:=  24 - unten start
;
;    if wy = 0 or wy = 24 then exit

wsplit
 lda wy
 sta crnt        ; wy sichern

 beq +           ; if wy = 0 or wy = 24 then exit
 cmp #24
 beq +

 ; Trennline bei wy zeichnen
 jsr set_screen_pointers

       ; for y:= 39 downto 0 do
 ;   mem[wlnp+y] := 64
 ;   mem[wclnp+y] := mem[crnt_color]

 ldy #COLS
-
 lda #64         ; Bildschirmcode horiz. Linie
 sta (wlnp),y
 lda crnt_color
 sta (wclnp),y
 dey
 bpl -

 ; zuerst unteres Fenster anlegen und loeschen
 ldy crnt        ; unten start:= wy + 1
 iny
 tya
 jsr set_wptrs
 lda #24         ; unten rows:= 24 - (wy + 1)
 sec
 sbc crnt
 tay
 dey
 sty wrows
 jsr clear_screen

 ; Daten des unteren Fensters in die Zwischenablage legen
 lda wptrs
 sta sptrs
 lda wptrs+1
 sta sptrs+1
 lda wrows
 sta srows
 lda wx
 sta sx
 lda wy
 sta sy

 ; danach oberes Fenster anlegen und loeschen
 lda #0          ; oben start:= 0
 jsr set_wptrs
 ldy crnt        ; oben rows:= wy - 1
 dey
 sty wrows
 jsr clear_screen

+
 rts


; -- wunsplit --

;    Wieder ein grosses Fenster ueber den gesamten
;    Bildschirm anlegen und dieses loeschen

wunsplit
 jsr set_default
 jsr clear_screen
 rts


; -- whcopy --

;    Fenster auf dem Drucker ausgeben

whcopy
 lda #4          ; Geraeteadresse
 sta $ba
 lda #126        ; logische Filenummer
 sta $b8
 lda #0          ; Sekundaeradresse
 sta $b9
 lda #0          ; Laenge Dateiname (kein Dateiname)
 sta $b7
 jsr fopen
 ldx $b8
 jsr chkout

       lda wy          ; wy auf dem Stack sichern
       pha

 ; writeln()
 lda #13
 jsr chrout

 ; wy := 0
       ldy #0
       sty wy

 ; repeat
 ;   set_start_of_line()
-
 jsr set_start_of_line ; wlnp zeigt auf aktuelle Zeile

 ;   for y:= 0 to 39 do
 ;     a := mem[wlnp+y]
 ;     a := a and 127
 ;     if a < 32 then a := a or 64
 ;     write(a)
 ldy #0
--
 lda (wlnp),y

 and #$7f        ; ggf. Invertierung loeschen
 cmp #$20        ; Grossbuchstabe ?
 bcs +
 ora #$40        ; in ASCII umwandeln
+
 jsr chrout      ; Y-Reg wird erhalten
 iny
 cpy #COLS
 bcc --
 beq --

 ;   writeln()
 ; until wy > wrows
 lda #13
 jsr chrout
 inc wy
 ldy wy
 cpy wrows
 bcc -
 beq -

 pla             ; wy wieder herstellen
 sta wy
 jsr set_start_of_line ; wlnp wieder herstellen

 jsr clrchn
 lda #126        ; logische Filenummer
 jsr fclose
 rts


;####################################################################
;#
;# Zeigertabelle
;#
;####################################################################

 ; 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
;#
;####################################################################

 ; Zeiger $0326/$0327
sav_outptr
 !wo 0

 ; Aktuelle Farbe
sav_color
 !by 0

 ; Reverse-Flag
sav_invers
 !by 0

 ; Zeropage $d1 bis $f4
sav_scrzp
 !wo 0, 0, 0, 0, 0, 0, 0, 0
 !wo 0, 0, 0, 0, 0, 0, 0, 0
 !wo 0, 0