#include <direct.h>
#include "DemoInterface.h"
#include "SM_d3d.h"
#include "SM_main.h"
#include "SM_Shader.h"
#include "SM_Timer.h"
#include "SM_Main.h"
#include "SM_Music.h"
#include "SM_Renderable.h"
#include "SM_ResourceManager.h"
#include "SM_Shader.h"
#include "SM_RenderPipeline.h"
#include "SM_Coordinates.h"
#include "SM_CommonVF.h"
#include "SM_Screen.h"
#include "SM_Metaballs.h"
#include "SM_DebugText.h"
#include "SM_Voxelizer.h"
#include "SM_AviDecoder.h"
#include "MVFS.h"
#include "FXFilter.h"
#include "FX3DText.h"
#include "MSystemFunctions.h"
#include "MSurface.h"
#include "SM_Sound.h"
#include "SM_Keyboard.h"



bool							          DemoControl::g_bDrawFPS=false;

int g_iBeamShader = -1;
int g_iOpaqueShader = -1;



CKeyboardHandler  Keyboard;
  

DemoControl::DemoControl()
{  
}

DemoControl::~DemoControl()
{
}

int D3DRequirements(int iMode)
{  
  SM_Main::OutputDebug("Pixel shader support: %x\n", SM_D3d::GetModes()[iMode].dcDeviceCaps.PixelShaderVersion);
  SM_Main::OutputDebug("Vertex tweening: %s\n", 
    (SM_D3d::GetModes()[iMode].dcDeviceCaps.VertexProcessingCaps & D3DVTXPCAPS_TWEENING)?"TRUE":"FALSE");  

  /*
  if (FAILED( SM_D3d::D3D()->CheckDeviceFormat(SM_D3d::GetModes()[iMode].uDevice, 
                                   D3DDEVTYPE_HAL,
                                   SM_D3d::GetModes()[iMode].d3dFormat,
                                   0,
                                   D3DRTYPE_TEXTURE,
                                   D3DFMT_X8R8G8B8)) &&
      FAILED( SM_D3d::D3D()->CheckDeviceFormat(SM_D3d::GetModes()[iMode].uDevice, 
                                   D3DDEVTYPE_HAL,
                                   SM_D3d::GetModes()[iMode].d3dFormat,
                                   0,
                                   D3DRTYPE_TEXTURE,
                                   D3DFMT_X4R4G4B4             )))
  {
    return 0;
  }
  */

  
  /*
  D3DCAPS8 caps;                                   
  SM_D3d::D3D()->GetDeviceCaps(SM_D3d::GetModes()[iMode].uDevice, D3DDEVTYPE_HAL, &caps);
  if ((caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) == 0)
  {
    return 0;
  }

  if ((caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP ) == 0)
  {
    return 0;
  }
  */
  
                    
  return 1;
}

int DemoControl::Init(HWND hwnd, int iResX, int iResY, 
                      unsigned uBPP, bool bStencil, bool bFullscreen, bool bAntialias, 
                      bool bRetrace, bool bUpdateWindow, bool bLockable)
{
  Shutdown();

  if (SM_D3d::InitDisplay(hwnd, iResX, iResY, 
        uBPP, 
        bStencil, 
        bFullscreen, 
        D3DRequirements, "A8R8G8B8 or A4R4G4B4 Textures, Render to Texture", 
        bAntialias,
        bRetrace,
        bUpdateWindow,
        bLockable)!=0)
  {
    SM_Main::OutputError("Error initializing display");
    return (-1);
  }

  if (SM_Music::Init(hwnd)!=0)
  {
    MessageBox(NULL, "Couldn't start music sys. Quitting", "Error", MB_OK);
    return (-1);
  }  

  Keyboard.Init();
  SM_Main::SetKeyboardHandler(&Keyboard);



	return 0;
}

int DemoControl::Shutdown()
{
  ShutdownDemoInfrastructure();

  SM_Music::Shutdown();
  SM_D3d::ShutdownDisplay();
  return 0;
}


