delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1999/02/16/00:31:56

Message-ID: <36C90198.90D8905C@ameritech.net>
Date: Mon, 15 Feb 1999 23:26:48 -0600
From: John Scott Kjellman <jkjellman AT ameritech DOT net>
X-Mailer: Mozilla 4.04 [en] (Win95; I)
MIME-Version: 1.0
To: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
CC: djgpp AT delorie DOT com
Subject: Re: How to check the carry flag? (long)
References: <Pine DOT SUN DOT 3 DOT 91 DOT 990215102108 DOT 10128P-100000 AT is>
Reply-To: djgpp AT delorie DOT com

Eli,

See the below program text.  I compiled it using RHIDE (file name CFTEST.CC). 
If you run it and then press a few keys, it will display the character (if
printable) and the getxkey() value for each key.  The '1' key should be
translated to a '2' and the '0' key should be dropped, but isn't!  BTW, in my
previous posting I stated 0x30 was the scan code for the '0' key, it is not 0x0B
is, 0x30 is the ASCII value ;-)  This just doesn't seem to follow the docs....

KJohn

===================== start of CFTEST.CC ==================
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <keys.h>
#include <dpmi.h>
#include <go32.h>
#include <pc.h>
#include <sys\movedata.h>
    
// required supporting data
_go32_dpmi_registers Regs;
static _go32_dpmi_seginfo info;
static _go32_dpmi_seginfo OldInt15Vector;

const unsigned short CarryFlagMask = 0x0001;

//
// This function is the ISR used to handle int 15 func 4f interrupts.
// Int 15 func 4f is called by the BIOS everytime it reads a character
// from the 8042 (keyboard controller).  It places the scan code read
// in the AL register.  On exit from this handler, if carry is cleared
// the BIOS will ignore the scan code.  If carry is set, the BIOS will
// process the data in AL as the scan code (i.e. you can change the
// scan code if you want).
//
// This function does two things, if it sees a scancode 0x0B ('0' key)
// it clears the carry flag so the BIOS will ignore the '0' key.  If it
// sees a scan code 0x02 ('1' key), it changes it to 0x03 ('2' key).
void Int15Handler( _go32_dpmi_registers *Regs )
{
 // if we are being called for int 0x15, function 0x4f (BIOS key intercept)
 // and the carry flag is set (it is clear for dropping this scan code)
 if ( Regs->h.ah != 0x4f )
    return;
  
 // if this is the '0' key make code, ask BIOS to drop it
 if ( Regs->h.al == 0x0b )
    Regs->x.flags = Regs->x.flags & ~CarryFlagMask;

 // if this is the '1' key scan code (0x02), change the '2' key scan code (0x03)
 if ( Regs->h.al == 0x02 )
    Regs->h.al = 0x03;

  return;
}

//
// This function locks the Int15Handler() ISR code and data areas into memory
// so the DPMI server cannot swap them out to disk or move them in physical
// memory.  It then adds this the Int15Handler address to the interrupt
// vector table so it will be called via int 15.
// NOTE: This function must be placed after the Int15Handler in this file
void StartInt15Handler()
{
    // lock handler's memory
    _go32_dpmi_lock_code( Int15Handler, (unsigned long)StartInt15Handler -
(unsigned long)Int15Handler );
    _go32_dpmi_lock_data( &Regs, sizeof(Regs) );

    // install int 15 handler
    _go32_dpmi_get_real_mode_interrupt_vector( 0x15, &OldInt15Vector );
    info.pm_offset = (long unsigned int)Int15Handler;
    _go32_dpmi_allocate_real_mode_callback_iret( &info, &Regs );
    _go32_dpmi_set_real_mode_interrupt_vector( 0x15, &info );
}

//
// This routine removes Int15Handler from the system interrupt table
// and frees any used resource
void StopInt15Handler()
{
    _go32_dpmi_set_real_mode_interrupt_vector( 0x15, &OldInt15Vector );
    _go32_dpmi_free_real_mode_callback( &info );
}

int main()
{
    unsigned short Key;
    
    printf( "Starting int 15 handler\n" );
    StartInt15Handler();
    printf( "\n\nPress any key, the getkey() values will be displayed.\n" );
    printf( "  Escape to exit.\n" );
    printf( "  '0' should do nothing.\n" );
    printf( "  '1' should show as '2'.\n" );

    while( Key != K_Escape )
    {
        Key = getxkey();
        if ( isprint( Key ) )
           printf( "'%c'(%02x) ", (char) Key, Key );
        else
           printf( "N/A(%02x) ", Key );
    }

    StopInt15Handler();

    return 0;
}

==================== end of CFTEST.CC ===============

Eli Zaretskii wrote:
> 
> On Sun, 14 Feb 1999, John Scott Kjellman wrote:
> 
> > Once I do this, if the BIOS generated an int 15 (func 4f) and the
> > scan code in AL is 0x30 (make code for '0' key), clearing the carry
> > flag and returning should cause the BIOS to ignore the '0' key scan
> > code.  This does not work!
> 
> It should work, though.  The documentation for the function
> `_go32_dpmi_allocate_real_mode_callback_iret' says that any changes to
> the registers' struct will be reflected back to real mode.  And the
> DPMI spec includes an example of a function that hooks Int 21h and
> sets the carry flag under certain conditions, so at least in theory
> this should have worked.
> 
> It might be that the carry flag is cleared by the wrapper created by
> `_go32_dpmi_allocate_real_mode_callback_iret', but I don't see any
> instruction which does that.  Maybe if you look at its source (the
> file gormcb.c in djlsr202.zip) you will see some bug like that.
> 
> Are you sure that the carry flag not being set is your problem?  Maybe
> some other cause is at work here?
> 
> > If this is too confusing (I know it is a l-o-n-g explanation), please let me
> > know and I'll write a simpler program to demonstrate what I am trying to
> > accomplish.
> 
> It's not confusing, but a simple test program might help to
> investigate the problem.

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019