#include <memory.h>
#include "SH2.h"
#include "Cpu_SH2.h"
#include "Mem_SH2.h"
#include "Mem_M68K.h"
#include "vdp_32X.h"


int MSH2_Speed;
int SSH2_Speed;


/*** MSH2_Init - Initialise the Master SH2 CPU ***/

int MSH2_Init()
{
	SH2_Init(&M_SH2, 0);

	SH2_Set_Fetch_Reg(&M_SH2, 0, 0x06000000, 0x0603FFFF, (UINT16 *) &_32X_Ram[0]);
	SH2_Set_Fetch_Reg(&M_SH2, 1, 0x26000000, 0x2603FFFF, (UINT16 *) &_32X_Ram[0]);
	SH2_Set_Fetch_Reg(&M_SH2, 2, 0x02000000, 0x023FFFFF, (UINT16 *) &_32X_Rom[0]);
	SH2_Set_Fetch_Reg(&M_SH2, 3, 0x22000000, 0x223FFFFF, (UINT16 *) &_32X_Rom[0]);
	SH2_Set_Fetch_Reg(&M_SH2, 4, 0x00000000, 0x000003FF, (UINT16 *) &_32X_MSH2_Rom[0]);
	SH2_Set_Fetch_Reg(&M_SH2, 5, 0x20000000, 0x200003FF, (UINT16 *) &_32X_MSH2_Rom[0]);
	SH2_Set_Fetch_Reg(&M_SH2, 6, 0xC0000000, 0xC0000FFF, (UINT16 *) &(M_SH2.Cache[0]));
	SH2_Set_Fetch_Reg(&M_SH2, 7, 0x00000000, 0x00000000, (UINT16 *) -1);

	SH2_Add_ReadB(&M_SH2, 0x00, 0x00, MSH2_Read_Byte_00);
	SH2_Add_ReadW(&M_SH2, 0x00, 0x00, MSH2_Read_Word_00);
	SH2_Add_ReadL(&M_SH2, 0x00, 0x00, MSH2_Read_Long_00);

	SH2_Add_ReadB(&M_SH2, 0x02, 0x02, SH2_Read_Byte_Rom);
	SH2_Add_ReadW(&M_SH2, 0x02, 0x02, SH2_Read_Word_Rom);
	SH2_Add_ReadL(&M_SH2, 0x02, 0x02, SH2_Read_Long_Rom);

	SH2_Add_ReadB(&M_SH2, 0x04, 0x04, SH2_Read_Byte_FB1);
	SH2_Add_ReadW(&M_SH2, 0x04, 0x04, SH2_Read_Word_FB1);
	SH2_Add_ReadL(&M_SH2, 0x04, 0x04, SH2_Read_Long_FB1);
/*
	SH2_Add_ReadB(&M_SH2, 0x05, 0x05, SH2_Read_Byte_FB1);
	SH2_Add_ReadW(&M_SH2, 0x05, 0x05, SH2_Read_Word_FB1);
	SH2_Add_ReadL(&M_SH2, 0x05, 0x05, SH2_Read_Long_FB1);
*/
	SH2_Add_ReadB(&M_SH2, 0x06, 0x06, SH2_Read_Byte_Ram);
	SH2_Add_ReadW(&M_SH2, 0x06, 0x06, SH2_Read_Word_Ram);
	SH2_Add_ReadL(&M_SH2, 0x06, 0x06, SH2_Read_Long_Ram);

	SH2_Add_WriteB(&M_SH2, 0x00, 0x00, MSH2_Write_Byte_00);
	SH2_Add_WriteW(&M_SH2, 0x00, 0x00, MSH2_Write_Word_00);
	SH2_Add_WriteL(&M_SH2, 0x00, 0x00, MSH2_Write_Long_00);

	SH2_Add_WriteB(&M_SH2, 0x04, 0x04, SH2_Write_Byte_FB1);
	SH2_Add_WriteW(&M_SH2, 0x04, 0x04, SH2_Write_Word_FB1);
	SH2_Add_WriteL(&M_SH2, 0x04, 0x04, SH2_Write_Long_FB1);
/*
	SH2_Add_WriteB(&M_SH2, 0x05, 0x05, SH2_Write_Byte_FB1);
	SH2_Add_WriteW(&M_SH2, 0x05, 0x05, SH2_Write_Word_FB1);
	SH2_Add_WriteL(&M_SH2, 0x05, 0x05, SH2_Write_Long_FB1);
*/
	SH2_Add_WriteB(&M_SH2, 0x06, 0x06, SH2_Write_Byte_Ram);
	SH2_Add_WriteW(&M_SH2, 0x06, 0x06, SH2_Write_Word_Ram);
	SH2_Add_WriteL(&M_SH2, 0x06, 0x06, SH2_Write_Long_Ram);

	SH2_Map_Cache_Trough(&M_SH2);

	SH2_Reset(&M_SH2, 0);

	return 0;
}


