Ctrl+Up / Ctrl+Down

Programming, for all ages and all languages.
Post Reply
asmfreak
Posts: 6
Joined: Wed Jan 02, 2008 11:41 am

Ctrl+Up / Ctrl+Down

Post by asmfreak »

I am writing a Turbo Vision Program and would like to use the Ctrl+Up / Ctrl+Down key combinations. Turbo Vision uses the "non-extended" functions 00h and 01h of int 16h to read keystrokes, which unfortunately don't support these combinations. This is strange because Ctrl+Left and Ctrl+Right ARE supported. I could rewrite TProgram.GetEvent to use the "extended" functions 10h and 11h, but these functions are not supported on every computer. I have thought about writing my own INT 9 handler to make sure these combinations are stored in the keyboard buffer, and modifying functions 00h and 01h of int 16h to return these combinations. Do you think this would solve the problem ? Or don't old (PC/XT) keyboards support this combination anyway ?
User avatar
Telgin
Member
Member
Posts: 72
Joined: Thu Dec 20, 2007 1:45 pm

Post by Telgin »

Sorry if this is completely wrong / jibberish, but I think it's all based on the keyboard controller, not the keyboard. From what I read, OSes have to interpret shift / ctrl / alt keys being down while another his hit is by just intercepting the shift / ctrl / alt event, and remembering it until it is released.

So, in short, I'd say that rewriting whatever part of the code that is responsible for intercepting key strokes would probably allow you to add this functionality.
asmfreak
Posts: 6
Joined: Wed Jan 02, 2008 11:41 am

Post by asmfreak »

Thank you for your response.
Telgin wrote:Sorry if this is completely wrong / jibberish, but I think it's all based on the keyboard controller, not the keyboard. From what I read, OSes have to interpret shift / ctrl / alt keys being down while another his hit is by just intercepting the shift / ctrl / alt event, and remembering it until it is released.
Yes, this is true for most keys, but with some keys (e.g. SysReq / Pause), the data actually sent by the keyboard changes if Ctrl / Alt / Shift are pressed simultaneously. And I just thougt there might be some reason why Ctrl-Left / Ctrl-Right ARE supported by old BIOSes, while Ctrl-Up / Ctrl-Down are NOT.
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: Ctrl+Up / Ctrl+Down

Post by jal »

asmfreak wrote:This is strange because Ctrl+Left and Ctrl+Right ARE supported.
Strange as it is, that's how the first IBM PC BIOS did it, so all BIOSes to follow also do it.
I could rewrite TProgram.GetEvent to use the "extended" functions 10h and 11h, but these functions are not supported on every computer.
True, most XT BIOSes won't have it, but AT and up do. So there's absolutely no need to not use function 10h, unless you're aiming at PC/XT compatability. If you want to support PC/XT, then write your own INT9 handler. It's rather easy, but you need a translation table from scancodes -> ASCII, and from ctrl/shift/alt+key to 'scancode'. See e.g. here for a complete list.


JAL
asmfreak
Posts: 6
Joined: Wed Jan 02, 2008 11:41 am

Post by asmfreak »

There are several reasons why I am not so sure if writing my own INT 9 handler is really a good idea:

(1) The INT 9 handler defines the relationship between scancodes and ASCII characters (i.e. the "keyboard layout") and is therefore language-dependend. In most cases, INT 9 is probably serviced by the BIOS or KEYB.COM, and I want to keep the settings the user has chosen in the BIOS setup or specified on KEYB.COM's command line rather than always using the standard US keyboard layout. The only way to keep these settings would be to process only Ctrl-Up / Ctrl-Down myself and to forward any other key combinations to the previously installed handler. But that's exactly where the real trouble starts: While it is rather easy to "chain" to a software interrupt handler (you just have to call it with the same register values "your" handler was called with), a hardware interrupt handler is reading the data it is working with from external ports rather than from CPU registers, so when the previously installed handler is called, the state of the hardware should be just as it was when "my" handler was called. As "my" handler will already have read the scancode from port 60h (to determine if it identifies the Up or Down key), the state of the hardware won't be the same. I am not sure if reading port 60h a second time is guaranteed to return the same value. In any case, the "Output Buffer Full" bit in the keyboard controller's status register (port 64h) will return to 0 after the first read of port 60h, and this may confuse the previously installed handler. If it waits for this bit to be 1 before reading port 60h, the system will be hung.

(2) I have very little information on the old PC/XT keyboards. Wouldn't it be possible, that old BIOSes didn't support these combinations because some of these old keyboards couldn't handle them correctly ?

(3) I am currently disassembling the standard INT 9 handler provided by my BIOS. Believe me: It is not that easy.

P.S.: I am working with a German keyboard and know US keyboards only from photos I have seen on the internet. Do they always have 101 keys, or are there some that have 102 ? The 102nd key is the one between LShift and Z, isn't it ? How is it labelled on a US keyboard if it is present ? "|\" ?
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Post by jal »

asmfreak wrote:There are several reasons why I am not so sure if writing my own INT 9 handler is really a good idea:

