Trouble detecting keyboard inputs while in a game loop

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Caffeine
Member
Member
Posts: 79
Joined: Mon Nov 15, 2021 9:48 pm

Re: Trouble detecting keyboard inputs while in a game loop

Post by Caffeine »

alexfru wrote:
Caffeine wrote:
iansjack wrote:No. But failure to do points 3 or 4 that I mentioned would mean that you get just one interrupt.
What do you mean by just get one interrupt?
The interrupt controller and the keyboard need to know that the CPU has finished handling the interrupt before there's another one generated and delivered to the CPU.
Is there a way to figure out if this is the issue? Also I do not know if any of the points you mentioned were done incorrectly. I don't think that they are but I may be missing something.
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Trouble detecting keyboard inputs while in a game loop

Post by iansjack »

Without seeing your code it's impossible to say. You should provide a link to an online repository.
Caffeine
Member
Member
Posts: 79
Joined: Mon Nov 15, 2021 9:48 pm

Re: Trouble detecting keyboard inputs while in a game loop

Post by Caffeine »

iansjack wrote:Without seeing your code it's impossible to say. You should provide a link to an online repository.
Here: https://github.com/zachary-d-r/CaffeineOS
Caffeine
Member
Member
Posts: 79
Joined: Mon Nov 15, 2021 9:48 pm

Re: Trouble detecting keyboard inputs while in a game loop

Post by Caffeine »

Octocontrabass wrote:
Caffeine wrote:To confirm - the Keyboard interrupt is not being called. I set up a breakpoint and it is not going off while in the loop.
Have you set EFLAGS.IF?

How and when do you initialize the interrupt controllers? (It should be done before you initialize the keyboard controller.)

