CC65/C: Ensure joystick press is registered only once

Since we do not have native C compilers on the Oric, this forum will be mostly be used by people using CC65 or the OSDK. But any general C related post will be welcome !
User avatar
xahmol
Flight Lieutenant
Posts: 437
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

CC65/C: Ensure joystick press is registered only once

Post by xahmol »

My rewrite of my Ludo game in C using CC65 is almost done. See attached disk image:
LUDO.dsk
(131.5 KiB) Downloaded 216 times
Source

UPDATE: Issue solved with workaround, see below.

I have only one issue left, and that is getting to make the joystick routine work properly.

TL;DR: How to avoid the joystick registring more than once on one joystick move or fire press?

I settled on the IJK library from ISS' openOricLibrary as I found that one to be the easiest to implement. Also, porting the OSDK lib for joystick support from Dbug to CC65 was looking way more difficult as I have no clue how to do IRQ handlers in CC65.

Good news: the IJK routines work perfectly testing in Oricutron with the keyboard emulation on the keypad for joy1 (do not have controllers or joysticks on the PC yet).
Bad news: if I test on real hardware with the IJK joystick interface from Raxiss, every joystick move is registered many times, making navigation trough the menus virtually impossible.

Any way to solve that?
I already did implement code to wait until the joystick is neutral again (until doing so I had the issue in Oricutron as well). That works in Oricutron, but not on real hardware. No clue why.

My present code:

Code: Select all

unsigned char getkey(unsigned char* allowedkeys, unsigned char joyallowed)
{
    /* Function to wait on valid key or joystick press/move
       Input: allowedkeys = string with valid key press options
       Output: key value (or joystick converted to key value)    */

    unsigned char key;

    do
    {
        key = 0;
        if(joyinterface && joyallowed)
        {
            ijk_read();
            if(ijk_ljoy&4) { key = C_ENTER; }
            if(ijk_ljoy&1) { key = C_RIGHT; }
            if(ijk_ljoy&2) { key = C_LEFT; }
            if(ijk_ljoy&8) { key = C_DOWN; }
            if(ijk_ljoy&16) { key = C_UP; }
            if(ijk_rjoy&4) { key = C_ENTER; }
            if(ijk_rjoy&1) { key = C_RIGHT; }
            if(ijk_rjoy&2) { key = C_LEFT; }
            if(ijk_rjoy&8) { key = C_DOWN; }
            if(ijk_rjoy&16) { key = C_UP; }
            if(key){
                do
                {
                   ijk_read();
                } while (ijk_ljoy || ijk_rjoy);
            }
        }
        if(key == 0)
        {
            if(kbhit()) { key = cgetc();}
        }
    } while (strchr(allowedkeys, key)==0 || key == 0);
    return key;
}
Where this part above is the part that waits for the joystock to get neutral:

Code: Select all

do
                {
                   ijk_read();
                } while (ijk_ljoy || ijk_rjoy);
Apart from that: the game should be fully playable now. Over here, apart from the joystick, everything works now including save game file operations to Sedoric (using the openOricLibrary from Iss again) and music (in the end used the MYM player routine that the 8Bit Unity library adapted from the original routine in OSDK from DBug). Any feedback besides the joystick part is also appreciated!
Last edited by xahmol on Wed Feb 24, 2021 11:44 am, edited 6 times in total.
User avatar
xahmol
Flight Lieutenant
Posts: 437
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: CC65/C: Ensure joystick press is registered only once

Post by xahmol »

By the way: in the last version of my BASIC implementation of this game I also used the same Raxiss IJK routine with basically the same key and joystick polling routine logic in BASIC. Did not have any issue on real hardware then, probably because BASIC is so slow that the routine is not polled again before the joystick is neutral again.
So apparently the speed of C is the ‘problem’ here. So would some kind of a wait routine do the trick without making the responsiveness very bad?
User avatar
Dbug
Site Admin
Posts: 4437
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: CC65/C: Ensure joystick press is registered only once

Post by Dbug »

You need to debounce:

Basically, key presses, as given by the ROM are single events, even if the key stayed pressed, then it auto-repeats: This is done for you by the system.
If you were reading the keyboard matrix directly, you would have the same issue as you currently have with the joystick, basically you need to keep the previous value of the joystick, and only register the impulse if the value changes (in your case, from "not pressed" to "pressed").
User avatar
xahmol
Flight Lieutenant
Posts: 437
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: CC65/C: Ensure joystick press is registered only once

Post by xahmol »

Well, I think I understand you, but why does then the while loop to wait until the joystick reads neutral again not do the trick? That waits for the joystick reading to come from anything before to zero again.
(and why does it work in Oricutron and not on real hardware)?
User avatar
xahmol
Flight Lieutenant
Posts: 437
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: CC65/C: Ensure joystick press is registered only once