int DemoControl::Load(const char* pcPath)
{
  char pcDirectory[256];
  char pcAux[256];
  char pcAux2[256];

  MExtractPath(pcDirectory, pcPath);
  
  if (pcDirectory[0])
  {
  
    pcDirectory[strlen(pcDirectory)-1]='\0';
    strcpy(pcAux, pcDirectory);
    MExtractPath(pcDirectory, pcAux);
  }
  else
  {
    strcpy(pcDirectory, ".");
  }

  if (_chdir(pcDirectory) == -1)
  {
    SM_Main::OutputError("Failed to change dir");
    return (-1);
  }    
  else
  {
    SM_Main::OutputConsole("Working directory is now %s\n", pcDirectory);
  }
  
  strcpy(pcAux, "Data/");
  MExtractFile(pcAux2 , pcPath);
  strcat(pcAux, pcAux2);

  if (InitDemoInfrastructure() != 0)
  {
    MessageBox(NULL, "Error initiating demo infrastructure", "Error", MB_OK);
    return -1;
  }

  if (LoadScript(pcAux)!=0)
  {
    MessageBox(NULL, "Error loading script", "Error", MB_OK);
    return (-1);
  }

  
  
	return 0;
}

int DemoControl::InitDemoInfrastructure    ()
{
  ShutdownDemoInfrastructure();

  if (ResourceManager::Init()!=0)
  {
    MessageBox(NULL, "Error initiating ResourceManager. Quitting", "Error", MB_OK);
    return (-1);
  }

  if (ShaderManager::Init()!=0)
  {
    SM_Main::OutputError("Error initializing Shader Manager");
    return (-1);
  }
  
  if (ShaderManager::ParseShadersDir("data/shaders/")!=0)
  {
    SM_Main::OutputError("Error parsing shaders");
    return (-1);
  }
  
  #ifndef RETAIL
  if (DebugText::Init()!=0)
  {
    SM_Main::OutputError("Error initializing debug text. Have you textures/DEBUG_00.TGA?");
    return (-1);
  }
  #endif


  if (ScreenManager::Init()!=0)
  {
    SM_Main::OutputError("Error initializing image manager");
    return (-1);
  }  


  if (TextManager::Init("data/texts/text.txt")!=0)
  {
    SM_Main::OutputError("Error loading data/texts/text.txt");
    return (-1);
  }

  if (SM_Voxelizer::Init() != 0)
  {
    SM_Main::OutputError("Error initializing voxelizer");
    return (-1);
  }

  if (SM_Metaballs::Init() != 0)
  {
    SM_Main::OutputError("Error initializing metaballs");
    return (-1);
  }

  g_iBeamShader = ShaderManager::LoadShader("BEAMFLARE");
  g_iOpaqueShader = ShaderManager::LoadShader("BEAMOPAQUE");

  if (g_iBeamShader == -1 || g_iOpaqueShader == -1)
  {
    SM_Main::OutputError("Shaders BEAMFLARE and BEAMOPAQUE must be defined");    
  }

  if (SM_AviDecoder::InitSubsystem() != 0)
  {
    SM_Main::OutputError("Error initializing video stream system");    
  }

  /*
  SM_AviDecoder Test;

  Test.Init("data/videos/highway.avi");
  Test.GetFrame(0);
  */

  return 0;
}

int DemoControl::ShutdownDemoInfrastructure()
{
  if (SM_AviDecoder::ShutdownSubsystem() != 0)
  {
    SM_Main::OutputError("Error initializing video stream system");    
  }

  if (g_iBeamShader != -1)
  {
    ShaderManager::ReleaseShader(g_iBeamShader);
    g_iBeamShader = -1;
  }

  if (g_iOpaqueShader != -1)
  {
    ShaderManager::ReleaseShader(g_iOpaqueShader);
    g_iOpaqueShader = -1;
  }

  SM_Metaballs::Shutdown();
  TextManager::Shutdown();
  ScreenManager::Shutdown();
  #ifndef RETAIL  
  DebugText::Shutdown();
  #endif  

  SM_DemoScript::Shutdown();
  ShaderManager::Shutdown();

  ResourceManager::Shutdown();
  
  return 0;
}


