Johann 'Myrkraverk' Oskarsson
2019-10-21 10:31:44 UTC
Dear c.o.m.programmer,
Instead of overwriting int 15 and hook the keyboard translator, I
decided to experiment with my own keyboard interrupt handler. So far,
it seems to work OK apart from a long beep in DOSBox-X on first use. I
believe that's something to do with my code rather than DOSBox-X itself.
As an experimental code, I cannot recommend anyone trying it on real
hardware. I would like to know why the continuous beep happens.
The interrupt routine is somewhat black art to me. Why am I reading and
then writing different bits to the keyboard controller?
What is the significance of using sti() at the start of the function,
and outp( 0x20, 0x20 ) at the end?
/* file: kb.c -*- c-default-style: "k&r" -*- */
/* A simple program to demonstrate keyboard driver in protected mode.
* Hopefully.
*
* Compile with:
* wcl386 -l=causeway -za99 kb.c
* for the CauseWay version, or adjust for DOS4GW.
*
* Alternatively compile as 16bit program with:
* wcl -za99 kb.c
*
* Known side effects: beeps steadily on first run in DOSBox-X but
* otherwise appears to work.
*/
#include <dos.h>
int quit = 0;
void sti( void );
#pragma aux sti = "sti" modify exact [] nomemory;
void ( _interrupt _far *dos_kbd)( void );
/*
* This routine is translated from assembly into C, from the book
* Black Art of 3D Game Programming, by Andre Lamothe, page 224.
*/
void _interrupt _far kbd( void ) {
sti(); // Why do I need STI here?
/* What exactly is the purpose of the inp() and outp() routines
* below? Getting the scan code is obvious, but what exactly am
* I doing with the control bits?
*/
int scancode = inp( 0x60 ); // raw keyboard buffer
int control = inp( 0x61 ); // raw keyboard control
control |= 0x82; // mask off the right bits?
outp( 0x61, control ); // output the control bits
outp( 0x61, 0x7f ); // finish the keyboard song and dance
if ( scancode == 1 ) quit = 1; // scan code 1 = escape
/*
* For now we just ignore every input, and set the quit flag to
* true if the user pressed ESC.
*/
outp( 0x20, 0x20 ); // PIC enable interrupts
}
int
main( int argc, char *argv[] )
{
dos_kbd = _dos_getvect( 0x09 ); // keyboard interrupt
_dos_setvect( 0x09, kbd );
while ( !quit )
;
_dos_setvect( 0x09, dos_kbd );
return 0;
}
/* end of file: kb.c */
Instead of overwriting int 15 and hook the keyboard translator, I
decided to experiment with my own keyboard interrupt handler. So far,
it seems to work OK apart from a long beep in DOSBox-X on first use. I
believe that's something to do with my code rather than DOSBox-X itself.
As an experimental code, I cannot recommend anyone trying it on real
hardware. I would like to know why the continuous beep happens.
The interrupt routine is somewhat black art to me. Why am I reading and
then writing different bits to the keyboard controller?
What is the significance of using sti() at the start of the function,
and outp( 0x20, 0x20 ) at the end?
/* file: kb.c -*- c-default-style: "k&r" -*- */
/* A simple program to demonstrate keyboard driver in protected mode.
* Hopefully.
*
* Compile with:
* wcl386 -l=causeway -za99 kb.c
* for the CauseWay version, or adjust for DOS4GW.
*
* Alternatively compile as 16bit program with:
* wcl -za99 kb.c
*
* Known side effects: beeps steadily on first run in DOSBox-X but
* otherwise appears to work.
*/
#include <dos.h>
int quit = 0;
void sti( void );
#pragma aux sti = "sti" modify exact [] nomemory;
void ( _interrupt _far *dos_kbd)( void );
/*
* This routine is translated from assembly into C, from the book
* Black Art of 3D Game Programming, by Andre Lamothe, page 224.
*/
void _interrupt _far kbd( void ) {
sti(); // Why do I need STI here?
/* What exactly is the purpose of the inp() and outp() routines
* below? Getting the scan code is obvious, but what exactly am
* I doing with the control bits?
*/
int scancode = inp( 0x60 ); // raw keyboard buffer
int control = inp( 0x61 ); // raw keyboard control
control |= 0x82; // mask off the right bits?
outp( 0x61, control ); // output the control bits
outp( 0x61, 0x7f ); // finish the keyboard song and dance
if ( scancode == 1 ) quit = 1; // scan code 1 = escape
/*
* For now we just ignore every input, and set the quit flag to
* true if the user pressed ESC.
*/
outp( 0x20, 0x20 ); // PIC enable interrupts
}
int
main( int argc, char *argv[] )
{
dos_kbd = _dos_getvect( 0x09 ); // keyboard interrupt
_dos_setvect( 0x09, kbd );
while ( !quit )
;
_dos_setvect( 0x09, dos_kbd );
return 0;
}
/* end of file: kb.c */
--
Johann | email: invalid -> com | www.myrkraverk.com/blog/
I'm not from the Internet, I just work there. | twitter: @myrkraverk
Johann | email: invalid -> com | www.myrkraverk.com/blog/
I'm not from the Internet, I just work there. | twitter: @myrkraverk