Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 sooooo the only way this is working for me is with #pragma data-name (push,"PMGMEM") unsigned char pmg_mem; #pragma data-name (pop) if i use the pragma bss-name as suggested above it doesn't work but again, now that it is working, how can i make sure that pmg_mem actually points to 0x2800 address? Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted April 24, 2019 Share Posted April 24, 2019 BUT, how can i make sure that pmg_mem is the address appears in the cfg file (in this case 0x2800)? any suggestions? It's not a static and so would be in your map/label file? Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 so , in the map file, there is no reference for the pmg_mem in the asm listing file it appears. here are the references to it: Line 108: 000000r 1 .export _pmg_mem Line 110: 000000r 1 .export _setupPMG Line 117: 000000r 1 .segment "PMGMEM" Line 126: 000000r 1 _pmg_mem: Line 130: 000001r 1 ; void __near__ setupPMG (void) Line 135: 000000r 1 .proc _setupPMG: near Line 143: 00000Ar 1 AD rr rr lda _pmg_mem Line 154: 000027r 1 AD rr rr lda _pmg_mem Line 174: 000052r 1 AD rr rr lda _pmg_mem Line 236: 000098r 1 20 rr rr jsr _setupPMG there is nowhere a reference to the 0x2800 address..... any other suggestions? Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted April 24, 2019 Share Posted April 24, 2019 Its not going to be given an address until it is linked! As _pmg_mem is exported in the asm I would have thought you'd see it in the output. However I would suggest going for the post #21 approach Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 (edited) Its not going to be given an address until it is linked! As _pmg_mem is exported in the asm I would have thought you'd see it in the output. However I would suggest going for the post #21 approach i don't understand edit: i used altirra debugger to dump the display list (i use SEGMENT for display list memory address as well) and it doesn't work as expected the address of the display is given by the linker without considering the segment address i've set uffffffffffffffffff need help Edited April 24, 2019 by Yaron Nir Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 so here are the steps again: atari cfg (MEMORY+SEGMENT parts): MEMORY { PMGMEMORY: file = "", define = yes, start = $2000, size = $0800; DLISTMEMORY: file = "", define = yes, start = $2800, size = $0400; SCRMEMORY: file = "", define = yes, start = $2C00, 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; } 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; DLISTMEM: load = DLISTMEMORY, type = bss, define = yes; PMGMEM: load = PMGMEMORY, type = bss, define = yes; SCRMEM: load = SCRMEMORY, type = bss, define = yes; } top of the header cc65 file: #pragma data-name (push,"DLISTMEM") unsigned char dlist_mem; #pragma data-name (pop) #pragma data-name (push,"SCRMEM") unsigned char scr_mem; #pragma data-name (pop) code for display list: unsigned char DisplayList[] = { DL_BLK8, DL_BLK8, DL_BLK8, DL_LMS(DL_CHR40x8x4), 0, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_JVB, 0, DL_JMP }; void setupDisplayList() { DisplayList[28] = dlist_mem; DisplayList[4] = scr_mem; memcpy((void*) dlist_mem,&DisplayList,sizeof(DisplayList)); OS.sdlst = (void*)dlist_mem; bzero((void*)scr_mem,40*25); } altirra debugger dlist dump: Altirra> .dumpdlist BC20: x3 blank 8 BC23: mode 2 @ BC40 BC26: x23 mode 2 BC3D: waitvbl BC20 not expected result ((( HELP??!?? Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted April 24, 2019 Share Posted April 24, 2019 You're going to need to zip and attach minimal sources and the command to build Quote Link to comment Share on other sites More sharing options...
Irgendwer Posted April 24, 2019 Share Posted April 24, 2019 #pragma data-name (push,"DLISTMEM") unsigned char dlist_mem; #pragma data-name (pop) code for display list: unsigned char DisplayList[] = { DL_BLK8, DL_BLK8, DL_BLK8, DL_LMS(DL_CHR40x8x4), 0, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_CHR40x8x4, DL_JVB, 0, DL_JMP }; void setupDisplayList() { DisplayList[28] = dlist_mem; DisplayList[4] = scr_mem; memcpy((void*) dlist_mem,&DisplayList,sizeof(DisplayList)); OS.sdlst = (void*)dlist_mem; bzero((void*)scr_mem,40*25); } ...so "dlist_mem" is an unsigned char (just an 8 bit value) in your "DLISTMEM" segment. And you assign this 8 bit value to something that should be an address/buffer/array...? (Thanks for making this question public so I can save the effort to answer via the PM.) Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted April 24, 2019 Share Posted April 24, 2019 (edited) The code is a confusion of things discussed before... The DisplayList is an unsigned char array when previous this was done as a void to cover the addresses being words. There is an unnecessary DL_JMP following the DL_JVB. As highlight in the previous post, dlist_mem would be better off as a unsigned char *dlist_mem or unsigned char dlist_mem[] But if left as-is then as per post #17, the assignments would have to use 'address of' and obtain the low and high values, e.g. DisplayList[29] = &dlist_mem >> 8; DisplayList[28] = &dlist_mem & 0xFF; DisplayList[5] = &scr_mem >> 8; DisplayList[4] = &scr_mem & 0xFF; Edited April 24, 2019 by Wrathchild Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 guys, you're missing the point here. leave the correctness of the display list aside, will fix that later. i want to make sure that what i use in SEGMENT cfg is references properly in the cc65 code. per the request here is a zip with the project. if you run it, and break to debugger, and examine the display list, you will see that both the DLIst address and Screen Mem are not what defined in SEGEMENT..... test_dli.rar Quote Link to comment Share on other sites More sharing options...
sanny 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. Just using MEMORY should work as well. 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 Overlapping with SYSCHKCHNK is not an issue, since it's just the first load chunk which checks available memory and aborts loading if the program doesn't fit. No problem if it's afterwards overwritten with parts of the main program. Quote Link to comment Share on other sites More sharing options...
sanny Posted April 24, 2019 Share Posted April 24, 2019 i want to make sure that what i use in SEGMENT cfg is references properly in the cc65 code.. With these diffs you can see the addresses of dlist_mem and scr_mem to be correct. --- test_dli.org/build.bat 2019-04-24 21:15:12.313302800 +0200 +++ test_dli/build.bat 2019-04-24 21:15:09.792907982 +0200 @@ -1,5 +1,5 @@ del testdli.xex -cl65 -t atari -l test_dli.asm -Osir main.c -o testdli.xex --mapfile testdli.map -C atari.cfg +cl65 -t atari -l test_dli.asm -Osir main.c -o testdli.xex --mapfile testdli.map -C atari.cfg -vm testdli.xex diff -ru test_dli.org/dlist.h test_dli/dlist.h --- test_dli.org/dlist.h 2019-04-24 21:14:14.779897100 +0200 +++ test_dli/dlist.h 2019-04-24 21:15:25.016976491 +0200 @@ -1,11 +1,11 @@ -#pragma data-name (push,"DLISTMEM") +#pragma bss-name (push,"DLISTMEM") unsigned char dlist_mem; -#pragma data-name (pop) +#pragma bss-name (pop) -#pragma data-name (push,"SCRMEM") +#pragma bss-name (push,"SCRMEM") unsigned char scr_mem; -#pragma data-name (pop) +#pragma bss-name (pop) unsigned char DisplayList[] = { Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted April 24, 2019 Share Posted April 24, 2019 Here's my own cleanup (allergic to code in header files, that's ok for c++) and in incorporates the defining your segments in a separate asm file. @sanny, yes, I was ok with the SYSCHKCHNK as the sprite-mem clearing would handle that. yaron.zip Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 Sanny, What do you mean by this : With these diffs you can see the addresses of dlist_mem and scr_mem to be correct.? Which tool do you use ? Im not sure I follow Wrathchild Tnx I will look at your cleaned zip file When creating a game , of code is bot properly separated one can get lost with one big main.c file..... I prefer the C++ style Quote Link to comment Share on other sites More sharing options...
sanny Posted April 24, 2019 Share Posted April 24, 2019 What do you mean by this : With these diffs you can see the addresses of dlist_mem and scr_mem to be correct.? Which tool do you use ? Im not sure I follow See https://en.wikipedia.org/wiki/Diff#Unified_format In a nutshell, remove lines starting with "-" and add lines starting with "+". My post just shows the changes I did. Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 Tnx sanny! Quote Link to comment Share on other sites More sharing options...
sanny Posted April 24, 2019 Share Posted April 24, 2019 When creating a game , of code is bot properly separated one can get lost with one big main.c file..... I prefer the C++ style I have to agree with Wrathchild. For a small/simple program it works. But you are going to get problems if your .h file with code is included into more than one C file. Then you'll get link errors, because the functions from the .h file are mulitple defined. Remember, you don't need to have just one main.c file, you can have multiple C files... Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 (edited) Sanny, What I normally do is have 1 main.c and several *.h files I hate put huge portion of code in 1 file Edit: I also use the #ifdef directive to make sure it is linked once.... Edited April 24, 2019 by Yaron Nir Quote Link to comment Share on other sites More sharing options...
sanny Posted April 24, 2019 Share Posted April 24, 2019 Why not use multple C files? main.c pmg.c dlist.c? Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 Didnt you say it is not recommended and linking errors will occur? Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted April 24, 2019 Share Posted April 24, 2019 Didnt you say it is not recommended and linking errors will occur? He means if two c files include the same header you have just created two versions of the same thing. If you have a single main.c then adding extra code via an 'h' file is a bit of a mis-use of what a header file is. In, say, MADS, I do have a main ".asm" file which then includes lots of other ".asm" files, so equating that across you'd still be better off calling these ".c". In C, the header is a declaration for other C file to know what is exposed. A #ifdef already-included protection is therefore no protection for code within a header file being included twice, it will be, once in each C file including it. You are protecting from the #include line being written twice in the main.c file (or heaven-forbid in one of the other header files). In C++ the ".h" header also defines, for example, what a class definition is but the implementation would still be in a ".cpp" file. The C++ header typically also provides the inline code for inclusion in a different source file using that class but the whole implementation isn't held there for a once and once only inclusion in the solution. Quote Link to comment Share on other sites More sharing options...
sanny Posted April 24, 2019 Share Posted April 24, 2019 He means if two c files include the same header you have just created two versions of the same thing. If you have a single main.c then adding extra code via an 'h' file is a bit of a mis-use of what a header file is. ACK In C, the header is a declaration for other C file to know what is exposed. A #ifdef already-included protection is therefore no protection for code within a header file being included twice, it will be, once in each C file including it. You are protecting from the #include line being written twice in the main.c file (or heaven-forbid in one of the other header files). Since you seem to always just use one main.c file, it works for you. But if you happen to create another C file, like pmg.c, it will also include your header with a function definition. Since both main.c and pmg.c then declare a setupPMG() function (as an example), you will get an error when linking, since the linker sees two versions of the same function. Look at Wrathchild's rework of your code. He did it like it should be :-) Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted April 24, 2019 Author Share Posted April 24, 2019 Will do Tnx both . If will have more questions will post. Cheers Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted April 24, 2019 Share Posted April 24, 2019 To wrap up the header stuff, I've knocked together a simplistic example to demonstrate the conflict sanny and I highlighted. Within the 'bad' version the function MyMath gets generated in both the Math1 and Math2 object files and so when the linking occurs there is a conflict. CC65 however looks to be clever enough to not only spot and warn of this, but consolidate them into one - so presumably it knows they are also identical. examples.zip 1 Quote Link to comment Share on other sites More sharing options...
+Stephen Posted April 24, 2019 Share Posted April 24, 2019 I applaud you guys using C on these 6502 machines. It seems so much harder than pure asm to me, but I guess it's all what you get used to. I've been coding in C# full-time for 13 years now, did a little C / C++ before that. On my Atari though, it was BASIC then ASM. It's hard for me to go back to these old BASIC dialects with no structure after all this time of everything being object oriented, etc. Super hard to fight the limitations of C on these old machines too. 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.