int	LockDDSurface(MSurface& sSurface, IDirect3DSurface8* pSurface)
{
  D3DSURFACE_DESC ddSurfaceDesc;

  if (FAILED(pSurface->GetDesc(&ddSurfaceDesc)))
  {
    return -1;
  }
  
  D3DLOCKED_RECT LockedInfo;
	if (pSurface->LockRect(&LockedInfo, 0, 0) != D3D_OK)
	{
		return (-1);
	}

	MSurfaceDescriptor sdSurfaceDescriptor;

	sdSurfaceDescriptor.m_uiWidth			    =ddSurfaceDesc.Width;
	sdSurfaceDescriptor.m_uiHeight			  =ddSurfaceDesc.Height;
	sdSurfaceDescriptor.m_uiByteStride		=LockedInfo.Pitch;

  switch (ddSurfaceDesc.Format)
  {
  case D3DFMT_R8G8B8 :   sdSurfaceDescriptor.m_pfPixelFormat = CommonPixelDescriptors[E__RGB24__888]; break;
  case D3DFMT_A8R8G8B8:  sdSurfaceDescriptor.m_pfPixelFormat = CommonPixelDescriptors[E_ARGB32_8888]; break;
  case D3DFMT_X8R8G8B8:  sdSurfaceDescriptor.m_pfPixelFormat = CommonPixelDescriptors[E__RGB32__888]; break;
  case D3DFMT_R5G6B5 :   sdSurfaceDescriptor.m_pfPixelFormat = CommonPixelDescriptors[E__RGB16__565]; break;
  case D3DFMT_X1R5G5B5:  sdSurfaceDescriptor.m_pfPixelFormat = CommonPixelDescriptors[E__RGB16__555]; break;
  case D3DFMT_A1R5G5B5:  sdSurfaceDescriptor.m_pfPixelFormat = CommonPixelDescriptors[E__RGB16__555]; break;
  case D3DFMT_A4R4G4B4:  sdSurfaceDescriptor.m_pfPixelFormat = CommonPixelDescriptors[E_ARGB16__444]; break;  
  case D3DFMT_X4R4G4B4:  sdSurfaceDescriptor.m_pfPixelFormat = CommonPixelDescriptors[E_ARGB16__444]; break;
  default:
    pSurface->UnlockRect();
    return -1;
  }
	
	sSurface.Init(sdSurfaceDescriptor, LockedInfo.pBits, NULL);	
  
	return (0);
}

int	UnlockDDSurface(MSurface& sSurface, IDirect3DSurface8* pSurface)
{  
	if (FAILED(pSurface->UnlockRect()))
	{
		return (-1);
	}

	return (0);
}

