> Have you done much of this?

I'm about 30% through such a project right now, and I have written C code for 6502-family CPUs in the past, although not specifically for the NES. I wouldn't say it's a lot of it, the way I wrote "a lot" of C code for x86, PPC or ARM, but I did definitely did use it to write more than trivial/one-off programs.

> I looked into it a while back and it seemed like the style of C required was very much its own flavor.

As far as cc65 goes, I think it's (mostly?) ANSI-compliant. There are a couple of quirks that you need to be aware of due to the underlying processor, but that's true of any machine. For example, the 6502 lacks native arithmetic instructions for 16- and 32-bit operands, so the compiler won't generate the same kind of code for adding uint8_t operands and adding uint16_t operands.

Then, of course, each compiler has its own quirks :). cc65 doesn't do micro-optimizations, for example, so a lot of the things that we're taking for granted in gcc or clang don't happen automatically in cc65. But that's also true of pretty much any compiler, or, well, at least it used to be true back in the day.

But if you look at the code... it's pretty typical C, I've definitely seen worse. It's possible to write cleaner compilers targeting a much wider subset of C for 6502 than, say, for the 8051. I have absolutely no fond memories about programming that damn thing, in neither ASM, Pascal or C :). Some programmers are a little too inventive for their own good and hide a lot of stuff behind all sorts of macros and whatnot but you can definitely write the kind of C code that would be merged into the Linux kernel if it had a 6502 port.

I don't have any numbers but a lot, if not most of the current crop of indie/retro games aren't written in ASM anymore, at least not on platforms with decent C compilers (NES, SNES, Amiga...). Some games (platformers, side-scrollers) have a sufficiently regular structure that you can write them in Assembly without cursing the day you were born. But games that are less linear than that, or that require even the dumbest autonomous AI that's just a branching instruction smarter than "fire at every 3 seconds, use special ability if player_health < 10", are pretty painful to build without higher-level abstractions. It's definitely possible, it's just that debugging high-level problems ("why is this enemy not switching from offensive to defensive spells when its health drops below 50") in a low-level language is generally above the motivation threshold for things you do on your own time.

Either way, though, knowing your way around Assembly is a good idea. First, touching some assembly code every once in a while is unavoidable. If you're writing games for old enough consoles, NES included, you do occasionally have to touch bootstrap code, and that's all LDA, CRN, HCF and ACDC. Second, most (cross) compilers that you can run today, whether modern or vintage and ran in an emulator, are orders of magnitude worse than gcc, clang or MS C/C++. The fact that compilers orders of magnitude worse than those can still be used to write entire programs is testament to just how good modern compilers are. But useful though they may be, they will still occasionally spit out really bad code, and while knowing enough Assembly to outdo the compiler isn't necessarily required, knowing enough to figure out when the compiler does something dumb and speculate on how to change your code to set it straight is really useful.

FWIW, I learned 6502 assembly first and I am, or I used to be, pretty good at it. Back when I first became interested in this topic, around 2002 or so, there weren't any good compilers available for free (cc65 was around but, as far as I remember, its support for the C64, which is what I cared for back then, wasn't exactly stellar. But I may be wrong, it's been a long time). But the tooling we have today is good enough that I rarely need to write any.