Jump to content
IGNORED

CC65 config file - how to use the segment properly


Recommended Posts

i want to add 3 memory segrments:

 

1. Player Missile Memory

2. Display List

3. Screen Memory

 

i add to the cfg file in the section memory the 3 new values:

MEMORY {
    ZP:         file = "", define = yes, start = $0082, size = $007E;

# file header, just $FFFF
    HEADER:     file = %O,               start = $0000, size = $0002;

# "system check" load chunk
    SYSCHKHDR:  file = %O,               start = $0000, size = $0004;
    SYSCHKCHNK: file = %O,               start = $2E00, size = $0300;
    SYSCHKTRL:  file = %O,               start = $0000, size = $0006;
    PMGMEMORY:  file = %O,               start = $2000, size = $0800;
    DISPLAYLIST:file = %O,               start = $2900, size = $0400;
    SCREEN_MEMORY:file = %O,             start = $2E00, size = $0800;
# "main program" load chunk
    MAINHDR:    file = %O,               start = $0000, size = $0004;
    MAIN:       file = %O, define = yes, start = %S,    size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
    TRAILER:    file = %O,               start = $0000, size = $0006;
}

is the given addresses above correct?

PMG - 2K boundary

DLIST - 1K Boundary

ScreenMem - 1000 Bytes (45X25) char Antic mode 4

 

Then i added in the config file the segment part to use these location:

SEGMENTS {
    ZEROPAGE:  load = ZP,         type = zp;
    EXTZP:     load = ZP,         type = zp,                optional = yes;
    EXEHDR:    load = HEADER,     type = ro;
    SYSCHKHDR: load = SYSCHKHDR,  type = ro,                optional = yes;
    SYSCHK:    load = SYSCHKCHNK, type = rw,  define = yes, optional = yes;
    SYSCHKTRL: load = SYSCHKTRL,  type = ro,                optional = yes;
    MAINHDR:   load = MAINHDR,    type = ro;
    STARTUP:   load = MAIN,       type = ro,  define = yes;
    LOWBSS:    load = MAIN,       type = rw,                optional = yes;  # not zero initialized
    LOWCODE:   load = MAIN,       type = ro,  define = yes, optional = yes;
    ONCE:      load = MAIN,       type = ro,                optional = yes;
    CODE:      load = MAIN,       type = ro,  define = yes;
    RODATA:    load = MAIN,       type = ro;
    DATA:      load = MAIN,       type = rw;
    INIT:      load = MAIN,       type = rw,                optional = yes;
    BSS:       load = MAIN,       type = bss, define = yes;
    AUTOSTRT:  load = TRAILER,    type = ro;
    PMGMEM:    load = PMGMEMORY,  type = ro,   define = yes;
    DLIST:     load = DISPLAYLIST,  type = ro, define = yes;
    SCRMEM:    load = SCREEN_MEMORY,  type = ro, define = yes;
}

i defined them as RO (read only?) and used define = yes

is that correct?

 

now i want to use these memory locations in my CC65 code.

 

i know i need to use the #pragma directive for that.

but i am not sure on how to use that proerply in the code.

 

for example,

i want to let ANTIC know that the PMG memory addressis PMGMEM (from the config file)

 

so i can do this:

#pragma data-name (push, "PMGMEM")

 

but now comes my question. i can use below the PMGMEM, but when do i do the #pragma pop part?

 

i need a good example for that

 

thanks in advanced

 

Cheer

Link to comment
Share on other sites

The MEMORY part of the cfg file is to fix the locations. The SEGMENT part can be used to pre-populate them, but that is optional.

 

But your cfg file, as is, doesn't work. You need to create "chunk headers" for each part of memory you want to load independently from the MAIN chunk. See the MAINHDR memory area.

 

So, if you don't know the format of Atari executable files, it's better to use the atari-xex.cfg instead of atari.cfg as starting point. With this config file, cc65 takes care about the details of the executable format. For each MEMORY definition if will automatically create an appropriate chunk header.

Link to comment
Share on other sites

i will use the atari-xex.cfg . thank you sanny. and thanks for explaning that for my need i should only use the MEMORY part and not the SEGMENT part of the cfg.

 

one thing still remains as a question. once defined in the MEMORY sectiono of the cfg. how do i use it in code ?

do i use it explicitly? meaning, just use the variable as i name it in the MEMORY section?

do i use it using pargma directive? if so, how extactly? give an example

 

