Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65.

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

gutomaia
Posts: 31
Joined: Fri Jun 15, 2012 10:12 am

Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65.

Post by gutomaia »

Hi guys.

I'm creating a cfg file for CC65 with the following requirements:

NES_MAPPER: type = weak, value = 4; # mapper number MMC3
NES_PRG_BANKS: type = weak, value= 8;
NES_CHR_BANKS: type = weak, value = 0;
NES_MIRRORING: type = weak, value = 0;

I do need to use a CHR-RAM, that's why I've put without CHR RAM. Although, after several attempts and tweaks on my CFG file, I was not able to create a working NES file for the game. Some help and clues?

Bellow, It's my complete nes.cfg file. I was not able to spot where is the problem is. Btw, anyone has any links to config templates? Thanks

Code: Select all

SYMBOLS {
    __STACKSIZE__: type = weak, value = $0300; # 3 pages stack
    NES_MAPPER: type = weak, value = 4;             # mapper number
    NES_PRG_BANKS: type = weak, value= 8;           # number of 16K PRG banks, change to 2 for NROM256
    NES_CHR_BANKS: type = weak, value = 0;          # number of 8K CHR banks
    NES_MIRRORING: type = weak, value = 1;          # 0 horizontal, 1 vertical, 8 four screen
}
MEMORY {
    ZP:     file = "", start = $0002, size = $00FE, type = rw, define = yes;

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

    # 3 16K ROM Banks @ $8000
    PRG0: start = $8000, size = $2000, file = %O ,fill = yes, define = yes;
    PRG1: start = $8000, size = $2000, file = %O ,fill = yes, define = yes;
    PRG2: start = $8000, size = $2000, file = %O ,fill = yes, define = yes;

    # 3 16K ROM Banks @ $a000
    PRG3: start = $a000, size = $2000, file = %O ,fill = yes, define = yes;
    PRG4: start = $a000, size = $2000, file = %O ,fill = yes, define = yes;
    PRG5: start = $a000, size = $2000, file = %O ,fill = yes, define = yes;

    # fixed 16K ROM banks @ $c000
    PRG6: start = $c000, size = $2000, file = %O ,fill = yes, define = yes;

    # final bank has
    # - startup
    # - code
    # - vectors
    PRG7:    file = %O, start = $E000, size = $1FFA, fill = yes, define = yes;
    VECTORS: file = %O, start = $FFFA, size = $0006, fill = yes;

    # 8 8k CHR Banks (64k)
    CHR:   file = %O, start = $0000, size = $10000, fill = yes;

    # standard 2k SRAM (-zeropage)
    # $0100-$0200 cpu stack
    # $0200-$0500 3 pages for ppu memory write buffer
    # $0500-$0800 3 pages for cc65 parameter stack
    SRAM:   file = "", start = $0500, size = __STACKSIZE__, define = yes;

    # additional 8K SRAM Bank
    # - data (run)
    # - bss
    # - heap
    RAM:    file = "", start = $6000, size = $2000, define = yes;
}

SEGMENTS {
    ZEROPAGE: load = ZP,              type = zp;
    HEADER:   load = HEADER,          type = ro;
    CODE0:    load = PRG0,            type = ro,  define   = yes, optional = yes;
    CODE1:    load = PRG1,            type = ro,  define   = yes, optional = yes;
    CODE2:    load = PRG2,            type = ro,  define   = yes, optional = yes;
    CODE3:    load = PRG3,            type = ro,  define   = yes, optional = yes;
    CODE4:    load = PRG4,            type = ro,  define   = yes, optional = yes;
    CODE5:    load = PRG5,            type = ro,  define   = yes, optional = yes;
    CODE6:    load = PRG6,            type = ro,  define   = yes, optional = yes;
    RODATA:   load = PRG6,            type = ro,  define   = yes;
    ONCE:     load = PRG6,            type = ro,  optional = yes;
    DATA:     load = PRG6, run = RAM, type = rw,  define   = yes;
    STARTUP:  load = PRG6,            type = ro,  define   = yes;
    CODE:     load = PRG7,            type = ro,  define   = yes;
    VECTORS:  load = VECTORS,         type = ro;
    CHARS:    load = CHR,             type = ro;
    BSS:      load = SRAM,            type = bss, define   = yes;
}
FEATURES {
    CONDES: type    = constructor,
            label   = __CONSTRUCTOR_TABLE__,
            count   = __CONSTRUCTOR_COUNT__,
            segment = ONCE;
    CONDES: type    = destructor,
            label   = __DESTRUCTOR_TABLE__,
            count   = __DESTRUCTOR_COUNT__,
            segment = RODATA;
    CONDES: type    = interruptor,
            label   = __INTERRUPTOR_TABLE__,
            count   = __INTERRUPTOR_COUNT__,
            segment = RODATA,
            import  = __CALLIRQ__;
}
------

