AxibugEmuOnline/References/VirtuaNESex_src_191105/NES/Mapper/BoardMMC3.cpp
2024-08-05 17:58:53 +08:00

185 lines
3.6 KiB
C++

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "DebugOut.h"
#include "typedef.h"
#include "macro.h"
#include "nes.h"
#include "mmu.h"
#include "cpu.h"
#include "ppu.h"
#include "apu.h"
#include "pad.h"
#include "rom.h"
#include "mapper.h"
#include "Config.h"
#include "BoardMMC3.h"
BYTE MMC3_cmd;
BYTE MMC3_DRegBuf[8];
BYTE MMC3_A000B, MMC3_A001B;
BYTE MMC3_IRQCount, MMC3_IRQLatch, MMC3_IRQa, MMC3_IRQReload;
// ------------------------- Generic MM3 Code ---------------------------
void MMC3_RegReset()
{
MMC3_IRQReload = MMC3_IRQCount = MMC3_IRQLatch = MMC3_IRQa = 0;
MMC3_cmd = MMC3_A000B = MMC3_A001B = 0;
MMC3_DRegBuf[0] = 0;
MMC3_DRegBuf[1] = 2;
MMC3_DRegBuf[2] = 4;
MMC3_DRegBuf[3] = 5;
MMC3_DRegBuf[4] = 6;
MMC3_DRegBuf[5] = 7;
MMC3_DRegBuf[6] = 0;
MMC3_DRegBuf[7] = 1;
FixMMC3PRG(0);
FixMMC3CHR(0);
}
void pwrap(WORD A, BYTE V)
{
SetPROM_8K_Bank(A>>13, V&0x7F);
}
void cwrap(WORD A, BYTE V)
{
if (VROM_1K_SIZE) SetVROM_1K_Bank(A>>10, V);
else SetCRAM_1K_Bank(A>>10, V);
}
void mwrap(BYTE V)
{
// if (!nes->rom->Is4SCREEN()) {
if ( V == 0 ) SetVRAM_Mirror( VRAM_VMIRROR );
else if ( V == 1 ) SetVRAM_Mirror( VRAM_HMIRROR );
else if ( V == 2 ) SetVRAM_Mirror( VRAM_MIRROR4L );
else SetVRAM_Mirror( VRAM_MIRROR4H );
// }
}
void FixMMC3PRG(BYTE V)
{
if (V & 0x40) {
pwrap(0xC000, MMC3_DRegBuf[6]);
pwrap(0x8000, ~1);
} else {
pwrap(0x8000, MMC3_DRegBuf[6]);
pwrap(0xC000, ~1);
}
pwrap(0xA000, MMC3_DRegBuf[7]);
pwrap(0xE000, ~0);
}
void FixMMC3CHR(BYTE V)
{
int cbase = (V & 0x80) << 5;
cwrap((cbase ^ 0x000), MMC3_DRegBuf[0] & (~1));
cwrap((cbase ^ 0x400), MMC3_DRegBuf[0] | 1);
cwrap((cbase ^ 0x800), MMC3_DRegBuf[1] & (~1));
cwrap((cbase ^ 0xC00), MMC3_DRegBuf[1] | 1);
cwrap(cbase ^ 0x1000, MMC3_DRegBuf[2]);
cwrap(cbase ^ 0x1400, MMC3_DRegBuf[3]);
cwrap(cbase ^ 0x1800, MMC3_DRegBuf[4]);
cwrap(cbase ^ 0x1c00, MMC3_DRegBuf[5]);
mwrap(MMC3_A000B);
}
void MMC3_CMDWrite(WORD A, BYTE V)
{
switch (A & 0xE001) {
case 0x8000:
if ((V & 0x40) != (MMC3_cmd & 0x40))
FixMMC3PRG(V);
if ((V & 0x80) != (MMC3_cmd & 0x80))
FixMMC3CHR(V);
MMC3_cmd = V;
break;
case 0x8001:
{
int cbase = (MMC3_cmd & 0x80) << 5;
MMC3_DRegBuf[MMC3_cmd & 0x7] = V;
switch (MMC3_cmd & 0x07) {
case 0:
cwrap((cbase ^ 0x000), V & (~1));
cwrap((cbase ^ 0x400), V | 1);
break;
case 1:
cwrap((cbase ^ 0x800), V & (~1));
cwrap((cbase ^ 0xC00), V | 1);
break;
case 2:
cwrap(cbase ^ 0x1000, V);
break;
case 3:
cwrap(cbase ^ 0x1400, V);
break;
case 4:
cwrap(cbase ^ 0x1800, V);
break;
case 5:
cwrap(cbase ^ 0x1C00, V);
break;
case 6:
if (MMC3_cmd&0x40) pwrap(0xC000, V);
else pwrap(0x8000, V);
break;
case 7:
pwrap(0xA000, V);
break;
}
break;
}
case 0xA000:
MMC3_A000B = V;
mwrap(MMC3_A000B);
break;
case 0xA001:
MMC3_A001B = V;
break;
}
}
void MMC3_IRQWrite(WORD A, BYTE V)
{
switch (A & 0xE001) {
case 0xC000: MMC3_IRQReload = 0;MMC3_IRQCount = V; break;
case 0xC001: MMC3_IRQReload = 0;MMC3_IRQLatch = V; break;
case 0xE000: MMC3_IRQReload = 0;MMC3_IRQa = 0; break;//nes->cpu->ClrIRQ(IRQ_MAPPER);
case 0xE001: MMC3_IRQReload = 0;MMC3_IRQa = 1; break;
}
}
void MMC3_HSync(INT scanline)
{
if ((scanline >= 0 && scanline <= 239)) {
// if (nes->ppu->IsDispON())
// {
if (MMC3_IRQa && !MMC3_IRQReload) {
if (scanline == 0) {
if (MMC3_IRQCount) {
MMC3_IRQCount -= 1;
}
}
if (!(MMC3_IRQCount)){
MMC3_IRQReload = 0xFF;
MMC3_IRQCount = MMC3_IRQLatch;
// nes->cpu->SetIRQ(IRQ_MAPPER);
}
MMC3_IRQCount--;
}
// }
}
}
// ----------------------------------------------------------------------