thanks again

cheers

Link to comment
Share on other sites

MEMORY {
    PMG:        file = %O,               start = $2000, size = $0800;
    DLIST:      file = %O,               start = $2900, size = $0400;
    SCRMEM:     file = %O,               start = $2E00, size = $03EB;
    ZP:         file = "", define = yes, start = $0082, size = $007E;
# "system check" load chunk
    SYSCHKCHNK: file = %O,               start = $2E00, size = $0300;
# "main program" load chunk
    MAIN:       file = %O, define = yes, start = %S,    size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
}

this is the snippet of the new cfg file i am using, where you can see i've added to memory section the 3 new memory locations to be used in the code

 

please show me an example on how to use it in the code?

if i try to do it explicity i get an error....

Link to comment
Share on other sites

i will use the atari-xex.cfg . thank you sanny. and thanks for explaning that for my need i should only use the MEMORY part and not the SEGMENT part of the cfg.

 

You didn't answer whether you want to pre-populate or not. If you just want to define the memory areas and not pre-populate them, the atari.cfg should work as well (as you posted, but you don't need the SEGMENT defines then).

 

See https://cc65.github.io/doc/ld65.html#ss5.6

 

You should add "define=yes" to the memory definition, then there will be symbols "__<name>_START__" available.

 

Use #pragma to put data into these memory areas (but as I think you don't want to pre-populate them).

 

Then, for example, to set the DList address:

extern unsigned char _DLIST_START__[];

...
OS.sdlst = _DLIST_START__;

Untested...

Link to comment
Share on other sites

Hi Sanny,

 

this is the cfg file:

FEATURES {
    STARTADDRESS: default = $7000;
}
SYMBOLS {
    __SYSTEM_CHECK__:    type = import;  # force inclusion of "system check" load chunk
    __STACKSIZE__:       type = weak, value = $0800; # 2k stack
    __STARTADDRESS__:    type = export, value = %S;
    __RESERVED_MEMORY__: type = weak, value = $0000;
    __SYSCHKHDR__:       type = export, value = 0; # Disable system check header
    __SYSCHKTRL__:       type = export, value = 0; # Disable system check trailer
}
MEMORY {
    PMGMEM:     file = "", define = yes, start = $2000, size = $0800;
    DLISTMEM:   file = "", define = yes, start = $2900, size = $0400;
    SCRMEM:     file = "", define = yes, start = $2E00, size = $03EB;
    ZP:         file = "", define = yes, start = $0082, size = $007E;
# "system check" load chunk
    SYSCHKCHNK: file = %O,               start = $2E00, size = $0300;
# "main program" load chunk
    MAIN:       file = %O, define = yes, start = %S,    size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
}
FILES {
    %O: format = atari;
}
FORMATS {
    atari: runad = start,
           initad = SYSCHKCHNK: __SYSTEM_CHECK__;
}
SEGMENTS {
    ZEROPAGE:  load = ZP,         type = zp;
    EXTZP:     load = ZP,         type = zp,                optional = yes;
    SYSCHK:    load = SYSCHKCHNK, type = rw,  define = yes, optional = yes;
    STARTUP:   load = MAIN,       type = ro,  define = yes;
    LOWBSS:    load = MAIN,       type = rw,                optional = yes;  # not zero initialized
    LOWCODE:   load = MAIN,       type = ro,  define = yes, optional = yes;
    ONCE:      load = MAIN,       type = ro,                optional = yes;
    CODE:      load = MAIN,       type = ro,  define = yes;
    RODATA:    load = MAIN,       type = ro;
    DATA:      load = MAIN,       type = rw;
    INIT:      load = MAIN,       type = rw,                optional = yes;
    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__;
}

i've highlighted above the new 3 memory names that i've added

 

here is rthe map file:

Modules list:
-------------
dli.o:
    CODE              Offs=000000  Size=00000B  Align=00001  Fill=0000
main.o:
    CODE              Offs=00000B  Size=000010  Align=00001  Fill=0000
    DATA              Offs=000000  Size=000001  Align=00001  Fill=0000
C:\Program Files (x86)\CC65/lib/atari.lib(callmain.o):
    CODE              Offs=00001B  Size=000017  Align=00001  Fill=0000
    DATA              Offs=000001  Size=000004  Align=00001  Fill=0000