/*** SSH2_Init - Initialise the Slave SH2 CPU ***/

int SSH2_Init()
{
	SH2_Init(&S_SH2, 1);

	SH2_Set_Fetch_Reg(&S_SH2, 0, 0x06000000, 0x0603FFFF, (UINT16 *) &_32X_Ram[0]);
	SH2_Set_Fetch_Reg(&S_SH2, 1, 0x26000000, 0x2603FFFF, (UINT16 *) &_32X_Ram[0]);
	SH2_Set_Fetch_Reg(&S_SH2, 2, 0x02000000, 0x023FFFFF, (UINT16 *) &_32X_Rom[0]);
	SH2_Set_Fetch_Reg(&S_SH2, 3, 0x22000000, 0x223FFFFF, (UINT16 *) &_32X_Rom[0]);
	SH2_Set_Fetch_Reg(&S_SH2, 4, 0x00000000, 0x000003FF, (UINT16 *) &_32X_SSH2_Rom[0]);
	SH2_Set_Fetch_Reg(&S_SH2, 5, 0x20000000, 0x200003FF, (UINT16 *) &_32X_SSH2_Rom[0]);
	SH2_Set_Fetch_Reg(&S_SH2, 6, 0xC0000000, 0xC0000FFF, (UINT16 *) &(S_SH2.Cache[0]));
	SH2_Set_Fetch_Reg(&S_SH2, 7, 0x00000000, 0x00000000, (UINT16 *) -1);

/*
	SH2_Add_Fetch(&S_SH2, 0x06000000, 0x0603FFFF, (UINT16 *) &_32X_Ram[0]);
	SH2_Add_Fetch(&S_SH2, 0x26000000, 0x2603FFFF, (UINT16 *) &_32X_Ram[0]);
	SH2_Add_Fetch(&S_SH2, 0x02000000, 0x003FFFFF, (UINT16 *) &_32X_Rom[0]);
	SH2_Add_Fetch(&S_SH2, 0x22000000, 0x203FFFFF, (UINT16 *) &_32X_Rom[0]);
	SH2_Add_Fetch(&S_SH2, 0x00000000, 0x000003FF, (UINT16 *) &_32X_SSH2_Rom[0]);
	SH2_Add_Fetch(&S_SH2, 0x20000000, 0x200003FF, (UINT16 *) &_32X_SSH2_Rom[0]);
	SH2_Add_Fetch(&S_SH2, 0x00000000, 0x00000000, (UINT16 *) -1);
*/
	SH2_Add_ReadB(&S_SH2, 0x00, 0x00, SSH2_Read_Byte_00);
	SH2_Add_ReadW(&S_SH2, 0x00, 0x00, SSH2_Read_Word_00);
	SH2_Add_ReadL(&S_SH2, 0x00, 0x00, SSH2_Read_Long_00);

	SH2_Add_ReadB(&S_SH2, 0x02, 0x02, SH2_Read_Byte_Rom);
	SH2_Add_ReadW(&S_SH2, 0x02, 0x02, SH2_Read_Word_Rom);
	SH2_Add_ReadL(&S_SH2, 0x02, 0x02, SH2_Read_Long_Rom);

	SH2_Add_ReadB(&S_SH2, 0x04, 0x04, SH2_Read_Byte_FB1);
	SH2_Add_ReadW(&S_SH2, 0x04, 0x04, SH2_Read_Word_FB1);
	SH2_Add_ReadL(&S_SH2, 0x04, 0x04, SH2_Read_Long_FB1);
/*
	SH2_Add_ReadB(&S_SH2, 0x05, 0x05, SH2_Read_Byte_FB1);
	SH2_Add_ReadW(&S_SH2, 0x05, 0x05, SH2_Read_Word_FB1);
	SH2_Add_ReadL(&S_SH2, 0x05, 0x05, SH2_Read_Long_FB1);
*/
	SH2_Add_ReadB(&S_SH2, 0x06, 0x06, SH2_Read_Byte_Ram);
	SH2_Add_ReadW(&S_SH2, 0x06, 0x06, SH2_Read_Word_Ram);
	SH2_Add_ReadL(&S_SH2, 0x06, 0x06, SH2_Read_Long_Ram);

	SH2_Add_WriteB(&S_SH2, 0x00, 0x00, SSH2_Write_Byte_00);
	SH2_Add_WriteW(&S_SH2, 0x00, 0x00, SSH2_Write_Word_00);
	SH2_Add_WriteL(&S_SH2, 0x00, 0x00, SSH2_Write_Long_00);

	SH2_Add_WriteB(&S_SH2, 0x04, 0x04, SH2_Write_Byte_FB1);
	SH2_Add_WriteW(&S_SH2, 0x04, 0x04, SH2_Write_Word_FB1);
	SH2_Add_WriteL(&S_SH2, 0x04, 0x04, SH2_Write_Long_FB1);
/*
	SH2_Add_WriteB(&S_SH2, 0x05, 0x05, SH2_Write_Byte_FB1);
	SH2_Add_WriteW(&S_SH2, 0x05, 0x05, SH2_Write_Word_FB1);
	SH2_Add_WriteL(&S_SH2, 0x05, 0x05, SH2_Write_Long_FB1);
*/
	SH2_Add_WriteB(&S_SH2, 0x06, 0x06, SH2_Write_Byte_Ram);
	SH2_Add_WriteW(&S_SH2, 0x06, 0x06, SH2_Write_Word_Ram);
	SH2_Add_WriteL(&S_SH2, 0x06, 0x06, SH2_Write_Long_Ram);

	SH2_Map_Cache_Trough(&S_SH2);

	SH2_Reset(&S_SH2, 0);

	return 0;
}


