Handling events in C
Chris Mahoney (1684) 2165 posts |
Now that I have my Pi up and running again, I’m investigating what’s involved with creating a fairly simple game in C (I have DDE 25). I want to be able to catch keypresses (thinking of the arrow keys at this point although I’ll want more later) and it seems that I can do that with event 11 (page 1-158). Page 1-148 says that “you must first OS_Claim the event vector EventV”. This is my first foray into vectors and I’m having trouble with getting OS_Claim to work. Coincidentally there’s another OS_Claim thread active right now but it’s all in scary assembler :) The first thing I noticed is that unlike, say, OS_Byte or OS_File, there isn’t a C method for OS_Claim in os.h (part of RISC_OSLib). I’ve seen advice to not call SWIs directly so I’m a bit confused about the “proper” way to do this. The documentation for OS_Claim (page 1-66) says that R1 should contain “address of claiming routine that is to be added to vector”. The examples are in BASIC/assembler so I’m not sure exactly how to handle this in C. Here’s what I have so far:
If I compile and run that, then I got the “Got this far” message but when I press Space to close the program I get “Internal error: abort on instruction fetch at &00008084” followed by the entire system freezing to the point that I need to power it off and on (even the mouse pointer doesn’t move). If I run it in DDT then it crashes at the _kernel_swi line with “Error / address exception / data abort in debugger” followed by the contents of the registers (interestingly R0 contains 0×0B at that point, not the 0×10 that I’d expect). The very fact that I’m managing to crash it this spectacularly would indicate that I’m doing something absolutely, completely wrong :) Can anyone advise how to safely OS_Claim a vector from C? Or alternatively, if I’m going down the wrong track, any suggestions on what I should be doing instead to handle key presses? Thanks :) |
Rick Murray (539) 13840 posts |
Some quick observations – sitting in bed with a big cup of tea ‘cos it is holiday time now – you are getting unexpected events because certain events have their own event code, while various others hang all off EventV. You need to examine the data passed via EventV to see if that is the event you want. If so, deal with it, else pass it on. |
Chris Mahoney (1684) 2165 posts |
Aha! You’re right; I do need the OS_Byte 14 call too, but I was just trying to get the OS_Claim working first. Not releasing it might explain it though! It’s now Christmas morning over here so I’m more interested in tearing into presents than digging into code :) so it may be a little while before I try that, but it sounds like a valid point. I also realised after posting that I left another question unasked: How do I make my program “pause” and wait for events? The docs state that Wimp apps will call Wimp_Poll but I’m not sure what to do in a text-mode app. I’ll probably end up putting a Wimp front-end on the thing at some point, but one step at a time… Thanks for the help, and merry Christmas :) |
Chris Mahoney (1684) 2165 posts |
OK, I’ve added an OS_Release (along with calls to OS_Byte 14 and 13 to enable and disable the actual keypress event) and it no longer crashes. However, I still haven’t found any way to issue a “wait for events” in a single-tasking app. Is that even possible? Page 1-65 seems to imply that it’s possible, but it’s open to interpretation. I have no real issue with setting it up in Wimp and using Wimp_Poll, but I’m just trying to keep things simple at this stage. If it’s possible to get it going “as-is” then I’d prefer that for now. |
Chris Mahoney (1684) 2165 posts |
I’ve been taking a look at the source to Hopper (I don’t know why I didn’t think of that earlier) and it’s using OS_Byte 121 (“Keyboard scan”) to detect keypresses. It looks a bit simpler so I think I’ll forget about EventV for now and go down the OS_Byte path instead :) Edit: It seems to use a Wimp keypress event too, but I’ll just keep working through the code and I’m sure that I’ll figure it out now that I have a working example :) |
Steve Fryatt (216) 2105 posts |
Yes, for anything at the application level you don’t want to be sitting on EventV1: that’s “reserved” for things operating at a much lower level. The main problem is that you can’t put your EventV code into application space, as vectors don’t respect the possibility that an application can get paged in and out by the Wimp. The other problem is that you’re down with things that might be “messing around” with the keypresses, and that raises questions about the order in which pieces of code claim the vector. The OS_Byte calls are ideal for a single-tasking application that doesn’t run as part of the Wimp (ie. something that’s written in a “old-fashioned” style). OS_Byte 121 or OS_Byte 129 are probably the calls you need; if you’re using the ones that scan (as opposed to the ones that extract presses from the keyboard buffer, which are less useful for arcade games), remember to flush the keyboard buffer before you pass control back to the Wimp – otherwise all the keypresses will be dumped on the app that happens to own the caret as soon as multitasking resumes. OS_Byte 21 is useful here. If you’re working within the confines of the Wimp, then as you say, reason code 8 from Wimp_Poll(Idle) is what you need. 1 If you do end up using EventV at the application level, then you need to put the event code in the RMA and use pollwords with Wimp_Poll(Idle) to safely pass the keypresses back. Or, at least set up some semaphore arrangement so that the application code in application space can check the state of the RMA code without getting upset if an interrupt occurs while the application is trying to read the state and the EventV code ends up changing that state at the same time. |
Chris Mahoney (1684) 2165 posts |
Thanks for that; nice and informative for a newbie like me :) You’re right about the keyboard buffer not being too useful, indeed having no luck there is what drew me to events in the first place. But as is typical of programming, what I thought I wanted and what I actually wanted ended up being different things. It’s good to know about OS_Byte 21 too as it sounds like I’ll need it! Thanks again :) |
Chris Mahoney (1684) 2165 posts |
Sorry, me again :) I must still be missing something here. I’ve rejigged things to use Wimp/Toolbox/Eventlib and while most things are working, I’m still having trouble with key presses. Here’s the specific line of code (the rest is a fairly simple “skeleton” at this stage but I can supply a more complete example if needed):
If I change Wimp_EKeyPressed to Wimp_EMouseClick then my_handler runs as soon as I click the mouse (so I know that I’m setting it all up correctly). But when I change back to Wimp_EKeyPressed, key presses seem to do nothing. my_handler certainly doesn’t run. Do I need to explicitly enable keyboard input or something? I’ve been through the docs a few times and can’t see anything about how to do this. Does anyone know what I’m missing here? Edit: I should point out that Hopper directly reads the event code returned by Wimp_Poll instead of using Eventlib, but that doesn’t seem to work in a Toolbox app as it apparently always returns a generic “Toolbox event” code (I think it was 255). |
Colin (478) 2433 posts |
Have you set the button type for your window in ResEd, in the window’s main menu → other properties, to 14 – or 15 if you don’t want mouse clicks. If you use ResTest you will see the events the window will return. If that doesn’t work does your window have the input focus – title bar turns yellow. Your window won’t get any keypress events without the input focus. |
Chris Mahoney (1684) 2165 posts |
Setting the button type has fixed it. Thanks; I would never have figured that one out myself :) |