CC65: Configure AOROM

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

User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

CC65: Configure AOROM

Post by Diskover »

Using CC65, how can I configure the parameters to function as AOROM?
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: CC65: Configure AOROM

Post by tepples »

Are you expecting to put C code in more than one PRG ROM bank? Or would you be fine with putting only engine code written in assembly language and the data that that engine code accesses, such as graphics data, level maps, and the music engine and its data, into banks other than the bank with C code?

If you confirm that you are fine with the sum of all compiled C code being no larger than about 32000 bytes, then you can devote the other 768 bytes of all banks to a trampoline between your C bank and your engine banks, and one of us can describe how to create such a trampoline later.
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: CC65: Configure AOROM

Post by Diskover »

I just need to know the file configuration *. Cfg to make a small example :lol:

Yes, it would be to use C.
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: CC65: Configure AOROM

Post by dougeff »

I would compile each bank separately, and concatenate them together.

And make sure each bank has a reset vector handler, in case the user hits 'reset' while the wrong bank is loaded. (And NMI/IRQ handlers).
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
rainwarrior
Posts: 8733
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: CC65: Configure AOROM

Post by rainwarrior »

CC65 has no direct support for banking.

Dougeff's suggestion to compile and link each bank separately works, though. You can compile C code to more than one bank like that, but you will need to take care to make sure that RAM usage that is supposed to be shared is in the same location across banks, and RAM usage that isn't is moved into other segments to avoid overlap. This will require careful use of extra segments for that purpose.

This is a whole lot easier if you just use one bank for C, and all the other banks are just assembly and data storage / unpacking. (In which case you don't have to do separate linking at all. All of your assembly banks can coexist peacefully with the C bank.)

I have no idea why tepples suggested "768 bytes" for a bank switching routine-- it should take far less than that.

The reason you can't link C in more than one bank is that the generated code requires immediate access to the C runtime libraries, which can only be linked into one bank. Since C code can't do a cross-bank call, the runtime library will fail for code placed in another bank. You can't include a copy of the CRT in each bank, either, without linking those banks separately.
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: CC65: Configure AOROM

Post by Diskover »

I keep in mind about the banksiwch. Do not worry.

The only thing I want to know is how to configure the *. CFG, please. -
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: CC65: Configure AOROM

Post by tepples »

rainwarrior wrote:I have no idea why tepples suggested "768 bytes" for a bank switching routine-- it should take far less than that.
Because that's the difference between 32K meaning 32000 bytes and 32K meaning 32768 bytes, and I was trying to simplify my post in certain ways. I concede that I may have oversimplified. It also gives space for, say, the NMI handler being in all banks.

Paste the .cfg that you're using for NROM, and I can create a .cfg for AOROM. Or are you using the default .cfg for -t nes?
User avatar
rainwarrior
Posts: 8733
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: CC65: Configure AOROM

Post by rainwarrior »

The format is documented here: http://cc65.github.io/doc/ld65.html

To use C you should have segments for ZEROPAGE, BSS, DATA, RODATA, and CODE. The memory part of the CFG creates a list of memory regions that will belong either in memory or be output to a file.

To output a .NES file you would need a memory block for zeropage and RAM (not output to file), and then a block for a header and one block per bank. (You can subdivide more if you need to, but not necessary.) Individual segments that need to be aligned, such as reset/nmi/irq vectors, can be done with a segment with a start attribute (e.g.) "start = $FFFA".
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: CC65: Configure AOROM

Post by Diskover »

Would this be correct?

Code: Select all

MEMORY {
	# Zero page
	ZP: start = $00, size = $100, type = rw, define = yes;

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

	# AOROM
	PRG0: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG1: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG2: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG3: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG4: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG5: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG6: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG7: start = $C000, size = $3ffa, file = %O, fill = yes, define = yes;
	
	VECTORS: start = $fffa, size = $6, file = %O, fill = yes;

	RAM: start = $0300, size = $0500, define = yes;

}

SEGMENTS {
	HEADER:		load = HEADER,	type = ro;
	ROM0:		load = PRG0,	type = ro,	define = yes;
	ROM1:		load = PRG1,	type = ro,	define = yes;
	ROM2:		load = PRG2,	type = ro,	define = yes;
	ROM3:		load = PRG3,	type = ro,	define = yes;
	ROM4:		load = PRG4,	type = ro,	define = yes;
	ROM5:		load = PRG5,	type = ro,	define = yes;
	ROM6:		load = PRG6,	type = ro,	define = yes;
	STARTUP:	load = PRG7,	type = ro,  define = yes;
	LOWCODE:	load = PRG7,	type = ro,					optional = yes;
	INIT:		load = PRG7,	type = ro,	define = yes,	optional = yes;
	DATA:		load = PRG7, run = RAM, type = rw,  define = yes;
	RODATA:		load = PRG7,	type = ro,	define = yes;
	CODE:		load = PRG7, 	type = ro, 	define = yes;
	VECTORS:	load = VECTORS,	type = rw;
	BSS:		load = RAM,		type = bss, define = yes;
	HEAP:		load = RAM,		type = bss, 				optional = yes;
	ZEROPAGE:	load = ZP,		type = zp;
}

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 = $0500;      # 5 pages stack
}

And ctr0.s

Code: Select all

NES_MAPPER				=2			;mapper number
NES_PRG_BANKS			=8			;number of 16K PRG banks, change to 2 for NROM256
NES_CHR_BANKS			=0			;number of 8K CHR banks
NES_MIRRORING			=1			;0 horizontal, 1 vertical, 8 four screen
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: CC65: Configure AOROM

Post by dougeff »

