Jump to content

How do I use the keyboard handler the proper way?

Recommended Posts

I can't believe I am not able to solve this myself...


Until now in assembly, I always read the keycode in CH myself if I was using keyboard keys in my programs.

After mastering disk i/O with IOCB I thought, hell, that's easy! What an elegant OS our Atari has!


Now I tried to use the keyboard 'the proper way' , reading a key via CIO.


I came across that small routine:

00010 ------------------------------00020 *  READ CHAR FROM KEYBOARD   *00030 *  CHAR WILL BE IN THE       *00040 *  <A> REGISTER              *00050 *  <X>,<Y> will be destroyed *00060 ------------------------------00070 *00080 GETKEY   LDA $E425   GET ADRESS-VECTOR00090          PHA         FROM ROM HANDLER TAB00100          LDA $E424   PLACE ADDRESS AS00110          PHA         RETURN ADDRESS TO STACK00120          RTS         JUMP TO ROM-ROUTINE00130 *

But It doesn't work, I just get EOLs all the time. Maybe I have to open a channel first?


I always thought the keyboard handler is resident, so there should be always an open keyboard channel set by the OS, but which one?

when I use .IOCB command in Altirra's debugger to check IOCB status, no K: channel seems to be open. (my code runs from 'compile and run' in WUDSN)

So how do I open a channel for "K:" ? I can't find an example anywhere about how to do it properly. Do I have to use a specific channel number? Do I have to use open for read or write? Which IOCB registers do I have to set and how?


This should be such a simple task, it's embarrassing...

Link to comment
Share on other sites

The E:, S:, and K: handlers in the OS are all the same module internally and cross-call between each other. K: doesn't need to be open because E: directly calls into the keyboard routines.


The problem is that the K: handler is checking bit 0 of ICAX1Z to see if should respond in forced read mode. CIO normally copies ICAX1,X to ICAX1Z before invoking the device handler, but since you are bypassing CIO you'll need to set up it up yourself by setting ICAX1Z=$04.


Interestingly, while this behavior is documented for E:, it doesn't seem to be documented for K:. The OS manual says that there are no device dependent bits in ICAX1, even though both OS-B and the XL/XE OS check ICAX1Z in K: GET BYTE.


If you want to do it the fully correct way, you'll have to open K: through an IOCB. Set X=IOCB*16, i.e. $10 for IOCB #1, ICBAL,X and ICBAH,X to point to the filename ('K', $9B), ICAX1,X to the mode ($04 for read), and ICCMD,X to the OPEN command ($03). JSR CIOV with X=$10 to open the IOCB and check the N flag for an error. To read a byte, do a zero byte read with ICCMD,X=$07, ICBLL,X=0, ICBLH,X=0, X=IOCB*16, JSR CIOV and receive the byte in the A register. Close the IOCB with ICCMD,X=$0C, X=IOCB*16, JSR CIOV.

Edited by phaeron
  • Like 1
Link to comment
Share on other sites

A trick if you want to continue processing and not be held up waiting for a key - check the CH variable ($2FC, 764 dec) - only do the CIO call if the value is < $C0.

That will ignore situations of no keypress or SHIFT + CONTROL + key (which generate keyclick but don't return anything).

There are some "null" keypresses though that fall into the $80 - $BF scan code range.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...