It is currently Fri Oct 19, 2018 9:52 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 15 posts ] 
Author Message
PostPosted: Thu Sep 06, 2018 9:16 am 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 78
Location: Colorado
I'm guessing I have too much code or possibly data from a .chr in one segment, but I'm pretty new to programming for the NES, so if anyone would be willing to provide me with a brief explaination of

1.) How segments work
2.) How you prevent them from overflowing

it would really help me out.

Sorry for the noob question

Thanks!

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 9:31 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20676
Location: NE Indiana, USA (NTSC)
Start by reading ld65 Users Guide section 5.

Then paste your ld65 config file, and any source code within a .segment "TILES", and the sizes of any files referenced by .incbin within that segment.


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 9:32 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6895
Location: Canada
Segments are defined in a .cfg file for ca65.

The .cfg file has two main parts:

MEMORY defines the file layout. It's a collection of blocks of data that either go into the output file or are omitted. The omitted ones are usually for RAM.

The SEGMENT definitions are a subdivision of the MEMORY blocks, they're what you fill it up with. In your assembly code when you write .segment "TILES" everything folllowing that line will go into that segment. While MEMORY block are basically a fixed thing, SEGMENT sections usually can expand and contract to fill the MEMORY container they're placed inside. It's the linker's job (ld65) to pack them all together.

The documentation of this is here: http://cc65.github.io/doc/ld65.html

In the case of your "TILES" segment, it depends on what kind of ROM you're making, and I don't know what's in you .cfg but I'd gues it probably goes into a memory block called something like "CHR" that's 8kb in size. If you're 4kb over I'd guess you might have 3 .incbin statements in there, each referencing a 4k file of graphics data. Or maybe you have 2 .incbin statements, 1 of 8k and 1 of 4k, etc. The overflow just means you've put more in than it can hold, and to fix it you need to remove some of that data.


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 10:08 am 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 78
Location: Colorado
rainwarrior wrote:
In the case of your "TILES" segment, it depends on what kind of ROM you're making, and I don't know what's in you .cfg but I'd gues it probably goes into a memory block called something like "CHR" that's 8kb in size.


Actually I think you may have made this template I'm using. I can't remember for certain, but your pic looks super familiar (maybe you just helped me on a different question I had)

Anyway, if you did make the template I'm using thank you very much for that it's been super helpful.

Another stupid question I have... what is the BSS segment? I'm having a heck of a time getting good answers out of Google for some of these questions.

Thanks for all your help,
Rick

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 10:11 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7671
Location: Seattle
battagline wrote:
Another stupid question I have... what is the BSS segment? I'm having a heck of a time getting good answers out of Google for some of these questions.
https://en.wikipedia.org/wiki/.bss


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 10:13 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6895
Location: Canada
The etymology of BSS is unclear to me, but it's the CC65 term used for a block that's reserved for RAM. Wikipedia has an article on .bss, but really it's just ca65's standard naming convention for your main block of general purpose RAM.

I actually usually just call the equivalent segment "RAM" in my cfg, but if you're looking at the minimal example I made a while back I probably wanted to be consistent with their default terminology.


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 11:01 am 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 78
Location: Colorado
You know, maybe I'm just dense, but I'm still not sure I understand the reason you would use BSS over any other vanilla segment. It sounds like it's just a segment that doesn't start off being initialized to anything, but I'm not even certain I'm right about that.

Thanks

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 11:11 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7671
Location: Seattle
The pertinent difference between the BSS segment and the DATA segment is that the latter is explicitly initialized by the C runtime. The DATA segment's initial values must be stored somewhere (i.e. consuming ROM) and copied over on boot; the BSS segment instead is just a default value (which officially is 0, but maybe you removed that part of crt0)

That's why the DATA segment requires separate load and run values in the linker, but the BSS segment doesn't.

