/***************************************************************************

	m68000.c

	M68000 CPU interface

***************************************************************************/

#include "ncdz.h"
#include "c68k.h"


void m68000_init(void)
{
    C68k_Init(&C68K, NULL);
    C68k_Set_ReadB(&C68K, m68k_read_memory_8);
    C68k_Set_ReadW(&C68K, m68k_read_memory_16);
    C68k_Set_WriteB(&C68K, m68k_write_memory_8);
    C68k_Set_WriteW(&C68K, m68k_write_memory_16);
    C68k_Set_Fetch(&C68K, 0x000000, 0x1fffff, (u32)neogeo_prg_memory);
    C68k_Set_Fetch(&C68K, 0xc00000, 0xc7ffff, (u32)neogeo_rom_memory);
    C68k_Reset(&C68K);
}


void m68000_reset(int param)
{
	u32 opbase = param ? 0x000000 : 0xc00000;

    C68k_Reset(&C68K);
	m68000_set_reg(M68K_A7,  m68k_read_memory_32(opbase));
	m68000_set_reg(M68K_USP, m68k_read_memory_32(opbase));
	m68000_set_reg(M68K_PC,  m68k_read_memory_32(opbase + 4));
	m68000_set_reg(M68K_SR,  0x2700);
}


void m68000_exit(void)
{
	/* nothing to do ? */
}


int m68000_execute(int cycles)
{
    return C68k_Exec(&C68K, cycles);
}


void m68000_set_irq_line(int irqline, int state)
{
	if (irqline == IRQ_LINE_NMI)
		irqline = 7;

	switch (state)
	{
	case CLEAR_LINE:
		C68k_Set_IRQ(&C68K, 0);
		return;

	case ASSERT_LINE:
		C68k_Set_IRQ(&C68K, irqline);
		return;

	default:
		C68k_Set_IRQ(&C68K, irqline);
		return;
	}
}


unsigned m68000_get_reg(int regnum)
{
    switch (regnum)
    {
	case M68K_PC:  return C68k_Get_PC(&C68K);
	case M68K_USP: return C68k_Get_USP(&C68K);
	case M68K_SR:  return C68k_Get_SR(&C68K);
	case M68K_D0:  return C68k_Get_DReg(&C68K, 0);
	case M68K_D1:  return C68k_Get_DReg(&C68K, 1);
	case M68K_D2:  return C68k_Get_DReg(&C68K, 2);
	case M68K_D3:  return C68k_Get_DReg(&C68K, 3);
	case M68K_D4:  return C68k_Get_DReg(&C68K, 4);
	case M68K_D5:  return C68k_Get_DReg(&C68K, 5);
	case M68K_D6:  return C68k_Get_DReg(&C68K, 6);
	case M68K_D7:  return C68k_Get_DReg(&C68K, 7);
	case M68K_A0:  return C68k_Get_AReg(&C68K, 0);
	case M68K_A1:  return C68k_Get_AReg(&C68K, 1);
	case M68K_A2:  return C68k_Get_AReg(&C68K, 2);
	case M68K_A3:  return C68k_Get_AReg(&C68K, 3);
	case M68K_A4:  return C68k_Get_AReg(&C68K, 4);
	case M68K_A5:  return C68k_Get_AReg(&C68K, 5);
	case M68K_A6:  return C68k_Get_AReg(&C68K, 6);
	case M68K_A7:  return C68k_Get_AReg(&C68K, 7);
	default: return 0;
	}
}


void m68000_set_reg(int regnum, unsigned val)
{
    switch (regnum)
    {
	case M68K_PC:  C68k_Set_PC(&C68K, val); break;
	case M68K_USP: C68k_Set_USP(&C68K, val); break;
	case M68K_SR:  C68k_Set_SR(&C68K, val); break;
	case M68K_D0:  C68k_Set_DReg(&C68K, 0, val); break;
	case M68K_D1:  C68k_Set_DReg(&C68K, 1, val); break;
	case M68K_D2:  C68k_Set_DReg(&C68K, 2, val); break;
	case M68K_D3:  C68k_Set_DReg(&C68K, 3, val); break;
	case M68K_D4:  C68k_Set_DReg(&C68K, 4, val); break;
	case M68K_D5:  C68k_Set_DReg(&C68K, 5, val); break;
	case M68K_D6:  C68k_Set_DReg(&C68K, 6, val); break;
	case M68K_D7:  C68k_Set_DReg(&C68K, 7, val); break;
	case M68K_A0:  C68k_Set_AReg(&C68K, 0, val); break;
	case M68K_A1:  C68k_Set_AReg(&C68K, 1, val); break;
	case M68K_A2:  C68k_Set_AReg(&C68K, 2, val); break;
	case M68K_A3:  C68k_Set_AReg(&C68K, 3, val); break;
	case M68K_A4:  C68k_Set_AReg(&C68K, 4, val); break;
	case M68K_A5:  C68k_Set_AReg(&C68K, 5, val); break;
	case M68K_A6:  C68k_Set_AReg(&C68K, 6, val); break;
	case M68K_A7:  C68k_Set_AReg(&C68K, 7, val); break;
   	default: break;
    }
}


#ifdef SAVE_STATE

void state_save_m68000(u8 *state_buf)
{
	int i;
	u8 *in = state_buf;
	u32 pc = C68k_Get_PC(&C68K);

	for (i = 0; i < 8; i++)
		state_save_long(&C68K.D[i], 1);
	for (i = 0; i < 8; i++)
		state_save_long(&C68K.A[i], 1);

	state_save_long(&C68K.flag_C, 1);
	state_save_long(&C68K.flag_V, 1);
	state_save_long(&C68K.flag_notZ, 1);
	state_save_long(&C68K.flag_N, 1);
	state_save_long(&C68K.flag_X, 1);
	state_save_long(&C68K.flag_I, 1);
	state_save_long(&C68K.flag_S, 1);
	state_save_long(&C68K.USP, 1);
	state_save_long(&pc, 1);
	state_save_long(&C68K.Status, 1);
	state_save_long(&C68K.IRQLine, 1);
}

void state_load_m68000(u8 *state_buf)
{
	int i;
	u8 *out = state_buf;
	u32 pc;

	for (i = 0; i < 8; i++)
		state_load_long(&C68K.D[i], 1);
	for (i = 0; i < 8; i++)
		state_load_long(&C68K.A[i], 1);

	state_load_long(&C68K.flag_C, 1);
	state_load_long(&C68K.flag_V, 1);
	state_load_long(&C68K.flag_notZ, 1);
	state_load_long(&C68K.flag_N, 1);
	state_load_long(&C68K.flag_X, 1);
	state_load_long(&C68K.flag_I, 1);
	state_load_long(&C68K.flag_S, 1);
	state_load_long(&C68K.USP, 1);
	state_load_long(&pc, 1);
	state_load_long(&C68K.Status, 1);
	state_load_long(&C68K.IRQLine, 1);

	C68k_Set_PC(&C68K, pc);
}

#endif
