Let's Code MS DOS 0x24: Low Level Keyboard Programming

Ғылым және технология

Getting input from the keyboard can be as easy as calling the getch() function. But for games we need a better solution. For games on MS DOS machines you need quick, unbuffered input. To simply get the state of keypresses we need to talk to the keyboard controller directly. Let’s have a look at how that’s done!
Support me on Patreon: / root42
Support me on Ko-Fi: ko-fi.com/root42
Support me on PayPal: paypal.me/ArneSchmitz
Support me on KZread: / @root42
Source code: github.com/root42/doskbc
Previous episodes:
Keyboard: • Let's Code MS DOS 0x02...
Sound Blaster: • Let's Code MS DOS 0x0B...
IRQ Handling: • Let's Code MS DOS 0x0D...
Music: A Little Wonder by Spino2006

Пікірлер: 26

  • @root42
    @root427 ай бұрын

    After the useful comments by @staticage6 and @JimLeonard I pushed an updated revision of the code: github.com/root42/doskbc/tree/ce48a9245730507c61b01b76cf50e9d3e70eea0d This version doesn't use the enable/disable calls and also calls the original keyboard handler for improved compatibility with less compatible systems like the PC Jr and Tandy 1000. The main difference is that we do not use the SCP at 0x61, but instead call the original IRQ handler and then modify the keyboard buffer so it doesn't overflow, because keys are not being fetched e.g. via getch(). The original version is still available here: github.com/root42/doskbc/tree/f0e3e7c3129acc308c8148dca9e83c6329758425

  • @JimLeonard

    @JimLeonard

    7 ай бұрын

    Looks good!

  • @applebumpcaster8240
    @applebumpcaster82407 ай бұрын

    As a "modern programer" i always wondered how these old technologies work. Working around this industry, i never experienced it. Maybe for personal projects? sounds fun! It's cool for their time and i have been surfing around the net. but most of the information was lost (or hard to find or not the one i been looking for.) your series about this old school stuff is amazing. Really helpful. Thank you. liked and subscribed!

  • @root42

    @root42

    7 ай бұрын

    The information is mostly still there. But you have to look for it. Most was obviously published in books back in the day. So archive.org is a good start as they have many old tech books available. Also lots of txt files float around. Also this is very useful: stanislavs.org/helppc/

  • @wesbat9012
    @wesbat90126 ай бұрын

    Thanks for taking the time to make this series! I really enjoy these videos, they are useful and also a great source of inspiration and motivation. I programmed in DOS in the 90's as a hobby using Turbo Pascal. Recently I got a copy of K&R and started using Turbo C. I dare say programming has become fun again.

  • @root42

    @root42

    6 ай бұрын

    Yes, the simplicity lets you concentrate on algorithms and coding itself instead of what frameworks and libraries to pick.

  • @keyvanmehrbakhsh4069
    @keyvanmehrbakhsh40697 ай бұрын

    arne you are doing awesome job taking apart all of these things that was used to be so intact so no one out of the industry would have get it. I learned a lot from your codes wanted so share my appreciation .

  • @root42

    @root42

    7 ай бұрын

    Thank you

  • @maxmuster7003
    @maxmuster70037 ай бұрын

    Another way is to stop/disable the IRQ 1 and then polling the keyboard controller. First status port hex 64 if there is a byte in the input buffer and additional check if it is a byte from the PS2 mouse. If it is a byte from the keyboard we can poll the byte(make or break code) from port hex 60. At the end we can use software interrupt hex 16 to clear the keyboard buffer and then to enable IRQ 1.

  • @root42

    @root42

    7 ай бұрын

    Thanks, haven’t seen that one yet.

  • @maxmuster7003

    @maxmuster7003

    7 ай бұрын

    @@root42Example for polling the keyboard controller: cli mov al, 2 ; dissable IRQ 1 out 21h, al sti ; main loop BEGIN: in al, 64h test al, 1 jz short NOKEY ; if no key test al, 20h ; or PS2 mouse jnz short NOKEY in al, 60h ; get make/break code dec al ; Escape ? jz HOME ; .... ; compare the byte with a table of keys ; if we found a key we can we use the offset with a second table of ASCII for output NOKEY: ; ..... ; ....... jmp BEGIN HOME: cli xor al, al ; enable IRQ 1 out 21h, al sti mov ah, 1 int 16h

  • @JimLeonard
    @JimLeonard7 ай бұрын

    I always love to see new dos programming tutorials, especially those that involve hardware and interrupts! But I'm torn with this one, as the are some issues that will cause problems on real hardware. If you would like a list of suggestions, let me know how to get them to you (or I can comment here?).

  • @root42

    @root42

    7 ай бұрын

    Just put them here, Jim. So people can pick up your advice directly. I am always open to code reviews. :)

  • @JimLeonard

    @JimLeonard

    7 ай бұрын

    ​@@root42 Thanks :-) So, some unnecessary things first: You don't need to disable interrupts in an interrupt handler, because the CPU clears the interrupt flag when an INT is executed, so interrupts are already disabled upon entry to an interrupt handler. Also, you don't need to explicitly enable interrupts at the very end of the interrupt handler (I'm assuming enable() = STI), because IRET pops the flags off the stack, which restores the interrupt flag (ie. interrupts are then automatically enabled). The compatibility concern is that your code is valid for AT and higher systems, but may not work properly on XT-class systems as well as some of the stranger XT clones. For compatibility with all systems, my preferred keyboard handler reads the status from 0x60 and stores it in an array like you do, but then does nothing else and instead CALLs the old keyboard interrupt handler, which lets the original keyboard code in the BIOS handle the port, state, LEDs, etc. including all of the regular cleanup needed. Then, because the old handler likely enters a key into the keyboard buffer, I clear the buffer by setting the keyboard buffer head equal to the tail by copying the word at 0x40:0x1c to 0x40:0x1a. Finally, I exit the handler WITHOUT outputting 0x20 to port 0x20, because the old keyboard handler has already done that. This has worked on every system I've tried, even the PCjr which doesn't have an 8042 keyboard controller. Hope this helps!

  • @root42

    @root42

    7 ай бұрын

    @@JimLeonardThanks for the input. The CLI/STI makes sense, was already mentioned by @staticage6. I thought about handing over to the original keyboard handler, but was exactly thinking about the problem that I would need to clear the buffer, or else we would get a lot of beeping after a short while... 😀 So thank you for the hint to modify the word at 0x0040:0x001A. I totally forgot that this is the buffer location. I don't have an XT system (yet) -- Sergey's Micro 8088 is still lying unpopulated next to me. So I only tested on my 486, which worked. But for clarity: This would "only" be an issue with machines that don't implement 0x61 correctly, right? So PC Jr, maybe Tandy 1000...? The original PC should still implement 0x61 ....?

  • @JimLeonard

    @JimLeonard

    7 ай бұрын

    @@root42 It should work on real IBMs, yes, but the PCjr and Tandy systems are more prevalent than you think :⁠-⁠) But there are other benefits to compatibility: Smaller code size.

  • @root42

    @root42

    7 ай бұрын

    I pushed a version that uses the original keyboard handler and buffer. Seems to work fine, I think.

  • @staticage6
    @staticage67 ай бұрын

    Nice little program there! Thanks for sharing. I also want to point out that in your interrupt routine, you do not need the enable() and disable() functions for disabling interrupts as the CPU will do that for you at every interrupt call.

  • @DanielMonteiroNit
    @DanielMonteiroNit7 ай бұрын

    Man, you're 4 hours late. I needed that video today 😅 I end up using INT 16, AH=1

  • @DanielMonteiroNit

    @DanielMonteiroNit

    7 ай бұрын

    TBF, I do intend to write something better (particularly for the protected mode version of the game engine, which has much more memory available)

  • @root42

    @root42

    7 ай бұрын

    I think a refactor is coming up for you!

  • @DanielMonteiroNit

    @DanielMonteiroNit

    7 ай бұрын

    @@root42 that's exactly the name of the branch I'm working on 😂

  • @szaman6204
    @szaman62047 ай бұрын

    i love ms-dos system

  • @alisharifian535
    @alisharifian5357 ай бұрын

    I am really curious to know if there is a way to use windows key in Ms-Dos.

  • @root42

    @root42

    7 ай бұрын

    You can try it out! Just print out the keycodes in the program.

  • @TreeOfWisdom2
    @TreeOfWisdom27 ай бұрын

    why waste time with PICO-8 when you have DOS?

Келесі