intvnut Posted February 25, 2012 Share Posted February 25, 2012 By the way, the build tools are available in Cygwin. In any case, you can get the free Active Perl. I've sometimes had problems with Cygwin. Their whole "cygdrive" fiction, trying to transform Windows paths into Unix paths and flipping slashes around really messes things up. Dunno if they've stopped doing that, but that was the reason I left Cygwin. That said, I have plenty of happy coworkers, so maybe the problem's just me. The ActiveState Perl is what I use. It worked first-time with this script. It may not be the world's sexiest build script, but it gets the job done. Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 25, 2012 Share Posted February 25, 2012 Oops, one tiny, tiny bug crept in. In "build.pl", delete this line (near the end of the file): binmode($cfh); That's not supposed to be there. The only real effect it has is to generate a .cfg file with *nix-style newlines instead of Windows-style on a Windows machine. jzIntv doesn't care, but notepad does. **shrug** Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 25, 2012 Share Posted February 25, 2012 (edited) By the way, the build tools are available in Cygwin. In any case, you can get the free Active Perl. I've sometimes had problems with Cygwin. Their whole "cygdrive" fiction, trying to transform Windows paths into Unix paths and flipping slashes around really messes things up. Dunno if they've stopped doing that, but that was the reason I left Cygwin. That said, I have plenty of happy coworkers, so maybe the problem's just me. The ActiveState Perl is what I use. It worked first-time with this script. It may not be the world's sexiest build script, but it gets the job done. Cygwin still does that. "/drives/c/program\ files/". Yup, it's rather silly. I avoid any problems by "thinking UNIX" when using Cygwin, and not interacting with any Windows-ish parts. In essence, just rooting somewhere off the C:\ drive. I also set up symlinks and environment variables to my common directories so that I don't have to remember, is it "c:/" or "/drives/c/" or "/mnt/drives/c/"? -dZ. Edited February 25, 2012 by DZ-Jay Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 25, 2012 Share Posted February 25, 2012 (edited) Cygwin still does that. "/drives/c/program\ files/". Yup, it's rather silly. I avoid any problems by "thinking UNIX" when using Cygwin, and not interacting with any Windows-ish parts. In essence, just rooting somewhere off the C:\ drive. I also set up symlinks and environment variables to my common directories so that I don't have to remember, is it "c:/" or "/drives/c/" or "/mnt/drives/c/"? Yuck. :-) You know, it wasn't too much of a problem for me, actually. But, when I was building jzIntv with Cygwin, explaining to people how to tell jzIntv where to find their games made me feel like a certain textile-challenged emperor. As it is, the command line already turns a few people off. The cygdrive thing, though, would be enough for many folk to argue jzIntv didn't actually have a Windows port, but rather was a Unix program that happens to run in Windows somehow, which isn't the case at all. Anyway... getting a little off topic. The new perl build script at least limits the dependencies to one program that has a solid Windows port and is easy to install. If we end up needing more build shenanigans, we can fold it into that perl script. Edited February 25, 2012 by intvnut Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 26, 2012 Share Posted February 26, 2012 Ok, just a minor update. I added some word-wrapping logic (which makes the screen much more readable) and a *More* facility to pause after each screenful. Both make it much easier to playtest. I also added the build.pl fix, and renamed 26K to 34K as it should be. adv5_for_inty.zip Quote Link to comment Share on other sites More sharing options...
vprette Posted February 27, 2012 Author Share Posted February 27, 2012 Ok, just a minor update. I added some word-wrapping logic (which makes the screen much more readable) and a *More* facility to pause after each screenful. Both make it much easier to playtest. I also added the build.pl fix, and renamed 26K to 34K as it should be. Hello if I see right, the text now is organised to never cut the words between two rows, right? this is very good.... In fact, to move your code into my scheleton seems very complex for me.... so I may consider keeping my code from title to intro and hidden novel up to level 1 when your code will take place..... to do this and keep my original screen layout, I need to: 1 - reintroduce the custom font 2 - skip the initial message with request for instruction (those are exaclty the same written in the manual) 3 - use the circle/arrow instead of "more" as indicating the text will continue. When 2 pages need to be shown because of a very long text, there will be 2 yellow arrows 4 - handle the command from controller (8 direction + up/down + pause music) in whic .asm I have to deep to make those changes? 1 -> "ansi.asm"? 2 -> ? 3 -> ? 4 -> ? Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 27, 2012 Share Posted February 27, 2012 Ok, just a minor update. I added some word-wrapping logic (which makes the screen much more readable) and a *More* facility to pause after each screenful. Both make it much easier to playtest. I also added the build.pl fix, and renamed 26K to 34K as it should be. Hello if I see right, the text now is organised to never cut the words between two rows, right? this is very good.... In fact, to move your code into my scheleton seems very complex for me.... so I may consider keeping my code from title to intro and hidden novel up to level 1 when your code will take place..... to do this and keep my original screen layout, I need to: 1 - reintroduce the custom font 2 - skip the initial message with request for instruction (those are exaclty the same written in the manual) 3 - use the circle/arrow instead of "more" as indicating the text will continue. When 2 pages need to be shown because of a very long text, there will be 2 yellow arrows 4 - handle the command from controller (8 direction + up/down + pause music) in whic .asm I have to deep to make those changes? 1 -> "ansi.asm"? 2 -> ? 3 -> ? 4 -> ? Ok, let's wade through all this. First off, I figure you'd just completely replace ansi.asm with something to handle output differently. I just used it as a quick and dirty starting point because I had it handy. All text output eventually goes through "putchar", and that's defined in puts.asm. Whatever output mechanism you define, you'd hook it up there. For example, one idea would be to have it print everything to a virtual "frame buffer" in memory, and then you could use the disc to scroll around. That code would also handle the "more" facility and so on. The best strategy would be to slurp up all input to this off-screen buffer until the game gets to a point where it's waiting for input, and then your display code takes over presenting it to the player. All of the display update and such would then be handled by tasks you hang off of P Machinery. You hook the two together through putchar. Changing the font over happens "automagically" when you replace ansi.asm with your own code. :-) User input currently comes in at two places: getline.asm and more.asm. The second one, "more.asm", would go away once you have the more sophisticated output display. "getline" is where you know the engine has switched from output to input mode. When the game reaches getline, you can let the user page through the display, scrolling up and down if they like. This is also where you'd inject keystrokes for commands triggered from the controller keypad. I would suggest removing the call to SCAN_ECS from getline, and change it to a more generic "getkey" function. Have a separate P Machinery task scan the keyboard into an input buffer that getkey consults. If someone hits the controller disc, you can flush the keyboard buffer and replace it with the user's command. Also insert an "ESC" at the start of a controller-triggered command if it's a verb, and that will cause getline to back out anything else the user has typed. (Try it -- ESC already does this actually.) Something like this (untested): typeahead EQU 20 BYTEARRAY kb, typeahead ;; allow some typeahead BYTEVAR kb.head ;; first char to return to player BYTEVAR kb.tail ;; most recently queued keystroke ;; ======================================================================== ;; ;; GETKEY Read the next key of input from the player. ;; ;; ======================================================================== ;; getkey PROC PSHR R5 ; Wait for a key to show up. @@wait: ;CALL yield ; allow time slicing properly MVI kb.head, R1 CMP kb.tail, R1 BEQ @@wait INCR R1 ; consume keystroke CMPI #typeahead, R1 ; wrap around end of buffer BLT @@no_wrap CLRR R1 @@no_wrap MVO R1, kb.head ADDI #kb, R1 MVI@ R1, R0 ; get keystroke PULR PC ENDP ;; ======================================================================== ;; ;; FLUSHK Flush the keyboard buffer ;; ;; ======================================================================== ;; flushk PROC CLRR R0 MVO R0, kb.head MVO R0, kb.tail JR R5 ENDP ;; ======================================================================== ;; ;; PUTKEY Put a keystroke into the keyboard buffer. ;; ;; ======================================================================== ;; putkey PROC ; Is there room? MVI kb.tail, R1 SUB kb.head, R1 BPL @@no_wrap1 ADDI #typeahead, R1 ; handle tail-wrap @@no_wrap1 CMPI #typeahead, R1 BGE @@leave ; no room MVI kb.tail, R1 INCR R1 CMPI #typeahead, R1 BLT @@no_wrap2 CLRR R1 @@no_wrap2 MVO R1, kb.tail ; Make room for keystroke ADDI #kb, R1 MVO@ R0, R1 ; put in keystroke @@leave JR R5 ENDP ;; ======================================================================== ;; ;; KEYSCAN Keyboard scanning task ;; ;; ======================================================================== ;; keyscan PROC PSHR R5 CALL SCAN_KBD CMPI #KEY.NONE, R0 BEQ @@no_key PULR R5 B putkey ; queue the keystroke @@nokey PULR PC ENDP ;; ======================================================================== ;; ;; KEYPAD Handle numeric keys on controller keypad. ;; ;; This function goes in the controller dispatch table. ;; ;; ======================================================================== ;; keypad PROC ANDI #$FF, R2 ; ignore controller number CMPI #$80, R2 ; ignore key release events BLT @@press JR R5 @@press: PSHR R5 MOVR R2, R1 ADDI #@@cmdptr, R1 ; Command string pointer table MVI@ R1, R4 ; Is it a 'macro'? TSTR R4 BNEQ @@do_macro ; put code here to process R1 if it isn't a macro command ; ie. pause/unpause music, etc. @@done: PULR PC @@do_macro: CALL flushk ; flush queued keystrokes MVII #KEY.ESC, R0 CALL putkey ; queue an ESC to flush getline @@keyloop: MVI@ R4, R0 TSTR R0 BEQ @@done CALL putkey B @@keyloop ; 0 @@cmdptr DECLE @@look; ; 1 2 3 DECLE @@get, @@n, @@drop ; 4 5 6 DECLE @@w, @@out, @@e ; 7 8 9 DECLE 0, @@s, 0 ; 7 and 9 -- leave open? ; C E DECLE 0, 0 ; C and E -- leave open? @@look: STRING "look", $A, 0 @@get: STRING "get ", 0 @@n: STRING "north", $A, 0 @@drop: STRING "drop ", 0 @@w: STRING "west", $A, 0 @@out: STRING "out", $A, 0 @@e: STRING "east", $A, 0 @@s: STRING "south", $A, 0 ENDP That integrates the two input streams into one. Then in getline, instead of calling SCAN_ECS, you just call getkey: CALL SCAN_KBD CMPI #KEY.NONE, R0 BEQ @@loop becomes CALL getkey The initial welcome message gets triggered by this code in adv.asm: MVII #INITIAL, R0 CALL process @@forever: MVII #REPEAT, R0 CALL process B @@forever That part gets replaced entirely when you pull everything into your framework. The adv.asm file needs to go away--it's just a placeholder since I didn't build this directly on P Machinery. This loop should become a P Machinery task of sorts when you're in the "in game" state: @@forever: MVII #REPEAT, R0 CALL process B @@forever Got all that? getkey.asm Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 27, 2012 Share Posted February 27, 2012 Attached is a quick stab at an ansi.asm replacement. It also defines control characters 16 thru 31 to change foreground colors. You'd call 'refresh' from an interrupt context to keep the display refreshed. I haven't tested this code -- I don't even know if it assembles correctly -- but I thought I'd at least get this stab down in writing. To integrate it w/ CC, you'd delete the 'putchar' function from puts.asm. Also, you need to change all references to A_r and A_c in the code to vfb.r and vfb.c. The 'more' functionality will be broken for now, but that can be fixed later. The main idea of this code is that you can scroll the screen by simply updating vfb.tos and setting vfb.do_refr. The next frame, the screen will scroll to the new line. So, you can write your disc handler to manipulate the scroll position, and allow the player to scroll back through several pages of text. (Right now I've set it to 64 lines, which is just over 5 screenfuls of text.) This should fit comfortably in JLP RAM alongside the other buffers. vfb.asm Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 28, 2012 Share Posted February 28, 2012 (edited) Just a quick bit of status from my end: I've updated the engine to "yield" periodically while running as a self-triggering task via RUNQ, and have converted it to use the VFB approach for text instead of the ANSI interpreter. The "more" functionality is absent in this version, but we can add it back later. At this point, I probably need to start integrating it with P Machinery. The core engine is pretty much ready for that now. EDIT: Valter, if you send me the code you have, I can try integrating mine with yours and sending you back the result. You can email it to me or PM me if you prefer not to post it here. adv5_intv.zip Edited February 28, 2012 by intvnut Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 28, 2012 Share Posted February 28, 2012 Just a quick bit of status from my end: I've updated the engine to "yield" periodically while running as a self-triggering task via RUNQ, and have converted it to use the VFB approach for text instead of the ANSI interpreter. The "more" functionality is absent in this version, but we can add it back later. At this point, I probably need to start integrating it with P Machinery. The core engine is pretty much ready for that now. EDIT: Valter, if you send me the code you have, I can try integrating mine with yours and sending you back the result. You can email it to me or PM me if you prefer not to post it here. I'm sorry I haven't been able to help much with the integration, I've been busy with many things at the same time and I haven't even had the chance of running your engine. Joe, let me know if you have any questions regarding P-Machinery, of if I can help in any way. -dZ. Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 28, 2012 Share Posted February 28, 2012 BTW, one nifty feature that comes with the latest code drop above is "typeahead": You can continue to type while the engine "thinks", and it'll buffer up to 20 keystrokes. The code uses a (bugfixed) version of the getkey code I posted earlier. Once it drops into P Machinery and we hook up a controller scanner, then getkey can return keystrokes from both the hand controller and the ECS keyboard as one unified input stream. Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 28, 2012 Share Posted February 28, 2012 I'm sorry I haven't been able to help much with the integration, I've been busy with many things at the same time and I haven't even had the chance of running your engine. Joe, let me know if you have any questions regarding P-Machinery, of if I can help in any way. Sure thing, and I understand. I believe Valter has already been hanging some code off of P-Machinery, so I'd like to start with whatever he has. I downloaded a version from the other thread, but I think I should set to modifying whatever Valter already has to avoid further integration issues. One thing I did run into: I can't just trivially get rid of the introduction screen. We'll have to modify the actual game database (the .d files), since all the variable initialization occurs in the same execution stream that prints out the welcome message. Either that, or I'll have to run the init once, capture the memory image, and bypass the intro that way. That may actually be better, since it'll speed up "boot". Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 28, 2012 Share Posted February 28, 2012 Joe, Does your engine include its own keyboard input processor, or were you expecting to hook it up to P-Machinery? P-Machinery offers hooks for input processors. They just need to be defined in the state dispatch table, and that's all. My intention was to create a generic getKey() keyboard handler that reads the keyboard input, and then a keyboard input processor which is just a wrapper to it with the purpose of triggering key-down and key-up events. A similar architecture exists for the game controllers in P-Machinery, where there's an internal "getKey()" function that handles de-bouncing and de-noising the input signal; and individual input processors that wrap around it, decode the results, and trigger the appropriate events. However, for this game perhaps it'll be easier to just ignore the future re-use of this architecture and write an all-in-one input processor for your getKey() function that will handle the buffer and all. -dZ. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 28, 2012 Share Posted February 28, 2012 (edited) Once it drops into P Machinery and we hook up a controller scanner, then getkey can return keystrokes from both the hand controller and the ECS keyboard as one unified input stream. The architecture in P-Machinery is similar to your SCANHAND routine, in that it decodes the input and triggers events. The event handlers are the game-specific parts, which in this case should be the ones handling the buffer. This allows for other applications using the keyboard without buffering. Then for this input processor you'll have events for: Keypad Action buttons Disc ECS Keyboard Edited February 28, 2012 by DZ-Jay Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 28, 2012 Share Posted February 28, 2012 Joe, Does your engine include its own keyboard input processor, or were you expecting to hook it up to P-Machinery? P-Machinery offers hooks for input processors. They just need to be defined in the state dispatch table, and that's all. My intention was to create a generic getKey() keyboard handler that reads the keyboard input, and then a keyboard input processor which is just a wrapper to it with the purpose of triggering key-down and key-up events. A similar architecture exists for the game controllers in P-Machinery, where there's an internal "getKey()" function that handles de-bouncing and de-noising the input signal; and individual input processors that wrap around it, decode the results, and trigger the appropriate events. However, for this game perhaps it'll be easier to just ignore the future re-use of this architecture and write an all-in-one input processor for your getKey() function that will handle the buffer and all. -dZ. dZ, For the ECS keyboard, I'm expecting something to call "keyscan" periodically to scan the ECS keyboard and drop keystrokes into my typeahead buffer. The rest of the game calls "getkey" which consumes from that buffer. (I also just modified getkey to pump keyscan if the keyboard buffer is empty.) I'd suggest keyscan get called, say, once per frame. In my simple driver program (adv.asm), I just call it from the ISR. For controller input, I'm expecting something else to call a controller scanner and do decode/dispatch, like I've done in the past with SCANHAND / QTASK. For controller events that translate into keystrokes, I've written (and posted upthread) code that receives those events and expands them into the typeahead buffer. That particular handler expects SCANHAND-style events, but it can be adapted to whatever controller scanner you like. The main thing is that it wants to be called when it sees a keypad key that it has to process. Colossal Cave doesn't need keydown/keyup, just keydown. (I figure autorepeat isn't really useful in this game.) So if your input processor framework just calls keyscan, that's sufficient. The keystrokes, though, won't generate events into the event queue. Rather, they go straight to my typeahead buffer. For reference, here's all the keyboard logic. SCAN_KBD is the keyboard scanner I posted on the ECS keyboard tutorial. typeahead EQU 20 BYTEARRAY kb, typeahead ;; allow some typeahead BYTEVAR kb.head ;; first char to return to player BYTEVAR kb.tail ;; most recently queued keystroke ;; ======================================================================== ;; ;; GETKEY Read the next key of input from the player. ;; ;; ======================================================================== ;; getkey PROC PSHR R5 ; Wait for a key to show up. B @@first @@wait: CALL yield ; allow time slicing properly CALL keyscan ; why not? @@first: MVI kb.head, R1 CMP kb.tail, R1 BEQ @@wait INCR R1 ; consume keystroke CMPI #typeahead, R1 ; wrap around end of buffer BLT @@no_wrap CLRR R1 @@no_wrap MVO R1, kb.head ADDI #kb, R1 MVI@ R1, R0 ; get keystroke PULR PC ENDP ;; ======================================================================== ;; ;; FLUSHK Flush the keyboard buffer ;; ;; ======================================================================== ;; flushk PROC CLRR R0 MVO R0, kb.head MVO R0, kb.tail JR R5 ENDP ;; ======================================================================== ;; ;; PUTKEY Put a keystroke into the keyboard buffer. ;; ;; ======================================================================== ;; putkey PROC ; Is there room? MVI kb.tail, R1 SUB kb.head, R1 BPL @@no_wrap1 ADDI #typeahead, R1 ; handle tail-wrap @@no_wrap1 CMPI #typeahead, R1 BGE @@leave ; no room MVI kb.tail, R1 INCR R1 CMPI #typeahead, R1 BLT @@no_wrap2 CLRR R1 @@no_wrap2 MVO R1, kb.tail ; Make room for keystroke ADDI #kb, R1 MVO@ R0, R1 ; put in keystroke @@leave JR R5 ENDP ;; ======================================================================== ;; ;; KEYSCAN Keyboard scanning task ;; ;; ======================================================================== ;; keyscan PROC PSHR R5 CALL SCAN_KBD CMPI #KEY.NONE, R0 BEQ @@no_key PULR R5 B putkey ; queue the keystroke @@no_key PULR PC ENDP And here's the event handler that converts controller input to a sequence of keystrokes, which I called a "macro" below. My expectation was that whatever decodes the controller would eventually dispatch to this to handle keypad events. ;; ======================================================================== ;; ;; KEYPAD Handle numeric keys on controller keypad. ;; ;; This function goes in the controller dispatch table. ;; ;; ======================================================================== ;; keypad PROC ANDI #$FF, R2 ; ignore controller number CMPI #$80, R2 ; ignore key release events BLT @@press JR R5 @@press: PSHR R5 MOVR R2, R1 ADDI #@@cmdptr, R1 ; Command string pointer table MVI@ R1, R4 ; Is it a 'macro'? TSTR R4 BNEQ @@do_macro ; put code here to process R1 if it isn't a macro command ; ie. pause/unpause music, etc. @@done: PULR PC @@do_macro: CALL flushk ; flush queued keystrokes MVII #KEY.ESC, R0 CALL putkey ; queue an ESC to flush getline @@keyloop: MVI@ R4, R0 TSTR R0 BEQ @@done CALL putkey B @@keyloop ; 0 @@cmdptr DECLE @@look; ; 1 2 3 DECLE @@get, @@n, @@drop ; 4 5 6 DECLE @@w, @@out, @@e ; 7 8 9 DECLE 0, @@s, 0 ; 7 and 9 -- leave open? ; C E DECLE 0, 0 ; C and E -- leave open? @@look: STRING "look", $A, 0 @@get: STRING "get ", 0 @@n: STRING "north", $A, 0 @@drop: STRING "drop ", 0 @@w: STRING "west", $A, 0 @@out: STRING "out", $A, 0 @@e: STRING "east", $A, 0 @@s: STRING "south", $A, 0 ENDP Speaking of macros, we could add macros on the ECS keyboard side too. If you see CTRL+letter, it's pretty easy to expand that out into a word, which might make typing common verbs a little nicer. Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 28, 2012 Share Posted February 28, 2012 (edited) Once it drops into P Machinery and we hook up a controller scanner, then getkey can return keystrokes from both the hand controller and the ECS keyboard as one unified input stream. The architecture in P-Machinery is similar to your SCANHAND routine, in that it decodes the input and triggers events. The event handlers are the game-specific parts, which in this case should be the ones handling the buffer. This allows for other applications using the keyboard without buffering. Then for this input processor you'll have events for: Keypad Action buttons Disc ECS Keyboard It wouldn't be hard to replace my keyscan with your ECS keyboard event generator. Just have the event handler call "putkey" for each keydown event. Edited February 28, 2012 by intvnut Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 28, 2012 Share Posted February 28, 2012 Once it drops into P Machinery and we hook up a controller scanner, then getkey can return keystrokes from both the hand controller and the ECS keyboard as one unified input stream. The architecture in P-Machinery is similar to your SCANHAND routine, in that it decodes the input and triggers events. The event handlers are the game-specific parts, which in this case should be the ones handling the buffer. This allows for other applications using the keyboard without buffering. Then for this input processor you'll have events for: Keypad Action buttons Disc ECS Keyboard It wouldn't be hard to replace my keyscan with your ECS keyboard event generator. Just have the event handler call "putkey" for each keydown event. In fact, it would look almost identical to the keypad handler I posted above. It could sort keystrokes into "macro" and "not macro", even. You might even be able to merge them into one function that handles both, just with two entry points so that you can shift the event number ranges. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 28, 2012 Share Posted February 28, 2012 Once it drops into P Machinery and we hook up a controller scanner, then getkey can return keystrokes from both the hand controller and the ECS keyboard as one unified input stream. The architecture in P-Machinery is similar to your SCANHAND routine, in that it decodes the input and triggers events. The event handlers are the game-specific parts, which in this case should be the ones handling the buffer. This allows for other applications using the keyboard without buffering. Then for this input processor you'll have events for: Keypad Action buttons Disc ECS Keyboard It wouldn't be hard to replace my keyscan with your ECS keyboard event generator. Just have the event handler call "putkey" for each keydown event. I guess I'm muddling the waters by using terms that collide with yours. Your "getkey" function is the one that fetches from the buffer, right? My "getkey" function (which I admit is probably a misnomer) is the one that polls the controller. In your scenario, it'll also write into the typeahead buffer, so it would be your "keyscan" routine. If I understand your approach, the controller model should be different from the keyboard model, because both use cases are different. The former is event based, and the latter depends on a typeahead buffer that needs to get read (and thus, flushed) by the game periodically. Is this right? -dZ. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 28, 2012 Share Posted February 28, 2012 For the ECS keyboard, I'm expecting something to call "keyscan" periodically to scan the ECS keyboard and drop keystrokes into my typeahead buffer. The rest of the game calls "getkey" which consumes from that buffer. (I also just modified getkey to pump keyscan if the keyboard buffer is empty.) I'd suggest keyscan get called, say, once per frame. In my simple driver program (adv.asm), I just call it from the ISR. Just a note on this: By default, P-Machinery calls the assigned input processor for the current state on the "idle" task (when the queue is empty). When I say "by default," I mean that's how it was written. Since the game loop is intended to run once per ISR, this resulted in at least 60 Hz resolution in the worse case scenario, and a much higher resolution in the normal cases. For twitchy arcade games like Pac-Man and Christmas Carol, this was a good thing. I don't expect it should be such a big deal to change this to call the input processor at the end of the game loop from the ISR. -dZ. Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 28, 2012 Share Posted February 28, 2012 It wouldn't be hard to replace my keyscan with your ECS keyboard event generator. Just have the event handler call "putkey" for each keydown event. I guess I'm muddling the waters by using terms that collide with yours. Your "getkey" function is the one that fetches from the buffer, right? My "getkey" function (which I admit is probably a misnomer) is the one that polls the controller. In your scenario, it'll also write into the typeahead buffer, so it would be your "keyscan" routine. If I understand your approach, the controller model should be different from the keyboard model, because both use cases are different. The former is event based, and the latter depends on a typeahead buffer that needs to get read (and thus, flushed) by the game periodically. Is this right? It's not hard to adapt to the event-based model. It is, in effect, what I have now, I've just short circuited the event queue. If you've already got an input event generator, then the keydown event handler for both the controller keypad and the ECS keyboard are pretty much identical. Both will (usually) result in one or more calls to "putkey" to insert keystrokes into my typeahead buffer. I say "usually" because Valter does want to use certain keypad inputs for non-keystroke things, but that's OK. We may even want ECS keyboard bindings for special actions too. So really, the use model for both the keypad and keyboard are more similar than different. So yeah, you can replace keyscan with whatever you had in mind for ECS keyboard scanning, and just register a keyboard event handler which looks almost identical (and may even share 99% of the code with) the keypad event handler I have above. Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 28, 2012 Share Posted February 28, 2012 For the ECS keyboard, I'm expecting something to call "keyscan" periodically to scan the ECS keyboard and drop keystrokes into my typeahead buffer. The rest of the game calls "getkey" which consumes from that buffer. (I also just modified getkey to pump keyscan if the keyboard buffer is empty.) I'd suggest keyscan get called, say, once per frame. In my simple driver program (adv.asm), I just call it from the ISR. Just a note on this: By default, P-Machinery calls the assigned input processor for the current state on the "idle" task (when the queue is empty). When I say "by default," I mean that's how it was written. Since the game loop is intended to run once per ISR, this resulted in at least 60 Hz resolution in the worse case scenario, and a much higher resolution in the normal cases. For twitchy arcade games like Pac-Man and Christmas Carol, this was a good thing. I don't expect it should be such a big deal to change this to call the input processor at the end of the game loop from the ISR. -dZ. One downside of the "yield" strategy is that the task queue is never actually empty, since it always immediately queues a "resume" task before returning to RUNQ. I guess a yield should also trigger the idle tasks to run? That should be easy enough. Instead of returning to RUNQ.loop, it can return to RUNQ.bktsk. Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 28, 2012 Share Posted February 28, 2012 For the ECS keyboard, I'm expecting something to call "keyscan" periodically to scan the ECS keyboard and drop keystrokes into my typeahead buffer. The rest of the game calls "getkey" which consumes from that buffer. (I also just modified getkey to pump keyscan if the keyboard buffer is empty.) I'd suggest keyscan get called, say, once per frame. In my simple driver program (adv.asm), I just call it from the ISR. Just a note on this: By default, P-Machinery calls the assigned input processor for the current state on the "idle" task (when the queue is empty). When I say "by default," I mean that's how it was written. Since the game loop is intended to run once per ISR, this resulted in at least 60 Hz resolution in the worse case scenario, and a much higher resolution in the normal cases. For twitchy arcade games like Pac-Man and Christmas Carol, this was a good thing. I don't expect it should be such a big deal to change this to call the input processor at the end of the game loop from the ISR. -dZ. One downside of the "yield" strategy is that the task queue is never actually empty, since it always immediately queues a "resume" task before returning to RUNQ. I guess a yield should also trigger the idle tasks to run? That should be easy enough. Instead of returning to RUNQ.loop, it can return to RUNQ.bktsk. Of course, if I do that, I'll have to take this out of yield: MVI TSKQHD, R0 CMP TSKQTL, R0 BNEQ @@doit JR R5 That short-circuits the yield if no other task has been queued. See, while 'process' is running, the queue will be empty, sure, but it always re-queues itself before returnning, so RUNQ never sees the queue empty. :-) Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 28, 2012 Share Posted February 28, 2012 For the ECS keyboard, I'm expecting something to call "keyscan" periodically to scan the ECS keyboard and drop keystrokes into my typeahead buffer. The rest of the game calls "getkey" which consumes from that buffer. (I also just modified getkey to pump keyscan if the keyboard buffer is empty.) I'd suggest keyscan get called, say, once per frame. In my simple driver program (adv.asm), I just call it from the ISR. Just a note on this: By default, P-Machinery calls the assigned input processor for the current state on the "idle" task (when the queue is empty). When I say "by default," I mean that's how it was written. Since the game loop is intended to run once per ISR, this resulted in at least 60 Hz resolution in the worse case scenario, and a much higher resolution in the normal cases. For twitchy arcade games like Pac-Man and Christmas Carol, this was a good thing. I don't expect it should be such a big deal to change this to call the input processor at the end of the game loop from the ISR. -dZ. One downside of the "yield" strategy is that the task queue is never actually empty, since it always immediately queues a "resume" task before returning to RUNQ. I guess a yield should also trigger the idle tasks to run? That should be easy enough. Instead of returning to RUNQ.loop, it can return to RUNQ.bktsk. Of course, if I do that, I'll have to take this out of yield: MVI TSKQHD, R0 CMP TSKQTL, R0 BNEQ @@doit JR R5 That short-circuits the yield if no other task has been queued. See, while 'process' is running, the queue will be empty, sure, but it always re-queues itself before returnning, so RUNQ never sees the queue empty. :-) I get it. The queue is not really empty from the RUNQ perspective, but yield calls the idle task before queueing itself. I wonder if it'll be better if P-Machinery were to just queue the input processor at the bottom of the state ISR, like it does with DOTIMER()... Your thoughts? Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 28, 2012 Share Posted February 28, 2012 Ok... minor update to the code, and a neat GIF. adv5_intv.zip 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 28, 2012 Share Posted February 28, 2012 Ok... minor update to the code, and a neat GIF. Wow! NIFTY INDEED! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.