Yaron Nir Posted April 24, 2019 Share Posted April 24, 2019 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 Quote Link to comment Share on other sites More sharing options...
sanny Posted April 24, 2019 Share Posted April 24, 2019 (edited) Do you want to have these 3 memory areas pre-populated, or do you fill them at runtime? Edited April 24, 2019 by sanny Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 Hi Sanny, i thought the ID of using the segment and the memory of the config file is to pre-populate them and fix the location. no? Quote Link to comment Share on other sites More sharing options...
sanny Posted April 24, 2019 Share Posted April 24, 2019 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. Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 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 Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 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.... Quote Link to comment Share on other sites More sharing options...
sanny Posted April 24, 2019 Share Posted April 24, 2019 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... Quote Link to comment Share on other sites More sharing options...
sanny Posted April 24, 2019 Share Posted April 24, 2019 And, if you don't want to pre-populate, it's better to use 'file="";' instead of 'file=%O;' Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 Sanny, your suggested on how to use the memory address is not working. i've compiled also to produce the map file, and in the map file there is no recollection on DLIST nor __DLIST_START__ help?? Quote Link to comment Share on other sites More sharing options...
sanny Posted April 24, 2019 Share Posted April 24, 2019 can you show your config and map files? Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 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?? Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 (edited) 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 April 24, 2019 by Yaron Nir Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted April 24, 2019 Share Posted April 24, 2019 You've removed your SEGMENT entries? PMGMEM: load = PMGMEMORY, type = ro, define = yes; DLIST: load = DISPLAYLIST, type = ro, define = yes; SCRMEM: load = SCREEN_MEMORY, type = ro, define = yes; the 'define = yes' is what exposes the symbols Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 yes, as to what sanny suggested i only used the MEMORY section of the cfg file. do i need to add them back? Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted April 24, 2019 Share Posted April 24, 2019 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 Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 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 >> ; but for now, the PMGMEMORY is undefined symbol plz help? Quote Link to comment Share on other sites More sharing options...
baktra Posted April 24, 2019 Share Posted April 24, 2019 (edited) 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 April 24, 2019 by baktra Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 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? Quote Link to comment Share on other sites More sharing options...
baktra Posted April 24, 2019 Share Posted April 24, 2019 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. Quote Link to comment Share on other sites More sharing options...
baktra Posted April 24, 2019 Share Posted April 24, 2019 (edited) 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 April 24, 2019 by baktra Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted April 24, 2019 Share Posted April 24, 2019 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 1 Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 #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) Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted April 24, 2019 Share Posted April 24, 2019 Check docs, its bss-name Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 #pragma data-name (push,"PMGMEM") unsigned char pmg_mem; #pragma data-name (pop) this seems to be compiling and running. and i see the PMG on screen BUT, how can i make sure that pmg_mem is the address appears in the cfg file (in this case 0x2800)? any suggestions? Quote Link to comment Share on other sites More sharing options...
baktra Posted April 24, 2019 Share Posted April 24, 2019 #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. 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.