Jump to content
IGNORED

CC65 config file - how to use the segment properly


Recommended Posts

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?

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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 by Yaron Nir
Link to comment
Share on other sites

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??!??

Link to comment
Share on other sites

#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.)

Link to comment
Share on other sites

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 by Wrathchild
Link to comment
Share on other sites

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

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.

 

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.

Link to comment
Share on other sites

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[] = 
 {

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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...

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

 

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 :-)

 

Link to comment
Share on other sites

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

  • Like 1
Link to comment
Share on other sites

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.

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...