Metropoli BBS
VIEWER: frmi_ex.asm MODE: TEXT (CP437)
; Program to test FRMI with XMS
; Written by Erwann Corvellec

IDEAL
P386
JUMPS
MODEL LARGE, PASCAL

INCLUDE "FRMI.INC"
INCLUDE "MYMACROS.MAC"

STACK 200h
═══════════════════════════════════════════════════════════════════════════════

DATASEG
   XMS_TO_ALLOC     EQU 500
   XMS_TO_ALLOC_STR EQU "500"

   TCR              EQU 13, 10
   
   LABEL XMS_Handle WORD
         DW ?

   LABEL XMS_Address DWORD
         DD ?

   @MKPS ERRMSG_Bad_CPU,             <TCR, "A 386 CPU or greater is needed !", TCR>     
   @MKPS ERRMSG_V86,                 <TCR, "Your CPU is running in V86 MODE ! Please remove QEMM386, 386MAX, EMM386, etc.", TCR>
   
   @MKPS ERRMSG_PM,                  <TCR, "You're running under the ", 34>
   @MKPS ERRMSG_DPMS,                <"Novell DOS 7 DPMS">
   @MKPS ERRMSG_PHAR_LAP,            <"Phar Lap 386/DOS-Extender">
   @MKPS ERRMSG_DOS4GW,              <"Rational Systems DOS/4GW or DOS/16M">
   @MKPS ERRMSG_DOSX,                <"DOSX (DOS Extender)">
   @MKPS ERRMSG_DPMI,                <"DPMI 16 or 32">
   @MKPS ERRMSG_PM_EM,               <34, " !", TCR, "Please remove it, and try again...", TCR>

   @MKPS ERRMSG_XMS_NOT_INSTALLED,   <"XMS driver is not present !", TCR>
   @MKPS ERRMSG_XMS_BAD_VERSION,     <"XMS driver V2.0 or greater is needed !", TCR>
   @MKPS ERRMSG_XMS_BAD_A20,         <"A20 gate can not be enabled !", TCR>

   @MKPS ERRMSG_Not_Enough_Free_XMS, <TCR, "Not enough free XMS ! ", XMS_TO_ALLOC_STR, "KB needed...", TCR>
   @MKPS ERRMSG_XMS_Check_Error,     <"XMS checking error !", TCR>
   
   @MKPS INFOMSG_Writing_To_XMS,     <TCR, "Writing ", XMS_TO_ALLOC_STR, "KB to XMS.", TCR>
   @MKPS INFOMSG_Checking_XMS,       <"Checking the written data...", TCR>
   @MKPS INFOMSG_XMS_Check_NO_Error, <"XMS Checking successful !", TCR>

═══════════════════════════════════════════════════════════════════════════════

CODESEG
ASSUME CS:@code, DS:@data

PROC  Disp_PS NEAR USES AX BX CX DX
      ARG PS:NEAR PTR BYTE

   Mov   AH, 40h
   Mov   CH, 0
   Mov   BX, [PS]
   Mov   CL, [BX]
   Inc   BX
   Mov   DX, BX
   Mov   BX, 1
   INT   21h
   RET
ENDP

───────────────────────────────────────────────────────────────────────────────
STARTUPCODE
   CALL  FRMI_START
   JNC   @@In_FRM

   Cmp   AH, CPU_80386
   JAE   @@CPU_Type_OK

   CALL  Disp_PS, OFFSET ERRMSG_Bad_CPU
   @DOS_EXIT 1

@@CPU_Type_OK:
   Cmp   AL, PM_V86
   JNE   @@Test_DPMS

   CALL  Disp_PS, OFFSET ERRMSG_V86
   @DOS_EXIT 1

@@Test_DPMS:
   CALL  Disp_PS, OFFSET ERRMSG_PM

   Cmp   AL, PM_DPMS
   JNE   @@Test_PHAR_LAP

   CALL  Disp_PS, OFFSET ERRMSG_DPMS
   JMP   @@Disp_End_Msg

@@Test_PHAR_LAP:
   Cmp   AL, PM_PHAR_LAP
   JNE   @@Test_DOS4GW

   CALL  Disp_PS, OFFSET ERRMSG_PHAR_LAP
   JMP   @@Disp_End_Msg

