Live data from Hacker News

How to program an NES game in C

nesdoug.com

21–30 of 70 posts

Re: How to program an NES game in C

#21

IMHO a 6502 is too limited to be effectively programmed in C; even this part of the article gives all the limitations: https://nesdoug.com/2015/11/15/2-how-cc65-works/ With this important note: "clean unaltered C code will compile into very slow code that takes up too much of the limited memory space." In other words, "C" written for such a CPU will be in a vastly different style from more "normal" C, so that it migh…

From that page, "use ++g instead of g++ (it’s faster)" I've seen people say this a repeatedly when talking about "embedded" environments, but never understood why - won't it end up compiling to the same thing either way?

I think in C the temporary will be optimized away.

I keep meaning to test this in C++. I presume that it would for fundamental types, but wouldn't be able to be objects, because the side effects of that operation could be in another module. I use ++i for C++ iterators for that reason, and the habit tends to spill over to C.

Re: How to program an NES game in C

#22

IMHO a 6502 is too limited to be effectively programmed in C; even this part of the article gives all the limitations: https://nesdoug.com/2015/11/15/2-how-cc65-works/ With this important note: "clean unaltered C code will compile into very slow code that takes up too much of the limited memory space." In other words, "C" written for such a CPU will be in a vastly different style from more "normal" C, so that it migh…

From that page, "use ++g instead of g++ (it’s faster)" I've seen people say this a repeatedly when talking about "embedded" environments, but never understood why - won't it end up compiling to the same thing either way?

Depends on the compiler.

'a++' (postfix) and '++a' (prefix) have slightly different meanings in terms of return values. Postfix will return the value of 'a' before the increment, while prefix will return 'a' after the increment operation.

In a simple compiler, you would store the previous value of 'a' in the case of postfix in case you need to assign it. This results in a superfluous store instruction in most cases.

Of course, a smarter compiler could see the lack of assignment and throw away the store instruction during an optimization pass.

Re: How to program an NES game in C

#23

IMHO a 6502 is too limited to be effectively programmed in C; even this part of the article gives all the limitations: https://nesdoug.com/2015/11/15/2-how-cc65-works/ With this important note: "clean unaltered C code will compile into very slow code that takes up too much of the limited memory space." In other words, "C" written for such a CPU will be in a vastly different style from more "normal" C, so that it migh…

Does c65 turn structs into parallel arrays?

If you have something like

    struct Monster {
      unsigned char hitPoints;
      unsigned char damage;
      unsigned char shieldLevel;
      char* name;
    };
    static Monster s_monsters[] = {
      { 5,   1, 0, "orc", },
      { 50, 10, 5, "dragon", },
      { 10,  3, 1, "goblin", },
    };
that's a no-no on 6502. You generally need to store those in parallel byte arrays including the string pointer's upper and lower bytes each in separate arrays. That was usually done with assembler macros or compile time tools but it was important not to have to generate addresses that have to manually assembled in 6502. Similarly there's no multiply so math like sizeof(Monster) * index.

Re: How to program an NES game in C

#25

IMHO a 6502 is too limited to be effectively programmed in C; even this part of the article gives all the limitations: https://nesdoug.com/2015/11/15/2-how-cc65-works/ With this important note: "clean unaltered C code will compile into very slow code that takes up too much of the limited memory space." In other words, "C" written for such a CPU will be in a vastly different style from more "normal" C, so that it migh…

Forth then ?

6502 FIG Forth kernel: https://pastie.se/3ec4854e

Re: How to program an NES game in C

#26

IMHO a 6502 is too limited to be effectively programmed in C; even this part of the article gives all the limitations: https://nesdoug.com/2015/11/15/2-how-cc65-works/ With this important note: "clean unaltered C code will compile into very slow code that takes up too much of the limited memory space." In other words, "C" written for such a CPU will be in a vastly different style from more "normal" C, so that it migh…

From that page, "use ++g instead of g++ (it’s faster)" I've seen people say this a repeatedly when talking about "embedded" environments, but never understood why - won't it end up compiling to the same thing either way?

I'd argue you regardless you should write what you mean

If you mean "increment g" then write "++g"

If you mean "temp = g; increment g; return g" then write "g++"

It doesn't really matter that the compiler may optimize out the "temp". If you're writing "g++" you're indicating you want the value before it's been incremented.

Re: How to program an NES game in C

#27

Earlier quoted context omitted.

Yeah, C generally assumes a 'linear' memory space, so memory banks don't really fit into it extremely well. That said, with a little work you could likely coax the linker into doing a lot of the work for you. You would have to be a little careful though, as code in different banks could not effectively call each-other directly, even though the compiler would likely not yell at you. But you could just organize your co…

My impression is that the banking was more often used for graphics rather than logic.

This approach can be used for code and resources. For simpler games it is easier to just not bank the code, but for more resource intensive games you can end up banking code and resources.

Re: How to program an NES game in C

#28

IMHO a 6502 is too limited to be effectively programmed in C; even this part of the article gives all the limitations: https://nesdoug.com/2015/11/15/2-how-cc65-works/ With this important note: "clean unaltered C code will compile into very slow code that takes up too much of the limited memory space." In other words, "C" written for such a CPU will be in a vastly different style from more "normal" C, so that it migh…

Does c65 turn structs into parallel arrays? If you have something like struct Monster { unsigned char hitPoints; unsigned char damage; unsigned char shieldLevel; char* name; }; static Monster s_monsters[] = { { 5, 1, 0, "orc", }, { 50, 10, 5, "dragon", }, { 10, 3, 1, "goblin", }, }; that's a no-no on 6502. You generally need to store those in parallel byte arrays including the string pointer's upper and lower bytes e…

cc65 has a whole page on how to deal with the fact that it's a single-pass compiler with hardly any optimization [1]. It's almost more like a macro assembler than an actual compiler.

http://www.cc65.org/doc/coding.html

Re: How to program an NES game in C

#29
How did they actually make NES games? By that I mean, what types of computers were they using for creating NES games? Other 6502-based computers? Could they run the NES games on there? Or did they have to burn to a cart to test things every time?

How did they design graphics? Was it basically graph paper, which then they translated into sprites by hand?

Re: How to program an NES game in C

#30

IMHO a 6502 is too limited to be effectively programmed in C; even this part of the article gives all the limitations: https://nesdoug.com/2015/11/15/2-how-cc65-works/ With this important note: "clean unaltered C code will compile into very slow code that takes up too much of the limited memory space." In other words, "C" written for such a CPU will be in a vastly different style from more "normal" C, so that it migh…

Also AVR is nice for C programming, it even have GCC support.
Post reply on HN