cc65 and RODATA

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

tonma
Posts: 23
Joined: Tue Mar 28, 2017 6:26 am
Contact:

cc65 and RODATA

Post by tonma » Fri Mar 31, 2017 1:06 am

Hi,
I use the mapper mmc3 but I think its work the same with another.

I would like to store integer tables to draw my room in RODATA. So I use const unsigned char array but they are added to the PRG. I thought that constants are placed in ROM.
I will have 100 arrays for my rooms, so it will not fit in 16ko of PRG.

I add the pragma value for Rodata before my constant array : #pragma rodata-name (push, "RODATA"). But I certainly confuse PRG-ROM and PRG-RAM.

I use cc65 and in my nes.cfg, i have :

Code: Select all

#ROM Addresses:
    PRG: start = $c000, size = $3ffa, file = %O ,fill = yes, define = yes;

SEGMENTS {
...
CODE:     load = PRG,            type = ro,  define = yes;
RODATA:   load = PRG,            type = ro,  define = yes;
...
};
Do I need to add another PRG-ROM ? So I'll have the code in PRG1 and multiple switchable PRG2 with my rodata?


Image

tonma
Posts: 23
Joined: Tue Mar 28, 2017 6:26 am
Contact:

Re: cc65 and RODATA

Post by tonma » Fri Mar 31, 2017 3:12 am

I did tests with a simple hello world.

With a prg of 16kb it works.
If I add a second, the screen is all gray and I have nothing in the ppu, as if the chr bank was not loaded! But I didn't change chr address.

Left works, right doesn't work.
Image

I add in nes.cfg :

Code: Select all

#ROM Addresses:
   PRG: start = $E000, size = $1ffa, file = %O ,fill = yes, define = yes;
    # PRG: start = $8000, size = $7ffa, file = %O ,fill = yes, define = yes;
	
    PRG1: start = $8000, size = $1fff, file = %O ,fill = yes, define = yes;
    PRG2: start = $A000, size = $1fff, file = %O ,fill = yes, define = yes;
    PRG3: start = $E000, size = $1fff, file = %O ,fill = yes, define = yes;

    # Hardware Vectors at end of the ROM
    VECTORS: start = $fffa, size = $6, file = %O, fill = yes;


#1 Bank of 8K CHR ROM
    CHR: start = $0000, size = $2000, file = %O, fill = yes;
}




SEGMENTS {
    HEADER:   load = HEADER,         type = ro;
    STARTUP:  load = PRG,            type = ro,  define = yes;
    LOWCODE:  load = PRG,            type = ro,                optional = yes;
	CODE1:     load = PRG1,            type = ro,  define = yes;
    CODE2:     load = PRG2,            type = ro,  define = yes;
    CODE3:     load = PRG3,            type = ro,  define = yes;
    
    INIT:     load = PRG,            type = ro,  define = yes, optional = yes;
    CODE:     load = PRG,            type = ro,  define = yes;
    RODATA:   load = PRG,            type = ro,  define = yes;
    DATA:     load = PRG, run = RAM, type = rw,  define = yes;
    VECTORS:  load = VECTORS,        type = rw;
    CHARS:    load = CHR,            type = rw;
    BSS:      load = RAM,            type = bss, define = yes;
    HEAP:     load = RAM,            type = bss, optional = yes;
    ZEROPAGE: load = ZP,             type = zp;
    ONCE:     load = PRG,            type = ro,  define = yes;
}
reset.s :

Code: Select all

.segment "HEADER"

    .byte $4e,$45,$53,$1a
	.byte 02	; 2 PRG-ROM 16ko
	.byte 01     ; 1 CHR
	.byte %00110000	;   ;00	mapper 3 Horizontal mirroring ;
	.byte 00
	.res 8,0
code in c at the end :

Code: Select all

#pragma rodata-name ("CODE1")
#pragma code-name ("CODE1")

#pragma rodata-name ("CODE2")
#pragma code-name ("CODE2")

#pragma rodata-name ("CODE3")
#pragma code-name ("CODE3")

User avatar
dougeff
Posts: 2750
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: cc65 and RODATA

Post by dougeff » Fri Mar 31, 2017 5:25 am

I guess you are testing separating the PRG into different banks.

PRG3: start = $E000, size = $1fff

Why is this not starting at $c000. And size = $2000. All the sizes should be $2000

And the placement of banks is out of order.

If PRG is the last bank...it should be listed after PRG3.

Edit, and I don't see a header segment in the ROM definition.
nesdoug.com -- blog/tutorial on programming for the NES

tonma
Posts: 23
Joined: Tue Mar 28, 2017 6:26 am
Contact:

Re: cc65 and RODATA

Post by tonma » Fri Mar 31, 2017 5:51 am

dougeff wrote:I guess you are testing separating the PRG into different banks.

PRG3: start = $E000, size = $1fff

Why is this not starting at $c000. And size = $2000. All the sizes should be $2000

