jduarte@BONNIE.ICS.UCI.EDU (04/10/90)
Hi 'Netters!! I was wondering if any of you know how to "put" characters into the character queue for DOS-based machines...I'm trying to write a program that will put these characters in the keyboard buffer. I have tried the Interrupt #16 I believe with #5 or something like that, but my machine refuses to recognize 'em. Any help??? Thanks, Jose D. P.S. - I am using TP5.0 w/DOS 3.1 on a clone.
indridi@rhi.hi.is (Indridi Bjornsson) (04/11/90)
In article <9004091113.aa22797@BONNIE.ICS.UCI.EDU> jduate@BONNIE.ICS.UCI.EDU writes: >Hi 'Netters!! >I was wondering if any of you know how to "put" characters into the >character queue for DOS-based machines...I'm trying to write a >program that will put these characters in the keyboard buffer. >I have tried the Interrupt #16 I believe with #5 or something like that, >but my machine refuses to recognize 'em. Any help??? YES ! you are right about INT 16h (AH=5h), it is Keyboard Write, but it doesn't work with all machines. It only works on limited numbers if XT's, but for most AT's and 386's. In IBM Technical Reference is stated that the Keyboard Write interrupt is supported in: AT BIOS dated 11/15/85 and after XT BIOS dated 01/10/86 and after PC XT Model 286 and ofcourse PS/2 So, if you have a BIOS that doesn't support the Keyboard Write you just have to do it yourself. The keyboard buffer is implemented as circular queue, standard 32 bytes of length (When I say standard I mean there are some program that change it), and is located in [$0040:$001E]. Each character in the buffer take one Word, one char for itself and one for the scan code (exept when it is a function key). In the BIOS working area are also two pointers: Keyboard Buffer Head Pointer (located at [$0040:$001A]) Keyboard Buffer Tail Pointer (located at [$0040:$001C]). You have also two other locations in the Bios that store information about the keyboard buffer, they are: Keyboard Buffer Start Offset Pointer (at [$0040:$0080]) Keyboard Buffer End Offset Pointer (at [$0040:$0080]) they usualy contain $1e=30 and $3e=62 which are at the beginning and the end of the buffer. The Tail pointer points at next avaliable location in the buffer but the Head pointer points at the next key to read. H e l l o W o r l d ^ ^ Head Tail If Head=Tail then the buffer is empty. So to put a key in the buffer you have to: - check to see if the buffer is full (Head-Tail) > 2 (BE AWARE: It's a circular queue) - put the char and the scan code, at the location where the Head is pointing to. - Advance the Head to the next position. Here is a litle Demo I wrote in TP: --cut here -- cut here -- PROGRAM KeyboardDemo; USES Dos,CRT; VAR BufferStart:WORD ABSOLUTE $0040:$0080; BufferEnd :WORD ABSOLUTE $0040:$0082; BufferHead :WORD ABSOLUTE $0040:$001A; BufferTail :WORD ABSOLUTE $0040:$001C; Buffer :Array[0..$3D] OF Char ABSOLUTE $0040:$0000; { BufferHead/Tail contain the offset in segment $0040 so we just let the Buffer begin at $0040:$0000 } Shift_Status: Byte Absolute $0000:$0417; FUNCTION KBPDec(HH:Word):Word; BEGIN HH:=HH-2; IF (HH=BufferStart) THEN HH:=BufferEnd; KBPDec:=HH; END; FUNCTION KBPInc(HH:Word):Word; BEGIN HH:=HH+2; IF (HH=BufferEnd) THEN HH:=BufferStart; KBPInc:=HH; END; PROCEDURE ClrKBBuffer; BEGIN BufferHead:=BufferTail; Shift_Status:=0; { Clear the SHIFT Status to } END; FUNCTION KBFull:Boolean; VAR temp:Word; BEGIN temp:=KBPInc(BufferTail); KBFull:=(temp=BufferHead); END; FUNCTION KBEmpty:Boolean; VAR temp:Word; BEGIN KBEmpty:=(BufferHead=BufferTail); END; PROCEDURE KBWrite(Key,Scan:Char); BEGIN Buffer[BufferTail]:=Key; Buffer[BufferTail+1]:=Scan; BufferTail:=KBPInc(BufferTail); END; VAR temp : Integer; STR : String; BEGIN ClrScr; STR:='Hello world here I come'; FOR temp:=1 TO Length(STR) DO IF Not(KBFull) THEN BEGIN { If they buffer isn't full so we can write into it } KBWrite(STR[temp],' '); END; Write('Here is the contenent of the Buffer : '); ReadLn(STR); END. --cut here -- cut here -- This is a bit "Brute force" way for implementing Keyboard Write 'cause it can conflict with the "real" one (INT 9h). But on most occasion it will work. You could also fiddle with the DOS template (INT 21h AH=0Ah & AH=0Ch), but that's another story. Hope this will help :-) -- Indridi Bjornsson Ljosheimum 18A, 4h. Internet: indridi@rhi.hi.is 104 Reykjavik. UUCP: ..!mcvax!hafro!rhi!indridi ICELAND University of Iceland. ------------------------------------------------------------------------------
n257cl@tamunix.tamu.edu (Sean Malloy) (04/13/90)
AHEM Interrupt #16 is actually interrupt 16h (decimal 22)... Although PASCAL may seem to operate in base 10 (decimal) your machine works best with numbers which are base 2 or base 16 (hexadecimal). Hope this helps. -Sean