C:\Program Files (x86)\CC65/lib/atari.lib(condes.o):
    CODE              Offs=000032  Size=00000C  Align=00001  Fill=0000
    DATA              Offs=000005  Size=000025  Align=00001  Fill=0000
    ONCE              Offs=000000  Size=00000C  Align=00001  Fill=0000
C:\Program Files (x86)\CC65/lib/atari.lib(crt0.o):
    BSS               Offs=000000  Size=000005  Align=00001  Fill=0000
    STARTUP           Offs=000000  Size=000063  Align=00001  Fill=0000
C:\Program Files (x86)\CC65/lib/atari.lib(pushax.o):
    CODE              Offs=00003E  Size=00001A  Align=00001  Fill=0000
C:\Program Files (x86)\CC65/lib/atari.lib(system_check.o):
    SYSCHK            Offs=000000  Size=0000F6  Align=00001  Fill=0000
C:\Program Files (x86)\CC65/lib/atari.lib(zerobss.o):
    CODE              Offs=000058  Size=000023  Align=00001  Fill=0000
C:\Program Files (x86)\CC65/lib/atari.lib(zeropage.o):
    ZEROPAGE          Offs=000000  Size=00001A  Align=00001  Fill=0000


Segment list:
-------------
Name                   Start     End    Size  Align
----------------------------------------------------
ZEROPAGE              000082  00009B  00001A  00001
SYSCHK                002E00  002EF5  0000F6  00001
STARTUP               007000  007062  000063  00001
ONCE                  007063  00706E  00000C  00001
CODE                  00706F  0070E9  00007B  00001
DATA                  0070EA  007113  00002A  00001
BSS                   007114  007118  000005  00001


Exports list by name:
---------------------
__BSS_RUN__               007114 RLA    __BSS_SIZE__              000005 REA    
__CONSTRUCTOR_COUNT__     000000 REA    __CONSTRUCTOR_TABLE__     00706F RLA    
__DESTRUCTOR_COUNT__      000000 REA    __DESTRUCTOR_TABLE__      0070EA RLA    
__LOWCODE_RUN__           007063 RLA    __LOWCODE_SIZE__          000000 REA    
__RESERVED_MEMORY__       000000 REA    __STACKSIZE__             000800 REA    
__STARTADDRESS__          007000 REA    __STARTUP__               000001 REA    
__SYSCHKHDR__             000000 REA    __SYSCHKTRL__             000000 REA    
__SYSTEM_CHECK__          002E47 REA    _main                     007087 RLA    
callmain                  00708A RLA    donelib                   0070A1 RLA    
initlib                   007063 RLA    ptr1                      00008A RLZ    
pushax                    0070B1 RLA    sp                        000082 RLZ    
start                     007001 RLA    zerobss                   0070C7 RLA    



Exports list by value:
----------------------
__SYSCHKTRL__             000000 REA    __RESERVED_MEMORY__       000000 REA    
__SYSCHKHDR__             000000 REA    __LOWCODE_SIZE__          000000 REA    
__CONSTRUCTOR_COUNT__     000000 REA    __DESTRUCTOR_COUNT__      000000 REA    
__STARTUP__               000001 REA    __BSS_SIZE__              000005 REA    
sp                        000082 RLZ    ptr1                      00008A RLZ    
__STACKSIZE__             000800 REA    __SYSTEM_CHECK__          002E47 REA    
__STARTADDRESS__          007000 REA    start                     007001 RLA    
initlib                   007063 RLA    __LOWCODE_RUN__           007063 RLA    
__CONSTRUCTOR_TABLE__     00706F RLA    _main                     007087 RLA    
callmain                  00708A RLA    donelib                   0070A1 RLA    
pushax                    0070B1 RLA    zerobss                   0070C7 RLA    
__DESTRUCTOR_TABLE__      0070EA RLA    __BSS_RUN__               007114 RLA    



