This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

"nes.lib" from CC65 not good?

"nes.lib" from CC65 not good?
by on (#154183)
On this forum, I've read a few times that the file "nes.lib" for the CC65 isn't very good and instead an alternate library should be used. And now I wanted to to know why exactly this is the case.

Until now, the only thing that I need the "nes.lib" for is when I have language constructs that cannot be translated directly into assembly code.
For example, when I have a function that takes parameters or when I write something like array[index++] = 5. In this case, the compiler relies on predefined variables and functions and then I have to specify -t nes instead of -t none in the compiler options, so that the compiler takes these functions from the "nes.lib".

But what I haven't done until now is using any actual predefined functions.
For example, I never tried to use printf or clrscr or sleep or something like that for my NES game. All the "nes.lib" does in my program is transforming C language constructs into assembly code.

So, where exactly is the "nes.lib" bad and what's the advantage in using an alternate library?
Re: "nes.lib" from CC65 not good?
by on (#154187)
It's mostly the startup code (crt0.s) in nes.lib that is not great: https://github.com/cc65/cc65/blob/maste ... nes/crt0.s
Re: "nes.lib" from CC65 not good?
by on (#154188)
I'm currently trying to rewrite all these, to make a basic template for writing projects in C, now that I've had some small successes. crt0 and others seem to add a bunch of subroutines to the ROM that I never use, so it will be edited down.
Re: "nes.lib" from CC65 not good?
by on (#154190)
dougeff wrote:
crt0 and others seem to add a bunch of subroutines to the ROM that I never use, so it will be edited down.

Note that the linker will optimize out any object files that are not referenced ("reference" means that some symbol from the object file is imported). So you don't have to go crazy when trying to "optimize" the library.

Off topic: This is actually a pretty cool feature for other uses as well. For example you could have a library with a bunch of graphical tiles. If they are referenced via a symbol, the linker can pull in only the graphics that are used, discarding unused ones.
Re: "nes.lib" from CC65 not good?
by on (#154199)
I meant mostly neslib.s -- it adds a ton of subroutines to the rom that I don't need.

I'm working from Shiru's example files and Chase game files, rather than writing from scratch.
Re: "nes.lib" from CC65 not good?
by on (#154200)
thefox wrote:
It's mostly the startup code (crt0.s) in nes.lib that is not great: https://github.com/cc65/cc65/blob/maste ... nes/crt0.s

I've never used this.
I have my own startup code and NMI interrupt in an actual assembly file. Which I called "Main.s", by the way. I don't know if the name has any influence. However, I don't have an actual int main() anywhere in my program.
Instead, the end of the code in the Reset interrupt (the one that then goes into a forever loop) calls a function named ProcessNextFrame. And that function is my connection to the C code. There, I do all the game-related stuff then.

How would you even call the startup code from the "crt0.s" from the "nes.lib"?
For example, how does the compiler know if it shall include my own code that is declared for .segment "HEADER" or the code from "crt0.s" that is used in .segment "HEADER"? Or what would I have to do to use .segment "CHARS" .include "neschar.inc" in my program?

So far, I have no idea how to use the startup code from the lib if I wanted to. (Of course I don't want to, but out of curiosity.) I mean, unlike functions like rand that you can actually call in your code, I see no way of putting this startup stuff from the "nes.lib" into my program in the first place.


So, apart from that startup code which I don't use anyway, is there any reason not to use the "nes.lib" that is shipped with the compiler and to use another one?


About the subroutines that aren't used: Doesn't the compiler exclude them from the ROM anyway? After all, if it didn't, wouldn't this mean that the ROM automatically includes all the standard C functions, from printf to strlen?
Re: "nes.lib" from CC65 not good?
by on (#154218)
DRW wrote:
How would you even call the startup code from the "crt0.s" from the "nes.lib"?
For example, how does the compiler know if it shall include my own code that is declared for .segment "HEADER" or the code from "crt0.s" that is used in .segment "HEADER"? Or what would I have to do to use .segment "CHARS" .include "neschar.inc" in my program?


The compiler (cc65) turns .c files into .s or directly into .o files.
The assembler (ca65) turns .s into .o files.
The archiver (ar65) turns a collection of .o files into a .lib.

The object file (.o) is basically assembly code turned into a binary format that the linker can use. All of the information decomposed into machine code and symbols and information needed to put everything together. The .s or .o files don't need to know about anything else outside the file. The .import and .export directives create information in the .o file that connect those symbols to other .o files at link time, but when they're being assembled it doesn't matter what they actually point to (doesn't need to know at that point).

The linker (ld65) combines a bunch of .o or .lib files into the final output ROM. The .cfg file specifies to the linker how that ROM will be laid out. The .o/lib files that you specify in the link step are the contents that will fill up the segments specified in the .cfg file.

CC65 does a thing called "lazy linking" with .lib files. It won't include an .o in the link unless something else makes a reference to it. Like, ".import _printf / jsr _printf" in an included file would mean that if it finds in a .lib an .o that has ".export _printf" it will get included in the build.

So... it's the inputs to the linker that decide what goes into the ROM. Specifically the list of .o files, .lib files, and the .cfg file.
Re: "nes.lib" from CC65 not good?
by on (#154219)
I guess you misunderstood me.

My question was not about compilers in general, but about the "crt0.s" in the "nes.lib":

The "nes.lib" has startup code and some other stuff in the "crt0.s". But I never used this. I have my own initialization.
So, how would I even include the "crt0.s" stuff into the ROM if I wanted to use it?

For example, how do you control whether this part of the "crt0.s" gets into your ROM:
Code:
.segment "CHARS"

        .include        "neschar.inc"



However, there's one thing about the general compiler stuff and about lazy linking that I'd like to know:

Let's say I have a source code file with 20 functions. The compiler turns this code file into an object file.
In my main program, I use one of the 20 functions from that file. (And the functions don't reference each other. All of them are standalone.)
Does the linker include the entire contents of the object file into my executable or just that one function that I used?
Re: "nes.lib" from CC65 not good?
by on (#154220)
DRW wrote:
The "nes.lib" has startup code and some other stuff in the "crt0.s". But I never used this. I have my own initialization.
So, how would I even include the "crt0.s" stuff into the ROM if I wanted to use it?

I believe that the compiler will shove a ".forceimport __STARTUP__" into the module where you define main(). This in turn will pull in crt0.s (because it defines the __STARTUP__ symbol). If you don't define main(), crt0 won't get linked unless you actually reference some of the symbols exported from there.

Quote:
Let's say I have a source code file with 20 functions. The compiler turns this code file into an object file.
In my main program, I use one of the 20 functions from that file. (And the functions don't reference each other. All of them are standalone.)
Does the linker include the entire contents of the object file into my executable or just that one function that I used?

It will include the entire object file. No, there's no way to include only portions of it (other than defining each function in a separate object file, which is actually done quite a lot in the cc65 runtime library).

EDIT: One more note: it will only do the optimization for libraries. If you explicitly specify an object file on the command line, it gets always included.
Re: "nes.lib" from CC65 not good?
by on (#154238)
dougeff wrote:
I meant mostly neslib.s -- it adds a ton of subroutines to the rom that I don't need.


I've never used it in relation to the C compiler (if it makes any difference), but in the assembler I've used the .IFREF directive to exclude subroutines if they aren't referenced.