440 lines
9.6 KiB
NASM
440 lines
9.6 KiB
NASM
;
|
|
; 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!!
|
|
;
|
|
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 stuff...
|
|
;
|
|
|
|
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
|
|
ifdef NEC_98
|
|
PS2_MCA db 0 ; Micro Channel Flag
|
|
public bClockFlag ; save machine clock
|
|
bClockFlag db 0 ; 5Mhz = 0 ; 8Mhz = other
|
|
else ; NEC_98
|
|
PS2_MCA db ? ; Micro Channel Flag
|
|
endif ; NEC_98
|
|
|
|
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
|
|
|
|
ifdef NEC_98
|
|
;
|
|
; Get system clock
|
|
;
|
|
mov ax,0002h
|
|
mov bx,0040h ; get segment addres
|
|
; make descriptor(real mode segment)
|
|
; return the segment descriptor
|
|
; in the case of exist the appointed segment descriptor already
|
|
; (not make sure repeatedly)
|
|
int 31h
|
|
jc error_exit ; in the case of failed ->jmp
|
|
|
|
push es
|
|
mov es,ax
|
|
mov al,byte ptr es:[101h] ; get system info
|
|
and al,80h
|
|
mov byte ptr bClockFlag,al ; save clock
|
|
pop es
|
|
endif ; NEC_98
|
|
|
|
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
|
|
|
|
ifdef NEC_98
|
|
error_exit:
|
|
dec wEnabled ; mark as being enabled
|
|
xor ax,ax
|
|
ret 2
|
|
endif ; NEC_98
|
|
|
|
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
|
|
|
|
ifndef NEC_98
|
|
DOUT <TIMER: *** unable to find vtdapi.386 ***>
|
|
endif ; NEC_98
|
|
|
|
;
|
|
; 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!
|
|
|
|
ifndef NEC_98
|
|
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
|
|
endif ; NEC_98
|
|
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
|
|
;
|
|
ifdef NEC_98
|
|
mov ax,0002h
|
|
mov bx,0040h
|
|
int 31h
|
|
jc error_init
|
|
push es
|
|
mov es,ax
|
|
test byte ptr es:[101h],80h
|
|
pop es
|
|
mov cx,0f000h
|
|
jz @f
|
|
mov cx,0c300h
|
|
@@:
|
|
xor bx,bx
|
|
else ; NEC_98
|
|
xor bx,bx ; BX:CX = 64k
|
|
xor cx,cx
|
|
inc bx
|
|
endif ; NEC_98
|
|
|
|
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
|
|
@@:
|
|
ifdef NEC_98
|
|
mov ax,0001h
|
|
else ; NEC_98
|
|
mov ax,bx ; Return TRUE
|
|
endif ; NEC_98
|
|
mov [di].evID,ax ; enable event
|
|
|
|
pop di
|
|
ret
|
|
|
|
ifdef NEC_98
|
|
error_init:
|
|
xor ax,ax
|
|
pop di
|
|
ret
|
|
endif ; NEC_98
|
|
|
|
Lib286Init endp
|
|
|
|
sEnd
|
|
|
|
end LibInit
|