home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / ins_msb / 9202 / ems.bas < prev    next >
BASIC Source File  |  1991-12-19  |  9KB  |  335 lines

  1. ' EMS.Bas - Demonstrate using LIM EMS v3.2 expanded memory
  2.  
  3. 'If you use the PDS product, change the next line to include
  4. 'the QBX.BI include file instead of the QB.BI file
  5.  
  6. '$INCLUDE: 'QB.BI'
  7.  
  8. DECLARE SUB CallEmm (EmmFuncNbr%)
  9. DECLARE FUNCTION EmmDriverExists2% ()
  10. DECLARE FUNCTION EmmDriverExists1% ()
  11. DECLARE SUB EmmPrintStatus (Status%)
  12. DECLARE FUNCTION FmtPointer$ (P AS ANY)
  13. DECLARE FUNCTION Hi% (Operand%)
  14. DECLARE FUNCTION Lo% (Operand%)
  15.  
  16. DEFINT A-Z
  17.  
  18. CONST EmsInt = &H67         'EMS interrupt number
  19. CONST IoCtlFunc = &H44      'IOCtl DOS Function number
  20. CONST PageLen = 16384       'Length of memory page
  21. CONST MsgLen = 16           'Message length
  22. CONST MsgsPerPage = PageLen \ MsgLen
  23. CONST NumMsgs = 5000
  24.  
  25. '*** Emm functions ***
  26.  
  27. CONST GetStatus = &H40
  28. CONST GetPageFrameAddr = &H41
  29. CONST GetUnallocPages = &H42
  30. CONST GetEmmVersion = &H46
  31. CONST AllocatePages = &H43
  32. CONST MapHandlePage = &H44
  33. CONST DeallocatePages = &H45
  34.  
  35. CLS
  36.  
  37. TYPE address
  38.   Segment AS LONG
  39.   Offset AS LONG
  40. END TYPE
  41.  
  42. DIM P0 AS address             'Pointer to physical page 1
  43. DIM P1 AS address             'Pointer to physical page 2
  44. DIM P2 AS address             'Pointer to physical page 3
  45. DIM P3 AS address             'Pointer to physical page 4
  46. DIM MsgBuf AS address         'Pointer into mapped memory
  47. DIM Buff AS STRING * 16       'Buffer for message to store in EM
  48. DIM I AS INTEGER              'Dummy variable
  49. DIM SHARED EmmRegs AS RegType 'Registers for interrupt calls
  50. DIM Page AS LONG              'Page frame address
  51. DIM Index AS LONG             'Index into page frame
  52. DIM StrNum AS STRING * 6      'Holds record # for EMM msg
  53.  
  54. 'Test for the existence of the EMM driver
  55. 'You can choose from 1 of 2 methods
  56.  
  57. 'IF EmmDriverExists1% THEN         'Method 1
  58. IF EmmDriverExists2% THEN          'Method 2
  59.   PRINT "EMM driver exists"
  60. ELSE
  61.   PRINT "No EMM driver detected."
  62. END IF
  63.  
  64. 'Print the current status of the EMM driver
  65.  
  66. PRINT "Checking EMM status"
  67. CALL CallEmm(GetStatus)
  68. PRINT "EMM status ok"
  69.  
  70. 'Print the version number of the EMM driver
  71.  
  72. CALL CallEmm(GetEmmVersion)
  73.  
  74. PRINT "EMS driver version = ";
  75.  
  76. AL% = Lo%(EmmRegs.ax)
  77. MajorVersion = AL% \ 16
  78. MinorVersion = AL% AND &HF
  79. PRINT USING "!."; RIGHT$(STR$(MajorVersion), 1);
  80. PRINT USING "!"; RIGHT$(STR$(MinorVersion), 1)
  81.  
  82. IF AL% < &H32 THEN
  83.   PRINT "Error - EMM version is earlier than 3.2"
  84.   SYSTEM
  85. END IF
  86.  
  87. '***** Print the page frame & physical window addresses *****
  88.  
  89. CALL CallEmm(GetPageFrameAddr)
  90.  
  91. P0.Segment = EmmRegs.bx   'Window 0 -> P0 = BX:0000
  92. P1.Segment = EmmRegs.bx   'Window 1 -> P1 = BX:4000
  93. P2.Segment = EmmRegs.bx   'Window 2 -> P2 = BX:8000
  94. P3.Segment = EmmRegs.bx   'Window 3 -> P3 = BX:C000
  95. P0.Offset = &H0
  96. P1.Offset = &H4000
  97. P2.Offset = &H8000
  98. P3.Offset = &HC000
  99.  
  100. PRINT "Page frame segment address = "; HEX$(EmmRegs.bx)
  101. PRINT "Physical page 0 address = "; FmtPointer$(P0)
  102. PRINT "Physical page 1 address = "; FmtPointer$(P1)
  103. PRINT "Physical page 2 address = "; FmtPointer$(P2)
  104. PRINT "Physical page 3 address = "; FmtPointer$(P3)
  105.  
  106. '***** Print # of unallocated pages and total # of pages *****
  107.  
  108. CALL CallEmm(GetUnallocPages)
  109. PRINT "Total EMS pages = "; EmmRegs.dx
  110. PRINT "Unused EMS pages = "; EmmRegs.bx
  111.  
  112. '***** Allocate some pages of expanded memory *****
  113.  
  114. EmmRegs.bx = (NumMsgs + MsgsPerPage) \ MsgsPerPage
  115. CALL CallEmm(AllocatePages)
  116. PRINT "Allocated "; EmmRegs.bx; " pages to handle #"; EmmRegs.dx
  117. EmmHandle = EmmRegs.dx
  118.  
  119. '***** Load EMS RAM with data *****
  120.  
  121. MsgBuf = P0
  122. PRINT "Storing messages into extended memory page frame"
  123. LastPageNbr = -1
  124. FOR I = 0 TO NumMsgs - 1
  125.   LOCATE 14, 50: PRINT USING "#,###"; I
  126.   StrNum = STR$(I)
  127.   Buff = " EMS msg #" + StrNum
  128.   Page = I \ MsgsPerPage
  129.   Index = I MOD MsgsPerPage
  130.   MsgBuf.Offset = Index * LEN(Buff)
  131.  
  132.   '***** Map indicated logical page into physical page 0 ****
  133.  
  134.   IF Page <> LastPageNbr THEN
  135.     AH = MapHandlePage
  136.     AL = 0
  137.     EmmRegs.ax = AH * 256 + AL  'Map EMS page & Physical page 0
  138.     EmmRegs.bx = Page
  139.     EmmRegs.dx = EmmHandle                      'EMM RAM handle
  140.     CALL INTERRUPT(EmsInt, EmmRegs, EmmRegs)
  141.     LastPageNbr = Page
  142.   END IF
  143.  
  144.   AH = Hi%(EmmRegs.ax)
  145.   IF AH = 0 THEN
  146.  
  147.     ' Set message into memory
  148.  
  149.     DEF SEG = MsgBuf.Segment
  150.     FOR J = 0 TO MsgLen - 1
  151.       POKE MsgBuf.Offset + J, ASC(MID$(Buff, J + 1, 1))
  152.     NEXT J
  153.     DEF SEG
  154.  
  155.   ELSE
  156.     CALL EmmPrintStatus(AH)
  157.     EXIT FOR
  158.   END IF
  159. NEXT I
  160.  
  161. PRINT
  162.  
  163. 'Allow user to access any message in the buffer
  164.  
  165. I = &HFF
  166.  
  167. WHILE I <> -1
  168.   INPUT "Enter message # to retrieve, or -1 to quit: "; I
  169.   IF (I >= 0) AND (I < NumMsgs) THEN
  170.  
  171.     MsgBuf = P3
  172.     Page = I \ MsgsPerPage
  173.     Index = I MOD MsgsPerPage
  174.     
  175. '***** Map indicated page into physical page 3 *****
  176.  
  177.     AH = MapHandlePage                 'Map EMM page
  178.     AL = 3                             ' using physical page 3
  179.     EmmRegs.ax = AH * 256 + AL
  180.     EmmRegs.bx = Page                  'Logical page number
  181.     EmmRegs.dx = EmmHandle             'EMM RAM handle
  182.  
  183.     CALL INTERRUPT(EmsInt, EmmRegs, EmmRegs)
  184.     AH = Hi%(EmmRegs.ax)
  185.     IF AH = 0 THEN
  186.       MsgBuf.Offset = MsgBuf.Offset + Index * LEN(Buff)
  187.  
  188.       'Move the bytes from memory to a local variable
  189.  
  190.       DEF SEG = MsgBuf.Segment
  191.       FOR J = 0 TO MsgLen - 1
  192.         MID$(Buff, J + 1, 1) = CHR$(PEEK(MsgBuf.Offset + J))
  193.       NEXT J
  194.       DEF SEG
  195.  
  196.       PRINT "Retrieved message -> "; Buff;
  197.       PRINT " from page #"; Page; " Index"; Index
  198.     ELSE
  199.       CALL EmmPrintStatus(AH)
  200.       I = -1
  201.     END IF
  202.   END IF
  203.  
  204. WEND
  205.  
  206. '***** Free the EMS RAM back to the EMM driver *****
  207.  
  208. EmmRegs.dx = EmmHandle
  209. CALL CallEmm(DeallocatePages)
  210. PRINT "Released all memory for handle "; EmmRegs.dx
  211. END
  212.  
  213. 'Error handling routine
  214.  
  215. oops:
  216.   SELECT CASE ERR
  217.     CASE 53   'File/device not found.
  218.       PRINT "No EMM driver found"
  219.       SYSTEM
  220.     CASE ELSE
  221.       PRINT "Unknown error #"; ERR
  222.       SYSTEM
  223.   END SELECT
  224.  
  225. SUB CallEmm (EmmFuncNbr)
  226.  
  227.   EmmRegs.ax = EmmFuncNbr * 256
  228.   CALL INTERRUPT(EmsInt, EmmRegs, EmmRegs)
  229.   AH = Hi%(EmmRegs.ax)
  230.   IF AH <> 0 THEN
  231.     CALL EmmPrintStatus(AH)
  232.     SYSTEM
  233.   END IF
  234.  
  235. END SUB
  236.  
  237. FUNCTION EmmDriverExists1%
  238.  
  239. DIM EmsDriver AS address
  240. DIM EmsIdString AS STRING * 8
  241.  
  242. EmmDriverExists1% = 0                   'False
  243. DEF SEG = 0
  244. VectorAddr = &H67 * 4
  245. EmsDriver.Segment = PEEK(VectorAddr + 3) * 256& + _
  246.                     PEEK(VectorAddr + 2)
  247.  
  248. IF EmsDriver.Segment <> 0 THEN
  249.   DEF SEG = EmsDriver.Segment
  250.   EmsDriver.Offset = 10
  251.   FOR I = 0 TO 7
  252.    MID$(EmsIdString, I + 1, 1) = CHR$(PEEK(EmsDriver.Offset + I))
  253.   NEXT I
  254.   IF EmsIdString = "EMMXXXX0" THEN
  255.    EmmDriverExists1% = -1
  256.   END IF
  257. END IF
  258. DEF SEG
  259.  
  260. END FUNCTION
  261.  
  262. FUNCTION EmmDriverExists2%
  263.  
  264. DIM EmmHandle AS INTEGER      'Handle for EMM allocated pages
  265.  
  266. ON ERROR GOTO oops
  267.   EmmDriverExists2% = -1      'Set default return value to TRUE
  268.   OPEN "I", 1, "EMMXXXX0"
  269.  
  270.   EmmRegs.ax = IoCtlFunc * 256&           'Call IOCtl Function
  271.   EmmRegs.bx = FILEATTR(1, 2)             'Set DOS file handle#
  272.   CALL INTERRUPT(&H21, EmmRegs, EmmRegs)  'Call DOS
  273.   CLOSE 1
  274.   IF (EmmRegs.flags AND 1) = 0 THEN       'Call successfull
  275.    IF (EmmRegs.dx AND &H80) = &H80 THEN  'Handle is for a dev
  276.     PRINT "Handle refers to a device"
  277.    ELSE
  278.     PRINT "Handle refers to a file"
  279.     PRINT "Unable to contact EMM driver if present"
  280.     SYSTEM
  281.    END IF
  282.   ELSE 'Call unsuccessfull
  283.    SELECT CASE EmmRegs.ax
  284.     CASE 1: PRINT "Invalid IOCtl subfunction"
  285.     CASE 5: PRINT "Access to IOCTL denied"
  286.     CASE 6: PRINT "Invalid handle"
  287.     CASE ELSE
  288.       PRINT "Unknown error # "; EmmRegs.ax
  289.    END SELECT
  290.    PRINT "Unable to contact EMM driver"
  291.    SYSTEM
  292.   END IF
  293.   EXIT FUNCTION
  294.  
  295. END FUNCTION
  296.  
  297. SUB EmmPrintStatus (Status%)
  298.   SELECT CASE Status%
  299.     CASE &H0: S$ = "Status ok"
  300.     CASE &H80: S$ = "Driver malfunction"
  301.     CASE &H81: S$ = "Hardware malfunction"
  302.     CASE &H83: S$ = "Bad Handle"
  303.     CASE &H84: S$ = "Undefined function"
  304.     CASE &H85: S$ = "No free handles"
  305.     CASE &H86: S$ = "Page map context error"
  306.     CASE &H87: S$ = "Insufficient memory pages"
  307.     CASE &H88: S$ = "Not enough free pages"
  308.     CASE &H89: S$ = "Can't allocate zero pages"
  309.     CASE &H8A: S$ = "Logical page out of range"
  310.     CASE &H8B: S$ = "Physical page out of range"
  311.     CASE &H8C: S$ = "Page map hardware RAM full"
  312.     CASE &H8D: S$ = "Page map already has a handle"
  313.     CASE &H8E: S$ = "Page map not mapped to handle"
  314.     CASE &H8F: S$ = "Undefined subfunction number"
  315.     CASE ELSE
  316.       S$ = "Unknown status number $" + HEX$(Status%)
  317.   END SELECT
  318.   PRINT "EMM: " + S$
  319. END SUB
  320.  
  321. FUNCTION FmtPointer$ (P AS address)
  322.   F$ = "$" + RIGHT$(HEX$(P.Segment), 4)
  323.   F$ = F$ + ":$" + RIGHT$(HEX$(P.Offset), 4)
  324.   FmtPointer$ = F$
  325. END FUNCTION
  326.  
  327. FUNCTION Hi% (Operand%)
  328.   Hi% = Operand% \ 256
  329. END FUNCTION
  330.  
  331. FUNCTION Lo% (Operand%)
  332.   Lo% = Operand% MOD 256
  333. END FUNCTION
  334.  
  335.