int DemoControl::Run(float fTime, MSurface* pSurface)
{
  SM_DemoScript::SetTime(fTime);


  if (Keyboard.IsPressed(VK_ESCAPE))
  {
    SM_DemoScript::Shutdown();
    return (0);
  }

  if (Keyboard.IsPressed(VK_F1))
  {
    g_bDrawFPS=!g_bDrawFPS;    
  }

  if (Keyboard.IsPressed(VK_F2))
  {
    ShaderManager::ToggleWireframe();    
  }
  

          
  int iScriptReturn;
  ResourceManager::NewFrame();
    if ((iScriptReturn=SM_DemoScript::RunCommands())==1)
    {      
      SM_DemoScript::RunPreStartFrame(0, MAX_LAYERS);      
      if (SM_D3d::StartFrame()==0)
      {
        Coordinates::UpdatePhysicalSize();

        SM_D3d::SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
        SM_D3d::SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
        SM_D3d::SetRenderState(D3DRS_ALPHAREF, 0);
        SM_D3d::SetRenderState(D3DRS_DITHERENABLE, TRUE);
        //float fBias=-0.5f+3.0f*sinf(Timer::GetTime());
        //float fBias=12.0f;
        //SM_D3d::SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&fBias)));

        DWORD dwClearTarget = D3DCLEAR_TARGET;


        if (g_SceneFilter && g_SceneFilter->m_bNoClear)
        {
          dwClearTarget = 0;
        }

        if (g_SceneFilter)
        {
          SM_D3d::Device()->Clear(0, NULL, dwClearTarget |D3DCLEAR_ZBUFFER| (SM_D3d::GetCurrentMode()->bStencil?D3DCLEAR_STENCIL:0) , g_SceneFilter->GetBackColor(), 1.0f, 0 );
        }
        else
        {
          #ifdef _DEBUG
          SM_D3d::Device()->Clear(0, NULL, dwClearTarget |D3DCLEAR_ZBUFFER | (SM_D3d::GetCurrentMode()->bStencil?D3DCLEAR_STENCIL:0), D3DCOLOR_XRGB(0,int(128+127.0f*sinf(Timer::GetTime())),0), 1.0f, 0 );
          #else
          SM_D3d::Device()->Clear(0, NULL, dwClearTarget |D3DCLEAR_ZBUFFER | (SM_D3d::GetCurrentMode()->bStencil?D3DCLEAR_STENCIL:0), D3DCOLOR_XRGB(255,255,255), 1.0f, 0 );
          #endif
        }        
        
        SM_D3d::Device()->BeginScene();       

        RenderPipeline::Flush();
      
        g_SceneFilter->RunPreRender(Timer::GetTime());

        int iLayer;
        for (iLayer = 0 ; iLayer < 8 ; iLayer++)
        {        
          g_SceneFilter->RunPreLayer(iLayer, Timer::GetTime());
          iScriptReturn|=SM_DemoScript::Run(iLayer, iLayer+1);
          g_SceneFilter->RunPostLayer(iLayer, Timer::GetTime());
        }

        g_SceneFilter->Run(Timer::GetTime());      
        g_SceneFilter->RunPostRender(Timer::GetTime());


        iScriptReturn|=SM_DemoScript::Run(8, 16);


        Coordinates::UpdatePhysicalSize();
      
        #ifndef RETAIL
        
        static float fFps;
        static int   iFrame=0;
        static DWORD dwLastTime=0;
  
        DWORD dwTime=timeGetTime();
        if (dwTime-dwLastTime>1000)
        {
          fFps=1000.0f*float(iFrame)/float(dwTime-dwLastTime);
          iFrame=0;
          dwLastTime=dwTime;        
        } 
      
        static int g_iPolis;

        g_iPolis=ShaderManager::GetPolygons()-g_iPolis;      
        if (g_bDrawFPS)
        {
          DebugText::RenderText(0, 16, "%Time: %.2f %.0f fps / Polis %i", fTime, fFps, g_iPolis);
        }
        g_iPolis=ShaderManager::GetPolygons();
        iFrame++;

      
        SM_DemoEffect* pEffect;
      
        if (g_bDrawFPS)
        {
          int iEffects=0;
          for (pEffect=SM_DemoScript::GetFirstActiveEffect() ; pEffect ; pEffect=SM_DemoScript::GetNextActiveEffect())
          {
            DebugText::RenderText(0, 32+16*iEffects, "%s Layer: %i", pEffect->m_pcInstanceName, pEffect->m_iLayer);
            iEffects++;
          }          
        }
        #endif
                  
        if (pSurface)
        {
          IDirect3DSurface8* pD3DSurface;
          if (!FAILED(SM_D3d::Device()->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pD3DSurface)))
          {
            SM_Main::OutputDebug("Output Frame\n");

            MSurface s;
            if (LockDDSurface(s, pD3DSurface) == 0)
            {
              *pSurface = s;
            }
            UnlockDDSurface(s, pD3DSurface);

            pD3DSurface->Release();
          }
        }
        
        SM_D3d::Device()->EndScene();
        SM_D3d::Device()->Present( NULL, NULL, NULL, NULL );

        SM_D3d::EndFrame();
        SM_DemoScript::RunPostEndFrame(0, MAX_LAYERS);              
      }    
    }
    else
    {
      switch (iScriptReturn)
      {
      case -1:
        SM_Main::OutputError(NULL, "Script Runtime Error", "Error", MB_OK);
        //bEscape=true;
        break;
      case 0:
        break;
        //bEscape=true;
      }      
    }  

  return iScriptReturn;
}

int DemoControl::RunToTime(float fTime, MSurface* pSurface)
{
  SM_Main::OutputConsole("DemoControl::RunToTime(%f)\n", fTime);
  Reset();
  SM_DemoScript::SetRunToMode(true);
  int iReturn = Run(fTime, pSurface);
  SM_DemoScript::SetRunToMode(false);

  return iReturn;
}

int DemoControl::Reset()
{
  SM_Main::OutputConsole("DemoControl::Reset()\n");
  return SM_DemoScript::Reset();
}