/*** MSH2_Reset - Reset the Master SH2 (and stuff around) ***/

void MSH2_Reset()
{
	SH2_Reset(&M_SH2, 0);

	memset(_32X_Comm, 0, 0x10);
	memset(_32X_FIFO_A, 0, 4 * 2);
	memset(_32X_FIFO_B, 0, 4 * 2);
	_32X_ADEN = 0;
	_32X_FM = 0;
	_32X_RV = 0;
	_32X_DREQ_ST = 0;
	_32X_DREQ_SRC = 0;
	_32X_DREQ_DST = 0;
	_32X_DREQ_LEN = 0;
	_32X_FIFO_Block = 0;
	_32X_FIFO_Read = 0;
	_32X_FIFO_Write = 0;
	_32X_MINT = 0;
	_32X_HIC = 0;
}


/*** SSH2_Reset - Reset the Slave SH2 (and stuff around) ***/

void SSH2_Reset()
{
	SH2_Reset(&S_SH2, 0);

	_32X_SINT = 0;
}


/*** MSH2_Reset_CPU - Reset the Master SH2 CPU only ***/

void MSH2_Reset_CPU()
{
	SH2_Reset(&M_SH2, 1);
}


/*** SSH2_Reset - Reset the Slave SH2 CPU only ***/

void SSH2_Reset_CPU()
{
	SH2_Reset(&S_SH2, 1);
}


/*** _32X_Set_FB - Update Frame Buffer memory map ***/

