TGB1718 Posted November 22, 2021 Share Posted November 22, 2021 In a program I'm writing, I want to reserve the 16K memory area @ $4000 , I've looked through the cc65 manual and found a topic which says you need a different config file and it gives an example of how to do this. I've copied the example given and compiled as shown, but it throws out several errors and won't compile. I tried changing the parameters, but can't seem to resolve the issues Just wondering if anyone has used this and got it working ? Quote Link to comment Share on other sites More sharing options...
sanny Posted November 22, 2021 Share Posted November 22, 2021 I'd guess the example from the docs is outdated. ? Can you post that exactly did you try and the errors you got? Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted November 22, 2021 Author Share Posted November 22, 2021 This is what I get:- ld65: Warning: split.cfg(49): Segment 'EXEHDR' does not exist ld65: Warning: split.cfg(49): Segment 'MAINHDR' does not exist ld65: Warning: split.cfg(49): Segment 'AUTOSTRT' does not exist ld65: Warning: split.cfg(14): Segment 'CODE' overflows memory area 'RAMLO' by 5676 bytes ld65: Error: Cannot generate most of the files due to memory area overflow Quote Link to comment Share on other sites More sharing options...
ilmenit Posted November 22, 2021 Share Posted November 22, 2021 By reserving do you mean excluding it from code/data (for ext.mem bank)? Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted November 22, 2021 Author Share Posted November 22, 2021 2 minutes ago, ilmenit said: By reserving do you mean excluding it from code/data (for ext.mem bank)? Maybe for later I will need the bank, but for now I just want that area free Quote Link to comment Share on other sites More sharing options...
ilmenit Posted November 22, 2021 Share Posted November 22, 2021 13 minutes ago, TGB1718 said: Maybe for later I will need the bank, but for now I just want that area free I will try to make a minimal example for it, but meanwhile you can look at the compilation and cfg of https://github.com/ilmenit/AdamIsMe where I'm using it. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted November 22, 2021 Author Share Posted November 22, 2021 @ilmenit Many thanks, I did try yours, but still loads of errors similar to the example I tried ld65: Warning: split.cfg(83): Segment 'FILEHDR' does not exist ld65: Warning: split.cfg(83): Segment 'NEXEHDR' does not exist ld65: Warning: split.cfg(83): Segment 'GFX' does not exist ld65: Warning: split.cfg(83): Segment 'FIRST_END' does not exist ld65: Warning: split.cfg(83): Segment 'SFX' does not exist ld65: Warning: split.cfg(83): Segment 'CHKHDR' does not exist ld65: Warning: split.cfg(33): Segment 'DATA' overflows memory area 'RAM' by 193 bytes ld65: Error: Cannot generate most of the files due to memory area overflow Quote Link to comment Share on other sites More sharing options...
sanny Posted November 22, 2021 Share Posted November 22, 2021 Most warnings can be ignored, but not the ones like "...overflows memory area...". There is not enough space in this area, you need to shuffle around and put something into other segments. Quote Link to comment Share on other sites More sharing options...
sanny Posted November 22, 2021 Share Posted November 22, 2021 Make a verbose map file to see what things are in this overflowing area and pick some and put them into another area. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted November 22, 2021 Author Share Posted November 22, 2021 8 minutes ago, sanny said: Most warnings can be ignored, but not the ones like "...overflows memory area...". There is not enough space in this area, you need to shuffle around and put something into other segments. Unfortunately I have no idea how to do this 8 minutes ago, sanny said: Make a verbose map file to see what things are in this overflowing area and pick some and put them into another area. or this Quote Link to comment Share on other sites More sharing options...
sanny Posted November 22, 2021 Share Posted November 22, 2021 cl65 -tatari -C file.cfg -O -m hello.map -vm -o hello.com hello.c This will create a hello.map map file. Quote Link to comment Share on other sites More sharing options...
ggn Posted November 22, 2021 Share Posted November 22, 2021 (edited) For what it's worth: @ilmenit's repository builds successfully here by editing "build-atari.bat" and changing the path of cc65 and then executing the script in Windows. Edited November 22, 2021 by ggn Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted November 22, 2021 Author Share Posted November 22, 2021 36 minutes ago, sanny said: cl65 -tatari -C file.cfg -O -m hello.map -vm -o hello.com hello.c This will create a hello.map map file. Thank you, I now have a map and can see why there's an overflow error. not quite sure what to do about it, just trying to figure out where it's getting it's values from. I'll go back to the original config file and see if I can fix that one Quote Link to comment Share on other sites More sharing options...
ivop Posted November 22, 2021 Share Posted November 22, 2021 3 hours ago, sanny said: Most warnings can be ignored Why, I assume they are there for a reason? Quote Link to comment Share on other sites More sharing options...
sanny Posted November 22, 2021 Share Posted November 22, 2021 43 minutes ago, ivop said: Why, I assume they are there for a reason? I don't know those segments, they are custom made. The author knows if it's fatal if they are not present. One would need to look at the full project and not just the error messages. Quote Link to comment Share on other sites More sharing options...
ilmenit Posted November 22, 2021 Share Posted November 22, 2021 (edited) In attachment there is a "minimalistic example" I tried to put to explain how to use the linker .CFG to generate any output that is desired. In the example the code is split into two segments: from $2000 to $4000 from $8000 up First, it's not easy to understand what's going on and took me a while to read the documentation. It's complex, but reason is that it's very flexible and allows to generate binary files for any platform, in any format. Maybe there is some other, easier way of defining it and if anybody knows I'd be grateful for this information. The linker configuration file description is here https://cc65.github.io/doc/ld65.html#s5 and if you want to prepare your own unfortunately you have to understand most of it. You will also need to understand Atari executable format to build proper XEX file. I'll try to explain here shortly how to create a file with "reserved window" $4000 to $8000 for use of Extended Memory. In fact you can put code and data also there (as long as you make sure that nothing of it is used when this memory is banked out). Lets start then. For the first two sections of .CFG file (FEATURES and SYMBOLS) I recommend to read the manual: # Main memory block is loaded after RMT music FEATURES { STARTADDRESS: default = $2000; } SYMBOLS { __FILEHDR__: type = import; __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STACKSIZE__: type = weak, value = $400; __STARTADDRESS__: type = export, value = %S; __RESERVED_MEMORY__: type = weak, value = $0000; __RAM_AVAIL__: value = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__, type = weak; } Writing code in CC65 for Atari you should at least understand __STACKSIZE__, __STARTADDRESS__ and __RESERVED_MEMORY__. Next there is very important section MEMORY: MEMORY { ZP: file = "", define = yes, start = $0082, size = $0035; # load chunk HEADER: file = %O, start = $0000, size = $0002; # load chunk FSTHDR: start = $0000, size = $4, file = %O; RAM_LOW: start = %S, size = $4000 - %S, file = %O; # load chunk SECHDR: start = $0000, size = $4, file = %O; RAM_HIGH: start = $8000, size = __RAM_AVAIL__ - $8000, file = %O; TRAILER: file = %O, start = $0000, size = $0006; } This section is describing memory layout of your program and what is actually generated to executable file (when file = %O). MEMORY layout of chunks assures that no code/data will overwrite other memory chunks (linker will show error if you will try to put too much into one memory chunk). We create two memory chunks (RAM_LOW and RAM_HIGH), where: RAM_LOW will have reserved memory from STARTADDRESS $2000 up to $4000 RAM_HIGH will have reserved memory from $8000 up to available memory. In the MEMORY section create the output XEX file. To understand how it works you need to understand XEX file format - it's very simple and described in many places e.g. here. We output to the file following data 1. XEX Header -> 4 bytes, $FFFF 2. First XEX Section Header for RAM_LOW -> 4 bytes that describe the memory chunk addresses 3. Data for RAM_LOW -> size depending on the code/data 4. Second XEX Section Header for RAM_HIGH -> 4 bytes that describe the memory chunk addresses 5. Data for RAM_HIGH -> size depending on the code/data 6. TRAILER -> RUN section that will execute your program Next we move to Segment section, that tells what is loaded to defined MEMORY chunks: SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; FILEHDR: load = HEADER, type = ro; # discarded old EXE header ########### FIRSTHDR: load = FSTHDR, type = ro; # first load chunk FIRST_START: load = RAM_LOW, type = ro, define = yes; STARTUP: load = RAM_LOW, type = ro, start=%S, define = yes; ONCE: load = RAM_LOW, type = ro, optional = yes; INIT: load = RAM_LOW, type = rw, optional = yes; LOWDATA: load = RAM_LOW, type = rw, define = yes, optional = yes; LOWRODATA: load = RAM_LOW, type = ro, define = yes, optional = yes; LOWCODE: load = RAM_LOW, type = rw, define = yes, optional = yes; FIRST_END: load = RAM_LOW, type = ro, define = yes; # we are generating data up to this place LOWBSS: load = RAM_LOW, type = bss, define = yes; # type=BSS section is not included into binary ########### ########### SECONDHDR: load = SECHDR, type = ro; # second load chunk SECOND_START: load = RAM_HIGH, type = ro, define = yes; CODE: load = RAM_HIGH, type = ro, define = yes; DATA: load = RAM_HIGH, type = rw, define = yes, optional = yes; # for data out of banked area RODATA: load = RAM_HIGH, type = ro, define = yes; SECOND_END: load = RAM_HIGH, type = ro, define = yes; # we are generating data up to this place BSS: load = RAM_HIGH, type = bss, define = yes; # type=BSS section is not included into binary ########### AUTOSTRT: load = TRAILER, type = ro; } To create your own you need to understand what CODE, DATA, RODATA and BSS segments are, short description is also here https://cc65.github.io/doc/ld65.html#toc5.2 What I did here is duplication of all these segments into LOW and HIGH memory areas, so a single C file can be compiled in a way that code, data, read-only data and uninitialized data defined in this C will go to selected memory chunk (LOW or HIGH). More about it later. I added also two markers for each section (FIRST_START, FIRST_END and SECOND_START, SECOND_END) that allows to easily calculate amount of data for XEX Section headers (later in src/link.asm file). The markers are placed before BSS section because BSS section is "virtual" (uninitialized data is not going to executable file). The FEATURES section I used the default one. The next file is src/link.asm that contains helper data that is going to our XEX file: .import __FIRST_START_LOAD__ , __SECOND_START_LOAD__ .import __FIRST_END_LOAD__ , __SECOND_END_LOAD__ .export __FILEHDR__: absolute = 1 .export __FIRSTHDR__: absolute = 1 .export __SECONDHDR__: absolute = 1 ; These are Atari DOS file segment headers in binary form .segment "FILEHDR" .word $FFFF .segment "FIRSTHDR" .word __FIRST_START_LOAD__ .word __FIRST_END_LOAD__ - 1 .segment "SECONDHDR" .word __SECOND_START_LOAD__ .word __SECOND_END_LOAD__ - 1 ; defining segments so they can be used in .CFG file .segment "FIRST_START" .segment "FIRST_END" .segment "SECOND_START" .segment "SECOND_END" ; Lets define all the segments so there is no error if e.g. there is no uninitialized data going to BSS segment from the C code .segment "LOWBSS" .segment "LOWCODE" .segment "LOWDATA" .segment "LOWRODATA" 1. We import our markers FIRST_START, FIRST_END and SECOND_START, SECOND_END from linker .CFG file so we can use them as data. 2. We define all the headers (for XEX and then for 2 XEX sections, with start and end addresses of data) 3. We define also segments that can be not used in C code yet, which would produce error about missing segments. This prevents it. Now lets move to compilation. We cannot use the "basic" cl65 utility (compile and link), because it's placing code, data, bss for each file into the same memory chunks. I created a helpful .BAT file that is placing selected files into selected memory chunks. It's first compiling (cc65) the source codes to .s (asm), then performing assembling to .o (object file), and then linking everything together, with inclusion of link.asm file that has header data for our XEX. set all_files= for %%x in ( src/low ) do ( cc65 -Cl -T -Osir --cpu 6502 -t atari --code-name "LOWCODE" --data-name "LOWDATA" --rodata-name "LOWRODATA" --bss-name "LOWBSS" %%x.c || goto :error ca65 -t atari %%x.s || goto :error set all_files=!all_files! %%x.o ) for %%x in ( src/main src/high ) do ( cc65 -Cl -T -Osir --cpu 6502 -t atari %%x.c || goto :error ca65 -t atari %%x.s || goto :error set all_files=!all_files! %%x.o ) ca65 -t atari src/link.asm || goto :error ld65 -Ln program.lbl --mapfile program.map --dbgfile program.dbg -C atari-atr.cfg -o program.xex %all_files% atari.lib src/link.o @IF NOT EXIST program.xex ( @echo Compilation error goto :error ) Make sure that you have proper paths defined for the tools. When compiled properly we will have our source codes compiled into LOW and HIGH memory: In "Adam Is Me" I'm using also memory in the bank area during the main game, only making sure that when extended memory is needed (for UNDO) I'm not going to call any function there nor use any data. two-sections.zip Edited November 23, 2021 by ilmenit 2 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted November 23, 2021 Author Share Posted November 23, 2021 @ilmenit thank you for a comprehensive description and examples, I will read through and give it a try today 1 Quote Link to comment Share on other sites More sharing options...
sanny Posted November 23, 2021 Share Posted November 23, 2021 (edited) @ilmenit, thank you for your thorough explanation. Your build script could be simplified by using cl65. I don't have a Windows at hand, here are the commands I issued manually: $ cl65 -c -Cl -T -Osir --cpu 6502 -t atari --code-name "LOWCODE" --data-name "LOWDATA" --rodata-name "LOWRODATA" --bss-name "LOWBSS" -o low.o src/low.c $ cl65 -c -Cl -T -Osir --cpu 6502 -t atari -o main.o src/main.c $ cl65 -c -Cl -T -Osir --cpu 6502 -t atari -o high.o src/high.c $ cl65 -c -Cl -T -Osir --cpu 6502 -t atari -o link.o src/link.asm $ cl65 -t atari -C atari-atr.cfg -o program.xex -m program.map *.o $ ls -ltr total 84 -rw-r--r-- 1 chris chris 18944 Dec 10 2020 chkxex.exe -rw-r--r-- 1 chris chris 988 Nov 22 23:19 build-atari.bat -rw-r--r-- 1 chris chris 3231 Nov 22 23:49 atari-atr.cfg -rw-r--r-- 1 chris chris 744 Nov 23 12:18 low.o -rw-r--r-- 1 chris chris 870 Nov 23 12:19 main.o drwxr-xr-x 2 chris chris 4096 Nov 23 12:19 src/ -rw-r--r-- 1 chris chris 708 Nov 23 12:19 high.o -rw-r--r-- 1 chris chris 770 Nov 23 12:19 link.o -rw-r--r-- 1 chris chris 3236 Nov 23 12:20 program.xex -rw-r--r-- 1 chris chris 28828 Nov 23 12:20 program.map $ ataricom program.xex ataricom 0.30-150320 (c) 2008-2014 Matthias Reichl <hias@horus.com> block 1: 2000-208e (bytes: 143, offset: 6) block 2: 8000-8c04 (bytes: 3077, offset: 153) block 3: 02e0-02e1 (bytes: 2, offset: 3234) RUN: 2001 $ PS: you don't need to provide your own FILEHDR, you could use the one from atari.lib. PS2: with recent CC65 ("recent" being less that ~ 8 years old), you don't need to set CC65_xxx and LD65_xxx environment variables. Just add cc65 to your PATH. Edited November 23, 2021 by sanny 1 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted November 23, 2021 Author Share Posted November 23, 2021 @sanny I put your commands into a batch file, unfortunately I think it needs your atari-atr.cfg, file all the others throw different errors about missing external. The main one is __RESERVED_MEMORY__ , I put it on the command line -D__RESERVED_MEMORY__=0 but it still fails I'll keep playing, may be able to resolve it another way Quote Link to comment Share on other sites More sharing options...
sanny Posted November 23, 2021 Share Posted November 23, 2021 The atari-atr.cfg is not by me, it's from @ilmenit's project. What are "all the others" cfg files? > "...but it still fails" How does it fail? Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted November 23, 2021 Author Share Posted November 23, 2021 The others I used are the built in ones supplied in cc65 if fails with external references or missing memory areas using atari.cfg ld65: Error: Missing memory area assignment for segment 'LOWDATA' and atarixl.cfg ld65: Warning: E:\Program Files (x86)\CC65/cfg/atarixl.cfg(86): Segment 'SRPREPHDR' does not exist ld65: Warning: E:\Program Files (x86)\CC65/cfg/atarixl.cfg(86): Segment 'SRPREP' does not exist ld65: Warning: E:\Program Files (x86)\CC65/cfg/atarixl.cfg(86): Segment 'SRPREPTRL' does not exist Unresolved external '__RESERVED_MEMORY__' referenced in: atari/system_check.s(165) atari/system_check.s(168) atari/crt0.s(75) atari/crt0.s(79) ld65: Error: 1 unresolved external(s) found - cannot create output file Quote Link to comment Share on other sites More sharing options...
ilmenit Posted November 23, 2021 Share Posted November 23, 2021 @TGB1718 - what @sanny wrote above was about simplification of my build script (using cl65 instead of pair cc65+ca65). It will not work as copy-paste with the default CC65 .CFGs. Quote Link to comment Share on other sites More sharing options...
sanny Posted November 23, 2021 Share Posted November 23, 2021 @TGB1718, what do you want to achieve? A program which a "hole" in the $4000-$7FFF area, correct? @ilmenit showed you a working example. You could use that as a starting point to add your code. Of course, @ilmenit's program doesn't work with the cc65 supplied CFGs. But you could also use the example in the cc65 docs as starting point. You haven't said what exactly is not working. Quote Link to comment Share on other sites More sharing options...
sanny Posted November 23, 2021 Share Posted November 23, 2021 You could also look at the atari-xex.cfg linker script. It automatically creates load chunks, and the internals of load-chunk-generation/EXE-file-format are not needed. Look at targettest/atari in CC65 for an multi-chunk example. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted November 23, 2021 Author Share Posted November 23, 2021 15 minutes ago, sanny said: what do you want to achieve? A program which a "hole" in the $4000-$7FFF area, correct? Yes, that's what I'm trying to achieve, I'll spend today reading through and look again at the examples supplied here and see where I get, it's obviously a complex subject Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.