/*
* 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;
}
}
}