218 lines
4.9 KiB
C++
218 lines
4.9 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
|
// BoardCoolBoy //
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//code by CaH4e3 from fceumm
|
|
|
|
void BoardCoolBoy::Reset()
|
|
{
|
|
if(!(VROM_8K_SIZE)) SetYCRAM_8K_Bank(0);
|
|
|
|
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
|
IRQReload = IRQCount = IRQLatch = IRQa = 0;
|
|
MMC3cmd = A000B = A001B = 0;
|
|
|
|
DRegBuf[0] = 0;
|
|
DRegBuf[1] = 2;
|
|
DRegBuf[2] = 4;
|
|
DRegBuf[3] = 5;
|
|
DRegBuf[4] = 6;
|
|
DRegBuf[5] = 7;
|
|
DRegBuf[6] = 0;
|
|
DRegBuf[7] = 1;
|
|
|
|
FixCBMMC3PRG(MMC3cmd);
|
|
FixCBMMC3CHR(MMC3cmd);
|
|
}
|
|
|
|
void BoardCoolBoy::WriteLow( WORD addr, BYTE data )
|
|
{
|
|
if( addr >= 0x5000 && addr <= 0x5FFF ) XRAM[addr-0x4000] = data;
|
|
if(addr>=0x6000)
|
|
{
|
|
if(A001B&0x80) CPU_MEM_BANK[addr>>13][addr&0x1FFF] = data;
|
|
if ((EXPREGS[3] & 0x90) != 0x80) {
|
|
EXPREGS[addr & 3] = data;
|
|
FixCBMMC3PRG(MMC3cmd);
|
|
FixCBMMC3CHR(MMC3cmd);
|
|
}
|
|
}
|
|
}
|
|
|
|
void BoardCoolBoy::Write( WORD addr, BYTE data )
|
|
{
|
|
switch (addr & 0xE001) {
|
|
case 0x8000:
|
|
if ((data & 0x40) != (MMC3cmd & 0x40))
|
|
FixCBMMC3PRG(data);
|
|
if ((data & 0x80) != (MMC3cmd & 0x80))
|
|
FixCBMMC3CHR(data);
|
|
MMC3cmd = data;
|
|
break;
|
|
case 0x8001:
|
|
{
|
|
int cbase = (MMC3cmd & 0x80) << 5;
|
|
DRegBuf[MMC3cmd & 0x7] = data;
|
|
switch (MMC3cmd & 0x07) {
|
|
case 0:
|
|
PPUSW((cbase ^ 0x000), data & (~1));
|
|
PPUSW((cbase ^ 0x400), data | 1);
|
|
break;
|
|
case 1:
|
|
PPUSW((cbase ^ 0x800), data & (~1));
|
|
PPUSW((cbase ^ 0xC00), data | 1);
|
|
break;
|
|
case 2:
|
|
PPUSW(cbase ^ 0x1000, data);
|
|
break;
|
|
case 3:
|
|
PPUSW(cbase ^ 0x1400, data);
|
|
break;
|
|
case 4:
|
|
PPUSW(cbase ^ 0x1800, data);
|
|
break;
|
|
case 5:
|
|
PPUSW(cbase ^ 0x1C00, data);
|
|
break;
|
|
case 6:
|
|
if (MMC3cmd&0x40) CPUSW(0xC000, data);
|
|
else CPUSW(0x8000, data);
|
|
break;
|
|
case 7:
|
|
CPUSW(0xA000, data);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case 0xA000:
|
|
A000B = data;
|
|
if (!nes->rom->Is4SCREEN()) {
|
|
if (A000B & 0x01) SetVRAM_Mirror(VRAM_HMIRROR);
|
|
else SetVRAM_Mirror(VRAM_VMIRROR);
|
|
}
|
|
break;
|
|
case 0xA001:
|
|
A001B = data;
|
|
break;
|
|
case 0xC000: IRQReload = 0;IRQCount = data; break;
|
|
case 0xC001: IRQReload = 0;IRQLatch = data; break;
|
|
case 0xE000: IRQReload = 0;IRQa = 0;nes->cpu->ClrIRQ(IRQ_MAPPER); break;
|
|
case 0xE001: IRQReload = 0;IRQa = 1; break;
|
|
}
|
|
|
|
}
|
|
|
|
void BoardCoolBoy::PPUSW(WORD A, BYTE V)
|
|
{
|
|
uint32 mask = 0xFF ^ (EXPREGS[0] & 0x80);
|
|
if (EXPREGS[3] & 0x10) {
|
|
if (EXPREGS[3] & 0x40) {
|
|
int cbase = (MMC3cmd & 0x80) << 5;
|
|
switch (cbase ^ A) {
|
|
case 0x0400:
|
|
case 0x0C00: V &= 0x7F; break;
|
|
}
|
|
}
|
|
SetYCRAM_1K_Bank(A>>10,
|
|
(V & 0x80 & mask) | ((((EXPREGS[0] & 0x08) << 4) & ~mask))
|
|
| ((EXPREGS[2] & 0x0F) << 3)
|
|
| ((A >> 10) & 7)
|
|
);
|
|
} else {
|
|
if (EXPREGS[3] & 0x40) {
|
|
int cbase = (MMC3cmd & 0x80) << 5;
|
|
switch (cbase ^ A) {
|
|
case 0x0000: V = DRegBuf[0]; break;
|
|
case 0x0800: V = DRegBuf[1]; break;
|
|
case 0x0400:
|
|
case 0x0C00: V = 0; break;
|
|
}
|
|
}
|
|
SetYCRAM_1K_Bank(A>>10, (V & mask) | (((EXPREGS[0] & 0x08) << 4) & ~mask));
|
|
}
|
|
}
|
|
|
|
void BoardCoolBoy::CPUSW(WORD A, BYTE V)
|
|
{
|
|
uint32 mask = ((0x3F | (EXPREGS[1] & 0x40) | ((EXPREGS[1] & 0x20) << 2)) ^ ((EXPREGS[0] & 0x40) >> 2)) ^ ((EXPREGS[1] & 0x80) >> 2);
|
|
uint32 base = ((EXPREGS[0] & 0x07) >> 0) | ((EXPREGS[1] & 0x10) >> 1) | ((EXPREGS[1] & 0x0C) << 2) | ((EXPREGS[0] & 0x30) << 2);
|
|
|
|
if ((EXPREGS[3] & 0x40) && (V >= 0xFE) && !((MMC3cmd & 0x40) != 0)) {
|
|
switch (A & 0xE000) {
|
|
case 0xA000:
|
|
if ((MMC3cmd & 0x40)) V = 0;
|
|
break;
|
|
case 0xC000:
|
|
if (!(MMC3cmd & 0x40)) V = 0;
|
|
break;
|
|
case 0xE000:
|
|
V = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!(EXPREGS[3] & 0x10))
|
|
SetPROM_8K_Bank(A>>13, (((base << 4) & ~mask)) | (V & mask));
|
|
else {
|
|
mask &= 0xF0;
|
|
uint8 emask;
|
|
if ((((EXPREGS[1] & 2) != 0)))
|
|
emask = (EXPREGS[3] & 0x0C) | ((A & 0x4000) >> 13);
|
|
else
|
|
emask = EXPREGS[3] & 0x0E;
|
|
SetPROM_8K_Bank(A>>13, ((base << 4) & ~mask)
|
|
| (V & mask)
|
|
| emask
|
|
| ((A & 0x2000) >> 13));
|
|
}
|
|
}
|
|
|
|
void BoardCoolBoy::FixCBMMC3PRG(BYTE data)
|
|
{
|
|
if (data & 0x40) {
|
|
CPUSW(0xC000, DRegBuf[6]);
|
|
CPUSW(0x8000, ~1);
|
|
} else {
|
|
CPUSW(0x8000, DRegBuf[6]);
|
|
CPUSW(0xC000, ~1);
|
|
}
|
|
CPUSW(0xA000, DRegBuf[7]);
|
|
CPUSW(0xE000, ~0);
|
|
}
|
|
|
|
void BoardCoolBoy::FixCBMMC3CHR(BYTE data)
|
|
{
|
|
int cbase = (data & 0x80) << 5;
|
|
PPUSW((cbase ^ 0x000), DRegBuf[0] & (~1));
|
|
PPUSW((cbase ^ 0x400), DRegBuf[0] | 1);
|
|
PPUSW((cbase ^ 0x800), DRegBuf[1] & (~1));
|
|
PPUSW((cbase ^ 0xC00), DRegBuf[1] | 1);
|
|
PPUSW(cbase ^ 0x1000, DRegBuf[2]);
|
|
PPUSW(cbase ^ 0x1400, DRegBuf[3]);
|
|
PPUSW(cbase ^ 0x1800, DRegBuf[4]);
|
|
PPUSW(cbase ^ 0x1c00, DRegBuf[5]);
|
|
}
|
|
|
|
void BoardCoolBoy::HSync(INT scanline)
|
|
{
|
|
if ((scanline >= 0 && scanline <= 239)) {
|
|
if (nes->ppu->IsDispON())
|
|
{
|
|
if (IRQa && !IRQReload) {
|
|
if (scanline == 0) {
|
|
if (IRQCount) {
|
|
IRQCount -= 1;
|
|
}
|
|
}
|
|
if (!(IRQCount)){
|
|
IRQReload = 0xFF;
|
|
IRQCount = IRQLatch;
|
|
nes->cpu->SetIRQ(IRQ_MAPPER);
|
|
}
|
|
IRQCount--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|