Nate5700 wrote:
I've coded in C/C++, Java, most recently Haxe (one not as many folks are familiar with but it's quite similar to Java). Anyway, it's been a while since I've done anything in C or C++ but I do remember what a struct is, so that's a helpful analogy. I guess what I'm getting hung up on is having to allocate the memory manually for each thing and having that space reserved, as opposed to just saying "struct xyz" and that all happening automatically. In other words, how to keep it all organized? For some things it seems simple, like having labels for bytes in RAM like "scroll_x" and "scroll_y". But for stuff that's more dynamic? Like, it doesn't make sense for every enemy in the game to have its own RAM space to track it's location and alive/dead state. So I guess I just need a bucket of RAM reserved to keep things like that in kind of a tabular format and load/unload things into/from it as needed. I guess I'm just wondering if there are tried and tested methods for this that are commonly used.
The 3 posts above mine here are applicable to this question, but the short answer is this:
Higher-level languages -- which C falls under in this case -- hide a very large amount of the work actually going on at the CPU level. I'm speaking generally and abstractly here (i.e. what I say is for the most part true but not entirely): a CPU itself has no real concept of memory management. There is no CRT/crt0 (C run-time library) in the CPU. There is no concept of
malloc/free (part of libc or other base library) in the CPU. In fact, for the most part, there is no concept of a kernel in the CPU. The CPU will do whatever it's told. Present-day CPUs (x86/x64) are complicated and have insane layers of memory modelling and features that I don't want to get into. Ignore all that and think simple.
With the NES, you are literally writing assembly code that runs native on the CPU. Software-wise, it doesn't get more low level than that. On common-day x86 this is also true (as long as you ignore the x86/x64 microcode part) (I used to code in 286/386 assembly back in the day, so I'm a bit familiar with that platform too, but today things are a complicated mess). On the NES, there is no OS, there is no BIOS, it's literally "CPU starts running your code at address $8000" and you do everything yourself (esp. relating to memory).
Strictly speaking about memory:
What you know on the NES is the following: it has 2KBytes of RAM located within address range $0000 to $07FF. That's it. The end. Really. :-) How you choose to use (access, use, segregate/split up/etc.) is entirely up to you and the code you write. There is no concept of "dynamically allocated memory" at the CPU level (on any CPU, actually!); actual machine code has to do this.
I had a bigger write up here, but I decided to put it on pastebin since it very quickly gets a bit off-topic (that is to say, off the topic of memory layout/management) very quickly, so you can read it only if you want to:
https://pastebin.com/LPi7ZfK7Asking if there are tried-and-true methods for all of this (good layout, etc.) is a good question, and appreciated, but I think most of the answers you'll get on this subject are very specific. For example, if you were to ask that about, say, map design -- because you idealise having huge open worlds (say, twice as large as the overworld Zelda 1) -- people might be able to say "well it depends on X/Y/Z/A/B/C. Can you give us some insight into those?", you answer, and they say "I'd suggest you lay out your map data like this, and here's why".
But when it comes to just general RAM/memory layout, I don't think there's any kind of commonplace "good recommendation".
I think one of the blockers here, conversationally, is that you don't know 6502 assembly. Once you get familiar with that, you're going to learn the limits of the CPU, and why certain things are the way they are. A big one is that you're going to learn why there is so much on the 6502 that relates to or revolves around the number 256 (specifically, pages of memory, where a page is always 256 bytes in size, ex. $0000 to $00FF is page 0 (zero page), $0100 to $01FF is page 1, etc.)), and that how you go about accessing >256 bytes (or even doing things like handling a number larger than 256, e.g. a score), is kind of "weird" compared to existing PLs and x86/x64 CPUs you're used to today (64-bit linear addressing is a LOT of addressing space!). You'll also learn just how annoying multiplication/division is on the 6502, and how a lot of how you do code (and everything, actually!) tries to minimise use of anything other than bitshifts for *2 (4, 8, 16...) or /2 (4, 8, 16...). This is getting a bit off-topic; my point is that once you learn 6502, a lot of the "memory layout" questions you have you'll be able to answer yourself, and if you get stumped on something precise, you'll know what to ask.
In general, I don't think anyone has really ever tried to document "what's universally best" for this type of thing on a particular architecture (NES) or CPU (6502), with regards to doing a game. It's because everyone ends up doing it differently -- and that's the same thing seen in commercial NES games too (Capcom had their own way of doing stuff, Konami did, Nintendo did, Rare did, Acclaim did, etc.).