There is a bounty on this issue, what that means, I intend to pay 50 USD for someone that would help or at least, lead me to fix this.

How that would work and the rules are the following:

* the Main goal it's to run the demo on actual devices, mostly some clones that are able to run MMC3 games.
* the Second goal it's to change the 8 CHR-ROM to a single CHR-RAM that still works on the same devices.

The bounty it's split on:
1) 25 USD to make the DEMO work on those devices and increase the compatibility with emulators (just run on fceux) https://github.com/gutomaia/NES_bankswi ... e/issues/1.
2) 5 USD to fix a load of bank 2 on 8000. https://github.com/gutomaia/NES_bankswi ... e/issues/2
3) 20 USD to keep demo work on the devices and switch to a CHR-RAM. https://github.com/gutomaia/NES_bankswi ... e/issues/3

For each bounty, there is a link to a related issue on the Github repository. If any bounty became fulfilled, I will update this post with the username who achieved it.
To be eligible to participate, you must be a member of the forum so I can send you PM to finish the transaction.

That's it.
the game is afoot


----

UPDATE
Solved bounty #2 - Then I'm increasing bounty #1 to 30 USD.

Any tip that leads to the answer also counts.


----

UPDATE

Bounty is off. Thanks all for all your support.
Last edited by gutomaia on Wed Dec 16, 2020 6:57 am, edited 5 times in total.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65.

Post by tepples »

How big do you want the PRG ROM to be? Eight 16K PRG banks or eight 8 KiB PRG banks?

For creating the header, see my header macro pack.
gutomaia
Posts: 31
Joined: Fri Jun 15, 2012 10:12 am

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65.

Post by gutomaia »

Thanks tepples for answering so fast.
tepples wrote: Wed Dec 02, 2020 12:49 pm How big do you want the PRG ROM to be? Eight 16K PRG banks or eight 8 KiB PRG banks?
I do need eight 8 KiB PGR banks. I'm swithing banks to load different parts of code and assets on the CHR RAM.
tepples wrote: Wed Dec 02, 2020 12:49 pm For creating the header, see my header macro pack.
I've just looked. Not sure how that would fit in my project. I'm using C, mostly following some examples on 8bitworkshop by Steven Hugg. Like the bank switch example at https://8bitworkshop.com/v3.7.0/?file=b ... atform=nes
gutomaia
Posts: 31
Joined: Fri Jun 15, 2012 10:12 am

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65.

Post by gutomaia »

I've just compared the Ns time with the MMC3 docs: https://wiki.nesdev.com/w/index.php/MMC3

I didn't find anything awkward.

---- UPDATED ----

To better explain and receive feedback on the problem, I've opened a git repository with just an exemplo. I will evolve that example on the actual CHR RAM example that I'm aiming for.

Here's the link to the repository: https://github.com/gutomaia/NES_bankswitch_example

Just clone and type "make". The script should handle the packing and compile.

Thanks.
gutomaia
Posts: 31
Joined: Fri Jun 15, 2012 10:12 am

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65 (50 USD bounty).

Post by gutomaia »

I've just released a bounty for this topic. Questions on the topic will remain related to the subject. Questions related to the bounty can be answered thru private messages.
gutomaia
Posts: 31
Joined: Fri Jun 15, 2012 10:12 am

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65 (50 USD bounty).

Post by gutomaia »

Debug over bounty #1