void _32X_Set_FB()
{
	if (_32X_VDP.State & 0x1)		// Frame Buffer 1 displayed
	{
		if (_32X_FM)
		{
			SH2_Add_ReadB(&M_SH2, 0x04, 0x04, SH2_Read_Byte_FB0);
			SH2_Add_ReadW(&M_SH2, 0x04, 0x04, SH2_Read_Word_FB0);
			SH2_Add_ReadL(&M_SH2, 0x04, 0x04, SH2_Read_Long_FB0);
			SH2_Add_ReadB(&M_SH2, 0x24, 0x24, SH2_Read_Byte_FB0);
			SH2_Add_ReadW(&M_SH2, 0x24, 0x24, SH2_Read_Word_FB0);
			SH2_Add_ReadL(&M_SH2, 0x24, 0x24, SH2_Read_Long_FB0);

			SH2_Add_WriteB(&M_SH2, 0x04, 0x04, SH2_Write_Byte_FB0);
			SH2_Add_WriteW(&M_SH2, 0x04, 0x04, SH2_Write_Word_FB0);
			SH2_Add_WriteL(&M_SH2, 0x04, 0x04, SH2_Write_Long_FB0);
			SH2_Add_WriteB(&M_SH2, 0x24, 0x24, SH2_Write_Byte_FB0);
			SH2_Add_WriteW(&M_SH2, 0x24, 0x24, SH2_Write_Word_FB0);
			SH2_Add_WriteL(&M_SH2, 0x24, 0x24, SH2_Write_Long_FB0);

			SH2_Add_ReadB(&S_SH2, 0x04, 0x04, SH2_Read_Byte_FB0);
			SH2_Add_ReadW(&S_SH2, 0x04, 0x04, SH2_Read_Word_FB0);
			SH2_Add_ReadL(&S_SH2, 0x04, 0x04, SH2_Read_Long_FB0);
			SH2_Add_ReadB(&S_SH2, 0x24, 0x24, SH2_Read_Byte_FB0);
			SH2_Add_ReadW(&S_SH2, 0x24, 0x24, SH2_Read_Word_FB0);
			SH2_Add_ReadL(&S_SH2, 0x24, 0x24, SH2_Read_Long_FB0);

			SH2_Add_WriteB(&S_SH2, 0x04, 0x04, SH2_Write_Byte_FB0);
			SH2_Add_WriteW(&S_SH2, 0x04, 0x04, SH2_Write_Word_FB0);
			SH2_Add_WriteL(&S_SH2, 0x04, 0x04, SH2_Write_Long_FB0);
			SH2_Add_WriteB(&S_SH2, 0x24, 0x24, SH2_Write_Byte_FB0);
			SH2_Add_WriteW(&S_SH2, 0x24, 0x24, SH2_Write_Word_FB0);
			SH2_Add_WriteL(&S_SH2, 0x24, 0x24, SH2_Write_Long_FB0);

			M68K_Read_Byte_Table[8 * 2] = _32X_M68K_Read_Byte_Table[(6 * 2)];
			M68K_Read_Word_Table[8 * 2] = _32X_M68K_Read_Word_Table[(6 * 2)];
			M68K_Write_Byte_Table[8] = _32X_M68K_Write_Byte_Table[6];
			M68K_Write_Word_Table[8] = _32X_M68K_Write_Word_Table[6];
		}
		else
		{
			SH2_Add_ReadB(&M_SH2, 0x04, 0x04, Def_READB);
			SH2_Add_ReadW(&M_SH2, 0x04, 0x04, Def_READW);
			SH2_Add_ReadL(&M_SH2, 0x04, 0x04, Def_READL);
			SH2_Add_ReadB(&M_SH2, 0x24, 0x24, Def_READB);
			SH2_Add_ReadW(&M_SH2, 0x24, 0x24, Def_READW);
			SH2_Add_ReadL(&M_SH2, 0x24, 0x24, Def_READL);

			SH2_Add_WriteB(&M_SH2, 0x04, 0x04, Def_WRITEB);
			SH2_Add_WriteW(&M_SH2, 0x04, 0x04, Def_WRITEW);
			SH2_Add_WriteL(&M_SH2, 0x04, 0x04, Def_WRITEL);
			SH2_Add_WriteB(&M_SH2, 0x24, 0x24, Def_WRITEB);
			SH2_Add_WriteW(&M_SH2, 0x24, 0x24, Def_WRITEW);
			SH2_Add_WriteL(&M_SH2, 0x24, 0x24, Def_WRITEL);

			SH2_Add_ReadB(&S_SH2, 0x04, 0x04, Def_READB);
			SH2_Add_ReadW(&S_SH2, 0x04, 0x04, Def_READW);
			SH2_Add_ReadL(&S_SH2, 0x04, 0x04, Def_READL);
			SH2_Add_ReadB(&S_SH2, 0x24, 0x24, Def_READB);
			SH2_Add_ReadW(&S_SH2, 0x24, 0x24, Def_READW);
			SH2_Add_ReadL(&S_SH2, 0x24, 0x24, Def_READL);

			SH2_Add_WriteB(&S_SH2, 0x04, 0x04, Def_WRITEB);
			SH2_Add_WriteW(&S_SH2, 0x04, 0x04, Def_WRITEW);
			SH2_Add_WriteL(&S_SH2, 0x04, 0x04, Def_WRITEL);
			SH2_Add_WriteB(&S_SH2, 0x24, 0x24, Def_WRITEB);
			SH2_Add_WriteW(&S_SH2, 0x24, 0x24, Def_WRITEW);
			SH2_Add_WriteL(&S_SH2, 0x24, 0x24, Def_WRITEL);

			M68K_Read_Byte_Table[8 * 2] = _32X_M68K_Read_Byte_Table[(8 * 2) - 1];
			M68K_Read_Word_Table[8 * 2] = _32X_M68K_Read_Word_Table[(8 * 2) - 1];
			M68K_Write_Byte_Table[8] = _32X_M68K_Write_Byte_Table[8 - 1];
			M68K_Write_Word_Table[8] = _32X_M68K_Write_Word_Table[8 - 1];
		}
	}
	else
	{
		if (_32X_FM)
		{
			SH2_Add_ReadB(&M_SH2, 0x04, 0x04, SH2_Read_Byte_FB1);
			SH2_Add_ReadW(&M_SH2, 0x04, 0x04, SH2_Read_Word_FB1);
			SH2_Add_ReadL(&M_SH2, 0x04, 0x04, SH2_Read_Long_FB1);
			SH2_Add_ReadB(&M_SH2, 0x24, 0x24, SH2_Read_Byte_FB1);
			SH2_Add_ReadW(&M_SH2, 0x24, 0x24, SH2_Read_Word_FB1);
			SH2_Add_ReadL(&M_SH2, 0x24, 0x24, SH2_Read_Long_FB1);

			SH2_Add_WriteB(&M_SH2, 0x04, 0x04, SH2_Write_Byte_FB1);
			SH2_Add_WriteW(&M_SH2, 0x04, 0x04, SH2_Write_Word_FB1);
			SH2_Add_WriteL(&M_SH2, 0x04, 0x04, SH2_Write_Long_FB1);
			SH2_Add_WriteB(&M_SH2, 0x24, 0x24, SH2_Write_Byte_FB1);
			SH2_Add_WriteW(&M_SH2, 0x24, 0x24, SH2_Write_Word_FB1);
			SH2_Add_WriteL(&M_SH2, 0x24, 0x24, SH2_Write_Long_FB1);

			SH2_Add_ReadB(&S_SH2, 0x04, 0x04, SH2_Read_Byte_FB1);
			SH2_Add_ReadW(&S_SH2, 0x04, 0x04, SH2_Read_Word_FB1);
			SH2_Add_ReadL(&S_SH2, 0x04, 0x04, SH2_Read_Long_FB1);
			SH2_Add_ReadB(&S_SH2, 0x24, 0x24, SH2_Read_Byte_FB1);
			SH2_Add_ReadW(&S_SH2, 0x24, 0x24, SH2_Read_Word_FB1);
			SH2_Add_ReadL(&S_SH2, 0x24, 0x24, SH2_Read_Long_FB1);

			SH2_Add_WriteB(&S_SH2, 0x04, 0x04, SH2_Write_Byte_FB1);
			SH2_Add_WriteW(&S_SH2, 0x04, 0x04, SH2_Write_Word_FB1);
			SH2_Add_WriteL(&S_SH2, 0x04, 0x04, SH2_Write_Long_FB1);
			SH2_Add_WriteB(&S_SH2, 0x24, 0x24, SH2_Write_Byte_FB1);
			SH2_Add_WriteW(&S_SH2, 0x24, 0x24, SH2_Write_Word_FB1);
			SH2_Add_WriteL(&S_SH2, 0x24, 0x24, SH2_Write_Long_FB1);

			M68K_Read_Byte_Table[8 * 2] = _32X_M68K_Read_Byte_Table[(6 * 2)];
			M68K_Read_Word_Table[8 * 2] = _32X_M68K_Read_Word_Table[(6 * 2)];
			M68K_Write_Byte_Table[8] = _32X_M68K_Write_Byte_Table[6];
			M68K_Write_Word_Table[8] = _32X_M68K_Write_Word_Table[6];
		}
		else
		{
			SH2_Add_ReadB(&M_SH2, 0x04, 0x04, Def_READB);
			SH2_Add_ReadW(&M_SH2, 0x04, 0x04, Def_READW);
			SH2_Add_ReadL(&M_SH2, 0x04, 0x04, Def_READL);
			SH2_Add_ReadB(&M_SH2, 0x24, 0x24, Def_READB);
			SH2_Add_ReadW(&M_SH2, 0x24, 0x24, Def_READW);
			SH2_Add_ReadL(&M_SH2, 0x24, 0x24, Def_READL);

			SH2_Add_WriteB(&M_SH2, 0x04, 0x04, Def_WRITEB);
			SH2_Add_WriteW(&M_SH2, 0x04, 0x04, Def_WRITEW);
			SH2_Add_WriteL(&M_SH2, 0x04, 0x04, Def_WRITEL);
			SH2_Add_WriteB(&M_SH2, 0x24, 0x24, Def_WRITEB);
			SH2_Add_WriteW(&M_SH2, 0x24, 0x24, Def_WRITEW);
			SH2_Add_WriteL(&M_SH2, 0x24, 0x24, Def_WRITEL);

			SH2_Add_ReadB(&S_SH2, 0x04, 0x04, Def_READB);
			SH2_Add_ReadW(&S_SH2, 0x04, 0x04, Def_READW);
			SH2_Add_ReadL(&S_SH2, 0x04, 0x04, Def_READL);
			SH2_Add_ReadB(&S_SH2, 0x24, 0x24, Def_READB);
			SH2_Add_ReadW(&S_SH2, 0x24, 0x24, Def_READW);
			SH2_Add_ReadL(&S_SH2, 0x24, 0x24, Def_READL);

			SH2_Add_WriteB(&S_SH2, 0x04, 0x04, Def_WRITEB);
			SH2_Add_WriteW(&S_SH2, 0x04, 0x04, Def_WRITEW);
			SH2_Add_WriteL(&S_SH2, 0x04, 0x04, Def_WRITEL);
			SH2_Add_WriteB(&S_SH2, 0x24, 0x24, Def_WRITEB);
			SH2_Add_WriteW(&S_SH2, 0x24, 0x24, Def_WRITEW);
			SH2_Add_WriteL(&S_SH2, 0x24, 0x24, Def_WRITEL);

			M68K_Read_Byte_Table[8 * 2] = _32X_M68K_Read_Byte_Table[8 * 2];
			M68K_Read_Word_Table[8 * 2] = _32X_M68K_Read_Word_Table[8 * 2];
			M68K_Write_Byte_Table[8] = _32X_M68K_Write_Byte_Table[8];
			M68K_Write_Word_Table[8] = _32X_M68K_Write_Word_Table[8];
		}
	}
}
