source410: literal 4.10 source reconstruction + BC++ 4.52 fleet toolchain archived

- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
  is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
  Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
  (extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
  BT game source (never mixed into CODE/). Round 1-3 state:
  * 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
    (BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
    since 1996.
  * BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
    its binary-recorded line 400 exactly.
  * BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
    (Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
    TeamScore=12 flagged [T4]).
  * MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
    (VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
    the period compiler is the drift detector).
  * Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
    (per-TU verification sweep under authentic OPT.MAK flags).
  * README: corrected roadmap - MECH.HPP is the capstone grown with the mech
    TU reconstructions; BTREG.CPP green = the header-family milestone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-19 07:33:26 -05:00
co-authored by Claude Fable 5
parent 599b2388a1
commit 63312e07f9
5913 changed files with 756089 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
@echo off
if not "%TASM%"=="" goto skip
set tasm=tasm
:skip
if not %3.==. goto noobjdir
set objdir=.
goto objdirset
:noobjdir
set objdir=%3
:objdirset
if not %2.==. goto noc0dir
set c0dir=.
goto c0dirset
:noc0dir
set c0dir=%2
:c0dirset
if %1.==clib. goto clib
if %1.==winlib. goto winlib
if %1.==dpmi16. goto dpmi16
goto error
:clib
echo Building DOS startups
cd %c0dir%
%TASM% /M /MX /Q /T /D__TINY__ c0, %objdir%\c0t
%TASM% /M /MX /Q /T /D__SMALL__ c0, %objdir%\c0s
%TASM% /M /MX /Q /T /D__COMPACT__ c0, %objdir%\c0c
%TASM% /M /MX /Q /T /D__MEDIUM__ c0, %objdir%\c0m
%TASM% /M /MX /Q /T /D__LARGE__ c0, %objdir%\c0l
%TASM% /M /MX /Q /T /D__HUGE__ c0, %objdir%\c0h
%TASM% /M /MX /Q /T /D__TINY__ /D_DSSTACK_ c0, %objdir%\c0ft
%TASM% /M /MX /Q /T /D__SMALL__ /D_DSSTACK_ c0, %objdir%\c0fs
%TASM% /M /MX /Q /T /D__COMPACT__ /D_DSSTACK_ c0, %objdir%\c0fc
%TASM% /M /MX /Q /T /D__MEDIUM__ /D_DSSTACK_ c0, %objdir%\c0fm
%TASM% /M /MX /Q /T /D__LARGE__ /D_DSSTACK_ c0, %objdir%\c0fl
%TASM% /M /MX /Q /T /D__HUGE__ c0, %objdir%\c0fh
if not %c0dir%==. cd ..
goto exit
:winlib
echo Building Windows startups
cd %c0dir%
%TASM% /M /MX /Q /T /D__SMALL__ /D__WINDOWS__ c0w, %objdir%\c0ws
%TASM% /M /MX /Q /T /D__COMPACT__ /D__WINDOWS__ c0w, %objdir%\c0wc
%TASM% /M /MX /Q /T /D__MEDIUM__ /D__WINDOWS__ c0w, %objdir%\c0wm
%TASM% /M /MX /Q /T /D__LARGE__ /D__WINDOWS__ c0w, %objdir%\c0wl
%TASM% /M /MX /Q /T /D__SMALL__ /D__WINDOWS__ c0d, %objdir%\c0ds
%TASM% /M /MX /Q /T /D__COMPACT__ /D__WINDOWS__ c0d, %objdir%\c0dc
%TASM% /M /MX /Q /T /D__MEDIUM__ /D__WINDOWS__ c0d, %objdir%\c0dm
%TASM% /M /MX /Q /T /D__LARGE__ /D__WINDOWS__ c0d, %objdir%\c0dl
if not %c0dir%==. cd ..
goto exit
:dpmi16
echo Building DPMI16 startup
cd %c0dir%
%TASM% /M /MX /Q /T /D__LARGE__ /D__WINDOWS__ /D__DPMI16__ c0w, %objdir%\c0x
if not %c0dir%==. cd ..
goto exit
:error
echo BUILD-C0.BAT
echo Usage: build-c0 libtype [srcdir [objdir]]
echo libtype clib (DOS) or winlib (Windows) or dpmi16 (DPMI16)
echo srcdir source subdirectory (default is ".")
echo objdir object subdirectory relative to srcdir (default is ".")
echo Example: build-c0 clib startup ..\lib
echo This batch file builds the C startup module (or modules) for
echo DOS or Windows. All memory models are built.
:exit
+745
View File
@@ -0,0 +1,745 @@
;[]------------------------------------------------------------[]
;| C0.ASM -- Start Up Code for DOS |
;[]------------------------------------------------------------[]
;
; C/C++ Run Time Library - Version 6.5
;
; Copyright (c) 1987, 1994 by Borland International
; All Rights Reserved.
;
locals
__C0__ = 1
INCLUDE RULES.ASI
; Segment and Group declarations
_TEXT SEGMENT BYTE PUBLIC 'CODE'
ENDS
_FARDATA SEGMENT PARA PUBLIC 'FAR_DATA'
ENDS
_FARBSS SEGMENT PARA PUBLIC 'FAR_BSS'
ENDS
IFNDEF __TINY__
_OVERLAY_ SEGMENT PARA PUBLIC 'OVRINFO'
ENDS
_1STUB_ SEGMENT PARA PUBLIC 'STUBSEG'
ENDS
ENDIF
_DATA SEGMENT PARA PUBLIC 'DATA'
ENDS
_INIT_ SEGMENT WORD PUBLIC 'INITDATA'
InitStart label byte
ENDS
_INITEND_ SEGMENT BYTE PUBLIC 'INITDATA'
InitEnd label byte
ENDS
_EXIT_ SEGMENT WORD PUBLIC 'EXITDATA'
ExitStart label byte
ENDS
_EXITEND_ SEGMENT BYTE PUBLIC 'EXITDATA'
ExitEnd label byte
ENDS
_CVTSEG SEGMENT WORD PUBLIC 'DATA'
ENDS
_SCNSEG SEGMENT WORD PUBLIC 'DATA'
ENDS
IFNDEF __HUGE__
_BSS SEGMENT WORD PUBLIC 'BSS'
ENDS
_BSSEND SEGMENT BYTE PUBLIC 'BSSEND'
ENDS
ENDIF
IFNDEF __TINY__
_STACK SEGMENT STACK 'STACK'
ENDS
ENDIF
ASSUME CS:_TEXT, DS:DGROUP
; External References
extrn _main:DIST
extrn _exit:DIST
extrn __exit:DIST
extrn __abort:DIST
extrn ___ErrorMessage:DIST
extrn __nfile:word
extrn __setupio:near ;required!
extrn __stklen:word
IFNDEF __TINY__
extrn __ExceptInit:DIST
ENDIF
IF LDATA EQ false
extrn __heaplen:word
ENDIF
SUBTTL Start Up Code
PAGE
;/* */
;/*-----------------------------------------------------*/
;/* */
;/* Start Up Code */
;/* ------------- */
;/* */
;/*-----------------------------------------------------*/
;/* */
PSPHigh equ 00002h
PSPEnv equ 0002ch
PSPCmd equ 00080h
public __AHINCR
public __AHSHIFT
__AHINCR equ 1000h
__AHSHIFT equ 12
IFDEF __NOFLOAT__
MINSTACK equ 128 ; minimal stack size in words
ELSE
MINSTACK equ 256 ; minimal stack size in words
ENDIF
;
; At the start, DS and ES both point to the segment prefix.
; SS points to the stack segment except in TINY model where
; SS is equal to CS
;
_TEXT SEGMENT
IFDEF __TINY__
ORG 100h
ENDIF
STARTX PROC NEAR
; Save general information, such as :
; DGROUP segment address
; DOS version number
; Program Segment Prefix address
; Environment address
; Top of far heap
IFDEF __TINY__
mov dx, cs ; DX = GROUP Segment address
ELSE
mov dx, DGROUP ; DX = GROUP Segment address
ENDIF
mov cs:DGROUP@@, dx ;
mov ah, 30h
int 21h ; get DOS version number
mov bp, ds:[PSPHigh]; BP = Highest Memory Segment Addr
mov bx, ds:[PSPEnv] ; BX = Environment Segment address
mov ds, dx
mov _version@, ax ; Keep major and minor version number
mov _psp@, es ; Keep Program Segment Prefix address
mov _envseg@, bx ; Keep Environment Segment address
mov word ptr _heaptop@ + 2, bp
;
; Save several vectors and install default divide by zero handler.
;
call SaveVectors
; Count the number of environment variables and compute the size.
; Each variable is ended by a 0 and a zero-length variable stops
; the environment. The environment can NOT be greater than 32k.
mov ax, _envseg@
mov es, ax
xor ax, ax
mov bx, ax
mov di, ax
mov cx, 07FFFh ; Environment cannot be > 32 Kbytes
cld
@@EnvLoop:
repnz scasb
jcxz InitFailed ; Bad environment !!!
inc bx ; BX = Nb environment variables
cmp es:[di], al
jne @@EnvLoop ; Next variable ...
or ch, 10000000b
neg cx
mov _envLng@, cx ; Save Environment size
mov cx, dPtrSize / 2
shl bx, cl
add bx, dPtrSize * 4
and bx, not ((dPtrSize * 4) - 1)
mov _envSize@, bx ; Save Environment Variables Nb.
; Determine the amount of memory that we need to keep
IFDEF _DSSTACK_
mov dx, ds
ELSE
mov dx, ss
ENDIF
sub bp, dx ; BP = remaining size in paragraphs
IF LDATA
mov di, seg __stklen
mov es, di
mov di, es:__stklen ; DI = Requested stack size
ELSE
mov di, __stklen ; DI = Requested stack size
ENDIF
;
; Make sure that the requested stack size is at least MINSTACK words.
;
cmp di, 2*MINSTACK ; requested stack big enough ?
jae AskedStackOK
mov di, 2*MINSTACK ; no --> use minimal value
IF LDATA
mov es:__stklen, di ; override requested stack size
ELSE
mov __stklen, di ; override requested stack size
ENDIF
AskedStackOK label near
IFDEF _DSSTACK_
add di, offset DGROUP: edata@
jb InitFailed ; DATA segment can NOT be > 64 Kbytes
ENDIF
IF LDATA EQ false
add di, __heaplen
jb InitFailed ; DATA segment can NOT be > 64 Kbytes
ENDIF
mov cl, 4
shr di, cl ; $$$ Do not destroy CL $$$
inc di ; DI = DS size in paragraphs
cmp bp, di
IF LDATA EQ false
jb InitFailed ; Not enough memory
cmp __stklen, 0
je ExpandDS ; Expand DS up to 64 Kb
cmp __heaplen, 0
jne ExcessOfMemory ; Much more available than needed
ExpandDS label near
mov di, 1000h
cmp bp, di
ja ExcessOfMemory ; Enough to run the program
mov di, bp
jmp short ExcessOfMemory ; Enough to run the program
ELSE
jnb ExcessOfMemory ; Much more available than needed
ENDIF
; All initialization errors arrive here
InitFailed label near
call __abort
; Return to DOS the amount of memory in excess
; Set far heap base and pointer
ExcessOfMemory label near
mov bx, di
add bx, dx
mov word ptr _heapbase@ + 2, bx
mov word ptr _brklvl@ + 2, bx
mov ax, _psp@
sub bx, ax ; BX = Number of paragraphs to keep
mov es, ax ; ES = Program Segment Prefix address
mov ah, 04Ah
push di ; preserve DI
int 021h ; this call clobbers SI,DI,BP !!!!!!
pop di ; restore DI
shl di, cl ; $$$ CX is still equal to 4 $$$
cli ; req'd for pre-1983 88/86s
mov ss, dx ; Set the program stack
mov sp, di
sti
IFNDEF _DSSTACK_
mov ax, seg __stklen
mov es, ax
mov es:__stklen, di ; If separate stack segment, save size
ENDIF
IFNDEF __HUGE__
; Reset uninitialized data area
xor ax, ax
mov es, cs:DGROUP@@
mov di, offset DGROUP: bdata@
mov cx, offset DGROUP: edata@
sub cx, di
cld
rep stosb
ENDIF
; If default number of file handles have changed then tell DOS
cmp __nfile, 20
jbe @@NoChange
cmp _osmajor@, 3 ; Check for >= DOS 3.3
jb @@NoChange
ja @@DoChange
cmp _osminor@, 1Eh
jb @@NoChange
@@DoChange:
mov ax, 5801h ; Set last fit allocation
mov bx, 2
int 21h
jc @@BadInit
mov ah, 67h ; Expand handle table
mov bx, __nfile
int 21h
jc @@BadInit
mov ah, 48h ; Allocate 16 bytes to find new
mov bx, 1 ; top of memory address
int 21h
jc @@BadInit
inc ax ; Adjust address to point after block
mov word ptr _heaptop@ + 2, ax
dec ax ; Change back and release block
mov es, ax
mov ah, 49h
int 21h
jc @@BadInit
mov ax, 5801h ; Set first fit allocation
mov bx, 0
int 21h
jnc @@NoChange
@@BadInit: call __abort
@@NoChange:
; Prepare main arguments
xor bp,bp ; set BP to 0 for overlay mgr
IFNDEF __TINY__
push bp
call __ExceptInit
pop ax
ENDIF
mov es, cs:DGROUP@@
mov si,offset DGROUP:InitStart ;si = start of table
mov di,offset DGROUP:InitEnd ;di = end of table
call Initialize
; ExitCode = main(argc,argv,envp);
IF LDATA
push word ptr __C0environ+2
push word ptr __C0environ
push word ptr __C0argv+2
push word ptr __C0argv
ELSE
push word ptr __C0environ
push word ptr __C0argv
ENDIF
push __C0argc
call _main
; Flush and close streams and files
push ax
call _exit
;---------------------------------------------------------------------------
; _cleanup() call all #pragma exit cleanup routines.
; _checknull() check for null pointer zapping copyright message
; _terminate(int) exit program with error code
;
; These functions are called by exit(), _exit(), _cexit(),
; and _c_exit().
;---------------------------------------------------------------------------
; Call cleanup routines
__cleanup PROC DIST
PUBLIC __cleanup
mov es, cs:DGROUP@@
push si
push di
mov si,offset DGROUP:ExitStart
mov di,offset DGROUP:ExitEnd
call Cleanup
pop di
pop si
ret
__cleanup ENDP
; Check for null pointers before exit
__checknull PROC DIST
PUBLIC __checknull
IF LDATA EQ false
IFNDEF __TINY__
push si
push di
mov es, cs:DGROUP@@
xor ax, ax
mov si, ax
mov cx, 16
ComputeChecksum label near
add al, es:[si]
adc ah, 0
inc si
loop ComputeChecksum
sub ax, CheckSum
jz @@SumOK
mov dx, offset DGROUP:NullCheck
pushDS_
push dx
call ___ErrorMessage
pop dx
popDS_
@@SumOK: pop di
pop si
ENDIF
ENDIF
ret
__checknull ENDP
; Exit to DOS
__terminate PROC DIST
PUBLIC __terminate
mov bp,sp
mov ah,4Ch
mov al,[bp+cPtrSize]
int 21h ; Exit to DOS
__terminate ENDP
STARTX ENDP
SUBTTL Vector save/restore & default Zero divide routines
PAGE
;[]------------------------------------------------------------[]
;| |
;| Interrupt Save/Restore routines and default divide by zero |
;| handler. |
;| |
;[]------------------------------------------------------------[]
ZeroDivision PROC FAR
mov dx, offset DGROUP:ZeroDivMSG
pushDS_
push dx
call ___ErrorMessage
pop dx
popDS_
mov ax, 3
push ax
call __exit ; _exit(3);
ZeroDivision ENDP
;--------------------------------------------------------------------------
; savevectors()
;
; Save vectors for 0, 4, 5 & 6 interrupts. This is for extended
; signal()/raise() support as the signal functions can steal these
; vectors during runtime.
;--------------------------------------------------------------------------
SaveVectors PROC NEAR
push ds
; Save INT 0
mov ax, 3500h
int 021h
mov word ptr _Int0Vector@, bx
mov word ptr _Int0Vector@+2, es
; Save INT 4
mov ax, 3504h
int 021h
mov word ptr _Int4Vector@, bx
mov word ptr _Int4Vector@+2, es
; Save INT 5
mov ax, 3505h
int 021h
mov word ptr _Int5Vector@, bx
mov word ptr _Int5Vector@+2, es
; Save INT 6
mov ax, 3506h
int 021h
mov word ptr _Int6Vector@, bx
mov word ptr _Int6Vector@+2, es
;
; Install default divide by zero handler.
;
mov ax, 2500h
mov dx, cs
mov ds, dx
mov dx, offset ZeroDivision
int 21h
pop ds
ret
SaveVectors ENDP
;--------------------------------------------------------------------------
; _restorezero() puts back all the vectors that SaveVectors took.
;
;NOTE : TSRs must BE AWARE that signal() functions which take these
; vectors will be deactivated if the keep() function is executed.
; If a TSR wants to use the signal functions when it is active it
; will have to save/restore these vectors itself when activated and
; deactivated.
;--------------------------------------------------------------------------
__restorezero PROC DIST
PUBLIC __restorezero
IFDEF __HUGE__
push ds
mov ds, cs: DGROUP@@
ENDIF
push ds
mov ax, 2500h
lds dx, _Int0Vector@
int 21h
pop ds
push ds
mov ax, 2504h
lds dx, _Int4Vector@
int 21h
pop ds
push ds
mov ax, 2505h
lds dx, _Int5Vector@
int 21h
pop ds
IFNDEF __HUGE__
push ds
ENDIF
mov ax, 2506h
lds dx, _Int6Vector@
int 21h
pop ds
ret
ENDP
;------------------------------------------------------------------
; Loop through a startup/exit (SE) table,
; calling functions in order of priority.
; ES:SI is assumed to point to the beginning of the SE table
; ES:DI is assumed to point to the end of the SE table
; First 64 priorities are reserved by Borland
;------------------------------------------------------------------
PNEAR EQU 0
PFAR EQU 1
NOTUSED EQU 0ffh
SE STRUC
calltype db ? ; 0=near,1=far,ff=not used
priority db ? ; 0=highest,ff=lowest
addrlow dw ?
addrhigh dw ?
SE ENDS
Initialize proc near
@@Start: mov ax,100h ;start with lowest priority
mov dx,di ;set sentinel to end of table
mov bx,si ;bx = start of table
@@TopOfTable: cmp bx,di ;and the end of the table?
je @@EndOfTable ;yes, exit the loop
cmp es:[bx.calltype],NOTUSED;check the call type
je @@Next
mov cl, es:[bx.priority] ;move priority to CX
xor ch, ch
cmp cx,ax ;check the priority
jae @@Next ;too high? skip
mov ax,cx ;keep priority
mov dx,bx ;keep index in dx
@@Next: add bx,SIZE SE ;bx = next item in table
jmp @@TopOfTable
@@EndOfTable: cmp dx,di ;did we exhaust the table?
je @@Done ;yes, quit
mov bx,dx ;bx = highest priority item
cmp es:[bx.calltype],PNEAR ;is it near or far?
mov es:[bx.calltype],NOTUSED;wipe the call type
push es ;save es
je @@NearCall
@@FarCall: call DWORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@NearCall: call WORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@Done: ret
endp
Cleanup proc near
@@Start: mov ah,0 ;start with highest priority
mov dx,di ;set sentinel to end of table
mov bx,si ;bx = start of table
@@TopOfTable: cmp bx,di ;and the end of the table?
je @@EndOfTable ;yes, exit the loop
cmp es:[bx.calltype],NOTUSED;check the call type
je @@Next
cmp es:[bx.priority],ah ;check the priority
jb @@Next ;too low? skip
mov ah,es:[bx.priority] ;keep priority
mov dx,bx ;keep index in dx
@@Next: add bx,SIZE SE ;bx = next item in table
jmp @@TopOfTable
@@EndOfTable: cmp dx,di ;did we exhaust the table?
je @@Done ;yes, quit
mov bx,dx ;bx = highest priority item
cmp es:[bx.calltype],PNEAR ;is it near or far?
mov es:[bx.calltype],NOTUSED;wipe the call type
push es ;save es
je @@NearCall
@@FarCall: call DWORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@NearCall: call WORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@Done: ret
endp
;------------------------------------------------------------------
; The DGROUP@ variable is used to reload DS with DGROUP
PubSym@ DGROUP@, <dw ?>, __PASCAL__
; __MMODEL is used to determine the memory model or the default
; pointer types at run time.
public __MMODEL
__MMODEL dw MMODEL
_TEXT ENDS
SUBTTL Start Up Data Area
PAGE
;[]------------------------------------------------------------[]
;| Start Up Data Area |
;| |
;| WARNING Do not move any variables in the data |
;| segment unless you're absolutely sure |
;| that it does not matter. |
;[]------------------------------------------------------------[]
_DATA SEGMENT
; Magic symbol used by the debug info to locate the data segment
public DATASEG@
DATASEG@ label byte
; The Check string must NOT be moved or changed without
; changing the null pointer check logic
IFNDEF __TINY__
NULL db 4 dup(0)
CheckStr db 'NULL CHECK'
db 2 dup (0)
db 4 dup (0) ;destructor count
db 2 dup (0) ;exception list
db 4 dup (0) ;exception vptr
db 6 dup (0) ;reserved
ENDIF
CopyRight db 'Borland C++ - Copyright 1994 Borland Intl.',0
IF LDATA EQ false
IFNDEF __TINY__
CheckSum equ 002B9h
NullCheck db 'Null pointer assignment', 13, 10, 0
ENDIF
ENDIF
ZeroDivMSG db 'Divide error', 13, 10, 0
;
; Interrupt vector save areas
;
; Interrupt vectors 0,4,5 & 6 are saved at startup and then restored
; when the program terminates. The signal/raise functions might
; steal these vectors during execution.
;
; Note: These vectors save area must not be altered
; without changing the save/restore logic.
;
PubSym@ _Int0Vector <dd 0>, __CDECL__
PubSym@ _Int4Vector <dd 0>, __CDECL__
PubSym@ _Int5Vector <dd 0>, __CDECL__
PubSym@ _Int6Vector <dd 0>, __CDECL__
;
; Miscellaneous variables
;
PubSym@ _C0argc, <dw 0>, __CDECL__
dPtrPub@ _C0argv, 0, __CDECL__
dPtrPub@ _C0environ, 0, __CDECL__
PubSym@ _envLng, <dw 0>, __CDECL__
PubSym@ _envseg, <dw 0>, __CDECL__
PubSym@ _envSize, <dw 0>, __CDECL__
PubSym@ _psp, <dw 0>, __CDECL__
PubSym@ _version, <label word>, __CDECL__
PubSym@ _osversion, <label word>, __CDECL__
PubSym@ _osmajor, <db 0>, __CDECL__
PubSym@ _osminor, <db 0>, __CDECL__
PubSym@ errno, <dw 0>, __CDECL__
PubSym@ _Exception_list,<dw -1>, __CDECL__
; Memory management variables
IF LDATA EQ false
PubSym@ __heapbase, <dw DGROUP:edata@>, __CDECL__
ENDIF
IFNDEF __HUGE__
PubSym@ __brklvl, <dw DGROUP:edata@>, __CDECL__
ENDIF
PubSym@ _heapbase, <dd 0>, __CDECL__
PubSym@ _brklvl, <dd 0>, __CDECL__
PubSym@ _heaptop, <dd 0>, __CDECL__
; If stack in DS and Large data model then override location of __emu
IFDEF _DSSTACK_
IF LDATA
public __emu
__emu db 044h DUP (0)
db 0CCh DUP (?)
ENDIF
ENDIF
_DATA ENDS
_CVTSEG SEGMENT
PubSym@ _RealCvtVector, <label word>, __CDECL__
ENDS
_SCNSEG SEGMENT
PubSym@ _ScanTodVector, <label word>, __CDECL__
ENDS
IFNDEF __HUGE__
_BSS SEGMENT
bdata@ label byte
ENDS
_BSSEND SEGMENT
edata@ label byte
ENDS
ENDIF
IFNDEF __TINY__
_STACK SEGMENT
db 128 dup(?) ;minimum stack size
ENDS
ENDIF ; __TINY__
END STARTX
+426
View File
@@ -0,0 +1,426 @@
;[]------------------------------------------------------------[]
;| C0D.ASM -- Start Up Code For Windows DLLs |
;[]------------------------------------------------------------[]
;
; C/C++ Run Time Library - Version 6.5
;
; Copyright (c) 1991, 1994 by Borland International
; All Rights Reserved.
;
locals
__C0__ = 1
include RULES.ASI
ASSUME CS:_TEXT, DS:DGROUP
public __acrtused ;satisfy MS for now
__acrtused equ 0
extrn LIBMAIN:far ;the C routine to be called
extrn LOCALINIT:far ;Windows heap init routine
extrn LOCKSEGMENT:far
extrn UNLOCKSEGMENT:far
extrn GETWINFLAGS:far
extrn __WEP:far
extrn __cexit:DIST
ifdef __LARGE__
ifndef _BUILDRTLDLL
extrn FREELIBRARY:far
extrn __LockDLL:DIST
endif
endif
extrn __setupio:near ;required!
public LibEntry ;Entry point for the DLL
publicdll WEP
NULL segment
db 16 dup (0) ;Windows
db 4 dup (0) ;destructor count
db 2 dup (0) ;exception list
db 4 dup (0) ;exception vptr
db 6 dup (0) ;reserved
db 2 dup (0) ;VBX control jump vector
;MUST be at SS:20h
db 2 dup (0) ;reserved
ends
_CVTSEG segment
public __RealCvtVector
__RealCvtVector label word
ends
_SCNSEG segment
public __ScanTodVector
__ScanTodVector label word
ends
_FPSEG segment
public __FPVector
__FPVector dd 0
ends
_DATA segment
public _errno
_errno dw 0
public __protected
__protected dw 0
public __8086
__8086 dw 0
public __8087
__8087 dw 0
public __version
__version label word
public __osversion
__osversion label word
public __osmajor
__osmajor db 0
public __osminor
__osminor db 0
public __osmode ;Used for OS/2 protected mode by MS,
__osmode db 0 ;currently set to 0 under Windows
public __hInstance
__hInstance dw 0
public __WinAllocFlag ;Used by malloc for additional flags
__WinAllocFlag dw 2000h ;to pass to GlobalAlloc (used in DLLs)
;default value is GMEM_SHARE
public __LockWIN87EM ;Used do lock down WIN87EM to avoid
__LockWIN87EM dw 1 ;DLL unload ordering problem
ifdef __LARGE__
ifndef _BUILDRTLDLL
public __LockRTLHandle
__LockRTLHandle dw 0 ;Handle of RTLDLL (locked)
endif
endif
public __abend
__abend label word
_abend dw 1 ;If LibEntry is called gets set to
;normal state (0). If it is 1 then
;exit routines are not performed
;Gets set to 1 if DLL is terminated
;by a call to abort() or _exit().
CopyRight db 'Borland C++ - Copyright 1994 Borland Intl.',0
ends
_TEXT segment
LibEntry proc far
mov __hInstance, di ;save SI and DI
push si
push di ;handle of the module instance
push ds ;library data segment
push cx ;heap size
push es ;command line segment
push si ;command line offset
;if we have some heap then initialize it
jcxz @@Init ;jump if no heap specified
;call the Windows function LocalInit() to set up the heap
;LocalInit((LPSTR)start, WORD cbHeap);
push ds ;Heap segment
xor ax,ax
push ax ;Heap start offset in segment
push cx ;Heap end offset in segment
call LOCALINIT
xchg ax,cx
jcxz @@JmpExit ;quit if it failed
jmp short @@Init
@@JmpExit: jmp @@Exit
@@Init:
IF LDATA EQ false
mov ax,-1
push ax
call LOCKSEGMENT
ENDIF
;Clear _BSS, uninitialized data area
xor ax, ax
push ds
pop es
mov di,offset DGROUP:BeginBSS
mov cx,offset DGROUP:EndBSS
sub cx,di
cld
rep
stosb
;Determine DOS version
mov ah, 30h
int 21h
mov __version, ax ; save minor and major revision
;Determine whether we are in protected mode
call GETWINFLAGS
test ax,1 ; WF_PMODE = 1
jz @@realmode ; Note: GETWINFLAGS returns a long,
; so if WF_PMODE changed it could be
; in the high word.
mov __protected, 8 ; Eight is for convenience.
@@realmode:
;Test for 8087 presence
test ax,0400h ; WF_8087 = 0x0400
jz @@no8087
mov __8087, 1
@@no8087:
and ax,08h+04h+02h ; WF_CPU486|WF_CPU386|WF_CPU286
shr ax,1 ; Convert to 4 or 2 or 1 or 0
test ax,0004h ; Have 4, 486 done
jnz @@NoAdjust
or ax,ax ; Have 0, 8086 done
jz @@NoAdjust
inc ax ; Have 2 or 1, need 3 or 2
@@NoAdjust:
mov __8086,ax ; Set CPU Type
;Call our initialization functions, including C++ static constructors.
mov ax,ds
mov es,ax
mov si,offset DGROUP:InitStart ;si = start of table
mov di,offset DGROUP:InitEnd ;di = end of table
call Initialize
mov _abend, 0 ; Set LibEntry called
;invoke the C routine to do any special initialization
@@Main: call LIBMAIN ;invoke the 'C' routine (result in AX)
or ax, ax
ifdef __LARGE__
ifndef _BUILDRTLDLL
jz @@LibMainRet
push ax
call __LockDLL
mov __LockRTLHandle, ax
pop ax
@@LibMainRet:
endif
endif
mov di, __hInstance ;restore SI and DI
pop si
ret
@@Exit: mov ax, 0 ;set return code
pop si ;remove arguments to LIBMAIN
pop es ; since we didn't call it.
pop cx
pop ds
pop di
pop si ;restore saved SI. DI is restored
ret ; by removing arguments to LIBMAIN
endp
;---------------------------------------------------------------------------
; _cleanup() call all #pragma exit cleanup routines.
; _checknull() check for null pointer zapping copyright message
; _terminate(exitcode, quick) exit program with error code
; _restorezero() restore interrupt vectors
;
; These functions are called by exit(), _exit(), _cexit(),
; and _c_exit().
;---------------------------------------------------------------------------
; Call cleanup routines
__cleanup PROC DIST
PUBLIC __cleanup
mov ax,ds
mov es,ax
push si
push di
mov si,offset DGROUP:ExitStart
mov di,offset DGROUP:ExitEnd
call Cleanup
pop di
pop si
ret
__cleanup ENDP
; Check for null pointers before exit. NO-OP on Windows.
__checknull PROC DIST
PUBLIC __checknull
ret
__checknull ENDP
; Restore grabbed interrupt vectors. NO-OP on Windows.
__restorezero PROC DIST
PUBLIC __restorezero
ret
__restorezero ENDP
; Exit to DOS
;
; Usage: void _terminate(int exitcode, int quick);
__terminate PROC DIST
PUBLIC __terminate
mov bp,sp
mov al,[bp+cPtrSize] ; get exitcode
mov ah,4ch
int 21h
ret
endp
WEP proc windows pascal far nParam:WORD
push si
push di
cmp _abend, 0
jne @@error
push nParam
call __WEP
push ax
call __cexit ; perform cleanup without exiting
@@unlock:
ifdef __LARGE__
ifndef _BUILDRTLDLL
mov ax, __LockRTLHandle
or ax, ax
jz @@RTLNotLocked
push ax
call FreeLibrary
@@RTLNotLocked:
endif
endif
IF LDATA EQ false
mov ax,-1
push ax
call UNLOCKSEGMENT
ENDIF
pop ax
pop di
pop si
ret
@@error:
push 1
jmp @@unlock
endp
; Return default data segment in AX
__GetDGROUP PROC FAR
PUBLIC __GetDGROUP
mov ax, DGROUP
ret
endp
;------------------------------------------------------------------
; Loop through a startup/exit (SE) table,
; calling functions in order of priority.
; ES:SI is assumed to point to the beginning of the SE table
; ES:DI is assumed to point to the end of the SE table
; First 64 priorities are reserved by Borland
;------------------------------------------------------------------
PNEAR EQU 0
PFAR EQU 1
NOTUSED EQU 0ffh
SE STRUC
calltype db ? ; 0=near,1=far,ff=not used
priority db ? ; 0=highest,ff=lowest
addrlow dw ?
addrhigh dw ?
SE ENDS
Initialize proc near
@@Start: mov ax,100h ;start with lowest priority
mov dx,di ;set sentinel to end of table
mov bx,si ;bx = start of table
@@TopOfTable: cmp bx,di ;and the end of the table?
je @@EndOfTable ;yes, exit the loop
cmp es:[bx.calltype],NOTUSED;check the call type
je @@Next
mov cl, es:[bx.priority] ;move priority to CX
xor ch, ch
cmp cx,ax ;check the priority
jae @@Next ;too high? skip
mov ax,cx ;keep priority
mov dx,bx ;keep index in dx
@@Next: add bx,SIZE SE ;bx = next item in table
jmp @@TopOfTable
@@EndOfTable: cmp dx,di ;did we exhaust the table?
je @@Done ;yes, quit
mov bx,dx ;bx = highest priority item
cmp es:[bx.calltype],PNEAR ;is it near or far?
mov es:[bx.calltype],NOTUSED;wipe the call type
push es ;save es
je @@NearCall
@@FarCall: call DWORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@NearCall: call WORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@Done: ret
endp
Cleanup proc near
@@Start: mov ah,0 ;start with highest priority
mov dx,di ;set sentinel to end of table
mov bx,si ;bx = start of table
@@TopOfTable: cmp bx,di ;and the end of the table?
je @@EndOfTable ;yes, exit the loop
cmp es:[bx.calltype],NOTUSED;check the call type
je @@Next
cmp es:[bx.priority],ah ;check the priority
jb @@Next ;too low? skip
mov ah,es:[bx.priority] ;keep priority
mov dx,bx ;keep index in dx
@@Next: add bx,SIZE SE ;bx = next item in table
jmp @@TopOfTable
@@EndOfTable: cmp dx,di ;did we exhaust the table?
je @@Done ;yes, quit
mov bx,dx ;bx = highest priority item
cmp es:[bx.calltype],PNEAR ;is it near or far?
mov es:[bx.calltype],NOTUSED;wipe the call type
push es ;save es
je @@NearCall
@@FarCall: call DWORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@NearCall: call WORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@Done: ret
endp
ends
end LibEntry
+448
View File
@@ -0,0 +1,448 @@
;[]------------------------------------------------------------[]
;| C0W.ASM -- Start Up Code For Windows |
;[]------------------------------------------------------------[]
;
; C/C++ Run Time Library - Version 6.5
;
; Copyright (c) 1991, 1994 by Borland International
; All Rights Reserved.
;
locals
__C0__ = 1
include RULES.ASI
ASSUME CS:_TEXT, DS:DGROUP
public __acrtused ;satisfy MS for now
__acrtused equ 0
IFNDEF __DPMI16__
public __WINMAINCALL ; used internally
ENDIF
public __INITAPPCALLED ; used internally
IFNDEF __DPMI16__
extrn WINMAIN:DIST
ENDIF
extrn INITAPP:far
extrn INITTASK:far
extrn FATALEXIT:far
extrn WAITEVENT:far
extrn LOCKSEGMENT:far
extrn UNLOCKSEGMENT:far
extrn GETWINFLAGS:far
IFDEF __DPMI16__
extrn _main:DIST
extrn _OkToInitWindowsRTL:DIST
extrn __abort:DIST
ENDIF
extrn _exit:DIST
extrn __exit:DIST
extrn __exitbuf:DIST
extrn __exitfopen:DIST
extrn __exitopen:DIST
extrn __setupio:near ;required!
extrn __ExceptInit:DIST
public __DestructorCount ;Offset to global destructor count
__DestructorCount EQU 10H
public __Exception_list ;Offset to global exception list
__Exception_list EQU 14H
NULL segment
db 16 dup (0) ;Windows
db 4 dup (0) ;destructor count
db 2 dup (0) ;exception list
db 4 dup (0) ;exception vptr
db 6 dup (0) ;reserved
db 2 dup (0) ;VBX control jump vector
;MUST be at SS:20h
db 2 dup (0) ;reserved
ends
_CVTSEG segment
public __RealCvtVector
__RealCvtVector label word
ends
_SCNSEG segment
public __ScanTodVector
__ScanTodVector label word
ends
_FPSEG segment
public __FPVector
__FPVector dd 0
ends
_DATA segment
public _errno
_errno dw 0
public __protected
__protected dw 0
public __8086
__8086 dw 0
public __8087
__8087 dw 0
public __psp
__psp dw 0
public __hInstance
__hInstance dw 0
public __hPrev
__hPrev dw 0
public __pszCmdline
__pszCmdline dw 0
public __cmdShow
__cmdShow dw 0
public __version
__version label word
public __osversion
__osversion label word
public __osmajor
__osmajor db 0
public __osminor
__osminor db 0
public __osmode ;Used for OS/2 protected mode by MS,
__osmode db 0 ; currently set to 0 under Windows
public __WinAllocFlag ;Used by malloc to get additional flags
__WinAllocFlag dw 0 ; to pass to GlobalAlloc (for DLL use)
public __LockWIN87EM ;Used do lock down WIN87EM to avoid
__LockWIN87EM dw 1 ; DLL unload ordering problem
public __abend
__abend dw 0 ;Signals abnormal end, don't run destructors etc.
IFDEF __DPMI16__
extrn __C0environ:dword
extrn __C0argv:dword
extrn __C0argc:word
ENDIF
CopyRight db 'Borland C++ - Copyright 1994 Borland Intl.',0
IFDEF __DPMI16__
DPMI16Error_s db 'This DPMI16 application was linked incorrectly and'
db ' will fail.',10,13,'$'
ENDIF
ends
_TEXT segment
Main proc near
;Windows initialization. Sets up registers and stack.
IFDEF __DPMI16__
mov ax, seg DGROUP
mov ds, ax
ENDIF
push bx cx es
xor ax,ax
push ax
call __ExceptInit
pop ax
pop es cx bx
;INITTASK returns:
; 'Failure:
; AX = zero if it failed
; Success:
; AX = 1
; CX = stack limit
; DX = cmdShow parameter to CreateWindow
; ES:BX = -> DOS format command line (ES = PSP address)
; SI = hPrevinstance
; DI = hinstance
call INITTASK
or ax,ax
jnz @@OK
jmp @@Fail
@@OK: mov word ptr ss:[__Exception_list], -1
mov __psp,es
mov word ptr __pszCmdline,bx
mov __hPrev,si
mov __hInstance,di
mov __cmdShow,dx
IF LDATA EQ false
mov ax,-1
push ax
call LOCKSEGMENT
ENDIF
;Clear _BSS, uninitialized data area
IFNDEF __HUGE__
xor ax, ax
push ds
pop es
mov di,offset DGROUP:BeginBSS
mov cx,offset DGROUP:EndBSS
sub cx,di
cld
rep
stosb
ENDIF
;Init the Windows App
xor ax,ax
push ax
call WAITEVENT
push __hInstance
call INITAPP
__INITAPPCALLED:or ax,ax
jnz @@InitOK
jmp @@Fail
@@InitOK:
;Determine DOS version
mov ah, 30h
int 21h
mov __version, ax ; save minor and major revision
;Determine whether we are in protected mode
call GETWINFLAGS
test ax,1 ; WF_PMODE = 1
jz @@realmode ; Note: GETWINFLAGS returns a long,
; so if WF_PMODE changed it could be
; in the high word.
mov __protected, 8 ; Eight is for convenience.
@@realmode:
;Test for 8086/8087 presence
test ax,0400h ; WF_8087 = 0x0400
jz @@no8087
mov __8087, 1
@@no8087:
and ax,08h+04h+02h ; WF_CPU486|WF_CPU386|WF_CPU286
shr ax,1 ; Convert to 4 or 2 or 1 or 0
test ax,0004h ; Have 4, 486 done
jnz @@NoAdjust
or ax,ax ; Have 0, 8086 done
jz @@NoAdjust
inc ax ; Have 2 or 1, need 3 or 2
@@NoAdjust:
mov __8086,ax ; Set CPU Type
IFDEF __DPMI16__
;
; Here we attempt to prevent an early death caused by linking
; the libs in the wrong order
;
call _OkToInitWindowsRTL
or ax, ax
jnz DPMI16Error
ENDIF
;Call our initialization functions, including C++ static constructors.
mov ax,ds
mov es,ax
mov si,offset DGROUP:InitStart ;si = start of table
mov di,offset DGROUP:InitEnd ;di = end of table
call Initialize
IFDEF __DPMI16__
;Set up and call _main for DPMI16 application
push word ptr [__C0environ+2]
push word ptr [__C0environ]
push word ptr [__C0argv+2]
push word ptr [__C0argv]
push [__C0argc]
call _main
ELSE
;Set up and call WinMain for Windows application
push __hInstance
push __hPrev
push __psp
push word ptr __pszCmdline
push __cmdShow
__WINMAINCALL: call WINMAIN
ENDIF
push ax ; Push return value
cmp __abend, 0
jne @@abnormalexit
call _exit ; Normal exit
@@abnormalexit: call __exit ; Abnormal exit, don't call destructors etc.
IFDEF __DPMI16__
DPMI16Error:
mov ah, 9
mov dx, offset DPMI16Error_s
int 21h
call __abort
ENDIF
;---------------------------------------------------------------------------
; _cleanup() call all #pragma exit cleanup routines.
; _checknull() check for null pointer zapping copyright message
; _terminate(int) exit program with error code
; _restorezero() restore interrupt vectors
;
; These functions are called by exit(), _exit(), _cexit(),
; and _c_exit().
;---------------------------------------------------------------------------
; Call cleanup routines
__cleanup PROC DIST
PUBLIC __cleanup
mov ax,ds
mov es,ax
push si
push di
mov si,offset DGROUP:ExitStart
mov di,offset DGROUP:ExitEnd
call Cleanup
pop di
pop si
ret
__cleanup ENDP
; Check for null pointers before exit. NO-OP on Windows.
__checknull PROC DIST
PUBLIC __checknull
ret
__checknull ENDP
; Restore grabbed interrupt vectors. NO-OP on Windows.
__restorezero PROC DIST
PUBLIC __restorezero
ret
__restorezero ENDP
; Exit to DOS
__terminate PROC DIST
PUBLIC __terminate
IF LDATA EQ false
mov ax,-1
push ax
call UNLOCKSEGMENT
ENDIF
mov bp,sp
mov al,[bp+cPtrSize]
mov ah,4ch ;exit
int 21h
__terminate ENDP
@@Fail: mov al,0ffh
push ax
call _exit
mov ah,4ch ;exit
int 21h
endp
; Return default data segment in AX
__GetDGROUP PROC FAR
PUBLIC __GetDGROUP
mov ax, ss
ret
endp
;------------------------------------------------------------------
; Loop through a startup/exit (SE) table,
; calling functions in order of priority.
; ES:SI is assumed to point to the beginning of the SE table
; ES:DI is assumed to point to the end of the SE table
; First 64 priorities are reserved by Borland
;------------------------------------------------------------------
PNEAR EQU 0
PFAR EQU 1
NOTUSED EQU 0ffh
SE STRUC
calltype db ? ; 0=near,1=far,ff=not used
priority db ? ; 0=highest,ff=lowest
addrlow dw ?
addrhigh dw ?
SE ENDS
Initialize proc near
@@Start: mov ax,100h ;start with lowest priority
mov dx,di ;set sentinel to end of table
mov bx,si ;bx = start of table
@@TopOfTable: cmp bx,di ;and the end of the table?
je @@EndOfTable ;yes, exit the loop
cmp es:[bx.calltype],NOTUSED;check the call type
je @@Next
mov cl, es:[bx.priority] ;move priority to CX
xor ch, ch
cmp cx,ax ;check the priority
jae @@Next ;too high? skip
mov ax,cx ;keep priority
mov dx,bx ;keep index in dx
@@Next: add bx,SIZE SE ;bx = next item in table
jmp @@TopOfTable
@@EndOfTable: cmp dx,di ;did we exhaust the table?
je @@Done ;yes, quit
mov bx,dx ;bx = highest priority item
cmp es:[bx.calltype],PNEAR ;is it near or far?
mov es:[bx.calltype],NOTUSED;wipe the call type
push es ;save es
je @@NearCall
@@FarCall: call DWORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@NearCall: call WORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@Done: ret
endp
Cleanup proc near
@@Start: mov ah,0 ;start with highest priority
mov dx,di ;set sentinel to end of table
mov bx,si ;bx = start of table
@@TopOfTable: cmp bx,di ;and the end of the table?
je @@EndOfTable ;yes, exit the loop
cmp es:[bx.calltype],NOTUSED;check the call type
je @@Next
cmp es:[bx.priority],ah ;check the priority
jb @@Next ;too low? skip
mov ah,es:[bx.priority] ;keep priority
mov dx,bx ;keep index in dx
@@Next: add bx,SIZE SE ;bx = next item in table
jmp @@TopOfTable
@@EndOfTable: cmp dx,di ;did we exhaust the table?
je @@Done ;yes, quit
mov bx,dx ;bx = highest priority item
cmp es:[bx.calltype],PNEAR ;is it near or far?
mov es:[bx.calltype],NOTUSED;wipe the call type
push es ;save es
je @@NearCall
@@FarCall: call DWORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@NearCall: call WORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@Done: ret
endp
ends
end Main
+698
View File
@@ -0,0 +1,698 @@
;[]-----------------------------------------------------------------[]
;| RULES.ASI -- Rules & Structures for assembler |
;[]-----------------------------------------------------------------[]
;
; C/C++ Run Time Library - Version 6.5
;
; Copyright (c) 1987, 1994 by Borland International
; All Rights Reserved.
;
;*** First we begin with a few of the major constants of C.
false equ 0 ; Beware ! For incoming parameters, non-false = true.
true equ 1 ; For results, we generate the proper numbers.
lesser equ -1 ; Incoming, lesser < 0
equal equ 0
greater equ 1 ; Incoming, greater > 0
PAGE
;[]------------------------------------------------------------[]
;| |
;| Conditional Assembly Directives |
;| |
;[]------------------------------------------------------------[]
;memory model aliases, for the convenience of building the library
IFDEF __t__
__TINY__ equ 1
ENDIF
IFDEF __s__
__SMALL__ equ 1
ENDIF
IFDEF __c__
__COMPACT__ equ 1
ENDIF
IFDEF __m__
__MEDIUM__ equ 1
ENDIF
IFDEF __l__
__LARGE__ equ 1
ENDIF
IFDEF __h__
__HUGE__ equ 1
ENDIF
IFNDEF __TINY__
IFNDEF __SMALL__
IFNDEF __MEDIUM__
IFNDEF __COMPACT__
IFNDEF __LARGE__
IFNDEF __HUGE__
%OUT You must supply a model symbol.
.ERR
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
;bit masks to extract default pointer types from MMODEL (at run-time)
FCODE equ 8000h
FDATA equ 4000h
IFDEF __TINY__ ; Small Code - Small Data
LPROG equ false
LDATA equ false
MMODEL equ 0
_DSSTACK_ equ <>
ENDIF
IFDEF __SMALL__ ; Small Code - Small Data
LPROG equ false
LDATA equ false
MMODEL equ 1
_DSSTACK_ equ <>
ENDIF
IFDEF __MEDIUM__ ; Large Code - Small Data
LPROG equ true
LDATA equ false
MMODEL equ FCODE+2
_DSSTACK_ equ <>
ENDIF
IFDEF __COMPACT__ ; Small Code - Large Data
LPROG equ false
LDATA equ true
MMODEL equ FDATA+3
ENDIF
IFDEF __LARGE__ ; Large Code - Large Data
LPROG equ true
LDATA equ true
MMODEL equ FCODE+FDATA+4
ENDIF
IFDEF __HUGE__ ; Large Code - Large Data
LPROG equ true
LDATA equ true
MMODEL equ FCODE+FDATA+5
ENDIF
IF LPROG
DIST equ FAR
ELSE
DIST equ NEAR
ENDIF
PAGE
;[]------------------------------------------------------------[]
;| |
;| Segment Declarations Macros |
;| |
;[]------------------------------------------------------------[]
Code_Seg@ MACRO ;; Open a Code Segment
IFDEF __WINDOWS__
_TEXT SEGMENT WORD PUBLIC 'CODE'
ELSE
_TEXT SEGMENT BYTE PUBLIC 'CODE'
ENDIF
ASSUME CS:_TEXT
ENDM
Code_EndS@ MACRO ;; Close a Code Segment
_TEXT ENDS
ENDM
Data_Seg@ MACRO ;; Open a Data Segment (initialized)
_DATA SEGMENT WORD PUBLIC 'DATA'
ENDM
Data_EndS@ MACRO ;; Close a Data Segment (initialized)
_DATA ENDS
ENDM
IFNDEF __HUGE__
BSS_Seg@ MACRO ;; Open a Data Segment (un-initialized)
_BSS SEGMENT WORD PUBLIC 'BSS'
ENDM
BSS_EndS@ MACRO ;; Close a Data Segment (un-initialized)
_BSS ENDS
ENDM
ENDIF
FarData_Seg@ MACRO ;; Open a FAR Data Segment
_FARDATA SEGMENT PARA PUBLIC 'FAR_DATA'
ENDM
FarData_EndS@ MACRO ;; Close a FAR Data Segment
_FARDATA ENDS
ENDM
FarBSS_Seg@ MACRO ;; Open a FAR BSS Segment
_FARBSS SEGMENT PARA PUBLIC 'FAR_BSS'
ENDM
FarBSS_EndS@ MACRO ;; Close a FAR BSS Segment
_FARBSS ENDS
ENDM
Const_Seg@ MACRO ;; Open a CONST Segment
_CONST SEGMENT WORD PUBLIC 'CONST'
ENDM
Const_EndS@ MACRO ;; Close a CONST Segment
_CONST ENDS
ENDM
Init_Seg@ MACRO ;; Open a INIT Segment
_INIT_ SEGMENT WORD PUBLIC 'INITDATA'
ENDM
Init_EndS@ MACRO ;; Close a INIT Segment
_INIT_ ENDS
ENDM
Exit_Seg@ MACRO ;; Open a EXIT Segment
_EXIT_ SEGMENT WORD PUBLIC 'EXITDATA'
ENDM
Exit_EndS@ MACRO ;; Close a EXIT Segment
_EXIT_ ENDS
ENDM
CVT_Seg@ MACRO
_CVTSEG SEGMENT WORD PUBLIC 'DATA'
ENDM
CVT_EndS@ MACRO
_CVTSEG ENDS
ENDM
SCN_Seg@ MACRO
_SCNSEG SEGMENT WORD PUBLIC 'DATA'
ENDM
SCN_EndS@ MACRO
_SCNSEG ENDS
ENDM
Header@ MACRO
Code_Seg@
Code_EndS@
Data_Seg@
Data_EndS@
BSS_Seg@
BSS_EndS@
ASSUME CS:_TEXT, DS:DGROUP
ENDM
;[]------------------------------------------------------------[]
;| |
;| Segment Definitions |
;| |
;[]------------------------------------------------------------[]
IFDEF __C0__
IFDEF __WINDOWS__
_TEXT SEGMENT WORD PUBLIC 'CODE'
ENDS
ELSE
_TEXT SEGMENT BYTE PUBLIC 'CODE'
ENDS
ENDIF
_FARDATA SEGMENT PARA PUBLIC 'FAR_DATA'
ENDS
_FARBSS SEGMENT PARA PUBLIC 'FAR_BSS'
ENDS
IFNDEF __WINDOWS__
IFNDEF __TINY__
_OVERLAY_ SEGMENT PARA PUBLIC 'OVRINFO'
ENDS
_1STUB_ SEGMENT PARA PUBLIC 'STUBSEG'
ENDS
ENDIF
ENDIF
IFDEF __WINDOWS__
NULL SEGMENT PARA PUBLIC 'BEGDATA'
ENDS
ENDIF
_DATA SEGMENT PARA PUBLIC 'DATA'
ENDS
ENDS
_CONST SEGMENT WORD PUBLIC 'CONST'
ENDS
IFDEF __WINDOWS__
_FPSEG SEGMENT WORD PUBLIC 'DATA'
ENDS
ENDIF
_CVTSEG SEGMENT WORD PUBLIC 'DATA'
ENDS
_SCNSEG SEGMENT WORD PUBLIC 'DATA'
ENDS
_INIT_ SEGMENT WORD PUBLIC 'INITDATA'
InitStart label byte
ENDS
_INITEND_ SEGMENT BYTE PUBLIC 'INITDATA'
InitEnd label byte
ENDS
_EXIT_ SEGMENT WORD PUBLIC 'EXITDATA'
ExitStart label byte
ENDS
_EXITEND_ SEGMENT BYTE PUBLIC 'EXITDATA'
ExitEnd label byte
ENDS
IFNDEF __HUGE__
_BSS SEGMENT WORD PUBLIC 'BSS'
BeginBSS label byte
ENDS
_BSSEND SEGMENT BYTE PUBLIC 'BSSEND'
EndBSS label byte
ENDS
ENDIF
IFDEF __WINDOWS__
IFDEF __HUGE__
DGROUP GROUP NULL,_DATA,_CONST,_FPSEG,_CVTSEG,_SCNSEG,_INIT_,_INITEND_,_EXIT_,_EXITEND_
ELSE
DGROUP GROUP NULL,_DATA,_CONST,_FPSEG,_CVTSEG,_SCNSEG,_INIT_,_INITEND_,_EXIT_,_EXITEND_,_BSS,_BSSEND
ENDIF
ELSE
IFNDEF __NOFLOAT__
IF LDATA
IFDEF __HUGE__
DGROUP GROUP _DATA,_CONST,_CVTSEG,_SCNSEG,_INIT_,_INITEND_,_EXIT_,_EXITEND_
ELSE
DGROUP GROUP _DATA,_CONST,_CVTSEG,_SCNSEG,_INIT_,_INITEND_,_EXIT_,_EXITEND_,_BSS,_BSSEND
ENDIF
ELSE
IFDEF __TINY__
DGROUP GROUP _TEXT,_DATA,_CONST,_CVTSEG,_SCNSEG,_INIT_,_INITEND_,_EXIT_,_EXITEND_,_BSS,_BSSEND
ELSE
DGROUP GROUP _DATA,_CONST,_CVTSEG,_SCNSEG,_INIT_,_INITEND_,_EXIT_,_EXITEND_,_BSS,_BSSEND
ENDIF
ENDIF
ELSE
IF LDATA
IFDEF __HUGE__
DGROUP GROUP _DATA,_CONST,_CVTSEG,_SCNSEG,_INIT_,_INITEND_,_EXIT_,_EXITEND_
ELSE
DGROUP GROUP _DATA,_CONST,_CVTSEG,_SCNSEG,_BSS,_BSSEND
ENDIF
ELSE
IFDEF __TINY__
DGROUP GROUP _TEXT,_DATA,_CONST,_CVTSEG,_SCNSEG,_INIT_,_INITEND_,_EXIT_,_EXITEND_,_BSS,_BSSEND
ELSE
DGROUP GROUP _DATA,_CONST,_CVTSEG,_SCNSEG,_INIT_,_INITEND_,_EXIT_,_EXITEND_,_BSS,_BSSEND
ENDIF
ENDIF
ENDIF ; __NOFLOAT__
ENDIF ; __WINDOWS__
ELSE
Code_Seg@
Code_EndS@
Data_Seg@
Data_EndS@
DGROUP GROUP _DATA
ENDIF ; __C0__
PAGE
;[]------------------------------------------------------------[]
;| |
;| Old Segment Declarations Macros |
;| |
;[]------------------------------------------------------------[]
CSeg@ MACRO ;; Open a Code Segment
IFDEF __WINDOWS__
_TEXT SEGMENT WORD PUBLIC 'CODE'
ELSE
_TEXT SEGMENT BYTE PUBLIC 'CODE'
ENDIF
ASSUME CS:_TEXT
ENDM
CSegEnd@ MACRO ;; Close a Code Segment
_TEXT ENDS
ENDM
DSeg@ MACRO ;; Open a Data Segment (initialized)
_DATA SEGMENT WORD PUBLIC 'DATA'
ENDM
DSegEnd@ MACRO ;; Close a Data Segment (initialized)
_DATA ENDS
ENDM
IFDEF __BSS__
IFNDEF __HUGE__
BSeg@ MACRO ;; Open a Data Segment (un-initialized)
_BSS SEGMENT WORD PUBLIC 'BSS'
ENDM
BSegEnd@ MACRO ;; Close a Data Segment (un-initialized)
_BSS ENDS
ENDM
ENDIF
ENDIF
Header@ MACRO
IFDEF __WINDOWS__
_TEXT SEGMENT WORD PUBLIC 'CODE'
ELSE
_TEXT SEGMENT BYTE PUBLIC 'CODE'
ENDIF
_TEXT ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
_DATA ENDS
IFDEF __BSS__
IFNDEF __HUGE__
_BSS SEGMENT WORD PUBLIC 'BSS'
_BSS ENDS
ENDIF
ENDIF
ASSUME CS:_TEXT, DS:DGROUP
ENDM
PAGE
;[]------------------------------------------------------------[]
;| |
;| C Naming Convention Macros |
;| |
;[]------------------------------------------------------------[]
UNDERSCORE EQU 1
ExtSym@ MACRO Sym, sType, sName
IFNB <sName>
IFIDN <sName>, <__PASCAL__>
NAMING = 0
ELSE
NAMING = UNDERSCORE
ENDIF
ENDIF
IF NAMING
EXTRN _&Sym : sType
Sym&@ equ _&Sym
ELSE
EXTRN Sym : sType
Sym&@ equ Sym
ENDIF
ENDM
PubSym@ MACRO Sym, Definition, sName
IFNB <sName>
IFIDN <sName>, <__PASCAL__>
NAMING = 0
ELSE
NAMING = UNDERSCORE
ENDIF
ENDIF
IF NAMING
PUBLIC _&Sym
_&Sym Definition
Sym&@ equ _&Sym
ELSE
PUBLIC Sym
Sym Definition
Sym&@ equ Sym
ENDIF
ENDM
Static@ MACRO Sym, Definition, sName
IFNB <sName>
IFIDN <sName>, <__PASCAL__>
NAMING = 0
ELSE
NAMING = UNDERSCORE
ENDIF
ENDIF
IF NAMING
_&Sym Definition
Sym&@ equ _&Sym
ELSE
Sym Definition
Sym&@ equ Sym
ENDIF
ENDM
PAGE
;[]------------------------------------------------------------[]
;| |
;| Macros which are Data Size Dependent |
;| |
;[]------------------------------------------------------------[]
IF LDATA
DPTR_ equ DWORD PTR
dPtrSize equ 4
LES_ equ LES
ES_ equ ES:
SS_ equ SS:
LDS_ equ LDS
pushDS_ MACRO
PUSH DS
ENDM
popDS_ MACRO
POP DS
ENDM
PushPtr MACRO dPtrOff, dPtrSeg
PUSH dPtrSeg
PUSH dPtrOff
ENDM
dPtr@ MACRO Sym, VALUE, sName ;; Static Data pointer
Static@ Sym, <DD VALUE>, sName
ENDM
dPtrPub@ MACRO Sym, VALUE, sName ;; Global Data Pointer
PubSym@ Sym, <DD VALUE>, sName
ENDM
dPtrExt@ MACRO Sym, sName ;; External Data Pointer
ExtSym@ Sym, DWORD, sName
ENDM
ELSE
DPTR_ equ WORD PTR
dPtrSize equ 2
LES_ equ MOV
ES_ equ DS:
SS_ equ DS:
LDS_ equ MOV
pushDS_ MACRO
ENDM
popDS_ MACRO
ENDM
PushPtr MACRO dPtrOff, dPtrSeg
PUSH dPtrOff
ENDM
dPtr@ MACRO Sym, VALUE, sName ;; Static Data pointer
Static@ Sym, <DW VALUE>, sName
ENDM
dPtrPub@ MACRO Sym, VALUE, sName ;; Global Data Pointer
PubSym@ Sym, <DW VALUE>, sName
ENDM
dPtrExt@ MACRO Sym, sName ;; External Data Pointer
ExtSym@ Sym, WORD, sName
ENDM
ENDIF
PAGE
;[]------------------------------------------------------------[]
;| |
;| Macros which are Code Size Dependent |
;| |
;[]------------------------------------------------------------[]
IF LPROG
CPTR_ equ DWORD PTR
cPtrSize equ 4
Proc@ MACRO Sym, sName ;; Open a Static function
Static@ Sym, <PROC FAR>, sName
ENDM
PubProc@ MACRO Sym, sName ;; Open a Public function
PubSym@ Sym, <PROC FAR>, sName
ENDM
ExtProc@ MACRO Sym, sName ;; External Function
ExtSym@ Sym, FAR, sName
ENDM
cPtr@ MACRO Sym, VALUE, sName ;; Static Function pointer
Static@ Sym, <DD VALUE>, sName
ENDM
cPtrPub@ MACRO Sym, VALUE, sName;; Global Function Pointer
PubSym@ Sym, <DD VALUE>, sName
ENDM
cPtrExt@ MACRO Sym, sName ;; External Function Pointer
ExtSym@ Sym, DWORD, sName
ENDM
ELSE
CPTR_ equ WORD PTR
cPtrSize equ 2
Proc@ MACRO Sym, sName ;; Open a Static function
Static@ Sym, <PROC NEAR>, sName
ENDM
PubProc@ MACRO Sym, sName ;; Open a Public function
PubSym@ Sym, <PROC NEAR>, sName
ENDM
ExtProc@ MACRO Sym, sName ;; External Function
ExtSym@ Sym, NEAR, sName
ENDM
cPtr@ MACRO Sym, VALUE, sName ;; Static Function pointer
Static@ Sym, <DW VALUE>, sName
ENDM
cPtrPub@ MACRO Sym, VALUE, sName ;; Global Function Pointer
PubSym@ Sym, <DW VALUE>, sName
ENDM
cPtrExt@ MACRO Sym, sName ;; External Function Pointer
ExtSym@ Sym, WORD, sName
ENDM
ENDIF
EndProc@ MACRO Sym, sName ;; Close a function
Static@ Sym, ENDP, sName
ENDM
PAGE
;[]------------------------------------------------------------[]
;| |
;| Miscellaneous Definitions |
;| |
;[]------------------------------------------------------------[]
;*** Set up some macros for procedure parameters and export/import
nearCall STRUC
nearBP dw ?
nearIP dw ?
nearParam dw ?
nearCall ENDS
farCall STRUC
farBP dw ?
farCSIP dd ?
aParam dw ?
farCall ENDS
;*** Next, we define some convenient structures to access the parts
; of larger objects.
_twoBytes STRUC
BY0 db ?
BY1 db ?
_twoBytes ENDS
_fourWords STRUC
W0 dw ?
W1 dw ?
W2 dw ?
W3 dw ?
_fourWords ENDS
_twoDwords STRUC
DD0 dd ?
DD1 dd ?
_twoDwords ENDS
_aFloat STRUC
double dq ?
_aFloat ENDS
; How to invoke MSDOS.
MSDOS@ MACRO
int 21h
ENDM
PAGE
; The next section concerns the use of registers. SI and DI are used
; for register variables, and must be conserved.
; Registers AX, BX, CX, DX will not be preserved across function calls.
; Firstly, the registers to be conserved through function calls, including
; the setup of local variables.
link@ MACRO _si,_di,_ES,locals
push bp
mov bp, sp
IFNB <locals>
lea sp, locals
ENDIF
IFNB <_si>
push si
ENDIF
IFNB <_di>
push di
ENDIF
ENDM
unLink@ MACRO _si,_di,_ES,locals
IFNB <_di>
pop di
ENDIF
IFNB <_si>
pop si
ENDIF
IFNB <locals>
mov sp, bp
ENDIF
pop bp
ENDM
.LIST