I have recently started learning to program games for NES.
How do you guys typically write programs?
Do you write whole programs in assembly? OR write them in C, compile with cc65 or something like that?
Which is efficient way?
-fsakura
Personally for now I write 100% in assembly, but that might change in the future.
Even if you code in C, some parts which are close to hardware will have to be coded in assembly.
Also, you'll have to adopt a particular coding style if you want CC65 to generate not-too-horrible code (by that I mean, less than 10x the size and execution time of the same code written in assembly), like declaring all variables STATIC, using loops in reverse order explicitely, and so on... doing so will reduce your code's readability and therefore if it's not portable and readable why use C in the first place ?
I should definitely do some kind of serious benchmarking to show how good or bad is CC65 for particular programs but I lack the time. I think the Atalan language looks like a promising alternative, as it is more suited for CPUs like the 6502 which is not very well suited for a C compiler to generate optimized code, which means that you'll either have to do departs from standard C, or code your algorithms in a weird non-standard way in order to be remotely efficient.
Assembly. Next question. ;)
fsakura wrote:
Which is efficient way?
(emphasis mine). So ... there's many different efficiencies here.
For
quick tests, and
even simple
games, it's hard to argue with using cc65... even if it is the odd "looks awfully odd C" that compiles to something small and fast. The amount of time it will take
you to spin something out will be dramatically lower, because more of the more boilerplate code is taken care of by something else. I personally really hate doing arithmetic in assembly (at least, beyond the simplest bit shifts and addition), so C is really nice here.
On the other hand, if you need special startup code, or you want to update large numbers of background tiles per frame, you'll need to write substantial portions of the thing in assembly anyway.
You might consider looking into
uc65 or
ca65hl, which are not C, but do afford some of the conveniences of higher-level programming.
lidnariq wrote:
I personally really hate doing arithmetic in assembly (at least, beyond the simplest bit shifts and addition)
Then you'll probably get a kick out of the floating-point library I'm working on, at least for turn-based games.
Thanks everyone for replies. Looks like there is no real advantage in using C here.
For now I have decided to use ASM, because it is helping me to know what happens exactly.
I am using ca65 compiler and ld65 linker to get my rom.
-faskura
I'm also a beginner and I use only assembly. I looked into CC65 and one of the first things I read was something like "you'll need good knowledge of assembly" and after that I went back to assembly.
Assembly is really not as bad as some people make it sound. The more about it you learn, the learning curve gets easier.
Nerdy Nights still the place to go for that first NES assembly tutorial?
http://nintendoage.com/forum/messagevie ... eadid=7155
I recently made this:
Minimal NES example using ca65It's not really an assembly tutorial, just an attempt to demonstrate how to use the NES with a very small example that I hope is followable.
Only Assembly, only hardcore
My advice is to learn more about 6502, really useful.
Assembly. I tried C in the past, it worked well and was nice for a change, but I couldn't have done it without knowledge of 6502 ASM. Once you've written a bunch of utility macros/sub-routines and feel comfortable, programming in assembly can be pretty fast, actually. Admittedly, complex arithmetic continues to be a pain. Also, sometimes it doesn't matter how slow a particular piece of code is, so in C you could opt for convenience and "write regular C" for a bit instead of the usual "odd C that is faster/smaller".
If you have no prior programming knowledge, assembly is easier to pick up IMO. You can learn C for 2 years and still not have a clue what you're doing (nor what the compiler is doing, which is important on a limited platform like the NES).
Also: ASM is fun.
Quote:
Also, sometimes it doesn't matter how slow a particular piece of code is, so in C you could opt for convenience and "write regular C" for a bit instead of the usual "odd C that is faster/smaller".
The problem is that even if you absolutely do not care about the speed, compiled C code will be much larger than hand written assembly and this can be a problem if you aim for a mapper with no or few bankswitching features.
Even if you want to aim for a larger cartridge, you still want to use that extra space effectively and not waste it completely to store horrid bloated code.
What I'm doing for the game I'm currently working on is writing it in C++ as a windows program (with a graphics/sound API designed around the NES specs), and when parts of the program become close to their final design, I port them into the NES version of the program. I'm acting as a human compiler, more or less.
I find doing it this way, I don't have to spend much time iterating/debugging assembly code because I already know what I want it to do going in. The difficult work of trying to find the right algorithms, tweaking the design, etc. is done more easily in the C++ version of the game. At the same time, I still get assembly code that's small and efficient enough, since I'm not going through a C compiler.
Occasionally I do end up wanting to tweak something that's already been ported to NES, and I have to update code in two places at once, but this has so far been fairly easy to keep up with.
I prefer to use a macro assembler. The software is only written for NES/Famicom/emulators, so the code does not need to be portable to compile into native code of other systems.
C codes compiled into the 6502 will be larger and slower too, as mentioned above, and I do agree to generally want to not store a lot of bloated code. I might use large ROM for level data or more complicated stuff, but the program can be written pretty small in assembly language compared to the level data. Using smaller ROM not only means you can use a smaller ROM cartridge (if you only have a large one, you can just copy the data several times so that it acts like a smaller ROM), but also makes the iNES ROM image file smaller, to take up less disk space and less download times.
Quote:
What I'm doing for the game I'm currently working on is writing it in C++ as a windows program (with a graphics/sound API designed around the NES specs), and when parts of the program become close to their final design, I port them into the NES version of the program. I'm acting as a human compiler, more or less.
Actually this may be pretty cool to do, and pretty efficient too.
The only problem is that personally I can only write command line tools for the PC, not GUI, so I can't develop a PC game.
Do you use a framebuffer for displaying the game ? Or do you already simulate the BG and sprites of the NES ?
I wrote simple PPU and APU simulators. They aren't as complex as an emulator would need to be, just something that looks/sounds the same on the surface. The "PPU" just fills up a framebuffer on request, and the "APU" fills up an audio buffer. Their public interfaces are based around the NES code I would be writing, so PPU::latch(x) is like writing $2006, or PPU::write(d) is like writing $2007, etc.
Getting the actual sound/video to the screen is done with
SDL, but could easily be replaced by whatever GUI framework is needed. The layer of code that connects the PPU/APU/input to the user's terminal is fairly minimal. I just happen to like SDL, and it's convenient for PC/Mac/Linux cross development.
Well I could probably learn how to program a GUI and make high level emulaiton of NES-like hardware features, but I'm pretty sure many people here on this board would be interested if you published it provided it's relatively user friendly.
So for my next game I could try that and see if it takes less than 9 years to develop the game
Yes, a pluggable PPU and APU simulator would be useful by allowing a game to be designed for prototyping on a PC and to NES piece by piece. Perhaps the APU side could be based on Blargg's Game Music Emu. But doing so would require extensions to the NSF semantics to support sound effects and other communication from the game engine to the virtual machine in which the NSF runs without having to completely reset the machine for every track.
Bregalad, I do intend to publish my NES game as open source in the long term, but not in the short term. A source code release is about a year off, I think. I hope to be publicly releasing a demo in a month or so, and a full release later this year. Source code I would make available later on.
If you're looking for a source example of how to use SDL to make a game, I recently made a 3 day game for Toronto Game Jam, which I released source for. It doesn't have an NES style PPU/APU but it's a working example of how to get graphics/sound/input up and running:
http://rainwarrior.itch.io/pastured-ewe
Actually I think simulating $2006/7 writes or APU directly is too low level for this specific purpose. Not that it doesn't make sense, if you really care about a 1:1 port on PC.
But if all you want is prototype your algorithm and code structure, I'd myself go for emulating one level higher, such as display metatiles and metasprites directly to the screen, as going any lower than that is a waste of time that will anyways be wasted a second time when ported to the NES.
Register-level PPU emulation still lets the programmer build the metatile and metasprite mapping algorithms in a high-level language. If you know your NES-side engine is limited to five 32-byte update packets per vertical blank, you can have the PC version attempt to respect this so that the game's speed doesn't end up tuned based on unrealistic expectations of video memory bandwidth.