Sie sind auf Seite 1von 9

--------------------------------------------------------------------------D E L P H I D O E S D O S --------------------------------------------------------------------------Revisions Mar 1995: Original document created Apr 1995: Corrections (-ERRC); Additions (SYSUTILS, CLASSES) Sep

1995: Updates, Additions (TYPINFO, DELPHIPM.EXE, Debugging) --------------------------------------------------------------------------Outline I. II. III. IV. V. VI. VII. VIII. IX. TURBO.TPL, DOS real mode system library TPP.TPL, DOS protected mode system library SYSUTILS, getting it to compile CLASSES, getting it to compile TYPINFO, converting TYPINFO.DCU to TYPINFO.TPP DELPHIPM, Delphi IDE creates DOS protected mode programs Debugging, Turbo Debugger 4.6 w/TDXDEBUG.DLL Notes Disclaimer

--------------------------------------------------------------------------Instructions for preparing DELPHI to compile a DOS EXE with DCC.EXE Requirements: 1) BP7 Runtime library source 2) Delphi VCL source 3) TASM.EXE 4) The new DLIB.EXE (15616 bytes) (available from CompuServe DELPHI forum) 5) Common sense Assumptions: 1) BP7 RTL is in \BP\RTL 2) Delphi VCL is in \DELPHI\SOURCE 3) \DELPHI\BIN is in your path as well as TASM.EXE 4) You can at least read ASM code Copy from \BP\RTL\SYS to \DELPHI\SOURCE\RTL\SYS (all are .ASM): MAIN, PARS, LAST, HEAP, F87H, EI87, EI86, DLIB, DAPP (* note ERRC that was in the original list has been removed - it should not be copied over or exception handling will not work !!!!! *) --------------------------------------------------------------------------I. DOS Real Mode -----------------------------------------------------------------------------------------------------------------------------------Objective: create a TURBO.TPL with units compiled under DELPHI 1) The first and main requirement is to get a SYSTEM.TPU for DOS mode. This will take some work because Delphi VCL source does not include MAIN.ASM which is required for compiling SYSTEM.PAS in DOS mode. Some things need to be removed from MAIN.ASM because they now exist in EXIT.ASM: - remove HaltTurbo, HaltError, Terminate, PrintString from the PUBLIC section. - remove the procedure code for the above procedures. (HaltError starts in around line 210 or so and HaltTurbo starts around 230 or so. PrintString ends around 395 +/- a few.) - up at the top in Externals after "ASSUME CS:CODE,DS:DATA" add another "EXTRN HaltError:NEAR,HaltTurbo:NEAR"

- down in "Int3FHandler" remove "SHORT" from "JMP SHORT HaltError" - after "MOV AX,200" in Int00Handler add "JMP HaltError" - after "MOV AX,255" in Int23Handler add "JMP HaltTurbo" 2) Create OBJ from ASM: In \DELPHI\SOURCE\RTL\SYS type TASM *.ASM 3) Compile SYSTEM: In \DELPHI\SOURCE\RTL\SYS type DCC -cd -$d- -o\BP\RTL\LIB SYSTEM 4) Start your TURBO.TPL: In \DELPHI\BIN type DLIB TURBO.TPL +..\SOURCE\RTL\SYS\SYSTEM.TPU Other files you may want to compile and include in TURBO.TPL: unit source can be found OVERLAY \BP\RTL\OVR CRT \BP\RTL\CRT DOS \BP\RTL\DOS (need to use TASM again) PRINTER \BP\RTL\PRT STRINGS \DELPHI\SOURCE\RTL70 (optional) MEMORY \BP\RTL\TV (optional) OBJECTS \BP\RTL\COMMON (optional) Compile the above files in the specified directory using DCC with the parameters -cd and -$d- to create "ver 8.0" .TPU files. Then add the TPU files to TURBO.TPL as shown in step 4. Now you're all set! Use DCC with the "undocumented" -cd switch to create DOS EXEs with classes, exception handling, etc. Note: Run-Time errors are converted to exceptions only if you include SysUtils in you program. SysUtils does not compile in DOS real mode. See section III. for info on compiling SysUtils in DPMI. --------------------------------------------------------------------------II. DOS Protected Mode (DPMI) ----------------------------------------------------------------------------------------------------------------------Objective: create a TPP.TPL with units compiled under DELPHI 1) Complete step 1 above. Make sure the .OBJ files still exist from step 2 above. 2) Create OBP from ASM: In \DELPHI\SOURCE\RTL\SYS type TASM -op -d_DPMI_ *.ASM *.OBP 3) Compile SYSTEM: In \DELPHI\SOURCE\RTL\SYS type DCC -cp -$d- -o\BP\RTL\LIB SYSTEM 4) Start your TURBO.TPL: In \DELPHI\BIN type DLIB TPP.TPL +..\SOURCE\RTL\SYS\SYSTEM.TPP Other files unit CRT DOS PRINTER STRINGS WINDOS WINAPI MEMORY you may want to compile and include in TPP.TPL: source can be found \BP\RTL\CRT \BP\RTL\DOS (TASM -op -d_DPMI_ *.ASM *.OBP) \BP\RTL\PRT \DELPHI\SOURCE\RTL70 \DELPHI\SOURCE\RTL70 \DELPHI\SOURCE\RTL\WIN \BP\RTL\TV (optional)

