;       SCCSID = @(#)demmisc2.asm	6.2 92/02/06

        TITLE MISC2 - Miscellanious routines for MS-DOS

;
; Miscellaneous useful routines
;
;   StrCpy
;   StrCmp
;   Ucase
;   StrLen
;   DStrLen
;   Idle
;   TableDispatch
;   FastInit                      ; DOS 4.0
;   FastRet                       ; DOS 4.0
;   NLS_OPEN                      ; DOS 4.0
;   NLS_LSEEK                     ; DOS 4.0
;   Fake_User_Stack               ; DOS 4.0
;   GetDevList                    ; DOS 4.0
;   NLS_IOCTL                     ; DOS 4.0
;   NLS_GETEXT                    ; DOS 4.0
;   MSG_RETRIEVAL                 ; DOS 4.0
;   Fake_Version                  ; DOS 4.0
;
;   Revision history:
;
;       Created: ARR 30 March 1983
;
;       A000   version 4.0   Jan. 1988
;       A001   DCR 486 - Share installation for >32mb drives
;       A006   DCR 503 - fake version number for IBMCACHE

.xlist
;
; get the appropriate segment definitions
;
include v86seg.inc
.xcref
include basemaca.inc
include osmaca.inc
include oldmaca.inc
include demmac.inc
include dossymc.inc
include demdbcs.inc
include struc30.inc
.cref
.list
        CpuMode 8086

V86CODE    SEGMENT
        ASSUME  CS:V86GROUP

        ReferV86  User_SP_2F,WORD         ;AN000;
        ReferV86  User_SP,WORD            ;AN000;
        ReferV86  User_SS,WORD            ;AN000;
        ReferV86  SysInitTable,BYTE       ;AN000;
        ReferV86  EXTERR,WORD             ;AN000;
        ReferV86  MSG_EXTERROR,DWORD      ;AN000;
        ReferV86  fshare,byte             ;AN001;
        ReferV86  Special_version,WORD    ;AN006;

Procedure   FStrCpy,NEAR
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING
        SaveReg <AX>
FCPYLoop:
        LODSB
        STOSB
        OR      AL,AL
        JNZ     FCPYLoop
        RestoreReg  <AX>
        return
EndProc FStrCpy


Break <Str$Len - compute length of string DS:DX>

;
;   StrLen  - Compute length of string DS:DX
;   Inputs:     DS:DX - pointer to string
;   Outputs:    CX is size of string NOT INCLUDING the "$"
;   Registers modified: CX

Procedure   Str$Len,NEAR
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING
        PUSH    DI
        PUSH    AX
        PUSH    ES

        CLD
        MOV     DI,DX
        PUSH    DS
        POP     ES
        MOV     CX,-1
        MOV     AL,'$'
        REPNE   SCASB
        NOT     CX
        DEC     CX

        POP     ES
        POP     AX
        POP     DI
        return
EndProc Str$Len

Break <StrLen - compute length of string ES:DI>

;
;   StrLen  - Compute length of string ES:DI
;   Inputs:     ES:DI - pointer to string
;   Outputs:    CX is size of string INCLUDING the NUL
;   Registers modified: CX

Procedure   StrLen,NEAR
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING
        PUSH    DI
        PUSH    AX
        MOV     CX,-1
        XOR     AL,AL
        REPNE   SCASB
        NOT     CX
        POP     AX
        POP     DI
        return
EndProc StrLen

;
;   DStrLen  - Compute length of string DS:SI
;   Inputs:     DS:SI - pointer to string
;   Outputs:    CX is size of string INCLUDING the NUL
;   Registers modified: CX
Procedure   DStrLen,NEAR
        CALL    XCHGP
        CALL    StrLen
        CALL    XCHGP
        return
EndProc DStrLen

Break   <XCHGP - exchange source and destination pointers>

Procedure XCHGP,NEAR
        SaveReg <DS,ES>
        RestoreReg  <DS,ES>
        XCHG    SI,DI
        return
EndProc XCHGP

ifdef NOT_MVDM ; BUGBUG danno 07-Dec-1988

Break   <Idle - wait for a specified amount of time>

;
;   Idle - when retrying an operation due to a lock/sharing violation, we spin
;   until RetryLoop is exhausted.
;
;   Inputs:     RetryLoop is the number of times we spin
;   Outputs:    Wait
;   Registers modified: none

Procedure   Idle,NEAR
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING
        TEST    fSharing,-1
        retnz
        SaveReg <CX>
        MOV     CX,RetryLoop
        JCXZ    Idle3
Idle1:  PUSH    CX
        XOR     CX,CX
Idle2:  LOOP    Idle2
        POP     CX
        LOOP    Idle1
Idle3:  RestoreReg  <CX>
        return
EndProc Idle

endif ; BUGBUG danno 07-Dec-1988

Break   <TableDispatch - dispatch to a table>

;
;   TableDispatch - given a table and an index, jmp to the approptiate
;   routine.  Preserve all input registers to the routine.
;
;   Inputs:     Push    return address
;               Push    Table address
;               Push    index (byte)
;   Outputs:    appropriate routine gets jumped to.
;               return indicates invalid index
;   Registers modified: none.

TableFrame  STRUC
OldBP   DW  ?
OldRet  DW  ?
Index   DB  ?
Pad     DB  ?
Tab     DW  ?
NewRet  DW  ?
TableFrame  ENDS

procedure   TableDispatch,NEAR
        ASSUME  CS:V86GROUP,DS:NOTHING,SS:NOTHING,SS:NOTHING
        PUSH    BP
        MOV     BP,SP
        PUSH    BX                      ; save BX
        MOV     BX,[BP.Tab]             ; get pointer to table
        MOV     BL,CS:[BX]              ; maximum index
        CMP     [BP.Index],BL           ; table error?
        JAE     TableError              ; yes
        MOV     BL,[BP.Index]           ; get desired table index
        XOR     BH,BH                   ; convert to word
        SHL     BX,1                    ; convert to word pointer
        INC     BX                      ; point past first length byte
        ADD     BX,[BP.Tab]             ; get real offset
        MOV     BX,CS:[BX]              ; get contents of table entry
        MOV     [BP.Tab],BX             ; put table entry into return address
        POP     BX                      ; restore BX
        POP     BP                      ; restore BP
        ADD     SP,4                    ; clean off Index and our return addr
        return                          ; do operation
TableError:
        POP     BX                      ; restore BX
        POP     BP                      ; restore BP
        RET     6                       ; clean off Index, Table and RetAddr
EndProc TableDispatch

ifdef NOT_MVDM ; BUGBUG danno 07-Dec-1988

Break   <Fake_User_Stack - save uesr stack >


;   DOS 3.3   6/10/86
;   Fake_User_Stack - save user stack pointer
;

Procedure   Fake_User_Stack,NEAR
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING

        MOV     AX,[User_SP_2F]               ; replace with INT 2F stack
        MOV     [user_SP],AX

        MOV     AX,CS
        MOV     [user_SS],AX                  ; V86GROUP

        RET
EndProc Fake_User_Stack

;
Break   <GetDevList - get device header list pointer>


;   DOS 3.3   7/25/86
;   GetDevList - get device header list pointer
;
;   Output: AX:BX points to the device header list

Procedure   GetDevList,NEAR
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING

        MOV     SI,OFFSET V86GROUP:SysInitTable
        LDS     SI,CS:[SI.SYSI_InitVars]

        MOV     AX,WORD PTR DS:[SI.SYSI_DEV]
        MOV     BX,WORD PTR DS:[SI.SYSI_DEV+2]

        RET
EndProc GetDevList


Break   <MSG_RETRIEVAL- get beginning addr of system and parser messages>

;   DOS 4.00
;
;   Inputs:     DL=0 get extended error message addr
;                 =1 set extended error message addr
;                 =2 get parser error message addr
;                 =3 set parser error message addr
;                 =4 get critical error message addr
;                 =5 set critical error message addr
;                 =6 get file system error message addr
;                 =7 set file system error message addr
;                 =8 get address for code reduction
;                 =9 set address for code reduction
;   Function:   get/set message address
;   Outputs:    ES:DI points to addr when get
;

Procedure   MSG_RETRIEVAL,NEAR                                    ;AN000;
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING      ;AN000;

        PUSH    AX                  ;AN000;;MS. save regs
        PUSH    SI                  ;AN000;;MS. save regs
        MOV     AX,DX               ;AN000;;MS.
        MOV     SI,OFFSET V86GROUP:MSG_EXTERROR ;AN000;;MS.
        TEST    AL,1                ;AN000;;MS. get ?
        JZ      toget               ;AN000;;MS. yes
        DEC     AL                  ;AN000;;MS.
toget:                              ;AN000;
        SHL     AL,1                ;AN000;;MS. times 2
        XOR     AH,AH               ;AN000;;MS.
        ADD     SI,AX               ;AN000;;MS. position to the entry
        TEST    DL,1                ;AN000;;MS. get ?
        JZ      getget                       ;AN000;;MS. yes
        MOV     WORD PTR CS:[SI],DI    ;AN000;;MS. set MSG
        MOV     WORD PTR CS:[SI+2],ES  ;AN000;;MS. address to ES:DI
        JMP     SHORT MSGret                 ;AN000;;MS. exit
getget:                                      ;AN000;
        LES     DI,DWORD PTR CS:[SI]         ;AN000;;MS. get msg addr
MSGret:                                      ;AN000;
        POP     SI                           ;AN000;;MS.
        POP     AX                           ;AN000;;MS.
        return                               ;AN000;;MS. exit

EndProc MSG_RETRIEVAL                        ;AN000;


Break   <Fake_version - set/reset version flag>

;
;   Inputs:     DL=0 current version number
;                 <>0  special version number
;   Function:   set special version number
;   Outputs:    version number is changed
;

Procedure   Fake_version,NEAR                                     ;AN000;
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING      ;AN000;

        MOV     [Special_version],DX   ;AN006;MS.
        return                         ;AN006;;MS. exit

EndProc Fake_version                   ;AN006;;MS.


endif ; BUGBUG danno 07-Dec-1988


V86CODE    ENDS

    END