@@Test_DOS4GW:
   Cmp   AL, PM_DOS4GW
   JNE   @@Test_DOSX

   CALL  Disp_PS, OFFSET ERRMSG_DOS4GW
   JMP   @@Disp_End_Msg

@@Test_DOSX:
   Cmp   AL, PM_DOSX
   JNE   @@DPMI

   CALL  Disp_PS, OFFSET ERRMSG_DOSX
   JMP   @@Disp_End_Msg

@@DPMI:
   CALL  Disp_PS, OFFSET ERRMSG_DPMI
   
@@Disp_End_Msg:
   CALL  Disp_PS, OFFSET ERRMSG_PM_EM
   @DOS_EXIT  1
   
───────────────────────────────────────────────────────────────────────────────
@@In_FRM:
   CALL  XMS_INIT
   JNC   @@XMS_Init_OK
   
   Cmp   AL, XMS_NOT_INSTALLED
   JNE   @@Test_XMS_BAD_VERSION
   
   CALL  Disp_PS, OFFSET ERRMSG_XMS_NOT_INSTALLED
   @DOS_EXIT  1

@@Test_XMS_BAD_VERSION:
   Cmp   AL, XMS_BAD_VERSION
   JNE   @@XMS_BAD_A20

   CALL  Disp_PS, OFFSET ERRMSG_XMS_BAD_VERSION
   @DOS_EXIT  1

@@XMS_BAD_A20:
   CALL  Disp_PS, OFFSET ERRMSG_XMS_BAD_A20
   @DOS_EXIT  1

───────────────────────────────────────────────────────────────────────────────
@@XMS_Init_OK:
   CALL  XMS_QUERY_FREE

   Cmp   AX, XMS_TO_ALLOC
   JAE   @@Enough_Free_XMS
   
   CALL  Disp_PS, OFFSET ERRMSG_Not_Enough_Free_XMS
   @DOS_EXIT  1

───────────────────────────────────────────────────────────────────────────────
@@Enough_Free_XMS:
   CALL  XMS_ALLOC, XMS_TO_ALLOC
   Mov   [XMS_Handle], AX

   CALL  XMS_LOCK, [XMS_Handle]
   Mov   [XMS_Address], EAX

   CALL  Disp_PS, OFFSET INFOMSG_Writing_To_XMS

   Xor   EDI, EDI                  ; Part to fill the XMS block
   Mov   EBX, [XMS_Address]
@@XMS_Fill_Loop:
   Mov   [DWORD PTR FS:EBX+EDI], 12345678h
   Add   EDI, 4
   Cmp   EDI, XMS_TO_ALLOC*1024
   JB    @@XMS_Fill_Loop

   CALL  Disp_PS, OFFSET INFOMSG_Checking_XMS

   Xor   EDI, EDI                  ; Part to check the filled XMS block
   Mov   EBX, [XMS_Address]
@@XMS_Check_Loop:
   Cmp   [DWORD PTR FS:EBX+EDI], 12345678h
   JNE   @@XMS_Check_Error
   Add   EDI, 4
   Cmp   EDI, XMS_TO_ALLOC*1024
   JB    @@XMS_Check_Loop
   JMP   @@XMS_Check_NO_ERROR

───────────────────────────────────────────────────────────────────────────────
@@XMS_Check_Error:
   CALL  Disp_PS, OFFSET ERRMSG_XMS_Check_Error
   JMP   @@XMS_Clean

───────────────────────────────────────────────────────────────────────────────
@@XMS_Check_NO_ERROR:
   CALL  Disp_PS, OFFSET INFOMSG_XMS_Check_NO_Error

   Mov   AX, 0B800h                ; FS can be used as a standard segment reg
   Mov   FS, AX
   Mov   [DWORD FS:2*80], 0CF4BBF4Fh

───────────────────────────────────────────────────────────────────────────────   
@@XMS_Clean:
   CALL  XMS_UNLOCK, [XMS_Handle]
   CALL  XMS_FREE, [XMS_Handle]

   @DOS_EXIT 0

END
[ RETURN TO DIRECTORY ]