How and when do you initialize the keyboard controller? (Usually you don't need to initialize much - just empty the output buffer.)
I believe I've se EFLAGS.IF. I've looked at the multiboot specification examples and am not sure if I did it right. I started with Brans Kernel Development tutorial and have not changed boot.asm since, so this is almost entirely copy and pasted from there.

Here I am setting constants for the multiboot header:

Code: Select all

; Declare constants for the multiboot header.
MAGIC equ 0x1BADB002
FLAG_VIDEO_MODE equ (1 << 2)
FLAGS equ FLAG_VIDEO_MODE
CHECKSUM equ -(MAGIC + FLAGS) & 0xFFFFFFFF
HEADER_ADDR equ 0 ; if flags[16] is set
LOAD_ADDR equ   0 ; if flags[16] is set
LOAD_END_ADDR equ   0 ; if flags[16] is set
BSS_END_ADDR equ 0 ; if flags[16] is set
ENTRY_ADDR equ 0 ; if flags[16] is set
MODE_TYPE equ 0 ; if flags[2] is set
WIDTH equ 0 ; if flags[2] is set
HEIGHT equ 0 ; if flags[2] is set
DEPTH equ 0x20 ; if flags[2] is set
And here is the .multiboot section:

Code: Select all

section .multiboot
align 4
	dd MAGIC
	dd FLAGS
	dd CHECKSUM
	dd HEADER_ADDR
	dd LOAD_ADDR
	dd LOAD_END_ADDR
	dd BSS_END_ADDR
	dd ENTRY_ADDR
	dd MODE_TYPE
	dd WIDTH
	dd HEIGHT
	dd DEPTH
And here is the keyboard code (after creating the scan code stuff to identify the key), also almost entirely copy and pasted from Brans Kernel Development Tutorial.

Code: Select all

int shiftPressed = 0;  // To check if shift is pressed

// Handles the keyboard interrupt
void keyboardHandler(struct regs *r) {
    unsigned char scancode;  // The scancode from our keyboard
    scancode = inportb(0x60);  // Read from the keyboards data register which is at 0x60

    // If the top bit of the byte we read from the keyboard is set, then a key has just been released
    if (scancode & 0x80) {
        // Use this to see if the user released the shift, alt or control keys
        switch (scancode) {
          case 0xaa: shiftPressed = 0; break;
        }
    }

    // Here a key was just pressed. Holding down a key means you will get repeated key press interrupts
    else {

        /* Just to show you how this works, we simply translate
        *  the keyboard scancode into an ASCII value, and then
        *  display it to the screen. You can get creative and
        *  use some flags to see if a shift is pressed and use a
        *  different layout, or you can add another 128 entries
        *  to the above layout to correspond to 'shift' being
        *  held. If shift is held using the larger lookup table,
        *  you would add 128 to the scancode when you look for it */

        switch (scancode) {
          // Arrowkeys
          // case 0x4b: moveCursorRealative(-1, 0); scroll();  break;
          // case 0x4d: moveCursorRealative(1, 0);  scroll(); break;
          // case 0x48: moveCursorRealative(0, -1); scroll();  break;
          // case 0x50: moveCursorRealative(0, 1);  scroll(); break;

          case 0x2a: shiftPressed = 1; break;  // Check if left shift is pressed
          case 0x36: shiftPressed = 1; break;  // Check if right shift is pressed

          default: { keyboardControll(getInput(kbdus[scancode], shiftPressed)); break; }
        }

    }
}

void installKeyboard() {
    installIrqHandler(1, keyboardHandler);
}
getInput returns the character depending on whether or not shift is pressed.
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Trouble detecting keyboard inputs while in a game loop

Post by Octocontrabass »

Caffeine wrote:I believe I've se EFLAGS.IF. I've looked at the multiboot specification examples and am not sure if I did it right.
According to the Multiboot specification, EFLAGS.IF will always be clear when the bootloader passes control to your kernel, so it doesn't matter what you put in your multiboot header.

If you don't have any code elsewhere to set EFLAGS.IF, you'll never receive interrupts. If EFLAGS.IF is not set while your game loop is running, your game loop won't receive interrupts. You can check EFLAGS.IF in your debugger.
Caffeine
Member
Member
Posts: 79
Joined: Mon Nov 15, 2021 9:48 pm

Re: Trouble detecting keyboard inputs while in a game loop

Post by Caffeine »

Octocontrabass wrote:
Caffeine wrote:I believe I've se EFLAGS.IF. I've looked at the multiboot specification examples and am not sure if I did it right.
According to the Multiboot specification, EFLAGS.IF will always be clear when the bootloader passes control to your kernel, so it doesn't matter what you put in your multiboot header.

If you don't have any code elsewhere to set EFLAGS.IF, you'll never receive interrupts. If EFLAGS.IF is not set while your game loop is running, your game loop won't receive interrupts. You can check EFLAGS.IF in your debugger.
Here is EFLAGS when in the GNU OS selection screen:

Code: Select all

(gdb) info reg eflags
eflags         0x2                 [ IOPL=0 ]
Here is is after I select my OS:

Code: Select all

(gdb) info reg eflags
eflags         0x200202            [ ID IOPL=0 IF ]
And here it is after I launch pong:

Code: Select all

(gdb) info reg eflags
eflags         0x200016            [ ID IOPL=0 AF PF ]
To be honest, I'm not sure what exactly all of this means, but is there a problem here?

And if there is, how do I set EFLAGS.IF in the game loop?
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Trouble detecting keyboard inputs while in a game loop

Post by iansjack »

I wonder if you need to do a little more learning before progressing. I get the feeling that you have copied a lot of code without really understanding it or the basics of the processor operation. You are asking some very basic questions (What does EFLAGS mean? How do I set the interrupt enable flag?)

The Intel or AMD Programmer's Manuals are pretty essential reading for anyone interested in OS development.
Caffeine
Member
Member
Posts: 79
Joined: Mon Nov 15, 2021 9:48 pm

Re: Trouble detecting keyboard inputs while in a game loop

Post by Caffeine »

iansjack wrote:I wonder if you need to do a little more learning before progressing. I get the feeling that you have copied a lot of code without really understanding it or the basics of the processor operation. You are asking some very basic questions (What does EFLAGS mean? How do I set the interrupt enable flag?)

The Intel or AMD Programmer's Manuals are pretty essential reading for anyone interested in OS development.
Okay, so I have done some reading and I am able to set the interrupt enable flag:

Code: Select all

eflags         0x200216            [ ID IOPL=0 IF AF PF ]
But it still does not detect keyboard interrupts. The PIC is working now! What I did is I cleared EFAGS.IF and the set it again. Now I need to be able to detect keyboard interrupts.
Caffeine
Member
Member
Posts: 79
Joined: Mon Nov 15, 2021 9:48 pm

Re: Trouble detecting keyboard inputs while in a game loop

Post by Caffeine »

I figured it out! The keyboard is never sending an EOI because I called loadPong() before the function returns.
Post Reply