#ifdef __GNUC__
#define __cdecl __attribute__((__cdecl__))
#endif

#ifdef WINDOWS

#undef UNICODE

#define WIN32_LEAN_AND_MEAN

#ifndef LINUX

#include <crtdbg.h>
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <timeapi.h>

#else

#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

// sleep ms, not seconds!
//#define Sleep sleep
#define Sleep(x) usleep((x*1000))

#endif

#include <stdlib.h>
#include <stdio.h>
#include "obk_config.h"
#include "new_common.h"
#include "driver/drv_public.h"
#include "cmnds/cmd_public.h"
#include "httpserver/new_http.h"
#include "quicktick.h"
#include "hal/hal_flashVars.h"
#include "selftest/selftest_local.h"
#include "new_pins.h"

#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))

// Need to link with Ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
#pragma comment(lib, "Winmm.lib")

int accum_time = 0;
int win_frameNum = 0;
// this time counter is simulated, I need this for unit tests to work
int g_simulatedTimeNow = 0;
extern int g_httpPort;
#define DEFAULT_FRAME_TIME 10

#if LINUX

#include <stdint.h>
#include <time.h>

uint32_t timeGetTime()
{
	struct timespec ts;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	return (uint32_t)((ts.tv_sec * 1000) + (ts.tv_nsec / 1000000));
}

void vTaskDelay(int x)
{
}
#endif

void strcat_safe_test()
{
	char tmpA[16];
	char tmpB[16];
	char buff[128];
	int res0, res1, res2, res3, res4, res5;
	tmpA[0] = 0;
	res0 = strcat_safe(tmpA, "Test1", sizeof(tmpA));
	res1 = strcat_safe(tmpA, " ", sizeof(tmpA));
	res2 = strcat_safe(tmpA, "is now processing", sizeof(tmpA));
	res3 = strcat_safe(tmpA, " very long string", sizeof(tmpA));
	res4 = strcat_safe(tmpA, " and it", sizeof(tmpA));
	res5 = strcat_safe(tmpA, " and it", sizeof(tmpA));
	tmpB[0] = 0;
	res0 = strcat_safe(tmpB, "Test1", sizeof(tmpB));
	res1 = strcat_safe(tmpB, " ", sizeof(tmpB));
	res2 = strcat_safe(tmpB, "is now processing", sizeof(tmpB));
	res3 = strcat_safe(tmpB, " very long string", sizeof(tmpB));
	res4 = strcat_safe(tmpB, " and it", sizeof(tmpB));
	res5 = strcat_safe(tmpB, " and it", sizeof(tmpB));

	urldecode2_safe(buff, "qqqqqq%40qqqq", sizeof(buff));
	urldecode2_safe(buff, "qqqqqq%40qqqq", sizeof(buff));
}

void Sim_RunFrame(int frameTime)
{
	// printf("Sim_RunFrame: frametime %i\n", frameTime);
	win_frameNum++;
	// this time counter is simulated, I need this for unit tests to work
	g_simulatedTimeNow += frameTime;
	accum_time += frameTime;
	QuickTick(0);
	WIN_RunMQTTFrame();
	HTTPServer_RunQuickTick();
	if (accum_time > 1000)
	{
		accum_time -= 1000;
		Main_OnEverySecond();
	}
}
void Sim_RunMiliseconds(int ms, bool bApplyRealtimeWait)
{
	while (ms > 0)
	{
		if (bApplyRealtimeWait)
		{
			Sleep(DEFAULT_FRAME_TIME);
		}
		Sim_RunFrame(DEFAULT_FRAME_TIME);
		ms -= DEFAULT_FRAME_TIME;
	}
}
void Sim_RunSeconds(float f, bool bApplyRealtimeWait)
{
	int ms = (int)(f * 1000);
	Sim_RunMiliseconds(ms, bApplyRealtimeWait);
}
void Sim_RunFrames(int n, bool bApplyRealtimeWait)
{
	int i;

	for (i = 0; i < n; i++)
	{
		if (bApplyRealtimeWait)
		{
			Sleep(DEFAULT_FRAME_TIME);
		}
		Sim_RunFrame(DEFAULT_FRAME_TIME);
	}
}