The device just crashes and closes the emulator. Looks the CPU is running over non-opcode values. One hypothesis is that there must be some MMC3 initiation code missing.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65 (50 USD bounty).

Post by lidnariq »

You must put your startup code in the last 8KB with MMC3.
gutomaia
Posts: 31
Joined: Fri Jun 15, 2012 10:12 am

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65 (50 USD bounty).

Post by gutomaia »

lidnariq wrote: Sat Dec 05, 2020 5:22 pm You must put your startup code in the last 8KB with MMC3.
Great! How to check if the start code it isn't on the last bank. And moreover, how to fix it?!

But let's start on the first step. Check if the last 8kb is the actual main code. Not sure how to check, the ROM built is this one: https://github.com/gutomaia/NES_bankswi ... /403200446
I think that's the best ROM to check.

But great tip. hope it leads to fix this.
gutomaia
Posts: 31
Joined: Fri Jun 15, 2012 10:12 am

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65 (50 USD bounty).

Post by gutomaia »

lidnariq wrote: Sat Dec 05, 2020 5:22 pm You must put your startup code in the last 8KB with MMC3.
First, you're right lidnariq, my startup code is not on the last bank.

With the following commands, I've removed the INES header and then broke into 8kb banks

dd bs=16 skip=1 if=bankswitch.nes of=bankswitch_noinesheader.nes
split -b 8192 bankswitch_noinesheader.nes

That resulted in 16 files:
xaa xab xac xad xae xaf xag xah xai xaj xak xal xam xan xao xap

XAJ to XAP are empty. Therefore, last 8kb are empty.

Now, based on your premise. Trying to figure out, what bank order will make it work. What's the expected bank arrangement for MMC3?
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65 (50 USD bounty).

Post by lidnariq »

Your configuration file defines eight 8 KB PRG banks, followed by one 64KB CHR bank. It's fine to not have any data in your CHR yet.

However, if you look in "xag" you'll see that it contains a bunch of stuff that you didn't put there. This is because your nes.cfg puts the STARTUP segment in CODE6 but you need – at the very least – crt0 to be in CODE.

Right now, your CONDES statements are putting something in the ONCE segment. I haven't figured out when I'd ever want those on the (RAM-poor) NES. You might get rid of of the FEATURES altogether, although someone else may have a reason to keep it.

Additionally, you may have noticed that it wasn't generating the listing files, which would have helped. Apparently cl65 requires that you put the --listing parameter in your makefile before the source file.
gutomaia
Posts: 31
Joined: Fri Jun 15, 2012 10:12 am

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65 (50 USD bounty).

Post by gutomaia »

lidnariq wrote: Mon Dec 07, 2020 12:12 pm Your configuration file defines eight 8 KB PRG banks, followed by one 64KB CHR bank. It's fine to not have any data in your CHR yet.
Yep I'm also playing with just one CHR

lidnariq wrote: Mon Dec 07, 2020 12:12 pm However, if you look in "xag" you'll see that it contains a bunch of stuff that you didn't put there. This is because your nes.cfg puts the STARTUP segment in CODE6 but you need – at the very least – crt0 to be in CODE.
I was wondering where that came from, not sure how to fix that with CC65.
lidnariq wrote: Mon Dec 07, 2020 12:12 pm Right now, your CONDES statements are putting something in the ONCE segment. I haven't figured out when I'd ever want those on the (RAM-poor) NES. You might get rid of of the FEATURES altogether, although someone else may have a reason to keep it.
I've tried, but a receive the following error, might be something wrong with my compiler parameters. BTW makefile and compiling are working for you?

Code: Select all

Unresolved external '__CONSTRUCTOR_COUNT__' referenced in:
  runtime/condes.s(30)
Unresolved external '__CONSTRUCTOR_TABLE__' referenced in:
  runtime/condes.s(32)
  runtime/condes.s(33)
Unresolved external '__DESTRUCTOR_COUNT__' referenced in:
  runtime/condes.s(47)
Unresolved external '__DESTRUCTOR_TABLE__' referenced in:
  runtime/condes.s(49)
  runtime/condes.s(50)