Imports list:
-------------
__BSS_RUN__ ([linker generated]):
    zerobss.o                 common/zerobss.s(
    system_check.o            atari/system_check.s(23)
__BSS_SIZE__ ([linker generated]):
    zerobss.o                 common/zerobss.s(
    system_check.o            atari/system_check.s(23)
__CONSTRUCTOR_COUNT__ ([linker generated]):
    condes.o                  runtime/condes.s(18)
__CONSTRUCTOR_TABLE__ ([linker generated]):
    condes.o                  runtime/condes.s(18)
__DESTRUCTOR_COUNT__ ([linker generated]):
    condes.o                  runtime/condes.s(19)
__DESTRUCTOR_TABLE__ ([linker generated]):
    condes.o                  runtime/condes.s(19)
__LOWCODE_RUN__ ([linker generated]):
    crt0.o                    atari/crt0.s(18)
__LOWCODE_SIZE__ ([linker generated]):
    crt0.o                    atari/crt0.s(18)
__RESERVED_MEMORY__ ([linker generated]):
    system_check.o            atari/system_check.s(25)
    crt0.o                    atari/crt0.s(16)
    [linker generated]        atari.cfg(20)
__STACKSIZE__ ([linker generated]):
    system_check.o            atari/system_check.s(24)
    [linker generated]        atari.cfg(20)
__STARTADDRESS__ ([linker generated]):
    system_check.o            atari/system_check.s(20)
__STARTUP__ (crt0.o):
    main.o                    main.s(13)
__SYSCHKHDR__ ([linker generated]):
    system_check.o            atari/system_check.s(28)
__SYSCHKTRL__ ([linker generated]):
    system_check.o            atari/system_check.s(28)
__SYSTEM_CHECK__ (system_check.o):
    [linker generated]        atari.cfg(27)
    [linker generated]        atari.cfg(5)
_main (main.o):
    callmain.o                runtime/callmain.s(11)
callmain (callmain.o):
    crt0.o                    atari/crt0.s(15)
donelib (condes.o):
    crt0.o                    atari/crt0.s(14)
initlib (condes.o):
    crt0.o                    atari/crt0.s(14)
ptr1 (zeropage.o):
    zerobss.o                 common/zerobss.s(9)
pushax (pushax.o):
    callmain.o                runtime/callmain.s(11)
sp (zeropage.o):
    pushax.o                  runtime/pushax.s(
    crt0.o                    /home/travis/build/cc65/cc65/asminc/zeropage.inc(11)
start (crt0.o):
    [linker generated]        atari.cfg(26)
zerobss (zerobss.o):
    crt0.o                    atari/crt0.s(15)


as you can see, no reference for any other the new 3 names

 

help??

Link to comment
Share on other sites

how can i make sure that when i write this:

extern unsigned char __DLISTMEM_START__;

it will refer to the MEMORY name in the cfg file and will have the proper value (in this case 0x2900)?

 

 

additional info:

 

i've looked at an example game called 'the curse of the lost miner" which was written in CC65.

So the config file there DOES define SEGMENT part of the memory values. it gives them the type of BSS which means un-initialized.

then in an asm file it defines an ".segment" with the name of the SEGEMENT in the config

it also uses the ".export" to that SEGMENT in the asm file and lastly it uses in the main code the "extern" as you described.

 

so i am a bit confused....

Edited by Yaron Nir
Link to comment
Share on other sites

Though the docs say define can be used in the MEMORY section I've always gone by its use in the SEGMENTS.

 

Couple of questions -

DLISTMEM is at $2900, why not $2800 as a size of $400 would wrap a boundary?
SCRMEM is at $2E00 but if you move DLISTMEM then this could go to $2C00 and so the size also fits within a boundary.

 

SYSCHKCHNK then overlaps but that shouldn't be an issue really but could be pushed to $3000 to be on the safe side as you've already pushed code start to $7000

Link to comment
Share on other sites

Though the docs say define can be used in the MEMORY section I've always gone by its use in the SEGMENTS.

 

Couple of questions -

DLISTMEM is at $2900, why not $2800 as a size of $400 would wrap a boundary?

SCRMEM is at $2E00 but if you move DLISTMEM then this could go to $2C00 and so the size also fits within a boundary.

 

SYSCHKCHNK then overlaps but that shouldn't be an issue really but could be pushed to $3000 to be on the safe side as you've already pushed code start to $7000

 

Well, the initial addresses were as you suggested. I can change these back.

 

Wrathchild, please help me out here.

 

so i have MEMORY and SEGMENT in the cfg.

 

now how do i use the segment in the CC65 code?

 

for example, i want to use PMGMEMORY (this is how it is defined in the SEGMENT part of the cfg) in the code

for example, tell ANTIC the address.

so one would wrtite:

POKE(0xD407 , (unsigned int)PMGMEMORY >> 8);

 

but for now, the PMGMEMORY is undefined symbol

 

plz help?

Link to comment
Share on other sites

There are several ways of doing that.

I do it using assembler as follows (it might not be the best way)

 

file gamedata.asm:

 

;-------------------------------------------------------------------------------
; PMG Area (dummy segment, not written to the binary file)
;-------------------------------------------------------------------------------
.segment "CLM_SEG_PMGAREA"       ;Whatever is defined below this will be in the "CLM_SEG_PMGAREA" segment defined in the linker .cfg file
_CLM_DATA_PMGAREA:               ;Define a label
.export  _CLM_DATA_PMGAREA       ;Ensure that the label is visible for the main c program
file main.c:
extern unsigned char  CLM_DATA_PMGAREA;
...
/*Set PMG memory start*/
    POKE(54279U,((unsigned)(&CLM_DATA_PMGAREA))>>;

Edited by baktra
Link to comment
Share on other sites

how can i make sure that when i write this:

extern unsigned char __DLISTMEM_START__;

it will refer to the MEMORY name in the cfg file and will have the proper value (in this case 0x2900)?

 

 

additional info:

 

i've looked at an example game called 'the curse of the lost miner" which was written in CC65.

So the config file there DOES define SEGMENT part of the memory values. it gives them the type of BSS which means un-initialized.

then in an asm file it defines an ".segment" with the name of the SEGEMENT in the config

it also uses the ".export" to that SEGMENT in the asm file and lastly it uses in the main code the "extern" as you described.

 

so i am a bit confused....

 

The asm file doesn't define a segment. It only says whatever is defined below the .segment directive belongs to the named segment. The segment must be already defined in the .cfg file.

The .export directive ensures that the label in the segment is visible for the main .c program. The c program sees the label as an unsigned char variable.

Link to comment
Share on other sites

hehehe baktra , so i've looked exactly at your example. this is taken from the curse of the lost miner game i've menition above right?

 

is there a way to use #pragma directive instead of the asm file?

I am not sure, but you can try the following:

#pragma bss-name ("PMG_SEGMENT")  //Temporarily change segment for uninitialized data to PMG_SEGMENT
unsigned char pmg_area;        
#pragma bss-name ("BSS")          //Change back to standard BSS segment      

int main() {

...

}
Edit: It actually works. I tested with modified CuLoMin source. Note that there is no extern. Also ensure you do not assign any value to the variable. Edited by baktra
Link to comment
Share on other sites

Something like sanny's approach in post #7 should suffice.

 

Only use one underscore when using it in C as C adds the prefixing underscore to variable names.

You can see this in baktra's assembly as that uses the prefixing underscore on the name but in C it isn't needed.

 

e.g. this (just using CODE as an example, not for real-life)

#include <atari.h>

extern unsigned char _CODE_START__[];

int main()
{
  OS.sdlst = _CODE_START__;
  return 0;
}
produces:
.proc _main: near

.segment "CODE"

lda     #>(__CODE_START__)
sta     $0230+1
lda     #<(__CODE_START__)
sta     $0230
ldx     #$00
txa
rts

.endproc
  • Like 1
Link to comment
Share on other sites


#pragma bsseg ("PMG_SEGMENT")  //Temporarily change segment for uninitialized data to PMG_SEGMENT
unsigned char pmg_area;        
#pragma bsseg ("BSS")          //Change back to standard BSS segment      

int main() {

...

}

#pragma bsseg is undefined , are you sure this is the proper pragma?

 

from what i read one can use #pragma data-name (push,"PMGMEM")

and

#pragma data-name(pop)

Link to comment
Share on other sites

 


#pragma bsseg ("PMG_SEGMENT")  //Temporarily change segment for uninitialized data to PMG_SEGMENT
unsigned char pmg_area;        
#pragma bsseg ("BSS")          //Change back to standard BSS segment      

int main() {

...

}
#pragma bsseg is undefined , are you sure this is the proper pragma?

 

from what i read one can use #pragma data-name (push,"PMGMEM")

and

#pragma data-name(pop)

 

 


#pragma bsseg ("PMG_SEGMENT")  //Temporarily change segment for uninitialized data to PMG_SEGMENT
unsigned char pmg_area;        
#pragma bsseg ("BSS")          //Change back to standard BSS segment      

int main() {

...

}
#pragma bsseg is undefined , are you sure this is the proper pragma?

 

from what i read one can use #pragma data-name (push,"PMGMEM")

and

#pragma data-name(pop)

 

Sorry. It actually is #pragma bss-name. Fixed in the post above.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...