bool bObkStarted = false;
void SIM_Hack_ClearSimulatedPinRoles();

void CHANNEL_FreeLabels();

void SIM_ShutdownOBK()
{
	if (bObkStarted)
	{
		DRV_ShutdownAllDrivers();
#if ENABLE_LITTLEFS
		release_lfs();
#endif
		SVM_FreeAllFiles();
		SVM_StopAllScripts();
		SIM_Hack_ClearSimulatedPinRoles();
		WIN_ResetMQTT();
		SPILED_Shutdown(); // won't hurt
		CHANNEL_FreeLabels();
		UART_ResetForSimulator();
		CMD_ExecuteCommand("clearAll", 0);
		CMD_ExecuteCommand("led_expoMode", 0);
#if ENABLE_OBK_BERRY
		CMD_ExecuteCommand("stopBerry", 0);
#endif
		// LOG deinit after main init so commands will be re-added
		LOG_DeInit();
	}
}
void SIM_StartOBK(const char *flashPath)
{

	if (flashPath)
	{
		SIM_SetupFlashFileReading(flashPath);
	}
	bObkStarted = true;
	Main_Init();
}
void SIM_ClearOBK(const char *flashPath)
{
	SIM_ShutdownOBK();
	SIM_StartOBK(flashPath);
}
void Test_PartitionSearch()
{
	SIM_ClearOBK(0);
	// SIM_SetupFlashFileReading("W:/GIT/FlashDumps/IoT/BK7231N/BK7231N_Milfra_3g_TB11_QIO_2024-20-8-15-32-47.bin");

	SIM_SetupFlashFileReading("W:/GIT/FlashDumps/IoT/BK7231N/BK7231N_QIO_Adelid_Curtains_MPD-Z_2024-23-10-18-21-33.bin");
	// SIM_SetupFlashFileReading("W:/GIT/FlashDumps/IoT/BK7231M/SparkleIoT_XH-CB2S_Mini_Switch.bin");
	// SIM_SetupFlashFileReading("W:/GIT/FlashDumps/IoT/BK7231M/VeSync_Aubess_BSD33_BSDOG02_Plug_1.0.01.bin");

	CMD_ExecuteCommand("startDriver BKPartitions", 0);
	Sim_RunFrames(500000, false);
}
void Win_DoUnitTests()
{
	Test_LEDstrips();

	// SELFTEST_ASSERT_EXPRESSION("sqrt(4)", 2)
	SELFTEST_ASSERT(PIN_ParsePinRoleName("Btn_pd") == IOR_Button_pd);
	SELFTEST_ASSERT(PIN_ParsePinRoleName("Btn_pd_n") == IOR_Button_pd_n);
	SELFTEST_ASSERT(PIN_ParsePinRoleName("TglChanOnTgl_pd") == IOR_ToggleChannelOnToggle_pd);

	//Test_Shutters();
	Test_TuyaMCU_TH08();
	Test_ButtonEvents();
	Test_Command_If();
	Test_MQTT();
	Test_HTTP_Client();
	// Test_PartitionSearch();
	Test_OpenWeatherMap();
	Test_MAX72XX();

	Test_Commands_Channels();

	Test_Driver_TCL_AC();

	Test_PIR();
#if ENABLE_OBK_BERRY
	Test_Berry();
#endif

	Test_TuyaMCU_Boolean();
	Test_TuyaMCU_DP22();

	Test_Demo_ConditionalRelay();
	Test_Expressions_RunTests_Braces();
	Test_Expressions_RunTests_Basic();
	Test_Enums();
	Test_Backlog();
	Test_DoorSensor();
	Test_Command_If_Else();
	Test_ChargeLimitDriver();
#if ENABLE_BL_SHARED
	Test_EnergyMeter();
#endif
	Test_TuyaMCU_Calib();
	// this is slowest
	Test_TuyaMCU_Basic();
	Test_TuyaMCU_Mult();
	Test_TuyaMCU_RawAccess();
	Test_TuyaMCU_Robustness();
	Test_Battery();
	Test_TuyaMCU_BatteryPowered();
	Test_JSON_Lib();
#if ENABLE_LED_BASIC
	Test_MQTT_Get_LED_EnableAll();
#endif
	Test_MQTT_Get_Relay();
	Test_Commands_Startup();
	Test_IF_Inside_Backlog();
	Test_WaitFor();
	Test_TwoPWMsOneChannel();
	Test_ClockEvents();
#if ENABLE_HA_DISCOVERY
	Test_HassDiscovery_Base();
	Test_HassDiscovery();
	Test_HassDiscovery_Ext();
#endif
	Test_Role_ToggleAll_2();
	Test_Demo_ButtonToggleGroup();
	Test_Demo_ButtonScrollingChannelValues();
	Test_CFG_Via_HTTP();
	Test_Commands_Calendar();
	Test_Commands_Generic();
	Test_Demo_SimpleShuttersScript();
	Test_Role_ToggleAll();
	Test_Demo_FanCyclingRelays();
	Test_Demo_MapFanSpeedToRelays();
	Test_MapRanges();
	Test_Demo_ExclusiveRelays();
	Test_MultiplePinsOnChannel();
	Test_Flags();
#ifndef LINUX
	// TODO: fix on Linux
	Test_DHT();
#endif
	Test_Tasmota();
	Test_NTP();
	Test_TIME_DST();
	Test_TIME_SunsetSunrise();
	Test_ExpandConstant();
	Test_ChangeHandlers_MQTT();
	Test_ChangeHandlers();
	Test_ChangeHandlers2();
	Test_ChangeHandlers_EnsureThatChannelVariableIsExpandedAtHandlerRunTime();
	Test_RepeatingEvents();
	Test_Commands_Alias();
	Test_Demo_SignAndValue();
	Test_LEDDriver();
	Test_LFS();
	Test_Scripting();
	Test_Tokenizer();
	Test_Pins();
	Test_Http();
	Test_Http_LED();
	Test_DeviceGroups();

	// Just to be sure
	// Must be last step
	// reset whole device
	SIM_ClearOBK(0);
}
long g_delta;
float SIM_GetDeltaTimeSeconds()
{
	return g_delta * 0.001f;
}
long start_time = 0;
bool bStartTimeSet = false;
long SIM_GetTime()
{
	long cur = timeGetTime();
	if (bStartTimeSet == false)
	{
		start_time = cur;
		bStartTimeSet = true;
	}
	return cur - start_time;
}
// this time counter is simulated, I need this for unit tests to work
int rtos_get_time()
{
	return g_simulatedTimeNow;
}
int g_bDoingUnitTestsNow = 0;

