2
0

buffer.pas 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. { This program demonstrates the usage of DOS real mode memory by
  2. executing a software interrupt which needs a buffer to store data
  3. into. Because these interrupts are real mode funcs, the buffer must
  4. be located in real mode memory space (first MB of memory). Such
  5. memory can only be allocated by the global_dos_alloc() and
  6. global_dos_free() functions of the GO32 unit.
  7. In more detail this program tries to detect a VESA 2.0 BIOS
  8. extension of your graphics card and outputs its version.
  9. Here's the necessary interrupt call description:
  10. Int 10h 4f00h : VESA BIOS extension installation check
  11. Input : AX = 4F00h
  12. ES:DI = pointer to 512 byte information buffer
  13. Output : AX = 004Fh if successful
  14. ES:DI = pointer to filled buffer
  15. Buffer structure : (relevant to this example)
  16. must be 'VESA' in the first 4 chars of the buffer to be
  17. valid VBE version in the next word
  18. Note : to request VBE 2.0 information, the first 4 bytes of the
  19. buffer must contain 'VBE2' prior to the interrupt call.
  20. (this makes the problem a bit tougher; we first have to copy the
  21. buffer with the 'VBE2' id to dos memory...)
  22. }
  23. uses
  24. go32;
  25. {The following 2 functions are wrappers to the GO32
  26. global_dos_alloc() and global_dos_free() functions to simplify their
  27. usage }
  28. { Function : dosalloc }
  29. { Input : size of a real mode location }
  30. { Output : selector and segment of a real mode location }
  31. procedure dosalloc(var selector : word;
  32. var segment : word; size : longint);
  33. var
  34. res : longint;
  35. begin
  36. { try to allocate real mode memory }
  37. res := global_dos_alloc(size);
  38. { the lower 16 bits of the result contain the selector to the
  39. allocated memory block }
  40. selector := word(res);
  41. { the upper 16 bits contain the real mode segment address of
  42. this block; the offset is always 0, so we don't need to return
  43. this }
  44. segment := word(res shr 16);
  45. end;
  46. { Function : dosfree }
  47. { Input : selector of a real mode block }
  48. { Output : none }
  49. { Description : de-allocates a previously allocated real mode
  50. memory}
  51. procedure dosfree(selector : word);
  52. begin
  53. { call the GO32 function with the selector }
  54. global_dos_free(selector);
  55. end;
  56. type
  57. VBEInfoBuf = packed record
  58. { contains 'VESA' if successful }
  59. Signature : array[0..3] of char;
  60. Version : Word;
  61. { pad to 512 bytes length }
  62. reserved : array[0..505] of byte;
  63. end;
  64. var
  65. { selector to our real mode buffer }
  66. selector,
  67. { real mode segment address of buffer }
  68. segment : Word;
  69. { register structure to issue a software interrupt }
  70. r : trealregs;
  71. infobuf : VBEInfoBuf;
  72. begin
  73. { first we reset the registers and infobuf variable }
  74. fillchar(r, sizeof(r), 0);
  75. fillchar(infobuf, sizeof(VBEInfoBuf), 0);
  76. { allocate real mode memory }
  77. dosalloc(selector, segment, sizeof(VBEInfoBuf));
  78. { check if an error occured during allocation }
  79. if (int31error<>0) then begin
  80. Writeln('Error while allocating real mode memory, halting');
  81. halt;
  82. end;
  83. { request VBE 2.0 information, fill out information buffer }
  84. infobuf.Signature := 'VBE2';
  85. { copy buffer to the allocated real mode memory }
  86. dosmemput(segment, 0, infobuf, sizeof(infobuf));
  87. { issue the interrupt; remember : DI = 0 }
  88. r.ax := $4f00; r.es := segment;
  89. realintr($10, r);
  90. { copy buffer to our infobuf variable again }
  91. dosmemget(segment, 0, infobuf, sizeof(infobuf));
  92. { free allocated real mode memory, because we don't need it
  93. anymore }
  94. dosfree(selector);
  95. { check if interrupt call was successful }
  96. if (r.ax <> $4f) then begin
  97. { write message and exit, because the infobuf doesn't contain
  98. any useful data we could tell the user }
  99. Writeln('VBE BIOS extension not available, function call ',
  100. 'failed');
  101. halt;
  102. end;
  103. { check if buffer is valid }
  104. if (infobuf.signature[0] = 'V') and
  105. (infobuf.signature[1] = 'E') and
  106. (infobuf.signature[2] = 'S') and
  107. (infobuf.signature[3] = 'A') then begin
  108. Writeln('VBE version ', hi(infobuf.version), '.',
  109. lo(infobuf.version), ' detected');
  110. end;
  111. end.