/*
* 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 MMC2Mapper extends Mapper {
boolean chrlatchL = true;
boolean chrlatchR = false;
int chrbankL1 = 0;
int chrbankR1 = 0;
int chrbankL2 = 0;
int chrbankR2 = 0;
@Override
public void loadrom() throws BadMapperException {
//needs to be in every mapper. Fill with initial cfg
super.loadrom();
//on startup:
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;
}
}
@Override
public final void cartWrite(int addr, int data) {
if (addr < 0x8000 || addr > 0xffff) {
super.cartWrite(addr, data);
return;
} else if (addr >= 0xa000 && addr <= 0xafff) {
//remap prg
for (int i = 0; i < 8; ++i) {
prg_map[i] = (1024 * (i + 8 * (data & 0xf))) & (chrsize - 1);
}
} else if (addr >= 0xb000 && addr <= 0xbfff) {
chrbankL1 = data & 0x1f;
setupPPUBanks();
} else if (addr >= 0xc000 && addr <= 0xcfff) {
chrbankL2 = data & 0x1f;
setupPPUBanks();
} else if (addr >= 0xd000 && addr <= 0xdfff) {
chrbankR1 = data & 0x1f;
setupPPUBanks();
} else if (addr >= 0xe000 && addr <= 0xefff) {
chrbankR2 = data & 0x1f;
setupPPUBanks();
} else if (addr >= 0xf000 && addr <= 0xffff) {
setmirroring((((data & (utils.BIT0)) != 0)) ? MirrorType.H_MIRROR : MirrorType.V_MIRROR);
}
}
@Override
public int ppuRead(final int addr) {
int retval = super.ppuRead(addr);
if (((addr & (utils.BIT3)) != 0)) {
//latch fires after 2nd read from pattern table
//A3 will be on for 2nd read b/c it's tile low bytes
switch (addr >> 4) {
//read of the 2nd byte of tile fd/fe/1fd/1fe
//switches the set of character banks used for that side
//of the pattern table
case 0xfd:
if ((addr & 3) == 0) {
chrlatchL = false;
setupPPUBanks();
}
break;
case 0xfe:
if ((addr & 3) == 0) {
chrlatchL = true;
setupPPUBanks();
break;
}
case 0x1fd:
chrlatchR = false;
setupPPUBanks();
break;
case 0x1fe:
chrlatchR = true;
setupPPUBanks();
default:
break;
}
}
return retval;
}
// public void notifyscanline(final int scanline) {
// System.err.println(" ScanLine " + scanline + " " + chrlatchL);
// }
private void setupPPUBanks() {
if (chrlatchL) {
setppubank(4, 0, chrbankL2);
} else {
setppubank(4, 0, chrbankL1);
}
if (chrlatchR) {
setppubank(4, 4, chrbankR2);
} else {
setppubank(4, 4, chrbankR1);
}
}
private void setppubank(int banksize, int bankpos, int banknum) {
for (int i = 0; i < banksize; ++i) {
chr_map[i + bankpos] = (1024 * ((banksize * banknum) + i)) % chrsize;
}
//utils.printarray(chr_map);
}
}