#include "sim/sim_public.h"

int SelfTest_GetNumErrors();
extern int g_selfTestsMode;

float myFabs(float f)
{
	if (f < 0)
		return -f;
	return f;
}
bool Float_Equals(float a, float b)
{
	float res = myFabs(a - b);
	return res < 0.001f;
}
bool Float_EqualsEpsilon(float a, float b, float epsilon)
{
	float res = myFabs(a - b);
	return res < epsilon;
}
#define VA_BUFFER_SIZE 4096
#define VA_COUNT 4
const char *va(const char *fmt, ...)
{
	va_list argList;
	static int whi = 0;
	static char buffer[VA_COUNT][VA_BUFFER_SIZE];

	whi++;
	whi %= VA_COUNT;
	char *p = buffer[whi];

	va_start(argList, fmt);
	vsnprintf(p, VA_BUFFER_SIZE, fmt, argList);
	va_end(argList);
	return p;
}

#ifdef LINUX
// fixes - temp
#endif

#if !ENABLE_SDL_WINDOW
bool SIM_ReadDHT11(int pin, byte *data)
{
	return false;
}
void Sim_SendFakeBL0942Packet(float v, float c, float p)
{
}
void SIM_GeneratePowerStateDesc(char *o, int outLen)
{
	*o = 0;
}
#endif

