home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c221 / 5.ddi / MWHC.005 / B3 < prev    next >
Encoding:
Text File  |  1992-12-09  |  60.6 KB  |  1,978 lines

  1. small_m = 1
  2. mach386 = 1
  3. GOC = 0
  4. .386p    ; Need 2 p to execute "lsl" to determine limit of data segment.
  5. .287
  6.  
  7. ; If you use Microsoft MASM (5.1) or MASM (6.0), enable one of the following
  8. ; equates.
  9. ; If you use MASM, you must also use "bd -mtop init.obj" to convert
  10. ; the MASM object to a Phar Lap object, if you wish to use the Phar Lap linker.
  11. ; USING_MASM_51    equ     1
  12. ; USING_MASM_60    equ     1
  13.  
  14. ; If you are using masm386 (not masm) to assemble this, with the intent
  15. ; to link with OS/2 2.0's link386, turn on USING_FLAT.  This avoids the use
  16. ; of DGROUP and CGROUP which OS/2 2.0's linear executable loader cannot
  17. ; support.
  18. ; USING_FLAT equ 1
  19.  
  20. ; If you are assembling for AUTOCAD ADS/ADI libraries:
  21. ;     386asmp init -nol -twoc -i \hc172\lib\src\ -d ADS
  22. ;     386asmp init -nol -twoc -i \hc172\lib\src\ -d PADI
  23.  
  24.     name    init
  25. ; (assemble this with "386asm init")
  26. ;**************************************************************************
  27. ;***  (c) Copyright 1983 - 1990            MetaWare Incorporated.    ***
  28. ;**************************************************************************
  29. ;***  You have the same rights to the object form of this program as    ***
  30. ;***  you do to the object code of the library.  You may not distribute ***
  31. ;***  this source, even if modified by you.                ***
  32. ;**************************************************************************
  33. ;***  The source to this module is provided                ***
  34. ;***  for the convenience of MetaWare Pascal and High C users that need ***
  35. ;***  to tailor their execution environments.                ***
  36. ;***  The casual user should NOT play with the code.            ***
  37. ;***  This code is subject to change without notice in future releases    ***
  38. ;***  of the compilers.                         ***
  39. ;**************************************************************************
  40. ;***  You must preserve the library copyright notice defined in this    ***
  41. ;***  module if your program uses any portion at all of the run-time    ***
  42. ;***  library (including this initializer or any other supplied run-    ***
  43. ;***  time source).  The copyright notice is in the definition of    ***
  44. ;***  the initial stack segment.  We recommend it be left right there.    ***
  45. ;***  But you can move it to anywhere you want as long it appears in    ***
  46. ;***  any linked program (.exe or ROM-burned program) using the library.***
  47. ;**************************************************************************
  48. ;*                                      *
  49. ;*    MetaWare Pascal or High C Runtime Initialization Module       *
  50. ;*             for small model, protected mode 386.             *
  51. ;*                                      *
  52. ;**************************************************************************
  53.     include model    ; Memory model.
  54.  
  55. ; GROWHEAP.
  56. ; Dynamic heap expansion.
  57. ; As an option the run-time system will contract the data area back to
  58. ; a minimum at start-up, and expand it dynamically.
  59. ; This is principally useful if you wish to allocate memory separately
  60. ; from the run-time system using the SETBLOCK (4a) command.
  61.  
  62. ; Phar Lap's DOS|Extender 1.1t or later can grow the heap dynamically.
  63. ; For enabling Phar Lap DOS|Extender to grow the heap dynamically,
  64. ; uncomment the next line.
  65. PHAR_LAP_CAN_GROW_HEAP equ 1
  66.  
  67. ; AIA's OS/386 2.0.10 or later can grow the heap dynamically.
  68. ; For older versions, comment out the next line.
  69. AIA_CAN_GROW_HEAP equ 1
  70. ; For Lahey-linked programs, we assume expansion can occur, since such
  71. ; linked programs do not give you all of memory.
  72.  
  73. ;-----
  74. ;    The following include file is provided by IGC. 
  75. ;    GDA.STR is general data area structure for VM/RUN (X-AM).
  76. ;    Upon entry to target program from VMRUN, EDX --> GDA.
  77. ;       GDA is not useful when solely in the Phar-Lap environment.
  78. ;    Use "gda.h" in the inc/ directory to access the GDA from C:
  79. ;        #include "gda.h"
  80. ;        GDA *gdaptr;
  81. ;-----
  82.     include gda.str
  83.  
  84. ; The difference between the Pascal and C run-time initialization
  85. ; is that in C, the argv array must be allocated and computed.
  86. ; In Pascal argument processing is handled through a separate argument pacakge.
  87.  
  88. ; Defines that you can set:
  89. ; 1. HC.  Set if this is for the High C library; not set otherwise.
  90. ; 2. STACK_SIZE.  Set this to the size of the stack you want.
  91. ; 3. no87.  Set this if you know you have no 8087 or 287.  It will eliminate
  92. ;    the initialization code for the chip.
  93. ;    Also, it will remove the printing of the "no87" environment variable
  94. ;    if you have an 8087/287 and the no87 variable is set to non-blank string.
  95. ;    (Don't confuse the "no87" define in this assembly from the no87
  96. ;    MS-DOS environment variable.  Read the programmer's Guide for more info
  97. ;    on the latter.)
  98. ;    Another reason to set this variable is that you know you're never
  99. ;    going to use an 8087/287, even if you have one.  It's especially
  100. ;    useful to remove the printing of the no87 environment variable on
  101. ;    programs for which the 8087/287 processor is irrelevant.
  102. ; 4. DOS.   Set this if this initializer is for MS-DOS (default).  Unset it
  103. ;    for embedded applications where DOS doesn't exist.  If you unset it,
  104. ;    you won't get argc/argv for C, nor the arg package for Pascal.
  105. ;    It doesn't remove all of the DOS-dependent code -- some of it you must
  106. ;    still rewrite for embedded applications (like how to find the top of
  107. ;    memory).  (By "unset" we mean just comment out the line setting it!)
  108. ;    Note that unsetting DOS doesn't remove all DOS-dependent code in
  109. ;    the library.  For example, the interrupt handler initialization
  110. ;    uses INT 21h, and so does all I/O.  Read the Embedded Applications
  111. ;    section of the Programmer's Guide for more information about how
  112. ;    to change those modules (source is generally provided).
  113. ; 5. SG_exists  -- Set when IGC environment is possible.
  114. ;    Unsetting it comments out code dependent on that environment only.
  115. ; 6. PL_exists    -- Set when PharLap DOS|Extender environment is possible.
  116. ;    Unsetting it comments out code dependent on that environment only.
  117. ; 7. NOWTK    -- Set if either the Weitek 1167 will never be present
  118. ;        -- or if you never care about it.
  119.  
  120. ifdef   WINDOWS
  121. ;no87    = 1    ; There can be no x87 processor.
  122. ;NOWTK = 1    ; There can be no Weitek processor.
  123. PL_weitek = 1   ; Windows uses a pharlap-style weitek setup.
  124. else
  125. ifdef ADS
  126. PL_exists = 1
  127. PL_weitek = 1
  128. else
  129. ifdef PADI
  130. PL_exists = 1
  131. PL_weitek = 1
  132. else
  133. SG_exists = 1
  134. PL_exists = 1
  135. PL_weitek = 1
  136. D4G_exists = 1
  137. AI_exists = 1
  138. endif ; PADI
  139. endif ; ADS
  140. endif ; WINDOWS
  141.  
  142. DOS equ 1    ; Initializer intended for MS-DOS.
  143. ; no87 equ 1
  144.  
  145. ; define HC if the initializer is to be for High C.
  146.   HC      equ      1
  147. ; Pascal is assumed otherwise.
  148.  
  149. ; Now set expression-identifiers so I can say "if this and not that".
  150. ; E.g., "compute x" defines macro ex to be 1 ifdef x, 0 otherwise.
  151. compute    macro    id
  152. ifdef    id
  153.     e&id = not 0
  154. else
  155.     e&id = 0
  156. endif
  157.     endm
  158.  
  159. compute HC    ; HC instead of Prof. Pascal.
  160. compute WINDOWS
  161. compute PL_exists
  162. compute AI_exists
  163. compute SG_exists
  164. compute D4G_exists
  165. compute DOS
  166. compute USING_MASM_51
  167. compute USING_MASM_60
  168. compute USING_FLAT
  169. compute ADS
  170. compute PADI
  171.  
  172. if eUSING_MASM_51 or eUSING_MASM_60
  173.     USING_MASM EQU 1
  174. endif
  175.  
  176. if eADS or ePADI
  177.     ACAD EQU 1
  178. endif
  179.  
  180. compute USING_MASM
  181.  
  182. comment @
  183.         Modified for AutoLISP and protected mode ADI
  184.  
  185.         Expects to be called at starting address as a subroutine, rather
  186.         than as an executable program from the operating system.  Stack
  187.         and segment registers must be correctly set up; and some
  188.         additional information is expected in these registers:
  189.  
  190.         ECX     Compatibility-check value.  Must be equal to (our
  191.                 locally defined symbol) chkval.  If it isn't, we assume
  192.                 we are erroneously being executed as an independent
  193.                 separate program.  This won't work, so we exit
  194.                 immediately to the system.
  195.  
  196.         DX:ESI  Pointer to structure containing initialization information.
  197.                 A minimum structure size of 8 bytes is mandatory (12 bytes
  198.                 if PADI is set).  The first 4 bytes of the structure must
  199.                 contain the number of bytes making up the structure.  The
  200.                 second 4 bytes must contain the initial heapsize of the
  201.                 child process, obtained from the loader in AutoCAD.  If
  202.                 PADI is set, the third 4 bytes must contain the physical
  203.                 address of the packet buffer in AutoCAD to be used for
  204.                 communication with protected mode ADI drivers.  All subsequent
  205.                 bytes are the business between AutoCAD and the loaded child
  206.                 process and may vary.
  207.  
  208.         The value we return is the argument to exit() which terminates us.
  209.         We preserve no registers, not even SS and SP.
  210.  
  211.         Some protected mode ADI, ADS, and AutoLISP modifications are
  212.         conditioned on the tag ACAD.
  213.  
  214.         Some code for ADS only is included only if the tag ADS is
  215.         predefined (e.g., in the assembler command line).
  216.  
  217.         Code required for AutoCAD protected mode ADI drivers only is included
  218.         by setting PADI in the assembler command line.
  219.         @
  220.  
  221. minmem equ 4    ; Offset within the structure containing initialization
  222.                 ; information to the initial heap size of the child process.
  223.  
  224. ifdef   PADI
  225. physadr equ 8   ; Offset within the structure containing initialization
  226.                 ; information to the physical address of a buffer shared
  227.                 ; between AutoCAD and a protected mode ADI driver.
  228. endif   ; PADI
  229.  
  230.  
  231. ;Memory Layout:
  232. ;
  233. ; High memory    +---------------+
  234. ;        | END OF MEMORY | 
  235. ;               |---------------|
  236. ;  _heaphi  ->  | top-of-heap    |
  237. ;        |   ...     |
  238. ;  _heaptop ->  |- - - - - - - -|  <- top of last user heap allocated
  239. ;        |   ...     |     (heaptop+1)..(heaphi) is available
  240. ;               | bottom-of-heap|
  241. ;  _TOP  ->    |---------------|  <- Of size STACK_SIZE, unless there isn't
  242. ;        |   stack    |  <- room, in which case the first heap
  243. ;        |   ...     |  <- allocation will fail.
  244. ;        | end-of-stack    |
  245. ;  _BASE ->    +---------------+
  246. ;        DATA   segments   (static variables and named common)
  247. ; Low memory    CODE   segments
  248. ; See the programmer's guide for more information and pictures of
  249. ; run-time organization with the different memory models.
  250. ; Stack margin1 is 512 bytes above the true end-of-stack.
  251. ; Stack margin2 is 256 bytes above the true end-of-stack.
  252. ; In non-large models, the stack margins go in a reserved area in the data
  253. ; segment, not in the stack segment.  In the large model, since there is
  254. ; no single data segment, the stack margins go at the tail end of the stack
  255. ; (at ss:-2 and ss:-4).
  256. ;
  257. ; If stack overflow checking is enabled, here is the code that is generated:
  258. ;    For procedures using 256 or less bytes in the stack:
  259. ;        cmp    esp,Stack_margin_1
  260. ;        jnb    around
  261. ;        int    0
  262. ;    around: ...
  263. ;
  264. ;    Since Stack_margin_2 is 512 above true e-o-s, such procedures will always
  265. ;    leave at least 256 bytes (512-256) left in the stack.
  266. ;
  267. ;    For procedures that use more than 256 bytes:
  268. ;        mov    eax,esp
  269. ;        sub    eax,Stack_margin_2
  270. ;        cmp    eax,Amount_to_allocate
  271. ;        jae    around
  272. ;        int    0
  273. ;    around: ...
  274. ;
  275. ;    Since Stack_margin1 is 256 from true end,
  276. ;    such procedures will leave at least 256 bytes in the stack.
  277. ;
  278. ;    Therefore, stack overflow occurs when less than 256 bytes would be
  279. ;    left AFTER stack allocation.
  280. ;    This permits the run-time environment to do some processing
  281. ;    such as producing a trace or cleaning up.
  282.  
  283. if eWINDOWS
  284. STACK_SIZE = 65536
  285. else
  286. ifdef    ACAD
  287. STACK_SIZE = 4000h
  288. else
  289. STACK_SIZE = 8192
  290. endif
  291. endif
  292.  
  293. ; Margin-big is used for small procedures -- it ensures a bigger margin.
  294. ; Margin-small is used for large procedures, since we do more accurate
  295. ; checking for them.
  296. Stack_margin_big    equ    512        ;Free stack bytes before overflow occurs
  297. Stack_margin_small    equ    256
  298. Stack_reserve    equ    4    ;At top, for the above two numbers (large model).
  299. STDERR        equ    2    ;standard error file handle
  300.  
  301.  
  302. if eWINDOWS
  303. ;   stack comes first for windows
  304.  
  305. if    not eUSING_MASM
  306.  
  307. ; Use dword alignment for stack segment in the future.
  308. STACKNAME equ ?STACK
  309. STACKNAME equ STACK
  310.  
  311. STACKNAME segment  dword stack  'STACK'    ; of at least 80 bytes.
  312. ; Copyright message got moved out of here so that the stack wouldn't
  313. ; take up space in the .exe file.
  314. start_of_stack equ this byte
  315.     db      STACK_SIZE dup (?)    ; The default stack of 8K.
  316. STACKNAME ends    ; MS-DOS loader puts info at the tail end of the stack during loading.
  317.  
  318. else    ; eUSING_MASM
  319.  
  320. ?STACK segment  dword stack  'STACK'    ; of at least 80 bytes.
  321. ; Copyright message got moved out of here so that the stack wouldn't
  322. ; take up space in the .exe file.
  323. start_of_stack equ this byte
  324.     db      STACK_SIZE dup (?)    ; The default stack of 8K.
  325. ?STACK ends    ; MS-DOS loader puts info at the tail end of the stack during loading.
  326.  
  327. endif ; not eUSING_MASM
  328. endif ; eWINDOWS
  329.  
  330. ;The following dummy segment instructs linker to put "code" lowest
  331. ;Must be made public since the main module also has public code,
  332. ;and some primitive linkers can't handle segments of the same name
  333. ;with different privacy attributes.  (This does not include Phar Lap's linker.)
  334. CODE    segment dword public 'CODE' 
  335. CODE    ends
  336.  
  337. DATA    segment dword public 'DATA' 
  338.     pubname stack_limit
  339. The_stack_margin equ this word
  340. def    stack_limit,dd,0    ; Stack margins.
  341.     dd    0
  342. DATA    ends
  343.  
  344. if not eWINDOWS
  345. ;   stack comes last if not windows
  346.  
  347. if    not eUSING_MASM
  348.  
  349. ; Use dword alignment for stack segment in the future.
  350. STACKNAME equ ?STACK
  351.  
  352. STACKNAME segment  dword stack  'STACK'    ; of at least 80 bytes.
  353. ; Copyright message got moved out of here so that the stack wouldn't
  354. ; take up space in the .exe file.
  355. start_of_stack equ this byte
  356.     db      STACK_SIZE dup (?)    ; The default stack of 8K.
  357. STACKNAME ends    ; MS-DOS loader puts info at the tail end of the stack during loading.
  358.  
  359. else    ; Handle MASM inadequacies.
  360.  
  361. ?STACK segment  dword stack  'STACK'    ; of at least 80 bytes.
  362. ; Copyright message got moved out of here so that the stack wouldn't
  363. ; take up space in the .exe file.
  364. start_of_stack equ this byte
  365.     db      STACK_SIZE dup (?)    ; The default stack of 8K.
  366. ?STACK ends    ; MS-DOS loader puts info at the tail end of the stack during loading.
  367.  
  368. endif ; not eUSING_MASM
  369. endif ; not eWINDOWS
  370.  
  371. ;  Line terminator convention.
  372.  
  373. _MWLTCONV    segment common dword 'DATA'  
  374. ; This must be a MetaWare Pascal string:  2 bytes for the length,
  375. ; then the actual string characters follow.
  376. ; Even if the string is of length one, leave the length of this
  377. ; segment at 8 bytes. (leave lt2 present even if not used.)
  378. ; Line termination convention for input:
  379. ltconv_in    dw    2    ; length is 2 for line terminator.
  380. lt1i        db    13    ; CR
  381. lt2i        db    10    ; LF
  382. ; Line termination convention for output; may be of any length:
  383. ltconv_out    dw    2    ; length is 2 for line terminator.
  384. lt1o        db    13    ; CR
  385. lt2o        db    10    ; LF
  386. _MWLTCONV    ends
  387.  
  388. PUBLIC __mwdfc, __mwdlc
  389. ifdef    HC
  390. _MWIFC    segment    public word 'DATA'
  391.     if eUSING_MASM_51
  392.     assume    cs:_MWIFC    ; hushes up MASM 5.1 errors
  393.     endif
  394. __mwifc    label    near
  395. _MWIFC    ends
  396. _MWIMC    segment    public word 'DATA'
  397. _MWIMC    ends
  398. _MWILC    segment    public word 'DATA'
  399.     if eUSING_MASM_51
  400.     assume    cs:_MWILC    ; hushes up MASM 5.1 errors
  401.     endif
  402. __mwilc    label    near
  403. _MWILC    ends
  404.  
  405. _MWDFC    segment    public word 'DATA'
  406.     if eUSING_MASM_51
  407.     assume    cs:_MWDFC    ; hushes up MASM 5.1 errors
  408.     endif
  409. __mwdfc    label near
  410. _MWDFC    ends
  411.  
  412. _MWDMC    segment    public word 'DATA'
  413. _MWDMC    ends
  414.  
  415. _MWDLC    segment    public word 'DATA'
  416.     if eUSING_MASM_51
  417.     assume    cs:_MWDLC    ; hushes up MASM 5.1 errors
  418.     endif
  419. __mwdlc    label near
  420. _MWDLC    ends
  421.  
  422. ; the following for use in windows's adk destructor, previously conflict
  423. ; with C++ destructor.
  424. if      eWINDOWS
  425. PUBLIC __mwdfw, __mwdlw
  426. _MWDFW    segment    public word 'DATA'
  427.     if eUSING_MASM_51
  428.     assume  cs:_MWDFW    ; hushes up MASM 5.1 errors
  429.     endif
  430. __mwdfw    label near
  431. _MWDFW    ends
  432. _MWDMW    segment    public word 'DATA'
  433. _MWDMW    ends
  434. _MWDLW    segment    public word 'DATA'
  435.     if eUSING_MASM_51
  436.     assume  cs:_MWDLW    ; hushes up MASM 5.1 errors
  437.     endif
  438. __mwdlw    label near
  439. _MWDLW    ends
  440. endif
  441.  
  442. endif
  443.  
  444. ; Define input and output descriptors
  445.  
  446. DSEG    segment dword 'DATA'
  447.     ; These are for Pascal but must be provided in C if we link in
  448.     ; the C initializer with Pascal routines.
  449.     pubnames <input,output>
  450.     pubnames <es,is_286,envp,8087,387,1167>
  451.     pubnames <argp,arglen,prognamep>
  452.     pubnames <CPU,OS,env,wind,printnochipmsg,init_ver>
  453.     pubnames <emc87,heap_expansion_enabled>
  454.     extrn     _osmajor:byte,_osminor:byte
  455. ifdef    HC
  456.     pubname argvp
  457. endif
  458. ; Pascal file variables Input and Output.  They are initialized in Pascal's Finit.p.
  459. defequ    input,dw,0
  460. defequ    output,dw,1
  461.  
  462. ; Initialize the "host" package that identifies the system we're running on.
  463. ; See the interface file Host.pf distributed with Professional Pascal or High C
  464. ; for the enumerated type declaration for the values of CPU and OS.
  465. defequ    CPU,db,8        ;Indicates 386. 
  466. defequ    OS,db,0     ;Indicates MSDOS.
  467.  
  468. _psp    equ    this byte
  469. def    es,df,0 ;The contents of es prior to invoking program
  470.         ; df is Microsoft's way of saying 48-bit pointer;
  471.         ; Phar Lap uses dp or df.
  472. escontents equ _psp             ; Program segment prefix pointer.
  473. ifdef    STACK_SIZE
  474.     public    _top,_base,_psp
  475. _top      dd    0        ; Top of stack (relative to SS).
  476. _base      dd    0        ; Base of stack (relative to DS).
  477. _heaphi   dd    0               ; offset to top of heap
  478. _heaptop  dd    0               ; offset to top of previous heap
  479.                                 ; (heaptop+1)..(heaphi) is available
  480. _totsiz   dd    0               ; temp work area
  481. osver      dd    ?
  482.  
  483. ifdef    SG_exists
  484.     public  _gda  
  485. _gda    dd      0               ; Address of gda (softguard only)  
  486. endif
  487.  
  488. endif
  489. defequ    argp,df,?    ;Pointer to command arguments
  490. ifdef HC
  491. defequ    argvp,df,?     ; Address of argv array for C.
  492. endif
  493.  
  494.     even
  495. if    eWINDOWS
  496.     pubname is_p
  497. if      not eHC     
  498. defequ  is_p,db,1      ; Is the RTE Pascal or C?  Affects whether
  499. else
  500. defequ  is_p,db,0      ; low-level interface clears errno.
  501. endif
  502. endif
  503. defequ    arglen,DD,?    ;Length of command argument string
  504. defequ    envp,df,0    ;Pointer to environment string
  505. defequ    is_286,db,0    ;True if this is a 286.
  506. _8087    equ    this word    ; Need word to store control word into.
  507. def    8087,dw,0    ;Set to true if 8087 is present
  508. temp    dw    0
  509. _387    equ    this word    ; Need word to store control word into.
  510. def    387,dw,0    ;Set to true if 80387 is present.
  511. _1167    equ    this word
  512. def    1167,dw,0    ; True if 1167 is present.
  513. _emc87    equ    this word
  514. def    emc87,dw,0    ; Set to true if emc87 is present.
  515. Null_pname db    0    ; Null prog name for < DOS 3.0.
  516. ; Prognamep is initialized to a 32-bit pointer to a 0-byte in case
  517. ; we can't obtain the program name.
  518. defequ    prognamep,dd,Null_pname  ;Pointer to program name
  519.     prognamep_seg dw 0
  520. SG_ENV = 1
  521. PL_ENV = 2
  522. AI_ENV = 3
  523. SSI_ENV= 4
  524. D4G_ENV= 5
  525. defequ    env,db,0      ; Which environment are we in?  SG/PL/AI?
  526. defequ    wind,db,0      ; Are we running under windows?
  527. defequ    printnochipmsg,db,0      ; Are we running under windows?
  528. defequ    init_ver,db,1      ; Which version of init is this? (1==LOC, 2==GOC)
  529. Lahey_format_load_file db 0    ; .plx (Phar-Lap linked) by default.
  530. CANT_EXPAND = 0
  531. CAN_EXPAND = 1
  532.  
  533. if eWINDOWS
  534.     defequ    heap_expansion_enabled,db,CANT_EXPAND
  535. else
  536.     defequ    heap_expansion_enabled,db,CAN_EXPAND
  537. endif
  538.  
  539. PSPseg  dw      24h     ; Pointer to DOS's Program segment prefix: Phar Lap.
  540. ENVseg    dw    2ch     ; Pointer to DOS's environment string: Phar Lap.
  541.  
  542. ifdef   ACAD
  543. chkval  equ     1234                    ; magic interface-compatibility code
  544. ifdef  ADS                              ; Avoid excess globals for ADS
  545. info_off    equ    ads_info_off
  546. info_sel    equ    ads_info_sel
  547. else
  548.         public  brkflg,stkflg
  549. endif   ; ADS
  550.         public  info_off,info_sel
  551. ifdef   PADI
  552.         public  cbufadr
  553. cbufadr  dd     0                       ; ptr to common pg between ACAD & PADI
  554. phys_adr dd     0                       ; physical address of common page
  555. endif   ; PADI
  556. brkflg  dd      0                       ; set nonzero for Control C
  557. stkflg  dd      0                       ; set nonzero for stack overflow
  558. interr  db      "Incompatible program interface",0Dh,0Ah,"$"
  559. rtnaddr df      0                       ; Caller's return address.
  560. info_off dd     0                       ; Offset of initialization info struct
  561. info_sel dw     0                       ; Selector of initialization info struct
  562. min_mem dd      0                       ; initial driver heap size
  563. endif   ; ACAD
  564.  
  565. DSEG    ends
  566. envptr    equ 2CH     ;Offset in DOS ctrl block where env address is located
  567. ;
  568. if eDOS
  569. if eWINDOWS
  570.     DGROUP  group DATA,DSEG,_MWLTCONV,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MW87_USED1,_MW387_USED1,_MW1167_USED1
  571.     DGROUP  group DATA,_MWDFW,_MWDMW,_MWDLW
  572. else
  573. if eUSING_MASM
  574.     DGROUP  group DATA,DSEG,_MWLTCONV,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MW87_USED1,_MW387_USED1,_MW1167_USED1,?STACK
  575. else
  576.     DGROUP  group DATA,DSEG,_MWLTCONV,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MW87_USED1,_MW387_USED1,_MW1167_USED1,STACKNAME
  577. endif
  578. endif
  579. else
  580.     DGROUP  group DATA,DSEG,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MWLTCONV,STACKNAME
  581. endif
  582.  
  583. assume_dgroup macro
  584. if    eUSING_FLAT
  585.     assume    ds:FLAT
  586. else    
  587.     assume  ds:DGROUP
  588. endif    
  589.     endm
  590.  
  591. ?INIT    segment dword 'CODE'
  592. if    not eUSING_FLAT
  593. CGROUP    group    ?INIT,CODE
  594.     assume cs:CGROUP
  595. else
  596. FLAT      group    ?INIT,CODE
  597.     assume cs:FLAT
  598. endif
  599.  
  600. ; Extern procs must be defined within current code segment for
  601. ; correct relocation bits to be generated. 
  602. extrn    _mwfinit:near
  603. ; Phar lap assembler won't take next line; it plays according to the rules (as opposed to Microsoft's assembler): 
  604. ;extequ    finit,near    ;Pascal file system initialization.
  605. extequ    cfinit,near ;C file system initialization.
  606. extequ    halt,near    ; Halt intrinsic.
  607. ifdef    HC
  608. extrn    main:near    ; Main program entry point
  609. extequ    set_up_args,near ; Routine to compute argv pointers.
  610. else
  611. extequ    main,near    ;Main program entry point
  612. ;extequ    init_interrupts,near    ; initialize interrupt handling.
  613. endif
  614.  
  615. ifdef   ACAD
  616. ifdef   ADS
  617. getinitinfo     equ    adsi_getinitinfo
  618. map_phys_mem    equ    ads_map_phys_mem
  619. endif   ; ADS
  620. ifndef  PADI
  621. extrn   getinitinfo:near        ; initialize child process loaded by AutoCAD
  622. endif   ; !PADI
  623. extrn   map_phys_mem:near       ; allows 3rd party to install a routine to map
  624.                                 ; physical memory between the stack and heap
  625. endif   ; ACAD
  626.  
  627. ; Where are the stack margins defined?    Top of stack or in data segment?
  628. if not eUSING_FLAT
  629. Stack_margin_big_place        equ    dword ptr DGROUP:The_stack_margin
  630. Stack_margin_small_place    equ    dword ptr DGROUP:The_stack_margin+Word_size
  631. else
  632. Stack_margin_big_place        equ    dword ptr The_stack_margin
  633. Stack_margin_small_place    equ    dword ptr The_stack_margin+Word_size
  634. endif
  635. ;
  636. ; DOS|Extender environment discovery code obtained from Phar Lap: 
  637.  
  638. ;**************************************************************************
  639. ;*  Here begins the execution of a Professional Pascal or High C program. *
  640. ;**************************************************************************
  641.  
  642. INIT    PROC    FAR
  643.     publab    INIT    ; Compiler generates this in upper case.
  644. genesis:
  645.     assume_dgroup
  646.  
  647.           jmp    short Discover_environment
  648.  
  649. ; We jump to the rest of the initialization and jump back so that
  650. ; when debugging we can easily see the call to main as the first call.
  651.  
  652. Init_return:
  653.  
  654. ifdef   ACAD
  655. ifndef  PADI
  656. Comment @
  657.         Take information from a structure in AutoCAD, pointed to by
  658.         info_sel:info_off, and store it for use by routines in the
  659.         program loaded by AutoCAD to which this module is linked.
  660.         @
  661.         movsx   eax,word ptr info_sel
  662.         push    eax
  663.         push    info_off
  664.         call    getinitinfo
  665.         add     esp,8
  666. endif
  667. endif
  668.  
  669. ; In C, Argc/Argv values have been pushed on the stack by the time we get here.
  670.  
  671.     pcall    main        ;call main program
  672.                 ; compiler generates defn of MAIN
  673.                 ; in a main program.
  674. Quit:                
  675.     ; In C, return the value returned by main to the system.
  676.     ; In Pascal, return 0.  To return a value in Pascal, use Halt(retcode).
  677. ifndef    HC
  678.     sub    eax,eax
  679. endif    
  680.     push    eax
  681.     pcall    halt
  682. ifdef    SG_exists
  683. ; Next 2 lines TEMPORARY for IGC only.
  684.     xor    eax,eax         ; We shouldn't get here.
  685.     call    _mwint21    
  686. endif   
  687. ifndef HC
  688.     ; Supply a dummy version of "call_onexit_fcns" for Pascal.
  689.     ; Cost:  1 byte here & 3 or 5 bytes for the call in term.p.
  690.     ; Benefits:  term.p is the same for Pascal and C.
  691.     publab    call_onexit_fcns
  692.     return
  693. endif
  694.     publab    restore_interrupts    ; For now, don't bother w/^C.
  695.     return
  696.  
  697. ifdef   ACAD
  698. comment @
  699.         For applications which are called as a subroutine from AutoCAD
  700.         (namely AutoLISP), here is the ultimate exit point which returns
  701.         back to AutoCAD.
  702.         @
  703. ifndef  ADS                     ; Take care with public names in ADS
  704.         public  exit_to_acad
  705. endif
  706. exit_to_acad:
  707.         jmp     rtnaddr         ; Return to AutoCAD
  708. endif   ; ACAD
  709.  
  710.  
  711. ifdef HC
  712.     db    'High C'
  713. else
  714.     db    'Professional Pascal'
  715. endif
  716.     db    ' Run-time Library Copyright (C) 1983-1990 MetaWare Incorporated.'
  717.  
  718. Discover_environment:
  719.  
  720. ifdef   ACAD
  721.         cmp     ecx,chkval              ; Proper chkval argument?
  722.         je      m00
  723.         mov     edx,offset interr       ; "Incompatible program interface"
  724.         mov     ah,9
  725.         int     21h                     ; Print the message.
  726.         mov     ax,4C01h
  727.         int     21h                     ; Exit to DOS.
  728. m00:
  729.         mov     info_off,esi            ; offset of initialization info struct
  730.         mov     info_sel,dx             ; selector of info struct
  731.         mov     es,dx
  732.         mov     eax,es:[esi].minmem
  733.         mov     min_mem,eax             ; initial heap size of driver
  734. ifdef   PADI
  735.         mov     eax,es:[esi].physadr
  736.         mov     phys_adr,eax            ; phys addr of pg w/ PADI packet buffer
  737. endif   ; PADI
  738.         mov     ax,ds
  739.         mov     es,ax
  740.         pop     dword ptr rtnaddr       ; Save return address, offset
  741.         pop     ax
  742.         mov     word ptr rtnaddr+4,ax   ;    and segment.
  743. endif   ; ACAD
  744.  
  745. ;       default assumptions
  746. if eWINDOWS
  747.     mov    env,SSI_ENV
  748. else
  749. if ePL_exists
  750.  
  751. ;    determine OS version
  752.     call    init_const
  753.  
  754.     mov     env,PL_ENV
  755. endif
  756.  
  757.     ; DOS|Extender environment discovery code obtained from Phar Lap:
  758. if eSG_exists
  759.     ; IGC: eax = abcdabcd.  Also, code segment is privilege level 3
  760.     ; (= 43 hex).
  761.     cmp     al,0cdh         ; eax = abcdabcd for IGC.
  762.     jne     short not_sg
  763.     cmp     ah,0abh
  764.     jne     short not_sg
  765.     ; Flaw: If we are in non-protected mode and get this far,
  766.     ; the cmp eax will have 16 bits too much constant, and will
  767.     ; cause the initializer to bomb.  It is unlikely that ax=abcd
  768.     ; yet eax <> abcdabcd.  --fixed with shift sequence.
  769. ;;;    cmp     eax,0abcdabcdh  ; Now try 386 instruction.
  770.     shr    eax,8
  771.     cmp    ah,0cdh
  772.     jne     short not_sg
  773.     shr    eax,8
  774.     cmp    ah,0abh
  775.     jne     short not_sg
  776.     mov     env,SG_ENV
  777.     mov     _gda,edx
  778.     jmp     short Initialize_everything
  779. not_sg: 
  780. endif ; SG_exists
  781.  
  782. if eD4G_exists
  783.     ; Magic code to figure out if this is Rational's 32-bit DOS extender.
  784.  
  785.     ; jmp    force_rational        
  786.     mov    dx,78h
  787.     mov    ax,0ff00h
  788.     call    _mwint21
  789.     cmp    eax, 4734ffffh    ; 4G
  790.     jne    short not_d4g
  791.  
  792. force_rational:
  793.         mov    env,D4G_ENV
  794.     mov    ax, es
  795.     mov    PSPseg, ax
  796.     mov    bx,2Ch
  797.     mov    ax,es:[bx]
  798.     mov    ENVseg, ax
  799. not_d4g:
  800. endif ; D4G_exists
  801.  
  802. if eAI_exists
  803.     cmp     env,D4G_ENV
  804.     je      short not_ai
  805.     cmp    env,SSI_ENV
  806.     je    short not_ai
  807.     mov    eax,osver
  808.         shr     eax,16
  809.         cmp     ax,'DX'
  810.         je      short not_ai
  811.         mov     env,AI_ENV
  812. not_ai:
  813. endif ; AI_exists
  814. endif ; eWINDOWS
  815.  
  816. ifdef WINDOWS
  817. ; Incoming registers:
  818. ; esi: initial amount of heap provided by loader, at tail end of DGROUP.
  819. ; ebx: pointer to argument strings.
  820. ; edi: pointer to program name.
  821. ; environ:
  822. ; ax:0:
  823. ;      (db 'var=value',0)*
  824. ;      (db 0)+      ; possibly some 0 padding for expansion later
  825. ; ax:edi:
  826. ;    db 'progname',0 ; fully-expanded (drive & path)
  827. ; ax:ebx:
  828. ;    db 'invoke name',0   ; the invocation prog name.
  829. ;    db 'arguments',0     ; 1 or more arguments.
  830. ;    db 0
  831. ; handle-table:
  832. ;    dd count
  833. ;    (db type, dd handle)*
  834. ;        type = 0 unused; 1 session; 2 file.
  835.  
  836.     mov    wind,1        ; Set the flag to say we are under windows
  837.  
  838.         mov     word ptr envp+Word_size,ax    ; Offset is already 0.
  839.         ; mov    envp,0        ; This is already 0.
  840.         
  841.         mov    word ptr argp+Word_size,ax    ; Offset of arguments.
  842.         mov    dword ptr argp,ebx        ; Will be adjusted to skip prog name later.
  843.         
  844.         mov    word ptr prognamep+Word_size,ax
  845.         mov     dword ptr prognamep,edi   ; Save prog name offset.
  846.         
  847.     ; initialize heap
  848.     mov    _base,0
  849.         mov     ax,ds
  850.         lsl     eax,eax                 ; Find total space.
  851.         mov     _heaphi,eax             ; End of heap.
  852.  
  853.         mov     _top,esi        ; heap starts here
  854.     mov    eax,esi            
  855.     inc    eax                    ; increase size to page boundary
  856.     add    eax,4095
  857.     and    eax,0fffff000h
  858.     dec     eax
  859.     mov    _heaptop,eax            ; and this is where heap really starts
  860. endif  ; WINDOWS
  861.  
  862. L1:    
  863.  
  864. ;INIT: Initialization code
  865. ; - set initial stackpointer, framepointer
  866. ; - calls FINIT and CFINIT to initialize file support
  867. ; - call  MAIN to invoke user's program
  868. ; - call  FTERM to close all open files
  869. ;
  870. ; Unneeded defn of DGROUP, since DS is fixed.
  871. ;dsgroup dw    DGROUP
  872.  
  873. ; Shorter than mov reg,-1
  874. getminus1 macro    reg
  875.     sub    reg,reg
  876.     dec    reg
  877.     endm
  878.  
  879. ifdef    HC
  880. Small_data_HC = 1
  881. endif
  882. SETBLOCK equ 4Ah
  883.  
  884. Initialize_everything:
  885.     sub    ebp,ebp     ;Initialize stack frame pointer
  886.     ; Make sure stack is mod 4 in case it's not.
  887.     and     esp,0fffffffch  ; Drop extra bytes.  Oh well.
  888.     assume_dgroup 
  889.  
  890. ; For the 386 we own all of memory.  Size up memory and inform the
  891. ; heap manager.
  892.  
  893.     mov    Stack_margin_big_place,Stack_margin_big
  894.     mov    Stack_margin_small_place,Stack_margin_small
  895.     add    Stack_margin_big_place,offset start_of_stack
  896.     add    Stack_margin_small_place,offset start_of_stack
  897.  
  898. ifdef  SG_exists
  899.     cmp     env,SG_ENV
  900.     jne    short next1
  901. ; Initialize stack, IGC environemnt.
  902. ; This code will work for h (highest) and a (append after load) stk options.  
  903. ; esp already setup by vmrun loader.
  904.     mov    eax,esp     ;get stack pointer
  905.     mov    ecx,[edx].GDA_STKSZ    ;get stack size, kbytes
  906.     shl    ecx,10        ;convert from k to # of bytes
  907.     sub    eax,ecx     ;calculate base of stack addr
  908.     mov    _base,eax    ; stack base
  909.     mov    eax,[edx].GDA_HLOD    ;get highest load address
  910.     mov    _top,eax    ; top of stack
  911.     inc    eax            ; increase size to page boundary
  912.     add    eax,4095
  913.     and    eax,0fffff000h
  914.     dec     eax
  915.     mov    _heaptop,eax    ; previous top of heap
  916.  
  917.     mov    ecx,[edx].GDA_HMEM    ;get available high memory
  918.     shl    ecx,10        ;convert from k to # of bytes
  919.     dec     ecx
  920.     add    eax,ecx     ;calculate heap top addr
  921.     mov    _heaphi,eax    ;top of heap
  922. ; Free memory below 640K for subsequent use by EXEC.
  923.     mov    ebx,[edx].GDA_TLOW    ; Subtract highest used low address.
  924.     sub    ebx,[edx].GDA_PSPA      ; Subtract lowest used low address. 
  925.     shr    ebx,4            ; Convert to paragraphs.
  926.     inc    ebx            ; Safety?
  927.     mov    ah,SETBLOCK         ; SETBLOCK to bx paragraphs from psp start.
  928.     call    _mwint21
  929.     test    byte ptr [edx].GDA_ENV,GDA_WEITEK
  930.     setne   byte ptr _1167
  931. next1:
  932. endif   
  933. if  ePL_exists or eAI_exists
  934.     cmp    env,PL_ENV
  935.      je    next2a
  936.     cmp    env,AI_ENV
  937.     je    next2a
  938.     jmp    next2
  939. next2a:
  940.     mov    _base,0        ; Start of stack.
  941.     lea     eax,32[esp]     ; eax = start of heap + some padding for safety.
  942.     mov    _top,eax
  943.     inc    eax            ; increase size to page boundary
  944.     add    eax,4095
  945.     and    eax,0fffff000h
  946.     dec     eax
  947.     mov    _heaptop,eax    ; end of previous heap
  948.  
  949.     mov    ax,ds
  950.     lsl    eax,eax        ; load segment limit of data segment.
  951.     mov    _heaphi,eax    ; Top of heap (linear address).
  952. next2:
  953. endif   
  954.  
  955. ;*******************************************************************************
  956. ; Remainder of initialization, independent of where stack lies.
  957. ;*******************************************************************************
  958.  
  959. ;*******************************************************************************
  960. ; Deal with 8087/287
  961. ; Discover whether 8087/287 exists unless no8087 has been set.
  962. ;*******************************************************************************
  963.  
  964. ifdef    no87
  965.     mov    byte ptr _8087,0
  966. else
  967.  
  968. ; Initialize floating point:  check for existence of 8087/287.
  969. ; We have to do this here so that we can avoid printing out the contents
  970. ; of NO87 if the machine doesn't have an 8087.
  971.     fninit            ;initialize 8087 if one exists
  972.     xor    eax,eax        ;Initialize 8087 flag to zero.
  973.     mov    temp,ax
  974.     sub    ecx,ecx         ; One byte shorter than mov ecx,15.
  975.     mov    cl,15
  976. ;       mov    ecx,15        ; Set ch := 0 on first try.
  977. waste1: loop    waste1
  978.     fnstcw    temp         ; Store cntl word
  979.     ; We used to just test for non-zero on 8087 systems; but that
  980.     ; didn't work for 287s.  Even if no 287, IBM ATs returned
  981.     ; garbage as the control word.
  982.     mov    cl,15
  983. waste2: loop    waste2
  984.     and    temp,00f3fh
  985.     cmp    temp,0033fh    ; Processor status after initialization.
  986.     jne    short no_8087
  987.     fnstsw    temp
  988.     mov    cl,15
  989. waste3: loop    waste3
  990.     test    temp,0b8bfh
  991.     jnz    short no_8087
  992.     fldcw    cs:fp_init_cw_emc    ;load control word
  993.     ; EMC 87 will leave on the upper bit in the control word:
  994.     fstcw    temp
  995.     test    byte ptr temp+1,80h    ; EMC part there?
  996.     jz    short not_EMC
  997.     mov    byte ptr _387,1    ; EMC also looks like a 387.
  998.     ; We load the normal control word in case someone else stores
  999.     ; it and expects the top bit to be off.
  1000.     fldcw    cs:fp_init_cw        ;load normal control word
  1001.     mov    byte ptr _emc87,1    ;Say that it's present.
  1002.     ; Now fall through to the code that will determine it's also a 387 clone.
  1003. not_EMC:
  1004.     mov    byte ptr _8087,1 ;Set to TRUE unless he requested to ignore the chip.
  1005.         fld1
  1006.         fldz
  1007.         fdiv    ; get infinity
  1008.         fld    st      ; Duplicate TOS.
  1009.         fchs
  1010.         fcompp    ; compare negative infinity with infinity.
  1011.         fstsw    ax  
  1012.         fwait
  1013.         sahf
  1014.         je    short no_8087 ; 387 says -inf <> +inf.  87/287 says they're equal.
  1015.         mov     byte ptr _387,1
  1016. no_8087:
  1017. endif ; no87
  1018.  
  1019. ifndef    NOWTK
  1020. ifdef    DOS
  1021. ;*******************************************************************************
  1022. ; Deal with Weitek 1167
  1023. ; Pharlap uses fs:; IGC uses ffc0_0000.
  1024. ; AIA with PharLap linker uses fs:
  1025. ; AIA with Lahey linker uses selector F8h we must load fs explicitly.
  1026. ;*******************************************************************************
  1027.  
  1028.         ; Early versions of the emc87 will hang if given weitek code.
  1029.     cmp    byte ptr _emc87,1
  1030.     je    Skip_all_weitek_processing
  1031.     ; No weitek with DOS4G
  1032.     cmp    env,D4G_ENV
  1033.     je      Skip_all_weitek_processing
  1034. seg_ldctx macro
  1035.     ;pop    fs:[0c000h]
  1036.     ; Until the assembler will allow address mode override, inline code a 1-byte-shorter move:
  1037.     db    67h,64h,8fh,06h,00,0c0h
  1038.     endm
  1039. seg_stctx macro
  1040.     db    67h,64h,0a1h,00h,0c4h    ; store context to eax.
  1041.     endm
  1042. flat_ldctx macro
  1043.     pop    ds:[0ffc0c000h]
  1044.     endm
  1045. flat_stctx macro
  1046.     pop    ds:[0ffc0c400h]
  1047.     endm
  1048.  
  1049.         ; For windows, we have to look for the chip, and set up fs if
  1050.         ; it is there.  A selector value for fs is put at ss:0 by the
  1051.         ; windows startup code.  We just move this selector into fs.
  1052.         cmp     _mwwind,1
  1053.         jne     start_test
  1054.         int     11h     ; get bios equipment list
  1055.         and     eax,01000000h   ; bit 24 set if weitek exists
  1056.         jz      Skip_all_weitek_processing
  1057.         mov     fs,ss:0
  1058.  
  1059. start_test:
  1060.  
  1061.         push     03ff0000h      ; truncate (1ff = round to nearest).
  1062.         push     30000000h      ; 
  1063.         push    0a0000000h      ; 1165 accum timer
  1064.         push     64000000h      ; 1164 accum timer
  1065.     push     16000000h      ; 1164/1165 flowthrough timer, 16 mhz
  1066.     push     98000000h    ; 20 mhz part init
  1067.     push     56000000h    ; 20 mhz part
  1068.     push    0b8000000h    ; test speed of chip.
  1069.     
  1070.     ; ldctx 1600_0000 1164/1165 flowthrough timer.
  1071.     ; ldctx 6400_0000 1164 accumulate timer.
  1072.     ; ldctx a000_0000 1165 accumulate timer.
  1073.     ; ldctx 3000_0000 reserved mode bits.
  1074.     ; ldctx 01ff_0000 rounding modes/exception mask.
  1075. ifdef    SG_exists
  1076.     cmp    env,SG_ENV
  1077.     jne    short next3
  1078.     cmp     byte ptr _1167,1
  1079.     jne     No_weitek
  1080.     flat_ldctx ; for test.
  1081.     flat_stctx ;    store context to eax.
  1082.     and     ah,80h
  1083.     jnz    short _20MHZ_part_flat
  1084.     pop    eax     ; Delete 20 mhz init stuff.
  1085.     pop    eax
  1086.     flat_ldctx
  1087.     jmp    short common_1167_flat
  1088. _20MHZ_part_flat:
  1089.     flat_ldctx
  1090.     flat_ldctx
  1091.     pop    eax    ; Kill the 16 mhz init.
  1092. common_1167_flat:
  1093.     flat_ldctx
  1094.     flat_ldctx
  1095.     flat_ldctx
  1096.     flat_ldctx
  1097.     flat_ldctx
  1098. next3:
  1099. endif   ; SG_exists
  1100.  
  1101. ifdef    PL_weitek
  1102.     ; Check that fs <> ds.  If so, Weitek installed at fs:.
  1103.     cmp    env,PL_ENV
  1104.     je    start_wtk
  1105.         cmp     env,AI_ENV
  1106.         je      start_wtk
  1107.     cmp    wind,1
  1108.     je    start_wtk
  1109.     add    esp,8*4 ; Get rid of the junk.
  1110.     jmp    next4
  1111. start_wtk:
  1112.     mov    ax,fs
  1113.     mov    bx,ds
  1114.     cmp    ax,bx
  1115.     je    short NW1
  1116.     and    ax,ax    ; If fs = 0 this was linked with Lahey linker.
  1117.     sete    Lahey_format_load_file
  1118.         jne     short go_ahead; if this isn't Lahey we are already (fs = weitek)
  1119.         mov     ax, 0F8h     ; test the f8 selector to see if it exists
  1120.         lar     bx, ax
  1121.         jnz     short NW1    ; if no then OS386 does not find a Weitek
  1122.         test    bh, 80h
  1123.         jz    short NW1    ; if f8 exists but present bit is not set
  1124.                      ; os386 does not find weitek    
  1125.         mov     fs, ax
  1126. go_ahead:
  1127.     mov    _1167,1
  1128.     ; Until the assembler will allow address mode override, inline code a 1-byte-shorter move:
  1129.     seg_ldctx ;    load ctx b8_000_000
  1130.     seg_stctx ;    store context to eax.
  1131.     and     ah,80h
  1132.     jnz    short _20MHZ_part
  1133.     pop    eax     ; Delete 20 mhz init stuff.
  1134.     pop    eax
  1135.     seg_ldctx
  1136.     jmp    short common_1167
  1137. NW1:    jmp    short No_weitek    
  1138. _20MHZ_part:
  1139.     seg_ldctx
  1140.     seg_ldctx
  1141.     pop    eax    ; Kill the 16 mhz init.
  1142. common_1167:    
  1143.     seg_ldctx
  1144.     seg_ldctx
  1145.     seg_ldctx
  1146.     seg_ldctx
  1147. next4:
  1148. endif   ; PL_weitek
  1149.     jmp    Finish_weitek
  1150. No_weitek:      
  1151.     add    esp,8*4 ; Get rid of the junk.
  1152.  
  1153. Skip_all_weitek_processing:
  1154. Finish_weitek:
  1155.  
  1156. endif  ; DOS
  1157. endif  ; NOWTK
  1158.  
  1159. ifdef    DOS
  1160. ;*******************************************************************************
  1161. ; Process environment area and parameter strings.
  1162. ;*******************************************************************************
  1163. Parm_string_offset = 80h        ; Offset in PSP containing parm string (len+bytes).
  1164. ifdef  SG_exists
  1165.     
  1166.         cmp     env,SG_ENV
  1167.         jne     short PL_PSP
  1168. ; GDA has pointer to PSP.  PSP has env seg, which, shifted left by 4,
  1169. ; yields the 32 bit address of the env.
  1170.     cld            ;All moves are forward
  1171.     mov     edi,[edx].GDA_PSPA    ; Get flat PSP address.
  1172.     mov    word ptr argp+Word_size,ds
  1173.     mov     dword ptr _psp,edi
  1174.     mov    word ptr _psp+Word_size,ds
  1175.     lea     eax,Parm_string_offset[edi]     ; eax = pso+edi.
  1176.     xor     ebx,ebx
  1177.     mov    bl,[eax]       ; Get length of parm string.
  1178.     mov    arglen,ebx
  1179.     inc    eax
  1180.     mov     dword ptr argp,eax    ; Addr of parm string.
  1181.     mov    bx,envptr[edi]    ; Get segment address of environment pointer.
  1182.     shl    ebx,4           ; Convert to 32-bit flat address.
  1183.     mov    dword ptr envp,ebx
  1184.     mov    word ptr envp+Word_size,ds    ; Fill out 48-bit address
  1185.     jmp    more_init2
  1186. PL_PSP: 
  1187. endif
  1188.  
  1189. if ePL_exists or eD4G_exists or eAI_exists
  1190.     cmp    env,PL_ENV
  1191.     je    short next5a
  1192.         cmp     env,AI_ENV
  1193.         je      short next5a
  1194.     cmp    env,D4G_ENV
  1195.     jne    next5
  1196. next5a:
  1197.     cmp    Lahey_format_load_file,1
  1198.     je      short ES_points_to_PSP_already
  1199.     mov    ax,PSPseg
  1200.     mov    bx,cs
  1201.     arpl    ax,bx
  1202.     mov    es,ax        ;Load es with psp address.
  1203.  
  1204.     ; Load environment segment into cx.
  1205.         mov    cx,ENVseg
  1206.         arpl    cx,bx
  1207.         jmp     short more 
  1208.  
  1209. ES_points_to_PSP_already:
  1210.     ; Load environment segment into cx.
  1211.     mov     cx,es:02ch
  1212.     mov     ax,es
  1213. more:
  1214.     mov    word ptr _psp+Word_size,ax      ; Construct 48-bit psp address.
  1215.         mov    word ptr escontents+Word_size,ax    ;No displacement
  1216.         mov    word ptr envp+Word_size,cx    ; Environment segment.
  1217.         xor    eax,eax
  1218.     mov    al,es:Parm_string_offset ;Length of parm string
  1219.     mov    arglen,eax
  1220.     mov    esi,Parm_string_offset+1
  1221.  
  1222. ; In C, the parameter string must be moved to a DS-accessible area
  1223. ; if small-data model.
  1224. ifdef    HC
  1225. ; Move the parm string into the stack so that it can be accessed by
  1226. ; small-data programs with only 16-bit pointers.
  1227.     add    eax,3
  1228.     and    al,0fch    ; Make sure eax is multiple of 4.
  1229.     sub    esp,eax    ; Length of parm string.
  1230.     mov    edi,esp    ; Move the parameter string here.
  1231.     mov    dword ptr argp,edi ; Save address of args.
  1232.     push    edx    ; Allow byte for parm string overwrite by C arg processor.
  1233.             ; but make stack word-aligned for efficiency.
  1234.     mov    ecx,eax    ; parameter length
  1235.     push    ds    ; Save it.
  1236.     push    es    ; source is es:esi
  1237.     pop    ds
  1238.     push    es    ; Save es.
  1239.     push    ss
  1240.     pop    es    ; Dest is ss:di.
  1241. ;    mov    esi,Parm_string_offset+1    ; Set up earlier.
  1242.     rep    movsb    ; es:di := parm string.
  1243.     pop    es
  1244.     pop    ds
  1245. else ; not eHC
  1246. ; Large-data or Pascal model; just store the address of the parms.
  1247.     mov    ax,word ptr escontents+Word_size
  1248.     mov    word ptr argp+Word_size,ax    
  1249.     mov    dword ptr argp,Parm_string_offset+1    ; Addr of parm string.    
  1250. endif   ; eHC
  1251. next5:
  1252. endif   ; ePL_exists
  1253.  
  1254. more_init2:
  1255.  
  1256. if    not eWINDOWS
  1257.         cmp     env,D4G_ENV    ; One doesn't shrink the heap in DOS4G.
  1258.         jne    short not_D4G2
  1259.  
  1260.     mov    eax,_top
  1261.     mov    _heaptop,eax    ; previous top of heap
  1262.         mov    _heaphi,eax     ; top of heap (empty)
  1263.     jmp    no_change
  1264.  
  1265. not_D4G2:
  1266.  
  1267. if ePL_exists
  1268.     cmp    env,PL_ENV
  1269.     jne    next6
  1270. ifndef    PHAR_LAP_CAN_GROW_HEAP    
  1271.     jmp     short no_change
  1272. else     
  1273.     ; Now free all of the heap, so that we allocate more only when necessary.
  1274. ifdef   ACAD
  1275.  
  1276. ifdef   PADI
  1277.         mov     ebx,_top                ; Get top of stack
  1278.         add     ebx,4095                ; Round it up a page
  1279.         shr     ebx,12                  ; Get number of pages
  1280.         push    ebx                     ; Store for later use
  1281.         push    ds
  1282.         pop     es
  1283.         mov     ah,SETBLOCK             ; Set PADI memory size to smallest #
  1284.         int     21h                     ;   of pages ecompassing top of stack
  1285.  
  1286.         mov     ebx,phys_adr            ; Get phys addr of pg w/ packet buffer
  1287.         mov     eax,250Ah
  1288.         mov     ecx,1
  1289.         int     21h                     ; Map pg w/ pkt buf to end of new PADI
  1290.                                         ;   memory block, above top of stack
  1291.         mov     cbufadr,eax             ; Store mapped offset as ptr to buf
  1292.  
  1293.         call    map_phys_mem            ; allow 3rd party a chance to map in
  1294.                                         ;   phys mem (returns # of pgs mapped)
  1295.         pop     ebx                     ; Get # of pgs to top of stack
  1296.         inc     ebx                     ; Add 1 for page mapped to end of seg
  1297.         add     ebx,eax                 ; Add add'l pgs mapped by 3rd party
  1298.         shl     ebx,12                  ; Get bottom of heap, in bytes
  1299.     dec     ebx
  1300.         mov     _heaptop,ebx
  1301.     and    ebx, 0fffffffch
  1302.         mov     _top,ebx                ; Assumption made _top is heap bottom
  1303. else    ; PADI
  1304.         mov     ebx,_top                ; Get top of stack
  1305.         add     ebx,4095                ; Round it up a page
  1306.         shr     ebx,12                  ; Get number of pages
  1307.         push    ebx                     ; Store for later use
  1308.         push    ds
  1309.         pop     es
  1310.         mov     ah,SETBLOCK             ; Set memory size to smallest #
  1311.         int     21h                     ;   of pages ecompassing top of stack
  1312.  
  1313.         call    map_phys_mem            ; Allow 3rd party a chance to map in
  1314.                                         ;   phys mem (returns # of pgs mapped)
  1315.         pop     ebx                     ; Get # of pgs to top of stack
  1316.         or      eax,eax                 ; Any pages mapped?
  1317.         jz      no_map
  1318.         add     ebx,eax                 ; If so, add it in
  1319.         shl     ebx,12                  ; Get bottom of heap, in bytes
  1320.     dec     ebx
  1321.         mov     _heaptop,ebx
  1322.     and    ebx, 0fffffffch
  1323.         mov     _top,ebx                ; Assumption made _top is heap bottom
  1324. no_map:
  1325. endif   ; PADI
  1326.  
  1327.         mov     ebx,min_mem             ; Initial size of heap
  1328. else    ; ACAD
  1329.     mov    ax,4
  1330.     mov    es,ax
  1331.     mov    ebx,es:[5ch]        ; Initial size of heap: load image size in bytes.
  1332. endif    ; ACAD
  1333.                                     ; See Phar Lap TN #21.
  1334.     jmp     short Free_up           
  1335. endif    
  1336. next6:
  1337. endif ; PL_exists
  1338.  
  1339. if eAI_exists
  1340.     cmp    env,AI_ENV
  1341.     jne    short next7
  1342.     mov    ebx,_top        ;top of stack in bytes
  1343. ifndef  AIA_CAN_GROW_HEAP
  1344.     cmp    Lahey_format_load_file,1
  1345.     jne     short no_change
  1346.     ; If Lahey format, we must be able to grow.
  1347. endif
  1348. next7:
  1349. endif ; AI_exists
  1350.  
  1351. if ePL_exists or eAI_exists
  1352. Free_up:
  1353.     add    ebx,4095        ; Round up to pages.
  1354.     shr     ebx,12                  ; Convert to 4K pages.
  1355.  
  1356. ifdef   ACAD
  1357. ifdef   PADI
  1358.         ; Initial heap size, set up in min_mem above with a minimum
  1359.         ; heap value that comes from the loader in AutoCAD, does not
  1360.         ; account for the extra page added on as a result of the page
  1361.         ; mapping done above to obtain access to a buffer common with
  1362.         ; AutoCAD.  Therefore, the number of pages for the initial
  1363.         ; heap size is increased by one.
  1364.  
  1365.         inc     ebx
  1366.  
  1367. endif   ; PADI
  1368.  
  1369.         ; Any additional pages mapped onto the segment as a result of
  1370.         ; calling map_phys_mem() above is added here.
  1371.  
  1372.         add     ebx,eax                 ; Add add'l pgs mapped by 3rd party
  1373. endif   ; ACAD
  1374.  
  1375.     inc    ebx              ; Add 1 page for initial heap.
  1376.  
  1377.     mov    edx,ebx                 ; compute heaphi
  1378.     shl    edx,12             
  1379.     dec     edx
  1380.  
  1381.     cmp    env,PL_ENV
  1382.     je     short No_para
  1383.     shl    ebx, 8            ; Convert pages to paragraphs for AIA.
  1384.     cmp    Lahey_format_load_file,1
  1385.     jne     short No_para     ; if AI_ENV and PL linker skip to allocation
  1386.                                   ; else must be AI_ENV and Lahey Linker so 
  1387.                                   ; we must grow the parent segment first
  1388. ;    call    grow_parent_segment
  1389. No_para:    
  1390.     push    ds
  1391.     pop     es                      ; Segment to free up.
  1392.     mov    ah,SETBLOCK         ; SETBLOCK to bx paragraphs from psp start.
  1393.     int     21h
  1394.     jc    short no_change         ; If couldn't get the extra page, oops!
  1395.     mov    _heaphi,edx
  1396. no_change:
  1397. endif ; PL_exists or AI_exists
  1398.  
  1399. doesnt_want_8087 macro
  1400. ; All this fuss just to print the NO87 string!
  1401. ifndef    no87
  1402.     push    eax
  1403.     push    edi    ; We're going to clobber these.
  1404.     cmp    _8087,0
  1405.     je    short no_print; No 87 exists on this machine; don't bother to print.
  1406.     cmp    wind,1
  1407.     je    short no_print
  1408.     mov    _8087,0 ; Set false.
  1409.     add    edi,5
  1410.     mov    esi,edi    ; Copy for later.
  1411.     mov    al,' '
  1412.     repe    scasb
  1413.     dec    edi
  1414.     cmp    byte ptr es:[edi],0     ; Did we get to end of string?
  1415.     je    short no_print
  1416.     mov    edi,esi    ; Now print the message, one character at a time.
  1417. again:    mov    dl,es:[edi]
  1418.     and    dl,dl
  1419.     je    short end_of_string
  1420.     mov    ah,6    ; Direct Console I/O.
  1421.     call    _mwint21    ; Print character.
  1422.     inc    edi
  1423.     jmp    again
  1424. end_of_string:
  1425.     mov    dl,0dh    ; \r\n.
  1426.     mov    ah,6
  1427.     call    _mwint21    ; Print character.
  1428.     mov    dl,0ah
  1429.     mov    ah,6
  1430.     call    _mwint21    ; Print character.
  1431. no_print:
  1432.     pop    edi
  1433.     pop    eax
  1434. endif    ; no87
  1435.     endm
  1436.  
  1437. Find_prog_name:
  1438. ;     -- Format of DOS environment:         VVV 3.x only VVV
  1439. ;     -- t1 nul t2 nul t3 nul ... tn nul nul x x program-name nul
  1440. ; Go to end of environment string to get program name for DOS 3.0.
  1441. ; While we're doing so, see if he said "NO87=" something, in which case,
  1442. ; mimicking Microsoft's emulator, we print the string (unless it's
  1443. ; nothing but blanks), and disable use
  1444. ; of the 80287 if the combination emulation/80287 library is linked in.
  1445.     les    edi,envp    ; Pointer to environment area.
  1446.     cmp     byte ptr es:[edi],0    ; No environment?
  1447.     je      no_environment_at_all
  1448.     xor    eax,eax        ; search for 0 byte.
  1449. Scan_again:
  1450.     cmp    dword ptr es:[edi],'78ON'   ; NO87
  1451.     jne    short not1
  1452.     cmp    byte ptr es:4[edi],'='   ; =
  1453.     jne    short not1
  1454.     doesnt_want_8087    ; Macro back-substituted here.
  1455. not1:    getminus1 ecx           ; Search lotsa bytes.
  1456.         repnz    scasb        ; Search for 0.
  1457. ; We MUST have found the 0 byte; we're positioned at the byte after.
  1458.     cmp    byte ptr es:[edi],0    ; Two 0 bytes in a row?
  1459.     jne    Scan_again    ; Nope, keep going.
  1460.  
  1461. ; Now we've found the environment area end.  +3 bytes later is the prog name.
  1462.     add    edi,3        ; Move to program name.
  1463.     cmp    _osmajor,3    ; Program name supplied by OS?
  1464.     jb      short NO_PNAME_AVAIL
  1465.     cmp     env,SG_ENV
  1466.     jne     short get_pname
  1467.     cmp     env,AI_ENV
  1468.     je      short get_pname
  1469.     ; IGC: pname is addressable.
  1470.     mov    dword ptr prognamep,edi
  1471.     mov    word ptr prognamep+Word_size,ds
  1472.     jmp    short _prog_name
  1473.  
  1474. NO_PNAME_AVAIL:
  1475. ; No program name.  Supply the null string.
  1476. ifdef    HC
  1477. ; Allocate the null byte on the stack right after the parms.
  1478.     xor    edx,edx
  1479.     push    edx        ; Null byte(s).
  1480.     mov    dword ptr prognamep,esp     ; Pointer to the program name.
  1481. endif
  1482.     jmp    short _prog_name
  1483.  
  1484. get_pname:
  1485. if      ePL_exists or eAI_exists
  1486.     cmp    env,PL_ENV
  1487.         je      next8a
  1488.         cmp     env,AI_ENV
  1489.         je      next8a
  1490.         jmp     next8
  1491. next8a:
  1492.  
  1493. ; In small-data C, the program name must be moved into the DS group.
  1494. ifdef    Small_data_HC        ; Move the program name to the stack.
  1495.     xor    eax,eax
  1496.     ; Find length of program name.
  1497.     getminus1 ecx
  1498.     mov    ebx,edi        ; Save starting address of name.
  1499.     repnz    scasb
  1500.     sub    edi,ebx        ; Length of name (including 0 trailer).
  1501.     lea     eax,3[edi]    ; Add some space on stack...
  1502.     and    eax,0fffch    ; Ensure mod 4 for nice value for SP.
  1503.     sub    esp,eax        ; Allocate space for name.
  1504.     mov    dword ptr prognamep,esp     ; Where the name will be put.
  1505.     mov    ecx,edi        ; Length of name
  1506.     mov    esi,ebx        ; Name is stored here.
  1507.     mov    edi,esp        ; Copy to here.
  1508.     push    ds
  1509.     mov    ds,word ptr envp+Word_size
  1510.     push    ss
  1511.     pop    es
  1512.     rep    movsb
  1513.     pop    ds
  1514. else
  1515.     ; Non-small data case:    just record the address.
  1516.     mov    dword ptr prognamep,edi
  1517.     mov    word ptr prognamep+Word_size,es
  1518. endif
  1519. next8:
  1520. endif
  1521.  
  1522. no_environment_at_all:
  1523. _prog_name:
  1524.  
  1525. ifdef HC
  1526.     ; Now allocate the space for the argv pointers.  One for the program name
  1527.     ; and one for each argument.  Although we don't know how many arguments there
  1528.     ; are, there can be at most 1 for every two characters of the environment
  1529.     ; string.
  1530.         mov     eax,arglen
  1531.         inc    eax
  1532.         shr    eax,1    ; Max arg ptrs for parameters
  1533.         inc    eax    ; Count the program name.
  1534.         inc    eax    ; ANSI requires argv[argc] = null pointer.
  1535.         shl    eax,2    ; Multiply by pointer size
  1536.         sub    esp,eax    ; Now allocate it.
  1537.         mov    dword ptr argvp,esp     ; sp is here.
  1538. endif    ; HC
  1539.  
  1540. endif    ; DOS
  1541.  
  1542. ;call file and user initialization, call main program
  1543.  
  1544.     assume_dgroup
  1545.     push    ds
  1546.     pop    es
  1547.     ; ss is already = ds.
  1548.     ; Since this is in Pascal, we must initialize ds first!
  1549. ;       call    init_interrupts
  1550.  
  1551. ; Phar lap asssembler won't take:
  1552. ;    pcall    finit ;initialize Pascal file system.
  1553.  
  1554.     mov    ebx,offset ds:__mwifc
  1555.     mov    ecx,offset ds:__mwilc
  1556.     sub    ecx,ebx
  1557. mustcall:    or    ecx,ecx
  1558.     jz    mustdone
  1559.     mov    edi,[ebx]
  1560.     add    ebx,4
  1561.     sub    ecx,4
  1562.     ifndef    Small_code
  1563.     mov    esi,[ebx]
  1564.     add    ebx,2
  1565.     sub    ecx,2
  1566.     endif
  1567.     or    edi,edi
  1568.     jz    mustcall
  1569.     push    ebx
  1570.     push    ecx
  1571.     ifdef    Small_code
  1572.     call    edi
  1573.     else
  1574.     push    edi
  1575.     push    esi
  1576.     mov    ebx,sp
  1577.     call    dword ptr [ebx]
  1578.     pop    ecx
  1579.     pop    ecx
  1580.     endif
  1581.     pop    ecx
  1582.     pop    ebx
  1583.     jmp    mustcall
  1584.  
  1585. mustdone:
  1586.  
  1587.     pcall    _mwfinit ;initialize Pascal file system.
  1588.     pcall    cfinit        ;initialize C file system.
  1589. if eHC and not eWINDOWS
  1590. ; In preparation for calling main, push addr of argv.
  1591.  
  1592. ifndef    Small_data
  1593.     push    word ptr Argvp+2    ; push segment
  1594. endif    ; Small_data
  1595.     push    dword ptr argvp    ; Push offset.
  1596.     sub    eax,eax        ; In case he supplies dummy routine:  argc = 0.
  1597.     pcall    set_up_args    ; Find argv values by scanning argument string.
  1598.     push    eax        ; Push computed ArgC.
  1599. endif   ; HC and not WINDOWS
  1600.  
  1601. ifdef    DOS
  1602. ; Now check if he used the 1167, but it doesn't exist.
  1603. _MW1167_USED1 segment common byte 'DATA'
  1604. magic6  dw    1 dup(?)    ; Not initialized.
  1605. offoops6 dd    1 dup(?)    ; Not initialized.
  1606. oopsptr6 dd     1 dup(?)        ; Not initialized.
  1607. _MW1167_USED1 ends
  1608.     cmp    byte ptr _1167,1 
  1609.     je     short OK3             ; If 8087 there, no further checking needed.
  1610.     cmp    magic6,0abcdh
  1611.     jne    short OK3
  1612.     mov    eax,oopsptr6
  1613.     cmp    eax,offoops6
  1614.     jne    short OK3
  1615.     mov     edx,oopsptr6
  1616.     jmp    short more_message
  1617. OK3:
  1618. ; Now check if he used the Cyrix EMC 87, but it doesn't exist.
  1619. _MWEMC_USED1 segment common byte 'DATA'
  1620. magic7  dw    1 dup(?)    ; Not initialized.
  1621. offoops7 dd    1 dup(?)    ; Not initialized.
  1622. oopsptr7 dd     1 dup(?)        ; Not initialized.
  1623. _MWEMC_USED1 ends
  1624. DGROUP group _MWEMC_USED1    ; Helps multiseg links.
  1625.     cmp    byte ptr _emc87,1 
  1626.     je     short OK4             ; If 8087 there, no further checking needed.
  1627. if    not eUSING_FLAT    
  1628.     cmp    DGROUP:magic7,0abcdh
  1629.     jne    short OK4
  1630.     mov    eax,DGROUP:oopsptr7
  1631.     cmp    eax,DGROUP:offoops7
  1632.     jne    short OK4
  1633.     mov     edx,DGROUP:oopsptr7
  1634. else
  1635.     cmp    magic7,0abcdh
  1636.     jne    short OK4
  1637.     mov    eax,oopsptr7
  1638.     cmp    eax,offoops7
  1639.     jne    short OK4
  1640.     mov     edx,oopsptr7
  1641. endif    
  1642.     jmp    short more_message
  1643. OK4:
  1644. ; Now check if he used the 8087, but it doesn't exist.
  1645. ; Here is how we determine if he dragged in fltused from the library:
  1646. ; magic will have a "magic" value, and offoops will have the offset of
  1647. ; the "oops" message.  If _mw87_used is not hauled in, magic and offoops
  1648. ; will be 0 when using all linkers under MS-DOS; on the Intel linkers 
  1649. ; they wil be garbage and WE HOPE THAT the fields won't accidentally  
  1650. ; look correct.  This is not foolproof, therefore, with linkers that don't  
  1651. ; zero out unitialized memory,  but it is much
  1652. ; cheaper than checking in the RTL for the 8087 presence for each 8087 
  1653. ; operator invoked.  I WISH OMF provided a "segment length"
  1654. ; fixup; then this could be made foolproof.
  1655. _MW87_USED1 segment common byte 'DATA'
  1656. magic   dw    1 dup(?)    ; Not initialized.
  1657. offoops dd    1 dup(?)    ; Not initialized.
  1658. oopsptr dd      1 dup(?)        ; Not initialized.
  1659. _MW87_USED1 ends
  1660.  
  1661.     cmp    byte ptr _8087,1 
  1662.     je     short OK              ; If 8087 there, no further checking needed.
  1663.     cmp    magic,0abcdh
  1664.     jne    short OK
  1665.     mov    eax,oopsptr
  1666.     cmp    eax,offoops
  1667.     jne    short OK
  1668.     mov     edx,oopsptr 
  1669. more_message:
  1670.     cmp    wind,1
  1671.     je    windchipmsg
  1672.     mov    ah,9
  1673.     call    _mwint21
  1674.     jmp     Quit
  1675. OK:     ; Did he require 387, and is it here?
  1676. _MW387_USED1 segment common byte 'DATA'
  1677. magic3  dw    1 dup(?)    ; Not initialized.
  1678. _MW387_USED1 ends
  1679.     cmp    byte ptr _387,1
  1680.     je      short OK2
  1681.     cmp     magic3,0abcdh
  1682.     jne     short OK2
  1683.     cmp    wind,1
  1684.     je    windchipmsg
  1685.     ; He used it, but it's not present.
  1686.     mov     edx,cs:oops3ptr 
  1687.     mov    ah,9
  1688.     call    _mwint21
  1689.     mov    edx,oopsptr
  1690.     add    edx,10    ; Skip past "8087/80287".
  1691.     jmp    more_message
  1692.  
  1693. windchipmsg:
  1694.     mov    printnochipmsg,1
  1695.     jmp    OK2
  1696.  
  1697. _387msg db      '80387','$'
  1698. oops3ptr dd     offset _387msg
  1699.  
  1700. OK2:    
  1701.     
  1702. endif    
  1703.  
  1704. if eWINDOWS
  1705.     extrn   _cinit:near
  1706.     call    _cinit
  1707.     db    0cbh
  1708.  
  1709. else
  1710.         jmp    Init_return
  1711. endif
  1712.  
  1713. fp_init_cw dw 03FFH       ; For initializing 8087/287.
  1714. fp_init_cw_emc dw 83FFH       ; For initializing EMC 87.
  1715.     ; The 8000 is for testing presence of EMC 87 part.
  1716.     assume    es:nothing
  1717. endif
  1718. INIT    endp
  1719.  
  1720. init_const proc
  1721.     publab init_const
  1722.     prolog
  1723.     assume_dgroup
  1724. ;    initialize constants ... may be called from init,
  1725. ;       or from WINDOWS environment initializer
  1726.  
  1727. ;    determine DOS version number
  1728.     push    eax
  1729.         xor     eax,eax
  1730.         mov     ah,30h        ; Get DOS version number
  1731.     call    _mwint21
  1732.         mov     word ptr _osmajor,ax    ; Moves minor (AH) and major (AL).
  1733.     mov    osver,eax    ; also save full version locally
  1734.     pop    eax
  1735.  
  1736.     epilog
  1737. init_const endp
  1738.  
  1739. if    AIA_CAN_GROW_HEAP
  1740. grow_parent_segment proc near    
  1741.         push    ebx             ; save regs that get altered
  1742.         push    edi
  1743.         push    es
  1744.  
  1745.         push    ebx             ; save paras - we need BX for OS386 call
  1746.         push    edx        ; this int 21 trashes edx
  1747.         mov     ax, 0ED00h      ; get info on segment which is to be grown
  1748.         mov     bx, ds
  1749.         call    _mwint21             
  1750.         pop    edx        ; restore edx
  1751.         pop     ebx             ; DI now contains parent segment for DGROUP
  1752.  
  1753.         mov     es, di          ; now shrink this segment to paras in EBX
  1754.         mov     ah, SETBLOCK
  1755.         call    _mwint21
  1756.  
  1757.         pop    es
  1758.         pop     edi        ; restore regs
  1759.         pop     ebx
  1760.         ret
  1761. grow_parent_segment endp
  1762. endif
  1763.  
  1764. if eWINDOWS
  1765.  
  1766. clear_bss proc
  1767.     publab    clear_bss
  1768.     prolog eax,ecx,edi
  1769.  
  1770.     assume_dgroup
  1771.  
  1772.     extrn    _edata:near
  1773.     extrn    _end:near
  1774.  
  1775.     xor    eax,eax
  1776.       mov    edi,offset ds:_edata
  1777.       mov    ecx,offset ds:_end
  1778.     sub    ecx,edi
  1779.     
  1780.     shr ecx,1
  1781.     rep stosw
  1782.     adc ecx,ecx
  1783.     rep stosb
  1784.     epilog
  1785. clear_bss endp
  1786.  
  1787. call_onentry_fcns proc
  1788.     publab call_onentry_fcns
  1789.     extrn   _init_environ:near
  1790.     call    _init_environ
  1791.     return
  1792. call_onentry_fcns endp
  1793.  
  1794. endif
  1795.  
  1796. expand_heap proc far
  1797.  
  1798. ;   The heap manager calls this routine to request memory from the heap.
  1799. ;   The expansion expands allocates more memory starting at _heaphi.
  1800. ;   Record the new top-of-heap in _heaphi.
  1801.  
  1802. heap_info    struc
  1803. request            dd    ?          ; size, in bytes, of request
  1804. allocated    dd    ?          ; size, in bytes, of allocated memory
  1805. virtbase    dd    ?          ; ptr to allocated memory
  1806. heap_info    ends
  1807.  
  1808.     publab    expand_heap
  1809.     prolog
  1810.     mov    edx,8[ebp]
  1811.     mov     [edx].allocated,0      ; assume we're not successful
  1812.  
  1813.         mov    eax,[edx].request      ; round request up to nearest page
  1814.     add    eax,4095
  1815.     and     eax,0fffff000h
  1816.     mov     [edx].request,eax
  1817.  
  1818.         mov     ebx,_heaphi            ; our upper-bounds
  1819.     sub     ebx,_heaptop           ; space left in heap
  1820.     cmp     eax,ebx                ; is it big enough?
  1821.     jg      short get_more
  1822.  
  1823.     mov     [edx].allocated,ebx    ; we've got room!!
  1824.     mov     eax,_heaptop           ; compute start of new user heap
  1825.     inc     eax  
  1826.     mov     [edx].virtbase,eax
  1827.     dec     eax                    ; compute new heaptop
  1828.     add     eax,ebx
  1829.     mov     _heaptop,eax 
  1830.     jmp     return_from_expand
  1831.  
  1832. get_more:
  1833. if eD4G_exists
  1834.         cmp     env,D4G_ENV
  1835.       jne    not_dos4g
  1836.  
  1837. ;       ***********************
  1838. ;       *                     *
  1839. ;       *       DOS4G         *
  1840. ;       *                     *
  1841. ;       ***********************
  1842.         mov    ebx,[edx].request       ; 64k minimum
  1843.     cmp    ebx,0ffffh            
  1844.     jg    short whole_chunk
  1845.     mov    ebx,010000h          
  1846.  
  1847. whole_chunk:
  1848.     mov    [edx].request,ebx       ; Total we ask for in the int31.
  1849.         shrd    ecx,ebx,16    
  1850.         shr    ecx,16
  1851.     shr    ebx,16
  1852.         mov    ax,0501h
  1853.         int    31h
  1854.     jc    return_from_expand
  1855.  
  1856.     ; Answer comes back in bx:cx.
  1857.     shl    ebx,16
  1858.     mov    bx,cx                ; Form 32-bit address in ebx.
  1859.     mov    [edx].virtbase,ebx
  1860.     mov    ecx,[edx].request       ; amount requested
  1861.     mov     [edx].allocated,ecx     ; is amount allocated
  1862.     add    ecx,ebx                ; add virtual base
  1863.     mov    _heaptop,ecx            ; user top of heap
  1864.     mov    _heaphi,ecx            ; same as system top of heap
  1865.  
  1866.      jmp    return_from_expand
  1867. endif   ;  D4G_exists
  1868.  
  1869. not_dos4g:
  1870. ;       ***********************
  1871. ;       *                     *
  1872. ;       *     NOT DOS4G       *
  1873. ;       *                     *
  1874. ;       ***********************
  1875.  
  1876.         ; Has the user shut off heap expansion?  
  1877.         cmp    heap_expansion_enabled,CANT_EXPAND
  1878.         je    return_from_expand
  1879.         cmp     env,PL_ENV
  1880.  
  1881. ifndef  PHAR_LAP_CAN_GROW_HEAP
  1882.     je      return_from_expand ; Must have release >= 1.1t.
  1883. else
  1884.     je    short Can_grow    
  1885. endif   
  1886.  
  1887. ifndef    AIA_CAN_GROW_HEAP
  1888. ;       If Lahey format, we must be able to grow.
  1889.     cmp    Lahey_format_load_file,1
  1890.     jne     short return_from_expand
  1891. else    
  1892.     cmp     env,AI_ENV
  1893.     jne    return_from_expand
  1894. endif   
  1895.  
  1896. Can_grow:
  1897. if not eWINDOWS
  1898.         mov    ax,ds                   ; see if heaphi has changed
  1899.         lsl    eax,eax
  1900.     cmp    _heaphi,eax
  1901.     je    short heap_ok
  1902.         mov     _heaptop,eax            ; reset pointers if it has
  1903.     mov     _heaphi,eax
  1904.  
  1905. heap_ok:
  1906.     mov     eax,_heaptop            ; next page starts on next byte
  1907.     inc     eax
  1908.     mov     [edx].virtbase,eax      ; new user heap will start here
  1909.  
  1910.         inc     eax                     ; size = offset + 1
  1911.     add     eax,[edx].request       ; add in request
  1912.     mov     _totsiz,eax              ; save totalsize
  1913.  
  1914.     shr    eax,12                  ; convert to pages
  1915.     cmp     env,AI_ENV
  1916.     jne    short pages
  1917.     shl    eax,8                ; convert pages to paragraphs for AI.
  1918.  
  1919.     ; if AI_ENV and PL linker skip to allocation
  1920.         ; else must be AI_ENV and Lahey Linker so 
  1921.         ; we must grow the parent segment first
  1922.     cmp    Lahey_format_load_file,1
  1923.     jne     short pages     
  1924.         call    grow_parent_segment
  1925.  
  1926. pages:    
  1927.     mov     ebx,eax                 ; prepare for INT 21h
  1928.     mov    ah,SETBLOCK
  1929.     call    _mwint21
  1930.     jc    short return_from_expand
  1931.  
  1932.     mov     eax,[edx].request       ; amount requested
  1933.     mov     [edx].allocated,eax     ; is amount allocated
  1934.  
  1935.     mov     eax,_totsiz              ; retrieve total size
  1936.     dec     eax                     ; convert to offset
  1937.     mov     _heaphi,eax             ; update pointers
  1938.     mov     _heaptop,eax
  1939. endif
  1940.  
  1941. return_from_expand:
  1942.     epilog    4
  1943. expand_heap endp    
  1944.  
  1945. ;
  1946. ;**************************************************************************
  1947. ;    function ss: Cardinal; {Returns paragraph address of stack segment
  1948. ;**************************************************************************
  1949. ;
  1950. ssx    proc    far
  1951.     publab    ss
  1952.     mov    ax,ss
  1953.     return
  1954. ssx    endp
  1955.  
  1956. ;**************************************************************************
  1957. ;    function Getds: Cardinal;    -- Returns ds register.
  1958. ;**************************************************************************
  1959. ;    This function may actually no longer be needed.
  1960.  
  1961. ifdef    Small_data
  1962. getds    proc    far
  1963.     publab    getds    ; return ds register.
  1964.     mov    ax,ds
  1965.     return
  1966. getds    endp
  1967. endif
  1968.  
  1969. dos_exit proc    far
  1970.     publab dos_exit
  1971.     mov     al,8[ebp]
  1972.     mov    ah,4ch
  1973.     call    _mwint21
  1974. dos_exit endp
  1975.  
  1976. ?INIT    ends
  1977.     end     genesis
  1978.