[MSX-C] Q&A official thread

Page 66/68
59 | 60 | 61 | 62 | 63 | 64 | 65 | | 67 | 68

By ~mk~

Champion (328)

~mk~'s picture

24-02-2023, 06:56

rolandve wrote:

Issue: I am showing a picture, waiting for a keypress before the next one. However: I am reading the keyboard with NEWKEY in the routine before the picture. These keys presses get buffered so my kbit() routine exits immediately.

I am using NEWKEY to scan for keys like up and down. Each keypress however generates about 35 or 40 hits. Kilbuf() however does not empty that buffer, it's completely ignored, so my routine gets executed way too many times. I have tried to manually set the NEWKEY row to 255, I've tried to use OLDKEY as a way to detect the moment I let go of the key but that doesn't work. Is there a smart way to detect the press of a single key and ignore the other measured moments in between?

Not sure I understand the problem with kbhit(). Can you elaborate?
The simplest way to achieve what you describe should be a combination of kbhit() and getch().

By rolandve

Champion (358)

rolandve's picture

25-02-2023, 09:54

~mk~ wrote:

Not sure I understand the problem with kbhit(). Can you elaborate?
The simplest way to achieve what you describe should be a combination of kbhit() and getch().

getch() doesn't take ctrl/left/right/up and down.

By aoineko

Paladin (1002)

aoineko's picture

25-02-2023, 11:22

I don't know MSX-C but I guess you can do what I do in MSXgl to handle this case.
Look for the INPUT_USE_KEYBOARD define in the Input module (input.h & input.c).

Basically, I have a Keyboard_Update() function that is called at each frame to update the part of the keyboard matrix we are interested in (it saves the previous state then refreshes the matrix).
Then you know that a key has just been pressed when its corresponding bit in the matrix is 0 and the one in the previous matrix is 1.

Attention, two subtleties in my method:
1) I reuse the RAM buffer allocated by the BIOS for the keyboard matrices (NEWKEY and OLDKEY). This only works if you do not use the BIOS interrupt handler (ISR). Otherwise, you can directly use the value of the NEWKEY table as an update of the keyboard matrix, but you must have your own table in memory to store the previous state (otherwise OLDKEY will be reset by the ISR). Using BIOS's ISR you will have a delay of one frame in the detection of the keystroke, but it will be imperceptible for the player.

2) I use a unique identifier for each key which is: row number * 16 + number of the key in the row (see KEY_ID enumeration). The row number is used to know which cell of the NEWKEY/OLDKEY tables to look at and the number of the key in the row is used to know which bit to check.

By DarkSchneider

Paladin (1011)

DarkSchneider's picture

25-02-2023, 15:18

Yes I remember also having issues with OLDKEY. You have to store in your own space and then keydown should be if is set in NEWKEY but not in your OLDKEY, keyup should be the opposite.

This is because your loop could be longer than the vblank period, so your are not reading a correct “old”. Don’t remember exactly but the way should be something like when you finish reading input in your loop, copy the system NEWKEY to your OLDKEY so you can use it as previous reference state.

By theNestruo

Champion (421)

theNestruo's picture

25-02-2023, 16:23

aoineko wrote:

1) I reuse the RAM buffer allocated by the BIOS for the keyboard matrices (NEWKEY and OLDKEY). This only works if you do not use the BIOS interrupt handler (ISR). Otherwise, you can directly use the value of the NEWKEY table as an update of the keyboard matrix, but you must have your own table in memory to store the previous state (otherwise OLDKEY will be reset by the ISR).

I also reuse OLDKEY and NEWKEY in my assembly library. :)
You can prevent BIOS interrupt handler from touching that area by reseting SCNCNT in you hook before returning to BIOS interrupt handler. You can also reset INTCNT and the sprite collision flag to prevent the BIOS interrupt handler from spending time checking if it has to call MSX-BASIC ON INTERVAL and ON SPRITE subroutines.

aoineko wrote:

Using BIOS's ISR you will have a delay of one frame in the detection of the keystroke, but it will be imperceptible for the player.

Actually, the delay varies between 1 frame and 3 frames depending on the particular BIOS.

If you can avoid it, I wouldn't realy on BIOS interrupt handler for reading the input (except for typing text). If you can read a few rows of the keyboard matrix then trick the BIOS interrupt handler to skip it, you'll get a more stable time spent in the interrupt handler, will give you better control of the readings, and will give the player better responsiveness. :)

By ~mk~

Champion (328)

~mk~'s picture

25-02-2023, 21:39

rolandve wrote:
~mk~ wrote:

Not sure I understand the problem with kbhit(). Can you elaborate?
The simplest way to achieve what you describe should be a combination of kbhit() and getch().

getch() doesn't take ctrl/left/right/up and down.

It works with cursor keys.
If you want more complex scan of keyboard I suggest you take a look at snsmat().

By rolandve

Champion (358)

rolandve's picture

14-03-2023, 08:24

~mk~ wrote:
rolandve wrote:
~mk~ wrote:

Not sure I understand the problem with kbhit(). Can you elaborate?
The simplest way to achieve what you describe should be a combination of kbhit() and getch().

getch() doesn't take ctrl/left/right/up and down.

It works with cursor keys.
If you want more complex scan of keyboard I suggest you take a look at snsmat().

I started with polling the keyboard directly, then snsmat and now I wait5 or 6 jiffy's after reading newkey.

By rolandve

Champion (358)

rolandve's picture

14-03-2023, 08:44

Another question: my code is getting long, and regardless of -r, I am running out of space for the compiler.
How do make loose .rel files of my code that I can include during linking.

cf name
cg -k name
m80 =name/z

creates the MAC and REL file. I can include that during linking, but when I declare the function in my main program, (and I know its in the .REL file), the compiler still complains: function NOT found.

By ~mk~

Champion (328)

~mk~'s picture

15-03-2023, 04:38

The compiler needs to know the function exists otherwise it'll complain.
Have you tried adding an empty definition in your main program, e.g. void myFunction(); ?
You can do that, or maybe a better idea, do in a separate .h file and #include in your main program.

By rolandve

Champion (358)

rolandve's picture

15-03-2023, 10:10

~mk~ wrote:

The compiler needs to know the function exists otherwise it'll complain.
Have you tried adding an empty definition in your main program, e.g. void myFunction(); ?
You can do that, or maybe a better idea, do in a separate .h file and #include in your main program.

I pre-defined them all in my code as empty definitions. Even more specific with the correct return types, which are also defined before the empty declarations.

tNode *addNode();
tNode *remNode();

Its about 10 functions to manage linked lists.

Page 66/68
59 | 60 | 61 | 62 | 63 | 64 | 65 | | 67 | 68