⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 h_mmc5.c

📁 一款游戏机的模拟器
💻 C
字号:
#include	"h_MMC5.h"
#include	"Sound\s_MMC5.h"

TMMC5	MMC5;

void	MMC5_Init (void)
{
	u8 x;

	MP->SetReadHandler(0x5,MMC5_Read);
	MP->SetWriteHandler(0x5,MMC5_Write);
	MMC5.PRG_Write_6789ABCDEF = MP->GetWriteHandler(0x8);
	for (x = 6; x <= 0xF; x++)
		MP->SetWriteHandler(x,MMC5_WritePRG);
	
	MP->Mirror_4();
	MMC5.NameTable0		= MP->GetCHR_Ptr1(0x8);
	MMC5.NameTable1		= MP->GetCHR_Ptr1(0x9);
	MMC5.ExRAM		= MP->GetCHR_Ptr1(0xA);
	MMC5.ExNameTable	= MP->GetCHR_Ptr1(0xB);

	MMC5.PRGsize = 3;
	MMC5.CHRsize = 0;
	
	MMC5.IRQenabled = MMC5.IRQreads = MMC5.IRQline = 0;
	MMC5.Mul1 = MMC5.Mul2 = MMC5.GfxMode = 0;
	
	MMC5.SplitMode = MMC5.SplitBank = MMC5.SplitScroll = 0;

	for (x = 0; x < 8; x++)	MMC5.CHR_A[x] = x;
	for (x = 0; x < 4; x++)	MMC5.CHR_B[x] = x;
	for (x = 0; x < 2; x++)	MMC5.WRAMprot[x] = 0;
	for (x = 0; x < 4; x++)
	{
		u8 y = x | 4;
		MMC5.WRAMtable[MMC5WRAM_0KB_0KB][x] = 
		MMC5.WRAMtable[MMC5WRAM_0KB_8KB][x] =
		MMC5.WRAMtable[MMC5WRAM_0KB_32KB][x] = -1;

		MMC5.WRAMtable[MMC5WRAM_0KB_0KB][y] =
		MMC5.WRAMtable[MMC5WRAM_8KB_0KB][y] =
		MMC5.WRAMtable[MMC5WRAM_32KB_0KB][y] = -1;

		MMC5.WRAMtable[MMC5WRAM_8KB_0KB][x] =
		MMC5.WRAMtable[MMC5WRAM_8KB_8KB][x] =
		MMC5.WRAMtable[MMC5WRAM_8KB_32KB][x] = 0;

		MMC5.WRAMtable[MMC5WRAM_0KB_8KB][y] =
		MMC5.WRAMtable[MMC5WRAM_8KB_8KB][y] =
		MMC5.WRAMtable[MMC5WRAM_32KB_8KB][y] = 1;

		MMC5.WRAMtable[MMC5WRAM_32KB_0KB][x] =
		MMC5.WRAMtable[MMC5WRAM_32KB_8KB][x] =
		MMC5.WRAMtable[MMC5WRAM_32KB_32KB][x] = x;
	
		MMC5.WRAMtable[MMC5WRAM_0KB_32KB][y] =
		MMC5.WRAMtable[MMC5WRAM_8KB_32KB][y] =
		MMC5.WRAMtable[MMC5WRAM_32KB_32KB][y] = y;
	}

	for (x = 0; x < 5; x++)	MMC5.PRG[x] = 0xFF;

	MMC5.UpdateCache = 0;
	MMC5.DrawStatus = 2;
	MMC5.TileCache = 0x40;
	MMC5sound_Init();
	MMC5_SyncPRG();
}

void	MMC5_Destroy (void)
{
	MMC5sound_Destroy();
}

int	MMC5_SaveMI (Ar128 MI, int x)
{
	u8 i;
			MI[x++] = MMC5.PRGsize;
			MI[x++] = MMC5.CHRsize;
			MI[x++] = MMC5.IRQenabled;
			MI[x++] = MMC5.IRQreads;
			MI[x++] = MMC5.IRQline;
			MI[x++] = MMC5.Mul1;
			MI[x++] = MMC5.Mul2;
			MI[x++] = MMC5.GfxMode;
for (i = 0; i < 8; i++)	MI[x++] = MMC5.CHR_A[i];
for (i = 0; i < 4; i++)	MI[x++] = MMC5.CHR_B[i];
for (i = 0; i < 5; i++)	MI[x++] = MMC5.PRG[i];
for (i = 0; i < 2; i++)	MI[x++] = MMC5.WRAMprot[i];
			MI[x++] = MMC5.SplitMode;
			MI[x++] = MMC5.SplitBank;
			MI[x++] = MMC5.SplitScroll;
	x = MMC5sound_SaveMI(MI,x);
	return x;
}

