; ; 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