And the placement of banks is out of order.

If PRG is the last bank...it should be listed after PRG3.

Edit, and I don't see a header segment in the ROM definition.
Yes I want to have one fixed bank PRG for my code and bank switchable for constant array. Something like : 10 PRG and 10 CHR. I looked the mmc3 mapper in nesdev wiki : 8K + 8K + 16K fixed PRG

Thanks, Now my PRG is in the good order but the CHR Still does not load.

Code: Select all

MEMORY {
#RAM Addresses:
    # Zero page
    ZP: start = $00, size = $100, type = rw, define = yes;
	#note, the c compiler uses about 10-20 zp addresses, and it puts them after yours.
	
	#OAM1: start = $0200, size = $0100, define = yes;
	#note, sprites stored here in the RAM
	
	RAM: start = $0300, size = $0400, define = yes;
	#note, I located the c stack at 700-7ff, see below

#INES Header:
    HEADER: start = $0, size = $10, file = %O ,fill = yes;

#ROM Addresses:
    PRG1: start = $8000, size = $2000, file = %O ,fill = yes, define = yes;
    PRG2: start = $A000, size = $2000, file = %O ,fill = yes, define = yes;
    PRG3: start = $C000, size = $2000, file = %O ,fill = yes, define = yes;
    PRG: start = $E000, size = $2000, file = %O ,fill = yes, define = yes;

    # Hardware Vectors at end of the ROM
    VECTORS: start = $fffa, size = $6, file = %O, fill = yes;

#1 Bank of 8K CHR ROM
    CHR: start = $0000, size = $2000, file = %O, fill = yes;
}


SEGMENTS {
    HEADER:   load = HEADER,         type = ro;
    STARTUP:  load = PRG,            type = ro,  define = yes;
    LOWCODE:  load = PRG,            type = ro,                optional = yes;
    
	CODE1:     load = PRG1,            type = ro,  define = yes;
    CODE2:     load = PRG2,            type = ro,  define = yes;
    CODE3:     load = PRG3,            type = ro,  define = yes;
	
    INIT:     load = PRG,            type = ro,  define = yes, optional = yes;
    CODE:     load = PRG,            type = ro,  define = yes;
    RODATA:   load = PRG,            type = ro,  define = yes;
    DATA:     load = PRG, run = RAM, type = rw,  define = yes;
    VECTORS:  load = VECTORS,        type = rw;
    CHARS:    load = CHR,            type = rw;
    BSS:      load = RAM,            type = bss, define = yes;
    HEAP:     load = RAM,            type = bss, optional = yes;
    ZEROPAGE: load = ZP,             type = zp;
    ONCE:     load = PRG,            type = ro,  define = yes;
}




FEATURES {
    CONDES: segment = INIT,
        type = constructor,
        label = __CONSTRUCTOR_TABLE__,
        count = __CONSTRUCTOR_COUNT__;
    CONDES: segment = RODATA,
        type = destructor,
        label = __DESTRUCTOR_TABLE__,
        count = __DESTRUCTOR_COUNT__;
    CONDES: type = interruptor,
        segment = RODATA,
        label = __INTERRUPTOR_TABLE__,
        count = __INTERRUPTOR_COUNT__;
}




SYMBOLS {
    __STACKSIZE__: type = weak, value = $0100;     # 1 page stack
	__STACK_START__: type = weak, value = $700;
}

Code: Select all

.segment "HEADER"

    .byte $4e,$45,$53,$1a
	.byte 02	; 2 PRG-ROM 16ko
	.byte 01
	.byte %00110000	;%00110000	;00	mapper 3 Horizontal mirroring ;
	.byte 00
	.res 8,0
Image
Last edited by tonma on Fri Mar 31, 2017 5:58 am, edited 1 time in total.

tepples
Posts: 22057
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: cc65 and RODATA

Post by tepples » Fri Mar 31, 2017 5:56 am

1. PRG ROM and CHR ROM sizes usually need to be powers of two. MMC3's behavior is unspecified with ROM sizes that are not powers of 2.

2. If you're planning to use 32K of PRG ROM, why are you using MMC3? For the timer?

3. MMC3's startup code needs to be in $E000-$FFFF so that it can map everything else into $8000-$DFFF.

tonma
Posts: 23
Joined: Tue Mar 28, 2017 6:26 am
Contact:

Re: cc65 and RODATA

Post by tonma » Fri Mar 31, 2017 6:12 am

tepples wrote:1. PRG ROM and CHR ROM sizes usually need to be powers of two. MMC3's behavior is unspecified with ROM sizes that are not powers of 2.

2. If you're planning to use 32K of PRG ROM, why are you using MMC3? For the timer?

3. MMC3's startup code needs to be in $E000-$FFFF so that it can map everything else into $8000-$DFFF.
But In my first example I have 2 PRG and 5 CHR and it's working !!

I don't know if the MMC3 is the best choice but I wish to have several CHR bank switchable and several PRG bank because I wish to add data while my deveolpment growing.
Maybe using mmc1 will be more simple ?

