MMC1, banking, ca65/ld65 woes

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

Post Reply
avalon
Posts: 3
Joined: Thu Aug 09, 2007 11:40 am

MMC1, banking, ca65/ld65 woes

Post by avalon »

I have written a program which might need more than 16KB of data at times, and I have "decided" that for clarity's sake (?) I'm going to use MMC1 and swap the lower bank, upper bank being static and containing the code. Thus, the memory setup I'd like to have is something like this:

(data/bank 1)(data/bank 2) ... (code/bank n)

Now, I'm not sure how to relay that information to ca65/ld65. The memory (mis-)configuration I currently have is:

Code: Select all

MEMORY {
	ROM1:    	start = $8000, size = $8000;
	ROM2:    	start = $c000, size = $8000;
}

SEGMENTS {
	DATA:		load = ROM1, type = ro;
	CODE:		load = ROM2, type = ro;
	VECTORS:	load = ROM2, type = ro, start = $FFFA;
}
I took a look at another memory configuration from an open-source project (Tetramino), which seems to have "fluff" like ZPA area declaration - does ca65/ld65 really (have to) care? Do I need to specify the ROM segments "type = rw" to be able to manipulate the mapper? The start address of the RAM area is $0300.. shouldn't that be $0200? Confusing. :)

Code: Select all

MEMORY {
  ZP:     start = $10, size = $f0, type = rw;
  # use first $10 zeropage locations as locals
  HEADER: start = $7f00, size = $0010, type = ro, file = %O;
  RAM:    start = $0300, size = $0500, type = rw;
  ROM:    start = $C000, size = $8000, type = ro, file = %O;
}

SEGMENTS {
  INESHDR:  load = HEADER, type = ro, align = $10;
  ZEROPAGE: load = ZP, type = zp;
  DATA:     load = ROM, run = RAM, type = rw, define = yes, align = $100;
  BSS:      load = RAM, type = bss, define = yes, align = $100;
  CODE:     load = ROM, type = ro, align = $100;
  RODATA:   load = ROM, type = ro, align = $100;
  DMC:      load = ROM, type = ro, align = $40;
  VECTORS:  load = ROM, type = ro, start = $FFFA;
}

FILES {
  %O: format = bin;
}
So, my question boils down to this - how can I introduce the additional data banks to my code & ca65/ld65? Code additions probably amount to something like:

Code: Select all

.segment "DATABNK1"
.incbin "foo1.bin"
.segment "DATABNK2"
.incbin "foo2.bin"
But.. yeah. I initially wrote the program using NESASM, tried to figure out the banking there to no avail, checked here for help and found out that it blows and this is the way to go, converted the program and here I am again. ;)
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: MMC1, banking, ca65/ld65 woes

Post by tepples »

avalon wrote:I have written a program which might need more than 16KB of data at times, and I have "decided" that for clarity's sake (?) I'm going to use MMC1 and swap the lower bank, upper bank being static and containing the code[...]

Code: Select all

MEMORY {
	ROM1:    	start = $8000, size = $8000;
	ROM2:    	start = $c000, size = $8000;
}
MMC1 banks in this configuration are size $4000, not size $8000.
I took a look at another memory configuration from an open-source project (Tetramino), which seems to have "fluff" like ZPA area declaration - does ca65/ld65 really (have to) care? Do I need to specify the ROM segments "type = rw" to be able to manipulate the mapper? The start address of the RAM area is $0300.. shouldn't that be $0200? Confusing. :)
My link script reserves $0200-$02FF for the OAM transfer buffer.
avalon
Posts: 3
Joined: Thu Aug 09, 2007 11:40 am

Re: MMC1, banking, ca65/ld65 woes

Post by avalon »

tepples wrote:MMC1 banks in this configuration are size $4000, not size $8000.
Indeed, left-overs from experimenting with stuff.
tepples wrote:My link script reserves $0200-$02FF for the OAM transfer buffer.
Speak of the devil.. :D Ok.. is it about not declaring areas/segments you don't want ld65 to touch? You also have the ZP memory area and the ZEROPAGE segment, but the segment doesn't seem to be referenced in the code. Is it necessary to tell ld65 that $0000 - $00ff is for ZPA (for initialization or something?), or is it enough that I know what it is for and how to use it?

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

Re: MMC1, banking, ca65/ld65 woes

Post by tepples »

avalon wrote:Speak of the devil.. :D Ok.. is it about not declaring areas/segments you don't want ld65 to touch?
Yes.
You also have the ZP memory area and the ZEROPAGE segment, but the segment doesn't seem to be referenced in the code.
That's because Tetramino was originally written for x816 but ported to cc65, so I went only halfway with making use of what my link script allowed me. See tvpassfail for a more complete example.
Is it necessary to tell ld65 that $0000 - $00ff is for ZPA (for initialization or something?)
No. You need to declare a section if you'll be putting something there.
avalon
Posts: 3
Joined: Thu Aug 09, 2007 11:40 am

Post by avalon »

Thanks for the info, I got it working although I possibly cheated by not playing around with ld65 and just building the image on the fly.

My memory configuration is now simply:

Code: Select all

MEMORY {
	ROM1:    	start = $8000, size = $4000, type = ro;
	ROM2:    	start = $c000, size = $4000, type = ro;
}

SEGMENTS {
	DATA:		load = ROM1, type = ro;
	CODE:		load = ROM2, type = ro;
	VECTORS:	load = ROM2, type = ro, start = $fffa;
}
I have declared 5 PRG banks and 0 CHR banks in the header. Then, I just compile and link the program and:

copy /b header.bin + dummy.bin + dummy.bin + dummy.bin + dummy.bin + myprog.prg

..dummy.bin containing 16KB of junk just to fill it up. There's a problem related to mapper usage (with FCE Ultra only?), though.
MMC1 documentation wrote: When the cart is first started, the first 16K ROM bank in the cart is loaded into $8000, and the LAST 16K bank into $C000.
Following addresses are offsets in the image.

iNES hdr = $00000 (5 banks of PRG-ROM, 0 CHR-ROM)
1st bank = $00010 (dummy data)
2nd bank = $04010 (dummy data)
3rd bank = $08010 (dummy data)
4th bank = $0c010 (dummy data)
5th bank = $10010 (program)

Everything seems to be OK in there as far as I can tell, but FCE Ultra w/debugger fails to load the last bank into $c000, although it loads the first one into $8000. No$nes seems to have no trouble whatsoever, and the program at least looks like it's working when run in the debugger..

edit:

Looks like 5 banks confused the other emulators - it works in FCEU, Nintendulator and friends with 4 banks.

edit:

MMC1 is annoying, switched to UNROM. :P
Post Reply