Page 1 of 1

cl65 linking problems with a vic20+16k

Posted: Thu Oct 01, 2020 9:14 am
by nanoflite
Hi,

I'm trying to port a game I made for the VIC20+3K to a VIC20+16K. However, I can't figure out how to let the linker generate a program that fits the memory layout of the VIC20+16k.

I put together a small repo explaining the problem I have...
https://github.com/nanoflite/vic20-16k

Here's the README:

CC65 ld65 configurations for the VIC20+16K

I'm trying to figure out how to create a VIC20 program with ca65 that can run on a VIC20 + 16K expansion.

The memory layout would be something like:

Code: Select all

0x1200: BASIC START LINE
0x2000: PROGRAM
I'm trying to create this with result the ld65 linker, but have had no success...

The program


Just a simple 'Hello' program....

I'm using 2 segments here BASIC and CODE.

Code: Select all

  .segment "BASIC"
 
        .word load
load:   .word @end
        .word 2020
        .byte $9e
        .byte .lobyte(main/1000 .mod 10) + $30
        .byte .lobyte(main/100 .mod 10) + $30
        .byte .lobyte(main/10 .mod 10) + $30
        .byte .lobyte(main/1 .mod 10) + $30
        .byte 0 
@end:   .word 0  

  .segment "CODE"

main:   ldx #0
:       lda text,x
        beq end
        jsr $ffd2
        inx
        clc
        bcc :-
end:    rts

text:
  .asciiz "HELLO"
Compile to main.o:

Code: Select all

ca65 -I.  --cpu 6502 main.s
Unexpanded VIC20 configuration

Code: Select all

FEATURES {
    STARTADDRESS: default = $11FF;
}

MEMORY {
    ZP:    start = $0000, size = $0100, type = rw;
    RAM0:  start = $0400, size = $0C00, type = rw;
    RAM:   start = $11FF, size = $0E00, type = rw;
    RAM1:  start = $2000, size = $4000, type = rw;
}

SEGMENTS {
    ZEROPAGE: load = ZP,   type = zp,  optional = yes;
    BASIC:    load = RAM,  type = rw,  optional = no ;
    CODE:     load = RAM,  type = rw,  optional = yes;
    DATA:     load = RAM,  type = rw,  optional = yes;
    BSS:      load = RAM,  type = bss, optional = yes;
}
All segments are in RAM.

Link:

Code: Select all

ld65  -Ln hello-1.lbl -m hello-1.map -C vic20-16k-asm-1.cfg -o hello-1.prg main.o
Result:

Code: Select all

00000000: 0112 0b12 e407 9e34 3632 3100 0000 a200  .......4621.....
00000010: bd1c 12f0 0720 d2ff e818 90f4 6048 454c  ..... ......`HEL
00000020: 4c4f 00                                  LO.
Expanded VIC20 (16K) configuration

Code: Select all

FEATURES {
    STARTADDRESS: default = $11FF;
}

MEMORY {
    ZP:    start = $0000, size = $0100, type = rw;
    RAM0:  start = $0400, size = $0C00, type = rw;
    RAM:   start = $11FF, size = $0E00, type = rw;
    RAM1:  start = $2000, size = $4000, type = rw;
}

SEGMENTS {
    ZEROPAGE: load = ZP,   type = zp,  optional = yes;
    BASIC:    load = RAM,  type = rw,  optional = no ;
    CODE:     load = RAM1, type = rw,  optional = yes;
    DATA:     load = RAM1, type = rw,  optional = yes;
    BSS:      load = RAM1, type = bss, optional = yes;
}
BASIC segment is in RAM, CODE segment is in RAM1.

Link:

Code: Select all

ld65  -Ln hello-2.lbl -m hello-2.map -C vic20-16k-asm-2.cfg -o hello-2.prg main.o
Result:

Code: Select all

00000000: 0112 0b12 e407 9e38 3139 3200 0000 a200  .......8192.....
00000010: bd0f 20f0 0720 d2ff e818 90f4 6048 454c  .. .. ......`HEL
00000020: 4c4f 00                                  LO.
The result is the same... I had hoped that the linker would grow the program so that the code in the 'CODE' segment would live at location 0x2000.

