/* * HalfNES by Andrew Hoffman * Licensed under the GNU GPL Version 3. See LICENSE file */ package com.grapeshot.halfnes.mappers; import com.grapeshot.halfnes.*; /** * * @author Andrew */ public class Mapper47 extends MMC3Mapper { //official Nintendo multicart mapper, mmc3 variant //used for super spike vball, nintendo world cup private int multibank = 1; @Override public void loadrom() throws BadMapperException { //needs to be in every mapper. Fill with initial cfg super.loadrom(); for (int i = 1; i <= 32; ++i) { prg_map[32 - i] = prgsize - (1024 * i); } for (int i = 0; i < 8; ++i) { chr_map[i] = 0; } setbank6(); } @Override public void cartWrite(int addr, int data) { if (addr < 0x6000 || addr > 0xffff) { super.cartWrite(addr, data); return; } //multicart bankswitches here if ((addr >= 0x6000) && (addr <= 0x7fff)) { multibank = data & 1; //setup all banks for (int i = 0; i < 8; ++i) { prg_map[i + 8] = ((1024 * (i + (data * 8))) % 131072) + multibank * 131072; } setbank6(); setupchr(); for (int i = 1; i <= 8; ++i) { prg_map[32 - i] = 131072 - (1024 * i) + multibank * 131072; } } //different register for even/odd writes if (((addr & (utils.BIT0)) != 0)) { //odd registers if ((addr >= 0x8000) && (addr <= 0x9fff)) { //bank change //System.err.println("setting " + whichbank + " " + data + " " + prgconfig); if (whichbank <= 5) { chrreg[whichbank] = data; setupchr(); } else if (whichbank == 6) { bank6 = data; setbank6(); } else if (whichbank == 7) { //bank 7 always swappable, always in same place for (int i = 0; i < 8; ++i) { prg_map[i + 8] = ((1024 * (i + (data * 8))) % 131072) + multibank * 131072; } } } else if ((addr >= 0xA000) && (addr <= 0xbfff)) { //prg ram write protect //cpuram.setPrgRAMEnable(!utils.getbit(data, 7)); } else if ((addr >= 0xc000) && (addr <= 0xdfff)) { //any value here reloads irq counter irqreload = true; } else if ((addr >= 0xe000) && (addr <= 0xffff)) { //iany value here enables interrupts irqenable = true; } } else { //even registers if ((addr >= 0x8000) && (addr <= 0x9fff)) { //bank select whichbank = data & 7; prgconfig = ((data & (utils.BIT6)) != 0); //if bit is false, 8000-9fff swappable and c000-dfff fixed to 2nd to last bank //if bit is true, c000-dfff swappable and 8000-9fff fixed to 2nd to last bank chrconfig = ((data & (utils.BIT7)) != 0); //if false: 2 2k banks @ 0000-0fff, 4 1k banks in 1000-1fff //if true: 4 1k banks @ 0000-0fff, 2 2k banks @ 1000-1fff setupchr(); setbank6(); //OOPS FORGOT THIS I GUESS } else if ((addr >= 0xA000) && (addr <= 0xbfff)) { //mirroring setup if (scrolltype != MirrorType.FOUR_SCREEN_MIRROR) { setmirroring(((data & (utils.BIT0)) != 0) ? MirrorType.H_MIRROR : MirrorType.V_MIRROR); } } else if ((addr >= 0xc000) && (addr <= 0xdfff)) { //value written here used to reload irq counter _@ end of scanline_ irqctrreload = data; } else if ((addr >= 0xe000) && (addr <= 0xffff)) { //any value here disables IRQ and acknowledges if (interrupted) { --cpu.interrupt; } interrupted = false; irqenable = false; } } } protected void setbank6() { if (!prgconfig) { //map c000-dfff to last bank, 8000-9fff to selected bank for (int i = 0; i < 8; ++i) { prg_map[i] = ((1024 * (i + (bank6 * 8))) % 131072) + multibank * 131072; prg_map[i + 16] = ((131072 - 16384) + 1024 * (i + multibank * 128)); } } else { //map 8000-9fff to last bank, c000 to dfff to selected bank for (int i = 0; i < 8; ++i) { prg_map[i] = ((131072 - 16384) + 1024 * (i + multibank * 128)); prg_map[i + 16] = ((1024 * (i + (bank6 * 8))) % 131072) + multibank * 131072; } } } protected void setppubank(int banksize, int bankpos, int banknum) { // System.err.println(banksize + ", " + bankpos + ", "+ banknum); for (int i = 0; i < banksize; ++i) { chr_map[i + bankpos] = ((1024 * ((banknum) + i)) % (chrsize / 2)) + multibank * 131072; } } }