OBJECTS \BP\RTL\COMMON (optional) SYSUTILS \DELPHI\SOURCE\RTL\SYS (new, see below) CLASSES \DELPHI\SOURCE\VCL Compile the above files in the specified directory using DCC with the parameters -cp and -$d- to create "ver 8.0" .TPP files. Then add the TPP files to TPP.TPL as shown in step 4. --------------------------------------------------------------------------III. SysUtils for DOS Protected Mode ---------------------------------------------------------------------------------------------------------------***** ***** I suggest creating the directory \DELPHI\SOURCE\DOS for all the ***** following work on SYSUTILS, TYPINFO, CLASSES, etc. ***** To get SYSUTILS to work properly in DOS PM you need to make a few minor changes to the source file (comes with VCL Source). First make a backup of the SYSUTILS.PAS file and then I suggest puting "{$IFDEF WINDOWS}..." around all of your changes. 1) FileRead/FileWrite: RTM.EXE only supports _lread/write not _hread/write and SysUtils needs to be updated to reflect that. I will use FileRead as the example: In INTERFACE {$IFDEF WINDOWS} function FileRead(Handle: Integer; var Buffer; Count: Longint): Longint; {$ELSE} function FileRead(Handle: Integer; var Buffer; Count: Word): Word; {$ENDIF} In IMPLEMENTATION function FileRead(Handle: Integer; var Buffer; Count: Word): Word; external 'KERNEL' index 82; { _lread } FileWrite needs the same changes and it has an external index of 86. 2) Units used in the IMPLEMENTATION section: {$IFDEF WINDOWS} uses WinTypes, WinProcs, ToolHelp; {$ELSE} uses WinAPI; {$ENDIF} 3) Remove some exception (hardware, etc) handling. Unfortunately RTM does not support MakeProcInstance and FreeProcInstance otherwise none of the following would have to be removed. A) in the INTERFACE section {$IFDEF WINDOWS} procedure EnableExceptionHandler(Enable: Boolean); {$ENDIF} B) Around the procedure "GetModNameAndLogAddr" in the IMPLEMENTATION section add {$IFDEF WINDOWS} and {$ENDIF}. C) In the procedure "ShowException": var .. existing definitions Buffer: array[0..255] of Char; {$IFDEF WINDOWS} GlobalEntry: TGlobalEntry;

hMod: THandle; {$ENDIF} begin {$IFDEF WINDOWS} .. existing code {$ENDIF} end; D) Before the procedure "ErrorHandler": {$IFDEF WINDOWS} const Flags = $10; .. other consts Recurse: Word = 0; {$ENDIF} In the procedure "ErrorHandler": 1: E := OutOfMemory; {$IFDEF WINDOWS} 2,4..10: with ExceptMap[ErrorCode] do E := EClass.CreateRes(EIdent); 3,11..16: .. end; {$ELSE} 2..16: with ExceptMap[ErrorCode] do E := EClass.CreateRes(EIdent); {$ENDIF} else Before the procedure "InterruptCallBack" add {$IFDEF WINDOWS} and after the end of the procedure "EnableExceptionHandler" add {$ENDIF}. In procedure "DoneExceptions" put IFDEF WINDOWS around the call to EnableExceptionHandler. In procedure "InitExceptions" put IFDEF WINDOWS around the assignment "TaskID := GetCurrentTask;" and the call to EnableExceptionHandler.

E)

F) G) H)

4) Add profile support provided in RTM.EXE. After the comment "{ Initialization file support }" add the following: {$IFNDEF WINDOWS} function GetProfileInt( appName, keyName : pchar; default : integer ) : word; far; external 'KERNEL' index 57; function GetProfileString( appName, keyName, default, returned : pchar; size : integer ) : integer; far; external 'KERNEL' index 58; {$ENDIF} Compile SYSUTILS for DOS PM from the command line: DCC -cp -$d- -r\DELPHI\LIB SYSUTILS It is all set to add the TPP.TPL and use in your programs. I have not been able to test every function that is provided. It would be diffucult to get SysUtils working for DOS Real Mode because of its use of resource files, although I am sure it is possible if someone would like to give it a shot. You could probably remove all the exception handling and get it to compile with BP7. --------------------------------------------------------------------------IV. Classes for DOS Protected Mode -----------------------------------------------------------------------------------------------------------------Getting the CLASSES unit to compile for DOS PM is very simple compared to SYSUTILS.

