I heard there were C compilers for the Game Boy as well but as far I know they were never widely used.
I heard there were C compilers for the Game Boy as well but as far I know they were never widely used.
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 code so that the code for each bank is in it's own section, and then tell the linker to link each of those sections at the address that it will be switched in at (Likely the same address for most of them). It might just barf at you, but a linker specifically for systems that do memory banking should have a way to express this.
That's why, even if you hacked so that Goomba's death behavior should point to the same as that of a Drybones, it would fail as the subroutine for that behavior isn't in the same bank as the Goomba.
They had the same features up until at least Xbox 360; they're just called 'overlays' on non execute from ROM systems. It doesn't really take an esoteric compiler or environment.
On old (16-bit) x86 you used "far" pointers, which were larger for cross segment access. These were larger and I assume slower since they encoded both the within-segment address and the segment number.
And admittedly, it can be hard to see where the hand-coded assembly ends and the compiled C code begins. There are occasional stylistic clues, but I'm generally spending more time figuring out what something does and why it's written than I am which language each piece was coded in. Most of the file and memory handling seems to be done through calls to the C library in that game.