home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / caway349.zip / SOURCE / ALL / CW32.ASM < prev    next >
Assembly Source File  |  1999-12-30  |  99KB  |  4,995 lines

  1. ;
  2. ;CauseWay v2 main file.
  3. ;
  4. ;
  5. ;Things to note:
  6. ;
  7. ;The IDT has a page to itself even though it only needs 2k. For RAW/VCPI systems
  8. ;the top 2k could be used for something else.
  9. ;
  10. ;Things to do:
  11. ;
  12. ;Put in some sort of system stack overflow checking and terminate the program
  13. ;if it happens.
  14. ;
  15.     option oldstructs
  16.  
  17.     include general.inc
  18.     include strucs.inc
  19.     include cw.inc
  20. ;    include cw-undoc.inc
  21.  
  22.     ifndef ENGLISH
  23. ENGLISH    equ    0
  24.     endif
  25.     ifndef SPANISH
  26. SPANISH    equ    0
  27.     endif
  28.  
  29. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  30. ;
  31. ;Main code segment. This takes care of calling the right initialisation routines
  32. ;and generaly getting everything rolling.
  33. ;
  34. _cwMain    segment para public 'Main thread' use16
  35.     assume cs:_cwMain, ds:_cwMain, ss:_cwStack
  36. ;
  37. ;Want a copyright message embedded first.
  38. ;
  39. Copyright    label byte
  40.     db 'CauseWay DOS Extender v'
  41. VersionMajor    db '3.'
  42. VersionMinor    db '49'
  43.     db " Copyright 1992-99 Michael Devore.",13,10,"All rights reserved.",13,10,0
  44.  
  45.  
  46.     .386
  47. ;-------------------------------------------------------------------------------
  48. ;
  49. ;Final init stuff.
  50. ;
  51. cwOpen    proc    near
  52.     assume ds:nothing        ;make our data addresable.
  53.     mov    ds,cs:DataSegment
  54.     assume ds:_cwMain
  55.     ;
  56.     mov    d[TerminationHandler],offset cwClose
  57.     mov    w[TerminationHandler+4],cs
  58. ;
  59. ;Now we know the machines details, re-size the program
  60. ;block again to release as much memory as possible.
  61. ;
  62.     mov    edi,offset Int21Buffer
  63.     push    ds
  64.     pop    es
  65.     mov    ax,RealPSPSegment
  66.     mov    es:Real_ES[edi],ax
  67.     mov    bx,_cwDPMIEMU
  68.     cmp    ProtectedType,2
  69.     jnz    @@KeepRaw
  70.     mov    bx,_cwRaw
  71. @@KeepRaw:    sub    bx,ax        ;Size program.
  72.     inc    bx
  73.     mov    TSRSize,bx
  74.     mov    es:Real_EBX[edi],ebx
  75.     mov    es:Real_EAX[edi],4a00h
  76.     mov    bl,21h
  77.     mov    ErrorNumber,1
  78.     sys    IntXX
  79.     test    es:w[edi+Real_Flags],1
  80.     jnz    @@9
  81.     mov    ErrorNumber,0    ;clear error number.
  82. ;
  83. ;Force accurate memory values.
  84. ;
  85.     or    ecx,-1
  86.     sys    GetMemLinear32
  87. ;
  88. ;Enable resource tracking and MCB allocations.
  89. ;
  90.     or    ResourceTracking,-1    ;Enable resource tracking.
  91. ;
  92. ;Run the main program.
  93. ;
  94.     mov    edx,offset MainExec    ;name to exec.
  95.     mov    esi,80h
  96.     mov    es,PSPSegment
  97.     xor    cx,cx
  98.     sys    cwExec        ;run the bugger.
  99.     jnc    @@8
  100.     add    ax,10-1        ;convert error number.
  101.     mov    ErrorNumber,ax
  102.     jmp    @@9
  103. @@8:    cmp    DebugDump,0
  104.     jnz    @@9
  105.     mov    ErrorLevel,ax    ;store programs error level.
  106.     mov    ErrorNumber,0    ;clear error number.
  107. @@9:    jmp    cwClose
  108. cwOpen    endp
  109.  
  110.  
  111. ;-------------------------------------------------------------------------------
  112. ;
  113. ;Shut everything down.
  114. ;
  115. cwClose    proc    near
  116.  
  117. IFDEF DEBUG4
  118.     push    eax
  119.     push    ebx
  120.     push    ecx
  121.     push    edx
  122.     push    ds
  123.     push    cs
  124.     pop    ds
  125.     mov    edx,OFFSET debugatext1
  126. debugaloop2:
  127.     cmp    BYTE PTR ds:[edx],0
  128.     je    debugab
  129.     mov    ecx,1
  130.     mov    bx,1
  131.     mov    ah,40h
  132.     int    21h
  133.     inc    edx
  134.     jmp    debugaloop2
  135. debugab:
  136.     mov    edx,OFFSET debugatext2
  137.     push    cs
  138.     pop    ds
  139.     mov    ecx,2
  140.     mov    bx,1
  141.     mov    ah,40h
  142.     int    21h
  143.     pop    ds
  144.     pop    edx
  145.     pop    ecx
  146.     pop    ebx
  147.     pop    eax
  148.     jmp    debugaout
  149.  
  150. debugatext1    DB    'Entering cwClose...',0
  151. debugatext2    DB    13,10
  152.  
  153. debugaout:
  154.     push    ecx
  155.     mov    ecx,100000h
  156. debugaloop:
  157. ;    dec    ecx
  158. ;    jne    debugaloop
  159.     pop    ecx
  160. ENDIF
  161.  
  162.     assume ds:nothing
  163.     mov    ds,cs:DataSegment
  164.     assume ds:_cwMain
  165.     ;
  166.     mov    ResourceTracking,0
  167.     mov    mcbAllocations,0
  168.     sti
  169.     mov    w[TerminationHandler+4],0
  170.     ;
  171.  
  172. IFDEF DEBUG4
  173.     push    eax
  174.     push    ebx
  175.     push    ecx
  176.     push    edx
  177.     push    ds
  178.  
  179.     mov    dx,w[ExceptionExtension+12]
  180. ;    lar    ax,dx
  181.     cmp    dx,127h
  182.     jnz    debughout
  183. ;    and    ah,3
  184. ;    cmp    ah,3
  185. ;    jne    debughout
  186.  
  187.     push    cs
  188.     pop    ds
  189.     mov    edx,OFFSET debughtext1
  190. debughloop2:
  191.     cmp    BYTE PTR ds:[edx],0
  192.     je    debughb
  193.     mov    ecx,1
  194.     mov    bx,1
  195.     mov    ah,40h
  196.     int    21h
  197.     inc    edx
  198.     jmp    debughloop2
  199. debughb:
  200.     mov    edx,OFFSET debughtext2
  201.     push    cs
  202.     pop    ds
  203.     mov    ecx,2
  204.     mov    bx,1
  205.     mov    ah,40h
  206.     int    21h
  207.     pop    ds
  208.     pop    edx
  209.     pop    ecx
  210.     pop    ebx
  211.     pop    eax
  212.     jmp    debughout
  213.  
  214. debughtext1    DB    'Calling DebugDisplay...',0
  215. debughtext2    DB    13,10
  216.  
  217. debughout:
  218.     push    ecx
  219.     mov    ecx,100000h
  220. debughloop:
  221. ;    dec    ecx
  222. ;    jne    debughloop
  223.     pop    ecx
  224.  
  225. ENDIF
  226.  
  227.     push    cs
  228.     push    offset @@dd0
  229.     push    w[ExceptionExtension+12]
  230.     mov    eax,offset DebugDisplay
  231.     push    ax
  232.     retf
  233. @@dd0:    ;
  234.  
  235.     cmp    ErrorNumber,0
  236.     jz    @@NoError
  237.  
  238.     mov    ax,ErrorNumber    ;Get the error number.
  239.     xor    dx,dx
  240.     mov    cx,10
  241.     div    cx
  242.     add    al,'0'
  243.     mov    b[ErrorM00n],al
  244.     add    dl,'0'
  245.     mov    b[ErrorM00n+1],dl
  246.  
  247.     cmp    EnableDebugDump,0    ; if debug dump turned off, no screen i/o
  248.     je    @@NoError
  249.  
  250.     xor    edx,edx
  251.     mov    dx,w[ErrorList]
  252.     mov    ah,9
  253.     int    21h
  254. ;
  255. ;Get a pointer to the appropriate error message and print it.
  256. ;
  257.     mov    bx,ErrorNumber
  258.     add    bx,bx
  259.     xor    edx,edx
  260.     mov    dx,[ErrorList+bx]
  261.     mov    ah,9
  262.     int    21h
  263. ;
  264. ;Now exit with the error number as the DOS "errorlevel".
  265. ;
  266. @@NoError:
  267. ;
  268. ;Remove extension patches.
  269. ;
  270.  
  271. IFDEF DEBUG4
  272.     push    eax
  273.     push    ebx
  274.     push    ecx
  275.     push    edx
  276.     push    ds
  277.     push    cs
  278.     pop    ds
  279.     mov    edx,OFFSET debugctext1
  280. debugcloop2:
  281.     cmp    BYTE PTR ds:[edx],0
  282.     je    debugcb
  283.     mov    ecx,1
  284.     mov    bx,1
  285.     mov    ah,40h
  286.     int    21h
  287.     inc    edx
  288.     jmp    debugcloop2
  289. debugcb:
  290.     mov    edx,OFFSET debugctext2
  291.     push    cs
  292.     pop    ds
  293.     mov    ecx,2
  294.     mov    bx,1
  295.     mov    ah,40h
  296.     int    21h
  297.     pop    ds
  298.     pop    edx
  299.     pop    ecx
  300.     pop    ebx
  301.     pop    eax
  302.     jmp    debugcout
  303.  
  304. debugctext1    DB    'Removing interrupt patches...',0
  305. debugctext2    DB    13,10
  306.  
  307. debugcout:
  308.     push    ecx
  309.     mov    ecx,100000h
  310. debugcloop:
  311. ;    dec    ecx
  312. ;    jne    debugcloop
  313.     pop    ecx
  314. ENDIF
  315.  
  316.     mov    di,offset ExtensionList    ;list of interupt patches.
  317. @@p1:    cmp    w[di+2],-1        ;search for the end of the table so we can restore
  318.     jz    @@p0        ;vectors in reverse order.
  319.     add    di,2
  320.     jmp    @@p1
  321.     ;
  322. @@p0:    mov    bp,w[di]
  323.     cmp    ds:w[bp+32],-1    ;installed?
  324.     jnz    @@p2
  325.     pushm    di,bp
  326.     push    cs
  327.     push    offset @@p3
  328.     push    ds:w[bp+20]
  329.     push    ds:w[bp+16]
  330.     retf
  331. @@p3:    popm    di,bp
  332. @@p2:    sub    di,2
  333.     cmp    di,offset ExtensionList-2
  334.     jnz    @@p0
  335. ;
  336. ;Remove api exception patches.
  337. ;
  338.     cmp    apiExcepPatched,0
  339.     jz    @@pe0
  340.     mov    ax,cs
  341.     push    ax
  342.     mov    ax,offset @@pe0
  343.     push    ax
  344.     mov    ax,apiCodeSeg
  345.     push    ax
  346.     mov    eax,offset UnPatchExc
  347.     push    ax
  348.     retf
  349. @@pe0:    ;
  350. ;
  351. ;Remove the API patch.
  352. ;
  353.     mov    es,apiDataSeg
  354.     assume es:_apiCode
  355.     test    SystemFlags,1
  356.     jz    @@Use32
  357.     mov    dx,es:w[OldIntSys]
  358.     mov    cx,es:w[OldIntSys+2]
  359.     jmp    @@Use0
  360. @@Use32:    mov    edx,es:d[OldIntSys]
  361.     mov    cx,es:w[OldIntSys+4]
  362. @@Use0:    mov    bl,31h
  363.     mov    ax,205h
  364.     int    31h
  365.     mov    es:d[cwIdentity],0
  366.     mov    es:d[cwIdentity+4],0
  367.     assume es:nothing
  368.     ;
  369. @@noAPI:
  370.     cmp    ProtectedType,2    ;DPMI?
  371.     jz    @@DPMI
  372.  
  373. IFDEF DEBUG4
  374.     push    eax
  375.     push    ebx
  376.     push    ecx
  377.     push    edx
  378.     push    ds
  379.     push    es
  380.     mov    ax,KernalZero
  381.     mov    es,ax
  382.     mov    ebx,0b8000h
  383.     mov    BYTE PTR es:[ebx],'1'
  384.     push    cs
  385.     pop    ds
  386.     mov    ecx,OFFSET debugdtext1
  387. debugdloop2:
  388.     cmp    BYTE PTR ds:[ecx],0
  389.     je    debugdb
  390.     mov    dl,ds:[ecx]
  391.     mov    ah,2
  392.     int    21h
  393.     inc    ecx
  394.     jmp    debugdloop2
  395. debugdb:
  396.     mov    dl,13
  397.     mov    ah,2
  398.     int    21h
  399.     mov    dl,10
  400.     mov    ah,2
  401.     int    21h
  402.     pop    es
  403.     pop    ds
  404.     pop    edx
  405.     pop    ecx
  406.     pop    ebx
  407.     pop    eax
  408.     jmp    debugdout
  409.  
  410. debugdtext1    DB    'Making raw addressable...',0
  411. debugdtext2    DB    13,10
  412.  
  413. debugdout:
  414.     push    ecx
  415.     mov    ecx,100000h
  416. debugdloop:
  417.     dec    ecx
  418.     jne    debugdloop
  419.     pop    ecx
  420. ENDIF
  421.  
  422. ;
  423. ;Make RAW stuff addressable.
  424. ;
  425.     cli            ;Don't want interrupts interfering.
  426.     mov    ax,KernalDS        ;Get supervisor data descriptor,
  427.     mov    ds,ax        ;DS,ES,FS,GS,SS must be data with 64k limit
  428.     assume ds:_cwRaw
  429.     mov    ax,KernalZero
  430.     mov    es,ax
  431. ;
  432. ;Switch to RAW exit code.
  433. ;
  434.     push    _cwMain
  435.     push    offset @@6
  436.     mov    ax,KernalCS
  437.     push    ax
  438.     mov    ax,offset RawVCPIRealMode
  439.     push    ax
  440.     retf
  441. @@6:    jmp    @@RealMode
  442. ;
  443. ;Remove DPMI stuff.
  444. ;
  445. @@DPMI:
  446.  
  447. IFDEF DEBUG4
  448.     push    eax
  449.     push    ebx
  450.     push    ecx
  451.     push    edx
  452.     push    ds
  453.     push    cs
  454.     pop    ds
  455.     mov    ecx,OFFSET debugetext1
  456. debugeloop2:
  457.     cmp    BYTE PTR ds:[ecx],0
  458.     je    debugeb
  459.     mov    dl,ds:[ecx]
  460.     mov    ah,2
  461.     int    21h
  462.     inc    ecx
  463.     jmp    debugeloop2
  464. debugeb:
  465.     mov    dl,13
  466.     mov    ah,2
  467.     int    21h
  468.     mov    dl,10
  469.     mov    ah,2
  470.     int    21h
  471.     pop    ds
  472.     pop    edx
  473.     pop    ecx
  474.     pop    ebx
  475.     pop    eax
  476.     jmp    debugeout
  477.  
  478. debugetext1    DB    'Removing DPMI setup...',0
  479. debugetext2    DB    13,10
  480.  
  481. debugeout:
  482.     push    ecx
  483.     mov    ecx,100000h
  484. debugeloop:
  485.     dec    ecx
  486.     jne    debugeloop
  487.     pop    ecx
  488. ENDIF
  489.  
  490.     assume ds:nothing
  491.     mov    ds,cs:DataSegment
  492.     assume ds:_cwMain
  493.  
  494.     if    0
  495.     cmp    d[OldInt21hExec],0
  496.     jz    @@d0
  497.     mov    bl,21h
  498.     mov    dx,w[OldInt21hExec]
  499.     mov    cx,w[OldInt21hExec+2]
  500.     mov    ax,201h
  501.     int    31h
  502. @@d0:    movzx    edx,dx
  503.     endif
  504.  
  505.     jmp    @@InRealMode
  506. ;
  507. ;Make sure our data is addressable.
  508. ;
  509. @@RealMode:    mov    ax,_cwMain
  510.     mov    ds,ax
  511.     assume ds:_cwMain
  512. ;
  513. ;Display the "CauseWay error: ??" bit.
  514. ;
  515. @@InRealMode:
  516.  
  517.     if    0
  518.     cmp    ErrorNumber,0
  519.     jz    @@NoError
  520.  
  521.     push    ax
  522.     mov    al,3
  523.     call    bordm
  524.     pop    ax
  525.  
  526.     mov    ax,ErrorNumber    ;Get the error number.
  527.     xor    dx,dx
  528.     mov    cx,10
  529.     div    cx
  530.     add    al,'0'
  531.     mov    b[ErrorM00n],al
  532.     add    dl,'0'
  533.     mov    b[ErrorM00n+1],dl
  534.  
  535.     cmp    EnableDebugDump,0    ; if debug dump turned off, no screen i/o
  536.     je    @@NoError
  537.  
  538.     xor    edx,edx
  539.     mov    dx,w[ErrorList]
  540.     mov    ah,9
  541.     int    21h
  542. ;
  543. ;Get a pointer to the appropriate error message and print it.
  544. ;
  545.     mov    bx,ErrorNumber
  546.     add    bx,bx
  547.     mov    dx,[ErrorList+bx]
  548.     mov    ah,9
  549.     int    21h
  550. ;
  551. ;Now exit with the error number as the DOS "errorlevel".
  552. ;
  553. @@NoError:
  554.     endif
  555.  
  556. ; MED, 12/24/99, coalesce free memory by attempting to allocate largest possible
  557. ;  with upper memory in the chain
  558.     mov    ax,5800h
  559.     int    21h
  560.     push    ax
  561.     mov    ax,5802h
  562.     int    21h
  563.     push    ax
  564.     mov    bx,1
  565.     mov    ax,5803h
  566.     int    21h
  567.     mov    bx,81h
  568.     mov    ax,5801h
  569.     int    21h
  570.  
  571.     mov    ah,48h
  572.     mov    bx,-1
  573.     int    21h
  574.  
  575.     pop    bx
  576.     mov    ax,5803h
  577.     int    21h
  578.     pop    bx
  579.     mov    ax,5801h
  580.     int    21h
  581.  
  582.     mov    ax,ErrorNumber
  583.     or    ax,ax
  584.     jnz    @@Exit
  585.     mov    ax,ErrorLevel
  586. @@Exit:
  587.  
  588. IFDEF DEBUG4
  589.     push    eax
  590.     push    ebx
  591.     push    ecx
  592.     push    edx
  593.     push    ds
  594.     push    cs
  595.     pop    ds
  596.     mov    edx,OFFSET debugbtext1
  597. debugbloop2:
  598.     cmp    BYTE PTR ds:[edx],0
  599.     je    debugbb
  600.     mov    ecx,1
  601.     mov    bx,1
  602.     mov    ah,40h
  603.     int    21h
  604.     inc    edx
  605.     jmp    debugbloop2
  606. debugbb:
  607.     mov    edx,OFFSET debugbtext2
  608.     push    cs
  609.     pop    ds
  610.     mov    ecx,2
  611.     mov    bx,1
  612.     mov    ah,40h
  613.     int    21h
  614.     pop    ds
  615.     pop    edx
  616.     pop    ecx
  617.     pop    ebx
  618.     pop    eax
  619.     jmp    debugbout
  620.  
  621. debugbtext1    DB    'Performing final real mode 4ch termination...',0
  622. debugbtext2    DB    13,10
  623.  
  624. debugbout:
  625.     push    ecx
  626.     mov    ecx,100000h
  627. debugbloop:
  628.     dec    ecx
  629.     jne    debugbloop
  630.     pop    ecx
  631. ENDIF
  632.  
  633.     mov    ah,4ch
  634.     int    21h
  635. cwClose    endp
  636.  
  637.  
  638. ;-------------------------------------------------------------------------------
  639. Int21hExecPatch proc    near
  640.     assume ds:nothing
  641.     pushf
  642.     cmp    ax,4b00h
  643.     jnz    @@Old
  644.  
  645.     inc    cs:Int21hExecCount
  646.  
  647.     popf
  648.     pushf
  649.     call    cs:d[OldInt21hExec]
  650.  
  651.     pushf
  652.     push bp
  653.     push ax
  654.     mov bp,sp
  655.     mov ax,[bp+2+2]
  656.     and ax,1
  657. ;    and w[bp+2+2+2+2+2],1
  658.     and w[bp+2+2+2+2+2],0fffeh    ; MED 01/24/96
  659.  
  660.     or w[bp+2+2+2+2+2],ax
  661.     pop ax
  662.     pop bp
  663.     popf
  664.  
  665.     dec    cs:Int21hExecCount
  666.  
  667.     iret
  668. @@Old:
  669.     popf
  670.     jmp    cs:d[OldInt21hExec]
  671. OldInt21hExec    dd 0
  672.     assume ds:_cwMain
  673. Int21hExecCount db 0
  674. Int21hExecPatch endp
  675.     .386p
  676.  
  677.  
  678. ;-------------------------------------------------------------------------------
  679. Bordm    proc    near
  680.     pushm    ax,dx
  681.     mov    ah,al
  682.     mov    dx,3dah
  683.     in    al,dx
  684.     mov    dl,0c0h
  685.     mov    al,11h
  686.     out    dx,al
  687.     mov    al,ah
  688.     out    dx,al
  689.     mov    al,20h
  690.     out    dx,al
  691.     popm    ax,dx
  692.     ret
  693. Bordm    endp
  694.  
  695. ;-------------------------------------------------------------------------------
  696. ;
  697. ;Some global data.
  698. ;
  699. RealPSPSegment    dw ?        ;Real mode PSP segment.
  700. RealENVSegment    dw ?        ;Real mode environment segment.
  701. ProtectedFlags    dw 0        ;Bit significant, 0-DPMI,1-VCPI,2-RAW.
  702. ProtectedType    dw 0        ;0-RAW,1-VCPI,2-DPMI.
  703. ProtectedForce    db 0
  704. DOSVersion    dw 0
  705. SystemFlags    dd 0
  706. apiCodeSeg    dw 0
  707. apiDataSeg    dw 0
  708. ;
  709. CodeSegment    dw MainCS    ;Setup CS selector.
  710. CodeSegmenti    dw InitCS
  711. DataSegment    dw MainDS    ;Setup DS selector.
  712. DataSegmenti    dw InitDS
  713. StackSegment    dw MainSS
  714. RealSegment    dw KernalZero
  715. PSPSegment    dw MainPSP
  716. ENVSegment    dw MainENV
  717. BasePSP    dw 0
  718. BasePSPAddress    dd 0
  719. ;
  720. TSRSize    dw 0
  721. ;
  722. ErrorNumber    dw 0
  723. ErrorLevel    dw 0
  724. ErrorList    dw ErrorM00,ErrorM01,ErrorM02,ErrorM03,ErrorM04,ErrorM05,ErrorM06,ErrorM07
  725.     dw ErrorM08,ErrorM09,ErrorM10,ErrorM11,ErrorM12,ErrorM13,ErrorM14,ErrorM15
  726.     dw ErrorM16
  727. ErrorM00    db 'CauseWay error '
  728. ErrorM00n    db '00 : $'
  729. ErrorM01    label byte
  730.     if ENGLISH
  731.     db 'Unable to re-size program memory block.',13,10,'$'
  732.     elseif SPANISH
  733.     db "Incapaz de redimensionar el bloque de memoria del programa.",13,10,"$"
  734.     endif
  735. ErrorM02    db "$"
  736. ErrorM03    db "$"
  737. ErrorM04    db "$"
  738. ErrorM05    label byte
  739.     if ENGLISH
  740.     db 'Not enough memory for CauseWay.',13,10,'$'
  741.     elseif SPANISH
  742.     db "Memoria insuficiente para CauseWay.",13,10,"$"
  743.     endif
  744. ErrorM06    db "$"
  745. ErrorM07    db "$"
  746. ErrorM08    db "$"
  747. ErrorM09    label byte
  748.     if ENGLISH
  749.     db 'Unrecoverable exception. Program terminated.',13,10,'$'
  750.     elseif SPANISH
  751.     db "Excepcion irrecuperable. Programa terminado.",13,10,"$"
  752.     endif
  753. ErrorM10    label byte
  754.     if ENGLISH
  755.     db 'Unable to find '
  756. ErrorM10_T    db 'application to load.',13,10,'$',32 dup (0)
  757.     elseif SPANISH
  758.     db "Incapaz de encontrar '
  759. ErrorM10_T    db 'aplicacion a cargar.",13,10,"$",32 dup (0)
  760.     endif
  761. ErrorM11    label byte
  762.     if ENGLISH
  763.     db 'DOS reported an error or corrupt file found.'
  764.     elseif SPANISH
  765.     db "DOS informo de un error o de un fichero corrupto."
  766.     endif
  767. ErrorM11_0    db 13,10,'$'
  768.     db "No:"
  769. ErrorM11_1    db "00000000",13,10,"$"
  770. ErrorM12    label byte
  771.     if ENGLISH
  772.     db 'Not enough memory to load application.',13,10,'$'
  773.     elseif SPANISH
  774.     db "Memoria insuficiente para cargar la aplicacion.",13,10,"$"
  775.     endif
  776. ErrorM13    db "$"
  777. ErrorM14    label byte
  778.     if ENGLISH
  779.     db 'Memory structures destroyed. Program terminated.',13,10,'$'
  780.     elseif SPANISH
  781.     db "Estructuras de memoria destruidas. Programa terminado.",13,10,"$"
  782.     endif
  783. ErrorM15    label byte
  784.     if ENGLISH
  785.     db 'DOS reported an error while accessing swap file. Program terminated.',13,10,'$'
  786.     elseif SPANISH
  787.     db "DOS informa de un error mientras se accede al fichero de swap. Programa terminado.",13,10,"$"
  788.     endif
  789. ErrorM16    label byte
  790.     if ENGLISH
  791.     db "Unsupported DOS function call, program terminated.",13,10,"$"
  792.     elseif SPANISH
  793.     db "Llamada a funcion no soportada del DOS, programa terminado.",13,10,"$"
  794.     endif
  795. ;
  796. ALIGN 4
  797. MainExec    db 128 dup (0)
  798. ;
  799. DtaBuffer    db 128 dup (0)
  800. ;
  801. TransferSize    dd 8192
  802. TransferReal    dw ?
  803. ;
  804. MouseETarget    dd 0,0
  805. ResourceTracking dw 0
  806. ForcedFind    dd 0,0
  807. mcbAllocations    dw 0
  808. LinearAddressCheck db 0
  809. ;
  810. TerminationHandler dd offset InitError,InitCS
  811. UserTermRoutine    DF    0
  812. UserTermDump    DF    0    ; dump location for register info
  813. ;
  814. DPMIStateAddr    df 0
  815. DPMIStateSize    dd 0
  816. DPMIStackOff    dw ?
  817. DPMIStackSeg    dw ?
  818. ;
  819. DebugDump    db 0
  820. EnableDebugDump    DB    1
  821. UserTermFlag    DB    0
  822. Pad1Flag    DB    0
  823.  
  824. IFDEF PERMNOEX
  825. NoEXECPatchFlag    DB    1
  826. ELSE
  827. NoEXECPatchFlag    DB    0
  828. ENDIF
  829.  
  830. ; MED, 11/11/99
  831. ; used to flag checking XMS total memory because EMM386 lies and acts as VCPI
  832. ;  host when NOVCPI set, but provides no memory
  833. VCPIHasNoMem    DB    0
  834.  
  835. NewCWErrName    DB    81 DUP (0)
  836. DOS4GFlag    db 0
  837. ;
  838. ;*** MED change for Michael Devore name
  839. CopyCheck    label byte
  840.     db 'C'-44,'a'-44,'u'-44,'s'-44,'e'-44,'W'-44,'a'-44,'y'-44,' '-44
  841.     db 'D'-44,'O'-44,'S'-44,' '-44,'E'-44,'x'-44,'t'-44,'e'-44,'n'-44
  842.     db 'd'-44,'e'-44,'r'-44,' '-44,'v'-44,255,255,255,255
  843.     db ' '-44,'C'-44,'o'-44,'p'-44,'y'-44,'r'-44,'i'-44,'g'-44
  844.     db 'h'-44,'t'-44,' '-44,'1'-44,'9'-44,'9'-44,'2'-44,'-'-44,'9'-44
  845.     db '9'-44,' '-44,'M'-44
  846.     db 'i'-44,'c'-44,'h'-44,'a'-44,'e'-44,'l'-44,' '-44,'D'-44,'e'-44
  847.     db 'v'-44,'o'-44,'r'-44,'e'-44,'.'-44,13-44,10-44,'A'-44,'l'-44,'l'-44
  848.     db ' '-44,'r'-44,'i'-44,'g'-44,'h'-44,'t'-44,'s'-44,' '-44,'r'-44
  849.     db 'e'-44,'s'-44,'e'-44,'r'-44,'v'-44,'e'-44,'d'-44,'.'-44,13-44,10-44
  850. CopyCount    dw 0
  851. ;
  852. Int21Buffer    db size RealRegsStruc dup (?)
  853. Int10Buffer    db size RealRegsStruc dup (?)
  854. Int33Buffer    db size RealRegsStruc dup (?)
  855. ;
  856. apiExcepPatched db 0
  857. ;
  858. ExtensionList    label word
  859.     dw ExceptionExtension
  860.     dw Int21hExtension,Int10hExtension,Int33hExtension
  861.     dw -1
  862. ;
  863. ExceptionExtension dw _Excep,0
  864.     dd offset ExcepEnd-ExcepStart
  865.     dd offset ExcepOpen,?
  866.     dd offset ExcepClose,?
  867.     dd 0
  868.     dd 0
  869.     dd 0
  870. ;
  871. Int21hExtension dw _Int21h,1        ;segment start.
  872.     dd offset Int21hEnd-Int21hStart    ;segment length.
  873.     dd offset Int21hOpen,?     ;init code.
  874.     dd offset Int21hClose,?    ;remove code.
  875.     dd 0            ;code selector.
  876.     dd 0            ;data selector.
  877.     dd 0            ;installed flag.
  878. ;
  879. Int10hExtension dw _Int10h,1        ;segment start.
  880.     dd offset Int10hEnd-Int10hStart    ;segment length.
  881.     dd offset Int10hOpen,?    ;init code.
  882.     dd offset Int10hClose,?    ;remove code.
  883.     dd 0            ;code selector.
  884.     dd 0            ;data selector.
  885.     dd 0            ;installed flag.
  886. ;
  887. Int33hExtension dw _Int33h,1        ;segment start.
  888.     dd offset Int33hEnd-Int33hStart    ;segment length.
  889.     dd offset Int33hOpen,?    ;init code.
  890.     dd offset Int33hClose,?    ;remove code.
  891.     dd 0            ;code selector.
  892.     dd 0            ;data selector.
  893.     dd 0            ;installed flag.
  894. ;
  895. Temp0_    dd ?
  896. Temp1_    dd ?
  897. ;
  898. DebugUserOff    DD    ?
  899. DebugUserSel    DW    ?
  900. DebugUserCount    DW    0    ; must be initialized, nonzero value flags operation
  901. DebugAsciiFlag    DB    ?
  902. _cwMain    ends
  903.  
  904.  
  905. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  906. ;
  907. ;Default stack used during startup and exit.
  908. ;
  909. _cwStack    segment para stack 'main stack' use16
  910.     db 2048 dup (0)
  911. _cwStackEnd    label byte
  912. _cwStack    ends
  913.  
  914.  
  915.     include raw&vcpi.asm
  916.  
  917.     include api.asm
  918.     include exceptn.asm
  919.     include int10h.asm
  920.     include int21h.asm
  921.     include int33h.asm
  922.  
  923.  
  924. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  925. ;
  926. ;The initialiseation code seg. Takes care of things like checking for the right
  927. ;processor and determining how we're going to get into protected mode.
  928. ;
  929. _cwInit    segment para public 'init code' use16
  930.     assume cs:_cwInit, ds:_cwMain
  931.  
  932. dpmiSelBuffer    db 8 dup (0)
  933.  
  934. ;-------------------------------------------------------------------------------
  935. Startup    proc    near
  936. ;
  937. ;Make global data addresable.
  938. ;
  939.     mov    ax,_cwMain
  940.     mov    ds,ax
  941.  
  942. ; MED, 12/30/99
  943. ; works around weird bug in some machines due to Windows/hardware/BIOS??? error
  944. ;  where a CauseWay application in AUTOEXEC.BAT which uses DOS function 8
  945. ;  to get a keystroke when no other application in AUTOEXEC.BAT gets a
  946. ;  keystroke will cause failure in Windows 98 (and 95?) when opening a DOS
  947. ;  box after Windows startup.  Caused by A20 or keyboard port stabilization?
  948.     mov    cx,127
  949. kloop:
  950.     mov    ax,0b00h
  951.     int    21h
  952.     test    al,al
  953.     jne    done
  954.     loop    kloop
  955. done:
  956.  
  957. ;
  958. ;Stow real mode PSP and environment values, we'll need them later.
  959. ;
  960.     mov    RealPSPSegment,es
  961.     mov    ax,es:w[02ch]
  962.     mov    RealEnvSegment,ax    ;Stow ENV for later.
  963. ;
  964. ;Re-size memory so we can allocate what we want high.
  965. ;
  966.     mov    cs:IErrorNumber,1
  967.     mov    ax,es
  968.     mov    bx,_cwEnd        ;Get program end segment.
  969.     sub    bx,ax        ;Size program.
  970.     inc    bx
  971.     mov    ah,4ah
  972.     int    21h        ;Re-size memory block.
  973.  
  974. ; MED 06/16/97
  975. ;    jc    InitError
  976.     jnc    chk386
  977.  
  978. toiniterr:
  979.     jmp    InitError
  980.  
  981. ;
  982. ;Check we're on at least a 386 system.
  983. ;
  984. chk386:
  985.     mov    cs:IErrorNumber,2
  986.     call    CheckProcessor
  987.  
  988. ;    jc    InitError
  989.     jc    toiniterr
  990.  
  991. ;
  992. ;Check DOS version is high enough.
  993. ;
  994.     mov    cs:IErrorNumber,4
  995.     call    CheckDOSVersion
  996.     jc    InitError
  997. ;
  998. ;Get execution name from environment.
  999. ;
  1000.     call    GetEXECName
  1001. ;
  1002. ;Retrieve setup info from 3P header.
  1003. ;
  1004.     call    GetSystemFlags
  1005. ;
  1006. ;Check if a suitable method for switching to protected mode exists.
  1007. ;
  1008.     call    GetProtectedType
  1009.     mov    cs:IErrorNumber,3
  1010.     cmp    ProtectedFlags,0    ;Any types available?
  1011.     jz    InitError
  1012. ;
  1013. ;Get CAUSEWAY environment variable settings.
  1014. ;
  1015.     call    GetENVStuff
  1016. ;
  1017. ;Decide which environment to use.
  1018. ;
  1019.     call    SetProtectedType
  1020. ;
  1021. ;Move the DTA to where we can get at it in the future.
  1022. ;
  1023.     mov    dx,offset DTABuffer
  1024.     mov    ah,1ah
  1025.     int    21h
  1026. ;
  1027. ;now see about type specific initialisations.
  1028. ;
  1029.     cmp    ProtectedType,2    ;DPMI initialiseation?
  1030.     jz    @@InitDPMI
  1031. ;
  1032. ;Useing either RAW or VCPI so do the stuff that's common to both for now.
  1033. ;
  1034.     mov    ax,_cwRaw
  1035.     mov    ds,ax
  1036.     assume ds:_cwRaw
  1037. ;
  1038. ;Get SDA address so VMM can change BREAK state.
  1039. ;
  1040.     .386
  1041.     push    ds
  1042.     mov    ax,5d06h
  1043.     int    21h
  1044.     mov    ax,ds
  1045.     pop    ds
  1046.     add    si,17h
  1047.     movzx    eax,ax
  1048.     shl    eax,4
  1049.     movzx    esi,si
  1050.     add    eax,esi
  1051.     mov    BreakAddress,eax
  1052. ;
  1053. ;Find out if XMS is present.
  1054. ;
  1055.     mov    ax,4300h        ;XMS install check.
  1056.     int    2fh
  1057.     cmp    al,80h        ;XMS present?
  1058.     jnz    @@NoXMS
  1059. ;
  1060. ;XMS detected so work out max block size and entry point.
  1061. ;
  1062.     mov    ax,4310h        ;Get XMS API.
  1063.     int    2fh
  1064.     mov    w[XMSControl],bx
  1065.     mov    w[XMSControl+2],es
  1066.     mov    XMSPresent,1        ;flag XMS is available.
  1067.  
  1068. ; MED, 09/10/99, support extended XMS API to calculate XMS available to CauseWay
  1069. ;  (maximum of 2G-32K, i.e. 32 handles/entries of 64K-1)
  1070.     mov    ah,0
  1071.     call    d[XMSControl]    ; get info
  1072.     cmp    ah,3
  1073.     jb    xms2
  1074.     cmp    bh,3
  1075.     jb    xms2
  1076.     cmp    bl,8
  1077.     jb    xms2            ; treat early 3.x drivers < 3.08 as 2.x
  1078.  
  1079. ; use extended XMS API
  1080.     mov    XMSVer3Present,1    ; flag XMS 3.x driver present
  1081.     mov    ah,88h
  1082.     call    d[XMSControl]    ;get size of biggest block free.
  1083.     mov    edx,eax
  1084.     test    eax,eax
  1085.     jz    @@YesXMS        ;no memory available.
  1086.     mov    cs:d[@@XMSSize],edx
  1087.     mov    ah,89h
  1088.     call    d[XMSControl]    ;claim biggest block to force XMS
  1089.     cmp    ax,1            ;to stake a claim on int 15h.
  1090.     jnz    @@YesXMS
  1091.     mov    cs:b[@@NumXMSHandles],1
  1092.     push    dx
  1093.     mov    ah,8eh
  1094.     call    d[XMSControl]    ; get handle information
  1095.     cmp    ax,1
  1096.     jnz    @@NoHandles3
  1097.     cmp    cx,4
  1098.     jc    @@NoHandles3
  1099.     sub    cx,2
  1100.     mov    cs:b[@@NumXMSHandles],32
  1101.     cmp    cx,32
  1102.     jnc    @@NoHandles3
  1103.     mov    cs:b[@@NumXMSHandles],cl    ; cx known 8-bit value
  1104.  
  1105. @@NoHandles3:
  1106.     pop    dx
  1107.     mov    ah,0ah
  1108.     call    d[XMSControl]    ;now free it.
  1109.  
  1110.     movzx    eax, BYTE PTR cs:[@@NumXMSHandles]
  1111.     mov    edx,eax
  1112.     shl    eax,16
  1113.     sub    eax,edx        ; eax == handles (up to 32) * 65535
  1114.     cmp    eax,cs:d[@@XMSSize]
  1115.     jae    @@ComputeSize
  1116.     mov    cs:d[@@XMSSize],eax    ; throttle maximum size
  1117.  
  1118. @@ComputeSize:
  1119.     push    eax
  1120.     xor    edx,edx
  1121.     movzx    ebx,BYTE PTR cs:[@@NumXMSHandles]
  1122.     div    ebx
  1123.     pop    ebx
  1124.     cmp    ax,4        ; eax known 16-bit value
  1125.     jnc    @@SizeOK3
  1126.     mov    ax,bx        ; ebx == maximum size, known 16-bit value here
  1127.  
  1128. @@SizeOK3:
  1129.     mov    XMSBlockSize,ax
  1130.     jmp    @@YesXMS
  1131.  
  1132. xms2:
  1133.     mov    ah,8
  1134.     call    d[XMSControl]    ;get size of biggest block free.
  1135.     mov    dx,ax
  1136.     or    ax,ax
  1137.     jz    @@YesXMS        ;no memory available.
  1138.     mov    cs:w[@@XMSSize],dx
  1139.     mov    ah,9
  1140.     call    d[XMSControl]    ;claim biggest block to force XMS
  1141.     cmp    ax,1        ;to stake a claim on int 15h.
  1142.     jnz    @@YesXMS
  1143.     mov    cs:b[@@NumXMSHandles],1
  1144.     push    dx
  1145.     mov    ah,0eh
  1146.     call    d[XMSControl]    ;now free it.
  1147.     cmp    ax,1
  1148.     jnz    @@NoHandles
  1149.     cmp    bl,4
  1150.     jc    @@NoHandles
  1151.     sub    bl,2
  1152.     mov    cs:b[@@NumXMSHandles],32
  1153.     cmp    bl,32
  1154.     jnc    @@NoHandles
  1155.     mov    cs:b[@@NumXMSHandles],bl
  1156. @@NoHandles:    pop    dx
  1157.     mov    ah,0ah
  1158.     call    d[XMSControl]    ;now free it.
  1159.     mov    ax,cs:w[@@XMSSize]
  1160.     push    ax
  1161.     xor    dx,dx
  1162.     xor    bh,bh
  1163.     mov    bl,cs:b[@@NumXMSHandles]
  1164.     div    bx
  1165.     pop    bx
  1166.     cmp    ax,4
  1167.     jnc    @@SizeOK
  1168.     mov    ax,bx
  1169. @@SizeOK:    mov    XMSBlockSize,ax
  1170.     jmp    @@YesXMS
  1171. ;
  1172. ;Install raw A20 handler.
  1173. ;
  1174. @@NoXMS:    call    InstallA20
  1175. ;
  1176. ;Get A20 state.
  1177. ;
  1178. @@YesXMS:    push    ds
  1179.     les    di,HighMemory    ;   with the four at FFFF:0090
  1180.     lds    si,LowMemory        ; Compare the four words at 0000:0080
  1181.     mov    cx,4
  1182.     cld
  1183.     repe  cmpsw
  1184.     pop    ds
  1185.     xor    ax,ax
  1186.     jcxz    @@A20OFF         ; Are the two areas the same?
  1187.     inc    ax            ; No, return A20 Enabled
  1188. @@A20OFF:    mov    A20Flag,al
  1189. ;
  1190. ;Change DOS allocation stratergy to highest so we'll get UMB's if available.
  1191. ;
  1192.     mov    ax,5800h
  1193.     int    21h
  1194.     mov    cs:w[@@OldStrat],ax
  1195.     mov    ax,5802h
  1196.     int    21h
  1197.     mov    cs:w[@@OldStrat+2],ax
  1198.     mov    bx,1
  1199.     mov    ax,5803h
  1200.     int    21h
  1201.     mov    bx,81h
  1202.     mov    ax,5801h
  1203.     int    21h
  1204. ;
  1205. ;Grab memory for page dir, page alias & first page table entry.
  1206. ;
  1207.     mov    bx,(4096*3)/16    ;smallest allocation possible.
  1208.     mov    ah,48h
  1209.     int    21h
  1210.     jc    @@OldWay
  1211.     push    ax
  1212.     movzx    eax,ax
  1213.     shl    eax,4        ;linear address.
  1214.     mov    ebx,eax
  1215.     add    eax,4095
  1216.     and    eax,0ffffffffh-4095    ;round up to next page.
  1217.     sub    eax,ebx
  1218.     shr    eax,4
  1219.     mov    bx,ax
  1220.     mov    cx,ax
  1221.     add    bx,(4096*3)/16
  1222.     mov    ah,4ah
  1223.     pop    es
  1224.     pushm    bx,cx,es
  1225.     int    21h        ;re-size the block.
  1226.     popm    bx,cx,es
  1227.     jnc    @@NewWay
  1228.     mov    ah,49h
  1229.     int    21h        ;release this block.
  1230.     ;
  1231. @@OldWay:    mov    cs:IErrorNumber,5
  1232.     mov    bx,(4096*4)/16    ;need space for 3 page tables on
  1233.     mov    ah,48h        ;4k boundary.
  1234.     int    21h
  1235.     jc    InitError
  1236.     mov    dx,ax
  1237.     movzx    eax,ax        ;get segment address.
  1238.     shl    eax,4        ;make linear.
  1239.     mov    ebx,eax
  1240.     add    eax,4095
  1241.     and    eax,0FFFFFFFFh-4095    ;round up to nearest page.
  1242.     mov    ecx,eax
  1243.     sub    ecx,ebx
  1244.     shr    ecx,4
  1245.     shr    eax,4        ;Get segment value again.
  1246.     jmp    @@GotSeg
  1247.     ;
  1248. @@NewWay:    mov    ax,es
  1249.     mov    dx,ax
  1250.     add    ax,cx        ;move to real start.
  1251.     ;
  1252. @@GotSeg:
  1253.     pushm    cx,dx
  1254.     mov    es,ax
  1255.  
  1256. ; MED 09/19/96
  1257. ;    mov    PageDirReal,ax    ;setup page directory address.
  1258. ;    add    ax,4096/16
  1259. ;    mov    Page1stReal,ax    ;setup 1st page table address.
  1260.     mov    Page1stReal,ax    ;setup 1st page table address.
  1261.     add    ax,4096/16
  1262.     mov    PageDirReal,ax    ;setup page directory address.
  1263.  
  1264.     add    ax,4096/16
  1265.     mov    PageAliasReal,ax    ;setup alias table address.
  1266.     xor    di,di
  1267.     mov    cx,4096*3
  1268.     xor    al,al
  1269.     cld
  1270.     rep    stosb        ;clear it.
  1271.     movzx    eax,PageDIRReal
  1272.     shl    eax,4
  1273.     mov    PageDIRLinear,eax
  1274.     mov    VCPI_CR3,eax
  1275.     movzx    eax,PageALIASReal
  1276.     shl    eax,4
  1277.     mov    PageAliasLinear,eax
  1278.     movzx    eax,Page1stReal
  1279.     shl    eax,4
  1280.     mov    Page1stLinear,eax
  1281.     popm    cx,dx
  1282. ;
  1283. ;See if enough wasted space to squeeze TSS into.
  1284. ;
  1285.     cmp    cx,(((size TSSFields)+2+16)/16)
  1286.     jc    @@TSSOld
  1287.     mov    ax,dx           ;get segment.
  1288.     add    dx,(((size TSSFields)+2+16)/16)    ;move segment base.
  1289.     sub    cx,(((size TSSFields)+2+16)/16)    ;update space left size.
  1290.     jmp    @@TSSGot
  1291. ;
  1292. ;Allocate memory for Kernal TSS.
  1293. ;
  1294. @@TSSOld:    mov    cs:IErrorNumber,5
  1295.     mov    bx,(((size TSSFields)+2+16)/16)    ;(4096/2)+2+16)/16
  1296.     mov    ah,48h
  1297.     int    21h
  1298.     jc    InitError
  1299. @@TSSGot:    mov    KernalTSSReal,ax
  1300. ;
  1301. ;See if enough wasted space to squeeze GDT into.
  1302. ;
  1303.     cmp    cx,((8*GDT_Entries)/16)+1
  1304.     jc    @@GDTOld
  1305.     mov    ax,dx           ;get segment.
  1306.     add    dx,((8*GDT_Entries)/16)+1    ;move segment base.
  1307.     sub    cx,((8*GDT_Entries)/16)+1    ;update space left size.
  1308.     jmp    @@GDTGot
  1309. ;
  1310. ;Allocate some memory for the GDT.
  1311. ;
  1312. @@GDTOld:    mov    cs:IErrorNumber,5
  1313.     mov    bx,((8*GDT_Entries)/16)+1
  1314.     mov    ah,48h
  1315.     int    21h
  1316.     jc    InitError
  1317. @@GDTGot:    mov    GDTReal,ax
  1318.     mov    es,ax
  1319.     movzx    eax,ax
  1320.     shl    eax,4
  1321.     mov    GDTLinear,eax
  1322.     xor    di,di
  1323.     mov    cx,(8*GDT_Entries)
  1324.     xor    al,al
  1325.     cld
  1326.     rep    stosb
  1327. ;
  1328. ;Allocate some memory for the stack.
  1329. ;
  1330.     mov    cs:IErrorNumber,5
  1331.     mov    ebx,RawStackPos
  1332.     shr    ebx,4
  1333.     mov    ah,48h
  1334.     int    21h
  1335.     jc    InitError
  1336.     mov    RawStackReal,ax
  1337.     mov    es,ax
  1338.     mov    cx,w[RawStackPos]
  1339.     xor    di,di
  1340.     xor    al,al
  1341.     cld
  1342.     rep    stosb
  1343.  
  1344. ; MED 09/19/96
  1345. ; Set address for VMM page to disk buffer.
  1346.     mov    cs:IErrorNumber,5
  1347.     mov    bx,4096/16
  1348.     mov    ah,48h
  1349.     int    21h
  1350.     jc    InitError
  1351.     mov    PageBufferReal,ax
  1352.     movzx    eax,ax
  1353.     shl    eax,4
  1354.     mov    PageBufferLinear,eax
  1355.  
  1356. ;
  1357. ;Restore DOS memory allocation stratergy.
  1358. ;
  1359.     mov    bx,cs:w[@@OldStrat+2]
  1360.     xor    bh,bh
  1361.     mov    ax,5803h
  1362.     int    21h
  1363.     mov    bx,cs:w[@@OldStrat]
  1364.     xor    bh,bh
  1365.     mov    ax,5801h
  1366.     int    21h
  1367. ;
  1368. ;Need to initialise 1st page table to map <1meg+64k 1:1.
  1369. ;
  1370.     mov    es,Page1stReal
  1371.     xor    di,di
  1372.     mov    cx,256+16        ;1st 1 meg + 64k.
  1373.     mov    esi,111b        ;user+write+present
  1374. @@0:    mov    es:[di],esi
  1375.     add    di,4        ;next page table entry.
  1376.     add    esi,4096        ;next physical page address.
  1377.     dec    cx
  1378.     jnz    @@0
  1379.  
  1380. ; MED 09/19/96
  1381. COMMENT !
  1382. ;
  1383. ;Set address for VMM page to disk buffer.
  1384. ;
  1385.     mov    ax,PageDIRReal
  1386.     mov    PageBufferReal,ax
  1387.     movzx    eax,ax
  1388.     shl    eax,4
  1389.     mov    PageBufferLinear,eax
  1390. END COMMENT !
  1391.  
  1392. ;
  1393. ;Set address for DOS INT 21h PM to Real transfer buffer.
  1394. ;
  1395.  
  1396. ; MED 09/19/96
  1397. ;    mov    bx,Page1stReal
  1398.     mov    bx,PageDirReal
  1399.  
  1400.     push    ds
  1401.     mov    ax,_cwMain
  1402.     mov    ds,ax
  1403.     assume ds:_cwMain
  1404.     mov    TransferReal,bx
  1405.     assume ds:_cwRaw
  1406.     pop    ds
  1407. ;
  1408. ;Allocate the GDT entries.
  1409. ;
  1410.     mov    es,GDTReal
  1411. ;
  1412. ;Fill in the null entry just for the hell of it.
  1413. ;
  1414.     xor    esi,esi        ;Null entry at 0.
  1415.     xor    ecx,ecx
  1416.     xor    ax,ax
  1417.     xor    di,di
  1418.     call    MakeDesc
  1419. ;
  1420. ;Fill in the VCPI entries so we don't try to use them later.
  1421. ;
  1422.     xor    esi,esi
  1423.     xor    ecx,ecx
  1424.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1425.     mov    di,VCPI_0
  1426.     call    MakeDesc
  1427.     xor    esi,esi
  1428.     xor    ecx,ecx
  1429.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1430.     mov    di,VCPI_1
  1431.     call    MakeDesc
  1432.     xor    esi,esi
  1433.     xor    ecx,ecx
  1434.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1435.     mov    di,VCPI_2
  1436.     call    MakeDesc
  1437. ;
  1438. ;Allocate 40h descriptor.
  1439. ;
  1440.     mov    esi,400h
  1441.     mov    ecx,65535
  1442.     xor    al,al
  1443.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1444.     mov    di,Kernal40h
  1445.     call    MakeDesc
  1446. ;
  1447. ;Allocate kernal task descriptors, TSS itself first.
  1448. ;
  1449.     movzx    esi,KernalTSSReal
  1450.     shl    esi,4
  1451.     mov    ecx,size TSSFields+2
  1452.     xor    al,al
  1453.     mov    ah,DescPresent+DescPL3+Desc386Tss
  1454.     mov    di,KernalTS
  1455.     call    MakeDesc
  1456. ;
  1457. ;TSS PL0 stack.
  1458. ;
  1459.     movzx    esi,KernalTSSReal
  1460.     shl    esi,4
  1461.     add    esi,tPL1Stack
  1462.     mov    ecx,65535
  1463.     mov    al,b[RawSystemFlags]
  1464.     xor    al,1
  1465.     shl    al,6
  1466.     mov    ah,DescPresent+DescPL0+DescMemory+DescRWData
  1467.     mov    di,KernalPL0
  1468.     call    MakeDesc
  1469. ;
  1470. ;Mode switch PL0 stack.
  1471. ;
  1472.     movzx    esi,KernalTSSReal
  1473.     shl    esi,4
  1474.     add    esi,tPL1Stack
  1475.     mov    ecx,65535
  1476.     xor    al,al
  1477.     mov    ah,DescPresent+DescPL0+DescMemory+DescRWData
  1478.     mov    di,KernalSwitchPL0
  1479.     call    MakeDesc
  1480. ;
  1481. ;LDT
  1482. ;
  1483.     xor    esi,esi
  1484.     xor    ecx,ecx
  1485.     xor    al,al
  1486.     mov    ah,DescPresent+DescPL3+DescLDT
  1487.     mov    di,KernalLDT
  1488.     call    MakeDesc
  1489. ;
  1490. ;Kernal (RAW) code seg.
  1491. ;
  1492.     xor    esi,esi
  1493.     mov    si,_cwRaw
  1494.     shl    esi,4
  1495.     mov    ecx,65535
  1496.     xor    al,al
  1497.     mov    ah,DescPresent+DescPL3+DescMemory+DescERCode
  1498.     mov    di,KernalCS
  1499.     call    MakeDesc
  1500. ;
  1501. ;Kernal (RAW) code seg at PL0
  1502. ;
  1503.     xor    esi,esi
  1504.     mov    si,_cwRaw
  1505.     shl    esi,4
  1506.     mov    ecx,65535
  1507.     xor    al,al
  1508.     mov    ah,DescPresent+DescPL0+DescMemory+DescERCode
  1509.     mov    di,KernalCS0
  1510.     call    MakeDesc
  1511. ;
  1512. ;Kernal (RAW) data seg.
  1513. ;
  1514.     xor    esi,esi
  1515.     mov    si,_cwRaw
  1516.     shl    esi,4
  1517.     mov    ecx,65535
  1518.     xor    al,al
  1519.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1520.     mov    di,KernalDS
  1521.     call    MakeDesc
  1522. ;
  1523. ;Kernal (RAW) stack seg.
  1524. ;
  1525.     movzx    esi,RawStackReal
  1526.     shl    esi,4
  1527.     mov    ecx,65535
  1528.     mov    al,b[RawSystemFlags]
  1529.     xor    al,1
  1530.     shl    al,6
  1531.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1532.     mov    di,KernalSS
  1533.     call    MakeDesc
  1534. ;
  1535. ;Kernal PL3 to PL0 call gate.
  1536. ;
  1537.     xor    ecx,ecx
  1538.     mov    esi,KernalCS0
  1539.     xor    al,al
  1540.     mov    ah,DescPresent+DescPL3+Desc386Call
  1541.     mov    di,KernalPL3_2_PL0
  1542.     call    MakeDesc
  1543. ;
  1544. ;DPMI emulator code seg.
  1545. ;
  1546.     xor    esi,esi
  1547.     mov    si,_cwDPMIEMU
  1548.     shl    esi,4
  1549.     mov    ecx,offset cwDPMIEMUEnd-cwDPMIEMUStart
  1550.     mov    al,1 shl 6
  1551.     mov    ah,DescPresent+DescPL3+DescMemory+DescERCode
  1552.     mov    di,DpmiEmuCS
  1553.     call    MakeDesc
  1554. ;
  1555. ;DPMI emulator code seg at PL0
  1556. ;
  1557.     xor    esi,esi
  1558.     mov    si,_cwDPMIEMU
  1559.     shl    esi,4
  1560.     mov    ecx,offset cwDPMIEMUEnd-cwDPMIEMUStart
  1561.     mov    al,1 shl 6
  1562.     mov    ah,DescPresent+DescPL0+DescMemory+DescERCode
  1563.     mov    di,DpmiEmuCS0
  1564.     call    MakeDesc
  1565. ;
  1566. ;DPMI emulator data seg.
  1567. ;
  1568.     xor    esi,esi
  1569.     mov    si,_cwDPMIEMU
  1570.     shl    esi,4
  1571.     mov    ecx,offset cwDPMIEMUEnd-cwDPMIEMUStart
  1572.     mov    al,1 shl 6
  1573.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1574.     mov    di,DpmiEmuDS
  1575.     call    MakeDesc
  1576. ;
  1577. ;Init PL3 to PL0 call gate.
  1578. ;
  1579.     xor    ecx,ecx
  1580.     mov    esi,InitCS0
  1581.     xor    al,al
  1582.     mov    ah,DescPresent+DescPL3+Desc386Call
  1583.     mov    di,InitPL3_2_PL0
  1584.     call    MakeDesc
  1585. ;
  1586. ;DPMI emulator PL3 to PL0 call gate.
  1587. ;
  1588.     xor    ecx,ecx
  1589.     mov    esi,DpmiEmuCS0
  1590.     xor    al,al
  1591.     mov    ah,DescPresent+DescPL3+Desc386Call
  1592.     mov    di,DpmiEmuPL3_2_PL0
  1593.     call    MakeDesc
  1594. ;
  1595. ;Zero to 4G segment.
  1596. ;
  1597.     xor    esi,esi
  1598.     or    ecx,-1
  1599.     xor    al,al
  1600.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1601.     mov    di,KernalZero
  1602.     call    MakeDesc
  1603. ;
  1604. ;Main PSP segment.
  1605. ;
  1606.     push    ds
  1607.     mov    ax,_cwMain
  1608.     mov    ds,ax
  1609.     assume ds:_cwMain
  1610.     movzx    esi,RealPspSegment
  1611.     assume ds:_cwRaw
  1612.     pop    ds
  1613.     shl    esi,4
  1614.     mov    ecx,256
  1615.     mov    al,0
  1616.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1617.     mov    di,MainPSP
  1618.     call    MakeDesc
  1619. ;
  1620. ;Main environment var.
  1621. ;
  1622.     push    ds
  1623.     mov    ax,_cwMain
  1624.     mov    ds,ax
  1625.     assume ds:_cwMain
  1626.     movzx    esi,RealEnvSegment
  1627.     assume ds:_cwRaw
  1628.     pop    ds
  1629.     shl    esi,4
  1630.     mov    ecx,0FFFFh
  1631.     xor    al,al
  1632.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1633.     mov    di,MainEnv
  1634.     call    MakeDesc
  1635. ;
  1636. ;Main code seg.
  1637. ;
  1638.     xor    esi,esi
  1639.     mov    si,_cwMain
  1640.     shl    esi,4
  1641.     mov    ecx,65535
  1642.     xor    al,al
  1643.     mov    ah,DescPresent+DescPL3+DescMemory+DescERCode
  1644.     mov    di,MainCS
  1645.     call    MakeDesc
  1646. ;
  1647. ;Main data seg.
  1648. ;
  1649.     xor    esi,esi
  1650.     mov    si,_cwMain
  1651.     shl    esi,4
  1652.     mov    ecx,65535
  1653.     xor    al,al
  1654.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1655.     mov    di,MainDS
  1656.     call    MakeDesc
  1657. ;
  1658. ;Main stack.
  1659. ;
  1660.     xor    esi,esi
  1661.     mov    si,_cwStack
  1662.     shl    esi,4
  1663.     mov    ecx,65535
  1664.     mov    al,b[RawSystemFlags]
  1665.     xor    al,1
  1666.     shl    al,6
  1667.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1668.     mov    di,MainSS
  1669.     call    MakeDesc
  1670. ;
  1671. ;Init code seg.
  1672. ;
  1673.     xor    esi,esi
  1674.     mov    si,_cwInit
  1675.     shl    esi,4
  1676.     mov    ecx,65535
  1677.     xor    al,al
  1678.     mov    ah,DescPresent+DescPL3+DescMemory+DescERCode
  1679.     mov    di,InitCS
  1680.     call    MakeDesc
  1681. ;
  1682. ;Init code seg at PL0
  1683. ;
  1684.     xor    esi,esi
  1685.     mov    si,_cwInit
  1686.     shl    esi,4
  1687.     mov    ecx,65535
  1688.     xor    al,al
  1689.     mov    ah,DescPresent+DescPL0+DescMemory+DescERCode
  1690.     mov    di,InitCS0
  1691.     call    MakeDesc
  1692. ;
  1693. ;Init data seg.
  1694. ;
  1695.     xor    esi,esi
  1696.     mov    si,_cwInit
  1697.     shl    esi,4
  1698.     mov    ecx,65535
  1699.     xor    al,al
  1700.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1701.     mov    di,InitDS
  1702.     call    MakeDesc
  1703. ;
  1704. ;Init GDT data alias.
  1705. ;
  1706.     mov    esi,GDTLinear
  1707.     mov    ecx,65535
  1708.     xor    al,al
  1709.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  1710.     mov    di,GDTData
  1711.     call    MakeDesc
  1712. ;
  1713. ;Setup TSS registers to run in protected mode. Setup GDT & IDT values.
  1714. ;
  1715.     mov    es,KernalTSSReal
  1716.     xor    di,di
  1717.     mov    cx,size TSSFields    ;+(4096/8)
  1718.     xor    al,al
  1719.     cld
  1720.     rep    stosb        ;clear TSS & IO map.
  1721.     or    ax,-1
  1722.     stosw            ;mark end of IO map.
  1723.     mov    es:SS0,KernalPL0
  1724.     mov    es:ESP0,tPL0StackSize-4
  1725.     mov    es:tLDT,KernalLDT
  1726.     mov    es:IOMap,size TSSFields    ;set displacement to IO table.
  1727. ;
  1728. ;Setup GDT load value.
  1729. ;
  1730.     movzx    eax,GDTReal
  1731.     shl    eax,4
  1732.     mov    d[GDTVal+2],eax
  1733.     mov    w[GDTVal],-1
  1734. ;
  1735. ;Setup Windows enhanced mode denial patch.
  1736. ;
  1737.     mov    ax,352fh        ;get existing vector.
  1738.     int    21h
  1739.     mov    w[OldInt2F],bx
  1740.     mov    w[OldInt2F+2],es
  1741.     mov    ax,252fh
  1742.     mov    dx,offset Int2FPatch
  1743.     int    21h
  1744. ;
  1745. ;Now patch RAW specific calls.
  1746. ;
  1747.     push    ds
  1748.     mov    ax,_cwMain
  1749.     mov    ds,ax
  1750.     assume ds:_cwMain
  1751.     cmp    ProtectedType,1    ;VCPI?
  1752.     assume ds:_cwRaw
  1753.     pop    ds
  1754.     jz    @@VCPI
  1755. ;
  1756. ;Use RAW method to switch to protected mode.
  1757. ;
  1758. @@RAW:    .386p
  1759. ;
  1760. ;Need to initialise 1st entry of page dir & alias.
  1761. ;
  1762.     movzx    eax,Page1stReal
  1763.     shl    eax,4
  1764.     or    eax,111b        ;user+write+present
  1765.     mov    es,PageDirReal
  1766.     xor    di,di
  1767.     mov    es:[di],eax
  1768.     mov    es,PageAliasReal
  1769.     mov    es:[di],eax
  1770.     mov    es,KernalTSSReal
  1771.     mov    es:[di].tCR3,eax    ;set CR3 in TSS as well.
  1772.     ;
  1773.     ;map alias into page dir as well.
  1774.     ;
  1775.     movzx    eax,PageAliasReal    ;get para address.
  1776.     shl    eax,4        ;make linear.
  1777.     or    eax,111b        ;user+write+present.
  1778.     mov    es,PageDirReal
  1779.     mov    di,1023*4
  1780.     mov    es:[di],eax        ;setup in last page dir entry.
  1781.     ;
  1782. ;    pushfd
  1783. ;    pop    eax
  1784. ;    mov    EFlagsSav,eax
  1785.     mov    eax,cr3
  1786.     mov    CR3Sav,eax
  1787.     mov    eax,cr0
  1788.     mov    CR0Sav,eax
  1789.     sidt    IDTSav        ;save old IDT value for switch back.
  1790.     sgdt    GDTSav
  1791.     pop    RetAdd
  1792.     cli            ;Don't want interupts interfering.
  1793.     lgdt    GDTVal        ;Setup GDT &
  1794.     lidt    f[IDTVal]        ;IDT.
  1795.     mov    eax,VCPI_CR3
  1796.     mov    cr3,eax        ;set page dir address.
  1797.     mov    eax,cr0        ;Get machine status &
  1798.     or    eax,080000001h    ;set PM+PG bits.
  1799.     mov    cr0,eax        ;/
  1800.  
  1801. ; MED 10/15/96
  1802.     mov    CR0ProtSav,eax    ; save protected mode status of CR0
  1803.  
  1804.     db 0eah        ;Absolute 16-bit jump, to clear
  1805.     dw @@RAW0,InitCS0        ;instruction pre-fetch & load CS.
  1806. @@RAW0:    mov    ax,KernalLDT        ;Point to empty LDT descriptor.
  1807.     lldt    ax        ;and set LDT.
  1808.     mov    cx,KernalTS        ;Get value for task register.
  1809.     ltr    cx        ;and set it.
  1810.     ;
  1811.     mov    Protected2Real,offset RawProt2Real
  1812.     mov    Real2Protected,offset RawReal2Prot
  1813.     jmp    @@inProt
  1814. ;
  1815. ;Use VCPI method to switch to protected mode.
  1816. ;
  1817. @@VCPI:    mov    cs:IErrorNumber,6
  1818.     cli
  1819.     push    ds
  1820.     xor    di,di        ;Page table offset.
  1821.     mov    es,Page1stReal    ;Page table segment
  1822.     mov    si,VCPI_0        ;VCPI GDT entries offset.
  1823.     and    si,not 3
  1824.     mov    ds,GDTReal        ;GDT segment.
  1825.     mov    ax,0de01h        ;Let VCPI server prepare.
  1826.     int    67h
  1827.     pop    ds
  1828.     or    ah,ah
  1829.     jnz    InitError
  1830.     mov    d[VCPI_Entry],ebx    ;Store entry point.
  1831.  
  1832. ; MED 11/05/96
  1833.     mov    FirstUninitPage,di    ; VCPI server advanced to first uninitialized page
  1834.                             ; table entry in client's page
  1835.  
  1836.     ;
  1837.     ;Now update PHYSICAL addresses of dir & 1st page tables.
  1838.     ;
  1839.     mov    es,Page1stReal
  1840.     movzx    edi,Page1stReal    ;get linear address.
  1841.     shl    edi,4        ;/
  1842.     shr    edi,12        ;page number.
  1843.     shl    edi,2        ;*4 bytes per entry.
  1844.     mov    eax,es:[di]        ;get physical address.
  1845.     and    eax,not 4095        ;clear status bits.
  1846.     or    eax,111b        ;set our bits.
  1847.     mov    es,PageDirReal
  1848.     xor    di,di
  1849.     mov    es:[di],eax
  1850.     mov    es,PageAliasReal
  1851.     mov    es:[di],eax
  1852.     ;
  1853.     mov    es,Page1stReal
  1854.     movzx    edi,PageDirReal    ;get linear address.
  1855.     shl    edi,4        ;/
  1856.     shr    edi,12        ;page number.
  1857.     shl    edi,2        ;*4 bytes per entry.
  1858.     mov    eax,es:[di]        ;get physical address.
  1859.     and    eax,0FFFFFFFFh-4095    ;clear status bits.
  1860.     mov    VCPI_CR3,eax        ;set VCPI CR3 value as well.
  1861.     mov    es,KernalTSSReal
  1862.     xor    di,di
  1863.     mov    es:[di].tCR3,eax    ;set CR3 in TSS as well.
  1864.     ;
  1865.     mov    es,Page1stReal
  1866.     movzx    edi,PageAliasReal    ;get linear address.
  1867.     shl    edi,4        ;/
  1868.     shr    edi,12        ;page number.
  1869.     shl    edi,2        ;*4 bytes per entry.
  1870.     mov    eax,es:[di]        ;get physical address.
  1871.     and    eax,0FFFFFFFFh-4095    ;clear status bits.
  1872.     or    eax,111b        ;user+write+present.
  1873.     mov    es,PageDirReal
  1874.     mov    di,1023*4
  1875.     mov    es:[di],eax        ;setup in last page dir entry.
  1876.     ;
  1877.     mov    VCPI_LDT,KernalLDT
  1878.     mov    VCPI_EIP,offset @@InProt
  1879.     mov    VCPI_TR,KernalTS    ;Get value for task register.
  1880.     mov    VCPI_CS,InitCS0
  1881.     xor    eax,eax
  1882.     mov    ax,seg _cwRaw
  1883.     shl    eax,4
  1884.     add    eax,offset GDTVal
  1885.     mov    VCPI_pGDT,eax
  1886.     xor    eax,eax
  1887.     mov    ax,seg _cwRaw
  1888.     shl    eax,4
  1889.     add    eax,offset IDTVal
  1890.     mov    VCPI_pIDT,eax
  1891.     cli
  1892.     mov    ax,0de0ch
  1893.     mov    si,seg _cwRaw
  1894.     movzx    esi,si
  1895.     shl    esi,4
  1896.     add    esi,offset VCPI_CR3
  1897.     int    67h
  1898.     ;
  1899.     mov    ax,_cwStack
  1900.     mov    ss,ax
  1901.     mov    esp,offset _cwStackEnd-4
  1902.     mov    ax,_cwRaw
  1903.     mov    ds,ax
  1904.     jmp    InitError        ;Shouldn't come through here.
  1905. ;
  1906. ;We're in protected mode at last, now we just have to move the DPMI emulation
  1907. ;stuff into extended memory and build a useful IDT.
  1908. ;
  1909. @@InProt:
  1910.     mov    ax,InitDS
  1911.     mov    ds,ax
  1912.     assume ds:_cwInit
  1913.     or    IProtectedMode,-1
  1914.     mov    ax,KernalDS        ;Get data descriptor.
  1915.     mov    ds,ax        ;/
  1916.     assume ds:_cwRaw
  1917.     mov    es,ax        ;/
  1918.     mov    fs,ax        ;/
  1919.     mov    gs,ax        ;/
  1920.     mov    ax,KernalPL0
  1921.     mov    ss,ax        ;/
  1922.     mov    esp,offset tPL0StackSize-4
  1923.     ;
  1924.     pushfd
  1925.     pop    eax
  1926.     and    ax,1011111111111111b    ;clear NT.
  1927.     push    eax
  1928.     popfd
  1929.     cld
  1930.     clts
  1931. ;
  1932. ;Switch to PL3 code seg for the hell of it.
  1933. ;
  1934.     .386
  1935.     mov    edx,offset _cwStackEnd-4
  1936.     mov    ecx,MainSS
  1937.     push    ecx        ;SS
  1938.     push    edx        ;ESP
  1939.     pushfd        ;EFlags
  1940.     pop    eax
  1941.     and    ax,1000111111111111b    ;clear NT & IOPL.
  1942.     or    ax,0011000000000000b    ;force IOPL.
  1943.     push    eax
  1944.     popfd
  1945.     push    eax
  1946.     xor    eax,eax
  1947.     mov    ax,InitCS
  1948.     push    eax        ;CS
  1949.     mov    eax,offset @@pl3
  1950.     push    eax        ;EIP
  1951.     db 66h
  1952.     iretd
  1953.     ;
  1954. @@pl3:    push    es
  1955.     mov    ax,KernalZero
  1956.     mov    es,ax
  1957.     mov    esi,GDTLinear
  1958.     add    esi,KernalTS-3
  1959.     mov    es:b[esi+5],DescPresent+DescPL3+Desc386Tss
  1960.     pop    es
  1961. ;
  1962. ;Setup initial segment variables.
  1963. ;
  1964.     push    ds
  1965.     mov    ax,MainDS
  1966.     mov    ds,ax
  1967.     assume ds:_cwMain
  1968.     or    w[SystemFlags],32768    ;Flags us in protected mode.
  1969.     mov    RealSegment,KernalZero
  1970.     mov    PspSegment,MainPSP
  1971.     mov    EnvSegment,MainENV
  1972.     mov    CodeSegment,MainCS
  1973.     mov    DataSegment,MainDS
  1974.     mov    StackSegment,MainSS
  1975.     assume ds:_cwRaw
  1976.     pop    ds
  1977. ;
  1978. ;Make sure A20 is enabled.
  1979. ;
  1980.     push    ds
  1981.     mov    ax,InitDS
  1982.     mov    ds,ax
  1983.     assume ds:_cwInit
  1984.     mov    IErrorNumber,7
  1985.     assume ds:_cwRaw
  1986.     pop    ds
  1987.     mov    ax,1
  1988.     push    cs
  1989.     push    offset @@1
  1990.     push    KernalCS
  1991.     push    offset A20Handler
  1992.     retf
  1993. @@1:    jnz    InitError
  1994. ;
  1995. ;Now get extended memory sorted out, move the page tables into extended memory
  1996. ;for a start.
  1997. ;
  1998.     push    ds
  1999.     mov    ax,InitDS
  2000.     mov    ds,ax
  2001.     assume ds:_cwInit
  2002.     mov    IErrorNumber,5
  2003.     assume ds:_cwRaw
  2004.     pop    ds
  2005.     mov    ax,KernalZero
  2006.     mov    es,ax
  2007. ;
  2008. ;Allocate 2nd page table so we can map extended memory.
  2009. ;
  2010.     call    d[fPhysicalGetPage]
  2011.     jc    InitError
  2012.     and    ecx,1        ;put user bits in useful place.
  2013.     shl    ecx,10
  2014.     and    edx,not 4095        ;lose user bits.
  2015.  
  2016.     or    edx,111b        ;present+user+write.
  2017.     or    edx,ecx        ;set use flags.
  2018.     mov    eax,1
  2019.     mov    esi,PageDIRLinear
  2020.     mov    es:d[esi+eax*4],edx    ;store this tables address.
  2021.     mov    esi,PageAliasLinear    ;get alias table address.
  2022.     mov    es:d[esi+eax*4],edx    ;setup in alias table as well.
  2023.     call    d[fCR3Flush]
  2024.     mov    edi,1024*4096*1023    ;base of page alias's.
  2025.     mov    eax,1024*4        ;get the entry number again.
  2026.     add    edi,eax
  2027.     mov    ecx,4096/4
  2028.     xor    eax,eax
  2029.     cld
  2030.     db 67h
  2031.     rep    stosd
  2032.     call    d[fCR3Flush]
  2033.     mov    LinearEntry,1024
  2034. ;
  2035. ;Setup DET page alias.
  2036. ;
  2037.     call    d[fPhysicalGetPage]    ;get page for new page 1st DET.
  2038.     jc    InitError
  2039.     mov    LinearEntry+8,edx    ;store physical address.
  2040.     and    ecx,1        ;put user bits in useful place.
  2041.     shl    ecx,10
  2042.     and    edx,not 4095        ;lose user bits.
  2043.     or    edx,111b        ;present+user+write.
  2044.     or    edx,ecx        ;set use flags.
  2045.     mov    eax,LinearEntry    ;get the entry number again.
  2046.     mov    esi,1024*4096*1023    ;base of page alias's.
  2047.     mov    es:d[esi+eax*4],edx    ;set physical address.
  2048.     call    d[fCR3Flush]
  2049.     mov    edi,LinearEntry
  2050.     shl    edi,12
  2051.     mov    ecx,4096/4
  2052.     xor    eax,eax
  2053.     cld
  2054.     db 67h
  2055.     rep    stosd        ;clear it.
  2056.     mov    eax,LinearEntry
  2057.     shl    eax,12        ;get linear address.
  2058.     mov    PageDETLinear,eax
  2059.     mov    eax,1022
  2060.     mov    esi,PageDIRLinear
  2061.     mov    edx,LinearEntry+8    ;get physical address again.
  2062.     or    edx,111b
  2063.     mov    es:[esi+eax*4],edx    ;put new page into the map.
  2064.     mov    esi,PageALIASLinear
  2065.     mov    es:[esi+eax*4],edx    ;put new page into the map.
  2066.     call    d[fCR3Flush]
  2067.     inc    LinearEntry
  2068. ;
  2069. ;Setup DET page 1st.
  2070. ;
  2071.     call    d[fPhysicalGetPage]    ;get page for new page 1st.
  2072.     jc    InitError
  2073.     mov    LinearEntry+8,edx    ;store physical address.
  2074.     and    ecx,1        ;put user bits in useful place.
  2075.     shl    ecx,10
  2076.     and    edx,not 4095        ;lose user bits.
  2077.     or    edx,111b        ;present+user+write.
  2078.     or    edx,ecx        ;set use flags.
  2079.     mov    esi,1024*4096*1023    ;base of page alias's.
  2080.     mov    eax,LinearEntry    ;get the entry number again.
  2081.     mov    es:d[esi+eax*4],edx    ;set physical address.
  2082.     call    d[fCR3Flush]
  2083.     mov    edi,LinearEntry
  2084.     shl    edi,12
  2085.     mov    ecx,4096/4
  2086.     mov    eax,MEM_FILL
  2087.     cld
  2088.     db 67h
  2089.     rep    stosd        ;copy old to new.
  2090.     mov    esi,PageDETLinear
  2091.     mov    eax,0
  2092.     mov    edx,LinearEntry+8    ;get physical address again.
  2093.     or    edx,111b
  2094.     mov    es:[esi+eax*4],edx    ;put new page into the map.
  2095.     call    d[fCR3Flush]
  2096.     inc    LinearEntry
  2097. ;
  2098. ;Allocate 2nd page DET
  2099. ;
  2100.     call    d[fPhysicalGetPage]    ;get page for new page 1st.
  2101.     jc    InitError
  2102.     mov    LinearEntry+8,edx    ;store physical address.
  2103.     and    ecx,1        ;put user bits in useful place.
  2104.     shl    ecx,10
  2105.     and    edx,not 4095        ;lose user bits.
  2106.     or    edx,111b        ;present+user+write.
  2107.     or    edx,ecx        ;set use flags.
  2108.     mov    esi,1024*4096*1023    ;base of page alias's.
  2109.     mov    eax,LinearEntry    ;get the entry number again.
  2110.     mov    es:d[esi+eax*4],edx    ;set physical address.
  2111.     call    d[fCR3Flush]
  2112.     mov    edi,LinearEntry
  2113.     shl    edi,12
  2114.     mov    ecx,4096/4
  2115.     mov    eax,MEM_FILL
  2116.     cld
  2117.     db 67h
  2118.     rep    stosd        ;copy old to new.
  2119.     mov    esi,PageDETLinear
  2120.     mov    eax,1
  2121.     mov    edx,LinearEntry+8    ;get physical address again.
  2122.     or    edx,111b
  2123.     mov    es:[esi+eax*4],edx    ;put new page into the map.
  2124.     call    d[fCR3Flush]
  2125.     inc    LinearEntry
  2126. ;
  2127. ;Move page alias into extended memory.
  2128. ;
  2129.     call    d[fPhysicalGetPage]    ;get page for new page 1st.
  2130.     jc    InitError
  2131.     mov    LinearEntry+8,edx    ;store physical address.
  2132.     and    ecx,1        ;put user bits in useful place.
  2133.     shl    ecx,10
  2134.     and    edx,not 4095        ;lose user bits.
  2135.     or    edx,111b        ;present+user+write.
  2136.     or    edx,ecx        ;set use flags.
  2137.     mov    eax,LinearEntry    ;get the entry number again.
  2138.     mov    esi,1024*4096*1023    ;base of page alias's.
  2139.     mov    es:d[esi+eax*4],edx    ;set physical address.
  2140.     call    d[fCR3Flush]
  2141.     push    ds
  2142.     mov    esi,PageAliasLinear
  2143.     mov    edi,LinearEntry
  2144.     shl    edi,12
  2145.     mov    ecx,4096/4
  2146.     push    es
  2147.     pop    ds
  2148.     cld
  2149.     db 67h
  2150.     rep    movsd        ;copy old to new.
  2151.     pop    ds
  2152.     mov    eax,PageALIASLinear
  2153.     mov    PageALIASLinear+4,eax
  2154.     mov    eax,LinearEntry
  2155.     shl    eax,12        ;get linear address.
  2156.     mov    PageALIASLinear,eax
  2157.     mov    esi,PageDIRLinear
  2158.     mov    eax,1023
  2159.     mov    edx,LinearEntry+8    ;get physical address again.
  2160.     or    edx,111b
  2161.     mov    ecx,es:[esi+eax*4]    ;get origional value.
  2162.     mov    PageALIASLinear+8,ecx
  2163.     mov    es:[esi+eax*4],edx    ;put new page into the map.
  2164.     mov    esi,PageALIASLinear
  2165.     mov    eax,1023
  2166.     mov    edx,LinearEntry+8    ;get physical address again.
  2167.     or    edx,111b
  2168.     mov    es:[esi+eax*4],edx    ;put new page into the map.
  2169.     call    d[fCR3Flush]
  2170.     inc    LinearEntry
  2171.  
  2172. ; MED 09/19/96
  2173. COMMENT !
  2174. ;
  2175. ;Move page 1st into extended memory.
  2176. ;
  2177.     call    d[fPhysicalGetPage]    ;get page for new page 1st.
  2178.     jc    InitError
  2179.     mov    LinearEntry+8,edx    ;store physical address.
  2180.     and    ecx,1        ;put user bits in useful place.
  2181.     shl    ecx,10
  2182.     and    edx,not 4095        ;lose user bits.
  2183.     or    edx,111b        ;present+user+write.
  2184.     or    edx,ecx        ;set use flags.
  2185.     ;
  2186.     ;Map it into general linear address space.
  2187.     ;
  2188.     mov    eax,LinearEntry    ;get the entry number again.
  2189.     mov    esi,1024*4096*1023    ;base of page alias's.
  2190.     mov    es:d[esi+eax*4],edx    ;set physical address.
  2191.     call    d[fCR3Flush]
  2192.     ;
  2193.     ;Copy table to new memory.
  2194.     ;
  2195.     push    ds
  2196.     mov    esi,Page1stLinear
  2197.     mov    edi,LinearEntry
  2198.     shl    edi,12
  2199.     mov    ecx,4096/4
  2200.     push    es
  2201.     pop    ds
  2202.     cld
  2203.     db 67h
  2204.     rep    movsd        ;copy old to new.
  2205.     pop    ds
  2206.     ;
  2207.     ;Make variables point to new memory.
  2208.     ;
  2209.     mov    eax,Page1stLinear
  2210.     mov    Page1stLinear+4,eax    ;store old address.
  2211.     mov    eax,LinearEntry
  2212.     shl    eax,12        ;get linear address.
  2213.     mov    Page1stLinear,eax    ;set new linear address.
  2214.     ;
  2215.     ;Set new address in page dir.
  2216.     ;
  2217.     mov    edx,LinearEntry+8    ;get physical address again.
  2218.     or    edx,111b
  2219.     ;
  2220.     mov    esi,PageDIRLinear
  2221.     mov    eax,0
  2222.     mov    ecx,es:[esi+eax*4]    ;get origional value.
  2223.     mov    Page1stLinear+8,ecx
  2224.     mov    es:[esi+eax*4],edx    ;put new page into the map.
  2225.     call    d[fCR3Flush]
  2226.     ;
  2227.     ;Set new address in page dir alias.
  2228.     ;
  2229.     mov    esi,PageALIASLinear
  2230.     mov    eax,0
  2231.     mov    es:[esi+eax*4],edx    ;put new page into the map.
  2232.     call    d[fCR3Flush]
  2233.     inc    LinearEntry
  2234. END COMMENT !
  2235.  
  2236. ;
  2237. ;Move page dir into extended memory.
  2238. ;
  2239.     call    d[fPhysicalGetPage]    ;get page for new page DIR.
  2240.     jc    InitError
  2241.     mov    LinearEntry+8,edx    ;store physical address.
  2242.     and    ecx,1        ;put user bits in useful place.
  2243.     shl    ecx,10
  2244.     and    edx,not 4095        ;lose user bits.
  2245.     or    edx,111b        ;present+user+write.
  2246.     or    edx,ecx        ;set use flags.
  2247.     ;
  2248.     ;Map it into normal linear address space.
  2249.     ;
  2250.     mov    eax,LinearEntry    ;get the entry number again.
  2251.     mov    esi,1024*4096*1023    ;base of page alias's.
  2252.     mov    es:d[esi+eax*4],edx    ;set physical address.
  2253.     call    d[fCR3Flush]
  2254.     ;
  2255.     ;Copy table to new memory.
  2256.     ;
  2257.     push    ds
  2258.     mov    esi,PageDIRLinear
  2259.     mov    edi,LinearEntry
  2260.     shl    edi,12
  2261.     mov    ecx,4096/4
  2262.     push    es
  2263.     pop    ds
  2264.     cld
  2265.     db 67h
  2266.     rep    movsd        ;copy old to new.
  2267.     pop    ds
  2268.     ;
  2269.     ;Make variables point to new memory.
  2270.     ;
  2271.     mov    eax,PageDirLinear
  2272.     mov    PageDIRLinear+4,eax    ;store old value.
  2273.     mov    eax,LinearEntry
  2274.     shl    eax,12        ;get linear address.
  2275.     mov    PageDIRLinear,eax    ;set new value.
  2276.     mov    eax,VCPI_CR3
  2277.     mov    PageDIRLinear+8,eax    ;store old physical address.
  2278.     mov    eax,LinearEntry+8
  2279.     mov    VCPI_CR3,eax        ;set new physical address.
  2280.     movzx    edi,KernalTSSReal
  2281.     shl    edi,4
  2282.     mov    es:[edi].tCR3,eax    ;set CR3 in TSS as well.
  2283.     call    d[fCR3Flush]
  2284.     inc    LinearEntry
  2285. ;
  2286. ;Setup IDT.
  2287. ;
  2288.     call    d[fPhysicalGetPage]    ;get page for new page DIR.
  2289.     jc    InitError
  2290.     mov    LinearEntry+8,edx    ;store physical address.
  2291.     and    ecx,1        ;put user bits in useful place.
  2292.     shl    ecx,10
  2293.     and    edx,not 4095        ;lose user bits.
  2294.     or    edx,111b        ;present+user+write.
  2295.     or    edx,ecx        ;set use flags.
  2296.     mov    eax,LinearEntry    ;get the entry number again.
  2297.     mov    esi,1024*4096*1023    ;base of page alias's.
  2298.     mov    es:d[esi+eax*4],edx    ;set physical address.
  2299.     call    d[fCR3Flush]
  2300.     mov    eax,LinearEntry
  2301.     shl    eax,12
  2302.     mov    d[IDTVal+2],eax
  2303.     mov    w[IDTVal],0+(256*8)-1
  2304.     ;
  2305.     mov    bp,256        ;number of vectors.
  2306.     mov    ecx,offset InterruptHandler ;code address.
  2307.     mov    esi,DpmiEmuCS0    ;gate to use.
  2308.     mov    al,0
  2309.     mov    ah,DescPresent+DescPL3+Desc386Int
  2310.     mov    edi,d[IDTVal+2]
  2311. @@3:    call    MakeDesc2
  2312.     add    edi,8        ;next table address.
  2313.     add    ecx,8        ;/
  2314.     dec    bp
  2315.     jnz    @@3
  2316.     inc    LinearEntry
  2317.     ;
  2318.     ;Re-load IDT value.
  2319.     ;
  2320.     push    es
  2321.     mov    edi,offset MemIntBuffer
  2322.     push    ds
  2323.     pop    es
  2324.     mov    Real_CS[edi],_cwInit
  2325.     mov    Real_IP[edi],offset IDTFlush
  2326.     mov    Real_SS[edi],0
  2327.     mov    Real_SP[edi],0
  2328.     call    d[fRawSimulateFCALL]
  2329.     pop    es
  2330. ;
  2331. ;Get extended memory for DPMI emulator.
  2332. ;
  2333.     push    ds
  2334.     mov    ax,InitDS
  2335.     mov    ds,ax
  2336.     assume ds:_cwInit
  2337.     mov    IErrorNumber,5
  2338.     assume ds:_cwRaw
  2339.     pop    ds
  2340.     ;
  2341.     mov    ebp,offset cwDPMIEMUEnd-cwDPMIEMUStart
  2342.     add    ebp,4095
  2343.     shr    ebp,12        ;Get number of pages needed.
  2344.     mov    eax,LinearEntry
  2345.     shl    eax,12
  2346.     mov    LinearEntry+4,eax    ;Store start address.
  2347. @@2:    call    d[fPhysicalGetPage]    ;try to allocate a page.
  2348.     jc    InitError
  2349.     and    ecx,1        ;put user bits in useful place.
  2350.     shl    ecx,10
  2351.     and    edx,not 4095        ;lose user bits.
  2352.     or    edx,111b        ;present+user+write.
  2353.     or    edx,ecx        ;set use flags.
  2354.     mov    eax,LinearEntry    ;get the entry number again.
  2355.     mov    esi,1024*4096*1023    ;base of page alias's.
  2356.     mov    es:d[esi+eax*4],edx    ;set physical address.
  2357.     call    d[fCR3Flush]
  2358.     inc    LinearEntry        ;update pointer.
  2359.     dec    ebp
  2360.     jnz    @@2
  2361. ;
  2362. ;Copy DPMI emulator code into extended memory we just allocated.
  2363. ;
  2364.     mov    edi,LinearEntry+4    ;Get the destination.
  2365.     mov    si,_cwDPMIEMU
  2366.     movzx    esi,si
  2367.     shl    esi,4        ;Point to the source.
  2368.     mov    ecx,offset cwDPMIEMUEnd-cwDPMIEMUStart
  2369.     shr    ecx,2
  2370.     push    ds
  2371.     push    es
  2372.     pop    ds
  2373.     cld
  2374.     db 67h
  2375.     rep    movsd        ;Copy it up their.
  2376.     pop    ds
  2377. ;
  2378. ;Setup DPMI emulator selectors.
  2379. ;
  2380.     push    es
  2381.     mov    ax,GDTData
  2382.     mov    es,ax
  2383.     mov    esi,LinearEntry+4
  2384.     mov    ecx,offset cwDPMIEMUEnd-cwDPMIEMUStart
  2385.     mov    al,1 shl 6
  2386.     mov    ah,DescPresent+DescPL3+DescMemory+DescERCode
  2387.     mov    di,DpmiEmuCS
  2388.     call    MakeDesc
  2389.     mov    esi,LinearEntry+4
  2390.     mov    ecx,offset cwDPMIEMUEnd-cwDPMIEMUStart
  2391.     mov    al,1 shl 6
  2392.     mov    ah,DescPresent+DescPL0+DescMemory+DescERCode
  2393.     mov    di,DpmiEmuCS0
  2394.     call    MakeDesc
  2395.     mov    esi,LinearEntry+4
  2396.     mov    ecx,offset cwDPMIEMUEnd-cwDPMIEMUStart
  2397.     mov    al,1 shl 6
  2398.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  2399.     mov    di,DpmiEmuDS
  2400.     call    MakeDesc
  2401.     pop    es
  2402. ;
  2403. ;Should be OK to enable interrupts at last.
  2404. ;
  2405.     mov    ah,1
  2406.     int    16h
  2407.     sti
  2408. ;
  2409. ;Initialise hardware interrupt call-back's.
  2410. ;
  2411.     call    InitHardwareInts
  2412. ;
  2413. ;Allocate memory for new GDT/LDT
  2414. ;
  2415.     push    ds
  2416.     mov    ax,InitDS
  2417.     mov    ds,ax
  2418.     assume ds:_cwInit
  2419.     mov    IErrorNumber,5
  2420.     assume ds:_cwRaw
  2421.     pop    ds
  2422.     ;
  2423.     mov    ebp,(8192*8)+8192
  2424.     shr    ebp,12        ;Get number of pages needed.
  2425.     mov    eax,LinearEntry
  2426.     shl    eax,12
  2427.     mov    LinearEntry+4,eax    ;Store start address.
  2428. @@6:    call    d[fPhysicalGetPage]    ;try to allocate a page.
  2429.     jc    InitError
  2430.     and    ecx,1        ;put user bits in useful place.
  2431.     shl    ecx,10
  2432.     and    edx,not 4095        ;lose user bits.
  2433.     or    edx,111b        ;present+user+write.
  2434.     or    edx,ecx        ;set use flags.
  2435.     mov    eax,LinearEntry    ;get the entry number again.
  2436.     mov    esi,1024*4096*1023    ;base of page alias's.
  2437.     mov    es:d[esi+eax*4],edx    ;set physical address.
  2438.     call    d[fCR3Flush]
  2439.     inc    LinearEntry        ;update pointer.
  2440.     dec    ebp
  2441.     jnz    @@6
  2442.     ;
  2443.     mov    esi,LinearEntry+4
  2444.     mov    MDTLinear,esi    ;store for allocation code.
  2445.     mov    MDTLinear+4,esi
  2446.     add    MDTLinear+4,8192*8    ;setup bit string address.
  2447.     ;
  2448.     ;Clear the memory to zero's.
  2449.     ;
  2450.     mov    edi,MDTLinear
  2451.     mov    ecx,(8192*8)+8192
  2452.     cld
  2453.     xor    al,al
  2454.     db 67h
  2455.     rep    stosb
  2456.     mov    edi,MDTLinear+4
  2457.     or    es:d[edi],-1        ;Force VCPI values to not used.
  2458.     ;
  2459.     ;See which table we want to use.
  2460.     ;
  2461.     test    RawSystemFlags,128    ;GDT or LDT?
  2462.     jnz    @@LDT
  2463.     ;
  2464.     ;Setup a new GDT.
  2465.     ;
  2466.     mov    esi,MDTLinear
  2467.     mov    GDTLinear+4,esi
  2468.     mov    ecx,65535
  2469.     xor    al,al
  2470.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  2471.     mov    di,GDTData
  2472.     push    es
  2473.     mov    es,di
  2474.     call    MakeDesc
  2475.     pop    es
  2476.     ;
  2477.     ;Copy current GDT to new GDT.
  2478.     ;
  2479.     push    ds
  2480.     mov    esi,GDTLinear
  2481.     mov    edi,GDTLinear+4
  2482.     mov    ax,KernalZero
  2483.     mov    ds,ax
  2484.     mov    ecx,GDT_Entries*8
  2485.     cld
  2486.     db 67h
  2487.     rep    movsb
  2488.     pop    ds
  2489.     ;
  2490.     ;Set new GDT values.
  2491.     ;
  2492.     pushf
  2493.     cli
  2494.     mov    eax,GDTLinear
  2495.     mov    GDTLinear+8,eax
  2496.     mov    eax,GDTLinear+4
  2497.     mov    GDTLinear,eax
  2498.     mov    d[GDTVal+2],eax
  2499.     mov    d[VCPI_GDT+2],eax
  2500.     popf
  2501.     ;
  2502.     ;Now mark all used descriptors in allocation control string.
  2503.     ;
  2504.     mov    edi,GDTLinear
  2505.     mov    esi,MDTLinear+4
  2506.     mov    cx,GDT_Entries
  2507. @@4:    test    es:b[edi+5],DescPresent    ;this descriptor in use?
  2508.     jz    @@5
  2509.     or    es:b[esi],-1
  2510. @@5:    add    edi,8        ;next descriptor.
  2511.     inc    esi        ;update descriptor number.
  2512.     dec    cx
  2513.     jnz    @@4
  2514.     ;
  2515.     ;Now setup extra GDT descriptors.
  2516.     ;
  2517.     push    es
  2518.     mov    ax,GDTData
  2519.     mov    es,ax
  2520.     ;
  2521.     mov    di,KernalB000
  2522.     mov    esi,0b0000h
  2523.     mov    ecx,65535
  2524.     xor    al,al
  2525.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  2526.     call    MakeDesc
  2527.     ;
  2528.     mov    di,KernalB800
  2529.     mov    esi,0b8000h
  2530.     mov    ecx,65535
  2531.     xor    al,al
  2532.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  2533.     call    MakeDesc
  2534.     ;
  2535.     mov    di,KernalA000
  2536.     mov    esi,0a0000h
  2537.     mov    ecx,65535
  2538.     xor    al,al
  2539.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  2540.     call    MakeDesc
  2541.     pop    es
  2542.     ;
  2543. @@LDT:    ;Setup new LDT.
  2544.     ;
  2545.     mov    esi,MDTLinear
  2546.     mov    LDTLinear,esi
  2547.     ;
  2548.     ;Map LDT into GDT.
  2549.     ;
  2550.     push    es
  2551.     mov    ax,GDTData
  2552.     mov    es,ax
  2553.     mov    di,KernalLDT
  2554.     mov    esi,LDTLinear
  2555.     mov    ecx,8192*8
  2556.     xor    al,al
  2557.     mov    ah,DescPresent+DescPL3+DescLDT
  2558.     call    MakeDesc
  2559.     pop    es
  2560.     ;
  2561.     mov    ah,1
  2562.     int    16h        ;force GDT/LDT reload with mode switch.
  2563. ;
  2564. ;Initialise application memory pool.
  2565. ;
  2566.     mov    eax,LinearEntry
  2567.     shl    eax,12
  2568.     mov    LinearBase,eax
  2569.     add    eax,4096
  2570.     mov    LinearLimit,eax
  2571.     ;
  2572.     call    d[fPhysicalGetPage]    ;try to allocate a page.
  2573.     jc    InitError
  2574.  
  2575.     and    ecx,1        ;put user bits in useful place.
  2576.     shl    ecx,10
  2577.     and    edx,not 4095        ;lose user bits.
  2578.     or    edx,111b        ;present+user+write.
  2579.     or    edx,ecx        ;set use flags.
  2580.     mov    eax,LinearEntry    ;get the entry number again.
  2581.     mov    esi,1024*4096*1023    ;base of page alias's.
  2582.     mov    es:d[esi+eax*4],edx    ;set physical address.
  2583.     call    d[fCR3Flush]
  2584.     mov    eax,LinearEntry    ;get the entry number again.
  2585.     mov    esi,1024*4096*1022
  2586.     mov    es:d[esi+eax*4],0    ;clear this pages details.
  2587. ;
  2588. ;Initialise virtual memory manager stuff.
  2589. ;
  2590.     call    d[fPhysicalGetPages]    ;find free pages.
  2591.     mov    eax,edx
  2592.     shl    eax,12
  2593.     add    eax,LinearLimit
  2594.     sub    eax,LinearBase
  2595.     mov    ebp,eax        ;save this for comparisons.
  2596.     mov    di,InitDS
  2597.     mov    fs,di
  2598.     mov    di,offset VMMDrivPath1    ;point to start of paths.
  2599.     assume fs:_cwInit
  2600.     cmp    fs:NoVMSwitch,0
  2601.     assume fs:nothing
  2602.     jnz    @@v9
  2603.     ;
  2604.     ;Work through list of posibles till we find a useful entry.
  2605.     ;
  2606. @@v0:
  2607.     cmp    fs:b[di],0
  2608.     jz    @@v7
  2609.     cmp    fs:b[di],-1
  2610.     jz    @@v9
  2611.     ;
  2612.     ;Check drive is valid and has enough free space.
  2613.     ;
  2614.  
  2615. COMMENT !
  2616. ; MED 10/11/96
  2617. ; if no drivespec, then use default drive
  2618.     cmp    BYTE PTR fs:[di+1],':'
  2619.     je    isdrive
  2620.  
  2621.     movzx    edx,di    ; scan to end of current pathspec
  2622. defloop:
  2623.     inc    dx            ; edx known 16-bit value so 16-bit increment is valid
  2624.     cmp    BYTE PTR fs:[edx],0
  2625.     jne    defloop
  2626.  
  2627. ; at end of current pathspec, now shift forward two bytes to allow for drive
  2628. shiftloop:
  2629.     mov    al,fs:[edx]
  2630.     mov    fs:[edx+2],al
  2631.     dec    dx
  2632.     cmp    di,dx        ; edx known 16-bit value so 16-bit compare is valid
  2633.     jae    shiftloop
  2634.  
  2635.     push    edi
  2636.     mov    edi,offset PageInt
  2637.     push    ds
  2638.     pop    es
  2639.     mov    [edi].Real_EAX,1900h
  2640.     mov    Real_SS[edi],0
  2641.     mov    Real_SP[edi],0
  2642.     mov    bl,21h
  2643.     call    d[fRawSimulateINT]
  2644.     mov    al,BYTE PTR [edi].Real_EAX
  2645.     pop    edi
  2646.     add    al,'A'        ; convert to drive
  2647.     mov    fs:[di],al
  2648.     mov    BYTE PTR fs:[di+1],':'    ; add colon to drivespec
  2649. END COMMENT !
  2650.  
  2651. isdrive:
  2652.     mov    dl,fs:[di]        ;get swap file drive.
  2653.     cmp    dl,61h        ; 'a'
  2654.     jb    @@v1
  2655.     cmp    dl,7Ah        ; 'z'
  2656.     ja    @@v1
  2657.     and    dl,5Fh        ;convert to upper case.
  2658. @@v1:    sub    dl,'A'        ;make it real.
  2659.     inc    dl        ;adjust for current type selection.
  2660.  
  2661. drivefree:
  2662.     mov    ah,36h        ;get free space.
  2663.     push    ebp
  2664.     int    21h        ;/
  2665.     pop    ebp
  2666.     cmp    ax,-1        ;invalid drive?
  2667.     jz    @@v7
  2668.     mul    cx        ;Get bytes per cluster.
  2669.     mul    bx        ;Get bytes available.
  2670.     shl    edx,16
  2671.     mov    dx,ax
  2672.     cmp    edx,ebp        ;Enough free space.
  2673.     jc    @@v7
  2674.     ;
  2675.     ;See if we can create a temp file.
  2676.     ;
  2677.  
  2678. ; MED 02/25/96, use name specified in CAUSEWAY e-var
  2679.     test    DesiredVMMName,-1
  2680.     je    med5a            ; no VMM name request
  2681.     push    di
  2682.     mov    si,di
  2683.     push    si            ; save -> filespec start
  2684.  
  2685. ; find end of pathspec
  2686. mednameloop:
  2687.     cmp    BYTE PTR fs:[si],0
  2688.     je    medndone
  2689.     inc    si
  2690.     jmp    mednameloop
  2691.  
  2692. ; append desired name on filespec
  2693. medndone:
  2694.  
  2695. ; 05/15/98
  2696. ; check for backslash already existing
  2697.     cmp    BYTE PTR fs:[si-1],'\'
  2698.     je    medbs
  2699.  
  2700.     mov    BYTE PTR fs:[si],'\'
  2701.     inc    si
  2702.  
  2703. medbs:
  2704.     mov    di,offset DesiredVMMName
  2705.  
  2706. medtransloop:
  2707.     mov    al,[di]
  2708.     mov    fs:[si],al
  2709.     inc    di
  2710.     inc    si
  2711.     test    al,al
  2712.     jne    medtransloop
  2713.     pop    si                ; restore si -> filespec start
  2714.  
  2715.     mov    edi,offset PageInt
  2716.     push    ds
  2717.     pop    es
  2718.     mov    [edi].Real_DS,_cwInit
  2719.     mov    [edi].Real_EDX,esi
  2720.     mov    [edi].Real_EAX,3c00h
  2721.     mov    [edi].Real_ECX,0
  2722.     mov    Real_SS[edi],0
  2723.     mov    Real_SP[edi],0
  2724.     mov    bl,21h
  2725.     call    d[fRawSimulateINT]
  2726.     test    Real_Flags[edi],1
  2727.     mov    eax,Real_EAX[edi]
  2728.     pop    di
  2729.     jz    @@v8
  2730.     jmp    @@v7
  2731.     ;
  2732.  
  2733. med5a:
  2734.     push    di
  2735.     mov    si,di
  2736.     mov    edi,offset PageInt
  2737.     push    ds
  2738.     pop    es
  2739.     mov    [edi].Real_DS,_cwInit
  2740.     mov    [edi].Real_EDX,esi
  2741.     mov    [edi].Real_EAX,5a00h
  2742.     mov    [edi].Real_ECX,0
  2743.     mov    Real_SS[edi],0
  2744.     mov    Real_SP[edi],0
  2745.     mov    bl,21h
  2746.     call    d[fRawSimulateINT]
  2747.     test    Real_Flags[edi],1
  2748.     mov    eax,Real_EAX[edi]
  2749.     pop    di
  2750.     jz    @@v8
  2751.     ;
  2752. @@v7:    add    di,128
  2753.     jmp    @@v0
  2754.     ;
  2755. @@v8:    ;Store the handle and copy the name accross.
  2756.     ;
  2757.     mov    VMMHandle,ax        ;store the handle.
  2758.     pushm    ds,fs
  2759.     pop    ds
  2760.     mov    di,offset VMMName
  2761.     mov    cx,128
  2762.     rep    movsb
  2763.     pop    ds
  2764.     mov    al,VMMName
  2765.     cmp    al,61h        ; 'a'
  2766.     jb    @@v2
  2767.     cmp    al,7Ah        ; 'z'
  2768.     ja    @@v2
  2769.     and    al,5Fh        ;convert to upper case.
  2770. @@v2:    mov    VMMName,al
  2771.  
  2772. ; MED 02/25/96, if pre-allocate, then force write to allocated size
  2773.     cmp    PreAllocSize,0
  2774.     je    medpre2
  2775.     mov    bx,VMMHandle
  2776.     mov    ecx,PreAllocSize
  2777.     mov    dx,cx
  2778.     shr    ecx,16
  2779.     mov    ax,4200h    ; seek from beginning of file
  2780.     int    21h
  2781.     xor    cx,cx        ; write zero bytes (pre-allocating based on seek)
  2782.     mov    ah,40h        ; write to file
  2783.     int    21h
  2784.     mov    ah,68h        ; commit file
  2785.     int    21h
  2786.     xor    dx,dx        ; get current size of swap file
  2787.     mov    cx,dx
  2788.     mov    ax,4202h
  2789.     int    21h
  2790.     mov    WORD PTR SwapFileLength,ax    ; update internal swapfile length variable
  2791.     mov    WORD PTR SwapFileLength+2,dx
  2792.  
  2793. medpre2:
  2794.     ;
  2795.     ;Now patch the exception vector.
  2796.     ;
  2797.     mov    bl,14        ;Page fault vector.
  2798.     movzx    eax,bl
  2799.     mov    ebx,eax
  2800.     shl    ebx,1        ;*2
  2801.     mov    eax,ebx
  2802.     shl    ebx,1        ;*4
  2803.     add    ebx,eax        ;*6
  2804.     push    ds
  2805.     mov    ax,DpmiEmuDS
  2806.     mov    ds,ax
  2807.     assume ds:_cwDPMIEMU
  2808.     add    ebx,offset ExceptionTable
  2809.     mov    edx,[ebx]        ;get offset.
  2810.     mov    cx,4[ebx]        ;get segment selector.
  2811.     mov    w[OldExcep14+4],cx
  2812.     mov    d[OldExcep14],edx    ;store 32 bit offset.
  2813.     mov    d[ebx],offset VirtualFault    ;set offset.
  2814.     mov    w[ebx+4],DpmiEmuCS    ;set segment selector.
  2815.     or    DpmiEmuSystemFlags,1 shl 1 ;flag VMM's presence.
  2816.     mov    ax,MainDS
  2817.     mov    ds,ax
  2818.     assume ds:_cwMain
  2819.     or    SystemFlags,1 shl 1    ;flag VMM's presence.
  2820.     assume ds:_cwRaw
  2821.     pop    ds
  2822.     or    RawSystemFlags,1 shl 1    ;flag VMM's presence.
  2823. @@v9:    ;
  2824.     push    ds
  2825.     pop    fs
  2826.  
  2827.     mov    ax,InitDS
  2828.     mov    ds,ax
  2829.     assume ds:_cwInit
  2830.     jmp    @@InProtected
  2831. ;
  2832. ;Do initialisations needed for DPMI
  2833. ;
  2834. @@InitDPMI:    mov    ax,_cwMain
  2835.     mov    ds,ax
  2836.     assume ds:_cwMain
  2837. ;
  2838. ;Get some memory for the transfer buffer.
  2839. ;
  2840.     mov    cs:IErrorNumber,5
  2841.     mov    bx,8192/16
  2842.     mov    ah,48h
  2843.     int    21h        ;get memory for transfer buffer.
  2844.     jc    InitError
  2845.     mov    TransferReal,ax
  2846. ;
  2847. ;Get some memory for the INT buffer.
  2848. ;
  2849.     mov    bx,((RawStackTotal/2)/16)+1
  2850.     mov    ah,48h
  2851.     int    21h
  2852.     jc    InitError
  2853.     mov    DPMIStackSeg,ax
  2854.     mov    DPMIStackOff,RawStackTotal/2
  2855. ;
  2856. ;Do instalation check and get mode switch address.
  2857. ;
  2858.     mov    cs:IErrorNumber,9
  2859.     mov    ax,1687h        ;DPMI instalation check.
  2860.     int    2fh
  2861.     or    ax,ax        ;None-zero means its not there.
  2862.     jnz    InitError
  2863. ;
  2864. ;Check for 32-bit support if needed.
  2865. ;
  2866.     test    SystemFlags,1 shl 14    ;Dual mode?
  2867.     jnz    @@Use16Bit23
  2868.     ;
  2869.     test    SystemFlags,1
  2870.     jz    @@Use32Bit23
  2871.     jmp    @@Use16Bit23
  2872. @@Use32Bit23:    mov    cs:IErrorNumber,9
  2873.     test    bx,1        ;Must offer 32 bit support.
  2874.     jz    InitError
  2875. @@Use16Bit23:    mov    bx,si        ;Get DPMI save buffer size.
  2876.     mov    ax,si
  2877.     or    bx,bx
  2878.     jz    @@d0        ;No guarante that it'll need it.
  2879. ;
  2880. ;Allocate memory for DPMI state save buffer.
  2881. ;
  2882.     mov    cs:IErrorNumber,5
  2883.     push    di
  2884.     push    es
  2885.     mov    ah,48h
  2886.     int    21h        ;Try and claim memory for it.
  2887.     pop    es
  2888.     pop    di
  2889.     mov    bx,ax
  2890.     jc    InitError
  2891. @@d0:    pushm    ax,ds
  2892.     mov    ax,_cwInit
  2893.     mov    ds,ax
  2894.     assume ds:_cwInit
  2895.     mov    DPMISwitch,di    ;Store the switch call address.
  2896.     mov    DPMISwitch+2,es
  2897.     mov    es,bx
  2898.     popm    ax,ds
  2899.     assume ds:_cwMain
  2900. ;
  2901. ;Attempt to switch mode.
  2902. ;
  2903.     test    SystemFlags,1
  2904.     jz    @@Use32Bit24
  2905.     xor    ax,ax        ;16 bit segments for this code.
  2906.     jmp    @@Use16Bit24
  2907. @@Use32Bit24:    mov    ax,1        ;32 bit segments for this code.
  2908. @@Use16Bit24:    push    ax
  2909.     mov    ax,_cwInit
  2910.     mov    ds,ax
  2911.     pop    ax
  2912.     assume ds:_cwInit
  2913.     pusha
  2914.     call    d[DPMISwitch]    ;Make the switch.
  2915.     popa
  2916.     jnc    @@DpmiInProtected
  2917.     mov    IErrorNumber,9
  2918.     push    ax
  2919.     mov    ax,_cwMain
  2920.     mov    ds,ax
  2921.     pop    ax
  2922.     assume ds:_cwMain
  2923.     test    w[SystemFlags+2],1    ;Dual mode?
  2924.     jz    InitError
  2925.     xor    SystemFlags,1
  2926.     xor    ax,1        ;toggle the mode.
  2927.     push    ax
  2928.     mov    ax,_cwInit
  2929.     mov    ds,ax
  2930.     pop    ax
  2931.     assume ds:_cwInit
  2932.     call    d[DPMISwitch]    ;Make the switch.
  2933.     jc    InitError        ;really isn't feeling well.
  2934. @@DpmiInProtected:
  2935.     mov    iDataSegment,ds
  2936.     mov    iCodeSegment,cs
  2937.     mov    iStackSegment,ss
  2938.     mov    iPSPSegment,es
  2939.     xor    eax,eax
  2940.     mov    ax,sp
  2941.     mov    esp,eax
  2942.     mov    ax,es:[2ch]
  2943.     mov    iENVSegment,ax
  2944. ;
  2945. ;Create _cwMain code segment.
  2946. ;
  2947.     mov    iErrorNumber,8
  2948.     mov    ax,0000h
  2949.     mov    cx,1
  2950.     int    31h        ;allocate a selector.
  2951.     jc    InitError
  2952.     mov    mCodeSegment,ax
  2953.     mov    bx,ax
  2954.     push    ds
  2955.     pop    es
  2956.     mov    di,offset dpmiSelBuffer
  2957.     mov    si,_cwMain
  2958.     movzx    esi,si
  2959.     shl    esi,4
  2960.     mov    ecx,65535
  2961.     xor    al,al
  2962.     mov    ah,DescPresent+DescPL3+DescMemory+DescERCode
  2963.     call    MakeDesc
  2964.     mov    ax,000ch
  2965.     push    ds
  2966.     pop    es
  2967.     mov    edi,offset dpmiSelBuffer
  2968.     int    31h
  2969. ;
  2970. ;Create _cwMain data segment.
  2971. ;
  2972.     mov    iErrorNumber,8
  2973.     mov    ax,0000h
  2974.     mov    cx,1
  2975.     int    31h        ;allocate a selector.
  2976.     jc    InitError
  2977.     mov    mDataSegment,ax
  2978.     mov    bx,ax
  2979.     push    ds
  2980.     pop    es
  2981.     mov    di,offset dpmiSelBuffer
  2982.     mov    si,_cwMain
  2983.     movzx    esi,si
  2984.     shl    esi,4
  2985.     mov    ecx,65535
  2986.     xor    al,al
  2987.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  2988.     call    MakeDesc
  2989.     mov    ax,000ch
  2990.     push    ds
  2991.     pop    es
  2992.     mov    edi,offset dpmiSelBuffer
  2993.     int    31h
  2994. ;
  2995. ;Create a 0-4G selector.
  2996. ;
  2997.     mov    iErrorNumber,8
  2998.     mov    ax,0000h
  2999.     mov    cx,1
  3000.     int    31h        ;allocate a selector.
  3001.     jc    InitError
  3002.     mov    iRealSegment,ax
  3003.     mov    bx,ax
  3004.     push    ds
  3005.     pop    es
  3006.     mov    di,offset dpmiSelBuffer
  3007.     xor    esi,esi
  3008.     or    ecx,-1
  3009.     xor    al,al
  3010.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  3011.     call    MakeDesc
  3012.     mov    ax,000ch
  3013.     push    ds
  3014.     pop    es
  3015.     mov    edi,offset dpmiSelBuffer
  3016.     int    31h
  3017. ;
  3018. ;Make main seg addressable now.
  3019. ;
  3020.     mov    ax,mDataSegment
  3021.     mov    es,ax
  3022.     assume es:_cwMain
  3023.     mov    ax,mCodeSegment
  3024.     mov    es:CodeSegment,ax
  3025.     mov    es:w[TerminationHandler+4],ax
  3026.     mov    ax,mDataSegment
  3027.     mov    es:DataSegment,ax
  3028.     mov    ax,iStackSegment
  3029.     mov    es:StackSegment,ax
  3030.     mov    ax,iPSPSegment
  3031.     mov    es:PSPSegment,ax
  3032.     mov    ax,iENVSegment
  3033.     mov    es:ENVSegment,ax
  3034.     mov    ax,iRealSegment
  3035.     mov    es:RealSegment,ax
  3036.     mov    ax,iCodeSegment
  3037.     mov    es:CodeSegmenti,ax
  3038.     mov    ax,iDataSegment
  3039.     mov    es:DataSegmenti,ax
  3040.     push    es
  3041.     pop    ds
  3042.     assume es:nothing
  3043.     assume ds:_cwMain
  3044.  
  3045.  
  3046. ;
  3047. ;Patch INT 21h exec function to preserve the stack.
  3048. ;
  3049.     if    0
  3050.     mov    bl,21h
  3051.     mov    ax,200h
  3052.     int    31h
  3053.     mov    w[OldInt21hExec],dx
  3054.     mov    w[OldInt21hExec+2],cx
  3055.     mov    dx,offset Int21hExecPatch
  3056.     mov    cx,_cwMain
  3057.     mov    bl,21h
  3058.     mov    ax,201h
  3059.     int    31h
  3060.     endif
  3061. ;
  3062. ;Make right stuff addresable again.
  3063. ;
  3064.     mov    ds,DataSegmenti
  3065.     assume ds:_cwInit
  3066.     or    IProtectedMode,-1
  3067. ;
  3068. ;Now get on with installing the higher level stuff.
  3069. ;
  3070. @@InProtected:    mov    ax,mDataSegment
  3071.     mov    ds,ax
  3072.     assume ds:_cwMain
  3073.     ;
  3074.     mov    ax,ProtectedType    ;Copy protected mode environment type into common
  3075.     shl    ax,1+1        ;variable for application access. Might become useful
  3076.     or    w[SystemFlags],ax    ;at some point. Other flags can be added at will.
  3077.     mov    ax,ProtectedFlags
  3078.     shl    ax,1+1+2
  3079.     or    w[SystemFlags],ax
  3080.     or    w[SystemFlags],32768    ;Flags us in protected mode.
  3081.     ;
  3082.     mov    ax,DataSegmenti
  3083.     mov    ds,ax
  3084.     assume ds:_cwInit
  3085. ;
  3086. ;Add CW API patch to int 31h and 2Fh.
  3087. ;
  3088.     mov    IErrorNumber,5
  3089.     xor    bx,bx
  3090.     mov    cx,offset _apiCodeEnd-_apiCodeStart
  3091.     mov    ax,0501h
  3092.     int    31h        ;Get memory.
  3093.     jc    InitError
  3094.     xor    si,si
  3095.     mov    di,offset _apiCodeEnd-_apiCodeStart
  3096.     mov    ax,0600h
  3097.     int    31h        ;Lock memory.
  3098.     jc    InitError
  3099.     shl    ebx,16
  3100.     mov    bx,cx
  3101.     mov    dpmiSelBase,ebx
  3102. ;
  3103. ;Allocate code selector.
  3104. ;
  3105.     mov    iErrorNumber,8
  3106.     mov    ax,0000h
  3107.     mov    cx,1
  3108.     int    31h        ;allocate a selector.
  3109.     jc    InitError
  3110.     mov    dpmiCodeSel,ax
  3111.     mov    bx,ax
  3112.     push    ds
  3113.     pop    es
  3114.     mov    di,offset dpmiSelBuffer
  3115.     mov    esi,dpmiSelBase
  3116.     mov    ecx,offset _apiCodeEnd-_apiCodeStart
  3117.     mov    al,1 shl 6
  3118.     mov    ah,DescPresent+DescPL3+DescMemory+DescERCode
  3119.     call    MakeDesc
  3120.     mov    ax,000ch
  3121.     push    ds
  3122.     pop    es
  3123.     mov    edi,offset dpmiSelBuffer
  3124.     int    31h
  3125. ;
  3126. ;Allocate data selector.
  3127. ;
  3128.     mov    iErrorNumber,8
  3129.     mov    ax,0000h
  3130.     mov    cx,1
  3131.     int    31h        ;allocate a selector.
  3132.     jc    InitError
  3133.     mov    dpmiDataSel,ax
  3134.     mov    bx,ax
  3135.     push    ds
  3136.     pop    es
  3137.     mov    di,offset dpmiSelBuffer
  3138.     mov    esi,dpmiSelBase
  3139.     mov    ecx,offset _apiCodeEnd-_apiCodeStart
  3140.     xor    al,al
  3141.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  3142.     call    MakeDesc
  3143.     mov    ax,000ch
  3144.     push    ds
  3145.     pop    es
  3146.     mov    edi,offset dpmiSelBuffer
  3147.     int    31h
  3148. ;
  3149. ;Copy API code into the new memory.
  3150. ;
  3151.     pushm    ds,es
  3152.     mov    es,dpmiDataSel
  3153.     mov    ds,iRealSegment
  3154.     xor    edi,edi
  3155.     mov    esi,edi
  3156.     mov    si,seg _apiCode
  3157.     shl    esi,4
  3158.     mov    ecx,offset _apiCodeEnd-_apiCodeStart
  3159.     db 67h
  3160.     rep    movsb
  3161.     popm    ds,es
  3162. ;
  3163. ;Setup descriptors in new memory.
  3164. ;
  3165.     pushm    ds,es
  3166.     mov    es,dpmiDataSel
  3167.     mov    ds,mDataSegment
  3168.     assume ds:_cwMain
  3169.     assume es:_apiCode
  3170.     mov    es:apiDSeg,ds
  3171.     mov    es:apiDDSeg,es
  3172.     mov    eax,d[SystemFlags]
  3173.     mov    es:d[apiSystemFlags],eax
  3174. ;
  3175. ;Set INT vector to bring API code into play.
  3176. ;
  3177.     mov    bl,31h
  3178.     mov    ax,204h
  3179.     int    31h
  3180.     test    SystemFlags,1
  3181.     jz    @@Use32
  3182.     mov    es:w[OldIntSys],dx
  3183.     mov    es:w[OldIntSys+2],cx
  3184.     jmp    @@Use0
  3185. @@Use32:    mov    es:d[OldIntSys],edx
  3186.     mov    es:w[OldIntSys+4],cx
  3187. @@Use0:    mov    bl,31h
  3188.     mov    edx,offset cwAPIpatch
  3189.     pushm    ax,ds
  3190.     mov    ax,DataSegmenti
  3191.     mov    ds,ax
  3192.     assume ds:_cwInit
  3193.     mov    cx,dpmiCodeSel
  3194.     assume ds:_cwMain
  3195.     popm    ax,ds
  3196.     mov    ax,205h
  3197.     int    31h
  3198. ;
  3199. ;Copy version through to API.
  3200. ;
  3201.     mov    al,b[VersionMajor]
  3202.     sub    al,'0'
  3203.     mov    es:cwMajorVersion,al
  3204.     mov    al,b[VersionMinor]
  3205.     sub    al,'0'
  3206.     shl    al,1    ;*2
  3207.     mov    ah,al
  3208.     shl    al,2    ;*8
  3209.     add    ah,al
  3210.     mov    al,b[VersionMinor+1]
  3211.     sub    al,'0'
  3212.     add    al,ah
  3213.     mov    es:cwMinorVersion,al
  3214.     assume es:nothing
  3215.     assume ds:_cwInit
  3216.     popm    ds,es
  3217. ;
  3218. ;Set flag so we know the API is in place.
  3219. ;
  3220.     mov    ax,dpmiDataSel
  3221.     mov    apiDataSegi,ax
  3222.     mov    bx,dpmiCodeSel
  3223.     push    ds
  3224.     mov    ds,mDataSegment
  3225.     assume ds:_cwMain
  3226.     mov    apiDataSeg,ax
  3227.     mov    apiCodeSeg,bx
  3228.     mov    d[TerminationHandler],offset InitError
  3229.     mov    w[TerminationHandler+4],cs
  3230.     assume ds:_cwInit
  3231.     pop    ds
  3232. ;
  3233. ;Sort out state save address & size.
  3234. ;
  3235.     push    ds
  3236.     mov    ds,mDataSegment
  3237.     assume ds:_cwMain
  3238.     mov    ax,0305h
  3239.     int    31h
  3240.     jc    @@NoState
  3241.     mov    w[DPMIStateSize],ax
  3242.     mov    w[DPMIStateSize+2],0
  3243.     test    SystemFlags,1
  3244.     jz    @@DS_Use32
  3245.     mov    w[DPMIStateAddr+2],si
  3246.     mov    w[DPMIStateAddr],di
  3247.     jmp    @@NoState
  3248. @@DS_Use32:    mov    w[DPMIStateAddr+4],si
  3249.     mov    d[DPMIStateAddr],edi
  3250.     ;
  3251. @@NoState:    pop    ds
  3252.     assume ds:_cwInit
  3253. ;
  3254. ;Patch exception vectors to put API handlers in place.
  3255. ;
  3256.     mov    ax,cs
  3257.     push    ax
  3258.     mov    ax,offset @@pe0
  3259.     push    ax
  3260.     mov    ax,dpmiCodeSel
  3261.     push    ax
  3262.     mov    eax,offset PatchExc
  3263.     push    ax
  3264.     retf
  3265. @@pe0:    ;
  3266. ;
  3267. ;Get memory for new PSP.
  3268. ;
  3269.     mov    IErrorNumber,5
  3270.     mov    ecx,(size PSP_Struc)+(size EPSP_Struc)
  3271.     sys    GetMem32
  3272.     jc    InitError
  3273.     push    ds
  3274.     mov    ds,mDataSegment
  3275.     assume ds:_cwMain
  3276.     xchg    bx,PSPSegment
  3277.     pushm    ds,es
  3278.     mov    es,PSPSegment
  3279.     mov    ds,bx
  3280.     xor    si,si
  3281.     xor    di,di
  3282.     mov    cx,256/4
  3283.     rep    movsd
  3284.     popm    ds,es
  3285.     assume ds:_cwInit
  3286.     pop    ds
  3287. ;
  3288. ;Initialise PSP fields.
  3289. ;
  3290.     mov    IErrorNumber,8
  3291.     push    ds
  3292.     push    es
  3293.     mov    ds,mDataSegment
  3294.     assume ds:_cwMain
  3295.     xor    edx,edx
  3296.     mov    es,PSPSegment
  3297.     mov    ax,EnvSegment
  3298.     mov    es:[PSP_Environment],ax    ;Setup ENV in PSP.
  3299.     mov    ax,RealENVSegment
  3300.     mov    es:w[EPSP_RealENV],ax
  3301.     mov    ax,offset Int21hExecCount
  3302.     mov    es:w[EPSP_ExecCount],ax
  3303.     mov    es:w[EPSP_ExecCount+2],ds
  3304.     mov    es:d[EPSP_Resource],edx    ;Clear memory fields.
  3305.     mov    es:d[EPSP_INTMem],edx
  3306.     mov    es:d[EPSP_DPMIMem],edx
  3307.     mov    es:w[EPSP_Parent],es    ;set parent PSP.
  3308.     mov    es:w[EPSP_Next],dx
  3309.     mov    es:d[EPSP_DTA],80h    ;Use default PSP DTA.
  3310.     mov    es:w[EPSP_DTA+4],es
  3311.     mov    eax,16384-(mcbChunkLen+mcbLen)
  3312.     mov    es:d[EPSP_mcbMaxAlloc],eax
  3313.     mov    es:d[EPSP_mcbHead],edx
  3314.     mov    es:w[EPSP_SegBase],0
  3315.     mov    es:w[EPSP_SegSize],0
  3316.     mov    es:d[EPSP_LastPSP],0
  3317.     mov    es:d[EPSP_NextPSP],0
  3318.     mov    es:d[EPSP_Exports],0
  3319.     mov    es:d[EPSP_Imports],0
  3320.     mov    es:d[EPSP_Links],80000000h
  3321.     mov    es:d[EPSP_EntryCSEIP+4],0
  3322.     mov    es:w[EPSP_PSPSel],es
  3323.     mov    BasePSP,es
  3324.     mov    bx,es
  3325.     sys    GetSelDet32
  3326.     mov    BasePSPAddress,edx
  3327.     ;
  3328.     sys    GetSel
  3329.     jc    InitError
  3330.     movzx    edx,es:w[PSP_HandlePtr+2]
  3331.     shl    edx,4
  3332.     movzx    ecx,es:w[PSP_Handles]
  3333.     movzx    eax,es:w[PSP_HandlePtr]
  3334.     add    edx,eax
  3335.     sys    SetSelDet32
  3336.     mov    dx,bx
  3337. @@normal:    mov    es:w[PSP_HandlePtr+2],dx
  3338.     mov    es:w[PSP_HandlePtr],0
  3339.     pop    es
  3340.     assume ds:_cwInit
  3341.     pop    ds
  3342. ;
  3343. ;Setup transfer buffer and selector.
  3344. ;
  3345.     mov    IErrorNumber,8
  3346.     sys    GetSel
  3347.     jc    InitError
  3348.     push    ds
  3349.     mov    ds,mDataSegment
  3350.     assume ds:_cwMain
  3351.     movzx    edx,TransferReal
  3352.     shl    edx,4
  3353.     mov    ecx,TransferSize
  3354.     sys    SetSelDet32
  3355.     jc    InitError
  3356.     push    es
  3357.     mov    es,PSPSegment
  3358.     mov    es:w[EPSP_TransProt],bx
  3359.     mov    ax,TransferReal
  3360.     mov    es:w[EPSP_TransReal],ax
  3361.     mov    eax,TransferSize
  3362.     mov    es:d[EPSP_TransSize],eax
  3363.     pop    es
  3364.     assume ds:_cwInit
  3365.     pop    ds
  3366. ;
  3367. ;Setup internaly EXPORT'ed symbols.
  3368. ;
  3369.     mov    bx,dpmiDataSel
  3370.     sys    GetSelDet32
  3371.     mov    edi,edx
  3372.     add    edi,offset apiExports
  3373.     push    ds
  3374.     mov    ds,mDataSegment
  3375.     assume ds:_cwMain
  3376.     push    es
  3377.     mov    es,PSPSegment
  3378.     mov    es:d[EPSP_Exports],edi
  3379.     mov    es,RealSegment
  3380.     mov    ebp,es:[edi]
  3381.     add    edi,4
  3382.     add    es:d[edi],edx
  3383.     add    edi,4
  3384. @@exp0:    add    es:d[edi],edx
  3385.     mov    esi,es:[edi]
  3386.     mov    bx,CodeSegment
  3387.     cmp    es:w[esi+4],0
  3388.     jz    @@exp1
  3389.     mov    bx,DataSegment
  3390.     cmp    es:w[esi+4],1
  3391.     jz    @@exp1
  3392.     mov    bx,apiCodeSeg
  3393.     cmp    es:w[esi+4],2
  3394.     jz    @@exp1
  3395.     mov    bx,apiDataSeg
  3396.     cmp    es:w[esi+4],3
  3397.     jz    @@exp1
  3398.     or    bx,-1
  3399. @@exp1:    mov    es:[esi+4],bx
  3400.     add    edi,4
  3401.     dec    ebp
  3402.     jnz    @@exp0
  3403.     pop    es
  3404.     assume ds:_cwInit
  3405.     pop    ds
  3406. ;
  3407. ;Initialise extensions. Written in a bit of a hurry but allows
  3408. ;additional interupt service code to live in other segments.
  3409. ;
  3410.     push    ds
  3411.     mov    ds,mDataSegment
  3412.     assume ds:_cwMain
  3413.     or    mcbAllocations,-1    ;Enable MCB code.
  3414.     ;
  3415.     mov    di,offset ExtensionList
  3416. @@e0:    cmp    w[di],-1        ;end of the list?
  3417.     jz    @@e9
  3418.     mov    bp,[di]        ;get pointer to details.
  3419.     movzx    ecx,ds:w[bp+4]    ;get patch size.
  3420.     sys    GetMemLinear32    ;get some memory.
  3421.     push    ds
  3422.     mov    ds,DataSegmenti
  3423.     assume ds:_cwInit
  3424.     mov    iErrorNumber,5
  3425.     assume ds:_cwMain
  3426.     pop    ds
  3427.     jc    InitError
  3428.     sys    LockMem32        ;lock the memory.
  3429.     jc    InitError
  3430.     sys    GetSel        ;get a selector to use for
  3431.     push    ds
  3432.     mov    ds,DataSegmenti
  3433.     assume ds:_cwInit
  3434.     mov    IErrorNumber,8    ;the code segment.
  3435.     assume ds:_cwMain
  3436.     pop    ds
  3437.     jc    InitError
  3438.     mov    edx,esi
  3439.     sys    SetSelDet32        ;set it's base and limit.
  3440.     jc    InitError
  3441.     push    ecx
  3442.     mov    cx,ds:[bp+2]        ;Get code seg size.
  3443.     sys    CodeSel        ;convert to executable.
  3444.     pop    ecx
  3445.     mov    ds:[bp+8+4],bx    ;store it for now.
  3446.     mov    ds:[bp+16+4],bx
  3447.     mov    ds:[bp+24],bx
  3448.     sys    GetSel        ;get a selector to use for data.
  3449.     jc    InitError
  3450.     sys    SetSelDet32        ;set it's base and limit.
  3451.     jc    InitError
  3452.     mov    ds:[bp+28],bx    ;store it for now.
  3453.     pushm    di,ds,es
  3454.     movzx    esi,ds:w[bp+0]    ;get real mode segment base.
  3455.     shl    esi,4
  3456.     mov    ds,RealSegment
  3457.     mov    es,bx
  3458.     xor    edi,edi
  3459.     db 67h
  3460.     rep    movsb
  3461.     popm    di,ds,es
  3462.     mov    ds:w[bp+32],-1    ;flag installed.
  3463.     pushm    di,bp,ds
  3464.     mov    es,DataSegment
  3465.     mov    ds,ds:[bp+28]
  3466.  
  3467.     push    cs
  3468.     push    offset @@e1
  3469.     push    es:w[bp+12]
  3470.     push    es:w[bp+8]
  3471.     retf            ;call init routine.
  3472. @@e1:    popm    di,bp,ds
  3473.     jc    InitError
  3474.     add    di,2
  3475.     jmp    @@e0
  3476. @@e9:    assume ds:_cwInit
  3477.     pop    ds
  3478.  
  3479. IFDEF DEBUG3
  3480.     push    eax
  3481.     push    ebx
  3482.     push    ecx
  3483.     push    es
  3484.     push    ds
  3485.     mov    ax,KernalZero
  3486.     mov    es,ax
  3487.  
  3488.     mov    ebx,0b81e0h
  3489.     mov    BYTE PTR es:[ebx],'F'
  3490.     mov    BYTE PTR es:[ebx+2],'P'
  3491.     mov    BYTE PTR es:[ebx+4],' '
  3492.     mov    BYTE PTR es:[ebx+6],' '
  3493.     mov    BYTE PTR es:[ebx+24],' '
  3494.     mov    BYTE PTR es:[ebx+26],' '
  3495.  
  3496.     mov    ax,KernalDS        ;Get data descriptor.
  3497.     mov    ds,ax
  3498.     assume ds:_cwRaw
  3499.     movzx    edx,FirstUninitPage
  3500.     push    edx
  3501.     mov    ecx,edx
  3502.     xor    edx,edx
  3503. deb3_3:
  3504.     rol    ecx,4
  3505.     mov    al,cl
  3506.     and    al,0fh
  3507.     cmp    al,10
  3508.     jb    deb3_2
  3509.     add    al,7
  3510. deb3_2:
  3511.     add    al,48
  3512.     mov    es:[ebx+edx*2+8],al
  3513.     inc    edx
  3514.     cmp    edx,8
  3515.     jb    deb3_3
  3516.     pop    edx
  3517.  
  3518.     mov    ecx,200000h
  3519. deb3_aloop:
  3520.     dec    ecx
  3521. ;    jne    deb3_aloop
  3522.     pop    ds
  3523.     pop    es
  3524.     pop    ecx
  3525.     pop    ebx
  3526.     pop    eax
  3527. ENDIF
  3528.  
  3529. COMMENT !
  3530. IFDEF DEBUG3
  3531.     push    ds
  3532.     push    es
  3533.     push    eax
  3534.     push    ebx
  3535.     push    ecx
  3536.     push    edx
  3537.     push    edi
  3538.     push    ebp
  3539.  
  3540.     mov    ax,KernalDS        ;Get data descriptor.
  3541.     mov    ds,ax
  3542.     assume ds:_cwRaw
  3543.     movzx    edi,Page1stReal    ;get linear address.
  3544.     shl    edi,4
  3545.     mov    ax,KernalZero
  3546.     mov    es,ax
  3547.     mov    bp,1024
  3548.     sub    esp,10
  3549.     push    ss
  3550.     pop    ds
  3551. moo1:
  3552.     mov    ecx,es:[edi]
  3553.     xor    edx,edx
  3554. deb5_3:
  3555.     rol    ecx,4
  3556.     mov    al,cl
  3557.     and    al,0fh
  3558.     cmp    al,10
  3559.     jb    deb5_2
  3560.     add    al,7
  3561. deb5_2:
  3562.     add    al,48
  3563.     mov    BYTE PTR ss:[esp+edx],al
  3564.     inc    edx
  3565.     cmp    edx,8
  3566.     jb    deb5_3
  3567.  
  3568.     mov    WORD PTR ss:[esp+8],0a0dh
  3569.     mov    edx,esp
  3570.     mov    ecx,10
  3571.     mov    ebx,1
  3572.     mov    ah,40h
  3573.     int    21h
  3574.  
  3575.     add    di,4        ;next page table entry.
  3576.     dec    bp
  3577.     jnz    moo1
  3578.  
  3579.     add    esp,10
  3580.     pop    ebp
  3581.     pop    edi
  3582.     pop    edx
  3583.     pop    ecx
  3584.     pop    ebx
  3585.     pop    eax
  3586.     pop    es
  3587.     pop    ds
  3588.     jmp    debout1
  3589.  
  3590. debout1:
  3591. ENDIF
  3592. END COMMENT !
  3593.  
  3594. ;
  3595. ;We're all done here so switch to main code segment for final re-size and run.
  3596. ;
  3597.     push    mCodeSegment
  3598.     push    offset cwOpen
  3599.     retf
  3600.  
  3601.     .286
  3602.  
  3603. @@OldStrat:    ;
  3604.     dw ?,?
  3605.  
  3606. @@NumXMSHandles:
  3607.     db ?
  3608.  
  3609. ; MED, 09/10/99, increase max XMS size to dword
  3610. @@XMSSize:    ;
  3611. ;    dw ?
  3612.     dd    0
  3613.  
  3614. Startup    endp
  3615.  
  3616.  
  3617. ;-------------------------------------------------------------------------------
  3618. ;
  3619. ;Something is wrong with this system so print an error message and get out of
  3620. ;here.
  3621. ;
  3622. InitError    proc    near
  3623. ;
  3624. ;Find out if we're in protected mode or not.
  3625. ;
  3626.     .386p
  3627.     assume ds:nothing
  3628.     cmp    cs:IProtectedMode,0          ; are we in protected mode?
  3629.  
  3630. ; MED 07/10/97, allow 286 non-crash at this point
  3631. ;    jz    @@RealMode
  3632.     jnz    chkapi
  3633.     jmp    @@RealMode
  3634. chkapi:
  3635.  
  3636.     cmp    cs:apiDataSegi,0    ;API installed?
  3637.     jz    @@noAPI
  3638.     ;
  3639.     mov    ds,cs:mDataSegment
  3640.     assume ds:_cwMain
  3641. ;
  3642. ;Remove extension patches.
  3643. ;
  3644.     mov    di,offset ExtensionList    ;list of interupt patches.
  3645. @@p1:    cmp    w[di+2],-1        ;search for the end of the table so we can restore
  3646.     jz    @@p0        ;vectors in reverse order.
  3647.     add    di,2
  3648.     jmp    @@p1
  3649.     ;
  3650. @@p0:    mov    bp,w[di]
  3651.     cmp    ds:w[bp+32],-1    ;installed?
  3652.     jnz    @@p2
  3653.     pushm    di,bp
  3654.     push    cs
  3655.     push    offset @@p3
  3656.     push    ds:w[bp+20]
  3657.     push    ds:w[bp+16]
  3658.     retf
  3659. @@p3:    popm    di,bp
  3660. @@p2:    sub    di,2
  3661.     cmp    di,offset ExtensionList-2
  3662.     jnz    @@p0
  3663. ;
  3664. ;Remove api exception patches.
  3665. ;
  3666.     cmp    apiExcepPatched,0
  3667.     jz    @@pe0
  3668.     mov    ax,cs
  3669.     push    ax
  3670.     mov    ax,offset @@pe0
  3671.     push    ax
  3672.     mov    ax,dpmiCodeSel
  3673.     push    ax
  3674.     mov    eax,offset UnPatchExc
  3675.     push    ax
  3676.     retf
  3677. @@pe0:    ;
  3678. ;
  3679. ;Remove the API patch.
  3680. ;
  3681.     mov    ds,cs:mDataSegment
  3682.     assume ds:_cwMain
  3683.     mov    es,apiDataSeg
  3684.     assume es:_apiCode
  3685.     test    SystemFlags,1
  3686.     jz    @@Use32
  3687.     mov    dx,es:w[OldIntSys]
  3688.     mov    cx,es:w[OldIntSys+2]
  3689.     jmp    @@Use0
  3690. @@Use32:    mov    edx,es:d[OldIntSys]
  3691.     mov    cx,es:w[OldIntSys+4]
  3692. @@Use0:    mov    bl,31h
  3693.     mov    ax,205h
  3694.     int    31h
  3695.     mov    es:d[cwIdentity],0
  3696.     mov    es:d[cwIdentity+4],0
  3697.     assume es:nothing
  3698.     ;
  3699. @@noAPI:    assume ds:nothing
  3700.     cmp    cs:IProtectedType,2    ;DPMI?
  3701.     assume ds:_cwInit
  3702.     jz    @@DPMI
  3703. ;
  3704. ;Make RAW stuff addressable.
  3705. ;
  3706.     cli            ;Don't want interrupts interfering.
  3707.     mov    ax,KernalDS        ;Get supervisor data descriptor,
  3708.     mov    ds,ax        ;DS,ES,FS,GS,SS must be data with 64k limit
  3709.     assume ds:_cwRaw
  3710.     mov    ax,KernalZero
  3711.     mov    es,ax
  3712. ;
  3713. ;Switch to RAW exit code.
  3714. ;
  3715.     push    _cwInit
  3716.     push    offset @@6
  3717.     mov    ax,KernalCS
  3718.     push    ax
  3719.     mov    ax,offset RawVCPIRealMode
  3720.     push    ax
  3721.     retf
  3722. @@6:    jmp    @@RealMode
  3723. ;
  3724. ;Remove DPMI stuff.
  3725. ;
  3726.     .386
  3727. @@DPMI:
  3728.  
  3729.     if    0
  3730.     assume ds:nothing
  3731.     mov    ds,cs:iDataSegment
  3732.     assume ds:_cwInit
  3733.     mov    ds,mDataSegment
  3734.     assume ds:_cwMain
  3735.     cmp    d[OldInt21hExec],0
  3736.     jz    @@d0
  3737.     mov    bl,21h
  3738.     mov    dx,w[OldInt21hExec]
  3739.     mov    cx,w[OldInt21hExec+2]
  3740.     mov    ax,201h
  3741.     int    31h
  3742. @@d0:
  3743.     endif
  3744.  
  3745.     assume ds:nothing
  3746.     mov    ds,cs:iDataSegment
  3747.     assume ds:_cwInit
  3748.  
  3749.     cmp    IErrorNumber,0
  3750.     jz    @@NoError
  3751.     mov    ax,IErrorNumber    ;Get the error number.
  3752.     xor    dx,dx
  3753.     mov    cx,10
  3754.     div    cx
  3755.     add    al,'0'
  3756.     mov    b[IErrorM00n],al
  3757.     add    dl,'0'
  3758.     mov    b[IErrorM00n+1],dl
  3759.     mov    dx,w[InitErrorList]
  3760.  
  3761.     mov    edi,offset DPMIErrRegs
  3762.     push    ds
  3763.     pop    es
  3764.     mov    Real_EDX[edi],edx
  3765.     mov    Real_EAX[edi],900h
  3766.     mov    Real_DS[edi],_cwInit
  3767.     xor    cx,cx        ;No stack parameters.
  3768.     mov    bh,ch        ;no flags.
  3769.     mov    ax,0300h
  3770.     int    31h        ;Use real dpmi service.
  3771. ;
  3772. ;Get a pointer to the appropriate error message and print it.
  3773. ;
  3774.     mov    bx,IErrorNumber
  3775.     add    bx,bx
  3776.     mov    dx,[InitErrorList+bx]
  3777.  
  3778.     mov    edi,offset DPMIErrRegs
  3779.     push    ds
  3780.     pop    es
  3781.     mov    Real_EDX[edi],edx
  3782.     mov    Real_EAX[edi],900h
  3783.     mov    Real_DS[edi],_cwInit
  3784.     xor    cx,cx        ;No stack parameters.
  3785.     mov    bh,ch        ;no flags.
  3786.     mov    ax,0300h
  3787.     int    31h        ;Use real dpmi service.
  3788.  
  3789.     jmp    @@NoError
  3790.     .286
  3791. ;
  3792. ;Make sure our data is addressable.
  3793. ;
  3794. @@RealMode:    mov    ax,_cwInit
  3795.     mov    ds,ax
  3796.     assume ds:_cwInit
  3797. ;
  3798. ;Display the "CauseWay error: ??" bit.
  3799. ;
  3800. @@InRealMode:    cmp    IErrorNumber,0
  3801.     jz    @@NoError
  3802.     mov    ax,IErrorNumber    ;Get the error number.
  3803.     xor    dx,dx
  3804.     mov    cx,10
  3805.     div    cx
  3806.     add    al,'0'
  3807.     mov    b[IErrorM00n],al
  3808.     add    dl,'0'
  3809.     mov    b[IErrorM00n+1],dl
  3810.     mov    dx,w[InitErrorList]
  3811.     mov    ah,9
  3812.     int    21h
  3813. ;
  3814. ;Get a pointer to the appropriate error message and print it.
  3815. ;
  3816.     mov    bx,IErrorNumber
  3817.     add    bx,bx
  3818.     mov    dx,[InitErrorList+bx]
  3819.     mov    ah,9
  3820.     int    21h
  3821. ;
  3822. ;Now exit with the error number as the DOS "errorlevel".
  3823. ;
  3824. @@NoError:    mov    ax,IErrorNumber
  3825.     mov    ah,4ch
  3826.     int    21h
  3827.     assume ds:_cwMain
  3828. InitError    endp
  3829.  
  3830.  
  3831. ;-------------------------------------------------------------------------------
  3832. ;
  3833. ;Initialise real mode hardware interupt vectors so that control is always passed to protected mode
  3834. ;even if the interupt occurs in real mode. This simulates the DPMI environment and is essential for
  3835. ;any program that re-programs IRQ-0 frequency.
  3836. ;
  3837. InitHardwareInts proc near
  3838.     .386
  3839.     pushm    ds,es
  3840.     mov    ax,KernalDS
  3841.     mov    ds,ax
  3842.     mov    ax,KernalZero
  3843.     mov    es,ax
  3844.     assume ds:_cwRaw
  3845. ;    mov    ch,16
  3846. ;    mov    cl,1ch
  3847. ;    call    @@0
  3848.     mov    ch,17
  3849.     mov    cl,23h        ;patch ctrl-break.
  3850.     call    @@0
  3851.     mov    ch,18
  3852.     mov    cl,24h        ;patch critical error.
  3853.     call    @@0
  3854.     popm    ds,es
  3855.     ret
  3856.     ;
  3857. @@0:    mov    ax,size CallBackStruc
  3858.     movzx    bx,ch
  3859.     mul    bx
  3860.     mov    bx,ax
  3861.     add    bx,offset CallBackTable
  3862.     pushf
  3863.     cli
  3864.     mov    CallBackNum[bx],cl    ;set interupt number.
  3865.     mov    CallBackFlags[bx],1+2    ;mark call back as used interupt.
  3866.     mov    ax,CallBackSize
  3867.     movzx    dx,ch
  3868.     mul    dx
  3869.     mov    si,offset ICallBackList
  3870.     add    si,ax        ;index list of calls.
  3871.     push    bx
  3872.     movzx    bx,cl
  3873.     shl    bx,2
  3874.     mov    dx,es:[bx]
  3875.     mov    cx,es:[bx+2]
  3876.     mov    es:[bx],si
  3877.     mov    es:w[bx+2],seg _cwRaw
  3878.     pop    bx
  3879.     mov    w[CallBackReal+2+bx],cx    ;store origional real mode vector.
  3880.     mov    w[CallBackReal+bx],dx
  3881.     popf
  3882.     ret
  3883.     assume ds:_cwMain
  3884.     .286
  3885. InitHardwareInts endp
  3886.  
  3887.  
  3888. ;-------------------------------------------------------------------------------
  3889. CheckProcessor    proc    near
  3890.     xor    ax,ax        ;Clear the flags.
  3891.     push    ax        ;/
  3892.     popf            ;/
  3893.     pushf            ;Get the flags back.
  3894.     pop    ax        ;/
  3895.     and    ax,0F000h        ;Get Bits 11-8
  3896.     cmp    ax,0F000h        ;Exist on this processor?
  3897.     je    @@9        ;Must be an 8086
  3898.     mov    ax,0F000h        ;Setup the flags again.
  3899.     push    ax        ;/
  3900.     popf            ;/
  3901.     pushf            ;Get them back.
  3902.     pop    ax        ;/
  3903.     and    ax,0F000h        ;Get Bits 11-8
  3904.     jz    @@9        ;Valid so must be 80286
  3905.     clc
  3906.     ret
  3907. @@9:    stc
  3908.     ret
  3909. CheckProcessor    endp
  3910.  
  3911.  
  3912. ;-------------------------------------------------------------------------------
  3913. CheckDOSVersion proc near
  3914.     mov    ah,30h
  3915.     int    21h        ;Get DOS version.
  3916.     mov    DOSVersion,ax
  3917.     cmp    al,3        ;3.? or above?
  3918.     jc    @@9
  3919.     jnz    @@0        ;less means trouble.
  3920.     cmp    ah,1
  3921.     jc    @@9
  3922. @@0:    clc
  3923.     ret
  3924. @@9:    stc
  3925.     ret
  3926. CheckDOSVersion endp
  3927.  
  3928.  
  3929. ;-------------------------------------------------------------------------------
  3930. ;
  3931. ;Check for "CAUSEWAY" environment variable and fetch any relevent settings.
  3932. ;
  3933. GetENVStuff    proc    near
  3934.     .386
  3935.     mov    es,RealEnvSegment
  3936.     xor    si,si
  3937. @@0:    mov    eax,es:[si]
  3938.     cmp    eax,"SUAC"
  3939.     jnz    @@1
  3940.     mov    eax,es:[si+4]
  3941.     cmp    eax,"YAWE"
  3942.     jz    @@2
  3943. @@1:    inc    si
  3944.     cmp    es:b[si-1],0
  3945.     jnz    @@1
  3946.     cmp    es:b[si],0        ;end of all strings?
  3947.     jnz    @@0
  3948.     jmp    @@9
  3949.     ;
  3950. @@2:    ;Found "CAUSEWAY" so have a look at the settings.
  3951.     ;
  3952.     add    si,8        ;skip to "="
  3953.     push    si
  3954. @@2_0:    mov    al,es:[si]
  3955.     cmp    al,61h        ; 'a'
  3956.     jb    @@2_1
  3957.     cmp    al,7Ah        ; 'z'
  3958.     ja    @@2_1
  3959.     and    al,5Fh        ;convert to upper case.
  3960. @@2_1:    mov    es:[si],al
  3961.     inc    si
  3962.     or    al,al
  3963.     jnz    @@2_0
  3964.     pop    si
  3965.     ;
  3966. @@3:    cmp    es:b[si]," "
  3967.     jnz    @@4
  3968.     inc    si
  3969.     jmp    @@3
  3970.     ;
  3971. @@4:    cmp    es:b[si],0        ;end?
  3972.     jz    @@9
  3973.     ;
  3974.     mov    eax,es:[si]
  3975.     cmp    eax,"MVON"        ;NOVM?
  3976.     jz    @@novm
  3977.     cmp    eax,"MXAM"        ;MAXMEM?
  3978.     jz    @@maxmem
  3979.     cmp    eax,"ATXE"        ;EXTALL?
  3980.     jz    @@extall
  3981.     cmp    eax,"IMPD"        ;DPMI?
  3982.     jz    @@dpmi
  3983.     cmp    eax,"PAWS"        ;swap?
  3984.     jz    @@swap
  3985.     cmp    eax,"MWOL"        ;lowmem?
  3986.     jz    @@lowmem
  3987.     cmp    eax,"EMIH"        ; himem?
  3988.     jz    @@himem
  3989.     cmp    eax,"APON"        ; nopass?
  3990.     jz    @@nopass
  3991.     cmp    eax,":ERP"        ; pre?
  3992.     jz    @@pre
  3993.     cmp    eax,"EMAN"        ; NAME?
  3994.     jz    @@name
  3995.     cmp    eax,"1DAP"        ; PAD1?
  3996.     jz    @@pad1
  3997.     cmp    eax,"XEON"        ; NOEX?
  3998.     jz    @@noex
  3999.     cmp    eax,"1GIB"        ; BIG1?
  4000.     jz    @@big1
  4001.     inc    si
  4002.     jmp    @@3
  4003.     ;
  4004. @@nopass:    ; shut off passing of real mode interrupts to protected mode
  4005.     add    si,4
  4006.     mov    ax,es:[si]
  4007.     cmp    ax,"SS"
  4008.     jnz    @@3
  4009.     add    si,2
  4010.     push    ds
  4011.     mov    bx,_cwRaw
  4012.     mov    ds,bx
  4013.     assume ds:_cwRaw
  4014.     or    NoPassFlag,-1
  4015.     assume ds:_cwMain
  4016.     pop    ds
  4017.     jmp    @@3
  4018.  
  4019. @@big1:    ; specify alternate extended memory size computation
  4020.     add    si,4
  4021.     push    ds
  4022.     mov    bx,_cwRaw
  4023.     mov    ds,bx
  4024.     assume ds:_cwRaw
  4025.     or    Big1Flag,-1
  4026.     assume ds:_cwMain
  4027.     pop    ds
  4028.     jmp    @@3
  4029.  
  4030. @@himem:    ;Set amount of physical memory to use.
  4031.     ;
  4032.     add    si,4
  4033.     mov    al,es:[si]
  4034.     cmp    al,"M"
  4035.     jnz    @@3
  4036.     inc    si
  4037.     cmp    es:b[si],":"
  4038.     jnz    @@3
  4039.     inc    si
  4040.     xor    edx,edx
  4041. @@hm0:    mov    al,es:[si]
  4042.     or    al,al
  4043.     jz    @@hm1
  4044.     cmp    al," "
  4045.     jz    @@hm1
  4046.     cmp    al,"0"
  4047.     jc    @@hm1
  4048.     cmp    al,"9"+1
  4049.     jnc    @@hm1
  4050.     sub    al,"0"
  4051.     movzx    eax,al
  4052.     add    edx,edx
  4053.     mov    ebx,edx
  4054.     add    edx,edx
  4055.     add    edx,edx
  4056.     add    edx,ebx
  4057.     add    edx,eax
  4058.     inc    si
  4059.     jmp    @@hm0
  4060. @@hm1:
  4061.     cmp    edx,4096*1024
  4062.     jnc    @@3
  4063.  
  4064.     shl    edx,10        ;turn K into byte's
  4065.     shr    edx,12        ;get number of pages.
  4066.     push    ds
  4067.     mov    bx,_cwRaw
  4068.     mov    ds,bx
  4069.     assume ds:_cwRaw
  4070.     mov    d[MaxMemPhys],edx
  4071.     assume ds:_cwMain
  4072.     pop    ds
  4073.     jmp    @@3
  4074.     ;
  4075. @@extall:    ;Set flag to use all extended memory.
  4076.     ;
  4077.     add    si,4
  4078.     mov    ax,es:[si]
  4079.     cmp    ax,"LL"
  4080.     jnz    @@3
  4081.     add    si,2
  4082.     push    ds
  4083.     mov    bx,_cwRaw
  4084.     mov    ds,bx
  4085.     assume ds:_cwRaw
  4086.     or    ExtALLSwitch,-1
  4087.     assume ds:_cwMain
  4088.     pop    ds
  4089.     jmp    @@3
  4090.     ;
  4091. @@novm:    ;They want to disable VM.
  4092.     ;
  4093.     add    si,4
  4094.     push    ds
  4095.     mov    bx,_cwInit
  4096.     mov    ds,bx
  4097.     assume ds:_cwInit
  4098.     or    NoVMSwitch,-1
  4099.     assume ds:_cwMain
  4100.     pop    ds
  4101.     jmp    @@3
  4102.     ;
  4103. @@maxmem:    ;Want to set maximum linear address space size.
  4104.     ;
  4105.     add    si,4
  4106.     mov    ax,es:[si]
  4107.     cmp    ax,"ME"
  4108.     jnz    @@3
  4109.     add    si,2
  4110.     cmp    es:b[si],":"
  4111.     jnz    @@3
  4112.     inc    si
  4113.     xor    edx,edx
  4114. @@mm0:    mov    al,es:[si]
  4115.     or    al,al
  4116.     jz    @@mm1
  4117.     cmp    al," "
  4118.     jz    @@mm1
  4119.     cmp    al,"0"
  4120.     jc    @@mm1
  4121.     cmp    al,"9"+1
  4122.     jnc    @@mm1
  4123.     sub    al,"0"
  4124.     movzx    eax,al
  4125.     add    edx,edx
  4126.     mov    ebx,edx
  4127.     add    edx,edx
  4128.     add    edx,edx
  4129.     add    edx,ebx
  4130.     add    edx,eax
  4131.     inc    si
  4132.     jmp    @@mm0
  4133. @@mm1:
  4134.     cmp    edx,4096
  4135.     jnc    @@3
  4136.  
  4137.     shl    edx,20        ;turn Meg into byte's
  4138.     push    ds
  4139.     mov    bx,_cwRaw
  4140.     mov    ds,bx
  4141.     assume ds:_cwRaw
  4142.     mov    d[MaxMemLin],edx
  4143.     assume ds:_cwMain
  4144.     pop    ds
  4145.     jmp    @@3
  4146.  
  4147. @@pre:    ;Want to set preallocate amount
  4148.     ;
  4149.     add    si,4
  4150.     xor    edx,edx
  4151. @@pr0:    mov    al,es:[si]
  4152.     or    al,al
  4153.     jz    @@pr1
  4154.     cmp    al," "
  4155.     jz    @@pr1
  4156.     cmp    al,"0"
  4157.     jc    @@pr1
  4158.     cmp    al,"9"+1
  4159.     jnc    @@pr1
  4160.     sub    al,"0"
  4161.     movzx    eax,al
  4162.     add    edx,edx
  4163.     mov    ebx,edx
  4164.     add    edx,edx
  4165.     add    edx,edx
  4166.     add    edx,ebx
  4167.     add    edx,eax
  4168.     inc    si
  4169.     jmp    @@pr0
  4170. @@pr1:
  4171.     cmp    edx,4096
  4172.     jnc    @@3
  4173.  
  4174.     shl    edx,20        ;turn Meg into byte's
  4175.     push    ds
  4176.     mov    bx,_cwRaw
  4177.     mov    ds,bx
  4178.     assume ds:_cwRaw
  4179.     mov    d[PreAllocSize],edx
  4180.     assume ds:_cwMain
  4181.     pop    ds
  4182.     jmp    @@3
  4183.  
  4184. @@pad1:
  4185.     mov    Pad1Flag,1
  4186.     add    si,4
  4187.     jmp    @@3
  4188.  
  4189. @@noex:
  4190.     mov    NoEXECPatchFlag,1
  4191.     add    si,4
  4192.     jmp    @@3
  4193.  
  4194. @@dpmi:    ;They want to force DPMI use if possible.
  4195.     ;
  4196.     mov    ProtectedForce,1
  4197.     add    si,4
  4198.     jmp    @@3
  4199.     ;
  4200. @@swap:    ;They want to specify the swap drive.
  4201.     ;
  4202.     add    si,4
  4203.     cmp    es:b[si],":"
  4204.     jnz    @@3
  4205.     inc    si
  4206.     mov    di,offset VMMDrivPath1
  4207.     push    ds
  4208.     mov    bx,_cwInit
  4209.     mov    ds,bx
  4210.     assume ds:_cwInit
  4211. @@s0:    mov    al,es:[si]
  4212.     mov    [di],al
  4213.     inc    si
  4214.     inc    di
  4215.     or    al,al
  4216.     jz    @@s1
  4217.  
  4218.     cmp    al,";"    ; MED 02/25/96
  4219.     je    @@s1
  4220.  
  4221.     cmp    al," "
  4222.     jnz    @@s0
  4223. @@s1:    mov    b[di-1],0
  4224.     assume ds:_cwMain
  4225.     pop    ds
  4226.     dec    si
  4227.     jmp    @@3
  4228.     ;
  4229. @@name:    ; Specify the swap name.
  4230.     ;
  4231.     add    si,4
  4232.     cmp    es:b[si],":"
  4233.     jnz    @@3
  4234.     inc    si
  4235.     mov    di,offset DesiredVMMName
  4236.     push    ds
  4237.     mov    bx,_cwRaw
  4238.     mov    ds,bx
  4239.     assume ds:_cwRaw
  4240.     xor    dx,dx
  4241. @@n0:    mov    al,es:[si]
  4242.     mov    [di],al
  4243.     inc    si
  4244.     inc    di
  4245.     or    al,al
  4246.     jz    @@n1
  4247.     inc    dx
  4248.     cmp    dx,12
  4249.     ja    @@n1        ; don't allow more than 12 chars in file name
  4250.  
  4251.     cmp    al,";"    ; MED 02/25/96
  4252.     je    @@n1
  4253.  
  4254.     cmp    al," "
  4255.     jnz    @@n0
  4256. @@n1:    mov    b[di-1],0
  4257.     assume ds:_cwMain
  4258.     pop    ds
  4259.     dec    si
  4260.     jmp    @@3
  4261.     ;
  4262. @@lowmem:    ;They want to specify low memory retention.
  4263.     ;
  4264.     add    si,4
  4265.     mov    ax,es:[si]
  4266.     cmp    ax,"ME"
  4267.     jnz    @@3
  4268.     add    si,2
  4269.     cmp    es:b[si],":"
  4270.     jnz    @@3
  4271.     inc    si
  4272.     xor    edx,edx
  4273. @@lm0:    mov    al,es:[si]
  4274.     or    al,al
  4275.     jz    @@lm1
  4276.     cmp    al," "
  4277.     jz    @@lm1
  4278.     cmp    al,"0"
  4279.     jc    @@lm1
  4280.     cmp    al,"9"+1
  4281.     jnc    @@lm1
  4282.     sub    al,"0"
  4283.     movzx    eax,al
  4284.     add    edx,edx
  4285.     mov    ebx,edx
  4286.     add    edx,edx
  4287.     add    edx,edx
  4288.     add    edx,ebx
  4289.     add    edx,eax
  4290.     inc    si
  4291.     jmp    @@lm0
  4292.     ;
  4293. @@lm1:    shl    edx,10-4        ;turn K into para's
  4294.     push    ds
  4295.     mov    bx,_cwRaw
  4296.     mov    ds,bx
  4297.     assume ds:_cwRaw
  4298.     movzx    ebx,w[CONVSaveSize]
  4299.     add    edx,ebx
  4300.     cmp    edx,65535
  4301.     jc    @@lm2
  4302.     mov    edx,65535
  4303. @@lm2:    mov    w[CONVSaveSize],dx    ;set new size.
  4304.     assume ds:_cwMain
  4305.     pop    ds
  4306.     ;
  4307.     jmp    @@3
  4308.     ;
  4309. @@9:    ;Now look for TEMP.
  4310.     ;
  4311.     xor    si,si        ;start at the beginning.
  4312. @@temp2:    mov    eax,es:[si]
  4313.     cmp    eax,"PMET"
  4314.     jz    @@temp0
  4315. @@temp1:    inc    si
  4316.     cmp    es:b[si-1],0
  4317.     jnz    @@temp1
  4318.     cmp    es:b[si],0
  4319.     jz    @@temp9
  4320.     jmp    @@temp2
  4321.     ;
  4322. @@temp0:    add    si,4
  4323.     cmp    es:b[si],"="
  4324.     jnz    @@temp9
  4325.     inc    si
  4326.     push    ds
  4327.     mov    bx,_cwInit
  4328.     mov    ds,bx
  4329.     mov    di,offset VMMDrivPath2
  4330. @@temp3:    mov    al,es:[si]
  4331.     mov    [di],al
  4332.     inc    si
  4333.     inc    di
  4334.     or    al,al
  4335.     jz    @@temp4
  4336.     cmp    al," "
  4337.     jnz    @@temp3
  4338. @@temp4:    mov    b[di-1],0
  4339.     pop    ds
  4340. @@temp9:    ;
  4341.     ;Look for TMP
  4342.     ;
  4343.     xor    si,si        ;start at the beginning.
  4344. @@tmp2:    mov    eax,es:[si]
  4345.     cmp    eax,"=PMT"
  4346.     jz    @@tmp0
  4347. @@tmp1:    inc    si
  4348.     cmp    es:b[si-1],0
  4349.     jnz    @@tmp1
  4350.     cmp    es:b[si],0
  4351.     jz    @@tmp9
  4352.     jmp    @@tmp2
  4353.     ;
  4354. @@tmp0:    add    si,4
  4355.     push    ds
  4356.     mov    bx,_cwInit
  4357.     mov    ds,bx
  4358.     mov    di,offset VMMDrivPath3
  4359. @@tmp3:    mov    al,es:[si]
  4360.     mov    [di],al
  4361.     inc    si
  4362.     inc    di
  4363.     or    al,al
  4364.     jz    @@tmp4
  4365.     cmp    al," "
  4366.     jnz    @@tmp3
  4367. @@tmp4:    mov    b[di-1],0
  4368.     pop    ds
  4369. @@tmp9:    ;
  4370.     ret
  4371.     .286
  4372. GetENVStuff    endp
  4373.  
  4374.  
  4375. ;-------------------------------------------------------------------------------
  4376. GetEXECName    proc    near
  4377.     .386
  4378. @@0:    mov    es,RealEnvSegment
  4379.     xor    si,si
  4380. @@1:    mov    al,es:[si]        ;Get a byte.
  4381.     inc    si        ;/
  4382.     or    al,al        ;End of a string?
  4383.     jnz    @@1        ;keep looking.
  4384.     mov    al,es:[si]        ;Double zero?
  4385.     or    al,al        ;/
  4386.     jnz    @@1        ;keep looking.
  4387.     add    si,3        ;Skip last 0 and word count.
  4388.     mov    di,offset MainExec
  4389.     mov    bx,_cwInit
  4390.     mov    fs,bx
  4391.     mov    bx,offset VMMDrivPath4
  4392.     mov    cx,128
  4393.     mov    dx,bx
  4394.     pushm    ds,ds,es
  4395.     popm    es,ds
  4396. @@2:    movsb
  4397.     mov    al,[si-1]
  4398.     mov    fs:[bx],al
  4399.     inc    bx
  4400.     cmp    b[si-1],"\"
  4401.     jnz    @@2_0
  4402.     mov    dx,bx
  4403.     dec    dx
  4404. @@2_0:    cmp    b[si-1],0        ;got to the end yet?
  4405.     jz    @@3
  4406.     dec    cx
  4407.     jnz    @@2
  4408. @@3:    mov    bx,dx
  4409.     mov    fs:b[bx],0        ;terminate VMM path.
  4410.  
  4411. COMMENT !
  4412. ; MED 10/10/96
  4413.     cmp    bx,offset VMMDrivPath4
  4414.     jne    genexit            ; non-null path
  4415.     mov    BYTE PTR fs:[bx],'.'    ; null path, give a valid one of '.\'
  4416.     mov    BYTE PTR fs:[bx+1],'\'
  4417.     mov    BYTE PTR fs:[bx+2],0
  4418. END COMMENT !
  4419.  
  4420. genexit:
  4421.     pop    ds
  4422.     pushm    ds,ds
  4423.     popm    es,fs
  4424.     ret
  4425.     .286
  4426. GetEXECName    endp
  4427.  
  4428.  
  4429. ;-------------------------------------------------------------------------------
  4430. GetSystemFlags    proc    near
  4431.     push    ds
  4432.     mov    dx,offset MainExec
  4433.     mov    ax,3d00h        ;open, read only.
  4434.     int    21h
  4435.     jc    @@5
  4436.     push    cs
  4437.     pop    ds
  4438.     assume ds:_cwInit
  4439.     mov    bx,ax
  4440.     mov    dx,offset IExeSignature    ;somewhere to put the info.
  4441.     mov    cx,1bh        ;size of it.
  4442.     mov    ah,3fh
  4443.     int    21h
  4444.     jc    @@4
  4445.     cmp    ax,1bh        ;did we read right amount?
  4446.     jnz    @@4
  4447.     cmp    w[IExeSignature],'ZM'    ;Normal EXE?
  4448.     jnz    @@4
  4449.     mov    ax,w[IExeLength+2]    ;get length in 512 byte blocks
  4450.  
  4451. ; MED 01/17/96
  4452.     cmp    WORD PTR [IExeLength],0
  4453.     je    medexe2        ; not rounded if no modulo
  4454.  
  4455.     dec    ax        ;lose 1 cos its rounded up
  4456.  
  4457. medexe2:
  4458.     add    ax,ax        ;mult by 2
  4459.     mov    dh,0
  4460.     mov    dl,ah
  4461.     mov    ah,al
  4462.     mov    al,dh        ;mult by 256=*512
  4463.     add    ax,w[IExeLength]    ;add length mod 512
  4464.     adc    dx,0        ;add any carry to dx
  4465.     mov    cx,ax
  4466.     xchg    cx,dx        ;swap round for DOS.
  4467.     mov    ax,4200h        ;set absolute position.
  4468.     int    21h
  4469.     mov    dx,offset INewHeader    ;somewhere to put the info.
  4470.     mov    cx,size NewHeaderStruc    ;size of it.
  4471.     mov    ah,3fh
  4472.     int    21h
  4473.     jc    @@4
  4474.     or    ax,ax        ;end of the file?
  4475.     jz    @@SetRUN
  4476.     cmp    ax,size NewHeaderStruc    ;did we read right amount?
  4477.     jnz    @@4
  4478.     cmp    w[INewHeader],'P3'    ;ID ok?
  4479.     jnz    @@4
  4480.     mov    si,offset INewHeader
  4481.     mov    ax,w[NewFlags+si]    ;Copy main flags.
  4482.     mov    cx,w[NewFlags+2+si]
  4483.     pop    ds
  4484.     push    ds
  4485.     assume ds:_cwMain
  4486.     mov    w[SystemFlags],ax
  4487.     mov    w[SystemFlags+2],cx
  4488.     mov    dx,_cwRaw
  4489.     mov    ds,dx
  4490.     assume ds:_cwRaw
  4491.     mov    w[RawSystemFlags],ax
  4492.     mov    w[RawSystemFlags+2],cx
  4493.     .386
  4494.     mov    dx,_cwDPMIEMU
  4495.     mov    ds,dx
  4496.     assume ds:_cwDPMIEMU
  4497.     mov    w[DpmiEmuSystemFlags],ax
  4498.     mov    w[DpmiEmuSystemFlags+2],cx
  4499.     mov    dx,_apiCode
  4500.     mov    ds,dx
  4501.     assume ds:_apiCode
  4502.     mov    w[apiSystemFlags],ax
  4503.     mov    w[apiSystemFlags+2],cx
  4504.     .286
  4505.     assume ds:_cwMain
  4506. @@4:    mov    ax,3e00h
  4507.     int    21h
  4508.     jmp    @@5
  4509.  
  4510. ;
  4511. ;Nothing on the end of the extender so replace the exec name with first
  4512. ;command line argument and shuffle everything else down. Allows CW32 to be used
  4513. ;to run 32-bit programs not attatched to it from the command line.
  4514. ;
  4515. @@SetRUN:    mov    ax,3e00h        ;close file, we don't need it.
  4516.     int    21h
  4517.     mov    ax,_cwMain
  4518.     mov    ds,ax
  4519.     assume ds:_cwMain
  4520.     push    es
  4521.     mov    es,RealPSPSegment
  4522.     mov    si,80h
  4523.     xor    ch,ch
  4524.     mov    cl,es:b[si]
  4525.     or    cx,cx
  4526.     jz    @@sr5
  4527.     inc    si
  4528.     mov    di,offset MainExec    ;default to storeing program name.
  4529.     ;
  4530.     ;Skip white space.
  4531.     ;
  4532. @@sr0:    mov    al,es:[si]
  4533.     cmp    al," "
  4534.     jnz    @@sr1
  4535.     inc    si
  4536.     dec    cx
  4537.     jnz    @@sr0
  4538.     jmp    @@sr3
  4539.     ;
  4540.     ;Get program name.
  4541.     ;
  4542. @@sr1:    mov    al,es:[si]
  4543.     cmp    al," "
  4544.     jz    @@sr2
  4545.     mov    es:b[si],' '
  4546.     mov    [di],al
  4547.     inc    si
  4548.     inc    di
  4549.     dec    cx
  4550.     jnz    @@sr1
  4551. @@sr2:    mov    b[di],0
  4552. @@sr3:    pop    es
  4553. ;
  4554. ;Clean up the command line, ie, remove any spaces created by removeing name.
  4555. ;
  4556.     push    es
  4557.     mov    es,RealPSPSegment
  4558.     mov    si,80h
  4559.     xor    ch,ch
  4560.     mov    cl,es:b[si]
  4561.     or    cx,cx
  4562.     jz    @@cl3
  4563.     inc    si
  4564.     mov    di,si
  4565. @@cl0:    cmp    es:b[si],' '
  4566.     jnz    @@cl1
  4567.     inc    si
  4568.     dec    cx
  4569.     jnz    @@cl0
  4570. @@cl1:    jcxz    @@cl2
  4571.     push    cx
  4572.     push    ds
  4573.     push    es
  4574.     pop    ds
  4575.     rep    movsb        ;Copy it down.
  4576.     pop    ds
  4577.     pop    cx
  4578. @@cl2:    mov    es:b[80h],cl        ;Store new length.
  4579. @@cl3:    xor    ch,ch
  4580.     add    cx,81h
  4581.     mov    si,cx
  4582.     mov    es:b[si],13        ;Terminate it correctly.
  4583. @@sr5:    pop    es
  4584.     ;
  4585.     assume ds:_cwMain
  4586. @@5:    pop    ds
  4587.     ret
  4588. GetSystemFlags    endp
  4589.  
  4590.  
  4591. ;-------------------------------------------------------------------------------
  4592. GetProtectedType proc near
  4593. ;
  4594. ;Find out what protected mode environments are available.
  4595. ;
  4596.     call    ChkDPMI        ;32 bit DPMI server present?
  4597.     jc    @@0
  4598.     or    ProtectedFlags,1
  4599. @@0:    call    ChkVCPI        ;VCPI >= v1.0 present?
  4600.     jc    @@1
  4601.     or    ProtectedFlags,2
  4602. @@1:    call    ChkRAW        ;Running in real mode?
  4603.     jc    @@2
  4604.     or    ProtectedFlags,4
  4605. @@2:    ret
  4606. GetProtectedType endp
  4607.  
  4608.  
  4609. ;-------------------------------------------------------------------------------
  4610. SetProtectedType proc near
  4611.     cmp    ProtectedForce,0
  4612.     jz    @@NoDPMIForce
  4613.     test    ProtectedFlags,1
  4614.     jnz    @@2
  4615.     ;
  4616. @@NoDPMIForce:    test    ProtectedFlags,4
  4617.     jz    @@1
  4618.     mov    ProtectedType,0    ;Use real mode.
  4619.     jmp    @@3
  4620. @@1:    test    ProtectedFlags,2
  4621.     jz    @@2
  4622.     mov    ProtectedType,1    ;Use VCPI.
  4623.     jmp    @@3
  4624. @@2:    mov    ProtectedType,2    ;Use DPMI.
  4625. @@3:    push    es
  4626.     mov    ax,_cwInit
  4627.     mov    es,ax
  4628.     assume es:_cwInit
  4629.     mov    ax,ProtectedType
  4630.     mov    es:IProtectedType,ax
  4631.     assume es:nothing
  4632.     pop    es
  4633.     ret
  4634. SetProtectedType endp
  4635.  
  4636.  
  4637. ;-------------------------------------------------------------------------------
  4638. ChkDPMI    proc    near
  4639. ;
  4640. ;See if DPMI server present.
  4641. ;
  4642.     mov    ax,1687h        ;DPMI instalation check.
  4643.     int    2fh
  4644.     or    ax,ax        ;None-zero means its not there.
  4645.     jnz    @@9
  4646.     test    w[SystemFlags],1
  4647.     jz    @@Use32Bit21
  4648.     jmp    @@Use16Bit21
  4649. @@Use32Bit21:    test    bx,1        ;Must offer 32 bit support.
  4650.     jz    @@9
  4651. @@Use16Bit21:    clc
  4652.     ret
  4653.     ;
  4654. @@9:    stc
  4655.     ret
  4656. ChkDPMI    endp
  4657.  
  4658.  
  4659. ;-------------------------------------------------------------------------------
  4660. ;
  4661. ; The following routine checks to see if a VCPI master program is installed.
  4662. ; If one is not, the carry flag is set on return
  4663. ; If one is, the version info is stored and the carry flag is cleared on return
  4664. ;
  4665. ChkVCPI    proc    near
  4666.     pushm    ax,bx,es
  4667.     xor    ax,ax
  4668.     mov    es,ax
  4669.     mov    si,es:[67h*4]    ;Check a handler exists.
  4670.     mov    di,es:[(67h*4)+2]
  4671.     mov    ax,si
  4672.     or    ax,di
  4673.     jnz    @@IsHandler
  4674.     cli
  4675.     mov    es:w[67h*4],offset @@DummyIRET
  4676.     mov    es:w[(67h*4)+2],cs
  4677. @@IsHandler:    pushm    si,di
  4678.     mov    ax,0DE00h        ;Get VCPI installed state
  4679.     int    67h
  4680.     popm    si,di
  4681.     mov    es:[67h*4],si    ;Check a handler exists.
  4682.     mov    es:[(67h*4)+2],di
  4683.     sti
  4684.     ;
  4685.     cmp    al,0
  4686.     jne    @@NotThere
  4687.     or    bx,3030h        ;Turn to ASCII
  4688.     cmp    bh,'1'
  4689.     jc    @@NotThere
  4690.     mov    ax,si
  4691.     or    ax,di        ;Only pretending to be their?
  4692.     jz    @@HopeThere
  4693.     ;
  4694.     call    @@ChkEMS        ;Make sure EMS is in first
  4695.     jc    @@HopeThere        ;EMS not in.
  4696.     call    @@GrabPage        ;Make sure EMS initiated
  4697. @@HopeThere:    clc            ;Set for no error
  4698.     jmp    @@Done
  4699. @@NotThere:    stc
  4700. @@Done:    popm    ax,bx,es
  4701.     ret
  4702. @@DummyIRET:    iret
  4703. ;
  4704. ; The following routine checks to see if an EMM is installed.
  4705. ; If one is not, the carry flag is set on return
  4706. ; If one is, the carry flag is cleared on return
  4707. ;
  4708. @@ChkEMS:    pushm    ax,bx,dx,es
  4709.     pushm    ds,cs
  4710.     pop    ds
  4711.     mov    dx,offset @@EMSName    ;Device driver name
  4712.     mov    ah,3Dh        ;Open file
  4713.     mov    al,0        ;Access/file sharing mode
  4714.     int    21h
  4715.     pop    ds
  4716.     jc    @@NotThere2
  4717.     mov    bx,ax        ;Put handle in proper place
  4718.     mov    ah,44h        ;IOCTL
  4719.     mov    al,07h        ;Get output status
  4720.     int    21h
  4721.     jc    @@NotThere1
  4722.     cmp    al,0FFh
  4723.     jne    @@NotThere1
  4724.     mov    ah,3Eh        ;Close file
  4725.     int    21h
  4726.     clc            ;Set for no error
  4727.     jmp    @@Done1
  4728. @@NotThere1:    mov    ah,3Eh        ;Close file
  4729.     int    21h
  4730. @@NotThere2:    stc
  4731. @@Done1:    popm    ax,bx,dx,es
  4732.     ret
  4733. ;
  4734. ; This function allocates an EMS page, and then releases it.  This is
  4735. ; done to make sure the EMS driver has switched the CPU to V86 mode.
  4736. ; On return, the carry is set if there was any problem using the EMS
  4737. ; functions.  Carry is clear otherwise.
  4738. ;
  4739. @@GrabPage:    mov    ah,43h        ;Allocate pages
  4740.     mov    bx,1        ;Get 1 page (16K)
  4741.     int    67h
  4742.     cmp    ah,0        ;Was there an error?
  4743.     jne    @@GPErr        ;Yes, so exit
  4744.     mov    ah,45h        ;Release EMS handle
  4745.     int    67h
  4746.     cmp    ah,0        ;Was there an error?
  4747.     jne    @@GPErr        ;Yes, so exit
  4748.     clc            ;Mark for no error
  4749.     jmp    @@GPEnd
  4750. @@GPErr:    stc
  4751. @@GPEnd:    ret
  4752. ;
  4753. @@EMSName    DB 'EMMXXXX0',0
  4754. ChkVCPI    endp
  4755.  
  4756.  
  4757. ;-------------------------------------------------------------------------------
  4758. ChkRAW    proc    near
  4759. ;
  4760. ;Can we run on this machine.
  4761. ;
  4762.     .286
  4763.     smsw    ax
  4764.     and    ax,1             ; are we in protected mode?
  4765.     jnz    @@9
  4766.     clc
  4767.     ret
  4768. @@9:    stc
  4769.     ret
  4770. ChkRAW    endp
  4771.  
  4772.  
  4773. ;-------------------------------------------------------------------------------
  4774. MakeDesc    proc    near
  4775. ;
  4776. ;Build a segment descriptor.
  4777. ;
  4778. ;On Entry:-
  4779. ;
  4780. ;ES:DI    - Descriptor entry to use.
  4781. ;ESI    - Linear base to set.
  4782. ;ECX    - limit in bytes.
  4783. ;AL    - Code size bit.
  4784. ;AH    - Present/PL/memory|system/type bits.
  4785. ;
  4786.     .386
  4787.     pushad
  4788.     and    di,not 7        ;lose RPL & TI
  4789.     cmp    ecx,0100000h      ; see if we need to set g bit
  4790.     jc    @@0
  4791.     shr    ecx,12           ; div by 4096
  4792.     or    al,80h           ; set g bit
  4793. @@0:    mov    es:[di],cx        ;store low word of limit.
  4794.     shr    ecx,16
  4795.     or    cl,al
  4796.     mov    es:[di+6],cl        ;store high bits of limit and gran/code size bits.
  4797.     mov    es:[di+2],si        ;store low word of linear base.
  4798.     shr    esi,16
  4799.     mov    bx,si
  4800.     mov    es:[di+4],bl        ;store mid byte of linear base.
  4801.     mov    es:[di+7],bh        ;store high byte of linear base.
  4802.     mov    es:[di+5],ah        ;store pp/dpl/dt/type bits.
  4803.     popad
  4804.     ret
  4805. MakeDesc    endp
  4806.  
  4807.  
  4808. ;-------------------------------------------------------------------------------
  4809. ;
  4810. ;Build a segment descriptor.
  4811. ;
  4812. ;On Entry:-
  4813. ;
  4814. ;ES:DI    - Descriptor entry to use.
  4815. ;ESI    - Linear base to set.
  4816. ;ECX    - limit in bytes.
  4817. ;AL    - Code size bit.
  4818. ;AH    - Present/PL/memory|system/type bits.
  4819. ;
  4820. MakeDesc2    proc    near
  4821.     .386
  4822.     pushad
  4823.     and    edi,not 7        ;lose RPL & TI
  4824.     cmp    ecx,0100000h      ; see if we need to set g bit
  4825.     jc    @@0
  4826.     shr    ecx,12           ; div by 4096
  4827.     or    al,80h           ; set g bit
  4828. @@0:    mov    es:[edi],cx        ;store low word of limit.
  4829.     shr    ecx,16
  4830.     or    cl,al
  4831.     mov    es:[edi+6],cl    ;store high bits of limit and gran/code size bits.
  4832.     mov    es:[edi+2],si    ;store low word of linear base.
  4833.     shr    esi,16
  4834.     mov    bx,si
  4835.     mov    es:[edi+4],bl    ;store mid byte of linear base.
  4836.     mov    es:[edi+7],bh    ;store high byte of linear base.
  4837.     mov    es:[edi+5],ah    ;store pp/dpl/dt/type bits.
  4838.     popad
  4839.     ret
  4840. MakeDesc2    endp
  4841.  
  4842.  
  4843. ;-------------------------------------------------------------------------------
  4844. ;
  4845. ;Dummy routine to call so that IDT value is re-loaded.
  4846. ;
  4847. IDTFlush    proc    far
  4848.     ret
  4849. IDTFlush    endp
  4850.  
  4851.  
  4852. ;-------------------------------------------------------------------------------
  4853. Bordi    proc    near
  4854.     pushm    ax,dx
  4855.     mov    ah,al
  4856.     mov    dx,3dah
  4857.     in    al,dx
  4858.     mov    dl,0c0h
  4859.     mov    al,11h
  4860.     out    dx,al
  4861.     mov    al,ah
  4862.     out    dx,al
  4863.     mov    al,20h
  4864.     out    dx,al
  4865.     popm    ax,dx
  4866.     ret
  4867. Bordi    endp
  4868.  
  4869.  
  4870. ;-------------------------------------------------------------------------------
  4871. ;
  4872. ;Initialisation specific data.
  4873. ;
  4874. apiDataSegi    dw 0
  4875. IProtectedMode    db 0
  4876. IProtectedType    dw 0
  4877. DPMISwitch    dw ?,?
  4878. dpmiSelBase    dd 0
  4879. dpmiCodeSel    dw ?
  4880. dpmiDataSel    dw ?
  4881. ;
  4882. iCodeSegment    dw InitCS
  4883. mCodeSegment    dw MainCS
  4884. iDataSegment    dw InitDS
  4885. mDataSegment    dw MainDS
  4886. iStackSegment    dw MainSS
  4887. iPSPSegment    dw MainPSP
  4888. iENVSegment    dw MainENV
  4889. iRealSegment    dw KernalZero
  4890. ;
  4891. INewHeader    NewHeaderStruc <>    ;make space for a header.
  4892. ;
  4893. IExeSignature    db ?    ;00 Identifier text.
  4894.     db ?    ;01 /
  4895. IExeLength    dw ?    ;02 Length of file MOD 512
  4896.     dw ?    ;04 Length of file in 512 byte blocks.
  4897. IExeRelocNum    dw ?    ;06 Number of relocation items.
  4898. IExeHeaderSize    dw ?    ;08 Length of header in 16 byte paragraphs.
  4899. IExeMinAlloc    dw ?    ;0A Minimum number of para's needed above program.
  4900. IExeMaxAlloc    dw ?    ;0C Maximum number of para's needed above program.
  4901. IExeStackSeg    dw ?    ;0E Segment displacement of stack module.
  4902. IExeEntrySP    dw ?    ;10 value for SP at entry.
  4903. IExeCheckSum    dw ?    ;12 Check sum...
  4904. IExeEntryIP    dw ?    ;14 Contents of IP at entry.
  4905. IExeEntryCS    dw ?    ;16 Segment displacement of CS at entry.
  4906. IExeRelocFirst    dw ?    ;18 First relocation item offset.
  4907. IExeOverlayNum    db ?    ;1A Overlay number.
  4908. ;
  4909. IErrorNumber    dw 0
  4910. InitErrorList    dw IErrorM00,IErrorM01,IErrorM02,IErrorM03,IErrorM04,IErrorM05,IErrorM06,IErrorM07
  4911.     dw IErrorM08,IErrorM09
  4912. IErrorM00    db 'CauseWay error '
  4913. IErrorM00n    db '00 : $'
  4914. IErrorM01    label byte
  4915.     if ENGLISH
  4916.     db 'Unable to re-size program memory block.',13,10,'$'
  4917.     elseif SPANISH
  4918.     db "Incapaz de redimensionar el bloque de memoria del programa",13,10,"$"
  4919.     endif
  4920. IErrorM02    label byte
  4921.     if ENGLISH
  4922.     db '386 or better required.',13,10,'$'
  4923.     elseif SPANISH
  4924.     db "Se requiere un 386 o superior.",13,10,"$"
  4925.     endif
  4926. IErrorM03    label byte
  4927.     if ENGLISH
  4928.     db 'Non-standard protected mode program already active.',13,10,'$'
  4929.     elseif SPANISH
  4930.     db "Programa en modo protegido no estandar activado.",13,10,"$"
  4931.     endif
  4932. IErrorM04    label byte
  4933.     if ENGLISH
  4934.     db 'DOS 3.1 or better required.',13,10,'$'
  4935.     elseif SPANISH
  4936.     db "DOS 3.1 o superior requerido.",13,10,"$"
  4937.     endif
  4938. IErrorM05    label byte
  4939.     if ENGLISH
  4940.     db 'Not enough memory for CauseWay.',13,10,'$'
  4941.     elseif SPANISH
  4942.     db "Memoria insuficiente para CauseWay.",13,10,"$"
  4943.     endif
  4944. IErrorM06    label byte
  4945.     if ENGLISH
  4946.     db 'VCPI failed to switch into protected mode.',13,10,'$'
  4947.     elseif SPANISH
  4948.     db "VCPI fallo al cambiar a modo protegido.",13,10,"$"
  4949.     endif
  4950. IErrorM07    label byte
  4951.     if ENGLISH
  4952.     db 'Unable to control A20.',13,10,'$'
  4953.     elseif SPANISH
  4954.     db "Capaz de controlar A20.",13,10,"$"
  4955.     endif
  4956. IErrorM08    label byte
  4957.     if ENGLISH
  4958.     db 'Selector allocation error.',13,10,'$'
  4959.     elseif SPANISH
  4960.     db "Error de asignacion del selector.",13,10,"$"
  4961.     endif
  4962. IErrorM09    label byte
  4963.     if ENGLISH
  4964.     db 'DPMI failed to switch to protected mode.',13,10,'$'
  4965.     elseif SPANISH
  4966.     db "DPMI fallo al cambiar a modo protegido.",13,10,"$"
  4967.     endif
  4968. ;
  4969. IFDEF PERMNOVM
  4970. NoVMSwitch    db 1
  4971. ELSE
  4972. NoVMSwitch    db 0
  4973. ENDIF
  4974.  
  4975. VMMDrivPath1    db 128 dup (0)    ;used by CAUSEWAY=SWAP:?:\??
  4976. VMMDrivPath2    db 128 dup (0)    ;used by TEMP=
  4977. VMMDrivPath3    db 128 dup (0)    ;used by TMP=
  4978. VMMDrivPath4    db 128 dup (0)    ;used by current path.
  4979. VMMDrivPath5    db 128 dup (0)    ;used by boot drive.
  4980.     db -1
  4981. ;
  4982. DPMIErrRegs    db size RealRegsStruc dup (0)
  4983. ;
  4984. _cwInit    ends
  4985.  
  4986.  
  4987. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  4988. ;
  4989. ;End marker so we know what to resize program memory size to initialy.
  4990. ;
  4991. _cwEnd    segment para public 'end marker'
  4992. _cwEnd    ends
  4993.  
  4994.     end    Startup
  4995.