int	MMC5_LoadMI (const Ar128 MI, int x)
{
	u8 i;
			MMC5.PRGsize		= MI[x++];
			MMC5.CHRsize		= MI[x++];
			MMC5.IRQenabled		= MI[x++];
			MMC5.IRQreads		= MI[x++];
			MMC5.IRQline		= MI[x++];
			MMC5.Mul1		= MI[x++];
			MMC5.Mul2		= MI[x++];
			MMC5.GfxMode		= MI[x++];
for (i = 0; i < 8; i++)	MMC5.CHR_A[i]		= MI[x++];
for (i = 0; i < 4; i++)	MMC5.CHR_B[i]		= MI[x++];
for (i = 0; i < 5; i++)	MMC5.PRG[i]		= MI[x++];
for (i = 0; i < 2; i++)	MMC5.WRAMprot[i]	= MI[x++];
			MMC5.SplitMode		= MI[x++];
			MMC5.SplitBank		= MI[x++];
			MMC5.SplitScroll	= MI[x++];
	x = MMC5sound_LoadMI(MI,x);
	MMC5_SyncPRG();
	return x;
}

void	MMC5_SetPRG (int Size, int Loc, int Bank)
{
	u8 x;
	if (Bank & 0x80)
	{
		if (Size == 8)		MP->SetPRG_ROM8(Loc,Bank);
		else if (Size == 16)	MP->SetPRG_ROM16(Loc,Bank >> 1);
		else if (Size == 32)	MP->SetPRG_ROM32(Loc,Bank >> 2);
	}
	else
	{
		if (Size == 8)
		{
			if (MMC5.WRAMtable[MMC5.WRAMsize][Bank & 0x7] == -1)
				for (x = Loc; x < Loc + 2; x++)
					MP->SetPRG_OB4(x);
			else	MP->SetPRG_RAM8(Loc,MMC5.WRAMtable[MMC5.WRAMsize][Bank & 0x7]);
		}
		else if (Size == 16)
		{
			if (MMC5.WRAMtable[MMC5.WRAMsize][Bank & 0x6] == -1)
				for (x = Loc; x < Loc + 4; x++)
					MP->SetPRG_OB4(x);
			else
			{
				MP->SetPRG_RAM8(Loc+0,MMC5.WRAMtable[MMC5.WRAMsize][(Bank & 0x6) | 0]);
				MP->SetPRG_RAM8(Loc+2,MMC5.WRAMtable[MMC5.WRAMsize][(Bank & 0x6) | 1]);
			}
		}
	}
}

void	MMC5_SyncPRG (void)
{
		MMC5_SetPRG( 8,0x6,MMC5.PRG[0] & 0x7F);
	switch (MMC5.PRGsize)
	{
	case 0:	MMC5_SetPRG(32,0x8,MMC5.PRG[4] | 0x80);	break;
	case 1:	MMC5_SetPRG(16,0x8,MMC5.PRG[2]       );
		MMC5_SetPRG(16,0xC,MMC5.PRG[4] | 0x80);	break;
	case 2:	MMC5_SetPRG(16,0x8,MMC5.PRG[2]       );
		MMC5_SetPRG( 8,0xC,MMC5.PRG[3]       );
		MMC5_SetPRG( 8,0xE,MMC5.PRG[4] | 0x80);	break;
	case 3:	MMC5_SetPRG( 8,0x8,MMC5.PRG[1]       );
		MMC5_SetPRG( 8,0xA,MMC5.PRG[2]       );
		MMC5_SetPRG( 8,0xC,MMC5.PRG[3]	     );
		MMC5_SetPRG( 8,0xE,MMC5.PRG[4] | 0x80);	break;
	}
}

void	MMC5_SyncCHRA (int Bank)
{
	switch (MMC5.CHRsize)
	{
	case 0:	MP->SetCHR_ROM8(0       ,MMC5.CHR_A[7       ]);	break;
	case 1:	MP->SetCHR_ROM4(0 | Bank,MMC5.CHR_A[3 | Bank]);	break;
	case 2:	MP->SetCHR_ROM2(0 | Bank,MMC5.CHR_A[1 | Bank]);
		MP->SetCHR_ROM2(2 | Bank,MMC5.CHR_A[3 | Bank]);	break;
	case 3:	MP->SetCHR_ROM1(0 | Bank,MMC5.CHR_A[0 | Bank]);
		MP->SetCHR_ROM1(1 | Bank,MMC5.CHR_A[1 | Bank]);
		MP->SetCHR_ROM1(2 | Bank,MMC5.CHR_A[2 | Bank]);
		MP->SetCHR_ROM1(3 | Bank,MMC5.CHR_A[3 | Bank]);	break;
	}
}