int __cdecl main(int argc, char **argv)
{
	bool bWantsUnitTests = 1;

#ifndef LINUX
	WSADATA wsaData;
#endif
	// clear debug data
	if (1)
	{
		FILE *f = fopen("sim_lastPublishes.txt", "wb");
		if (f != 0)
		{
			fprintf(f, "\n\n");
			fclose(f);
		}
	}
	printf("Argc: %i\n", argc);
	if (argc > 1)
	{
		int value;

		for (int i = 1; i < argc; i++)
		{
			if (argv[i][0] == '-')
			{
				if (wal_strnicmp(argv[i] + 1, "port", 4) == 0)
				{
					i++;

					if (i < argc && sscanf(argv[i], "%d", &value) == 1)
					{
						g_httpPort = value;
					}
				}
				else if (wal_strnicmp(argv[i] + 1, "w", 1) == 0)
				{
					i++;

					if (i < argc && sscanf(argv[i], "%d", &value) == 1)
					{
#if ENABLE_SDL_WINDOW
						SIM_SetWindowW(value);
#endif
					}
				}
				else if (wal_strnicmp(argv[i] + 1, "h", 1) == 0)
				{
					i++;

					if (i < argc && sscanf(argv[i], "%d", &value) == 1)
					{
#if ENABLE_SDL_WINDOW
						SIM_SetWindowH(value);
#endif
					}
				}
				else if (wal_strnicmp(argv[i] + 1, "runUnitTests", 12) == 0)
				{
					i++;

					if (i < argc && sscanf(argv[i], "%d", &value) == 1)
					{
						// 0 = don't run, 1 = run with system pause, 2 - run without system pause
						g_selfTestsMode = value;
					}
				}
			}
		}
	}
	printf("g_selfTestsMode %i\n", g_selfTestsMode);

	int iResult;

#if 0
	int maxTest = 100;
	for (int i = 0; i <= maxTest; i++) {
		float frac = (float)i / (float)(maxTest);
		float in = frac;
		float res = LED_BrightnessMapping(255, in);
		printf("Brightness %f with color %f gives %f\n", in, 255.0f, res);
	}
#endif
#ifndef LINUX
	// Initialize Winsock
	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0)
	{
		printf("WSAStartup failed with error: %d\n", iResult);
		return 1;
	}
