; Open File RSX ; ; Dieses RSX-Modul faengt den BDOS-Aufruf 'Open File' ab. ; Wenn im vorgegebenen FCB '?' auftreten, so wird vor 'Open File' ; die Funktion 'Search First' eingeschoben, damit kein BDOS- ; Error auftritt, und mit dem gefundenen Dateinamen die Open- ; Funktion ausgefuehrt. Wenn nicht, wird der Aufruf direkt an ; das BDOS weitergeleitet. ; TRUE equ 0ffffh FALSE equ not TRUE printstr equ 9 ; Print String Funktion openfile equ 15 ; Open File Funktion searchf equ 17 ; Search First Funktion scb equ 49 ; Get/Set System Control Block callrsx equ 60 ; Call RSX DEBUG equ TRUE ; Debug-Modus liefert mehr Meldungen ; fuer Tests Z80 equ TRUE ; Z80 statt 8080/8085-Code wird generiert ; Beginn RSX-Prefix db 0,0,0,0,0,0 ; Seriennummer jp start ; Beginn des RSX-Codes NEXT: jp $-$ ; Sprunganweisung prev: dw 0 ; Adresse vorheriges Modul remove: db 0ffh ; loesche bei Warmstart nonbank: db 0 ; lade immer rsxname: db 'OPEN ' ; Name des Modules (8 Stellen) db 0,0,0 ; benutzt von Lader und BDOS ; Beginn RSX-Code start: ld a,c ; pruefe BDOS Funktion cp openfile ; ist dies ein 'Open File' Aufruf ? jp z,gefangen ; wenn ja, dann tu's ; wenn DEBUG eingeschaltet, dann pruefe zusaetzlich, ob dies ein ; BDOS-Aufruf 'Call RSX' ist. Wenn ja, dann kehre mit Akku =0 ; zum rufenden Programm zurueck, und teile mit, dass das RSX-Modul ; geladen und aktiv ist. IF DEBUG cp callrsx ; ist es ein Aufruf fuer diese RSX ? jp nz,NEXT ; nein, weiter zur naechsten RSX ; oder zum BDOS ld a,d ; liegt ein Testprogramm-Aufruf an ? cp 0ffh jp nz,NEXT cp e ; Register DE = 0ffffh ? jp nz,NEXT ; nein, gebe Aufruf weiter xor a ; andernfalls setze Register A = 0 ret ; zurueck zum rufenden Programm ELSE jp NEXT ; zur naechsten RSX oder BDOS wenn ; keine 'Open File-Funktiton' ENDIF gefangen: ld hl,0 add hl,sp ; sichere aktuellen Stackpointer ld (userstack),hl ld sp,rsxstack ; richte lokalen Stack ein push bc ; sichere Benutzerregister push de ; Ueberpruefe Dateiname auf ' ?' ld b,11 ; max. Zeichenanzahl im Dateinamen inc de ; setze Zeiger auf 1. Namenszeichen loop: ld a,(de) cp '?' ; ist es ein '?' ? jp z,ersetze ; '?' gefunden, fuehre RSX aus inc de ; nein, naechstes Zeichen auch nicht? dec b ; stelle Zeichenzaehler nach jp nz,loop ; wenn das Programm hier angekommen ist, so befinden sich keine ; '?' im Dateinamen und der BDOS-Aufruf wird unveraendert ; weitergeleitet pop de ; Registerinhalte wiederherstellen pop bc ld hl,(userstack) ld sp,hl ; ebenso den alten Stackpointer jp NEXT ; und weiter zu BDOS ersetze: ; Hier wird die 'Search First'-Funktion eingeleitet, ; der FCB mit dem erstgefundenen Dateinamen gesetzt und ; abschliessend 'Open File' aufgerufen. ; Wenn der 'Search First' ein Fehler meldet, dann meldet ; sich die RSX mit einer einer entsprechenden Fehlermeldung an ; das aufrufende Programm zurueck. IF DEBUG ld de,meldung ; melde dass ein '?' gefunden wurde ld c,printstr ; 'Call BDOS' ueber NEXT !! call NEXT ENDIF pop de ; lade Adresse des FCB push de ; und sichern erneut ld c,searchf ; bereite Funktion vor call NEXT ; und rufe BDOS cp 0ffh ; nicht gefunden ? jp nz,gefunden ; gefunden, so fahre fort ; Hierher kommt das Programm nur, wenn 'Search First' ; nicht erfolgreich war. In diesem Fall unterbleibt der ; Open-Aufruf, da immer noch '?' im Dateinamen stehen, ; und wir kehren mit einer entsprechenden Fehlermeldung ; (Register A bzw. HL) zum rufenden Programm zurueck. pop de ; Registerinhalte wiederherstellen pop bc ld hl,(userstack) ; ebenso den alten Stackpointer ld sp,hl ret ; zurueck zum Programm gefunden: ; 'Search...' war erfolgreich, ersetze alten FCB durch ; den der gefundenen Datei und rufe 'Open File' auf. ; Die 'Search First'-Funktion legt im aktuellen DMA- ; Bereich den Directory-Sektor ab (128 Bytes), in dem ; die gefundene Datei steht und teilt in Reqister A ; mit, welcher dieser 4 Eintraege dazugehoert (0. ..3). ; Der Wert in Register A mit 32 muzltipliziert ist der ; Offset des gueltiqen Eintrags bezogen auf den Anfang ; des Sektors (32 = Laenge eines Directory-Eintrages). add a,a add a,a add a,a add a,a add a,a push af ; sichere Offset ; Um den gefundenen Namen laden zu koennen, braucht die ; RSX die aktuelle DMA-Adresse, die im SCB steht. ld c,scb ; 'Get/Set SCB'-Funktion ld de,scbpb ; SCB Parameter Block Adresse call NEXT ; BDOS Aufruf ; Reqister HL enthaelt nun aktuelle DMA-Adresse pop af ; lade Offsetwert wieder ld c,a ld b,0 ; setze Offset in Register BC add hl,bc ; HL zeigt nun auf den gefundenen FCB inc hl ; setze auf 1.Zeichen des Dateinamens pop de ; lade urspruengliche FCB-Adresse push de inc de ; setze auf 1. Zeichen Ur-Dateiname ; Kopiere den Namen der gefundenen Datei in den FCB des ; aufrufenden Programms (Ur-FCB) IF Z80 ; Mit einer Z80-CPU geht das per LDIR anderfalls ; (8080/8085) muss dieser Befehl eliminiert werden. ld bc,11 ; Anzahl Zeichen in Dateiname ldir ; Z80 Befehl ELSE ld b,11 ldir: ld a,(hl) inc hl ld (de),a inc de dec b jp nz,ldir ENDIF ; Der FCB des aufrufenden Programms ist nun bereit ; fuer den 'Open File'-Aufruf. pop de ; Alte Register wiederherstellen pop bc ; (Register C enthaelt dann wieder ; die Funktionsnummer fuer Open) ld hl,(userstack) ld sp,hl ; Alten Stackpointer wiederherstellen jp NEXT ; Das BDOS wird jetzt ganz normal die Datei oeffnen. scbpb: ; SCB Parameter Block: Eingerichtet um die aktuelle DMA- ; Adresse zu speichern (Adresse im SCB mit Offset 03ch) offset: db 03ch wert: db 0 ; 'Get'-Funktion userstack: dw 0 ; Ablage fuer alten Stackpointer ds 10 ; Bereich fuer lokalen RSX-Stack rsxstack equ $ ; RSX-Stack Basis ; Wenn DEBUG eingeschaltet ist, so wird folgende Meldung ; generiert IF DEBUG meldung: db '? im Dateinamen, abgefangen von >OPEN. RSX< ...' db 0dh,0ah,'$' ENDIF end