Re: [cc65] Disable KERNAL ROM ?

From: Oliver Schmidt <>
Date: 2013-02-14 09:17:18

> I'd rather say that it is more important who the actual target is. For small programs, the final size of a compiled binary is usually plainly repulsive when compared to few lines of assembler that would achieve the same thing.

Then one should do it using a few lines of assembler - honestly. cc65
comes with ca65 and the "new" linker configs for asm programs...

> Depends on how it is done. I personally would like to see the possibility of using all the RAM that can be used. But I also have to agree that it would be good to find a compromise that would not repulse someone who writes the hello.c to see how the compiler works (before getting on to something more serious) and after seeing 22KiB of binary as a result of one printf() just simply gives up. [*]
> [...]
> * - exaggerated on purpose ;-)

Even when taking your (*) into account I need to point out that the
size overhead we're talking about here certainly isn't a fixed one.
The only thing you always have are the IRQ/NMI handlers. The number of
thunks increases with the number of KERNAL calls and therefore with
the complexity of the program.

But let's look at some real numbers. Uz pointed out that the approach
discussed here is similiar to C16 vs. Plus/4. I just used the last
cc65 release (2.13.3) and built the classic hello world

#include <stdio.h>
void main(void)
  printf("Hello, World!\n");

for these two targets with -O. Note that I intentionally didn't
optimize by replacing printf() with puts() or even write() as we're
talking about beginners. Here are the numbers:

C16: 2671 bytes
Plus/4: 2755 bytes

At least to me the result is more than clear. Nobody cares about or
even notices a size increase in that scale. At least not the beginners
we're talking about here. Interestingly the difference is less then
the recent interrupt handling change gained. So potentially a hello
world built with the next release of cc65 for C64 with banking would
have a similiar size to one built with the last release without
banking ;-))

So to me the only argument left in my perspective is the
incompatibility with naive inline assembler. Maybe we should at this
point look at the differences between the two potential approaches
"linear RAM" and "custom segment behind KERNAL (and I/O)":

The custom segment means that by default no part of the program is
actually behind the KERNAL. So nothing keeps you from banking in the
KERNAL at any time you like. It's just that after some C library calls
it might be banked out again. We might discuss thunks that save and
restore the banking they found so that  a KERNAL banked in by the user
would stay banked in after C library calls. And then we might discuss
not banking out the KERNAL initially at all. So the startup/runtime/C
library would "only" set up things to _allow_for_ banking out the
KERNAL. And there would be a C library call for banking out and in. A
program could then use the memory behind the KERNAL either by setting
some pointer there, using heapadd() or using the custom segment and
have the linker/startup code do their magic. At least I personally
would have no issue at all with having to insert a call as the first
line of main() to bank out the KERNAL before starting to call any code
I linked into the custom segment.

The linear RAM on the other hand is easier to use for the pure C
programmer and doesn't produce waste due to not being able to exactly
fill the custom segment. On the other hand however banking in the
KERNAL is no option. And - what might be an important aspect - the
overhead for calling into the KERNAL might increase as every pointer
handed in or out of the KERNAL needs to either live in low RAM or
needs to be double-buffered. Unfortunately I have no overview on the
KERNAL calls used by the C library so I can't fully estimate the
downside of this. But at least for read() / write() it would make a
difference as the buffer they loop over to do BSIN / BSOUT is
potentially (and in fact likely) situated behind the KERNAL. As far as
I understand for write() one could "write through" the KERNAL but for
read() that's no option.

In case my assumptions above are correct my gut feeling is:
- A custom segment might rather replace the current c64 target.
- Linear RAM might rather become an additional target.

I'm personally open for both...

To unsubscribe from the list send mail to with
the string "unsubscribe cc65" in the body(!) of the mail.
Received on Thu Feb 14 09:17:32 2013

This archive was generated by hypermail 2.1.8 : 2013-02-14 09:17:36 CET