#endif
	printf("sizeof(short) = %d\n", (int)sizeof(short));
	printf("sizeof(int) = %d\n", (int)sizeof(int));
	printf("sizeof(long) = %d\n", (int)sizeof(long));
	printf("sizeof(unsigned long) = %d\n", (int)sizeof(unsigned long));
	printf("sizeof(float) = %d\n", (int)sizeof(float));
	printf("sizeof(double) = %d\n", (int)sizeof(double));
	printf("sizeof(long double) = %d\n", (int)sizeof(long double));
	printf("sizeof(led_corr_t) = %d\n", (int)sizeof(led_corr_t));
	printf("sizeof(mainConfig_t) = %d\n", (int)sizeof(mainConfig_t));

	if (sizeof(FLASH_VARS_STRUCTURE) != MAGIC_FLASHVARS_SIZE)
	{
		printf("sizeof(FLASH_VARS_STRUCTURE) != MAGIC_FLASHVARS_SIZE!: %i\n", sizeof(FLASH_VARS_STRUCTURE));
		system("pause");
	}
	if (sizeof(ledRemap_t) != MAGIC_LED_REMAP_SIZE)
	{
		printf("sizeof(ledRemap_t) != MAGIC_LED_REMAP_SIZE!: %i\n", sizeof(ledRemap_t));
		system("pause");
	}
	if (sizeof(led_corr_t) != MAGIC_LED_CORR_SIZE)
	{
		printf("sizeof(led_corr_t) != MAGIC_LED_CORR_SIZE!: %i\n", sizeof(led_corr_t));
		system("pause");
	}
	// printf("Offset MQTT Group: %i", OFFSETOF(mainConfig_t, mqtt_group));
	if (sizeof(mainConfig_t) != MAGIC_CONFIG_SIZE_V4)
	{
		printf("sizeof(mainConfig_t) != MAGIC_CONFIG_SIZE!: %i\n", sizeof(mainConfig_t));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, staticIP) != 0x00000527)
	{
		printf("OFFSETOF(mainConfig_t, staticIP) != 0x00000527z: %i\n", OFFSETOF(mainConfig_t, staticIP));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, wifi_ssid) != 0x00000014)
	{
		printf("OFFSETOF(mainConfig_t, wifi_ssid) != 0x00000014: %i\n", OFFSETOF(mainConfig_t, wifi_ssid));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, wifi_pass) != 0x00000054)
	{
		printf("OFFSETOF(mainConfig_t, wifi_pass) != 0x00000054: %i\n", OFFSETOF(mainConfig_t, wifi_pass));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, unused_fill) != 0x0000045E)
	{
		printf("OFFSETOF(mainConfig_t, unused_fill) != 0x0000045E: %i\n", OFFSETOF(mainConfig_t, unused_fill));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, buttonHoldRepeat) != 0x000004BA)
	{
		printf("OFFSETOF(mainConfig_t, buttonHoldRepeat) != 0x000004BA: %i\n", OFFSETOF(mainConfig_t, buttonHoldRepeat));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, shortDeviceName) != 0x2DE)
	{
		printf("OFFSETOF(mainConfig_t, shortDeviceName) != 0x2DE: %i\n", OFFSETOF(mainConfig_t, shortDeviceName));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull) != 0x00000597)
	{
		printf("OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull) != 0x00000597: %i\n", OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, dgr_sendFlags) != 0x00000460)
	{
		printf("OFFSETOF(mainConfig_t, dgr_sendFlags) != 0x00000460: %i\n", OFFSETOF(mainConfig_t, dgr_sendFlags));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, mqtt_host) != 0x00000094)
	{
		printf("OFFSETOF(mainConfig_t, mqtt_host) != 0x00000094: %i\n", OFFSETOF(mainConfig_t, mqtt_host));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, mqtt_userName) != 0x1D4)
	{
		printf("OFFSETOF(mainConfig_t, mqtt_userName) != 0x1D4: %i\n", OFFSETOF(mainConfig_t, mqtt_userName));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, mqtt_port) != 0x294)
	{
		printf("OFFSETOF(mainConfig_t, mqtt_port) != 0x294: %i\n", OFFSETOF(mainConfig_t, mqtt_port));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, mqtt_group) != 0x00000554)
	{
		printf("OFFSETOF(mainConfig_t, mqtt_group) != 0x00000554: %i\n", OFFSETOF(mainConfig_t, mqtt_group));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, LFS_Size) != 0x000004BC)
	{
		printf("OFFSETOF(mainConfig_t, LFS_Size) != 0x000004BC: %i\n", OFFSETOF(mainConfig_t, LFS_Size));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, ping_host) != 0x000005A0)
	{
		printf("OFFSETOF(mainConfig_t, ping_host) != 0x000005A0: %i\n", OFFSETOF(mainConfig_t, ping_host));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, buttonShortPress) != 0x000004B8)
	{
		printf("OFFSETOF(mainConfig_t, buttonShortPress) != 0x000004B8: %i\n", OFFSETOF(mainConfig_t, buttonShortPress));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, pins) != 0x0000033E)
	{
		printf("OFFSETOF(mainConfig_t, pins) != 0x0000033E: %i\n", OFFSETOF(mainConfig_t, pins));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, version) != 0x00000004)
	{
		printf("OFFSETOF(mainConfig_t, version) != 0x00000004: %i\n", OFFSETOF(mainConfig_t, version));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, initCommandLine) != 0x000005E0)
	{
		printf("OFFSETOF(mainConfig_t, initCommandLine) != 0x000005E0: %i\n", OFFSETOF(mainConfig_t, initCommandLine));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, wifi_ssid2) != 0x00000C00)
	{
		printf("OFFSETOF(mainConfig_t, wifi_ssid2) != 0x00000C00: %i\n", OFFSETOF(mainConfig_t, wifi_ssid2));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, wifi_pass2) != 0x00000C40)
	{
		printf("OFFSETOF(mainConfig_t, wifi_pass2) != 0x00000C40: %i\n", OFFSETOF(mainConfig_t, wifi_pass2));
		system("pause");
	}
	if (OFFSETOF(mainConfig_t, unused) != 0x00000CA5)
	{
		// printf("OFFSETOF(mainConfig_t, unused) != 0x00000CA5: %i\n", OFFSETOF(mainConfig_t, unused));
		// system("pause");
	}
	// Test expansion
	// CMD_UART_Send_Hex(0,0,"FFAA$CH1$BB",0);