void	MMC5_SyncCHRB (int Bank)
{
	switch (MMC5.CHRsize)
	{
	case 0:	MP->SetCHR_ROM8(0       ,MMC5.CHR_B[3]);break;
	case 1:	MP->SetCHR_ROM4(0 | Bank,MMC5.CHR_B[3]);break;
	case 2:	MP->SetCHR_ROM2(0 | Bank,MMC5.CHR_B[1]);
		MP->SetCHR_ROM2(2 | Bank,MMC5.CHR_B[3]);break;
	case 3:	MP->SetCHR_ROM1(0 | Bank,MMC5.CHR_B[0]);
		MP->SetCHR_ROM1(1 | Bank,MMC5.CHR_B[1]);
		MP->SetCHR_ROM1(2 | Bank,MMC5.CHR_B[2]);
		MP->SetCHR_ROM1(3 | Bank,MMC5.CHR_B[3]);break;
	}
}

void	MMC5_SyncMirror (void)
{
	MP->Mirror_Custom(
		(MMC5.Mirror >> 0) & 3,
		(MMC5.Mirror >> 2) & 3,
		(MMC5.Mirror >> 4) & 3,
		(MMC5.Mirror >> 6) & 3);	
}

int	__cdecl	MMC5_Read (int Bank, int Where)
{
	u8 read = 0xFF;
	switch (Where & 0xF00)
	{
	case 0x200:
		switch (Where)
		{
		case 0x204:	read = MMC5.IRQreads;
				MMC5.IRQreads &= 0x40;
				if (!MMC5.IRQenabled)
					MMC5.IRQreads = 0;			break;
		case 0x205:	read = ((MMC5.Mul1 * MMC5.Mul2) & 0x00FF) >> 0;	break;
		case 0x206:	read = ((MMC5.Mul1 * MMC5.Mul2) & 0xFF00) >> 8;	break;
		}							break;
	case 0xC00:
	case 0xD00:
	case 0xE00:
	case 0xF00:	if (MMC5.GfxMode != 1)
				read = MMC5.ExRAM[Where & 0x3FF];	break;
	}
	return read;
}

void	__cdecl	MMC5_Write (int Bank, int Where, int What)
{
	switch (Where & 0xF00)
	{
	case 0x000:	MMC5sound_Write((Bank << 12) | Where,What);	break;
	case 0x100:
		switch (Where)
		{
		case 0x100:	MMC5.PRGsize = What & 3;
				MMC5_SyncPRG();		break;
		case 0x101:	MMC5.CHRsize = What & 3;
				/*MMC5_SyncCHRA(0);	MMC5_SyncCHRA(4);*/
							break;
		case 0x102:	MMC5.WRAMprot[0] = What & 3;
							break;
		case 0x103:	MMC5.WRAMprot[1] = What & 3;
							break;
		case 0x104:	MMC5.GfxMode = What & 3;
				MMC5.UpdateCache = 1;	break;
		case 0x105:	MMC5.Mirror = What;
				MMC5_SyncMirror();	break;
		case 0x106:	memset(MMC5.ExNameTable,What,0x3C0);
							break;
		case 0x107:	memset(MMC5.ExNameTable+0x3C0,((What & 3) |
				((What & 3) << 2) | ((What & 3) << 4) |
				((What & 3) << 6)),0x3C);
							break;
		case 0x113:
		case 0x114:
		case 0x115:
		case 0x116:
		case 0x117:	MMC5.PRG[Where - 0x113] = What;
				MMC5_SyncPRG();		break;
		case 0x120:
		case 0x121:
		case 0x122:
		case 0x123:
		case 0x124:
		case 0x125:
		case 0x126:
		case 0x127:	MMC5.CHR_A[Where & 0x7] = What;	
				MMC5_SyncCHRA(0);
				MMC5_SyncCHRA(4);	break;
		case 0x128:
		case 0x129:
		case 0x12A:
		case 0x12B:	MMC5.CHR_B[Where & 0x3] = What;
				MMC5_SyncCHRB(0);
				MMC5_SyncCHRB(4);	break;
		case 0x130:	/* nobody knows... */	break;
		}		break;
	case 0x200:
		switch (Where)
		{
		case 0x200:	MMC5.SplitMode = What;	break;
		case 0x201:	MMC5.SplitScroll = What;break;
		case 0x202:	MMC5.SplitBank = What;	break;
		case 0x203:	MMC5.IRQline = What;	break;
		case 0x204:	MMC5.IRQenabled = What;	break;
		case 0x205:	MMC5.Mul1 = What;	break;
		case 0x206:	MMC5.Mul2 = What;	break;
		}		break;
	case 0xC00:
	case 0xD00:
	case 0xE00:
	case 0xF00:	if (MMC5.GfxMode != 3)
				MMC5.ExRAM[Where & 0x3FF] = What;
			if (MMC5.GfxMode == 1)
				MMC5.UpdateCache = 1;	break;
	}
}

