What do we want in a tutorial?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

Sik
Posts: 1589
Joined: Thu Aug 12, 2010 3:43 am

Re: What do we want in a tutorial?

Post by Sik » Fri Aug 21, 2015 9:23 am

C is easier once you want to see what the program is trying to do rather than how. It's just that it's way too slow and memory hungry to be usable on the 6502, at least for a NES game which is intended to perform well.

User avatar
dougeff
Posts: 2711
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: What do we want in a tutorial?

Post by dougeff » Fri Aug 21, 2015 7:24 pm

Re:cc65, coding NES in C

I downloaded Shiru and thefox's cc65 example files, and I noticed that thefox uses makefiles to compile the code. Does cc65 (or ca65) need an external program like 'make' to do a final compile compilation?
nesdoug.com -- blog/tutorial on programming for the NES

lidnariq
Posts: 9506
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: What do we want in a tutorial?

Post by lidnariq » Fri Aug 21, 2015 7:55 pm

You can mostly just use "cl65", but given the effort that the cc65 suite put into looking like a "real" computer's C compiler suite, a lot of people end up using Makefiles for more complex projects.

tepples
Posts: 22017
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: What do we want in a tutorial?

Post by tepples » Sat Aug 22, 2015 5:23 am

In addition, correct use of a makefile avoids A. having to re-run the PNG to CHR converter on all graphics every time you build the program or B. forgetting to manually re-run the PNG to CHR converter when something has in fact changed.

User avatar
dougeff
Posts: 2711
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: What do we want in a tutorial?

Post by dougeff » Sat Aug 22, 2015 9:32 am

I spent 4+ hours testing out cc65, and concluded that it's junk and nearly incompatible with NES architecture.

I downloaded 3 different versions of cc65, etc. Because I was getting all kinds of error messages, even with Shiru and thefoxs lib files, even editing cfg files. When I finally got it working... I wrote a simple test program that declares two variables, initializes them, adds them, and stores them to the name table...

Initializing them took up about 10 lines of ASM. Adding them over a dozen lines of ASM, and similar with storing to the name table. It doesn't seem to know how to use the registers. All math is 16 bit, even with 8 bit numbers (it just shoves a 0 in the upper byte for the math). New versions of cc65 are incompatible with older versions. Shirus runtime.lib wasn't working with 2 of 3. The standard NES.cfg is all wrong.

And, now I go back to using ASM6.

Edit, I redacted my statement, as using 'unsigned char' does use 8-bit math, and you can write optimized subroutines in ASM.
Last edited by dougeff on Thu Aug 27, 2015 10:18 am, edited 1 time in total.
nesdoug.com -- blog/tutorial on programming for the NES

User avatar
rainwarrior
Posts: 7824
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: What do we want in a tutorial?

Post by rainwarrior » Sat Aug 22, 2015 11:24 am

dougeff wrote:I spent 4+ hours testing out cc65, and concluded that it's junk and nearly incompatible with NES architecture.
It's entirely compatible with NES architecture.
I downloaded 3 different versions of cc65, etc. Because I was getting all kinds of error messages, even with Shiru and thefoxs lib files, even editing cfg files.
Use the version of CC65 it was built with, or rebuild the runtime lib with a newer version. It's not very productive to play a game of "is this still compatible?" with the libraries. (Though the problem here may just have been that shiru didn't document which version should be used, or how to rebuild the runtime? This is a problem with shiru's documentation though, not CC65.)
I wrote a simple test program that declares two variables, initializes them, adds them, and stores them to the name table...
Initializing them took up about 10 lines of ASM. Adding them over a dozen lines of ASM, and similar with storing to the name table.
Variable initialization is just a block copy operation, it would be the same amount of code whether it was 2 variables or 200, so it's reasonably efficient for use at scale.
It doesn't seem to know how to use the registers.
The C language shouldn't know how to use the registers. That's something a runtime library does, not a C language extension. Register manipulation needs to be done in assembly. Shiru's runtime library knows about the registers and has the appropriate functions for manipulating them via C calls.
All math is 16 bit, even with 8 bit numbers (it just shoves a 0 in the upper byte for the math).
CC65 is capable of doing 8 bit math. If you're sure you haven't implicitly converted to int by accident, it's possible that you've run into an unlucky case that is doing it improperly. If it's an error in the compiler you might share the problem code to the mailing lists so that it can be improved. You might be able to get what you want by inserting some explicit casts to unsigned char to combat implicit conversion to int?

The advantage of C is not having to think about the underlying code, though. It's going to be inefficient, this is a given. In the cases where you need efficiency, you can always write that part of your program in assembly, too, it's not like that's been taken away from you.
The standard NES.cfg is all wrong.
Yes, you should not use that, or the standard runtime libraries. They are designed for an entirely different purpose than NES game development. If you're using shiru's runtime library, you should use his supplied CFG file with it.

CC65 is very much usable for NES development. Maybe the existing tutorials have some documentation/usability problems, but that's its own issue. You've run into problems, but you can contact the people responsible for those issues to help get them fixed. Maybe you can help the next person who wants to try.

Sik
Posts: 1589
Joined: Thu Aug 12, 2010 3:43 am

Re: What do we want in a tutorial?

Post by Sik » Sat Aug 22, 2015 11:50 am

rainwarrior wrote:CC65 is capable of doing 8 bit math. If you're sure you haven't implicitly converted to int by accident, it's possible that you've run into an unlucky case that is doing it improperly.
This implicit conversion is mandated by the standard, although admittedly add is one of those operations where you can just forget the higher bits so it should be optimizable. Are optimizations turned on? If so then probably CC65 isn't being clever enough. Also I bet that using += would work around the issue (but then again that's something you shouldn't have to rely on).

User avatar
rainwarrior
Posts: 7824
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: What do we want in a tutorial?

Post by rainwarrior » Sat Aug 22, 2015 12:06 pm

Yeah, it's easy to envision a string of arithmetic operations producing some implicit casts to int that the optimizer just can't keep up with. It's a very weak optimizer.

Again, though, it's C, it's already expected to be inefficient. If the code is correct, what we're talking about is whether you have to do workarounds for some marginal gain. Most of the time there isn't much to gain with this kind of workaround.

My approach is to just code normally until an actual performance problem occurs (e.g. I get slowdown somewhere in my game) before I start looking for tricks to make the compiler more efficient, or rewriting parts in assembly. It doesn't really matter to me if there was some wasted calculation if I'm not exceeding my frame's timing budget yet.

If there's some use case that is common and intuitive, and should be easy to optimize but isn't, though, that kind of stuff is totally worth bringing up on the mailing list as a suggestion for future improvement to the compiler.

User avatar
dougeff
Posts: 2711
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: What do we want in a tutorial?

Post by dougeff » Sat Aug 22, 2015 1:31 pm

I was declaring them with 'int', because that's what I'm used to doing with small integers.
nesdoug.com -- blog/tutorial on programming for the NES

lidnariq
Posts: 9506
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: What do we want in a tutorial?

Post by lidnariq » Sat Aug 22, 2015 1:32 pm

"int" is required by the C standard to be at least 16 bits.

User avatar
dougeff
Posts: 2711
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: What do we want in a tutorial?

Post by dougeff » Sat Aug 22, 2015 2:37 pm

My philosophy is "technology should just work". When you turn the key in your car, it should start. When you press the back button on a browser, it should go back. And when you create a C environment specifically to function on an 8-bit 6502 processor, it should just do that. I shouldn't have to spend 4 hours trying to configure this or get the runtime library to do that, or trick the compiler into forcing a variable into 8-bits. And software updates should be backwards compatible. Anyway, I'm done bitching.

I was just trying to see if it would be easier to learn NES programming in C. I think the answer is 'no'. You still need to work with ASM at some point...for your start up code...for optimization when updating the PPU...for debugging the game later in FCEUX...etc.

I think I'll try ca65 next (ie, entirely in ASM), but I'll spare you my frustrated commentary if I can't get it to work right away. :)
nesdoug.com -- blog/tutorial on programming for the NES

User avatar
dougeff
Posts: 2711
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: What do we want in a tutorial?

Post by dougeff » Sat Aug 22, 2015 2:58 pm

unsigned char -- and optimize -- seemed to produce much more efficient code.
nesdoug.com -- blog/tutorial on programming for the NES

User avatar
mikejmoffitt
Posts: 1351
Joined: Sun May 27, 2012 8:43 pm

Re: What do we want in a tutorial?

Post by mikejmoffitt » Sat Aug 22, 2015 7:12 pm

For that I'd recommend a types.h with some typedefs to save time:

Code: Select all

typedef unsigned char u8;
typedef signed char s8;
So on and so forth.

Sik
Posts: 1589
Joined: Thu Aug 12, 2010 3:43 am

Re: What do we want in a tutorial?

Post by Sik » Sat Aug 22, 2015 9:24 pm

dougeff wrote:I was declaring them with 'int', because that's what I'm used to doing with small integers.
But huh, int isn't the type meant for small integers, short int is (and indeed short int is 8-bit on many old systems, no idea if that's what happens here though).

EDIT: tt'd because why not

tepples
Posts: 22017
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: What do we want in a tutorial?

Post by tepples » Sun Aug 23, 2015 6:01 am

Sik wrote:and indeed short int is 8-bit on many old systems
Do these systems predate the C standard? Because in the standard, short int is at least -32767 to 32767, which means at least 16-bit.

Post Reply