![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 /* 00002 Copyright 2005-2010 Intel Corporation. All Rights Reserved. 00003 00004 This file is part of Threading Building Blocks. 00005 00006 Threading Building Blocks is free software; you can redistribute it 00007 and/or modify it under the terms of the GNU General Public License 00008 version 2 as published by the Free Software Foundation. 00009 00010 Threading Building Blocks is distributed in the hope that it will be 00011 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00012 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with Threading Building Blocks; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 00019 As a special exception, you may use this file as part of a free software 00020 library without restriction. Specifically, if other files instantiate 00021 templates or use macros or inline functions from this file, or you compile 00022 this file and link it with other files to produce an executable, this 00023 file does not by itself cause the resulting executable to be covered by 00024 the GNU General Public License. This exception does not however 00025 invalidate any other reasons why the executable file might be covered by 00026 the GNU General Public License. 00027 */ 00028 00031 00032 #ifndef _CRT_SECURE_NO_DEPRECATE 00033 #define _CRT_SECURE_NO_DEPRECATE 00034 #endif 00035 // Check that the target Windows version has all API calls requried. 00036 #ifndef _WIN32_WINNT 00037 # define _WIN32_WINNT 0x0400 00038 #endif 00039 #if _WIN32_WINNT<0x0400 00040 # define YIELD_TO_THREAD() Sleep(0) 00041 #else 00042 # define YIELD_TO_THREAD() SwitchToThread() 00043 #endif 00044 #include "video.h" 00045 #include <fcntl.h> 00046 #include <io.h> 00047 #include <iostream> 00048 #include <fstream> 00049 00050 #pragma comment(lib, "gdi32.lib") 00051 #pragma comment(lib, "user32.lib") 00052 00053 // maximum mumber of lines the output console should have 00054 static const WORD MAX_CONSOLE_LINES = 500; 00055 const COLORREF RGBKEY = RGB(8, 8, 16); // at least 8 for 16-bit palette 00056 HWND g_hAppWnd; // The program's window handle 00057 HANDLE g_handles[2] = {0,0};// thread and wake up event 00058 unsigned int * g_pImg = 0; // drawing memory 00059 int g_sizex, g_sizey; 00060 static video * g_video = 0; 00061 WNDPROC g_pUserProc = 0; 00062 HINSTANCE video::win_hInstance = 0; 00063 int video::win_iCmdShow = 0; 00064 static WNDCLASSEX * gWndClass = 0; 00065 static HACCEL hAccelTable = 0; 00066 static DWORD g_msec = 0; 00067 static int g_fps = 0, g_updates = 0, g_skips = 0; 00068 00069 bool DisplayError(LPSTR lpstrErr, HRESULT hres = 0); // always returns false 00070 LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); 00071 00073 bool WinInit(HINSTANCE hInstance, int nCmdShow, WNDCLASSEX *uwc, const char *title, bool fixedsize) 00074 { 00075 WNDCLASSEX wndclass; // Our app's windows class 00076 if(uwc) { 00077 memcpy(&wndclass, uwc, sizeof(wndclass)); 00078 g_pUserProc = uwc->lpfnWndProc; 00079 } else { 00080 memset(&wndclass, 0, sizeof(wndclass)); 00081 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); 00082 wndclass.lpszClassName = title; 00083 } 00084 wndclass.cbSize = sizeof(wndclass); 00085 wndclass.hInstance = hInstance; 00086 wndclass.lpfnWndProc = InternalWndProc; 00087 wndclass.style |= CS_HREDRAW | CS_VREDRAW; 00088 wndclass.hbrBackground = CreateSolidBrush(RGBKEY); 00089 00090 if( !RegisterClassExA(&wndclass) ) return false; 00091 int xaddend = GetSystemMetrics(fixedsize?SM_CXFIXEDFRAME:SM_CXFRAME)*2; 00092 int yaddend = GetSystemMetrics(fixedsize?SM_CYFIXEDFRAME:SM_CYFRAME)*2 + GetSystemMetrics(SM_CYCAPTION); 00093 if(wndclass.lpszMenuName) yaddend += GetSystemMetrics(SM_CYMENU); 00094 00095 // Setup the new window's physical parameters - and tell Windows to create it 00096 g_hAppWnd = CreateWindowA(wndclass.lpszClassName, // Window class name 00097 title, // Window caption 00098 !fixedsize ? WS_OVERLAPPEDWINDOW : // Window style 00099 WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, 00100 CW_USEDEFAULT, // Initial x pos: use default placement 00101 0, // Initial y pos: not used here 00102 g_sizex+xaddend,// Initial x size 00103 g_sizey+yaddend,// Initial y size 00104 NULL, // parent window handle 00105 NULL, // window menu handle 00106 hInstance, // program instance handle 00107 NULL); // Creation parameters 00108 return g_hAppWnd != NULL; 00109 } 00110 00112 static bool RedirectIOToConsole(void) 00113 { 00114 int hConHandle; size_t lStdHandle; 00115 CONSOLE_SCREEN_BUFFER_INFO coninfo; 00116 FILE *fp; 00117 // allocate a console for this app 00118 AllocConsole(); 00119 00120 // set the screen buffer to be big enough to let us scroll text 00121 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); 00122 coninfo.dwSize.Y = MAX_CONSOLE_LINES; 00123 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); 00124 00125 // redirect unbuffered STDOUT to the console 00126 lStdHandle = (size_t)GetStdHandle(STD_OUTPUT_HANDLE); 00127 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); 00128 if(hConHandle <= 0) return false; 00129 fp = _fdopen( hConHandle, "w" ); 00130 *stdout = *fp; 00131 setvbuf( stdout, NULL, _IONBF, 0 ); 00132 00133 // redirect unbuffered STDERR to the console 00134 lStdHandle = (size_t)GetStdHandle(STD_ERROR_HANDLE); 00135 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); 00136 if(hConHandle > 0) { 00137 fp = _fdopen( hConHandle, "w" ); 00138 *stderr = *fp; 00139 setvbuf( stderr, NULL, _IONBF, 0 ); 00140 } 00141 00142 // redirect unbuffered STDIN to the console 00143 lStdHandle = (size_t)GetStdHandle(STD_INPUT_HANDLE); 00144 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); 00145 if(hConHandle > 0) { 00146 fp = _fdopen( hConHandle, "r" ); 00147 *stdin = *fp; 00148 setvbuf( stdin, NULL, _IONBF, 0 ); 00149 } 00150 00151 // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog 00152 // point to console as well 00153 std::ios::sync_with_stdio(); 00154 return true; 00155 } 00156 00157 00158 video::video() 00159 : red_mask(0xff0000), red_shift(16), green_mask(0xff00), 00160 green_shift(8), blue_mask(0xff), blue_shift(0), depth(24) 00161 { 00162 assert(g_video == 0); 00163 g_video = this; title = "Video"; running = threaded = calc_fps = false; updating = true; 00164 } 00165 00167 void video::win_set_class(WNDCLASSEX &wcex) 00168 { 00169 gWndClass = &wcex; 00170 } 00171 00172 void video::win_load_accelerators(int idc) 00173 { 00174 hAccelTable = LoadAccelerators(win_hInstance, MAKEINTRESOURCE(idc)); 00175 } 00176 00177 bool video::init_console() 00178 { 00179 if(RedirectIOToConsole()) { 00180 if(!g_pImg && g_sizex && g_sizey) 00181 g_pImg = new unsigned int[g_sizex * g_sizey]; 00182 if(g_pImg) running = true; 00183 return true; 00184 } 00185 return false; 00186 } 00187 00188 video::~video() 00189 { 00190 if(g_video) terminate(); 00191 } 00192 00193 DWORD WINAPI thread_video(LPVOID lpParameter) 00194 { 00195 video *v = (video*)lpParameter; 00196 v->on_process(); 00197 return 0; 00198 } 00199 00200 static bool loop_once(video *v) 00201 { 00202 // screen update notify 00203 if(int updates = g_updates) { 00204 g_updates = 0; 00205 if(g_video->updating) { g_skips += updates-1; g_fps++; } 00206 else g_skips += updates; 00207 UpdateWindow(g_hAppWnd); 00208 } 00209 // update fps 00210 DWORD msec = GetTickCount(); 00211 if(v->calc_fps && msec >= g_msec+1000) { 00212 double sec = (msec - g_msec)/1000.0; 00213 char buffer[256], n = _snprintf(buffer, 128, "%s: %d fps", v->title, int(double(g_fps + g_skips)/sec)); 00214 if(g_skips) _snprintf(buffer+n, 128, " - %d skipped = %d updates", int(g_skips/sec), int(g_fps/sec)); 00215 SetWindowTextA(g_hAppWnd, buffer); 00216 g_msec = msec; g_skips = g_fps = 0; 00217 } 00218 // event processing, including painting 00219 MSG msg; 00220 if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 00221 { 00222 if( msg.message == WM_QUIT ) { v->running = false; return false; } 00223 if( !hAccelTable || !TranslateAccelerator(msg.hwnd, hAccelTable, &msg) ) 00224 { 00225 TranslateMessage(&msg); 00226 DispatchMessage(&msg); 00227 } 00228 return true; // try again 00229 } 00230 return false; 00231 } 00232 00234 void video::main_loop() 00235 { 00236 // let Windows draw and unroll the window 00237 InvalidateRect(g_hAppWnd, 0, false); 00238 g_msec = GetTickCount(); // let's stay for 0,5 sec 00239 while(g_msec + 500 > GetTickCount()) { loop_once(this); Sleep(1); } 00240 g_msec = GetTickCount(); 00241 // now, start main process 00242 if(threaded) { 00243 g_handles[0] = CreateThread ( 00244 NULL, // LPSECURITY_ATTRIBUTES security_attrs 00245 0, // SIZE_T stacksize 00246 (LPTHREAD_START_ROUTINE) thread_video, 00247 this, // argument 00248 0, 0); 00249 if(!g_handles[0]) { DisplayError("Can't create thread"); return; } 00250 else // harmless race is possible here 00251 g_handles[1] = CreateEvent(NULL, false, false, NULL); 00252 while(running) { 00253 while(loop_once(this)); 00254 YIELD_TO_THREAD(); // give time for processing when running on single CPU 00255 DWORD r = MsgWaitForMultipleObjects(2, g_handles, false, INFINITE, QS_ALLINPUT^QS_MOUSEMOVE); 00256 if(r == WAIT_OBJECT_0) break; // thread terminated 00257 } 00258 running = false; 00259 if(WaitForSingleObject(g_handles[0], 300) == WAIT_TIMEOUT) 00260 TerminateThread(g_handles[0], 0); 00261 if(g_handles[0]) CloseHandle(g_handles[0]); 00262 if(g_handles[1]) CloseHandle(g_handles[1]); 00263 g_handles[0] = g_handles[1] = 0; 00264 } 00265 else on_process(); 00266 } 00267 00269 bool video::next_frame() 00270 { 00271 if(!running) return false; 00272 g_updates++; // Fast but inaccurate counter. The data race here is benign. 00273 if(!threaded) while(loop_once(this)); 00274 else if(g_handles[1]) { 00275 SetEvent(g_handles[1]); 00276 YIELD_TO_THREAD(); 00277 } 00278 return true; 00279 } 00280 00282 void video::show_title() 00283 { 00284 if(g_hAppWnd) 00285 SetWindowTextA(g_hAppWnd, title); 00286 }
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.