void	__cdecl	MMC5_WritePRG (int Bank, int Where, int What)
{
	if ((MMC5.WRAMprot[0] == 2) && (MMC5.WRAMprot[1] == 1))
		MMC5.PRG_Write_6789ABCDEF(Bank,Where,What);
}

static	u8	VScroll;

int	__cdecl	MMC5_TileHandler (int Bank, int TileNum, int Index)
{
	unsigned char Palette;

	if (Index == -1)
	{
		if ((MMC5.DrawStatus == 1) && (MMC5.DrawBank == Bank))
			return 0;
		MMC5.DrawStatus = 1;
		MMC5.DrawBank = Bank;
		MMC5_SyncCHRA(Bank);
		return 1;
	}
	else
	{
		MMC5.CurTile++;
		if ((MMC5.GfxMode < 2) && (MMC5.SplitMode & 0x80) && (MMC5.CurTile < 0x20))
		{
			if (((~MMC5.SplitMode & 0x40) && (MMC5.CurTile == 0)) || ((MMC5.SplitMode & 0x40) && (MMC5.CurTile == (MMC5.SplitMode & 0x1F))))
			{
				MP->Mirror_Custom(2,2,2,2);
				MP->SetCHR_ROM4(Bank,MMC5.SplitBank & 0x3F);
				return 1;
			}
			else if ((~MMC5.SplitMode & 0x40) && (MMC5.CurTile == 1 + (MMC5.SplitMode & 0x1F)))
			{
				MMC5_SyncMirror();
				MMC5_SyncCHRB(Bank);
			}
		}
		if (MMC5.CurTile == 0x20)
		{
			MMC5_SyncMirror();
			MMC5_SyncCHRB(Bank);
		}
		if (MMC5.GfxMode == 1)
		{
			int ExRAM = MMC5.ExRAM[Index];
			if (MMC5.TileCache != (ExRAM & 0x3F))
				MP->SetCHR_ROM4(Bank,MMC5.TileCache = ExRAM & 0x3F);
			Palette = ((ExRAM & 0xC0) >> 6) * 0x55;
			MMC5.NameTable0[0x3C0 | ((Index & 0x1C) >> 2) | ((Index & 0x380) >> 4)] = Palette;
			MMC5.NameTable1[0x3C0 | ((Index & 0x1C) >> 2) | ((Index & 0x380) >> 4)] = Palette;
			return 1;
		}
		else
		{
			if ((MMC5.DrawStatus == 0) && (MMC5.DrawBank == Bank))
				return 0;
			MMC5.DrawStatus = 0;
			MMC5.DrawBank = Bank;
			MMC5_SyncCHRB(Bank);
			return 1;
		}
	}
	return 0;
}

void	__cdecl	MMC5_HBlank (int Scanline, int Byte2001)
{
	MMC5.TileCache = 0x40;
	MMC5.DrawStatus = 2;
	MMC5.CurTile = -1;
	if (Scanline == -1)
	{
		if ((MMC5.UpdateCache) && (MMC5.GfxMode == 1))
		{
			MP->MMC5_UpdateAttributeCache();
			MMC5.UpdateCache = 0;
		}
	}
	if (Scanline == -1)
		VScroll = MMC5.SplitScroll;
	else if (Scanline < 240)
		VScroll++;
	if (VScroll >= 240)
		VScroll -= 240;
	if (Scanline <= 240)
	{
		if ((Scanline == MMC5.IRQline) && (Byte2001 & 0x18))
			MMC5.IRQreads |= 0x80;
		if ((MMC5.IRQreads & 0x80) && (MMC5.IRQenabled & 0x80))
			MP->IRQ();
	}
	else	MMC5.IRQreads |= 0x40;
	if (Scanline == 241)
	{
		MMC5_SyncCHRA(0);
		MMC5_SyncCHRA(4);
	}
}

void	__cdecl	MMC5_MapperSnd (s16 *Buffer, int Len)
{
	MMC5sound_Get(Buffer,Len);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -