;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; XMSRTN.ASM :- Moves data to and from extended memory.
;
;   Helper function for moving data to and from extended memory
;   through XMS manager which is HIMEM.SYS version 2.0 compatible.
;
;   You need to use MASM 6 to assemble the program.
;
;   Functions are:
;       sbkGetXMSEntry()
;       sbkAllocXM()
;       sbkFreeXM()
;       sbkMoveCMtoXM()
;       sbkMoveXMtoCM()
;
;
;   Author  : CWLim
;
;   Copyright (c) Creative Technology Ltd, 1993, All rights reserved
;
;
;   Important Note:
;       This source code is only intended as a supplement to the
;       existing SBK functions to facilitate the use of SBK
;       library.
;
;       You can use and modify these functions in any way you find
;       useful, provided that you agree that Creative Technology Ltd
;       has no warranty obligations or liability for any functions
;       which are modified.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

INCLUDE    sbkmodel.inc

;
; XMS API function numbers
;

ALLOCMEM   EQU    09H
FREEMEM    EQU    0AH
MOVEBLK    EQU    0BH


    .DATA

;
; Type-defined for XM move data structure
;
XMMoveStruct      STRUC
     dwBlkLen       DD    ?
     wSrcHandle     DW    0
     dwSrcOffset    DD    ?
     wDestHandle    DW    ?
     dwDestOffset   DD    ?
XMMoveStruct      ENDS

XMSControl          DD    0                    ; XMS entry
stMoveStruct        XMMoveStruct      <>


    .CODE   CodeSegmentName

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Get XMS driver entry address.
;
;   int sbkGetXMSEntry (void)
;
;   Entry :
;
;   Exit  :
;       Non-zero if successful, else returns 0.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

% sbkGetXMSEntry    PROC    <loaddsIF>      USES es

      MOV   AX,4300H
      INT   2FH
      CMP   AL,80H
      JE    gxm1
      MOV   AX,0
      JMP   SHORT gxm2
gxm1:
      MOV   AX,4310H
      INT   2FH
      MOV   WORD PTR [XMSControl],BX         ; XMS entry address
      MOV   WORD PTR [XMSControl+2],ES
      MOV   AX,1                             ; success
gxm2:
      RET
sbkGetXMSEntry      ENDP


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Allocates extended memory in a multiple of KBytes.
;
;   int  sbkAllocXM (WORD wBlkSize)
;
;   Entry :
;       wBlkSize :- block size to allocate
;
;   Exit  :
;       Handle of the allocated block, else returns 0.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

% sbkAllocXM    PROC    <loaddsIF>        wBlkSize : WORD

      MOV   AH,ALLOCMEM
      MOV   DX,wBlkSize
      CALL  [XMSControl]
      OR    AX,AX
      JE    @F
      MOV   AX,DX
@@:
      RET
sbkAllocXM      ENDP


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Releases the allocated extended memory.
;
;   int  sbkFreeXM (WORD wXMHandle)
;
;   Entry :
;       wXMHandle :- extended memory handle
;
;   Exit  :
;       Non-zero if successful, else returns 0.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

% sbkFreeXM    PROC    <loaddsIF>        wXMHandle : WORD

      MOV   AH,FREEMEM
      MOV   DX,wXMHandle
      CALL  [XMSControl]
      RET
sbkFreeXM     ENDP


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Moves a block of conventional memory to extended memory.
;
;   int sbkMoveCMtoXM (LPSTR lpBuf, DWORD dwMoveLen,
;                      WORD wXMHandle, DWORD dwXMOffset)
;
;   Entry :
;       lpBuf       :- buffer address in conventional memory
;       dwMoveLen   :- block length to move ( in even bytes)
;       wXMHandle   :- extended memory handle
;       dwXMOffset  :- extended memory offset
;
;   Exit  :
;       Non-zero if successful, else returns 0.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

% sbkMoveCMtoXM    PROC    <loaddsIF>   USES es di si,  lpBuf: FAR PTR BYTE,
                                                        dwMoveLen: DWORD,
                                                        wXMHandle: WORD,
                                                        dwXMOffset: DWORD
      MOV   SI,OFFSET DGROUP:stMoveStruct
      MOV   WORD PTR [SI].XMMoveStruct.wSrcHandle,0
      LES   DI,lpBuf
      MOV   WORD PTR [SI].XMMoveStruct.dwSrcOffset,DI
      MOV   WORD PTR [SI].XMMoveStruct.dwSrcOffset+2,ES

      ;
      ; Length has to be even byte, adjust if it
      ; is odd byte.
      ;
      LES   AX,dwMoveLen
      MOV   DX,ES
      TEST  AX,1                           ; odd byte ?
      JZ    @F
      ADD   AX,1
      ADC   DX,0                           ; if overflow, add to dx
@@:
      MOV   WORD PTR [SI].XMMoveStruct.dwBlkLen,AX
      MOV   WORD PTR [SI].XMMoveStruct.dwBlkLen+2,DX

      MOV   AX,wXMHandle
      MOV   WORD PTR [SI].XMMoveStruct.wDestHandle,AX

      LES   AX,dwXMOffset
      MOV   WORD PTR [SI].XMMoveStruct.dwDestOffset,AX
      MOV   WORD PTR [SI].XMMoveStruct.dwDestOffset+2,ES

      MOV   AH, MOVEBLK
      CALL  [XMSControl]
      RET
sbkMoveCMtoXM   ENDP

            
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Moves a block of extended memory to conventional memory.
;
;   int sbkMoveXMtoCM (LPSTR lpBuf, DWORD dwMoveLen,
;                      WORD wXMHandle, DWORD dwXMOffset)
;
;   Entry :
;       lpBuf       :- buffer address in conventional memory
;       dwMoveLen   :- block length to move ( in even bytes)
;       wXMHandle   :- extended memory handle
;       dwXMOffset  :- extended memory offset
;
;   Exit  :
;       Non-zero if successful, else returns 0.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

% sbkMoveXMtoCM    PROC    <loaddsIF>   USES es di si,  lpBuf: FAR PTR BYTE,
                                                        dwMoveLen: DWORD,
                                                        wXMHandle: WORD,
                                                        dwXMOffset: DWORD
      MOV   SI,OFFSET DGROUP:stMoveStruct
      MOV   WORD PTR [SI].XMMoveStruct.wDestHandle,0
      LES   DI,lpBuf
      MOV   WORD PTR [SI].XMMoveStruct.dwDestOffset,DI
      MOV   WORD PTR [SI].XMMoveStruct.dwDestOffset+2,ES

      ;
      ; Length has to be even byte, adjust if it
      ; is odd byte.
      ;
      LES   AX,dwMoveLen
      MOV   DX,ES
      TEST  AX,1                           ; odd byte ?
      JZ    @F
      ADD   AX,1
      ADC   DX,0                           ; if overflow, add to dx
@@:
      MOV   WORD PTR [SI].XMMoveStruct.dwBlkLen,AX
      MOV   WORD PTR [SI].XMMoveStruct.dwBlkLen+2,DX

      MOV   AX,wXMHandle
      MOV   WORD PTR [SI].XMMoveStruct.wSrcHandle,AX

      LES   AX,dwXMOffset
      MOV   WORD PTR [SI].XMMoveStruct.dwSrcOffset,AX
      MOV   WORD PTR [SI].XMMoveStruct.dwSrcOffset+2,ES

      MOV   AH, MOVEBLK
      CALL  [XMSControl]
      RET
sbkMoveXMtoCM   ENDP

       END          ;; End of code
