          ͻ
                                       
                                               
                            
                                       
                              
                                
            (c) 2000 Eugene Toder      version 1.10  
          ͼ

1. WHAT IS IT?
    CrtFix fixes bug in Borland Pascal's CRT unit that causes run-time
error 200 (division by zero usually, but not in this case) in the very
beginning of ANY programm that uses CRT unit when this programm is run
on Pentium Pro 200 or faster computer. This bug is hidden in Delay()
function startup code when it's testing CPU's speed. After dividing DX:AX
(which is the number of passes of delay's main loop in 1/18 second) by
55 (37h) the result doesn't fit into AX (DX:AX/55>$FFFF) and THIS causes
run-time error 200.

2. WHAT DOES IT DO?
    Of course, there are many ways of fixing this bug (you can divide
DX:AX by 110 (or more), or look for overflowing (like TPPATCH does), or do
anything else), but I've found another way. As I've said Delay() startup
code runs Delay() main loop for 1/18 second and calculates number of passes.
But on fast machines this number is too high. So we can just increase time
needed for one main loop's pass. This is original CRT code:

    00009C76:  sub ax, 01
    00009C79:  sbb dx, 00
    00009C7C:  jb  00009C83
    00009C7E:  cmp bl, es:[di]
    00009C81:  je  00009C76
    00009C83:  ret

In first two lines it subtracts 1 from DX:AX. Then if DX:AX<0 loop is ended.
Else if BL (where timer counter at start was stored) is not equal to ES:[DI]
(which is pointing to 40:6C - timer counter) loop is ended. I've changed it
to:

    00009C76:  dec ax
    00009C77:  mov cx, _DELAY_
    00009C7A:  loop 00009C7A
    00009C7C:  je 00009C83
    00009C7E:  cmp bl, es:[di]
    00009C81:  je 00009C76
    00009C83:  ret

It subtracts 1 from AX. Then it makes empty loop _DELAY_ times. Then if AX=0
it returns back. Then it does all the stuff. But it uses CX, so I had to
change Delay() code a bit. From:

    00009C6C:  xor dx, dx
    00009C6E:  call 00009C76

to

    00009C6C: push cx
    00009C6D: call 00009C76
    00009C70: pop cx

So one pass of Delay() main loop became longer and number of passes can fit
in AX. Delay() now works perfectly (and precise - unlike after TPPATCH)! Also
we now have parameter _DELAY_ which can increase precision of Delay() (small
values) or make it possible to run Delay() on fast machines (big values),
but whatever you choose programm will never cause run-time error 200 again.
On my Pentium II-300 I use values 40-45, but I recommend to use autodetect
(at least once :).

3. HOW TO USE IT?
    In a command line you should specify mask of files to be patched.
It can be ANY executable or unit (*.TPU, *.TPL) made with BP/TP. Mask can
also include path (e.g.: mask 'c:\utils\*.exe' specify all EXE files in
directory 'c:\utils'). If file mask in incomplete it'll be extended with
'*.exe'. You can also specify one of the following parameter (after or
before file mask):

    /d## - set delay factor (_DELAY_) to ## or enable auto-detect
           if 0 is specified.
    /t   - test mode. Only search for CRT code in files but don not
           patch. All other options (except log) are ignored.
    /b   - backup files before patching.
    /a   - ask before patching. You can choose: 'Yes' - patch this file,
           'No' - don't patch this file, 'Quit' - exit programm or
           'Backup' - back up this file, if you don't use /b parameter.
    /l   - write log file. In log file you can find names of all processed
           files (unless /p is specified), position of patched code in file
           and file status (PATCHED, BACKUPED).
    /p   - write to log only files containing CRT code. Can be used do
           make list of patched files, or files that need patching.
    /r   - recursive search. Search in all subdirectories of searching path
           (current directory or directory given in file mask).
    /h,/?- display help. 

    After finishing CrtFix shows statistic: number of processed files, files
containing CRT code, patched files and I/O errors. If you want to know WHAT
files it has fixed you can use /b (because it backups only patched files) or
/l parameters.
    CrtFix has a trick to prevent self patching so you can run it with mask
*.EXE without a fear. CrtFix checks files carefuly before patching them so no
file would be spoiled (I hope so :). Of course, packed files should be unpacked
first (look for UNP of cup386 if you have problems).
    CrtFix can be reapplied (for example, to change delay factor) and
applied after TPPATCH (and before ;).
   And that's all folks! Have a nice day.

4. HISTORY
Changes to version 1.10
+ /a parameter added - ask before patching
+ /l parameter added - write log file
+ /p parameter added - write to log only files, containing CRT code
+ /r parameter added - recursive search
+ /t parameter added - test mode
+ File mask can now include path
+ File mask extension added
+ Added I/O errors and "code found" statistic
+ Now can open readonly files (preserving R/O attribute)
+ Strict parameters checking
+ Fixed search bug (CRTFix didn't find code in some (rare ;) cases)
+ Some minor changes and bugfixes

Version 1.0 - first release

NOTE: I'm not responsible for any results of using CrtFix. You use it on
      your own risk. There is no warranty for this software.

      CrtFix executable and source code is public domain. Feel free to use
      or modify it as you wish. If you use or modify it in an interresting
      way, please tell me. I'll be glad if you send me your notes (and bug
      reports :) to eltoder@hotmail.com.

P.S.: This CrtFix doesn't use CRT at all.