int DemoControl::LoadCallback(unsigned uNumber, unsigned uEffects)
{
  ShaderManager::GetShader("NULL")->SetShaderState(0);
  SM_D3d::Device()->SetVertexShader(FVF_POSRHWDIFFUSETEX1);

  FVF_PosRhwDiffuseTex1 pV[4];
  unsigned short        pLine[8]={0,1,1,2,2,3,3,0};
  unsigned short        pIndices[6]={0,2,1,0,3,2};


  float fWidth  = Coordinates::PhysicalWidth();
  float fHeight = Coordinates::PhysicalHeight();
  
  #define  LOADINGBAR  0xFFFFFFFF
  #define LOADINGCOLOR 0xFFFF0000
  #define HEIGHT 8.0f
  
  pV[0].x=1.0f*fWidth/4.0f-0.5f; pV[0].y=fHeight/2.0f-HEIGHT/2.0f-0.5f; pV[0].z=0.0f; pV[0].u=0.0f; pV[0].v=0.0f; pV[0].oow=1.0f; pV[0].diffuse=LOADINGBAR;
  pV[1].x=3.0f*fWidth/4.0f-0.5f; pV[1].y=fHeight/2.0f-HEIGHT/2.0f-0.5f; pV[1].z=0.0f; pV[1].u=0.0f; pV[1].v=0.0f; pV[1].oow=1.0f; pV[1].diffuse=LOADINGBAR;
  pV[2].x=3.0f*fWidth/4.0f-0.5f; pV[2].y=fHeight/2.0f+HEIGHT/2.0f-0.5f; pV[2].z=0.0f; pV[2].u=0.0f; pV[2].v=0.0f; pV[2].oow=1.0f; pV[2].diffuse=LOADINGBAR;
  pV[3].x=1.0f*fWidth/4.0f-0.5f; pV[3].y=fHeight/2.0f+HEIGHT/2.0f-0.5f; pV[3].z=0.0f; pV[3].u=0.0f; pV[3].v=0.0f; pV[3].oow=1.0f; pV[3].diffuse=LOADINGBAR;

  SM_D3d::Device()->DrawIndexedPrimitiveUP(
        D3DPT_TRIANGLELIST, 
        0,
        4,
        2,
        pIndices,
        D3DFMT_INDEX16,
        pV, sizeof(FVF_PosRhwDiffuseTex1));
        
  float fBlockWidth = (fWidth/2.0f)/float(uEffects);
  int i;

  for (i = 0 ; i < uNumber ; i++)
  {
    pV[0].x=fWidth/4.0f+i*fBlockWidth              -0.5f; pV[0].y=fHeight/2.0f-HEIGHT/2.0f-0.5f; pV[0].z=0.0f; pV[0].u=0.0f; pV[0].v=0.0f; pV[0].oow=1.0f; pV[0].diffuse=LOADINGCOLOR;
    pV[1].x=fWidth/4.0f+i*fBlockWidth+fBlockWidth-0.5f;   pV[1].y=fHeight/2.0f-HEIGHT/2.0f-0.5f; pV[1].z=0.0f; pV[1].u=0.0f; pV[1].v=0.0f; pV[1].oow=1.0f; pV[1].diffuse=LOADINGCOLOR;
    pV[2].x=fWidth/4.0f+i*fBlockWidth+fBlockWidth-0.5f;   pV[2].y=fHeight/2.0f+HEIGHT/2.0f-0.5f; pV[2].z=0.0f; pV[2].u=0.0f; pV[2].v=0.0f; pV[2].oow=1.0f; pV[2].diffuse=LOADINGCOLOR;
    pV[3].x=fWidth/4.0f+i*fBlockWidth              -0.5f; pV[3].y=fHeight/2.0f+HEIGHT/2.0f-0.5f; pV[3].z=0.0f; pV[3].u=0.0f; pV[3].v=0.0f; pV[3].oow=1.0f; pV[3].diffuse=LOADINGCOLOR;
  
    SM_D3d::Device()->DrawIndexedPrimitiveUP(
        D3DPT_TRIANGLELIST, 
        0,
        4,
        2,
        pIndices,
        D3DFMT_INDEX16,
        pV, sizeof(FVF_PosRhwDiffuseTex1));

  }



  return 0;
}

