CC65: Configure AOROM
Moderator: Moderators
CC65: Configure AOROM
Using CC65, how can I configure the parameters to function as AOROM?
Re: CC65: Configure AOROM
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.
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.
Re: CC65: Configure AOROM
I just need to know the file configuration *. Cfg to make a small example
Yes, it would be to use C.
Yes, it would be to use C.
Re: CC65: Configure AOROM
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).
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
- rainwarrior
- Posts: 8733
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: CC65: Configure AOROM
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.
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.
Re: CC65: Configure AOROM
I keep in mind about the banksiwch. Do not worry.
The only thing I want to know is how to configure the *. CFG, please. -
The only thing I want to know is how to configure the *. CFG, please. -
Re: CC65: Configure AOROM
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.rainwarrior wrote:I have no idea why tepples suggested "768 bytes" for a bank switching routine-- it should take far less than that.
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?
- rainwarrior
- Posts: 8733
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: CC65: Configure AOROM
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".
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".
Re: CC65: Configure AOROM
Would this be correct?
And ctr0.s
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
Re: CC65: Configure AOROM
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.
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
Re: CC65: Configure AOROM
How?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.
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;
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
Re: CC65: Configure AOROM
NES_PRG_BANKS =16
8 banks of $8000 is 16 banks of $4000 (iNes header can only count by $4000).
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
Re: CC65: Configure AOROM
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
Re: CC65: Configure AOROM
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).
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
- rainwarrior
- Posts: 8733
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: CC65: Configure AOROM
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.
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.