Code: Select all

00000000: 0112 0b12 e407 9e38 3139 3200 0000 0000
00000010: 0000 0000 0000 0000 0000 0000 0000 0000
...
xxxxxxxx: a200 bd0f 20f0 0720 d2ff e818 90f4 454c   <<-- Pointing at 0x02000
...
Question

Why is this not the case and how do I solve this?

Thank you! Johan

Re: cl65 linking problems with a vic20+16k

Posted: Fri Oct 02, 2020 5:46 am
by nanoflite
Expanded VIC20 (16K) configuration - take 2

Found the solution (thanks to https://github.com/cc65/cc65/issues/1276)

Code: Select all

FEATURES {
    STARTADDRESS: default = $11FF;
}

MEMORY {
    ZP:    start = $0000, size = $0100, type = rw;
    RAM0:  start = $0400, size = $0C00, type = rw;
    RAM:   start = $11FF, size = $4E01, type = rw, fill = yes, fillVal = $00;
}

SEGMENTS {
    ZEROPAGE: load = ZP,   type = zp,  optional = yes;
    BASIC:    load = RAM,  type = rw,  optional = no ;
    DATA:     load = RAM,  type = rw,  optional = yes;
    BSS:      load = RAM,  type = bss, optional = yes;
    CODE:     load = RAM,  type = overwrite,  optional = yes, start = $2000;
}

BASIC and CODE segment are in RAM, but CODE is placed at a fixed offset and RAM is filled.

Link:

Code: Select all

ld65  -Ln hello-3.lbl -m hello-3.map -C vic20-16k-asm-3.cfg -o hello-3.prg main.o

Result:

Code: Select all

00000000: 0112 0b12 e407 9e38 3139 3200 0000 0000  .......8192.....
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
...
00000df0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000e00: 00a2 00bd 0f20 f007 20d2 ffe8 1890 f460  ..... .. ......`
00000e10: 4845 4c4c 4f00 0000 0000 0000 0000 0000  HELLO...........
00000e20: 0000 0000 0000 0000 0000 0000 0000 0000  ................
...
00004de0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00004df0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

Success!

What happens here is that the configuration instructs the linker to fill RAM with zeros, starting from 11FF to 6000.
The CODE segment is placed inside RAM, but at a specific location, 2000, overwriting a portion of RAM.

Here are some pointers to the relevant documentation:

* fill: https://cc65.github.io/doc/ld65.html#ss5.6
* overwrite: https://cc65.github.io/doc/ld65.html#ss5.4

Conclusion

The method with fill/overwrite works, but generates a huge file. A better approach would be to split the application in two parts and use a loader.

The linker has support for generating the right data to do this, via the `define` and `file` options.

Then a loader (tape loader) needs to be created that will be placed in the BASIC segment and that loads the other part of the program to the right location.

That's another project.

Re: cl65 linking problems with a vic20+16k

Posted: Fri Oct 02, 2020 6:47 am
by beamrider
Can I ask why you need that particular memory layout [with a hole in it after your loader code @ $1200] ? It's likely if you're writing a game you will need user-defined graphics etc which will need to go in the $1200 - $2000 range anyway, so you might as well link them in.

Re: cl65 linking problems with a vic20+16k

Posted: Fri Oct 02, 2020 7:45 am
by nanoflite
That's true. The memory layout comes from the fact that I wrote the game for the VIC20+3K... although it started out as a game for the unexpanded VIC and because I was not yet very familiar with the VIC20 memory layout when I started this project. So I included the assets into the program and the program copies them to the location for the custom characters. Not optimal.

I now wanted to test my program on a real VIC20... but I only have a 16K RAM expansion... so I though to quickly whip out a version that works on that configuration. Hence this configuration.