This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

CC65, NES, joystick

CC65, NES, joystick
by on (#74094)
Hi,

Could anyone put an example code in CC65 how to get joystick to work in NES ? I haven't found good (or any) examples, all my attempts so far haven't worked.


Thanks for advance !


-jp

by on (#74095)
Be more specific. By CC65 do you mean the C compiler or the CA65 assembler? You could also paste your earlier attempts here so we can tell you what you did wrong.

by on (#74096)
Yes, of course, sorry, I was too busy.

I'm using C, not asm, compiling using cl65 (-t nes -o XXX.nes XXX.c).


An example, which doesn't work, probably as the joystick driver is not installed or something:

Code:

#include <nes.h>
#include <joystick.h>

int joy;

void main() {
  POKE(0x4015,0xFF);
  while(1) {
    joy = joy_read(JOY_1);
    ......
    ......
  }
}


I make sound programming only, nothing else, so all .... means poking to sound registers directly as in example above. With joy_read() it stops there, seems to wait forever (something), without it, the sounds are generated and audible as usually.


Thanks !


-jp

by on (#74097)
Ah, in that case I have no idea what the problem is. I know the default CC65 NES libraries aren't that great but I'd expect joypad routines to work at least.

I wrote an alternative library some time ago, you might want to give it a go: http://kkfos.aspekt.fi/projects/nes/kne ... -for-cc65/ There's also a read_joy() function in there. The code you pasted would be something like this with my library:
Code:
#include "knes.h"

byte joy;

int main(void)
{
  _M(0x4015) = 0xFF;
  while(1) {
    joy = read_joy(0);
    // ...
  }
}


EDIT: Hmph, I guess I should've included an empty template in the KNES package... I doubt very many want to dig through the makefile and stuff in the demo "game"...

by on (#74099)
Thanks, I knew about your knes library replacement, I was actually going to try it next. I had (and still have:) the current official version, I downloaded snapshot version and installed it (before that mv cc65 cc65.org, working on Linux), before snapshot I downloaded your knes and compiled it without problems, after installing the snapshot version it doesn't compile, instead got this message:

Code:

ar65: Error: Wrong data version in `knes.lib'
make: *** [knes.lib] Error 1



I also got this message

Code:

Fatal error: The meaning of `-l' has changed. It does now expect a file name as argument.



These both with snapshot version cc65-snapshot-2.13.9.20110212, but not in official version cc65-2.13.2.

Any thoughts ?

And thanks !

-jp

ps. Do I need any other files than knes.h and knes.lib for compiling with cl65 ?

by on (#74100)
jp48 wrote:
Thanks, I knew about your knes library replacement, I was actually going to try it next. I had (and still have:) the current official version, I downloaded snapshot version and installed it (before that mv cc65 cc65.org, working on Linux), before snapshot I downloaded your knes and compiled it without problems, after installing the snapshot version it doesn't compile, instead got this message:

Code:

ar65: Error: Wrong data version in `knes.lib'
make: *** [knes.lib] Error 1


Hmm I can't even remember why I wrote it would only work with the snapshot version... maybe I compiled knes.lib with some older snapshot version (which is kind of stupid if I did). Anyway the object/library version number was probably bumped up so you'll need to replace nes.lib in the directory "knes/original" with the one in the snapshot version (in cc65-snapshot-nes-*.zip) and then recompile knes.lib.

Quote:
I also got this message

Code:

Fatal error: The meaning of `-l' has changed. It does now expect a file name as argument.



Yeah that's a pretty recent change in CC65, you can remove the -l argument from the makefile though, it only generates the listing files.

Quote:
These both with snapshot version cc65-snapshot-2.13.9.20110212, but not in official version cc65-2.13.2.

If it works with the official version, by all means use that. You can also recompile knes.lib for that if it doesn't otherwise work. Actually now that I think of it it's probably the best thing to do since there have been quite a few changes to the CC65 dev version after I released KNES v0.1... build breaking changes.

Quote:
ps. Do I need any other files than knes.h and knes.lib for compiling with cl65 ?

Yeah only those are needed.

by on (#74101)
Okay, let's move on:

I sticked to snapshot version, got the nes.lib and recompiled, removed -l options, compiled without errors. Using same code example we've worked , I get this error:

Code:

Unresolved external `_read_joy' referenced in:
  snd1.s(16)
ld65: Error: 1 unresolved external(s) found - cannot create output file



However I removed #include <peekpoke.h> and instead use your _M, it works perfectly, just the joystick external, there's something (same happened with official CC65 version).


Thanks again !


-jp

by on (#74102)
jp48 wrote:
Okay, let's move on:

I sticked to snapshot version, got the nes.lib and recompiled, removed -l options, compiled without errors. Using same code example we've worked , I get this error:

Seems like knes.c wasn't compiled and archived into knes.lib for some reason, did you use the supplied makefile? Try deleting the .lib and all .o files and recompiling knes.lib once more.

by on (#74103)
thefox wrote:
Seems like knes.c wasn't compiled and archived into knes.lib for some reason, did you use the supplied makefile? Try deleting the .lib and all .o files and recompiling knes.lib once more.


I actually removed whole knes directory, unzipped from the original, replaced the nes.lib from snapshot, compiles without errors (after removing -l flags), I copied knes.lib to /opt/lib/cc65/lib and knes.h to /opt/lib/cc65/include. I tried to copy both to same directory where my sources reside, with

Code:
#include <knes.h>

and

#include "knes.h"


And yes, I used original Makefile, here's the result of compiling:

Code:

cl65 -v -g -t none -c crt0.s
cl65 -t none -g -T -Cl -Oirs -c knes.c
cl65 -v -g -t none -c _read_joy.s
cp original/nes.lib knes.lib
ar65 d knes.lib _scrsize.o cclear.o chline.o clock.o clrscr.o color.o cputc.o crt0.o cvline.o get_tv.o gotox.o gotoxy.o gotoy.o mainargs.o ppu.o ppubuf.o randomize.o revers.o setcursor.o sysuname.o waitvblank.o wherex.o wherey.o
ar65 a knes.lib crt0.o knes.o _read_joy.o



_M() function/macro works perfectly !

Thanks very much of your efforts to help with this !


-jp

by on (#74105)
jp48 wrote:
thefox wrote:
Seems like knes.c wasn't compiled and archived into knes.lib for some reason, did you use the supplied makefile? Try deleting the .lib and all .o files and recompiling knes.lib once more.


I actually removed whole knes directory, unzipped from the original, replaced the nes.lib from snapshot, compiles without errors (after removing -l flags), I copied knes.lib to /opt/lib/cc65/lib and knes.h to /opt/lib/cc65/include. I tried to copy both to same directory where my sources reside, with

Aah damn I forgot, you also need a separate linker config file, can't use the default one, sorry about that. There's one for NROM in the "demo" directory: nes-nrom.cfg. Also you probably forgot to link with knes.lib, so add it to the command line when linking. And specify the config file with "-C nes-nrom.cfg". You can look in demo/Makefile for an example.

Linker config format has changed in snapshot so you'll need to remove this from it:
Code:
symbols {
    __STACKSIZE__ = $0200;
}

I can't remember what it needs to be replaced with but seems to work without it so...

Quote:
Thanks very much of your efforts to help with this !

No problem, thanks for ideas on how to improve the usability of the library. I should add a blank template and make sure it works without all of this hassle. It was supposed to make things EASIER, after all. :)

by on (#74126)
Well, still problems, the program compiles with two warnings, below:

Code:

ld65: Warning: nes-nrom.cfg(45): Segment `HEADER' does not exist
ld65: Warning: nes-nrom.cfg(45): Segment `DPCM' does not exist



It still produces ROM file but neither FCEU nor mednafen do open it.

I used nes-nrom.cfg, removed the three lines you mentioned and ensured that I link knes.lib:

Code:

cl65 -t nes -C nes-nrom.cfg -o snd1.nes snd1.c knes.lib



(and few combinations of other flags for cl65).

The template would be wonderful, don't be too "ankara" for yourself, this is version 0.1, at some point it makes things easier.


(and by "ankara" I don't mean any cities, just a Finnish word from Kitee to Tampere). :)


-jp

by on (#74130)
DPCM you can ignore. (It should have been made optional in the link script.) But if the header don exits, then of course nothing will open it.

by on (#74134)
tepples wrote:
DPCM you can ignore. (It should have been made optional in the link script.) But if the header don exits, then of course nothing will open it.


Yes, I already ignored DPCM simply by commenting it out. But header, where it should be, I mean, if I simply comment out the joy_read(), everything works, it is obvious there's some problem with the header, I just need to know how to solve it.

Thanks !


-jp

by on (#74141)
jp48 wrote:
Well, still problems, the program compiles with two warnings, below:

Code:

ld65: Warning: nes-nrom.cfg(45): Segment `HEADER' does not exist
ld65: Warning: nes-nrom.cfg(45): Segment `DPCM' does not exist



It still produces ROM file but neither FCEU nor mednafen do open it.

I used nes-nrom.cfg, removed the three lines you mentioned and ensured that I link knes.lib:

Code:

cl65 -t nes -C nes-nrom.cfg -o snd1.nes snd1.c knes.lib



(and few combinations of other flags for cl65).

The template would be wonderful, don't be too "ankara" for yourself, this is version 0.1, at some point it makes things easier.

Bleh, I'm completely out of touch with this stuff. I forgot how non-generic that config file was. :) Yeah, you can remove the DPCM segment, or add "optional = yes" to it. You also should change "-t nes" to "-t none" since you're specifying a linker config. Aaaand you also need to specify the iNES header: copy header.c and header.h over from demo/ directory and compile+link header.c in. I should probably add a macro to knes.h to allow specifying the header in an easier way...

So here's the command line that should work after that:
Code:
cl65 -t none -C nes-nrom.cfg -o snd1.nes snd1.c header.c knes.lib


Quote:
(and by "ankara" I don't mean any cities, just a Finnish word from Kitee to Tampere). :)

Heh heh... I don't think I am, I'm just surprised how much I've forgotten about this already. :)

Btw, here's the correct replacement for the symbols line in the config:
Code:
symbols {
    __STACKSIZE__: type = weak, value = $0200;
}

We'll see what I forgot about this time...

by on (#74143)
OK, let's continue:

I added 'optional = yes' to DPCM line, copied both kernel.c and kernel.h, commented out #include <nes.h>, I need VBLANK so I use one from knes.h. No errors in compiling, still stucks to reading joystick ie.

Code:

joy=read_joy(0);
if(joy & JOY_UP) par1=40;



If I comment out those two lines, sounds come out normally, except now wait_blank(); stucks to first sound (I tried disable_interrupts(); and enable_interrupts(); but it doesn't help).

I'm not sure if this all have something to do that I'm working only with sound, no display, just blank screen. However without joystick CC65 nes.h works exactly as it should work, waitvblank() works correctly etc.


Thanks !


-jp

by on (#74144)
jp48 wrote:
OK, let's continue:

I added 'optional = yes' to DPCM line, copied both kernel.c and kernel.h, commented out #include <nes.h>, I need VBLANK so I use one from knes.h. No errors in compiling, still stucks to reading joystick ie.

Code:

joy=read_joy(0);
if(joy & JOY_UP) par1=40;



If I comment out those two lines, sounds come out normally, except now wait_blank(); stucks to first sound (I tried disable_interrupts(); and enable_interrupts(); but it doesn't help).

I'm not sure if this all have something to do that I'm working only with sound, no display, just blank screen. However without joystick CC65 nes.h works exactly as it should work, waitvblank() works correctly etc.

wait_vblank() needs NMIs to be enabled. poll_vblank() works without NMI, but it will miss frames every now and then. You can use "PPU.ctrl = NMI_ON;" to enable the NMI. And yeah you can't use nes.h when you use knes.

by on (#74147)
OK, nes.h was already commented out, I added PPU.ctrl =NMI_ON and now VBLANK works correctly. Just the joystick. To check that it works, I copied the edited nes-nrom.cfg to knes/demo directory, cleaned *.o", demo.nes and compiled the demo game. All works, sound, joystick, etc. So, it seems that something is missing from my test code, I looked main.c from demo.nes, quite a lot possibilities to start guessing :). I put my code here, we need just to find what's missing, joystick works with knes so the problem is probably here:

Code:


#include <stdlib.h>
#include "knes.h"

int i,j,par1;
static byte joy;

void main()
{
   PPU.ctrl = NMI_ON;
   _M(0x4015) = 0xFF;
   par1 = 16;
   while(1)
     joy = read_joy(0);
     if(joy & JOY_UP) par1 = 40;
     {
          ....
          ....
     wait_vblank();
     }
}



..., ..., is poking or _M() to APU addresses. Everything works if I comment out 'joy =....' and 'if(joy....)' lines, otherwise it stucks before writing to APU regs.



-jp

by on (#74152)
I don't understand what exactly isn't working. Are you sure it hangs in read_joy()? Why are you including stdlib.h? Why is wait_vblank() inside the if() block?

by on (#74153)
thefox wrote:
I don't understand what exactly isn't working. Are you sure it hangs in read_joy()? Why are you including stdlib.h? Why is wait_vblank() inside the if() block?


This is a template for an algorithmic composition program, stdlib.h because I need rand(), I use joystick to feed/change/alter parameters to the mathematical processes inside the if {}, the results of the calculations are fed to sound registers, a series of wait_blank() is done after each calculations, that's why it is inside if{}.

It works when I comment out those two lines, which contains joystick-functions, without comments it stops before any sound. When I use the joystick nothing happens, ie. no sounds, it seems to hang in that point. Otherwise it works exactly as I've planned (I've made quite a lot of these for different consoles etc.), a lot of noisy stuff :).

by on (#74154)
OK, it is fixed, I used jed-editor, it adds {} automatically, unless you mentioned why wait_vblank() is inside if {}, I looked again and realized there's while{} too, changed my code, and works now, perfectly !


Thanks very much !



-jp

by on (#74155)
OK, didn't really understand what you just said but glad to hear you got it working. :)