User avatar
dougeff
Posts: 2750
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: cc65 and RODATA

Post by dougeff » Fri Mar 31, 2017 6:18 am

The vectors share space with the last fixed bank, so subtract that from PRG's size...

PRG: start = $E000, size = $1ffa, file = %O ,fill = yes, define = yes;

# Hardware Vectors at end of the ROM
VECTORS: start = $fffa, size = $6, file = %O, fill = yes;
nesdoug.com -- blog/tutorial on programming for the NES

tepples
Posts: 22057
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: cc65 and RODATA

Post by tepples » Fri Mar 31, 2017 6:20 am

tonma wrote:I don't know if the MMC3 is the best choice but I wish to have several CHR bank switchable and several PRG bank because I wish to add data while my deveolpment growing.
Maybe using mmc1 will be more simple ?
MMC3 will make your game somewhat more expensive to replicate on cartridges. If you're not trying to combine bits and pieces of different banks in the same picture, you might want to go with something like CNROM (mapper 3).

tonma
Posts: 23
Joined: Tue Mar 28, 2017 6:26 am
Contact:

Re: cc65 and RODATA

Post by tonma » Fri Mar 31, 2017 6:40 am

dougeff wrote:The vectors share space with the last fixed bank, so subtract that from PRG's size...

PRG: start = $E000, size = $1ffa, file = %O ,fill = yes, define = yes;

# Hardware Vectors at end of the ROM
VECTORS: start = $fffa, size = $6, file = %O, fill = yes;
Thanks, it's working. I'll try with more PRG and CHR now.

tonma
Posts: 23
Joined: Tue Mar 28, 2017 6:26 am
Contact:

Re: cc65 and RODATA

Post by tonma » Fri Mar 31, 2017 6:41 am

tepples wrote:
tonma wrote:I don't know if the MMC3 is the best choice but I wish to have several CHR bank switchable and several PRG bank because I wish to add data while my deveolpment growing.
Maybe using mmc1 will be more simple ?
MMC3 will make your game somewhat more expensive to replicate on cartridges. If you're not trying to combine bits and pieces of different banks in the same picture, you might want to go with something like CNROM (mapper 3).
But with CNROM (https://wiki.nesdev.com/w/index.php/CNROM) you can't switch bank ?
Maybe the mapper1 will be more simple and less expensive ? http://wiki.nesdev.com/w/index.php/MMC1

tepples
Posts: 22057
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: cc65 and RODATA

Post by tepples » Fri Mar 31, 2017 6:44 am

With CNROM, you can switch CHR ROM banks. If you aren't planning to exceed 32K PRG, that should be enough.

tonma
Posts: 23
Joined: Tue Mar 28, 2017 6:26 am
Contact:

Re: cc65 and RODATA

Post by tonma » Fri Mar 31, 2017 7:30 am

I'll use more than 32Ko sadly and it's because of that than I wish to make switchabele before coding.

With mapper mmc3, I can add 4 PRG banks of 8ko only, after I have a blank screen.

So I have 4 banks of 8ko and the fixed source code is in the last bank (3). But if I add 4 bank betwenn at the address $8000 for switching, my last bank became (7). Do I need to tell the console to use bank 7 ? I need to write some values at $8000.

User avatar
dougeff
Posts: 2750
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: cc65 and RODATA

Post by dougeff » Fri Mar 31, 2017 9:10 am

if I add 4 bank betwenn at the address $8000 for switching, my last bank became (7). Do I need to tell the console to use bank 7 ? I need to write some values at $8000.
As far as I know, the only thing for certain (at power on) is, the last $2000 of PRG will be at $e000. You will have to set the other banks with writes to 8000 and 8001.

And, to be nitpicking, you aren't telling the console, you are telling a tiny chip in the cartridge marked "MMC3" to switch banks.
nesdoug.com -- blog/tutorial on programming for the NES

tonma
Posts: 23
Joined: Tue Mar 28, 2017 6:26 am
Contact:

Re: cc65 and RODATA

Post by tonma » Fri Mar 31, 2017 11:53 am

dougeff wrote:
if I add 4 bank betwenn at the address $8000 for switching, my last bank became (7). Do I need to tell the console to use bank 7 ? I need to write some values at $8000.
As far as I know, the only thing for certain (at power on) is, the last $2000 of PRG will be at $e000. You will have to set the other banks with writes to 8000 and 8001.

And, to be nitpicking, you aren't telling the console, you are telling a tiny chip in the cartridge marked "MMC3" to switch banks.
:mrgreen:

Can you give me an example for writing the other banks with 8000 and 8001. Like PRG bank X at $8000 and CHR bank at PPU Memory map ($000) ?

tepples
Posts: 22057
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: cc65 and RODATA

Post by tepples » Fri Mar 31, 2017 12:02 pm

I gave MMC3 init code in this topic.

Post Reply