(In practice, ld65 lets you use the same load and run parameters for every segment; it's only code generated by CC65 that puts initialized global/static variables in DATA but uninitialized global/static variables in BSS. Also, you almost certainly want to use cc65 with the -Cl flag because the software stack is so slow, and this will put things in ... the BSS segment!)


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 11:18 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6895
Location: Canada
A couple of standard CC65 segments and their function:
Code:
.segment "RODATA" ; RODATA is for read only data
table:
.byte 1, 2, 3, ,4, 5

.segment "BSS" ; "uninitialized" RAM, we make reservations on it to create variables, no data is placed here
player_x: .res 2
player_y: .res 2
; in practice this is usually initialized by the program with zero at startup

.segment "ZEROPAGE" : zeropage ; "fast" uninitialized RAM, there is only 256 bytes of it and it resides at $0000-$00FF
; the ': zeropage' on the end is needed to tell the assembler that a segment is on the zero page,
; otherwise it won't know to generate the faster ZP instructions
; (the assembler ca65 doesn't know where segments go, but it generates the instructions.
; the linker ld65 knows where they go from the .cfg, but it can't change any of the instructions.)
; also: if the segment is literally named "ZEROPAGE", for that one case only the ': zeropage' part is implied, so it could have been omitted here.
important_counter: .res 1

.segment "CODE" ; basically the same as RODATA in function, but by convention people put code here rather than "data"
lda #5
sta $8000

.segment "DATA" ; sort of a combo of BSS and RODATA:
; this is initialized RAM, which means the actual intialization values go somewhere in ROM, but they're intended to live somewhere in RAM
; so the program has to copy them in at some point to do the initialization
current_level:
.byte 1 ; reserves 1 byte, initializes to 1
player_lives:
.byte 3, 3 ; reserve 2 bytes (for 2 players), both initialized to 3


Note, however, that you can completely redefine all the segment in your .cfg file, so this is merely a naming convention. The actual function/meaning of these comes from the .cfg.


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 11:50 am 
Offline
User avatar

Joined: Wed Sep 05, 2018 11:13 am
Posts: 78
Location: Colorado
Thanks guys that's super helpful! It's been a few decades since I've had to worry about memory allocation at even close to this level of detail.

_________________
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 6:23 pm 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 2006
Location: Fukuoka, Japan
Since we are talking about the BSS/DATA segments and C, I have a question about DATA reading load and run.

The nes is quite limited in size so I try to use the least possible about the C runtime. I avoid the loadData in ctr by never default initializing my variables except to 0 when I clear the RAM on RESET.

In normal C I wouldn't worry about that it just that I try to use the least possible about the C runtime. Is is a bad practice? I know that on the nes you cannot really code clean C code and I'm used to it and I have to be careful to not initialize by accident and check the map for possible error (when I see the DATA segment increase then I know I initialized one by accident).

What are people opinion on the subject?


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 6:30 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6895
Location: Canada
Well, if you want to give yourself safety against accidentally adding to the DATA segment, you could delete it (or comment it out) from your CFG. You'd also need to comment out the call to copydata in the CRT startup in your library, otherwise the copydata module will be referenced and require DATA to be defined. After doing this any accidental use of variable initialization would throw a linker error for you.


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 6:39 pm 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 2006
Location: Fukuoka, Japan
My makefile can compile the runtime to my needs and can remove unnecessary files (I keep a list of required file and it built it based on that). I did comment out that part in crt but there was still some added to the DATA segment without any linker error. I just realized that I did define that segment and it's in my CFG file so I will comment it out.

But isn't cc65 complaining when you remove some of their "default/internal" segments? I think I had an issue like that at the beginning or it was just a coincidental mistake. I still have that NULL segment being printed in my map list for whatever reason. I will try it out and share any issue related to it, if any. Thanks again!


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 6:51 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6895
Location: Canada
When you link with a library with ld65, it includes any module (.o) in that library that is referenced (imported) by one of your other modules. For instance, if you do a multiply by 5, the mulax5 module will be included in your program, but if you don't it will be left out.

As long as you don't reference any modules that need DATA, there won't be a problem. I think the linker will tell you what module referenced it, if you do get an error. You could also grep the runtime library sources for .data or .segment "DATA" maybe to take a survey of that stuff.


Top
 Profile  
 
PostPosted: Thu Sep 06, 2018 7:06 pm 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 2006
Location: Fukuoka, Japan
This is one of the reason I removed a list of files when compiling the lib. If I start to use something that I expected no to, it should fail since it doesn't exist in the lib to be included. I did a quick compile and there is no error so other parts doesn't seems to use DATA. Will recheck, just in case.

As for the NULL segment, I think they talked about in the CC65 but I don't remember why it's there. Will check the doc for that.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: ndiddy, TmEE and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group