// render credits to given drawport
FLOAT Credits_Render(CDrawPort *pdp)
{
  if (!_bCreditsOn) {
    return 0;
  }
  CDrawPort dpWide;
  pdp->MakeWideScreen(&dpWide);

  pdp->Unlock();
  dpWide.Lock();

  FLOAT fTime = GetTime();
  
  pixW = dpWide.GetWidth();
  pixH = dpWide.GetHeight();
  fResolutionScaling = (FLOAT)pixW / 640.0f;
  dpWide.SetFont( _pfdDisplayFont);
  pixLineHeight = floor(20*fResolutionScaling);

  const FLOAT fLinesPerSecond = _fSpeed;
  FLOAT fOffset = fTime*fLinesPerSecond;
  INDEX ctLinesOnScreen = pixH/pixLineHeight;
  INDEX iLine1 = fOffset;

  pixJ = iLine1*pixLineHeight-fOffset*pixLineHeight;
  iLine1-=ctLinesOnScreen;

  INDEX ctLines = _astrCredits.Count();
  BOOL bOver = TRUE;

  for (INDEX i = iLine1; i<iLine1+ctLinesOnScreen+1; i++) {
    CTString *pstr = &strEmpty;
    INDEX iLine = i;
    if (iLine>=0 && iLine<ctLines) {
      pstr = &_astrCredits[iLine];
      bOver = FALSE;
    }
    PrintOneLine(&dpWide, *pstr);
  }

  dpWide.Unlock();
  pdp->Lock();

  if (bOver) {
    return 0;
  } else if (ctLines-iLine1<ctLinesOnScreen) {
    return FLOAT(ctLines-iLine1)/ctLinesOnScreen;
  } else {
    return 1;
  }
}
void CChildFrame::TestGame( BOOL bFullScreen) 
{
  // turn off info window
  CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
  pMainFrame->HideInfoWindow();

  CWorldEditorView *pPerspectiveView = GetPerspectiveView();
  ASSERT( pPerspectiveView != NULL);
  SetActiveView( pPerspectiveView, FALSE);
	CWorldEditorDoc* pDoc = pPerspectiveView->GetDocument();

  CTFileName fnmWorldToPlay;
  CTFileName fnmTempWorld = CTString("Temp\\TestGame.wld");

  // if the world was never saved or if it is modified
  if( (!pDoc->m_bWasEverSaved && wed_bSaveTestGameFirstTime) || pDoc->IsModified())
  { // save world under temporary name
    ASSERT_VALID(pDoc);
    try {  
      pDoc->m_woWorld.Save_t(fnmTempWorld);
      fnmWorldToPlay = fnmTempWorld;
    } catch( char *strError) {
      AfxMessageBox( CString(strError));
      pPerspectiveView->EnableToolTips(TRUE);
      return;
    }
  // if the world is not modified (it is saved on disk)
  } else
  { // use the saved world
    fnmWorldToPlay = CTString(CStringA(pDoc->GetPathName()));
    try {
      fnmWorldToPlay.RemoveApplicationPath_t();
    } catch( char *strError) {
      AfxMessageBox( CString(strError));
      pPerspectiveView->EnableToolTips(TRUE);
      return;
    }
  }

  // set rendering preferences
  _wrpWorldRenderPrefs = pPerspectiveView->m_vpViewPrefs.m_wrpWorldRenderPrefs;
  _mrpModelRenderPrefs = pPerspectiveView->m_vpViewPrefs.m_mrpModelRenderPrefs;
  _wrpWorldRenderPrefs.SetShadowsType( pPerspectiveView->GetChildFrame()->m_stShadowType);
  _wrpWorldRenderPrefs.SetSelectedEntityModel( theApp.m_pEntityMarkerModelObject);
  _wrpWorldRenderPrefs.SetSelectedPortalModel( theApp.m_pPortalMarkerModelObject);
  _wrpWorldRenderPrefs.SetEmptyBrushModel( theApp.m_pEmptyBrushModelObject);
  _wrpWorldRenderPrefs.SetTextureLayerOn( theApp.m_bTexture1, 0);
  _wrpWorldRenderPrefs.SetTextureLayerOn( theApp.m_bTexture2, 1);
  _wrpWorldRenderPrefs.SetTextureLayerOn( theApp.m_bTexture3, 2);
  _wrpWorldRenderPrefs.DisableVisTweaks(FALSE);

  _wrpWorldRenderPrefs.SetSelectedEntityModel( theApp.m_pEntityMarkerModelObject);
  _wrpWorldRenderPrefs.SetSelectedPortalModel( theApp.m_pPortalMarkerModelObject);
  _wrpWorldRenderPrefs.SetEmptyBrushModel( theApp.m_pEmptyBrushModelObject);

  // prepare test game view/draw ports
  CViewPort *pvp = pPerspectiveView->m_pvpViewPort;
  CDrawPort *pdp = pPerspectiveView->m_pdpDrawPort;
  pdp->SetOverlappedRendering(FALSE); // we are not rendering scene over already rendered scene (used for CSG layer)

  // if full screen mode is required
  HWND hWndFullScreen=NULL;
  HINSTANCE hInstanceFullScreen;
  WNDCLASSEX wcFullScreen;
  char achWindowTitle[256]; // current window title
  if( bFullScreen) 
  {
    // get full screen display mode info
    const PIX pixSizeI = theApp.m_dmFullScreen.dm_pixSizeI;
    const PIX pixSizeJ = theApp.m_dmFullScreen.dm_pixSizeJ;
    const DisplayDepth dd = theApp.m_dmFullScreen.dm_ddDepth;
    const GfxAPIType gat  = theApp.m_gatFullScreen;
    // set OpenGL fullscreen (before window)
    if( gat==GAT_OGL) {
      const BOOL bRes = _pGfx->SetDisplayMode( gat, 0, pixSizeI, pixSizeJ, dd);
      if( !bRes) {
        WarningMessage( "Unable to setup full screen display.");
        return;
      }
    } // register the window class
    hInstanceFullScreen = AfxGetInstanceHandle();
    ASSERT( hInstanceFullScreen!=NULL);
    wcFullScreen.cbSize = sizeof(wcFullScreen);
    wcFullScreen.style = CS_HREDRAW | CS_VREDRAW;
    wcFullScreen.lpfnWndProc = ::DefWindowProc;
    wcFullScreen.cbClsExtra = 0;
    wcFullScreen.cbWndExtra = 0;
    wcFullScreen.hInstance = hInstanceFullScreen;
    wcFullScreen.hIcon = LoadIcon( hInstanceFullScreen, (LPCTSTR)IDR_MAINFRAME );
    wcFullScreen.hCursor = NULL;
    wcFullScreen.hbrBackground = NULL;
    wcFullScreen.lpszMenuName  = CString(APPLICATION_NAME);
    wcFullScreen.lpszClassName = CString(APPLICATION_NAME);
    wcFullScreen.hIconSm = NULL;
    RegisterClassEx(&wcFullScreen);

    // create a window, invisible initially
    hWndFullScreen = CreateWindowExA(
      WS_EX_TOPMOST,
      APPLICATION_NAME,
      "Serious Editor - Full Screen Test Game",   // title
      WS_POPUP,
      0,0,
      pixSizeI, pixSizeJ,  // window size
      NULL,
      NULL,
      hInstanceFullScreen,
      NULL);
    // didn't make it?
    ASSERT( hWndFullScreen!=NULL);
    if( hWndFullScreen==NULL) {
      if( gat==GAT_OGL) _pGfx->ResetDisplayMode( (enum GfxAPIType)theApp.m_iApi);
      WarningMessage( "Unable to setup window for full screen display.");
      return;
    }
    // set windows for engine
    CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
    SE_UpdateWindowHandle( hWndFullScreen);

    // set window title and show it
    sprintf( achWindowTitle, "Serious Editor - Test Game (FullScreen %dx%d)", pixSizeI, pixSizeJ);
    ::SetWindowTextA( hWndFullScreen, achWindowTitle);
    ::ShowWindow(    hWndFullScreen, SW_SHOWNORMAL);

    // set Direct3D full screen (after window)
#ifdef SE1_D3D
    if( gat==GAT_D3D) {
      const BOOL bRes = _pGfx->SetDisplayMode( gat, 0, pixSizeI, pixSizeJ, dd);
      if( !bRes) {
        WarningMessage( "Unable to setup full screen display.");
        ::DestroyWindow( hWndFullScreen);
        SE_UpdateWindowHandle( pMainFrame->m_hWnd);
        return;
      }
    }
#endif // SE1_D3D
    // create canvas
    _pGfx->CreateWindowCanvas( hWndFullScreen, &pvp, &pdp);
    // initial screen fill and swap, just to get context running
    BOOL bSuccess = FALSE;
    if( pdp!=NULL && pdp->Lock()) {
      pdp->Fill(C_dGREEN|CT_OPAQUE);
      pdp->Unlock();
      pvp->SwapBuffers();
      bSuccess = TRUE;
    }
    // must succeed!
    ASSERT( bSuccess);
    if( !bSuccess) {
      _pGfx->ResetDisplayMode( (enum GfxAPIType)theApp.m_iApi);
      WarningMessage( "Unable to setup canvas for full screen display.");
      return;
    }
  }

  // enable sound
  snd_iFormat = Clamp( snd_iFormat, (INDEX)CSoundLibrary::SF_NONE, (INDEX)CSoundLibrary::SF_44100_16);
  _pSound->SetFormat( (enum CSoundLibrary::SoundFormat)snd_iFormat, TRUE);

  // run quick test game
  extern BOOL _bInOnDraw; 
  _bInOnDraw = TRUE;
  _pGameGUI->QuickTest( fnmWorldToPlay, pdp, pvp);
  _bInOnDraw = FALSE;

  // disable sound
  _pSound->SetFormat( CSoundLibrary::SF_NONE);

  // restore default display mode and close test full screen window
  if( hWndFullScreen!=NULL) {
    _pGfx->ResetDisplayMode( (enum GfxAPIType)theApp.m_iApi);
    ::DestroyWindow( hWndFullScreen);
    SE_UpdateWindowHandle( pMainFrame->m_hWnd);
  }
  // redraw all views
  pDoc->UpdateAllViews( NULL);
  pPerspectiveView->EnableToolTips( TRUE);
}