home *** CD-ROM | disk | FTP | other *** search
- title 'CP/M Plus PIP Erweiterung'
-
- ; patches 1 bis 7: W. Muees '89
- ; patch 8: T. Reh 260190
- ; umgeschrieben f}r Z80 T. Reh 300190
-
- ; RSX zur Erweiterung von PIP um folgende Funktionen:
- ; a) Wenn die Quelldatei einen Byte Count <> 0 hat, wird dieser auch in der
- ; Zieldatei eingetragen.
- ; b) Ist das Archive-Attribute der Quelldatei gesetzt, wird es auch in der
- ; Zieldatei gesetzt.
- ; c) Existieren Zeiteintr{ge f}r die Quelldatei, erh{lt die Zieldatei diese
- ; Daten.
- ; d) Die Eingabe von Laufwerk und User in der Form 'DU:' ist f}r Quell- und
- ; Zielangabe zul{ssig.
-
- ; Das Kopieren von Archive-Attribut und Byte Count ist kein Problem, da CP/M-
- ; Plus Funktionen hierf}r besitzt. Zeiteintr{ge lassen sich nur mit einer
- ; 'unsauberen' Methode kopieren: man mu~ die BIOS-Funktion zum Setzen der
- ; Zeitvariablen im SCB blockieren und die gew}nschten Werte direkt in den SCB
- ; eintragen. Deswegen kann diese Methode nur in Systemen funktionieren, in
- ; denen die Uhr nicht durch Interrupts den SCB aktualisiert, sondern }ber die
- ; BIOS-Funktion 26 'Time'.
- ; [nderung gegen}ber Original von W. Muees: Es ist nun erlaubt, PIPRSX auch
- ; innerhalb residenter Programme zu verwenden, die den Warmstart-Vektor auf
- ; Adresse 0000h ver{ndern. (T. Reh 270190)
-
- ; Konstanten:
-
- false equ 0 ; Boolsche Konstanten
- true equ not false
-
- test equ false ; Protokollausgaben auf Drucker
-
- cmdbuf equ 237Dh ; Kopie der Kommandozeile von PIP
- srcxfcb equ 22C7h ; Startadresse erweiterter Source-FCB
- tmpfcb equ 22F6h ; Startadresse FCB f}r tempor{re Operationen
- dstxfcb equ 2325h ; Startadresse erweiterter Dest-FCB
- actpos equ 2371h ; aktuelle Position innerhalb FCB (Parser)
- actfcb equ 247Ch ; Adresse des aktuellen FCB (Parser)
- useerr equ 21BAh ; 'Invalid User Number' Fehlereinsprung
- offuse equ 45 ; Offset f}r User in XFCB
-
- cr equ 0Dh ; ASCII Carriage Return
- lf equ 0Ah ; ASCII Line Feed
-
- ; Print-Macro f}r Kontrollausgaben auf Drucker:
-
- print macro string
- local str
- ld hl,str
- call pstring
- dseg
- str: db string,cr,lf,0
- cseg
- endm
-
- ;*********************************************************************
-
- cseg
-
- ; RSX Header :
-
- serial: defb 0,0,0,0,0,0 ; serial number field
- start: jp instal ; jump to start of RSX
- next: jp 0 ; link to BDOS
- prev: defw 0 ; link to previous RSX
- remove: defb true ; remove after operation
- nonbnk: defb false ; loaded on every system
- rsxnam: defb 'PIPRSX ' ; name of RSX
- loader: defb 0 ; loader flag
- reserv: defw 0 ; reserved area
-
- ; Installation der RSX-Unterprogramme in PIP.COM.
- ; Wird einmalig bei Aufruf von BDOS 12 durchgef}hrt.
-
- instal: ld a,c
- cp 12 ; Return Version Number ?
- jr nz,next ; nur bei diesem Aufruf patchen
- ld hl,pattab
- ld bc,8FFh ; B=8 Patches, C=255 (wegen LDI)
- patlop: ld e,(hl)
- inc hl
- ld d,(hl)
- inc hl ; zu patchende Adresse in DE
- ld a,0CDh
- ld (de),a ; CALL-Befehl einsetzen
- inc de
- ldi
- ldi ; Zieladresse einsetzen (C wird dekrementiert)
- djnz patlop ; alle 8 Patches durchf}hren
-
- ld de,scbpb
- ld c,49
- call next ; 'Get SCB 3Ah' = Addresse des SCB
- ld a,h ; SCB Page
- ld (scbdat+1),a ; Adresse des Datum-Wortes im SCB
- inc a ; (LSB der Adressen ist konstant)
- ld (timjmp+1),a ; Adresse des TIME-Einsprungs in der BIOS-Leiste
-
- if test
- print 'PIP.COM patched'
- endif
-
- ld c,12
- jr next ; das war's patchen, weiter mit BDOS 12
-
- pattab: defw 06CCh,patch1 ; zu patchende Stellen in PIP.COM
- defw 0E62h,patch2 ; sowie die Adressen der zugeh|rigen
- defw 0E75h,patch3 ; PIPRSX-Unterprogramme
- defw 0E21h,patch4
- defw 1871h,patch5
- defw 0B69h,patch6
- defw 195Ah,patch7
- defw 1EE2h,patch8
-
- scbpb: defb 3Ah,0 ; SCB PB : Get SCB address
-
- ;*********************************************************************
-
- ; Patch 1 : Nach Eingabe der Kommandozeile.
- ; Pr}fen, ob Kopieren der Attribute zul{ssig.
- ; Unzul{ssig, wenn mehrere Dateien bearbeitet werden (z.B.
- ; Anf}gen) oder bei ver{ndernden Optionen.
-
- patch1: if test
- print 'PATCH 1 reached'
- endif
-
- xor a
- call vc_inh ; Alle RSX-Variablen l|schen
-
- ld c,0 ; Flag: nicht zwischen [ und ]
- ld hl,cmdbuf
- ld b,(hl) ; B = Anzahl eingegebener Zeichen
- inc b ; Korrektur
- buftst: inc hl ; Zeiger auf n{chstes Zeichen
- dec b
- jr z,p1end ; keine weiteren Zeichen : Ende
- ld a,(hl) ; Zeichen holen
- bit 0,c
- jr nz,opttst ; innerhalb Options-Klammern: Option pr}fen
- cp ','
- jr z,p1mult ; Komma: mehrere Input-Dateien!
- cp '['
- jr nz,buftst ; [ : Anfang der Optionen
- inc c ; dann C=1 : Flag gesetzt
- jr buftst ; weiter mit n{chstem Zeichen
-
- opttst: cp ']'
- jr z,optend ; Optionsklammer geschlossen: Flag r}cksetzen
- and 5Fh ; --> Gro~schrift (geht nur bei Buchstaben)
- otst1: push hl
- push bc
- ld hl,optlst
- ld bc,optlen
- cpir ; Zeichen in '{ndernden Optionen' suchen
- pop bc
- pop hl
- jr nz,buftst ; nicht gefunden: Option erlaubt
-
- p1mult: ld a,true
- ld (inhibit),a ; Inhibit setzen: Attribute nicht kopieren
- if test
- print 'MULTIPLE SOURCE FILES or CHANGING COPY'
- endif
- p1end: ld bc,dstxfcb ; Original-Code in PIP.COM
- ret
-
- optlst: defb 'DFILNPQSTUZ' ; Liste der 'verbotenen Optionen'
- optlen equ $-optlst
-
- optend: dec c ; C wieder 0 : nicht in Optionsausdruck
- jr buftst ; weiter suchen
-
- ;*********************************************************************
-
- ; Patch 2 : Vor dem \ffnen der Quelldatei.
- ; FCB patchen, so da~ der Byte Count ermittelt wird.
-
- patch2: if test
- print 'PATCH 2 reached'
- endif
-
- ld hl,srcxfcb+32 ; 'CR' byte auf FF setzen
- ld (hl),0FFh ; --> BDOS-OPEN bringt Byte Count zur}ck.
- ld bc,srcxfcb ; Original-Code
- ret
-
- ;*********************************************************************
-
- ; Patch 3 : Nach erfolgreichem \ffnen der Quelldatei.
- ; Byte Count, Arcv-Flag und Zeiteintrag speichern.
-
- patch3: if test
- print 'PATCH 3 reached'
- endif
-
- ld hl,srcxfcb+32
- ld a,(hl) ; Byte Count der ge|ffneten Datei
- ld (bytcnt),a ; speichern
- ld (hl),0 ; CR des FCB wieder auf 0 setzen
-
- if test
- or a
- jr z,p3ncnt
- print 'File has byte count'
- p3ncnt: endif
-
- ld hl,srcxfcb+11
- ld a,(hl) ; t3' enth{lt Archive-Flag
- and 80h
- ld (arcflg),a ; Flag = 00 or 80 hex, speichern
-
- if test
- or a
- jp z,p3narc
- print 'File has archive bit set'
- p3narc: endif
-
- ld hl,srcxfcb ; Quell-FCB in internen Puffer kopieren,
- ld de,intfcb ; da BDOS 102 den FCB-Inhalt zerst|rt.
- push de
- ld bc,36
- ldir
- xor a
- ld (stampd),a ; Annahme : keine Zeiteintr{ge
- pop de ; Adresse des internen FCB
- ld c,102
- call next ; BDOS aufrufen: Zeiteintr{ge ermitteln
- or a
- jr nz,p3end ; bei Fehler Zeiteintr{ge nicht beeinflussen
-
- ld hl,intfcb+28
- call getstp ; versuchen, 'Update Stamp' zu lesen
-
- if test
- jr z,p3crea ; kein Update Stamp : Create Stamp versuchen
- push bc
- push de
- print 'File has UPDATE stamp'
- pop de
- pop bc
- jr p3end
- else
- jr nz,p3end ; Update Stamp vorhanden: verwenden
- endif
-
- p3crea: ld hl,intfcb+24
- call getstp ; versuchen, 'Create' oder 'Access' zu lesen
- jr z,p3end ; kein Eintrag : nichts tun
-
- if test
- push bc
- push de
- print 'File has CREATE stamp'
- pop de
- pop bc
- endif
-
- p3end: ld a,(2412h) ; Original PIP.COM
- ret
-
- getstp: ld a,(hl)
- inc hl
- or (hl) ; Pr}fen ob Datum <> 0
- ld (stampd),a ; Flag speichern
- dec hl ; HL wieder auf Anfang Datenfeld
- ld de,date ; Ziel : Datum-Speicher
- ld bc,4 ; 4 Bytes kopieren (Datum und Zeit)
- ldir
- ret
-
- ;*********************************************************************
-
- ; Patch 4 : Vor dem Erzeugen der Zieldatei. Systemzeit manipulieren.
-
- patch4: if test
- print 'PATCH 4 reached'
- endif
-
- ld a,(inhibit)
- or a
- jr nz,p4end ; Attribute nicht kopieren: Ende
- ld a,(stampd)
- or a
- jr z,p4end ; Keine Zeiteintr{ge zu kopieren: Ende
-
- ld hl,(timjmp) ; Adresse des BIOS-26 Einsprungs
- ld a,(hl)
- cp 0C3h ; 'JP'-Befehl dort ?
- jr nz,p4end ; nein: lieber nichts patchen
-
- ld (changed),a ; Flag setzen: SCB und BIOS manipuliert
- ld (hl),0C9h ; 'JMP' durch 'RET'-Befehl ersetzen
- ld hl,date ; Speicher Datum und Zeit von Quelldatei
- ld de,(scbdat) ; Ziel: Datenfelder im SCB
- ld bc,4 ; 4 Byte in den SCB kopieren
- ldir
-
- if test
- print 'SYSTEM date&time changed'
- endif
-
- p4end: ld bc,tmpfcb ; Original PIP.COM
- ret
-
- ;*********************************************************************
-
- ; Patch 5 : Nach Schlie~en der Zieldatei. Systemzeit restaurieren.
-
- patch5: if test
- print 'PATCH 5 reached'
- endif
-
- call restor ; BIOS-Einsprung wieder hinbiegen
- ld a,(237Bh) ; Original PIP.COM
- ret
-
- ;*********************************************************************
-
- ; Patch 6 : Im Error-Handler. RSX r}cksetzen f}r evtl. Wiedergebrauch.
-
- patch6: if test
- print 'PATCH 6 reached'
- endif
-
- ld a,true
- call vc_inh ; Alle RSX-Variablen r}cksetzen
- ld a,(2368h) ; Original PIP.COM
- ret
-
- ;*********************************************************************
-
- ; Patch 7 : Vor dem Zuweisen und Setzen der Zieldatei-Attribute
-
- patch7: if test
- print 'PATCH 7 reached'
- endif
-
- ld a,(inhibit)
- or a
- jr nz,p7end ; keine Attribute kopieren: Ende
- ld a,(bytcnt)
- ld (dstxfcb+32),a ; Byte Count in Ziel-XFCB einsetzen
- ld hl,dstxfcb+6
- set 7,(hl) ; f6' setzen (Flag: Set Byte Count)
- ld hl,dstxfcb+11 ; Zeiger auf t3 (t3' ist Archive-Flag)
- ld a,(arcflg)
- or (hl)
- ld (hl),a ; t3' entsprechend Quelle setzen
- call vclear ; Variablen l|schen
- p7end: ld bc,dstxfcb ; Original PIP.COM
- ret
-
- ;*********************************************************************
-
- ; Patch 8 : Parser f}r 'DU:'-Eingaben manipulieren.
-
- patch8: ld a,(actpos) ; derzeitige Zeichenposition im Parser
- sub 2
- cp 2
- jr nc,p8end ; nicht 2 oder 3 : keine g}ltige DU-Angabe
- ld b,a ; B = 0 oder 1 (bei 1 bzw. 2 Stellen User)
- ld hl,(actfcb) ; Zeiger auf bereits begonnenen 'Dateinamen'
- inc hl ; -> Drive-Buchstabe
- inc hl ; -> 1. Ziffer Usernummer
- ld a,(hl)
- sub '0'
- cp 10
- jr nc,p8end ; keine Ziffer 0..9 : Abbruch
- dec b
- jr nz,pat8_1 ; actpos war 2 : nur eine Ziffer
- inc hl ; -> 2. Ziffer
- ld b,a ; Zehner nach B
- add a,a
- add a,a
- add a,b
- add a,a
- ld b,a ; 10 * Zehner nach B
- ld a,(hl) ; 2. Ziffer
- sub '0'
- cp 10
- jr nc,p8end ; keine Ziffer 0..9 : Abbruch
- add a,b ; User = 10 * Zehner + Einer
- pat8_1: cp 16
- jp nc,useerr ; Fehler: Usernummer zu hoch
- ld ix,(actfcb)
- ld (ix+offuse),a ; User im XFCB entsprechend Angabe setzen
- ld a,1
- ld (actpos),a ; actpos = 1, damit Drive-Code ok
- p8end: ld a,(actpos) ; Originalcode in PIP.COM
- ret ; zur}ck in PIP.COM
-
- ;******************************************************************************
-
- ; Variablen initialisieren, Einsprung in BIOS-26 wiederherstellen.
-
- vc_inh: ld (inhibit),a ; vorher Wert in A --> Inhibit-Flag
-
- vclear: xor a
- ld (bytcnt),a ; Zwischenspeicher f}r Byte-Count l|schen
- ld (arcflg),a ; Archive nicht gesetzt
- ld (srcxfcb+32),a ; Source: CR=0
-
- restor: ld a,(changed) ; Wurde BIOS-Einsprung gepatcht ?
- or a
- ret z ; nein: Ende
- ld hl,(timjmp)
- ld (hl),0C3h ; sonst Sprungbefehl restaurieren
- xor a
- ld (changed),a ; BIOS-Einsprung wieder Original
-
- if test
- print 'SYSTEM date&time restored'
- endif
-
- ret
-
- ;*********************************************************************
-
- ; Datenbereich:
-
- dseg
-
- scbdat: defw 00F4h ; Adresse des Datum-Wortes im SCB
- timjmp: defw 004Eh ; Adresse des TIME-Einsprungs der BIOS-Leiste
-
- inhibit:defs 1 ; 'true' wenn keine Attribute kopiert werden
- changed:defs 1 ; Flag <> 0 wenn BIOS-Einsprung manipuliert
- stampd: defs 1 ; Flag <> 0 wenn Source Zeiteintr{ge hat
-
- bytcnt: defs 1 ; Byte Count der Quelldatei
- arcflg: defs 1 ; Archive Attribut der Quelldatei (00 oder 80)
- date: defs 2 ; Datum und Uhrzeit aus Update-Eintrag
- time: defs 2 ; Reihenfolge mu~ <date,time> sein
-
- intfcb: defs 36 ; Kopie des Quell-FCB (ohne Erweiterungen)
-
- ;*********************************************************************
-
- ; Routine zum Ausdrucken von Texten als Test-Protokoll.
- ; S{mtliche Register k|nnen zerst|rt werden.
-
- if test
- cseg
- pstring:ld a,(hl)
- inc hl
- or a
- ret z ; NUL-Character : Ende
- push hl
- ld c,a ; Zeichen nach C
- ld hl,(timjmp) ; Adresse Einsprung BIOS-26
- ld l,0Fh ; Adresse Einsprung BIOS-5 'List Output'
- call ipchl ; Als UP Aufrufen
- pop hl
- jr pstring ; weiter bis NUL-Char
- ipchl: jp (hl)
- endif
-
- end
-