;
;  LibInit.asm	library stub to do local init for a Dynamic linked library
;
;  NOTE!!!! link this MODULE first or you will be sorry!!!!
;
?PLM=1  ; pascal call convention
?WIN=0  ; Windows prolog/epilog code
?DF=1
PMODE=1

.286
.xlist
include cmacros.inc
include windows.inc
include sysinfo.inc
include mmddk.inc
include mmsystem.inc
include timer.inc
;include vtdapi.inc
.list

.list

sBegin  Data
;
; Stuff needed to avoid the C runtime coming in
;
; also known as "MAGIC THAT SAVED ME" - Glenn Steffler 2/7/90
;
; Do not remove under penalty of sex change operation!!
;
            DD  0               ; So null pointers get 0
maxRsrvPtrs = 5
            DW  maxRsrvPtrs
usedRsrvPtrs = 0
labelDP     <PUBLIC,rsrvptrs>

DefRsrvPtr  MACRO   name
globalW     name,0
usedRsrvPtrs = usedRsrvPtrs + 1
ENDM

DefRsrvPtr  pLocalHeap          ; Local heap pointer
DefRsrvPtr  pAtomTable          ; Atom table pointer
DefRsrvPtr  pStackTop           ; top of stack
DefRsrvPtr  pStackMin           ; minimum value of SP
DefRsrvPtr  pStackBot           ; bottom of stack

if maxRsrvPtrs-usedRsrvPtrs
            DW maxRsrvPtrs-usedRsrvPtrs DUP (0)
endif

public  __acrtused
	__acrtused = 1

sEnd    Data

;
;
; END of nasty shit wierdness stuff that made my life a living hell...
;

externA     WinFlags
externFP    LocalInit
externFP    Disable286
externFP    Enable286
externW     wMaxResolution
externW     wMinPeriod

; here lies the global data

sBegin  Data

public wEnabled
wEnabled	dw  0		; enable = 1 ;disable = 0

public PS2_MCA
PS2_MCA         db      ?       ; Micro Channel Flag

sEnd    Data

    assumes es,nothing

sBegin  CodeInit
    assumes cs,CodeInit
    assumes ds,Data

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   Library unload function
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Disable routine is same as WEP

cProc   WEP,<FAR,PUBLIC>,<>
;   parmW   silly_param
cBegin nogen

    errn$   Disable

cEnd nogen

cProc   Disable,<FAR,PUBLIC>,<>
;   parmW   silly_param
cBegin nogen
    push    ds
    mov     ax,DGROUP           ; set up DS==DGROUP for exported funcs
    mov     ds,ax
    assumes ds,Data

    xor     ax,ax		; return value = no error

    cmp     wEnabled,ax 	; Q: enabled ?
    jz	    dis_done		; N: exit

    mov     wEnabled,ax 	; disabled now

    mov     ax,WinFlags
    test    ax,WF_WIN386
    jnz     dis_386

    ; running under win286
dis_286:
    call    Disable286
    jmp     dis_done

    ; running under win386
dis_386:
    call    Disable286

dis_done:
    pop     ds
    ret     2

cEnd nogen

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   Library Enable function
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cProc	Enable,<FAR,PUBLIC>,<>
;   parmW   silly_param
cBegin nogen
    mov     ax,wEnabled
    or      ax,ax               ; Q: already enabled ?
    jnz     enable_done 	; Y: exit

    inc     wEnabled		; mark as being enabled

    mov     ax,WinFlags
    test    ax,WF_WIN386
    jnz     enable_386

    ; running under win286
enable_286:
    call    Enable286
    jmp     enable_done

    ; running under win386
enable_386:
    call    Enable286

enable_done:
    ret     2

cEnd nogen

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       Library entry point
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

public LibInit
LibInit proc far

    ; CX    = size of heap
    ; DI    = module handle
    ; DS    = automatic data segment
    ; ES:SI = address of command line (not used)

    jcxz    lib_heapok	    ; heap size zero? jump over unneeded LocalInit call

    cCall   LocalInit,<ds,ax,cx>    ; dataseg, 0, heapsize
    or	    ax,ax
    jnz     lib_heapok	    ; if heap set continue on

lib_error:
    xor     ax,ax
    ret 		    ; return FALSE (ax = 0) -- couldn't init

lib_heapok:
    mov     ax,WinFlags
    test    ax,WF_WIN386
    jnz     lib_386

    ; running under win286
lib_286:
    call    Lib286Init
    jmp     lib_realdone    ; win 286 will enable timer on first event request

    ; running under win386
lib_386:
    call    Lib286Init

lib_realdone:
    ret

LibInit endp