int DemoControl::PreloadFX()
{
  using namespace SM_DemoScript;
  TCommandNode* pNode;
  

  unsigned uEffects = 0;
  for (pNode = GetCommandList() ; pNode ; pNode = pNode->pNext)
  {
    switch (pNode->pCommand->GetCommand())
    {
      case TCommand::CM_FX_LOAD:
      {
        if (strcmp(pNode->pCommand->GetFx()->m_pcInstanceName, "FILTER") == 0)
        {      
          if (pNode->pCommand->GetFx()->Init(pNode->pCommand->GetArgs()) != 0)
          {
            return -1;
          }            
        }
        else
        {
          uEffects++;
        }
      }
    }
  }

  unsigned uCurrent = 0;
  for (pNode = GetCommandList() ; pNode ; pNode = pNode->pNext)
  {
    switch (pNode->pCommand->GetCommand())
    {
      case TCommand::CM_FX_LOAD:
      {        
        if (strcmp(pNode->pCommand->GetFx()->m_pcInstanceName, "FILTER") != 0)
        { 
          if (SM_D3d::StartFrame()==0)
          {
            RenderPipeline::Flush();
            Coordinates::UpdatePhysicalSize();

            SM_D3d::Device()->BeginScene();       
            SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET |D3DCLEAR_ZBUFFER | (SM_D3d::GetCurrentMode()->bStencil?D3DCLEAR_STENCIL:0), D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );


            if (pNode->pCommand->GetFx()->Init(pNode->pCommand->GetArgs()) != 0)
            {
              return -1;
            }            

            uCurrent++;
            LoadCallback(uCurrent, uEffects);

            SM_D3d::Device()->EndScene();
            SM_D3d::EndFrame();
            SM_D3d::Device()->Present( NULL, NULL, NULL, NULL );
          }

        }                  
      }
    }
  }


  ResourceManager::NewFrame();
  if (SM_D3d::StartFrame()==0)
  {
    RenderPipeline::Flush();
    Coordinates::UpdatePhysicalSize();

    SM_D3d::Device()->BeginScene();       
    
    

  
    for (pNode = GetCommandList() ; pNode ; pNode = pNode->pNext)
    {
      switch (pNode->pCommand->GetCommand())
      {
        case TCommand::CM_FX_LOAD:
        {
          if (strcmp(pNode->pCommand->GetFx()->m_pcInstanceName, "FILTER") != 0)
          {      
            if (pNode->pCommand->GetFx()->DoPrecache())
            {
              pNode->pCommand->GetFx()->Start(0.0f);            
              pNode->pCommand->GetFx()->Run(0.0f);
              pNode->pCommand->GetFx()->Stop();
            }
          }
        }
      }
    }


    SM_D3d::Device()->Clear(0, NULL, D3DCLEAR_TARGET |D3DCLEAR_ZBUFFER | (SM_D3d::GetCurrentMode()->bStencil?D3DCLEAR_STENCIL:0), D3DCOLOR_XRGB(255,255,255), 1.0f, 0 );
    SM_D3d::Device()->EndScene();
    SM_D3d::EndFrame();
  }

  return 0;
}

int DemoControl::LoadScript(const char* pcScriptFile)
{
  MVFSFILE* f;
  int iReturn = -1;

  f=MVFS::fopen(pcScriptFile, "rb");

  if (!f)
  {
    SM_Main::OutputError("File not found %s", pcScriptFile);
    return (-1);
  }

  MVFS::fseek(f, 0, SEEK_END);
  int iLength=MVFS::ftell(f);
  MVFS::fseek(f, 0, SEEK_SET);

  char* pcBuffer=new char[iLength+1];
  if (!pcBuffer)
  {
    return -1;
  }

  if (iLength && MVFS::fread(pcBuffer, iLength, 1, f)!=1)
  {
    SM_Main::OutputError("Error reading script from %s", pcScriptFile);
    return (-1);
  }

  pcBuffer[iLength]='\0';
  
  if (SM_DemoScript::Init(pcBuffer, false, true) == -1)
  {    
    goto END;
  }
  
  iReturn = 0;
END:
  MVFS::fclose(f);    
  if (pcBuffer) delete[] pcBuffer;
  
  return (iReturn);
}


int DemoControl::SaveScript(const char* pcScriptFile)
{
  return 0;
}



