// 垂直同步: 0对应DDWAITVB_BLOCKBEGIN, 其他为DDWAITVB_BLOCKEND int DDrawWaitForVerticalBlank(int mode) { DWORD dwFlag = (mode == 0)? DDWAITVB_BLOCKBEGIN : DDWAITVB_BLOCKEND; HRESULT hr; if (lpDirectDraw7 == NULL) { if (DDrawInit() != 0) return -1; } hr = IDirectDraw7_WaitForVerticalBlank(lpDirectDraw7, dwFlag, NULL); if (hr != DD_OK) return -1; return 0; }
bool C4Application::DoInit(int argc, char * argv[]) { assert(AppState == C4AS_None); // Config overwrite by parameter StdStrBuf sConfigFilename; for (int32_t iPar=0; iPar < argc; iPar++) if (SEqual2NoCase(argv[iPar], "--config=")) sConfigFilename.Copy(argv[iPar] + 9); // Config check Config.Init(); Config.Load(sConfigFilename.getData()); Config.Save(); // sometimes, the configuration can become corrupted due to loading errors or w/e // check this and reset defaults if necessary if (Config.IsCorrupted()) { if (sConfigFilename) { // custom config corrupted: Fail Log("ERROR: Custom configuration corrupted - program abort!\n"); return false; } else { // default config corrupted: Restore default Log("Warning: Configuration corrupted - restoring default!\n"); Config.Default(); Config.Save(); Config.Load(); } } // Open log OpenLog(); Revision.Ref(C4REVISION); // Engine header message Log(C4ENGINECAPTION); LogF("Version: %s %s (%s)", C4VERSION, C4_OS, Revision.getData()); LogF("ExePath: \"%s\"", Config.General.ExePath.getData()); LogF("SystemDataPath: \"%s\"", Config.General.SystemDataPath); LogF("UserDataPath: \"%s\"", Config.General.UserDataPath); // Init C4Group C4Group_SetProcessCallback(&ProcessCallback); C4Group_SetTempPath(Config.General.TempPath.getData()); C4Group_SetSortList(C4CFN_FLS); // Cleanup temp folders left behind Config.CleanupTempUpdateFolder(); // Initialize game data paths Reloc.Init(); // init system group if (!Reloc.Open(SystemGroup, C4CFN_System)) { // Error opening system group - no LogFatal, because it needs language table. // This will *not* use the FatalErrors stack, but this will cause the game // to instantly halt, anyway. const char *szMessage = "Error opening system group file (System.ocg)!"; Log(szMessage); // Fatal error, game cannot start - have player notice MessageDialog(szMessage); return false; } // Parse command line ParseCommandLine(argc, argv); // Open additional logs that depend on command line OpenExtraLogs(); // Init external language packs Languages.Init(); // Load language string table if (!Languages.LoadLanguage(Config.General.LanguageEx)) // No language table was loaded - bad luck... if (!Languages.HasStringTable()) Log("WARNING: No language string table loaded!"); #if defined(WIN32) && defined(WITH_AUTOMATIC_UPDATE) // Windows: handle incoming updates directly, even before starting up the gui // because updates will be applied in the console anyway. if (Application.IncomingUpdate) if (C4UpdateDlg::ApplyUpdate(Application.IncomingUpdate.getData(), false, NULL)) return true; #endif // Fixup resolution if (!Config.Graphics.Windowed) ApplyResolutionConstraints(); // activate Active=true; // Init carrier window if (!isEditor) { if (!(pWindow = FullScreen.Init(this))) { Clear(); ShowGfxErrorDialog(); return false; } } else { if (!(pWindow = Console.Init(this))) { Clear(); return false; } } // init timers (needs window) Add(pGameTimer = new C4ApplicationGameTimer()); // Initialize OpenGL bool success = DDrawInit(this, GetConfigWidth(), GetConfigHeight(), Config.Graphics.BitDepth, Config.Graphics.Monitor); if (!success) { LogFatal(LoadResStr("IDS_ERR_DDRAW")); Clear(); ShowGfxErrorDialog(); return false; } if (!isEditor) { if (!SetVideoMode(Application.GetConfigWidth(), Application.GetConfigHeight(), Config.Graphics.BitDepth, Config.Graphics.RefreshRate, Config.Graphics.Monitor, !Config.Graphics.Windowed)) pWindow->SetSize(Config.Graphics.WindowX, Config.Graphics.WindowY); } // Initialize gamepad if (!pGamePadControl && Config.General.GamepadEnabled) pGamePadControl = new C4GamePadControl(); AppState = C4AS_PreInit; return true; }
bool C4Application::DoInit() { assert(AppState == C4AS_None); // Config overwrite by parameter StdStrBuf sConfigFilename; char szParameter[_MAX_PATH + 1]; for (int32_t iPar = 0; SGetParameter(GetCommandLine(), iPar, szParameter, _MAX_PATH); iPar++) if (SEqual2NoCase(szParameter, "/config:")) sConfigFilename.Copy(szParameter + 8); // Config check Config.Init(); Config.Load(true, sConfigFilename.getData()); Config.Save(); // sometimes, the configuration can become corrupted due to loading errors or // w/e // check this and reset defaults if necessary if (Config.IsCorrupted()) { if (sConfigFilename) { // custom config corrupted: Fail Log("Warning: Custom configuration corrupted - program abort!\n"); return false; } else { // default config corrupted: Restore default Log("Warning: Configuration corrupted - restoring default!\n"); Config.Default(); Config.Save(); Config.Load(); } } MMTimer = Config.General.MMTimer != 0; // Init C4Group C4Group_SetMaker(Config.General.Name); C4Group_SetProcessCallback(&ProcessCallback); C4Group_SetTempPath(Config.General.TempPath); C4Group_SetSortList(C4CFN_FLS); // Open log if (!OpenLog()) return false; // init system group if (!SystemGroup.Open(C4CFN_System)) { // Error opening system group - no LogFatal, because it needs language // table. // This will *not* use the FatalErrors stack, but this will cause the game // to instantly halt, anyway. Log("Error opening system group file (System.c4g)!"); return false; } // Language override by parameter const char *pLanguage; if (pLanguage = SSearchNoCase(GetCommandLine(), "/Language:")) SCopyUntil(pLanguage, Config.General.LanguageEx, ' ', CFG_MaxString); // Init external language packs Languages.Init(); // Load language string table if (!Languages.LoadLanguage(Config.General.LanguageEx)) // No language table was loaded - bad luck... if (!IsResStrTableLoaded()) Log("WARNING: No language string table loaded!"); // Set unregistered user name C4Group_SetMaker(LoadResStr("IDS_PRC_UNREGUSER")); // Parse command line Game.ParseCommandLine(GetCommandLine()); #ifdef WIN32 // Windows: handle incoming updates directly, even before starting up the gui // because updates will be applied in the console anyway. if (Application.IncomingUpdate) if (C4UpdateDlg::ApplyUpdate(Application.IncomingUpdate.getData(), false, NULL)) return true; #endif // activate Active = TRUE; // Init carrier window if (isFullScreen) { if (!(pWindow = FullScreen.Init(this))) { Clear(); return false; } } else { if (!(pWindow = Console.Init(this))) { Clear(); return false; } } // init timers (needs window) if (!InitTimer()) { LogFatal(LoadResStr("IDS_ERR_TIMER")); Clear(); return false; } // Engine header message Log(C4ENGINEINFOLONG); LogF("Version: %s %s", C4VERSION, C4_OS); #if defined(USE_DIRECTX) && defined(_WIN32) // DDraw emulation warning DWORD DDrawEmulationState; if (GetRegistryDWord(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\DirectDraw", "EmulationOnly", &DDrawEmulationState)) if (DDrawEmulationState) Log("WARNING: DDraw Software emulation is activated!"); #endif // Initialize D3D/OpenGL DDraw = DDrawInit(this, isFullScreen, FALSE, Config.Graphics.BitDepth, Config.Graphics.Engine, Config.Graphics.Monitor); if (!DDraw) { LogFatal(LoadResStr("IDS_ERR_DDRAW")); Clear(); return false; } #if defined(_WIN32) && !defined(USE_CONSOLE) // Register clonk file classes - notice: under Vista this will only work if we // have administrator rights char szModule[_MAX_PATH + 1]; GetModuleFileName(NULL, szModule, _MAX_PATH); SetC4FileClasses(szModule); #endif // Initialize gamepad if (!pGamePadControl && Config.General.GamepadEnabled) pGamePadControl = new C4GamePadControl(); AppState = C4AS_PreInit; return true; }
// 创建 DirectDraw屏幕 // 如果 bpp为0的话则创建窗口模式,w,h失效,否则全屏幕 CSURFACE *DDrawCreateScreen(HWND hWnd, int w, int h, int bpp, HRESULT *HR) { DDSURFACEDESC2 ddsd; CSURFACE *surface; HRESULT hr; if (lpDirectDraw7 == NULL) { if (DDrawInit() != 0) return NULL; } memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); // 创建窗口模式 if (bpp == 0) { hr = IDirectDraw7_SetCooperativeLevel(lpDirectDraw7, hWnd, DDSCL_NORMAL); if (hr != DD_OK) { fprintf(stderr, "DirectDraw: SetCooperativeLevel failed\n"); fflush(stderr); if (HR) *HR = hr; return NULL; } ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; surface = DDrawCreateFromDesc(&ddsd, &hr); if (surface == NULL) { fprintf(stderr, "DirectDraw: Create Primary Surface failed\n"); fflush(stderr); if (HR) *HR = hr; return NULL; } hr = IDirectDraw7_CreateClipper(lpDirectDraw7, 0, &surface->clip, 0); if (hr != DD_OK) { fprintf(stderr, "DirectDraw: Create Clipper failed\n"); fflush(stderr); if (HR) *HR = hr; surface->clip = NULL; DDrawSurfaceRelease(surface); return NULL; } hr = IDirectDrawClipper_SetHWnd(surface->clip, 0, hWnd); if (hr != DD_OK) { fprintf(stderr, "DirectDraw: SetHWnd failed\n"); fflush(stderr); if (HR) *HR = hr; DDrawSurfaceRelease(surface); return NULL; } hr = IDirectDrawSurface7_SetClipper(surface->lpDDS, surface->clip); if (hr != DD_OK) { fprintf(stderr, "DirectDraw: SetClipper failed\n"); fflush(stderr); if (HR) *HR = hr; DDrawSurfaceRelease(surface); return NULL; } } else { // 创建全屏模式 DWORD dwFlags; if (hFullScreenMode) { fprintf(stderr, "DirectDraw: Already in Full Screen Mode\n"); fflush(stderr); return NULL; } dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT | DDSCL_ALLOWMODEX; hr = IDirectDraw7_SetCooperativeLevel(lpDirectDraw7, hWnd, dwFlags); if (hr != DD_OK) { fprintf(stderr, "DirectDraw: SetCooperativeLevel failed\n"); fflush(stderr); if (HR) *HR = hr; return NULL; } hr = IDirectDraw7_SetDisplayMode(lpDirectDraw7, w, h, bpp, 0, DDSDM_STANDARDVGAMODE); if (hr != DD_OK) { fprintf(stderr, "DirectDraw: SetDisplayMode failed\n"); fflush(stderr); if (HR) *HR = hr; return NULL; } ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; ddsd.dwBackBufferCount = 1; surface = DDrawCreateFromDesc(&ddsd, &hr); if (surface == NULL) { fprintf(stderr, "DirectDraw: Create Primary Surface failed\n"); fflush(stderr); IDirectDraw7_RestoreDisplayMode(lpDirectDraw7); if (HR) *HR = hr; return NULL; } hFullScreenMode = 1; } IDirectDraw7_GetDisplayMode(lpDirectDraw7, &ddsd); surface->primary = 1; surface->hWnd = hWnd; return surface; }
// create surface from DDSURFACEDESC2 CSURFACE *DDrawCreateFromDesc(const DDSURFACEDESC2 *desc, HRESULT *hr) { LPDIRECTDRAWSURFACE7 lpDDS; DDSURFACEDESC2 ddsd; CSURFACE *surface; HRESULT result; if (lpDirectDraw7 == NULL) { if (DDrawInit() != 0) return NULL; } surface = (CSURFACE*)malloc(sizeof(CSURFACE)); assert(surface); ddsd = *desc; result = IDirectDraw7_CreateSurface(lpDirectDraw7, &ddsd, &lpDDS, NULL); if (hr) *hr = result; if (result != DD_OK) { free(surface); return NULL; } result = IDirectDrawSurface7_GetSurfaceDesc(lpDDS, &ddsd); if (hr) *hr = result; if (result != DD_OK) { IDirectDrawSurface7_Release(lpDDS); free(surface); return NULL; } surface->lpDDS = lpDDS; surface->ddsd = ddsd; surface->w = ddsd.dwWidth; surface->h = ddsd.dwHeight; surface->bpp = ddsd.ddpfPixelFormat.dwRGBBitCount; if (surface->bpp == 8) surface->pixfmt = PIXFMT_8; else if (surface->bpp == 15) surface->pixfmt = PIXFMT_RGB15; else if (surface->bpp == 16) surface->pixfmt = PIXFMT_RGB16; else if (surface->bpp == 24) surface->pixfmt = PIXFMT_RGB24; else if (surface->bpp == 32) { if (ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) { surface->pixfmt = PIXFMT_ARGB32; } else { surface->pixfmt = PIXFMT_RGB32; } } surface->pitch = ddsd.dwLinearSize; surface->bits = (unsigned char*)ddsd.lpSurface; surface->mask = 0; surface->lock = 0; surface->clip = NULL; surface->primary = 0; surface->hWnd = NULL; hSurfaceCounter++; return surface; }