In the INTERFACE section change the uses clause: {$IFDEF WINDOWS} uses SysUtils, WinTypes, WinProcs; {$ELSE} uses SysUtils, WinAPI; {$ENDIF} You need to create a unit called CONSTS that has the following: (This information was obtained via the online browser because Borland does not proved CONSTS.PAS - don't ask me why not): ======================================== unit Consts; {$R CONSTS.RES} interface const SAssignError SFCreateError SFOpenError SReadError SWriteError SMemoryStreamError SClassNotFound SInvalidImage SResNotFound SListIndexError SSortedListError SDuplicateString SDuplicateName SInvalidName SDuplicateClass SLineTooLong SInvalidPropertyValue SInvalidPropertyPath SUnknownProperty SReadOnlyProperty SPropertyException SRegisterError SParseError SIdentifierExpected SStringExpected SNumberExpected SCharExpected SSymbolExpected SInvalidString SInvalidProperty SInvalidBinary implementation end. ======================================== Now copy TYPINFO.INT to TYPINFO.PAS and copy the procedure/function declarations from the INTERFACE to IMPLEMENTATION. With each procedure and function add a "Begin End;". Have each function return NIL, 0, etc depending on its type. = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 61440; 61441; 61442; 61443; 61444; 61445; 61447; 61448; 61449; 61451; 61452; 61453; 61455; 61456; 61457; 61459; 61460; 61461; 61462; 61463; 61464; 61498; 61530; 61531; 61532; 61533; 61534; 61535; 61537; 61538; 61539;

Compile: DCC -cp -$d- -r\DELPHI\LIB CLASSES You can now use TList, TStrings, TStringList, TStream, etc in your DOS PM programs. Because of changes to SysUtils THandleStream.Read/Write is limited to a buffer size of word and not longint. You won't be able to use TReader and TWriter unless you can get Borland to give you the source or TPP for TYPINFO.PAS (or follow step V. below). --------------------------------------------------------------------------V. TypInfo for DOS Protected Mode ------------------------------------------------------------------------------------------------------------------With a little work you can convert the TYPINFO.DCU binary into a TYPINFO.TPP file for Delphi. - You must change a flag in the header indicating it is a DPMI unit. - You must change the ID stamps after each uses unit to match their corresponding unit's IDs. The reason you would want this is to enable object persistance. This will allow you to save objects that have published properties to a stream (and load from stream). See TStream.ReadComponent/WriteComponent. Note: I found this information out accidentally when I noticed that the .DCU and .TPP files for the same source unit were the same size. (The source units contained no IFDEFs based on compile mode.) I did a binary file compare on them and the only difference was the byte at offset 2F (12 for DCU and 11 for TPP). Assumptions: - TYPINFO.DCU 5936 02/15/95 08:00:00am 1) Take the TYPINFO.TPP that was created in step IV (Classes) and rename it to TYPINFO.OLD. 2) TDUMP TYPINFO.OLD to a file and print the first page. 3) Copy TYPINFO.DCU from \DELPHI\LIB to the current directory (I assume \DELPHI\SOURCE\DOS) as TYPINFO.TPP. 4) Load TYPINFO.TPP (the new one) into a hex file editor (NU's DISKEDIT for example). 5) Change the byte at offset 2F from 12 (Windows) to 11 (DPMI). 6) Here is the tricky part. - Notice the table of units that starts around offset E5. You should see TypInfo, System, Classes, and SysUtils. - Each unit name is followed by two null bytes and then two bytes that make up some sort of ID. - In the .TPP file that is a copy of the .DCU file these ID bytes should probably be as follows: TypInfo, 60 44; System, 34 0E; Classes, F5 D8; and SysUtils, 40 FC. - Now compare those to the bytes in the same positions in the TYPINFO.OLD file dump that you printed. - What you need to do is modify the bytes in the .TPP file that you have open and make them the same as the bytes in the .OLD file that you compiled. - I do not know if this is true in all cases but the new numbers on my system are as follows: TypInfo, DE 65; System, 49 12;

Classes, 82 ED; and SysUtils, FA B5. The number might be different in your case (?). (you should probably rename your TYPINFO.PAS now so that it doesn't end up getting recompiled in the future) 7) Recompile CLASSES.PAS Note: I have not done much testing in this area. In theory if you have TypInfo then you should be able to have persistent classes (with some work) using TReader and TWriter, etc. "Published" properties are what is stored (as well as properties defined in the "DefineProperties" method) when using persistent classes (anything descendent from TPersistent, such as TStrings & TComponent). --------------------------------------------------------------------------VI. Creating an IDE that generates TPP units and DOS DPMI EXEs!!!!!!!!!!!!! --------------------------------------------------------------------------After you have your TPP.TPL in the DELPHI\BIN directory you can actually get the Delphi IDE to recognize it and create DOS programs. You have to do it with a separate copy of DELPHI.EXE because it needs modification. Assumptions: - DELPHI.EXE 1188864 04/25/95 08:00:00am - You have successfully created TPP.TPL 1) Copy DELPHI.EXE to DELPHIPM.EXE. When you run DELPHIPM.EXE it will generate its own DELPHIPM.INI file in the Windows directory so you don't have to worry about the changes (such as eliminating COMPLIB.DCL) you make affecting the normal Delphi Windows IDE. If you are going to want online help you will also need to copy DELPHI.HDX to DELPHIPM.HDX and DELPHI.HLP to DELPHIPM.HLP. 2) Make DelphiPM read TPP.TPL: - Load DELPHIPM.EXE into a hex file editor (such an NU's DISKEDIT.EXE) - Goto offset 0392AD. You should see "[0A]DELPHI.DSL" - Change the bytes starting at 0392AD to 07 54 50 50 2E 54 50 4C 00 00 00 ([07]TPP.TPL[00][00][00]) - Goto offset 063C6F. You should see: 89 26 24 2C 26 C7 05 04 00 8A 46 0C This instruction (26C7050400) is where Delphi loads the flag determining which mode to compile in. (0004=Windows,0002=DPMI) (don't ask how I found it... it was one of those 3 hour midnight debugging projects) - Change offset 063C76 to 02. - Save your work. 3) Go into Windows and try it out (Don't forget to execute DELPHIPM and not DELPHI). It is really nice to be able to use features such as syntax highlighting, object browser, search for error address, project manager, etc. while working on DOS programs. You can compile your programs with Ctrl-F9. If you uncheck "Integrated Debugging" in the Environment options you can pressing F9 to run the program. ** In theory I suppose you could have the IDE compile DOS real mode programs by changing DELPHI.DSL to TURBO.TPL and the 04 byte to 01 but I have not tried this.

--------------------------------------------------------------------------VII. Debugging Delphi DOS Programs -----------------------------------------------------------------------------------------------------------------Sorry, no integrated debugging (yet?). But you can use Turbo Debugger 4.6 (TD.EXE) (maybe even 4.0 or 4.5, I don't know. I do know that 3.x give an "invalid linker" error) to debug your DELPHI DOS DPMI programs! Make sure you have TDXDEBUG.DLL (It should be in you \BP\BIN) because it was not included on my C++ CD-ROM. Add TD.EXE to your DELPHIPM's Tools menu by using "Options->Tools". Set the parameters to be: $EXENAME $PARAMS $TDW $SAVEALL. This will cause Delphi to recompile the project with external debug info before executing TD.EXE. --------------------------------------------------------------------------VIII. Notes ----------------------------------------------------------------------------------------------------------------------------------------1) Data Types, some of which are undocumented Name Size -------- ---ShortInt 8 *SmallInt 16 (stays 16 in 32bit-compiler) Integer 16 (32 in 32bit-compiler) LongInt 32 Byte 8 Word 16 *Cardinal 16 (32 in 32bit-compiler) Boolean 8 *Bool 16 (? in 32bit-compiler) *ByteBool 8 *WordBool 16 *LongBool 32 If we could only get Borland to give us LongWord(32), HugeInt(64), and HugeWord(64)! 2) How to convert a .DFM to text (does what CONVERT.EXE does): var xxx : TStream; yyy : TStream; begin xxx := nil; yyy := nil; try try xxx := TFileStream.Create( ParamStr(1), fmOpenRead ); yyy := TFileStream.Create( 'OUTPUT.TXT', fmCreate ); except WriteLn( 'Failed creating OUTPUT.TXT' ); exit; end; ObjectResourceToText( xxx, yyy ); finally xxx.Free; yyy.Free; end;

end; --------------------------------------------------------------------------IX. Disclaimer -------------------------------------------------------------------------------------------------------------------------------------Use at your own risk. I don't make any claims about the EXEs created as this is not official from Borland. (I hate to scare anyone off though, I have not experience any problems.) Kevin R. Smith 73632.712@compuserve.com

Das könnte Ihnen auch gefallen