Implementing Mapper 15 (100 in 1)

Discuss emulation of the Nintendo Entertainment System and Famicom.
User avatar
colinvella
Posts: 74
Joined: Sun Jun 05, 2016 1:41 pm

Implementing Mapper 15 (100 in 1)

Post by colinvella »

Hi,

I'm trying to implement Mapper 15 but I can't get it to work.

The following is the relevant code/logic of my implementation. Can anyone point out where I'm going wrong?

Thanks

Code: Select all

        public byte this[ushort address]
        {
            get
            {
                if (address < 0x2000)
                    return Cartridge.CharacterRom[address];

                int index = 0;
                switch (bankMode)
                {
                    case 0:
                        index = address & 0x3FFF;
                        if (address >= 0x8000 && address < 0xC000)
                        {
                            return Cartridge.ProgramRom[programRomBank * 0x4000 + index];
                        }
                        else if (address >= 0xC000)
                        {
                            return Cartridge.ProgramRom[(programRomBank | 1) * 0x4000 + index];
                        }
                        break;
                    case 1:
                        index = address & 0x3FFF;
                        if (address >= 0x8000 && address < 0xC000)
                        {
                            return Cartridge.ProgramRom[programRomBank * 0x4000 + index];
                        }
                        else if (address >= 0xC000)
                        {
                            // last bank
                            return Cartridge.ProgramRom[Cartridge.ProgramRom.Count - 0x4000 + index];
                        }
                        break;
                    case 2:
                        // 8k banks
                        index = address & 0x1FFF;
                        if (address >= 0x8000)
                        {
                            return Cartridge.ProgramRom[programRomBank * 0x4000 + subBank * 0x2000 + index];
                        }
                        break;
                    case 3:
                        // 16k banks (mirrored)
                        index = address & 0x3FFF;
                        if (address >= 0x8000)
                        {
                            return Cartridge.ProgramRom[programRomBank * 0x4000 + index];
                        }
                        break;
                }

                throw new Exception("Unhandled " + Name + " mapper read at address: " + Hex.Format(address));
            }

            set
            {
                if (address < 0x2000)
                {
                    Cartridge.CharacterRom[address] = value;
                    return;
                }

                if (address >= 0x8000)
                {
                    bankMode = address & 0x03;
                    programRomBank = value & 0x3f;
                    subBank = value >> 7;

                    byte mirrorMode = (value & 0x40) != 0 ? Cartridge.MirrorHorizontal : Cartridge.MirrorVertical;
                    if (Cartridge.MirrorMode != mirrorMode)
                    {
                        Cartridge.MirrorMode = mirrorMode;
                        Cartridge.MirrorModeChanged?.Invoke();
                    }
                    return;
                }

                throw new Exception("Unhandled " + Name + " mapper write at address: " + Hex.Format(address));
            }
        }

        private int bankMode;
        private int programRomBank;
        private int subBank;
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/
User avatar
Dwedit
Posts: 5257
Joined: Fri Nov 19, 2004 7:35 pm

Re: Implementing Mapper 15 (100 in 1)

Post by Dwedit »

Your memory map design is really weird, you seem to be combining the CPU and PPU memory maps.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
colinvella
Posts: 74
Joined: Sun Jun 05, 2016 1:41 pm

Re: Implementing Mapper 15 (100 in 1)

Post by colinvella »

Dwedit wrote:Your memory map design is really weird, you seem to be combining the CPU and PPU memory maps.
I have a dispatch-based memory class where I plug in the Mapper to the address range $0000-$1FFF and $6000-$FFFF when a cartridge is loaded. Hence the logic for CPU and PPU memory is in the same mapper instance and its isolated within it. I have so far managed to implement NROM, CNROM, AXROM, MMC1, MMC2, MMC3, Colour Dreams, UxROM and CPROM.
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/
User avatar
colinvella
Posts: 74
Joined: Sun Jun 05, 2016 1:41 pm

Re: Implementing Mapper 15 (100 in 1)

Post by colinvella »

I think I solved the problem, or at least found a solution that works with the Contra 16 100-in-1 rom.

The NesDev wiki for Mapper 15 states that the starting bank mode should be 2. There is a dispute at the end of the page that states there's a disagreement on the starting mode and some say it should be 0. I did try using 0 instead of 2 and it works.
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/