Post by xahmol »

Update: actually adding a wait of 10 cycles did do the trick....

Code: Select all

do
{
   ijk_read();
} while (ijk_ljoy || ijk_rjoy);
wait(10);
Where wait() is:

Code: Select all

void wait(unsigned int wait_cycles)
 {
    /* Function to wait for the specified number of cycles
       Input: wait_cycles = numnber of cycles to wait       */

    unsigned int starttime = clock();
    while (clock() - starttime < wait_cycles);
}
Just still do not understand why the wait() is needed. So any insight still is appreciated!

Updated the DSK at the start by the way by the version that now works here.
Full source code here: https://github.com/xahmol/ludo/tree/mai ... Atmos/CC65
User avatar
Dbug
Site Admin
Posts: 4437
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: CC65/C: Ensure joystick press is registered only once

Post by Dbug »

The IJK interface is designed to use a fancy bit of capacitor that loads during the off-time so it can do magic to enable the transistors while reading the values.

It may simply be that fast looping like that just makes it not work anymore, I don't think it's supposed to be accessed more than one per frame really.
User avatar
jbperin
Flight Lieutenant
Posts: 480
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: CC65/C: Ensure joystick press is registered only once

Post by jbperin »

xahmol wrote: Tue Feb 23, 2021 1:54 pm Full source code here: https://github.com/xahmol/ludo/tree/mai ... Atmos/CC65
Super mega cool !!

Thank you xahmol for sharing this game and its source.

I had already played the basic version and it seems to me that this one is a somewhat more responsive.

I casted a quick glance at the source code and I noticed various things that I can learn from it:
- How to deal with joystick (there are already some nice documentaiton on it but a working exemple often worth thousand of tutorials)
- How to load and save data (I haven't even thought it was possible :-))
- How to create big DSK game from several TAP file (I wonder if I can use that to embed more texture than what can fit in the RAM).

So I congratulate you for this work and I thank you for sharing your source code because it can help other people to progress.
User avatar
xahmol
Flight Lieutenant
Posts: 437
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: CC65/C: Ensure joystick press is registered only once

Post by xahmol »

jbperin wrote: Tue Feb 23, 2021 2:37 pm So I congratulate you for this work and I thank you for sharing your source code because it can help other people to progress.
Thanks!
Please note that over here I presently have a hybrid setup of CC65 working under Windows Subsystem for Linux with OSDK working under Windows.
So that is why I have MAKE files for the CC65 part and .bat files for the OSDK part. To do is to integrate that in one workflow somehow (probably by using the Windows version of CC65, as I do not think running OSDK under Wine under WSL makes sense if it even works.....)

Choose my CC65 setup under WSL as on the Commodore 128 I worked on a project build with Linux tools and was too lazy to redo everything in batch scripts for Windows (and I do like MAKE).

And I did not clean the repo yet of stuff I tried but choose not to use (especially in the include dir).
User avatar
jbperin
Flight Lieutenant
Posts: 480
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: CC65/C: Ensure joystick press is registered only once

Post by jbperin »

xahmol wrote: Tue Feb 23, 2021 2:43 pm
Please note that over here I presently have a hybrid setup of CC65 working under Windows Subsystem for Linux with OSDK working under Windows.
So that is why I have MAKE files for the CC65 part and .bat files for the OSDK part. To do is to integrate that in one workflow somehow (probably by using the Windows version of CC65, as I do not think running OSDK under Wine under WSL makes sense if it even works.....)

Choose my CC65 setup under WSL as on the Commodore 128 I worked on a project build with Linux tools and was too lazy to redo everything in batch scripts for Windows (and I do like MAKE).
I've never used WSL for now. But I already used Cygwin and/or Mingw and I can witness that it is easy to build cc65 on it.
Just like you I love Make and I usually find this beloved flavour on windows with cygwin or mingw.

With Mingw or Cygwin, you can get the command make. As for CC65, you can either use a prebuild windows version of CC65 or a version that you build from source with gcc under cygwin or mingw.
User avatar
xahmol
Flight Lieutenant
Posts: 437
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: CC65/C: Ensure joystick press is registered only once

Post by xahmol »

jbperin wrote: Tue Feb 23, 2021 2:53 pm With Mingw or Cygwin, you can get the command make.
Actually, I might be going this route if I have time to delve into it:
https://devblogs.microsoft.com/cppblog/ ... udio-code/

But my trouble with going to Windows for my C128 project was not only Make. It was also the work to rebuild commands like rm and other Linux bash commands to WIndows equivalents.
And even then: for some reason the Windows CC65 package did not compile working code from the C128 sources I used, while the Linux version does even without using the make files..... Probably caused by those C128 sources, maybe I just will have two CC65 installations on my machine, one Windows one and one Linux one.
Post Reply