///////////////////////////////////////////////////////////////////////////////
// Wonderswan emulator
////////////////////////////////////////////////////////////////////////////////
//
// 13.04.2002: Fixed a small bug causing crashes
//
//
//
//
//////////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include <direct.h>
#include <time.h>

//TODO:VIDEO
//#include "./source/sdl/include/sdl.h"
//#include "./source/sdl/include/sdlptc.h"

#include "./source/rom.h"
#include "./source/nec/nec.h"
#include "./source/memory.h"
#include "./source/gpu.h"
#include "./source/io.h"
#include "./source/ws.h"
#include "./source/ticker.h"

////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// VERY SLOW !!!!
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_rotate_backbuffer(int16 *backbuffer)
{
	static int16	temp[224*144];
	memcpy(temp,backbuffer,224*144*2);

	for (int line=0;line<144;line++)
		for (int column=0;column<224;column++)
			backbuffer[line+((223-column)<<7)+((223-column)<<4)]=temp[column+(line<<7)+(line<<6)+(line<<5)];
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_emulate_standard(void)
{
	uint32		 startTime, endTime, totalFrames;
	unsigned int nNormalLast=0;
	int			 nNormalFrac=0; 
	int			 nTime=0,nCount=0; int i=0;
	int			surfacePitch;

	// 15 bits RGB555
	//TODO:VIDEO
	//Format format(16,0x007c00,0x00003e0,0x0000001f);
	//Console console;
	//Surface *surface;

	if (app_rotated)
	{
//TODO:VIDEO
//		surface=new Surface(144,224,format);

		int16 *backbuffer=(int16*)malloc(224*144*sizeof(int16));
		memset(backbuffer,0x00,224*144*sizeof(int16));
		//TODO:VIDEO
		//surfacePitch=(surface->pitch()>>1);

		totalFrames=0;
		startTime=clock();
		nNormalLast=0;// Last value of timeGetTime()
		nNormalFrac=0; // Extra fraction we did
		nNormalLast=timeGetTime();

		// filter change
		//if (gui_command==GUI_COMMAND_FILTER_CHANGE)
		//{
		//	ws_loadState("oswan.wss");
		//}

		//TODO:VIDEO
		//surfacePitch>>=1;
		//console.open(app_window_title,144,224,format);

		while (1)
		{
			nTime=timeGetTime()-nNormalLast;					  // calcule le temps écoulé depuis le dernier affichage
			// nTime est en mili-secondes.
			// détermine le nombre de trames à passer + 1
			nCount=(nTime*600 - nNormalFrac) /10000; 	

			// si le nombre de trames à passer + 1 est nul ou négatif,
			// ne rien faire pendant 2 ms
			if (nCount<=0) 
			{ 
				Sleep(2); 
			} // No need to do anything for a bit
			else
			{
				nNormalFrac+=nCount*10000;				// 
				nNormalLast+=nNormalFrac/600;				// add the duration of nNormalFrac frames
				nNormalFrac%=600;							// 

				// Pas plus de 9 (10-1) trames non affichées 
				if (nCount>10) 
					nCount=10; 

				//TODO:VIDEO
				/*int ws_key_esc=0;

				while ( SDL_PollEvent(&app_input_event) )
				{
					if ( app_input_event.type == SDL_QUIT )
					{
						ws_key_esc = 1;
					}
				}
	
					ws_key_start=0;
					ws_key_left=0;
					ws_key_right=0;
					ws_key_up=0;
					ws_key_down=0;
					ws_key_button_1=0;
					ws_key_button_2=0;

				uint8 *keystate = SDL_GetKeyState(NULL);

				if ( keystate[SDLK_ESCAPE] ) 
					ws_key_esc = 1;
				if ( keystate[SDLK_UP] )
					ws_key_up=1;
				if ( keystate[SDLK_DOWN] ) 
					ws_key_down=1;
				if ( keystate[SDLK_RIGHT] )
					ws_key_right=1;
				if ( keystate[SDLK_LEFT] )
					ws_key_left=1;
				if (keystate[SDLK_RETURN])
					ws_key_start=1;
				if (keystate[SDLK_c])
					ws_key_button_1=1;
				if (keystate[SDLK_x])
					ws_key_button_2=1;
				if (keystate[SDLK_p])
					ws_cyclesByLine+=10;
				if (keystate[SDLK_o])
					ws_cyclesByLine-=10;

				if (ws_key_esc)
				{
					console.close();
					if (ws_rom_path)
						strcpy(old_rom_path,ws_rom_path);
					gui_open();

					if ((ws_rom_path!=NULL)||(app_terminate))
						break;
					if (gui_command)
					{
						if (gui_command==GUI_COMMAND_RESET)
							ws_reset();
						if (gui_command==GUI_COMMAND_SCHEME_CHANGE)
							ws_set_colour_scheme(ws_colourScheme);
						if (gui_command==GUI_COMMAND_FILTER_CHANGE)
						{
							ws_saveState("oswan.wss");
							ws_rom_path=old_rom_path;
							delete surface;
							return;
						}
					}

					console.open(app_window_title,144,224,format);
				}*/


				for (i=0;i<nCount-1;i++) 
					while (!ws_executeLine(backbuffer,0));

				while (!ws_executeLine(backbuffer,1));
				totalFrames++;


				ws_rotate_backbuffer(backbuffer);
				//TODO:VIDEO
				//int32 *vs = (int32 *)surface->lock();
				//memcpy(vs,backbuffer,224*144*2);				
				//surface->unlock();
				//surface->copy(console);
				//console.update();
			}
		}

		endTime=clock();
		float fps=totalFrames/(((float)(endTime-startTime))/(float)CLOCKS_PER_SEC);
		//console.close();
		//delete surface;

	}
	else
	{
		//TODO:VIDEO
		//surface=new Surface(224,144,format);

		int16 *backbuffer=(int16*)malloc(224*144*sizeof(int16));
		memset(backbuffer,0x00,224*144*sizeof(int16));
		//TODO:VIDEO
		//surfacePitch=(surface->pitch()>>1);

		totalFrames=0;
		startTime=clock();
		nNormalLast=0; // Last value of timeGetTime()
		nNormalFrac=0; // Extra fraction we did
		nNormalLast=timeGetTime();
		// filter change
		//if (gui_command==GUI_COMMAND_FILTER_CHANGE)
		//{
		//	ws_loadState("oswan.wss");
		//}


		//TODO:VIDEO
		//console.open(app_window_title,224,144,format);
		while (1)
		{
			nTime=timeGetTime()-nNormalLast;					  // calcule le temps écoulé depuis le dernier affichage
			// nTime est en mili-secondes.
			// détermine le nombre de trames à passer + 1
			nCount=(nTime*600 - nNormalFrac) /10000; 	

			// si le nombre de trames à passer + 1 est nul ou négatif,
			// ne rien faire pendant 2 ms
			if (nCount<=0) 
			{ 
				Sleep(2); 
			} // No need to do anything for a bit
			else
			{
				nNormalFrac+=nCount*10000;				// 
				nNormalLast+=nNormalFrac/600;				// add the duration of nNormalFrac frames
				nNormalFrac%=600;							// 

				// Pas plus de 9 (10-1) trames non affichées 
				if (nCount>10) 
					nCount=10; 

				//TODO:VIDEO
				/*int ws_key_esc=0;

				while ( SDL_PollEvent(&app_input_event) )
				{
					if ( app_input_event.type == SDL_QUIT )
					{
						ws_key_esc = 1;
					}
				}
	
				ws_key_start=0;
				ws_key_left=0;
				ws_key_right=0;
				ws_key_up=0;
				ws_key_down=0;
				ws_key_button_1=0;
				ws_key_button_2=0;

				uint8 *keystate = SDL_GetKeyState(NULL);

				if ( keystate[SDLK_ESCAPE] ) 
					ws_key_esc = 1;
				if ( keystate[SDLK_UP] )
					ws_key_up=1;
				if ( keystate[SDLK_DOWN] ) 
					ws_key_down=1;
				if ( keystate[SDLK_RIGHT] )
					ws_key_right=1;
				if ( keystate[SDLK_LEFT] )
					ws_key_left=1;
				if (keystate[SDLK_RETURN])
					ws_key_start=1;
				if (keystate[SDLK_c])
					ws_key_button_1=1;
				if (keystate[SDLK_x])
					ws_key_button_2=1;
				if (keystate[SDLK_p])
					ws_cyclesByLine+=10;
				if (keystate[SDLK_o])
					ws_cyclesByLine-=10;

				if (ws_key_esc)
				{
					console.close();
					if (ws_rom_path)
						strcpy(old_rom_path,ws_rom_path);
					gui_open();

					if ((ws_rom_path!=NULL)||(app_terminate))
						break;
					if (gui_command)
					{
						if (gui_command==GUI_COMMAND_RESET)
							ws_reset();
						if (gui_command==GUI_COMMAND_SCHEME_CHANGE)
							ws_set_colour_scheme(ws_colourScheme);
						if (gui_command==GUI_COMMAND_FILTER_CHANGE)
						{
							ws_saveState("oswan.wss");
							ws_rom_path=old_rom_path;
							delete surface;
							return;
						}
					}

					console.open(app_window_title,224,144,format);
				}*/

				for (i=0;i<nCount-1;i++) 
					while (!ws_executeLine(backbuffer,0));

				while (!ws_executeLine(backbuffer,1));
					totalFrames++;

				//int32 *vs = (int32 *)surface->lock();
				//memcpy(vs,backbuffer,224*144*2);
				//surface->unlock();
				//surface->copy(console);
				//console.update();
			}
		}

		endTime=clock();
		float fps=totalFrames/(((float)(endTime-startTime))/(float)CLOCKS_PER_SEC);
		//console.close();
		//delete surface;

	}
}


////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
int Run()
{
	//if (!log_init(LOG_PATH)) printf("Warning: cannot open log file %s\n",LOG_PATH);
 	//fprintf(log_get(),"Wonderswan emulator v0.70 (last build on %s %s)\n",__DATE__,__TIME__);
	ws_videoEnhancementType=0;
	//gui_hInstance=hInstance;
	//gui_open();
	
	while (!app_terminate)
	{
		if (ws_rom_path)
		{
			if (ws_init(ws_rom_path))
			{
				app_rotated=ws_rotated();
				app_gameRunning=1;
				ws_set_system(ws_system);
				ws_set_colour_scheme(ws_colourScheme);
				ws_reset();
				switch (ws_videoEnhancementType)
				{
				case 0: ws_emulate_standard(); break;
				}
			}
			ws_done();
		}
	}
	//log_done();
	return(0);
}