(1) The INT 9 handler defines the relationship between scancodes and ASCII characters (i.e. the "keyboard layout")
You have a point there. If you really want to stay compatible with all software out there, you're lost.
(2) I have very little information on the old PC/XT keyboards. Wouldn't it be possible, that old BIOSes didn't support these combinations because some of these old keyboards couldn't handle them correctly ?
The one and only XT keyboard is the IBM one. A recent thread mentioned at least a number of people here have such a keyboard. It would be easy to check whether or not they are supported, but I bet they are. The reason for not supporting it in BIOS could very well be some terminal emulation modes (remember the original CGA had brown instead of dark yellow hard coded into the hardware of the CRT because of terminal emulation), so perhaps an old IBM terminal allowed Ctrl-Left/Right but not Ctrl-Up/Down.
(3) I am currently disassembling the standard INT 9 handler provided by my BIOS. Believe me: It is not that easy.
Better take Bochs BIOS or the like, it's annotated and therefore easier. Unless you are looking at the BIOS of an original PC/XT, of course, but I'm assuming you look at a modern BIOS.
P.S.: I am working with a German keyboard and know US keyboards only from photos I have seen on the internet. Do they always have 101 keys, or are there some that have 102 ? The 102nd key is the one between LShift and Z, isn't it ? How is it labelled on a US keyboard if it is present ? "|" ?
Google is your friend. There are many resources on the internet about keyboard layouts.


JAL
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Post by mathematician »

asmfreak wrote:But that's exactly where the real trouble starts: While it is rather easy to "chain" to a software interrupt handler (you just have to call it with the same register values "your" handler was called with), a hardware interrupt handler is reading the data it is working with from external ports rather than from CPU registers, so when the previously installed handler is called, the state of the hardware should be just as it was when "my" handler was called. As "my" handler will already have read the scancode from port 60h (to determine if it identifies the Up or Down key), the state of the hardware won't be the same. I am not sure if reading port 60h a second time is guaranteed to return the same value. In any case, the "Output Buffer Full" bit in the keyboard controller's status register (port 64h) will return to 0 after the first read of port 60h, and this may confuse the previously installed handler. If it waits for this bit to be 1 before reading port 60h, the system will be hung.
If you consult the documentation for the keyboard controller I think you will find there is a way of stuffing scan codes into the controller so that they can be read from port 60h. I can't remember the details, but I remember thinking "interesting" when I stumbled upon it.
asmfreak
Posts: 6
Joined: Wed Jan 02, 2008 11:41 am

Post by asmfreak »

mathematician wrote:If you consult the documentation for the keyboard controller I think you will find there is a way of stuffing scan codes into the controller so that they can be read from port 60h. I can't remember the details, but I remember thinking "interesting" when I stumbled upon it.
Don't think I haven't thought about that. But this again will not work on all computers. HelpPC for example states that this works only on PS/2 systems.

The most convenient way of examining the scancode without "disturbing" the previously installed handler would be of course Int 15h, function 4Fh ("Keyboard intercept"), but again: This function wasn't defined on the original PC and won't be called by old BIOSes / old TSRs.

Just in case I decided to abandon backward compatibility: Does anyone know how to detect the presence of the "extended" functions 10h and 11h of Int 16h? HelpPC provides the following information:
Detecting Extended Keyboard BIOS

1. use INT 16,5 to stuff FFFF into the keyboard buffer
2. use INT 16,10 to read the keystrokes back
3. if the data stuffed into the keyboard is returned within 16
extended reads, the BIOS handles the extended keyboard
4. byte at 40:96 (BDA) is another method of detecting extended BIOS
but is not reliable since some compatibles give false positives
It would probably be easier to disable the keyboard, clear the keyboard buffer by setting the queue tail pointer to the same value as the queue head pointer (or the other way round), performing steps 1 and 2, and enabling the keyboard again, wouldn't it ? After all, a keyboard buffer larger than 16 words might be installed (pointed to by 0040h:0080h ("Keyboard buffer start") and 0040h:0082h ("Keyboard buffer end")). By the way, does anyone know how to detect if those variables are supported by the BIOS ? This would be important if I really decided to write my own Int 9 handler and to modify functions 00h and 01h of Int 16h, because when either the head pointer or the tail pointer reaches the physical end of the buffer, it will "wrap" back to the beginning, so I would have to know for sure where the buffer starts and ends.
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Post by mathematician »

asmfreak wrote: Just in case I decided to abandon backward compatibility: Does anyone know how to detect the presence of the "extended" functions 10h and 11h of Int 16h? HelpPC provides the following information.
How far back do you want to take backward compatibility? The above is something you would have needed to worry about if you were writing programs maybe twenty years ago. In those days MS-DOS still ruled the waves; OS/2 was predicted to be the next big thing, and never was.
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Post by jal »

asmfreak wrote:Just in case I decided to abandon backward compatibility: Does anyone know how to detect the presence of the "extended" functions 10h and 11h of Int 16h?
Yes, check Ralph B's interrupt list, it's all in there. There are various BIOS calls that indicate features present or absent. Check for the int16h/ah=10h and it'll direct you to it.


JAL
Post Reply