edit: It seems I posted this in the wrong place. Could a mod/admin move it for me? My apologies.I'm actually also new to coding in C, but I find it much easier than ASM. I'm the kind of learner who likes to ask a lot of questions, so if anyone can help, it'd be
MUCH appreciated.
Anyhow, I've always been really interested in coding for olders systems, and the NES dev scene seemed to be the most lively out of them all and I decided to give it a try. I've just entered the process of learning C (with a very basic knowledge of C++ already existing in my mind) and decided that as I learn new things in C and make a program out of them, that I could then take the time to learn to do the same thing on the NES.
So basically, I have both a basic text output and button input program coded, and I've already successfully converted the text output program to the NES:
Code:
#include "conio.h"
int main(void)
{
clrscr();
cprintf("Hey there! I'm the NES; glad to meet ya'!\n")"
while(1)
{
}
}
So
now that I can make my NES talk dirty to me, naturally, it was time to work on the button input program, yes? However, the problem is, I have no idea how to do this. I tried looking at some open-source code to see if I could figure it out myself, but I always got errors when trying to compile it with cc65. Would anyone be willing to lend me a hand?
Post the errors. Sounds more like a compiler/library problem in C than a NES specific problem.
Do not learn C while trying to code for the NES. Learn C first by making PC programs, then move to the NES. On PC you have debuggers, nice IDEs and stuff like that, plus tons of docs on anything related. On the NES you have only a command line compiler, almost no docs, and very few people able to help.
Regarding your question, it all depends from low level libraries you are using. In your example you use some library that contains clrscr and cprintf implementations for the NES. If it also have input processing functions, you should use them. Alternatively you can get another library, write your own library in assembly code and link it to your program, or write code in C that will directly access the hardware via pointers (possible, but is not recommended, as it slow and has unpredictable timings).
Shiru wrote:
Do not learn C while trying to code for the NES. Learn C first by making PC programs, then move to the NES. On PC you have debuggers, nice IDEs and stuff like that, plus tons of docs on anything related. On the NES you have only a command line compiler, almost no docs, and very few people able to help.
Regarding your question, it all depends from low level libraries you are using. In your example you use some library that contains clrscr and cprintf implementations for the NES. If it also have input processing functions, you should use them. Alternatively you can get another library, write your own library in assembly code and link it to your program, or write code in C that will directly access the hardware via pointers (possible, but is not recommended, as it slow and has unpredictable timings).
I'm using the NES libraries that came with the cc65 compiler, to my knowledge there it didn't come with any documentation on the functions included. The code I wrote was using commands found through NES specific C tutorials or stuff that I had assumed would work by looking through other peoples code.
Code:
#include "conio.h"
#include "nes.h"
#define DIR_LEFT PAD_LEFT
int main(void)
{
clrscr();
cprintf("Hey there! I'm the NES; glad to meet ya'!\n")"
if(PAD_LEFT)
{
clrscr();
cprintf("This is a basic test of joypad input.\n");
}
while(1)
{
}
}
I thought this would theoretically do the trick, but cc65 stated that PAD_LEFT had not been defined.
That's never going to work. You don't check the value of a constant (PAD_LEFT is just a number), you read the joypad and test if a button is being held down or not.
Is there any NES games written with the libraries provided with CC65? I don't know any, everyone (in other words: both of us) use their own libs rather than these.
Well, didn't you (and correct me if I'm wrong) write a tutorial for writing in C with the NES using the libraries provided with cc65? I'm pretty sure one of the articles I found while searching was created by you, and it seemed to me like those were the ones used.
I've done a bit of work with cc65 on NES.
I didn't consider the NES libraries that came with cc65 worthwhile for making games, except maybe a text adventure.
My approach has been to write low-level stuff in assembly (e.g. NMI graphics update, controller reading, sound register control) and then the rest as C unless it needs to be fast. I don't have anything prepared that I could share, at the moment, though. I wasn't trying to build a library anybody could use. When I've done some more work I'll probably make it open source, but I can't really provide a useful "library" at the moment.
Shiru's library is a good starting point. I would recommend trying that. I've only looked at it a little, because I find it easier to write my own stuff, but from what I've seen it's quite usable to make a small game without modification.
I wrote a tutorial for writing in C for the NES indeed, but using my own library. It does not have any generic things like cprintf and other standart stuff that is quite useless for real games, but does have everything you actually need to make a simple (and not so simple) games.
Why I made my own library - it is the same reasons rainwarrior mentioned. It is easier for me to write own stuff than to figure out something not really used and documented, and I'm sure these bundled libs are not have everything that is actually needed. No music and sound effects support, for example.
In that case, how does one write their own ASM libraries for the NES? I have read up a bit already on 6502 ASM and right now it seems I'll have to learn quite a bit more, but at least knowing what I should do at that point would be reassuring.
YeahManWAZZAP wrote:
Code:
if(PAD_LEFT)
{
.......
}
I thought this would theoretically do the trick, but cc65 stated that PAD_LEFT had not been defined.
You can get something very close to that working, but you need to use a global variable and have your NMI take care of joypad reads for you if you don't want to explicitly read the joypad each time. If you are just learning C the NES is not the best thing to learn on. Or - if you are just learning NES, C is not the best way to learn the NES. If you want to learn 6502 assembly, then maybe you can learn the NES at the same time.
It was explained in 'Writing functions in assembly code' section of my article how to write your functions in assembly. A bunch of functions bundled together in a some way called 'library'. You can also look up into sources of the examples of the article to see how crt0 could be done and things like that, but at that point good knowledge of C, 6502 assembly, NES hardware, and some knowledge of CC65 internals is necessary.
Alright; I will expand my knowledge of both before I continue attempting to code for the NES and return when I feel I am ready. Thank you for taking the time to help me out, I appreciate it very much.
cc65 comes with some sort of "joy" library and there is an NES joy "driver", but I don't know how to get those working, and as I've said, they really aren't suitable for games, I think the goal was just to provide basic C text program functionality.
If you use
Shiru's library, the gamepad code would look something like:
Code:
unsigned char pad;
pad = pad_poll(0);
if (pad & PAD_LEFT)
{
move_character_left();
}
YeahManWAZZAP wrote:
Shiru wrote:
Do not learn C while trying to code for the NES. Learn C first by making PC programs, then move to the NES. On PC you have debuggers, nice IDEs and stuff like that, plus tons of docs on anything related. On the NES you have only a command line compiler, almost no docs, and very few people able to help.
Regarding your question, it all depends from low level libraries you are using. In your example you use some library that contains clrscr and cprintf implementations for the NES. If it also have input processing functions, you should use them. Alternatively you can get another library, write your own library in assembly code and link it to your program, or write code in C that will directly access the hardware via pointers (possible, but is not recommended, as it slow and has unpredictable timings).
I'm using the NES libraries that came with the cc65 compiler, to my knowledge there it didn't come with any documentation on the functions included. The code I wrote was using commands found through NES specific C tutorials or stuff that I had assumed would work by looking through other peoples code.
Code:
#include "conio.h"
#include "nes.h"
#define DIR_LEFT PAD_LEFT
int main(void)
{
clrscr();
cprintf("Hey there! I'm the NES; glad to meet ya'!\n")"
if(PAD_LEFT)
{
clrscr();
cprintf("This is a basic test of joypad input.\n");
}
while(1)
{
}
}
I thought this would theoretically do the trick, but cc65 stated that PAD_LEFT had not been defined.
PAD_LEFT is a constant define for a bit field mask.
To test if PAD_LEFT bit is present, you would take another value, like
if (pad_var & PAD_LEFT) ...
This is assuming pad_var is filled in somewhere with the actual button states because the NES data is serial and has to be read 1 bit at a time and shifted into a variable, there isn't a register you can simply bit test.
Additionally, if you don't read the complete controller status, and bit test for PAD_LEFT within 1 iteration of your loop, it still won't work because it gets stuck at the while(1) loop.
just do the unsigned char for the temporary controller value, then the constant for the left button bit, and do a
Code:
if (ControllerStatus & LeftButton){
//code
}
because there's no bit test register, but a LDA+BIT or LDA+AND can test one bit easily.
3gengames wrote:
because there's no bit test register, but a LDA+BIT or LDA+AND can test one bit easily.
Or what I use to read the controllers: LDA+LSR
zzo38 wrote:
Or what I use to read the controllers: LDA+LSR
But then you are ignoring certain controllers, such as the one that plugs into the expansion port of the Famicom (which I believe returns data on bit 1).
I guess I forgot to mention all bits need to be LSR'd in to a memory location before, like they should be. Reading off the $4016/7 makes no sense to do.
tokumaru wrote:
zzo38 wrote:
Or what I use to read the controllers: LDA+LSR
But then you are ignoring certain controllers, such as the one that plugs into the expansion port of the Famicom (which I believe returns data on bit 1).
I know; it won't work if reading the keyboard. But for reading the standard controller, it works.
3gengames wrote:
I guess I forgot to mention all bits need to be LSR'd in to a memory location before, like they should be. Reading off the $4016/7 makes no sense to do.
If you want bits to be LSR'd into a memory location you can use ROL or ROR to RAM after LSR since it uses the same carry flag, in case you want to store the buttons state in RAM.
zzo38 wrote:
tokumaru wrote:
zzo38 wrote:
Or what I use to read the controllers: LDA+LSR
But then you are ignoring certain controllers, such as the one that plugs into the expansion port of the Famicom (which I believe returns data on bit 1).
I know; it won't work if reading the keyboard. But for reading the standard controller, it works.
It's not just the keyboard that plugs in to the Famicom expansion port, there are also 3rd party "standard controllers" for Famicom that do the same. And they'll not work if only the least significant bit is read.
Remember that on the original Famicom the controllers are hardwired, so once they stop working well the only solution is to plug one of these 3rd party controllers into the expansion port, so I imagine that a significant number of Famicom owners do use such controllers, and you are ignoring them. =)
tokumaru wrote:
Remember that on the original Famicom the controllers are hardwired, so once they stop working well the only solution is to plug one of these 3rd party controllers into the expansion port, so I imagine that a significant number of Famicom owners do use such controllers, and you are ignoring them. =)
Yes I know they are hard wired, but using a 3rd party controller which is not compatible does not seem a best solution to me. Better would be to rewire the cables so that you can connect the controllers externally (some of these signals may be shared with the expansion port), but including the bit2 of $4016 on the second controller port, so that you can use the microphone. And then you can add SELECT and START button on second controller as well, and including microphone too. Hopefully if you know how to build electronics hardware you could rewire the cables without too much difficulty.
Especially if someone makes a Famicom clone hardware, they could do this; include both Famicom expansion port and the both controller ports including microphone! It is what I would do if I made a Famicom clone hardware: It is like the original Famicom, including the expansion port, both controller ports (including microphone), Famicom expansion port, and an internal ROM which can function when no cartridge is inserted (and could include a BASIC or Forth interpreter). And then, comes with it, connected externally: the keyboard, both controllers (including microphone), and 72-to-60 adapter.
zzo38 wrote:
Yes I know they are hard wired, but using a 3rd party controller which is not compatible does not seem a best solution to me.
Maybe not to you, but to the average retro gamer who doesn't know anything about electronics, it is. I wouldn't say they are not compatible though, as a lot of official games accept input from such controllers. In fact, all licensed games I have personally looked at do read bit 1 as well as bit 0 (from really old games like Balloon Fight to newer ones like Kirby's Adventure). The only exceptions I remember are unlicensed Camerica games. This makes me think there was something about this in the official programming manuals.
I'm not forcing you to change your way of reading controllers, I was just pointing something in case you didn't know (the available tutorials don't seem to mention these Famicom controllers). If you were already aware of this and are ignoring these Famicom controllers on purpose, that's your problem.
tokumaru wrote:
In fact, all licensed games I have personally looked at do read bit 1 as well as bit 0 (from really old games like Balloon Fight to newer ones like Kirby's Adventure). The only exceptions I remember are unlicensed Camerica games. This makes me think there was something about this in the official programming manuals.
I'm not forcing you to change your way of reading controllers, I was just pointing something in case you didn't know (the available tutorials don't seem to mention these Famicom controllers). If you were already aware of this and are ignoring these Famicom controllers on purpose, that's your problem.
Perhaps this should be mentioned in the wiki.
I thought it was to combine them on the famicom game for use of an external P1 controller?
3gengames wrote:
I thought it was to combine them on the famicom game for use of an external P1 controller?
Combine what?
I was told you read the controller bits, and combine two of the 4016 bits or something like that to properly read the famicom controllers. It never made sense, I never implemented it, but I remember being told that somewhere on here.
The bottom line is that the built-in controller returns data on bit 0, and the expansion port controllers use bit 1. The actual method used to combine them varies from game to game. Some games read from $4016, store the value into a temp location, shift the accumulator right to line the bits up and OR them together, other games read from $4016, clear the top 6 bits and compare the result with #1: equal or more means that either one or both bits are set, so the carry flag can be used as a button state (I like this method better!). Anyway, the actual implementation doesn't matter, as long as you take both bits into consideration when reading $4016.
There are a fair number of games that don't read bit 1 and 0. Mainly it's stuff developed in Europe or North America, since reading both bits isn't relevant on the NES. Battletoads and Solstice don't, off the top of my head. (I'd bet the Famicom port of Battletoads does read both though-- haven't checked.)
rainwarrior wrote:
Battletoads and Solstice don't
You are right. I just checked, and even the japanese versions don't.
EDIT: Out of curiosity I went and checked Somari, that crapy chinese Sonic 1 port: it does read both bits, in a very inefficient way though (it uses the stack to keep track of the regular controller, a ZP variable for the expansion port controller, and ORs them together in the end).
If you have a non-AV Famicom and your controller has a problem it is not as though you cannot replace or repair them. While it's harder than just plugging in a new controller, anyone interested in the hobby of playing Famicom games in the current time frame shouldn't be too surprised if they need to open their machine up to repair something. Or to have someone else do it. It's the reality of still playing with these very old machines. Replacing a controller probably is easy though maybe not cheap.
Still, for us who are still making software it's so damn easy to support those controllers that I just don't see a reason not to. A little routine that runs once per frame will be ~50% slower, big deal.
What's so hard for those guys to put in new rubber pads like I do when it is needed with my controllers?
3gengames wrote:
What's so hard for those guys to put in new rubber pads like I do when it is needed with my controllers?
What? You know how to fix used controllers?!
Where is the store that sells new rubber pads? Or maybe there's a new rubber pad tree I could plant? ...i dont konw.
It isn't difficult to fix the rubber pad using a new one from any electronic device. Remove contact pad on the original rubber, leaving hole, put a new piece there so the hole in the old pad will just hold it in place.
Shiru wrote:
It isn't difficult to fix the rubber pad using a new one from any electronic device. Remove contact pad on the original rubber, leaving hole, put a new piece there so the hole in the old pad will just hold it in place.
Really? Say there's an old tv remote control laying around that wasn't used very much in the past... and now it just sits unused on the coffee table. So I could remove the contact pads from my NintendoES controller and replace them with some of the unused contact pads from the remote control? Is quality of pads an issue to worry about?
unregistered wrote:
3gengames wrote:
What's so hard for those guys to put in new rubber pads like I do when it is needed with my controllers?
What? You know how to fix used controllers?!
Where is the store that sells new rubber pads? Or maybe there's a new rubber pad tree I could plant? ...i dont konw.
Ebay of course. Check it out.
http://www.ebay.com/sch/i.html?_nkw=nes ... &_osacat=0
Well, there are two ways how the rubber pads 'broke'. The first is the rubber wears out in the area where it bends when you press the pad, it just tears apart, and that reduces 'bouncing' quality of the button, or whatever you would call it, down to zero. The second is that the conducting part of the rubber wears out, its resistance raises and it requires more and more force to make the controller register the button press.
The first can't be really fixed without replacing the worn part. The problem with replacing the rubber is that rubbers from other devices has different shape, so they aren't hold in place. That's why old rubber with removed contact pads can help, it can serve as a holder.
the second can be sort of fixed in a few ways without replacing the rubber, although it may not last for long - put some graphite on the conductive part, or use a thin sandpaper or a nailfile to remove thin surface layer.
Wow, thank you Shiru and 3gengames so much!
Goodness, I need to continue working on the game now...close ebay... and this excellent reading responses... bye. : )