Contents of the "nes.lib" in CC65

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Contents of the "nes.lib" in CC65
by on (#123605)
I've got a question about the file "nes.lib" of CC65:

Is this file just there for implementing the pure language features of C, like being able to pass parameters to functions etc., or does it also include help functions that I can actually call in my code?

For example, there is an "nes.h" (which is curiously not in the "cc65-nes-2.13.3-1.zip", but in the general "cc65-win32-2.13.3-1.zip") with two functions: waitvblank and get_tv.

Are these two functions implemented in "nes.lib"?
And are there other functions that have an implementation in "nes.lib" that I could use when including a certain header file?

Or is the "nes.lib" really just there for converting C language constructs into Assembler?
Re: Contents of the "nes.lib" in CC65
by on (#123606)
The nes.lib that you can get with CC65 is not very useful, I don't recommend it.

Shiru made a version of it that he distributed with his NES C tutorial. It is better.

You can use "ar65 l nes.lib" so see the object files contained in the library, in this library there will be one function contained in each object file, but that's just because of the convention. I'm not sure how to look at the exported symbols in an object file or library from cc65 (does anyone know?).

Basically, the nes.lib should contain the necessary C runtime implementation to support the C compiler, plus some NES specific startup stuff, plus whatever useful NES specific functions shiru or whomever wanted to put inside there.

In my own stuff, I use a CRT library built from the stuff in libsrc/runtime/ (minus condes.s, stkchk.s, callirq.s, and callmain.s) plus libsrc/common/copydata.s from the CC65 libraries, and then I wrote my own custom NES startup stuff which also went in there. I used it to make a music ROM for John Coltrane's giant steps. Source here: http://rainwarrior.ca/music/coltrane_src.zip
Re: Contents of the "nes.lib" in CC65
by on (#123633)
The thing is: When I write an NES game in C, I want to do everything myself and not use any external functions.

So, if this is part of my code:
Code:
void MyFunction(unsigned short value)
{
    unsigned short x = value + 1;
}

and the compiler needs a lib for it because passing parameters, creating local variables or handling two byte values is internally done with function calls in Assembler, then I will of course include that lib.

But what I don't want to have is this here:
Code:
#include <neslib.h>

void MyFunction()
{
    char c = get_controller_status();

    init_screen();
    draw_sprites();
}

Using a lib that the compiler needs for even converting the C language syntax into Assembler, that's of course necessary. But using a lib for some helper functions that encapsulate the behavior of the NES and that I can call in my code, that's not what I want because I want to write those things all by myself.

So, when I link the "nes.lib", what will end up in my NES file?

Will the dozens of functions that are included in the "nes.lib" be included in the final ROM? Or are only functions that are actually used somewhere in the code linked in the end?

What happens if I or the compiler that converts my C files to ASM files uses the "import" command to make a function from the lib known to my code, but that function is never actually used? Will that function be included in the NES file?
Re: Contents of the "nes.lib" in CC65
by on (#123634)
DRW wrote:
Will the dozens of functions that are included in the "nes.lib" be included in the final ROM? Or are only functions that are actually used somewhere in the code linked in the end?

Only the functions that you use will be included in the final ROM. Actually technically cc65 only does this at module (source code file) level, but the platform libraries like nes.lib have every function in a separate file so it works as you'd expect.

Quote:
What happens if I or the compiler that converts my C files to ASM files uses the "import" command to make a function from the lib known to my code, but that function is never actually used? Will that function be included in the NES file?

This is only a guess, but I'd guess an .import statement is enough for the function/module to be included into the build. (Reasoning: sometimes it would make sense to ensure a certain module is imported, without using anything from that module)

The C compiler will never generate .import statements unless you use "extern", or it needs one of the compiler support functions (for things such as parameter passing/retrieval, multiplication, etc).
Re: Contents of the "nes.lib" in CC65
by on (#123635)
The nes.lib that I compiled does not have any of my code, only the C compiler runtime. There are things like math routines, popa, popax etc. Here is all what the nes.lib contains.
Re: Contents of the "nes.lib" in CC65
by on (#123637)
thefox wrote:
The C compiler will never generate .import statements unless you use "extern", or it needs one of the compiler support functions (for things such as parameter passing/retrieval, multiplication, etc).

Right, I remembered it incorrectly. It wasn't the functions that are imported.

But the compiler does always import this:
Code:
.importzp   sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
What are those variables good for?

Besides, how does the compiler use calls like this one:
Code:
   jsr     incsp1
(this is generated when a function in C has parameters)
without including something like this in the assembler source file:
Code:
   .import      incsp1


Shiru wrote:
The nes.lib that I compiled does not have any of my code, only the C compiler runtime. There are things like math routines, popa, popax etc.

But in this case, what's the reason behind creating such a lib in the first place instead of using the one from the CC65 website?
Re: Contents of the "nes.lib" in CC65
by on (#123643)
DRW wrote:
But the compiler does always import this:
Code:
.importzp   sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
What are those variables good for?

Offhand I can say "sp" is a pointer to the cc65's software stack and tmp1, ptr1 and ptr2 are obviously some temporary helper variables. Information about others you can find out by googling "<variable name> cc65".

DRW wrote:
Besides, how does the compiler use calls like this one:

Code:
.autoimport on
Re: Contents of the "nes.lib" in CC65
by on (#123644)
DRW wrote:
But in this case, what's the reason behind creating such a lib in the first place instead of using the one from the CC65 website?

It is not creating, it is just compiling existing sources. The reason is to know what is inside rather than use a black box and to exclude all unwanted stuff (lib size is reduced well). I would put my code there too, but I prefer to have it in source form in case of customization for a project (happens often).
Re: Contents of the "nes.lib" in CC65
by on (#123653)
Yeah, that makes sense.

I'm asking myself why those generic C runtime functions are implemented in a lib that's specifically for the NES anyway. I would understand it if the "nes.lib" includes actual callable functions like the stuff from the conio. But does the conversion from pure C syntax into Assembler really work differently on different platforms? Does
Code:
void Test(unsigned char c)
{
}
produce different Assembler code for the NES and for the C64?
Re: Contents of the "nes.lib" in CC65
by on (#123676)
For the most part, no, there is not much that is NES specific in the nes.lib that you can get with CC65. The common CRT is the bulk of it. There is some NES specific stuff, but the kind of stuff they have in CC65's nes.lib is kinda garbage for game making purposes. It's purpose is to help port CC65 programs from other platforms to NES, and they're not designed around game making at all, really.

That's why you should use shiru's cut down nes.lib, or build your own like what I suggested (basically what's in the runtime folder with a few additions/removals). The set I used for my coltrane.nes project is basically the bare minimum needed to support CC65's C compiler, and all the NES specific stuff is in other assembly files I wrote for that project.

Here's the list of what I put in my CRT library:

Code:
libsrc/runtime/*.*
    - Makefile
    - condes.s (removed to disable .constructor/.destructor functionality, which required self modifying code)
    - stkchk.s (removed because it was the only crt module with a .constructor)
    - callirq.s (IRQs should be handled manually in assembly)
    - callmain.s (main is void(), arguments are irrelevant on NES)
libsrc/common/
    + copydata.s (needed to copy DATA segment to RAM)


See the crt0.s in my project for additional startup code needed to initialize the CC65 C runtime (it is very minimal, just need to setup the stack pointer and call the copydata routine from common). The other thing you need is a linker configuration that has the segments required by the C runtime, of which you can look at my nrom.cfg for an example.
Re: Contents of the "nes.lib" in CC65
by on (#123681)
DRW wrote:
I'm asking myself why those generic C runtime functions are implemented in a lib that's specifically for the NES anyway.

Well, that's just a misleading file name. This part of code is normally called 'runtime.lib' (the source folder is called like this), so I probably should rename it after removing the unneeded NES-related stuff.

Edit: well, in fact, I did rename the lib into runtime.lib. The original nes.lib (602K) from CC65 was provided with Alter Ego and Zooming Secretary, but in the C examples and Chase it is runtime.lib (104K). Completely forgot about it.
Re: Contents of the "nes.lib" in CC65
by on (#123689)
rainwarrior wrote:
That's why you should use shiru's cut down nes.lib, or build your own like what I suggested (basically what's in the runtime folder with a few additions/removals).

Yeah, if I ever create a complete game, I might actually remove the linkage to the "nes.lib" and manually insert all the function the compiler complains about into a separate file. Until then, for simplicity's sake, I will just leave it as it is.

Thanks for all the information.
Re: Contents of the "nes.lib" in CC65
by on (#123698)
DRW wrote:
if I ever create a complete game, I might actually remove the linkage to the "nes.lib" and manually insert all the function the compiler complains about into a separate file.

This increases maintenance cost and could easily make the code not compile and link on a different version of ca65, or compile and link but crash, due to the versions of the runtime routines differing.
Re: Contents of the "nes.lib" in CC65
by on (#123699)
So, you suggest me not to use an external runtime library and stick with the official one, correct?
Re: Contents of the "nes.lib" in CC65
by on (#123700)
My advice is to list the benefits of using Shiru's, or your plucked functions, and weigh them against the costs and choose based on which is more beneficial. Does the standard one impose anything on the generated ROM over a custom one if you don't explicitly call anything from it? (e.g. does it have some constructor code that you can't eliminate?)
Re: Contents of the "nes.lib" in CC65
by on (#123701)
blargg wrote:
Does the standard one impose anything on the generated ROM over a custom one if you don't explicitly call anything from it? (e.g. does it have some constructor code that you can't eliminate?)

Questions like that were the reason I was asking in the first place.

So, does it?