#ifndef LINUX
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_ALWAYS_DF);
#else
	// I still didn't figure out, where Init_Main is called in Windows binyry if g_selfTestsMode is 0
	// but we need it, so commands are registered and HTTPServer_Start() is called ...
	SIM_StartOBK(0);
#endif

	if (g_selfTestsMode)
	{
		g_bDoingUnitTestsNow = 1;
		SIM_ClearOBK(0);
		// let things warm up a little
		Sim_RunFrames(50, false);
		// run tests
		Win_DoUnitTests();
		Sim_RunFrames(50, false);
		g_bDoingUnitTestsNow = 0;
		if (g_selfTestsMode > 1)
		{
			return SelfTest_GetNumErrors();
		}
	}

#if ENABLE_SDL_WINDOW
	SIM_CreateWindow(argc, argv);
#endif

	CMD_ExecuteCommand("startDriver MQTTServer", 0);
#ifndef LINUX
	CMD_ExecuteCommand("MQTTHost 192.168.0.113", 0);
	CMD_ExecuteCommand("MqttPassword ma1oovoo0pooTie7koa8Eiwae9vohth1vool8ekaej8Voohi7beif5uMuph9Diex", 0);
	CMD_ExecuteCommand("MqttClient WindowsOBK", 0);
	CMD_ExecuteCommand("MqttUser homeassistant", 0);
#else
	CMD_ExecuteCommand("MQTTHost 192.168.0.113", 0);
	CMD_ExecuteCommand("MqttPassword ma1oovoo0pooTie7koa8Eiwae9vohth1vool8ekaej8Voohi7beif5uMuph9Diex", 0);
	CMD_ExecuteCommand("MqttClient LinuxOBK", 0);
	CMD_ExecuteCommand("MqttUser homeassistant", 0);
#endif
	CMD_ExecuteCommand("reboot", 0);
	// CMD_ExecuteCommand("addRepeatingEvent 1 -1 backlog addChannel 1 1; publishInt myTestTopic $CH1", 0);

	if (false)
	{
		while (1)
		{
			Sleep(DEFAULT_FRAME_TIME);
			Sim_RunFrame(DEFAULT_FRAME_TIME);
#if ENABLE_SDL_WINDOW
			SIM_RunWindow();
#endif
		}
	}
	else
	{
		long prev_time = SIM_GetTime();
		while (1)
		{
			long cur_time = SIM_GetTime();
			g_delta = cur_time - prev_time;
			if (g_delta <= 0)
				continue;
			// give CPU some time to rest
			Sleep(DEFAULT_FRAME_TIME);
			Sim_RunFrame(g_delta);
#if ENABLE_SDL_WINDOW
			SIM_RunWindow();
#endif
			prev_time = cur_time;
		}
	}
	return 0;
}

// initialise OTA flash starting at startaddr
int init_ota(unsigned int startaddr)
{
	return 0;
}

// add any length of data to OTA
void add_otadata(unsigned char *data, int len)
{
	return;
}

// finalise OTA flash (write last sector if incomplete)
void close_ota()
{
	return;
}

void otarequest(const char *urlin)
{
	return;
}

#endif
