Moving MAIN to new address in CC65

You need an actual VIC.

Moderator: Moderators

Post Reply
Floofus
Vic 20 Newbie
Posts: 3
Joined: Fri Jun 05, 2020 6:36 pm
Location: NYC

Moving MAIN to new address in CC65

Post by Floofus »

Hi everybody, I am attempting to compile a C file with CC65 + CA65 + LD65 for VIC-20 + 32k, with a custom cfg file that has a custom MAIN address. I copied the given vic20-32k.cfg to a new cfg file, and simply added $100 to LOADADDR, HEADER and MAIN. My end goal is to move MAIN up enough so that I can place the charset below it. Anyway when I start up the program, it either crashes, fails to start, or gives a basic error. Here is my cfg file:

Code: Select all

SYMBOLS {
    __LOADADDR__:  type = import;
    __EXEHDR__:    type = import;
    __STACKSIZE__: type = weak, value = $0800; # 2k stack
}
MEMORY {
    ZP:       file = "", define = yes, start = $0002, size = $001A;
    LOADADDR: file = %O,               start = $12FF, size = $0002;
    HEADER:   file = %O,               start = $1301, size = $000C;
    MAIN:     file = %O, define = yes, start = $130D, size = $6CF3 - __STACKSIZE__;
}
SEGMENTS {
    ZEROPAGE: load = ZP,       type = zp;
    LOADADDR: load = LOADADDR, type = ro;
    EXEHDR:   load = HEADER,   type = ro;
    STARTUP:  load = MAIN,     type = ro;
    LOWCODE:  load = MAIN,     type = ro,  optional = yes;
    ONCE:     load = MAIN,     type = ro,  optional = yes;
    CODE:     load = MAIN,     type = ro;
    RODATA:   load = MAIN,     type = ro;
    DATA:     load = MAIN,     type = rw;
    INIT:     load = MAIN,     type = bss;
    BSS:      load = MAIN,     type = bss, define   = yes;
}
FEATURES {
    CONDES: type    = constructor,
            label   = __CONSTRUCTOR_TABLE__,
            count   = __CONSTRUCTOR_COUNT__,
            segment = ONCE;
    CONDES: type    = destructor,
            label   = __DESTRUCTOR_TABLE__,
            count   = __DESTRUCTOR_COUNT__,
            segment = RODATA;
    CONDES: type    = interruptor,
            label   = __INTERRUPTOR_TABLE__,
            count   = __INTERRUPTOR_COUNT__,
            segment = RODATA,
            import  = __CALLIRQ__;
}
This is my simple C file, it sets the charset to $0000:

Code: Select all

#define POKE(addr,val) (*(unsigned char*) (addr) = (val))
#define PEEK(addr)     (*(unsigned char*) (addr))

int main (void)
{
    POKE(0x9005, PEEK(0x9005) | 0x8);
    return 0;
}
I have tried using vic20-32k.cfg and also vic20.cfg, both work fine. I also tried mimicking what they did in c64-asm.cfg by using STARTADDRESS, but same no-go results. The map file shows the updated MAIN address in the segment list section, and the produced prg file starts with the correct bytes: 01 13
User avatar
beamrider
Vic 20 Scientist
Posts: 1452
Joined: Sun Oct 17, 2010 2:28 pm
Location: UK

Re: Moving MAIN to new address in CC65

Post by beamrider »

The LOADADR and HEADER have to go into those locations because that's where the BASIC stub must sit on a 32K Vic.

Could you not put your characters above Main at $1800 like this

Code: Select all

LOADADDR: file = %O,     start = $0FFF, size = $0002;
HEADER:   file = %O,      start = $1001, size = $000C;
MAIN:     file = %O, define = yes, start = $100D, size = $1800 -  $100D  , fill=yes;
UDCRAM:	  file = %O,    start = $1800, size = $800;

.
.
.

CODE:     load = MAIN,     type = ro;
RODATA:   load = MAIN,     type = ro;
UDCCHAR:  load = UDCRAM,   type = ro;  	


edit: You could put your UDCs after the EXEHEADER like this...

Code: Select all

MEMORY {
    ZP:       file = "", define = yes, start = $0002, size = $001A;
    LOADADDR: file = %O,               start = $11FF, size = $0002;
    HEADER:   file = %O,               start = $1201, size = $000C;
    UDCRAM:   file = %O, define = yes, fill=yes, start = $120D, size = $0100;
    MAIN:     file = %O, define = yes, start = $130D, size = $8000 - $130D - __STACKSIZE__ ;
}
but the EXEHEADER always jumps to next byte after itself, so you need to link in a custom EXEHEADER with the correct start address.

If you use the above config and then manual SYS to $130D (4877), you will see that it works.

Image



Edit2

You could also link in a stub as follows leaving the CC65 EXEHEADER intact:

Config:

Code: Select all

MEMORY {
    ZP:       file = "", define = yes, start = $0002, size = $001A;
    LOADADDR: file = %O,               start = $11FF, size = $0002;
    HEADER:   file = %O,               start = $1201, size = $000F; # Add 3 bytes for jmp stub
    UDCRAM:   file = %O, define = yes, fill=yes, start =  $1210, size = $0800;
    MAIN:     file = %O, define = yes, start = $1A10, size = $8000 - $1A10 - __STACKSIZE__ ;
}
SEGMENTS {
    ZEROPAGE: load = ZP,       type = zp;
    LOADADDR: load = LOADADDR, type = ro;
    EXEHDR:   load = HEADER,   type = ro;
    EXEHDREX: load = HEADER,  type = ro;
    STARTUP:  load = MAIN,     define   = yes, type = ro;
    LOWCODE:  load = MAIN,     type = ro,  optional = yes;
    ONCE:     load = MAIN,     type = ro,  optional = yes;
    CODE:     load = MAIN,     type = ro;
    RODATA:   load = MAIN,     type = ro;
    DATA:     load = MAIN,     type = rw;
    INIT:     load = MAIN,     type = bss;
    BSS:      load = MAIN,     type = bss, define   = yes;
}

EXEHDREX.s

Code: Select all

.segment "EXEHDREX"
.import __MAIN_START__
jmp __MAIN_START__
..and here it's working. I've increase the UDC allocation to 2K. When you link in your data, you will need to reduce the file size by $0D to account for the BASIC stub.

Image
Floofus
Vic 20 Newbie
Posts: 3
Joined: Fri Jun 05, 2020 6:36 pm
Location: NYC

Re: Moving MAIN to new address in CC65

Post by Floofus »

beamrider wrote: Tue Jun 09, 2020 9:32 am edit: You could put your UDCs after the EXEHEADER like this...
Great, that works! Thank you. I will look into the EXEHEADER fix
Post Reply