Bank sizes should be $8000 each, example...

PRG0: start = $8000, size = $8000, file = %O, fill = yes, define = yes;

And, you should have vectors in every bank, just in case.

Edit - Furthermore. I believe that the first bank is loaded at start-up. So INIT (startup) should be in PRG0.

And, you might want an array of numbers (0-7) in every bank to avoid bus conflicts during bank switches.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: CC65: Configure AOROM

Post by Diskover »

dougeff wrote:Bank sizes should be $8000 each, example...

PRG0: start = $8000, size = $8000, file = %O, fill = yes, define = yes;

And, you should have vectors in every bank, just in case.

Edit - Furthermore. I believe that the first bank is loaded at start-up. So INIT (startup) should be in PRG0.

And, you might want an array of numbers (0-7) in every bank to avoid bus conflicts during bank switches.
How?

Code: Select all

VECTORS0: start = $fffa, size = $6, file = %O, fill = yes;
VECTORS1: start = $fffa, size = $6, file = %O, fill = yes;
VECTORS2: start = $fffa, size = $6, file = %O, fill = yes;
VECTORS3: start = $fffa, size = $6, file = %O, fill = yes;
VECTORS4: start = $fffa, size = $6, file = %O, fill = yes;
VECTORS5: start = $fffa, size = $6, file = %O, fill = yes;
VECTORS6: start = $fffa, size = $6, file = %O, fill = yes;
VECTORS7: start = $fffa, size = $6, file = %O, fill = yes;
On the other hand:

Code: Select all

NES_MAPPER				=7			;mapper number
NES_PRG_BANKS			=8			;number of 16K PRG banks, change to 2 for NROM256
NES_CHR_BANKS			=0			;number of 8K CHR banks
NES_MIRRORING			=0			;0 horizontal, 1 vertical, 8 four screen
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: CC65: Configure AOROM

Post by dougeff »

NES_PRG_BANKS =16

8 banks of $8000 is 16 banks of $4000 (iNes header can only count by $4000).
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
Diskover
Posts: 219
Joined: Thu Nov 24, 2011 7:16 am
Contact:

Re: CC65: Configure AOROM

Post by Diskover »

Let's see if it's something like this:

Code: Select all

# Zero page
	ZP: start = $00, size = $100, type = rw, define = yes;

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

	# AOROM 128K
	PRG0: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG1: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG2: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG3: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG4: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG5: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG6: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG7: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG8: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG9: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG10: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG11: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG12: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG13: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG14: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
	PRG15: start = $C000, size = $3ffa, file = %O, fill = yes, define = yes;
	
	VECTORS: start = $fffa, size = $6, file = %O, fill = yes;
	
	# standard 2K SRAM (-zeropage)
	RAM: start = $0300, size = $0500, define = yes;
	MAP1: start = $0400, size = $0500, define = yes;
}

SEGMENTS {
	HEADER:		load = HEADER,	type = ro;
	ROM0:		load = PRG0,	type = ro,	define = yes;
	ROM1:		load = PRG1,	type = ro,	define = yes;
	ROM2:		load = PRG2,	type = ro,	define = yes;
	ROM3:		load = PRG3,	type = ro,	define = yes;
	ROM4:		load = PRG4,	type = ro,	define = yes;
	ROM5:		load = PRG5,	type = ro,	define = yes;
	ROM6:		load = PRG6,	type = ro,	define = yes;
	ROM7:		load = PRG7,	type = ro,	define = yes;
	ROM8:		load = PRG8,	type = ro,	define = yes;
	ROM9:		load = PRG9,	type = ro,	define = yes;
	ROM10:		load = PRG10,	type = ro,	define = yes;
	ROM11:		load = PRG11,	type = ro,	define = yes;
	ROM12:		load = PRG12,	type = ro,	define = yes;
	ROM13:		load = PRG13,	type = ro,	define = yes;
	ROM14:		load = PRG14,	type = ro,	define = yes;
	STARTUP:	load = PRG15,	type = ro,  define = yes;
	LOWCODE:	load = PRG15,	type = ro,					optional = yes;
	INIT:		load = PRG15,	type = ro,	define = yes,	optional = yes;
	DATA:		load = PRG15, run = RAM, type = rw,  define = yes;
	RODATA:		load = PRG15,	type = ro,	define = yes;
	CODE:		load = PRG15, 	type = ro, 	define = yes;
	VECTORS:	load = VECTORS,	type = rw;
	BSS:		load = RAM,		type = bss, define = yes;
	HEAP:		load = RAM,		type = bss, 				optional = yes;
	ZEROPAGE:	load = ZP,		type = zp;
	MAP:	    load = MAP1,	type = bss, define = yes;
}

Code: Select all

NES_MAPPER				=7			;mapper number
NES_PRG_BANKS			=16			;number of 16K PRG banks
NES_CHR_BANKS			=0			;number of 8K CHR banks
NES_MIRRORING			=0			;0 horizontal, 1 vertical, 8 four screen
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: CC65: Configure AOROM

Post by dougeff »

Nope.

I'll make one up a little later.

Are you planning to put code in banks 1-7, or just in bank 0? (Important, since you're using cc65).
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
rainwarrior
Posts: 8733
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: CC65: Configure AOROM

Post by rainwarrior »

You still should just make 8 x 32k PRG memory blocks for the AOROM banks.

The number 16 in the iNES header is unrelated. Don't think of the iNES header as specifying "banks" (this is unfortunate terminology), it is simply "size of ROM / 16k". The NESASM assembler also uses this same bad terminology. Some mappers do have 16k banks, but I think there's a lot of unnecessary confusion because of this.
Post Reply