;FilePatcher by haftmann#software
;Limitations:
;Max. search pattern length: 255 bytes (by design)
;Max. replace pattern length: same as search pattern length (by design)
;Max. replace locations per file: 32 (by MaxPos constant)
;Max. file size: 2G-1 bytes (by system: DOS)
;Characteristics:
;file scan buffer: 4KB+4KB double buffer (by BufSize constant)
;resolve of wrap-around: by copying few bytes from upper to lower buffer
;program parses the command line once for each file (poor, saves memory)
;Change log:
;11/06: - fixed bug with uninitialized data near PosMin2
; - handling negative positions introduced by -p-xxx
; * errorlevel == 1 when nothing found
;
;09/01: + unicode (wide char) support (no OEM translation), option u
; + redirection of stdin for search pattern
; * shortened hex address output for short files
; * code optimized: "bset" (=SETFLAG) instead of "or" and such
;
;10/94: + p option for offsetting found position(s)
;
;1994: initial version as cracking aid (DiskEdit sucks)
;To do:
;+ Replace pattern from file
;* Structuring of source (proc/endp)
;* far scan buffer 64KB with automatic wrap-around (great idea)
;+ true inserting and deleting, moving rest of file
;* Enlargement of limits: search and replace pattern length, no replace limit
;+ searching and replacing with "wild" bytes or bits inside pattern
;+++ graphical hex/ascii viewer/editor, based on ANSI control sequences?
;Sucht Hexzeichenfolge in Datei, gibt Position (hex) aus
;und patcht das File.
;fpatch -scd2103 -p+1 -p-1 -rcd-21-04 anders.exe
;oder (Trennzeichen '-,/' erlaubt)
;fpatch /p204f /r#103,#2,##5 \dos/attrib.exe
;oder (# markiert Dezimal-Bytes, ## Dezimal-Wörter (Präfix!))
;fpatch -s'All Rights Reserved'0 -r"All Rights Reversed"0 -m term.com
;-p Positioniere!
;-s Suche!
;-r Ersetze! (Warnung bei fehlendem -m, wenn Suchkette zum Ersetzen
; mehrfach auftritt)
;-m Ersetze auch mehrfach!
;-i Suche vorgegebene Kleinbuchstaben case-insensitiv!
;-d Belasse Filedatum
;-# Dezimale Positionsausgabe
;Später noch:
;-dn,n,n,n,n,n Setze Filedatum auf Wert
MaxPos equ 32 ;Such/Ersetzpositionen pro File
BufSize equ 1000h ;Diskpuffergröße 4 KiloByte
;ein Maß für den transienten Bedarf des Programms
INCLUDE prolog.asm
;Start
mov bx,offset StckEnd
cmp sp,bx
mov al,8 ;Fehlercode
jn c,errm ;Insufficient Memory
mov sp,bx
;Dieses Programmstück sollte unnötig sein...
mov bx,(StckEnd-PSPOrg+0fh)/16 ;Paragrafengleichung
DOS 4ah ;Speicherblockgröße verändern
jn c,errm
xor bx,bx ;stdin
DOS 4400h ;sollte ohne Fehler arbeiten
btst dx,bit 7
jnz is_device
bset [Switches],(bit 11) or (bit 2)
is_device: call ParseO
jc errP ;Parameterfehler!
jz help ;Segítség!
loop1: ;Äußere Schleife!!
call FindFirst
jc errF
mov [parseptr],si
loop2: ;Innere Schleife!!
mov ax,3d02h
and [byte switches],37h ;Bits 3, 6 und 7 löschen!
and al,[byte switches]
int 21h ;Öffnen R/W oder R/O
jc errF ;DX=nullterminierter Filename
mov [handle],ax
xchg bx,ax ;wie üblich
call FetchFileLastByte
DOS 5700h ;Datum lesen
jc errF
mov [DateStamp],dx
mov [TimeStamp],cx
bset [switches],bit 7;scharf!
call ParseO
pushf
call SetStamp
mov bx,[handle]
DOS 3eh ;Schließen
popf
jc errP
call FindNext
jc errm ;nur DOS-ERROR
jnz loop2
mov si,[parseptr]
loop3: lodsb
cmp al,' '
jz loop3
dec si
jnc loop1 ;Nächste Gruppe von Dateinamen!
mov al,[byte switches+1]
and al,1
xor al,1
jr exial ;Errorlevel 01 bei Nothing found
help: ;Hilfetext
mov dx,offset msgH
xor bl,bl ;Errorlevel 0
jr errp1
errP: ;Parameterfehler
mov dx,offset msgP
mov bl,0ffh ;Errorlevel 255
jr errp1
errF: ;Dateifehler
xchg bx,ax
push dx
PRINT msgF
pop dx
call OSTR
jr errp11
errm: ;Fehlermeldung DOS
xchg bx,ax
PRINT msgE
mov al,bl
call AHEX
errp11: mov dx,offset NL$
errp1: mov ah,9
int 21h
exi: xchg ax,bx
exial: DOS 4Ch ;Fehlercode durchpipen
;(wie sich das für ein ordentliches Programm gehört!)
ParseO: ;Optionen abgrasen, CY=1: Fehler, Z=1: Hilfe angefordert
;sonst: SI zeigt auf (vermeintlichen) Dateinamen
cld
mov si,81h
xor ax,ax
mov [FndCntGes],ax
mov [PosCnt],ax
btst [Switches],bit 11
jz Parse2
xor bx,bx ;stdin
call Seek0 ;seek, AL ist schon 0
mov cx,255
mov dx,offset PString+1
DOS 3Fh ;read
mov [PString],al
mov ax,offset Parse
push ax
jmp opFindFromStdin ;Lossuchen!
Parse:
jc ParsErr
bset [switches],bit 3 ;mindestens 1 Kommando ok.
Parse2: lodsb
cmp al,' '
jz Parse2
call IsOption
jz Option ;Option prüfen!
dec si ;auf Dateiname, Z=0
btst [switches],bit 3
jz opErr ;Fehler wenn keine Option
ParsErr: ret
Option: ;Zuerst nur Syntaxprüfung von Optionen!
;Scharf mit gesetztem Bit 7(Switches)!
mov ax,offset Parse
push ax ;Rückkehradresse
lodsb ;Buchstabe
call UpCase
cmp al,'P'
je opPos
cmp al,'S'
jn z,opFind
cmp al,'R'
jn z,opRepl
cmp al,'M'
je opMore
cmp al,'I'
je opCase
cmp al,'H'
je opHelp
cmp al,'?'
je opHelp
cmp al,'D'
je opDate
cmp al,'#'
je opDecOutput
cmp al,'U'
je opUnicode
cmp al,'!'
je opName2StdOut
opErr: stc ;Syntaxfehler
ret
opHelp: pop ax ;1 Stackebene herauf!
opRet: ret
opPos: ;Positioniere!
lodsb
cmp al,'+'
jz PosPlus
cmp al,'-'
jz PosMinus
dec si
call InPos
jc opErr ;Zahl zu groß
jmp AppendPos
PosPlus:
call InPos
jc opErr
PosMin2: btst [switches],bit 7
jz opRet
mov cx,[FndCnt] ;Nur die zuletzt gefundenen!
mov bx,[PosCnt]
sub bx,cx
AddLoop: jcxz opRet
call GetPosAdr ;setzt DI je nach bl
add [di],ax
adc [di+2],dx
js al_neg
al_cont: dec cx
inc bl
clc
jr AddLoop
PosMinus:
call InPos
opErr0: jc opErr
neg ax
adc dx,0
neg dx
jr PosMin2
opDecOutput: ;setzt dezimalen Output
bset [switches],bit 4
ret
opDate: ;setzt "Keine Datumsverändering"
bset [switches],bit 5
ret
opCase: ;setze Casesensitivität
bset [switches],bit 0
ret
opMore: ;setze Mehrfachersetzung
bset [switches],bit 2 ;wird eh rückgesetzt pro File-Lauf
opRet1: ret
opUnicode: ;setzt Unicode-Eingabestrings (gilt nicht für Hex-Bytes)
bset [switches],(bit 12) or (bit 13)
lodsb ;folgt "M" für Motorola?
call UpCase
cmp al,'M'
je to_ret
bres [switches],bit 13
dec si
to_ret: ret
opName2StdOut:
cmp [byte si],'-'
mov bx,200h
jne n2o
mov bh,4
inc si
n2o: or [switches],bx
opRet01: ret
al_neg: ;negative Ersetzungsposition
btst [switches],bit 2 ;Doppelfunktion von -m
jnz al_cont ;wird von BlockWrite ignoriert
PRINT neg$
mov bl,-2
jmp errp11
opRepl: ;Ersetzung
bset [switches],bit 1;wird NICHT MEHR rückgesetzt!
call ReadStringW
jc opErr0
btst [switches],bit 7
jz opRet1
mov cx,[PosCnt]
jcxz nrpl
btst [switches],bit 2;Mehrfachersetzung erlaubt?
jnz rpl1
cmp [FndCntGes],2 ;????(Nicht ganz klar)
jc rpl1
PRINT rplrq
call YesNo
jnz rpl3
rpl1:
PRINT rpl$
mov bl,0
rpl2: call GetPos
inc bl
call BlockWrite
loop rpl2
PRINT done$
rpl3: mov [PosCnt],0 ;ClearPos
mov [FndCntGes],0 ;Fürs nächste Mal
jr NLRET01
nrpl: PRINT nrpl$
NLRET01: jmp NLRET
opFind: ;Suchen
btst [switches],bit 11; Standardeingabe umgelenkt?
jn nz,opErr ;ja: Fehler!
call ReadString
opFindFromStdin:
jc opRet2 ;Fehler
btst [switches],bit 7
jz opRet2 ;Operation noch kalt
mov [FndCnt],0
push si
call qsrc ;Suche Stringvorkommen
pop si
jc opRet2
mov ax,[FndCnt]
add [FndCntGes],ax ;Gesamtfindungen summieren
or ax,ax
jz nfnd
bset [switches],bit 8;Es wurde überhaupt etwas gefunden!
btst [switches],bit 10
jnz opRet2
push ax
mov dx,offset FileName ;Stattdessen Dateiname ausgeben
call OSTR
pop ax
btst [switches],(bit 9) or (bit 10) ;ein Quiet-Modus?
jnz NLRET
mov cx,ax
mov bx,[PosCnt]
sub bx,cx
PRINT fnd$ ;'Found at:'
HexLoop: mov al,' '
call OCHR
call GetPos
inc bl
push cx
call PosOut ;ausgeben
pop cx
loop HexLoop
jr NLRET
nfnd: btst [switches],bit 9
jnz opRet2
mov dx,offset filename
call OSTR
btst [switches],(bit 9) or (bit 10)
jnz NLRET
PRINT nfnd$ ;'Not found'
NLRET: PRINT NL$
clc
opRet2: ret
ReadStringW: mov cl,0
jr rds1
ReadString: ;Nachfolgenden String in Standardpuffer einlesen
mov cl,1
rds1: mov di,offset PString ;zunächst nur "void buffer"
xor ax,ax
push di cx
stosb ;Längenbyte
call ReadBytes
mov ax,di ;das Ende +1
pop cx di
jc RdsErr
sub ax,di ;sollte CY=0 sein!
dec al
cmp al,cl ;Länge Null?
stosb ;korrekte Länge
RdsErr: ret
proc Seek0
;Datei-Handle BX zur Position 0L seeken, AL=Bezug (0, 1 oder 2)
;PE: BX=Handle, AL=Ursprung
;PA: DX:AX=Position
;VR: AX,CX,DX
xor cx,cx
xor dx,dx
DOS 42h
ret
endp
proc FetchFileLastByte
;Dateigröße-1 bestimmen
;PE: BX=Handle
;PA: -
;VR: AX,CX,DX,DI
mov al,2
call Seek0
mov di,offset FileLastByte
sub ax,1
sbb dx,0
stosw
xchg dx,ax
stosw ;6 Bytes statt sonst 7
mov al,0
call Seek0
ret
endp
qsrc: ;Schnellsuche im Pufferbereich, Problem: Wrap Around!
;Lösung: Puffer doppeln, ab&zu Hinterteil nach vorn schieben
;(di)PString
;si: lfd. Suchposition
;cx: Puffer-Restlänge
xor cx,cx ;auf Null
xor dx,dx ;auch Null
mov ax,4200h ;Position Null!
mov bx,[handle]
int 21h
call BlockRead
jc SuchEnd
mov cx,ax ;Gelesene Länge
call VCopy
call BlockRead
jc SuchEnd ;Lesefehler
add cx,ax ;verlängern
mov [word FilePos],0
mov [word FilePos+2],0 ;nullsetzen
Schleife: jcxz SuchEnd1
mov ah,[PString+1] ;1. Suchzeichen
lodsb
dec cx
call CHRComp ;ah=al?
jnz Ungl
push cx si ;Position halten!
mov di,offset PString
mov bl,[di]
inc di
Innen: dec bl
jz FndEntry ;Position verewigen
inc di
mov ah,[di]
lodsb ;nächstes Byte
call CHRComp ;vergleichen
jnz Ungl1
jcxz Ungl1
dec cx
jr Innen
FndEntry:
pop ax
push ax
sub ax,offset Buffer1+1
add ax,[word FilePos]
mov dx,[word FilePos+2]
adc dx,0 ;Übertrag
call AppendPos ;dx-ax eintragen
jc SuchEnd2 ;Tabelle randvoll, sei kein Fehler
inc [FndCnt]
Ungl1: pop si cx
Ungl:
cmp si,offset Buffer2
jc Schleife
;Vorkopieren und Nachladen
call VCopy
call BlockRead
jc SuchEnd ;Lesefehler
add cx,ax ;verlängern
jr Schleife
SuchEnd2: pop si cx
SuchEnd1: clc
SuchEnd: ret
VCopy: ;Hinteren Bereich nach vorn kopieren
push cx di
mov si,offset Buffer2
mov di,offset Buffer1
shr cx,1 ;Boost
inc cx
rep movsw
mov si,offset Buffer1
pop di cx
ret
SetStamp: ;Stempel setzen wenn alles dazu ok
mov al,[byte switches]
not al
and al,22h
jnz SStE
mov bx,[handle]
mov cx,[TimeStamp]
mov dx,[DateStamp]
mov ax,5701h
int 21h
SStE: ret
BlockRead: ;Block-Lesen nach Buffer2
;PE: -
;PA: AX: Anzahl Zeichen
; CY: Lesefehler
;VR: AX
push bx cx dx
mov cx,BufSize ;Maximale Länge versuchen
add [word filepos],cx ;mit dem neuen CX
adc [word filepos+2],0
mov dx,offset Buffer2
mov bx,[handle]
DOS 3fh ;lesen
BW1: pop dx cx bx
ret
BlockWrite: ;Block-Schreiben aus Stringpuffer (max. 255 Bytes)
;PE: DX-AX: Dateiposition (nicht negativ!)
;PA: CY: Schreibfehler
;VR: AX
push bx cx dx
test dx,dx
js BW1 ;raus mit CY=0 (ignorieren)
mov bx,[handle]
mov cx,dx
mov dx,ax
mov ax,4200h
int 21h ;positionieren
mov cl,[PString]
xor ch,ch
mov dx,offset PString+1
DOS 40h ;schreiben
jc BW1
cmp ax,cx ;Disk full, ax<cx?
jr BW1
UpCase: ;al:= UpCase(al) ohne hohe Zeichen
cmp al,'a'
jb UpCas1
cmp al,'z'
ja UpCas1
and al,not 20h
UpCas1: ret
CHRComp: ;Gegenteil von UpCase mit Testung des Flags
test ah,20h ;Großbuchstabe gesucht?
jz LowCas1 ;bleibt al!
btst [switches],bit 0;Nie LowCase?
jz LowCas1 ;al bleibt
cmp al,'A'
jb LowCas1
cmp al,'Z'
ja LowCas1
or al,20h
LowCas1: cmp ah,al ;Z ist Ergebnis
ret
YesNo: ;liefert Z=1 beim Drücken auf 'Y'
PRINT yesno$
DOS 1
call UpCase
push ax
PRINT NL$
pop ax
cmp al,'Y'
ret
AppendPos: ;Füge künftige Ersetzposition hinzu!
;CY=1 Tabelle voll
mov bx,[PosCnt]
cmp bx,MaxPos
cmc
jc APErr ;Zu viele Positionen
inc [PosCnt]
call GetPosAdr
mov [di],ax
mov [di+2],dx ;Zeiger eintragen
APErr: ret
GetPosAdr: ;Erhalte in DI den Zeiger auf das Dateipositionsarray
push bx
shl bx,1
shl bx,1
mov di,offset Positions
add di,bx ;auf 'nem 386er ein "lea di,[Positions+bx*4]"
pop bx
ret
GetPos: ;Erhalte in DX-AX Ersetzposition Nr. bl
call GetPosAdr
mov ax,[di]
mov dx,[di+2]
ret
;Testet ob Zeichen eine Ziffer, al:= al-'0'!
IsDigit: sub al,'0'
jc ID1
cmp al,10
cmc
ID1: ret
_ANUM
;AL:= Hexäquivalent zum ASCII-Zeichen AL, CY=1: Keine HexZahl!
HexNibble: call ANum
cmp al,10h
cmc
hn1: ret
;Zweistelliges Hex-Byte einlesen nach [di]
InHexByte: push cx
mov al,[si]
call HexNibble
jc IHB1 ;Fehler 1.Zeichen
inc si
mov cl,4
mov ch,al
shl ch,cl
mov cl,al ;aufheben für 1-Zeichen-Hexzahlen!
mov al,[si]
call HexNibble
jc IHB2
or al,ch
inc si
jr IHB3
IHB2: mov al,cl ;alte Tetrade!
IHB3: stosb
IHD1: clc
IHB1: pop cx
ret
;8stellige Hexzahl (Dateiposition) einlesen nach DX-BX (und AX)
InHexDD: push cx
mov al,[si]
call HexNibble
jc IHB1 ;Schon 1. Zeichen fehlerhaft!
xor bx,bx
xor dx,dx
IHD2: mov cx,4
IHD3: shl bx,1
rcl dx,1
jc IHB1 ;Zahl zu groß
loop IHD3
or bl,al
inc si
mov al,[si]
call HexNibble
jnc IHD2
mov ax,bx
jr IHD1 ;clc, pop cx, ret
InPos: ;wertet Dezpräfix '#' aus
cmp [byte si],'#'
jne InHexDD
inc si
;Dezimalzahl nach DX-AX einlesen, Quelle=[si]
InDez: push bx
mov al,[si]
call IsDigit
jc IND1
xor bx,bx
xor dx,dx
InD2: push si di cx
xchg si,bx
xchg di,dx
mov bl,al
xor bh,bh
xor dx,dx
mov cx,10
InD3: add bx,si
adc dx,di
loop InD3
pop cx di si
jc IND1 ;Fehler: Überlauf!
inc si
mov al,[si]
call IsDigit
jnc InD2
clc
xchg ax,bx
IND1: pop bx
ret
;Testet, ob AL ein Opionspräfix ist
IsOption: cmp al,'/'
jz IO1
cmp al,'-'
IO1: ret
;Allgemeine Zeichenkette bis zum Leerzeichen einlesen
ReadBytes: ;(Zeichenkette darf nicht leer sein!)
;(ZK darf kein Zeichen <20h enthalten!)
rdLoop: lodsb
call IsOption
jz rdLoop
cmp al,','
jz rdLoop ;Komma als Trennzeichen zulassen
cmp al,'#'
je rdDez ;Dezimalbyte
cmp al,''''
jz rdString
cmp al,'"'
jz rdString
dec si ;Zeiger zurück!
cmp al,21h
cmc
jnc rdDone ;Ende Zeichenkette
call InHexByte
jc RB1 ;Fehlerhaft!
jr rdLoop
;
rdDez: cmp [si],al ;Doppel-Doppelkreuz?
je rdDezW
call InDez
jc RB1 ;Überlauf!
or dx,dx
jnz RB1 ;zu groß
or ah,ah
jnz RB1 ;noch zu groß
stosb
jr rdLoop
;
rdDezW: inc si
call InDez
jc RB1
or dx,dx
jnz RB1
stosw
jr rdLoop
;
rdString: mov cl,al ;Delimitor merken!
rdStr1: lodsb
cmp al,cl ;Stringende?
jz rdStr2
cmp al,13 ;Steuerzeichen CR?
je RB1 ;Fehler!
cmp al,10 ;LF?
je RB1
or al,al ;NUL?
jz RB1
rdStr3: btst [switches],bit 12
jz rdStr_byte
mov ah,0 ;eigentlich: Tabellenzugriff!
btst [switches],bit 13
jz rdStr_intel
xchg ah,al
rdstr_intel: stosw
jr rdStr1
rdstr_byte:
stosb
jr rdStr1
rdStr2:
cmp [si],al ;Noch ein Delimitor?
jne rdLoop ;nein, echtes String-Ende
inc si
jr rdStr3 ;als 1 Trennzeichen übersetzen
;
RB1: stc
rdDone: ret
;========= AUSGABEN ========================= DXAX AXHX AHEX DXAXDEZ ====
;######TEST#####
; db 6 dup (90h) ;paar Nops
PosOut: ;Positionsausgabe
btst [switches],bit 4;Bit 4=dezimal?
jnz DXAXDez
dxax: ;Hexausgabe DX-AX mit Bindestrich, aber DX nur, wenn Dateilänge>64KB
cmp [word HIGH FileLastByte],0
jz axhx ;weil High-Teil uninteressant
call axhx0
xchg cx,ax
mov al,'-'
call OCHR
xchg ax,cx
axhx0: xchg dx,ax
axhx: ;Hexausgabe AX
call ahex0
ahex0: xchg ah,al
ahex: ;Hexausgabe AL
push ax ;Werte erhalten
mov cl,4 ;oberes Nibble auf Bit 3...0
shr al,cl ; schieben
call ahex1
pop ax
ahex1: and al,0fh
add al,90h ;Hex -> ASCII
daa
adc al,40h
daa
OCHR: ;Zeichenausgabe ohne DX-Zerstörung (natürlich CHR in AL!)
push ax dx
mov dl,al
mov ah,2
int 21h
pop dx ax
ret
DXAXDez:;DX-AX dezimal vzl ausgeben mit Vornullenunterdrückung
;(unsigned long)
push bx
mov cl,11 ;maximale Ziffern(?)
AXD1: call ODigit
push cx
inc sp ;Nur H-Teil pushen!
dec cl
jnz AXD1
;
mov cx,11 ;LIFO dreht Ziffern herum!
AXD2: dec sp
pop ax ;AH=Zahl aus LIFO
or ch,ah ;Führende Null ausblenden
jnz AXD3
cmp cl,1
jne AXD4 ;bis auf die letzte, bitte!
AXD3: mov al,ah
add al,'0'
call OCHR
AXD4: dec cl
jnz AXD2
pop bx
ret
ODigit: ;Ziffernberechnung (ch), leider von hinten nach vorne!
;dx-ax durch 10 teilen, ohne INT0 zu erzeugen!
push ax
xor ax,ax
xchg ax,dx
mov bx,10 ;Divisor
div bx ;AX:= AX/10, Rest DX
mov bx,sp
xchg [bx],ax ;Sheisz Processor!
mov bx,10 ;Divisor
div bx ;AX:= DX-AX/10, Rest DX
mov ch,dl ;die Dezziffer!
pop dx
ret
FindFirst: ;was der Name schon sagt...
;PE: si: Dateiname mit Wildcards, abgeschlossen mit <=20h
;PA: dx: Dateiname als ASCIIZ
; si: Zeigt auf 1. Zeichen nach Dateiname
; CY: Fehler aufgetreten, AX=Code
; Z : Keine (weiteren) Dateien
push cx di
mov dx,offset DTA
DOS 1ah
mov di,offset FileName
call strcopyx
cmp [byte filename],'!' ;List-File?
jz OpenList
ff4: cmp di,offset filename
jz ff3
mov al,[di-1]
cmp al,'/'
jz ff3
cmp al,'\'
jz ff3
cmp al,':'
jz ff3
dec di
jr ff4
ff3: mov [BehindPath],di ;merken für FindNext
mov cx,7
mov dx,offset filename
DOS 4eh ;FindFirst
jc ff5
ff6: push si
mov si,offset DTA+1eh
mov di,[BehindPath]
call strcopyx
pop si
ff7: mov dx,offset FileName
or dx,dx ;Z=0, CY=0
ff5: pop di cx
ret
FindNext: ;
;PA: dx: ASCIIZ Dateiname
; CY: Fehler
; Z: Keine weiteren Dateien
push cx di
cmp [BehindPath],100
jc FindNextFile
DOS 4fh
jnc ff6
cmp al,12h
stc
jnz ff5
clc
jr ff5
OpenList: ;Dateiliste öffnen
mov dx,offset filename+1
mov ax,3d00h
int 21h
jc ff5 ;Listendatei nicht gefunden
mov [BehindPath],ax ;Handle retten
ffl1: call input ;CY=1: Fehler oder Dateiende!
jc ff5 ;Nicht EIN Dateiname erzeuge ERROR!
cmp al,21h
jc ffl1
fnf2: mov di,offset filename
ffl3: stosb
call input
jc ffl2 ;Ende der Liste
cmp al,21h
jnc ffl3
ffl2: xor al,al
stosb ;Endezeichen Null
jr ff7 ;Z=0
FindNextFile:
call input
jc fnf1 ;Keine gültigen Zeichen gelesen
cmp al,21h
jc findnextfile
jr fnf2
fnf1: xor al,al ;CY=0, Z=1: Listenende
jr ff5
input: ;liest 1 Byte von der Listendatei, schließt ggf. die Datei
push bx cx dx
mov bx,[BehindPath]
mov dx,offset a_byte
mov cx,1
DOS 3fh
jc inp1
cmp ax,1 ;Null Bytes gelesen?
jc inp1
mov al,[a_byte]
inp1: pop dx cx bx
ret
strcopyx: ;StringCopy mit Abschluß->=20h
cld
ff2: cmp [byte si],21h
jc ff1
movsb
jr ff2
ff1: mov [byte di],0 ;Abschluß-Null
ret
OSTR: ;Ausgabe nullterminierter String ab dx auf StdOut
push si dx
pop si
cld
OSTRloop: lodsb
or al,al
jz OSTRexi
call OCHR
jr OSTRloop
OSTRexi: pop si
ret
msgE: db 'DOS error $'
msgP: db 'Command line error. For help type -h'
NL$: db nl,'$'
msgF: db 'Can''t find or open file $'
fnd$: db ': Found at:$'
nfnd$: db ': Not found$'
done$: db 'done$'
nrpl$: db 'replace address buffer empty$'
rpl$: db 'replace.. $'
rplrq: db 'multiple locations found, replace all?$'
yesno$: db ' (Y/N)$'
neg$: db 'negative position - aborting (use -m before -p to ignore)$'
msgH:
db 'FilePatch 1.14 (haftmann#software) ++ Public Domain ++',nl
db 'Usage: fpatch {/|-}options filename [filename..] [<pattern-file]',nl
db 'Options are:',nl
db ' -sSTRING search string and store positions in address buffer (max. 32)',nl
db ' -p{hexnumber|#decnumber} store absolute position in replace address buffer',nl
db ' -p{+|-}{hexnum|#decnum} offset those buffer positions found by last search',nl
db ' -rSTRING replace STRING into positions stored and clear buffer for next op.',nl
db ' -m do not ask when replacing at multiply found positions (replace all)',nl
db ' -i search lower case letters in STRING case insensitively (strict for upper)',nl
db ' -u strings are Unicode (little endian), -um (big endian), no OEM conversion',nl
db ' -d keep file date and time',nl
db ' -# show positions found by option "-s" in decimal',nl
db ' -![-] write list file with [without] matches to stdout',nl,10
db 'STRING is: universal, spaceless chain of the following parts:',nl
db ' 1- or 2-digit hex byte with or without delimiters ,-/',nl
db ' #decimal-byte, ##decimal-word, "string" or ''string''',nl,10
db 'filename: Wildcards allowed, List-File with prefix ''!''!',nl,10
db 'Examples: fpatch -sCD213 -p+1 -p-1 -rcd-21-04 example.exe',nl
db ' fpatch /p204F /r#103,#2,##5 \path\*.exe',nl
db ' fpatch -s''All Rights Reserved''0 -r"All Rights Reversed"0 win.com',nl
db '$'
PosCnt dw 0 ;Anzahl Ersetzpositionen
Switches dw 0 ;Bit-Switches
;13: Big-Endian-Unicodes (Motorola-Notation)
;12: Unicode-String-Interpretation
;11: Standardeingabe ist umgeleitet, -s unmöglich, -m automatisch
;10: Ausgabe wenn String NICHT gefunden (statt "not found")
;9: Ausgabe des Dateinamens auf StdOut, wenn String gefunden (statt "found at")
;8: Es wurde (heute) schon mal was gefunden (für Errorlevel)
;7: "Scharfe" Aktionen an Datei (sonst nur Kommandozeilen-Syntaxprüfung)
;5: Keine Veränderung des Zeitstempels des Files
;4: Dezimale Positionsangaben
;3: Mindestens eine Option wurde angegeben
;2: Ignoriere Warnungen wenn mehrere Dateipositionen passen (-m)
;1: Ersetzen in Kommandozeile vorhanden: Datei im Modus 2 öffnen!
;0: Beachte Groß/Kleinschreibung beim Suchen nicht!
FndCntGes dw 0
FndCnt dw ?
handle dw ?
TimeStamp dw ?
DateStamp dw ?
FileLastByte dd ? ;nur für Breite der Hex-Ausgabe
ParsePtr dw ?
FilePos dd ? ;Dateiposition des Buffer1-Anfangs
DTA db 2bh dup (?) ;Unser DTA für Wilde Karten
A_Byte db ? ;einzelnes Lese-Byte (f. List-File)
FileName db 80 dup (?) ;Merkstelle für Dateiname und Pfad
BehindPath dw ?
alignv 16
Positions dd MaxPos dup (?) ;32 Merkpositionen pro File
PString db 100h dup (?) ;256 Byte Pascal-String
Buffer1 db BufSize dup (?) ;4 KB Lesepuffer
Buffer2 db BufSize dup (?) ;Noch ein Lesepuffer
Stck db 100h dup (?) ;Kellerspeicher
StckEnd:
ENDC
Detected encoding: OEM (CP437) | 1
|
|