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

	cps1.c

	CPS1エミュレーションコア

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

#include "cps1.h"
#include "../rewind.h"

int save_period_frames = 0;
const int WAIT_MILIS = (50+70+90)*1000; //tiempo de espera antes de regresar a otro estado

/******************************************************************************
	ローカル関数
******************************************************************************/

/*--------------------------------------------------------
	CPS1エミュレーション初期化
 -------------------------------------------------------*/

static int cps1_init(void)
{
	cps1_driver_init();

	return cps1_video_init();
}


/*--------------------------------------------------------
	CPS1エミュレーションリセット
 -------------------------------------------------------*/

static void cps1_reset(void)
{
	autoframeskip_reset();

	cps1_driver_reset();
	cps1_video_reset();

	timer_reset();
	input_reset();
	sound_reset();

	Loop = LOOP_EXEC;
}


/*--------------------------------------------------------
	CPSエミュレーション終了
 -------------------------------------------------------*/

static void cps1_exit(void)
{
	ui_popup_reset(POPUP_MENU);

	video_clear_screen();
	msg_screen_init("Exit emulation");

	msg_printf("Please wait.\n");

	cps1_video_exit();
	cps1_driver_exit();
	save_gamecfg(game_name);
	
	free_rewind_states();

	msg_printf("Done.\n");

	show_exit_screen();
}


/*--------------------------------------------------------
	CPS1エミュレーション実行
 -------------------------------------------------------*/

static void cps1_run(void)
{
	SceCtrlData pspPad;
	int framecount = 0;
	
	while (Loop >= LOOP_RESET)
	{
		cps1_reset();

		while (Loop == LOOP_EXEC)
		{
			if (Sleep)
			{
				do
				{
					sceKernelDelayThread(5000000);
				} while (Sleep);

				autoframeskip_reset();
			}
			
			framecount++;
		
			if( framecount ==  save_period_frames){
				save_rewind_state();
				framecount = 0;
			}
			
			
			/****************REVISION DE BOTON DE REBOBINADO (BOTON R+START)*******/
			sceCtrlPeekBufferPositive(&pspPad, 1);
			if( (pspPad.Buttons & PSP_CTRL_RTRIGGER) && (pspPad.Buttons & PSP_CTRL_START) ){
				sound_thread_enable(0); //se deshabilita el sonido en el rebobinado
			
				while(1){				
					//se inicia el ciclo de rebobinado
					if( read_rewind_state() > 0 ){
						//se emula un frame
						autoframeskip_reset();
						timer_update_cpu();
						update_screen();
						
						//se emula otro frame para evitar "fantasmas"
						timer_update_cpu();
						update_screen();
					}
					
					sceKernelDelayThread(WAIT_MILIS); //para evitar regresar todos los estados
									    //de forma inmediata y sin control
					sceCtrlPeekBufferPositive(&pspPad, 1);
					if ( (pspPad.Buttons & PSP_CTRL_START) == 0) //se solto el boton START, termina el rebobinado
						break;
						
				}
				
				//se habilita el sonido y continua la emulacion normal
				autoframeskip_reset();
				sound_thread_set_priority(option_vsync ? 0x12 : 0x08);
				sound_thread_set_volume();
				sound_thread_enable(option_sound_enable);
			}
			
			/*************FIN REVISION REBOBINADO****************/
			
			timer_update_cpu();
			update_inputport();
			update_screen();
			
			
		}

		video_clear_screen();
		sound_mute(1);
	}
}

/******************************************************************************
	グローバル関数
******************************************************************************/

/*--------------------------------------------------------
	CPS1エミュレーションメイン
 -------------------------------------------------------*/

void cps1_main(void)
{
	
	
	Loop = LOOP_RESET;
	
	save_period_frames = get_save_period(); //se obtiene el intervalo de guardado

	while (Loop >= LOOP_RESTART)
	{
		Loop = LOOP_EXEC;

		ui_popup_reset(POPUP_GAME);

		fatal_error = 0;

		video_clear_screen();

		if (memory_init())
		{
			if (sound_init())
			{
				input_init();

				if (cps1_init())
				{
					
					allocate_rewind_states(); //se reserva casi toda la memoria libre
					
					cps1_run();
				}
				cps1_exit();

				input_shutdown();
			}
			sound_exit();
		}
		memory_shutdown();
		show_fatal_error();
	}
}