ld65: Error: 4 unresolved external(s) found - cannot create output file
make: *** [bin/bankswitch.nes] Error 1
lidnariq wrote: Mon Dec 07, 2020 12:12 pm Additionally, you may have noticed that it wasn't generating the listing files, which would have helped. Apparently cl65 requires that you put the --listing parameter in your makefile before the source file.
I will give a try on the listing files. I think that I had it before, on previous versions of my Makefile.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65 (50 USD bounty).

Post by lidnariq »

gutomaia wrote: Mon Dec 07, 2020 12:32 pm I was wondering where that came from, not sure how to fix that with CC65.
lidnariq wrote: Mon Dec 07, 2020 12:12 pm This is because your nes.cfg puts the STARTUP segment in CODE6 but you need – at the very least – crt0 to be in CODE.
I ... did address that.
I've tried [removing CONDES], but a receive the following error, might be something wrong with my compiler parameters.
Then don't link in condes.s ?
BTW makefile and compiling are working for you?
I'm using git HEAD cc65, and --lib doesn't exist. I just removed that bit, because one doesn't usually include libraries in the compilation stage anyway.
User avatar
rainwarrior
Posts: 8734
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65 (50 USD bounty).

Post by rainwarrior »

lidnariq wrote: Mon Dec 07, 2020 12:50 pm
I've tried [removing CONDES], but a receive the following error, might be something wrong with my compiler parameters.
Then don't link in condes.s ?
If condes.o is getting linked it means there's a reference to initlib or donelib in your crt0.o. You could remove it from the library archive with ar65 but you wouldn't be able to explicitly unlink it. You have to rebuild crt0 without the reference to those two functions. Once that's done it won't matter if condes.o remains in the library, as it won't get linked without any references.

The FEATURES / CONDES stuff is useless for NES. It adds an ability for linked modules to have a startup/shutdown routine at program start and exit. The shutdown part doesn't really make sense on any platform where you don't return to an operating system on exit. The startup part might be useful, but AFAIK as a feature it's only used for an IRQ implementation on a few systems. I recommend getting rid of this feature from your library.


FWIW I don't really like any of the platform libraries that come with cc65. My approach is generally to take everything in libsrc/runtime and libsrc/common, and write my own crt0 that's part of my program rather than a library. That's enough to get all the basic stuff going. If you want to use some library functions like printf, etc. you might need to write some of the dependent routines, but if you're going to be making a game you probably don't need any of it. All ctr0.s really needs to do is handle a reset, jsr copydata, set up the C stack pointer, and jmp _main. (Example: dgolf.s)
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65 (50 USD bounty).

Post by dougeff »

Probably not relevant, but I believe exit() calls donelib. Don't use it in the C code. There is no OS to exit to anyway on the NES (as rainwarrior stated)
Last edited by dougeff on Mon Dec 07, 2020 5:06 pm, edited 1 time in total.
nesdoug.com -- blog/tutorial on programming for the NES
gutomaia
Posts: 31
Joined: Fri Jun 15, 2012 10:12 am

Re: Help on define MMC3 mapper with 8 PGR roms and CHR RAM with CC65 (50 USD bounty).

Post by gutomaia »

lidnariq wrote: Mon Dec 07, 2020 12:50 pm
gutomaia wrote: Mon Dec 07, 2020 12:32 pm I was wondering where that came from, not sure how to fix that with CC65.
lidnariq wrote: Mon Dec 07, 2020 12:12 pm This is because your nes.cfg puts the STARTUP segment in CODE6 but you need – at the very least – crt0 to be in CODE.
I ... did address that.
I've tried [removing CONDES], but a receive the following error, might be something wrong with my compiler parameters.
Then don't link in condes.s ?
BTW makefile and compiling are working for you?
I'm using git HEAD cc65, and --lib doesn't exist. I just removed that bit, because one doesn't usually include libraries in the compilation stage anyway.
Thanks, I made some changes:
- I put the STARTUP code in PGR7, then both are on the last bank.
- I started using the head of cc65 repository for compile.

But I'm still trying:
- remove the features you mentioned and remove condes.s from nes.lib
Post Reply