Das Maschinenspracheprogramm directory ist ein Filerequester, mit dem in einem laufenden BASIC-Programm ein Dateiname per Auswahl mit den Cursortasten in eine Variable übernommen werden kann.
Original von Dieter Bayer im 64'er Sonderheft 15, Seite 154 (1987).
Korrekturen von Peter Hagemann (1988 und 2022).
An TSB angepasst von Peter Hagemann (2023) und Arndt Dettke (2023) unter dem Namen „dirselect“.
Die Startadresse ist $C000 (49152). Das Programm belegt den Speicher $C000-$C297 (Original: $C000-$C285). Der Bereich unter dem BASIC-ROM ab $A000 dient als Pufferspeicher für die eingelesenen Directory-Einträge (16 Bytes pro Datei).
Der erste Parameter gibt die Startspalte der Dateiauswahlanzeige an. Er darf Werte von 0 bis 22 annehmen. Die Ausgabebreite beträgt 18 Zeichen.
Der zweite Parameter ist der Dateifilter. Mit "$" werden sämtliche Dateien aus dem Directory angezeigt. Mit dem Filter "$:[*" werden nur Dateien ausgewählt, die mit "[" beginnen.
Die im Sonderheft 15 veröffentlichte Fassung (s.u. SMON-Disassembler-Listing des Originals) enthält die drei Mängel 1-3. Diese Probleme sind in der korrigierten Fassung von 1988 behoben. Zwei weitere kleinere Mängel (4-5) sind in der neuesten Fassung von 2022 beseitigt.
Bei der Blockanzahl 34 gibt es Probleme, da sie mit dem Code für das Anführungszeichen verwechselt wird.
Im normalen Betriebssystem wird die Schriftfarbe der Dateinamen nicht gesetzt, die so unsichtbar bleiben.
Es gibt keine Möglichkeit, ohne Auswahl abzubrechen. Die korrigierte Version tut dies nach <Pfeil links>.
Die Farbe wird jetzt im ganzen Ausgabebereich (auch in den Zeichen links und rechts vom Dateinamen) gesetzt.
Nach der Dateiauswahl wird der Reverse-Modus ausgeschaltet.
;"directory" Dateiauswahldialog
;Original von Dieter Bayer aus dem 64'er SH15 (1987)
;mit Korrekturen von P.Hagemann (1988/2022)
!to "directory-v3.prg", cbm
* = $c000
errout = $a43a
frmevl = $ad9e
chkcom = $aefd
home = $e566
getvar = $b08b
frestr = $b6a3
getbyte = $b79e
iecin = $ffa5
setpar = $ffba
setfnp = $ffbd
open = $ffc0
clrchn = $ffcc
close = $ffc3
chkin = $ffc6
basout = $ffd2
getin = $ffe4
jsr home
lda #16 ;String-Länge 16
jsr $b47d ;macht Platz für String
stx $fc
sty $fd
jsr chkcom
jsr getbyte
stx startcol
txa
clc
adc #18
sta endcol ;Endespalte = Startspalte + 18
jsr chkcom
jsr frmevl
jsr frestr
jsr setfnp
jsr chkcom
jsr getvar
sta $fa
sty $fb
lda $0d
bne lc03b
ldx #22 ;Fehler 22
jmp errout
;------------------
lc03b lda #$7f
ldx #$08
ldy #$60
jsr setpar
jsr open
ldx #$7f
jsr chkin
ldx #4 ;4 Bytes überlesen
lc04e jsr iecin
bit $90
bvs lc05a
dex
bne lc04e
beq lc065
;------------------
lc05a jsr clrchn
lda #$7f
jsr close
jmp lc0d9
;------------------
lc065 jsr lc0c5 ;Zeiger auf RAM $a000
ldx startcol
beq lc075
lda #$1d ;Crsr right
lc06f jsr basout
dex
bne lc06f ;vor bis Startspalte
lc075 ldx #21 ;21 Bytes
lc077 jsr iecin
jsr basout
dex
bne lc077
jsr skip12 ;12 Bytes überlesen
ldx #8
lc083 jsr iecin
cmp #$22 ;Anführungszeichen
beq lc093
bit $90 ;Status Bit 6?
bvs lc05a ;EOF, dann fertig
dex
bne lc083 ;nächstes Byte
beq lc05a ;fertig
;------------------
lc093 ldy #00
lc095 jsr iecin ;(16-mal)
sta ($50),y ;in RAM $a000 ablegen
iny
cpy #16
bne lc095
lda #$ff ;Ende-Markierung
sta ($50),y
dey
lda ($50),y ;Byte davor
beq lc05a ;= 0 dann fertig
clc
lda $50
adc #$10 ;nächste 16 Bytes im RAM
sta $50
bcc lc0b3
inc $51
lc0b3 inc $02 ;maximale Anzahl der Datei-Einträge + 1
jsr skip12 ;12 Bytes überlesen
lc0b8 jsr iecin
bit $90
bvs lc05a ;eof, dann fertig
cmp #$22 ;sonst bis Anführungszeichen
bne lc0b8
beq lc093 ;nächster Dateieintrag
;------------------
;Init Zeiger auf Dateiname im RAM ab $a000
lc0c5 lda #$00
sta $02 ;Anzahl Einträge (0: keine)
sta $50 ;Zeichen
lda #$a0
sta $51 ;50/51 auf $a000
lda #$36 ;auf BASIC-RAM
sta $01 ; schalten
lda #$80 ;für alle Tasten
sta $028a ; Tastenwiederholung ein
rts
;------------------
lc0d9 lda $02
bne lc0e0 ;RAM-Einträge vorhanden
jmp lc21a ;sonst beenden
;------------------
;Init Auswahlbereich
lc0e0 jsr color ;Farbe setzen
sec
sbc #24 ;24
sta lc240 ;(unbenutzt)
lda #$00
sta selrow
sta ramrow
jsr ram2scr
lda #$01
sta currow
jsr invert
lda #$00
sta $c6
lc0fd jmp lc258 ;Tasteneingabe
;------------------
lc100 beq lc0fd
lc102 cmp #$0d ;Return
bne lc109
jmp lc1e7
;------------------
lc109 cmp #$91 ;Cursor up
beq lc140
cmp #$11 ;Cursor down
bne lc0fd ;Tastaturabfrage
jsr invert ;Auswahlbereich invertieren
inc ramrow
inc currow
lda ramrow
cmp $02 ;Maximum überschritten?
bne lc12a
dec currow
dec ramrow
jmp lc13a
;------------------
lc12a lda currow
cmp #25
bne lc13a
dec currow ;25, dann -1
inc selrow
jsr ram2scr
lc13a jsr invert
jmp lc0fd ;Tastaturabfrage
;------------------
lc140 jsr invert
dec ramrow
dec currow
lda ramrow
cmp #$ff ;negativ?
bne lc159
inc currow ;dann wieder +1
inc ramrow
jmp lc167
;------------------
lc159 lda currow
bne lc167
inc currow ;0, dann 1
dec selrow
jsr ram2scr
lc167 jsr invert
jmp lc0fd ;zur Tastenabfrage
;------------------
;aus Ram ab $a000 in Schirm ab $0400
ram2scr jsr ramptr ;Zeiger im Ram berechnen
lda #41 ;ab Zeile 2
clc
adc startcol
sta $52 ;Spalte Low-Byte
lda #$04
sta $53 ;Spalte High-Byte
ldx #24 ;24 Zeilen
lc17e ldy #$00
lc180 lda ($50),y ;Byte aus Ram (16-mal)
cmp #$ff ;Ende-Kennung
beq lc1af
cmp #$22 ;Anführungszeichen
bne lc18c
lda #$20 ;Rest mit Leerzeichen auffüllen
lc18c jsr lc224 ;Umwandeln in BSCode
sta ($52),y ;Zeichen in Schirm
iny
cpy #16 ;Dateilänge 16
bne lc180
clc
lda $50 ;RAM-Zeiger +1
adc #$10
sta $50
bcc lc1a1
inc $51
lc1a1 clc
lda $52 ;nächste spalte
adc #$28
sta $52
bcc lc1ac
inc $53
lc1ac dex
bne lc17e
lc1af rts
;------------------
;Zeiger im RAM ab $a000 für Auswahlbereich
ramptr lda #$00
sta $51
lda selrow ;Top-Of-Page RAM-Index bzw. RAM-Index des ausgewählten Eintrags (nach RETURN)
sta $50
asl $50
rol $51
asl $50
rol $51
asl $50
rol $51
asl $50
rol $51 ;mal 16
clc
lda $51
adc #$a0
sta $51
rts
;------------------
;Auswahlbereich im Bildschirm invertieren
invert ldx currow ;Zeilenzähler 1 bis 24
jsr $e9f0 ;Zeiger $d1/$d2 der Video-Adresse setzen
ldy startcol
lc1da lda ($d1),y
eor #$80 ;invertieren
sta ($d1),y
iny
cpy endcol
bne lc1da
rts
;------------------
;Return: in Variable übernehmen
lc1e7 clc
lda currow
adc selrow
sta selrow
dec selrow
jsr ramptr
ldy #$00
lc1f9 lda ($50),y ;16 Zeichen aus Ram
cmp #$22 ;Anführungszeichen: ende
beq lc206
sta ($fc),y ;in Eingabe-String-Platz schreiben
iny
cpy #$10
bne lc1f9
lc206 tya ;String in Variable
ldy #$00
sta ($fa),y
lda $fc
iny
sta ($fa),y
lda $fd
iny
sta ($fa),y
ldy #$00
beq + ;unbedingt
;------------------
;Beenden
lc21a ldy #$00
tya
sta ($fa),y ;Init Zeiger auf Variable
+ sty $c7 ;rvsoff
lda #$37
sta $01 ;ROM ein
rts ;Ende
;------------------
;Umwandeln in BSCode (ohne Pi-Berücksichtigung)
lc224 cmp #$20
bcc lc238
cmp #$40
bcc lc237
cmp #$60
bcc lc23c
cmp #$80
bcc lc23c
sec
sbc #$80
lc237 rts
;------------------
lc238 clc
adc #$80
rts
;------------------
lc23c sec
sbc #$40
rts
;------------------
skip12 lda #12 ;12 bytes
sta $a7
lc24a jsr iecin
dec $a7
bne lc24a ;überlesen
rts
;------------------
lc258 ;Tasteneingabe, auf Pfeil links prüfen
jsr getin
beq lc258
cmp #$5f ;Pfeil links
bne lc26c
jsr clrchn
lda #$7f ;127
jsr close
jmp lc21a ;beenden
;------------------
lc26c jmp lc102
;------------------
;Farbe im Ausgabebereich setzen
color lda #40 ;ab Zeile 2
clc
adc startcol
sta $f3 ;Spalte Low-Byte
lda #$d8
sta $f4 ;Spalte High-Byte
ldx #24 ;24 Zeilen
scl lda $0286 ;Zeichenfarbe
ldy #$00
sc2 sta ($f3),y ;Farbe setzen
iny
cpy #18 ;Länge 16+2
bne sc2
;nächste Zeile
clc
lda $f3
adc #40
sta $f3
bcc sc3
inc $f4
sc3 dex
bne scl
rts
;------------------
;Tab
lc240 !by $00
selrow !by $00 ;Top-Of-Page RAM-Index bzw. RAM-Index des ausgewählten Eintrags (nach RETURN)
currow !by $00 ;aktuelle Bildschirmzeile 1-24
ramrow !by $00 ;aktueller RAM-Eintrag
startcol !by $00 ;Nummer der ersten Spalte
endcol !by $00 ;Nummer der letzten Spalte
;------------------
Mit folgendem BASIC-Programm kann man die directory-Routine testen:
10 IF A=0 THEN A=1:LOAD"DIRECTORY-V3",8,1
20 DL=12*4096:PRINT CHR$(147)CHR$(5)
30 PRINT "{HOME}{3 DOWN}_ = BEENDEN":PRINT" OHNE AUSWAHL"
40 SYSDL,22,"$",F$
50 PRINT "{HOME}"CHR$(34)F$CHR$(34)
60 PRINT "{HOME}{6 DOWN}L = NEU LADEN"
70 GET A$:IF A$="" THEN 60
80 IF A$="L" THEN GOTO 20
Die Beispieldiskette HOMENTC1.D64 aus The Complete Home Entertainment Centre (Sammlung) soll die Arbeitsweise des Programms nachvollziehbar machen. Sie eignet sich deshalb gut, weil sie ein kurzes Directory und Dateien mit ein-, zwei- und dreistelligen Blockgrößen besitzt.