sEnd

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   Win 386 timer VTD code for initialization, and removal
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        externFP        GetVersion          ; in KERNEL
        externFP        MessageBox          ; in USER
        externFP        LoadString          ; in USER

sBegin  CodeInit
assumes cs,CodeInit
assumes ds,Data

;externNP    VTDAPI_GetEntryPt

; Assumes DI contains module handle
cProc WarningMessage <NEAR,PASCAL> <>
    LocalV aszErrorTitle, 32
    LocalV aszErrorMsg, 256
cBegin
    lea     ax, WORD PTR aszErrorTitle
    cCall   LoadString, <di, IDS_ERRORTITLE, ss, ax, 32>
    lea     ax, WORD PTR aszErrorMsg
    cCall   LoadString, <di, IDS_ERRORTEXT, ss, ax, 256>
    lea     ax, WORD PTR aszErrorTitle
    lea     bx, WORD PTR aszErrorMsg
    cCall   MessageBox, <NULL, ss, bx, ss, ax, MB_SYSTEMMODAL+MB_OK+MB_ICONHAND>
cEnd

if 0
Lib386Init proc near

    call    VTDAPI_GetEntryPt       ; this will return 0 if the VxD is not loaded

    or      ax,ax
    jnz     Lib386InitOk

    DOUT    <TIMER: *** unable to find vtdapi.386 ***>

    ;
    ;   warn the USER that we can't find our VxD, under windows 3.0
    ;   we can't bring up a message box, so only do this in win 3.1
    ;

    cCall   GetVersion
    xchg    al,ah
    cmp     ax,030Ah
    jb      Lib386InitFail

    cCall   WarningMessage,<>

Lib386InitFail:
    xor     ax,ax

Lib386InitOk:

    ret

Lib386Init endp
endif

Disable386 proc near

    errn$   Enable386               ; fall through

Disable386 endp

Enable386 proc near

    mov     ax,1		    ; nothing to do
    ret

Enable386 endp

sEnd	Code386

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   Win 286 timer drv code for initialization, and removal
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    externW     Events
    externFP    tddISR                  ; in local.asm

    externFP    GlobalWire              ; in KERNEL
    externFP    GlobalPageLock          ; in KERNEL

sBegin  CodeInit
    assumes cs,CodeInit
    assumes ds,Data

Lib286Init proc near
    ; get the system configuration

    ;
    ;   the FIXED_286 segment is not loaded, load it and pagelock it.
    ;
    mov     dx,seg tddISR               ; get the 286 code segment
    mov     es,dx
    mov     ax,es:[0]                   ; load it!
    cCall   GlobalWire, <dx>            ; get it low in memory
    cCall   GlobalPageLock, <dx>        ; and nail it down!

    mov     PS2_MCA,0			; Initialize PS2_MCA = FALSE
    stc					; Set this in case BIOS doesn't
    mov     ah,GetSystemConfig
    int     15h
    jc      Lib286Init_NoMicroChannel	; Successful call?
    or      ah,ah			; Valid return?
    jnz     Lib286Init_NoMicroChannel
    test    es:[bx.SD_feature1],SF1_MicroChnPresent
    jz      Lib286Init_NoMicroChannel
    inc     PS2_MCA			; PS2_MCA = TRUE
Lib286Init_NoMicroChannel:

    push    di

    push    ds
    pop     es
    mov     di,DataOFFSET Events	; ES:DI --> Events
    xor     ax,ax
    mov     cx,(MAXEVENTS * SizeEvent)/2
    rep     stosw			; zero out event structures.

    ; set up one event as the standard call-back routine for the
    ; BIOS timer service
    ;
    xor     bx,bx			; BX:CX = 64k
    xor     cx,cx
    inc     bx

    mov     di,DataOFFSET Events	; DS:DI --> Events

    mov     [di].evTime.lo,cx		; Program next at ~= 55ms
    mov     [di].evTime.hi,bx		; standard 18.2 times per second event
    mov     [di].evDelay.lo,cx		; First event will be set off
    mov     [di].evDelay.hi,bx		; at 55ms (65536 ticks)
    mov     [di].evResolution,TDD_MINRESOLUTION	; Allow 55ms either way
    mov     [di].evFlags,TIME_BIOSEVENT+TIME_PERIODIC

    mov     ax,WinFlags
    test    ax,WF_CPU286
    jz      @f
    mov     wMaxResolution,TDD_MAX286RESOLUTION
    mov	    wMinPeriod,TDD_MIN286PERIOD
@@:
    mov     ax,bx                       ; Return TRUE
    mov     [di].evID,ax		; enable event

    pop     di
    ret

Lib286Init endp

sEnd

    end LibInit
