123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- { This program demonstrates the usage of DOS real mode memory by
- executing a software interrupt which needs a buffer to store data
- into. Because these interrupts are real mode funcs, the buffer must
- be located in real mode memory space (first MB of memory). Such
- memory can only be allocated by the global_dos_alloc() and
- global_dos_free() functions of the GO32 unit.
- In more detail this program tries to detect a VESA 2.0 BIOS
- extension of your graphics card and outputs its version.
- Here's the necessary interrupt call description:
- Int 10h 4f00h : VESA BIOS extension installation check
- Input : AX = 4F00h
- ES:DI = pointer to 512 byte information buffer
- Output : AX = 004Fh if successful
- ES:DI = pointer to filled buffer
- Buffer structure : (relevant to this example)
- must be 'VESA' in the first 4 chars of the buffer to be
- valid VBE version in the next word
- Note : to request VBE 2.0 information, the first 4 bytes of the
- buffer must contain 'VBE2' prior to the interrupt call.
- (this makes the problem a bit tougher; we first have to copy the
- buffer with the 'VBE2' id to dos memory...)
- }
- uses
- go32;
- {The following 2 functions are wrappers to the GO32
- global_dos_alloc() and global_dos_free() functions to simplify their
- usage }
- { Function : dosalloc }
- { Input : size of a real mode location }
- { Output : selector and segment of a real mode location }
- procedure dosalloc(var selector : word;
- var segment : word; size : longint);
- var
- res : longint;
- begin
- { try to allocate real mode memory }
- res := global_dos_alloc(size);
- { the lower 16 bits of the result contain the selector to the
- allocated memory block }
- selector := word(res);
- { the upper 16 bits contain the real mode segment address of
- this block; the offset is always 0, so we don't need to return
- this }
- segment := word(res shr 16);
- end;
- { Function : dosfree }
- { Input : selector of a real mode block }
- { Output : none }
- { Description : de-allocates a previously allocated real mode
- memory}
- procedure dosfree(selector : word);
- begin
- { call the GO32 function with the selector }
- global_dos_free(selector);
- end;
- type
- VBEInfoBuf = packed record
- { contains 'VESA' if successful }
- Signature : array[0..3] of char;
- Version : Word;
- { pad to 512 bytes length }
- reserved : array[0..505] of byte;
- end;
- var
- { selector to our real mode buffer }
- selector,
- { real mode segment address of buffer }
- segment : Word;
- { register structure to issue a software interrupt }
- r : trealregs;
- infobuf : VBEInfoBuf;
- begin
- { first we reset the registers and infobuf variable }
- fillchar(r, sizeof(r), 0);
- fillchar(infobuf, sizeof(VBEInfoBuf), 0);
- { allocate real mode memory }
- dosalloc(selector, segment, sizeof(VBEInfoBuf));
- { check if an error occured during allocation }
- if (int31error<>0) then begin
- Writeln('Error while allocating real mode memory, halting');
- halt;
- end;
- { request VBE 2.0 information, fill out information buffer }
- infobuf.Signature := 'VBE2';
- { copy buffer to the allocated real mode memory }
- dosmemput(segment, 0, infobuf, sizeof(infobuf));
- { issue the interrupt; remember : DI = 0 }
- r.ax := $4f00; r.es := segment;
- realintr($10, r);
- { copy buffer to our infobuf variable again }
- dosmemget(segment, 0, infobuf, sizeof(infobuf));
- { free allocated real mode memory, because we don't need it
- anymore }
- dosfree(selector);
- { check if interrupt call was successful }
- if (r.ax <> $4f) then begin
- { write message and exit, because the infobuf doesn't contain
- any useful data we could tell the user }
- Writeln('VBE BIOS extension not available, function call ',
- 'failed');
- halt;
- end;
- { check if buffer is valid }
- if (infobuf.signature[0] = 'V') and
- (infobuf.signature[1] = 'E') and
- (infobuf.signature[2] = 'S') and
- (infobuf.signature[3] = 'A') then begin
- Writeln('VBE version ', hi(infobuf.version), '.',
- lo(infobuf.version), ' detected');
- end;
- end.
|