/src/app/app.cpp

https://bitbucket.org/vivkin/gam3b00bs/ · C++ · 347 lines · 258 code · 76 blank · 13 comment · 42 complexity · 8dc94ca391adc8e2040b56379e9be273 MD5 · raw file

  1. #include "common.h"
  2. #include "app.h"
  3. #include "network/network.h"
  4. #include "sound/sound.h"
  5. #include "renderer/device.h"
  6. #include "log.h"
  7. #include <stdio.h>
  8. #include <windows.h>
  9. #define CONFIG_FILE "./b00bs.ini"
  10. namespace app
  11. {
  12. struct state
  13. {
  14. timings time;
  15. int64 ticks_prev;
  16. int64 ticks_cur;
  17. HWND hwnd;
  18. };
  19. static state g_app = {};
  20. namespace input
  21. {
  22. static state key_states[INPUT_KEYS_MAX];
  23. static state button_states[INPUT_BUTTONS_MAX];
  24. static int16 cursor_rel[2], wheel_rel;
  25. static RECT old_clip;
  26. bool init()
  27. {
  28. ASSERT(g_app.hwnd);
  29. RAWINPUTDEVICE rid[2]; // keyboard & mouse
  30. RECT rect;
  31. memset(key_states, 0, sizeof(state) * INPUT_KEYS_MAX);
  32. memset(button_states, 0, sizeof(state) * INPUT_BUTTONS_MAX);
  33. cursor_rel[0] = cursor_rel[1] = wheel_rel = 0;
  34. GetWindowRect(g_app.hwnd, &rect);
  35. SetCursorPos((rect.left + rect.right) / 2, (rect.bottom + rect.top) / 2);
  36. GetClipCursor(&old_clip);
  37. ClipCursor(&rect);
  38. //ShowCursor(FALSE); // orly?
  39. rid[0].usUsagePage = 0x01;
  40. rid[0].usUsage = 0x02; // mouse
  41. rid[0].dwFlags = 0; //RIDEV_NOLEGACY;
  42. rid[0].hwndTarget = g_app.hwnd;
  43. rid[1].usUsagePage = 0x01;
  44. rid[1].usUsage = 0x06; // keyboard
  45. rid[1].dwFlags = 0; //RIDEV_NOLEGACY;
  46. rid[1].hwndTarget = g_app.hwnd;
  47. return RegisterRawInputDevices(rid, 2, sizeof(RAWINPUTDEVICE)) != 0;
  48. }
  49. void term()
  50. {
  51. ClipCursor(&old_clip);
  52. }
  53. bool tick()
  54. {
  55. uint32_t i;
  56. cursor_rel[0] = cursor_rel[1] = wheel_rel = 0;
  57. for (i = 0; i < INPUT_KEYS_MAX; ++i)
  58. if (key_states[i] == DOWN)
  59. key_states[i] = PRESSED;
  60. for (i = 0; i < INPUT_BUTTONS_MAX; ++i)
  61. if (button_states[i] == DOWN)
  62. button_states[i] = PRESSED;
  63. return true;
  64. }
  65. state get_key_state(uint16 key)
  66. {
  67. ASSERT(key < INPUT_KEYS_MAX);
  68. return key_states[key];
  69. }
  70. state get_button_state(uint16 button)
  71. {
  72. ASSERT(button < INPUT_BUTTONS_MAX);
  73. return button_states[button];
  74. }
  75. int16 get_wheel_rel()
  76. {
  77. return wheel_rel;
  78. }
  79. void get_cursor_pos(int16 *x, int16 *y)
  80. {
  81. ASSERT(x && y);
  82. POINT pt;
  83. GetCursorPos(&pt);
  84. ScreenToClient(g_app.hwnd, &pt);
  85. *x = (int16)pt.x;
  86. *y = (int16)pt.y;
  87. }
  88. void get_cursor_rel(int16 *xr, int16 *yr)
  89. {
  90. ASSERT(xr && yr);
  91. *xr = cursor_rel[0];
  92. *yr = cursor_rel[1];
  93. }
  94. }
  95. ///////////////////////////////////////////////////////////////////////
  96. uint32 get_config_int(const char* param_name, const char* section, uint32 default_val)
  97. {
  98. return GetPrivateProfileIntA(section,param_name,default_val,CONFIG_FILE);
  99. }
  100. ///////////////////////////////////////////////////////////////////////
  101. inline static int64 get_ticks()
  102. {
  103. int64 ticks;
  104. QueryPerformanceCounter( (LARGE_INTEGER*) &ticks );
  105. return ticks;
  106. }
  107. inline static int64 get_freq()
  108. {
  109. int64 f;
  110. QueryPerformanceFrequency( (LARGE_INTEGER*) &f );
  111. return f;
  112. }
  113. static void time_update()
  114. {
  115. g_app.ticks_cur = get_ticks();
  116. double dt = (g_app.ticks_cur - g_app.ticks_prev) / (double)get_freq();
  117. g_app.time.dt = (float) dt;
  118. g_app.time.T += dt;
  119. g_app.ticks_prev = g_app.ticks_cur;
  120. }
  121. //////////////////////////////////////////////////////////////////////////
  122. static LRESULT APIENTRY wndproc( HWND, UINT, unsigned, long );
  123. static bool init_window()
  124. {
  125. //WNDCLASSA wc = { 0, wndproc, 0, 0, GetModuleHandleA(0), LoadIcon(0,IDI_APPLICATION), LoadCursor(0,IDC_ARROW), (HBRUSH)GetStockObject(NULL_BRUSH), 0, "wndclass.4" };
  126. WNDCLASSA wc = { 0, wndproc, 0, 0, GetModuleHandleA(0), LoadIcon(0,IDI_APPLICATION), LoadCursor(0,IDC_ARROW), (HBRUSH)GetStockObject(WHITE_BRUSH), 0, "wndclass.4" };
  127. RegisterClassA( &wc );
  128. g_app.hwnd = CreateWindowA( "wndclass.4", "Render window", WS_VISIBLE | WS_OVERLAPPEDWINDOW, 100, 100, 800, 600, 0, 0, GetModuleHandleA(0), 0 );
  129. return g_app.hwnd != 0;
  130. }
  131. //////////////////////////////////////////////////////////////////////////
  132. // TODO: add more subsystem init here, in the required order
  133. bool init()
  134. {
  135. g_app.ticks_cur = g_app.ticks_prev = get_ticks();
  136. init_window();
  137. if( !g_app.hwnd )
  138. {
  139. fprintf( stderr, "Error: could not create window\n" );
  140. return false;
  141. }
  142. if (!input::init())
  143. {
  144. log_write("Error: could not initialize input layer\n");
  145. return false;
  146. }
  147. size_t network_pool_sz = get_config_int("network_pool","engine",8 * 1024 * 1024);
  148. if (!network::init(malloc(network_pool_sz), network_pool_sz))
  149. {
  150. fprintf( stderr, "Error: could not initialize network layer\n" );
  151. return false;
  152. }
  153. size_t sound_pool_sz = get_config_int("sound_pool","engine",256 * 1024 * 1024);
  154. size_t sound_decoder_sz = get_config_int("decoder_pool","engine",8 * 1024 * 1024);
  155. if (!snd::init(malloc(sound_pool_sz),sound_pool_sz,sound_decoder_sz))
  156. {
  157. fprintf( stderr, "Error: could not sound system\n" );
  158. return false;
  159. }
  160. RECT rect;
  161. GetClientRect(g_app.hwnd, &rect);
  162. renderer_desc_t renderer_desc;
  163. renderer_desc.depth = D3DFMT_D24X8;
  164. renderer_desc.width = rect.left - rect.right;
  165. renderer_desc.height = rect.bottom - rect.top;
  166. renderer_desc.window = g_app.hwnd;
  167. renderer_desc.windowed = true;
  168. renderer_desc.vsync = false;
  169. renderer_desc.refresh_rate = 0;
  170. renderer_desc.multisampling = 8;
  171. if( renderer::init(renderer_desc) )
  172. {
  173. log_write("Error: could not initialize gfx layer");
  174. return false;
  175. }
  176. if( !test_init() )
  177. {
  178. log_write("Error: test data initialization failed");
  179. return false;
  180. }
  181. // moar!
  182. return true;
  183. }
  184. void term()
  185. {
  186. renderer::term();
  187. network::term();
  188. input::term();
  189. DestroyWindow(g_app.hwnd);
  190. UnregisterClass("wndclass.4", GetModuleHandleA(0));
  191. g_app.hwnd = NULL;
  192. }
  193. // moves the frame
  194. bool tick()
  195. {
  196. MSG msg = {};
  197. while( TRUE == PeekMessageA(&msg,0,0,0,PM_REMOVE ) )
  198. {
  199. if( msg.message == WM_QUIT )
  200. return false;
  201. TranslateMessage( &msg );
  202. DispatchMessageA( &msg );
  203. }
  204. time_update();
  205. // TODO: do stuff
  206. // renderer::tick();
  207. Sleep(5);
  208. return true;
  209. }
  210. // returns timings for the last tick
  211. timings time()
  212. {
  213. return g_app.time;
  214. }
  215. ///////////////////////////////////////////
  216. static LRESULT APIENTRY wndproc( HWND hwnd, UINT msg, UINT wp, LONG lp )
  217. {
  218. static bool dont_resize_yet = false;
  219. static bool resizing = false;
  220. static RECT rcwnd = {0};
  221. static RAWINPUT ri;
  222. static UINT risize;
  223. switch( msg )
  224. {
  225. case WM_CREATE:
  226. GetClientRect( hwnd, &rcwnd );
  227. break;
  228. case WM_DESTROY: PostQuitMessage(0); return 0;
  229. case WM_ENTERSIZEMOVE: break;
  230. case WM_SIZE: break;
  231. case WM_EXITSIZEMOVE: break;
  232. case WM_INPUT:
  233. {
  234. risize = sizeof(ri);
  235. if (GetRawInputData((HRAWINPUT)lp, RID_INPUT, (PBYTE)&ri, &risize, sizeof(RAWINPUTHEADER)) == (UINT)(-1))
  236. return FALSE;
  237. if (ri.header.dwType == RIM_TYPEKEYBOARD && ri.data.keyboard.VKey < INPUT_KEYS_MAX)
  238. {
  239. input::state state = input::key_states[ri.data.keyboard.VKey];
  240. if (ri.data.keyboard.Flags & RI_KEY_BREAK)
  241. state = input::UP;
  242. else if (state == input::UP)
  243. state = input::DOWN;
  244. input::key_states[ri.data.keyboard.VKey] = state;
  245. } else if (ri.header.dwType == RIM_TYPEMOUSE)
  246. {
  247. for (uint32 i = 0, d, u; i < INPUT_BUTTONS_MAX; ++i)
  248. {
  249. input::state state = input::button_states[i];
  250. d = 1 << (i << 1);
  251. u = d << 1;
  252. if ((ri.data.mouse.usButtonFlags & d) && state == input::UP)
  253. state = input::DOWN;
  254. else if (ri.data.mouse.usButtonFlags & u)
  255. state = input::UP;
  256. input::button_states[i] = state;
  257. }
  258. if (ri.data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
  259. input::wheel_rel += (int16)ri.data.mouse.usButtonData;
  260. if (ri.data.mouse.usFlags == MOUSE_MOVE_RELATIVE)
  261. {
  262. input::cursor_rel[0] += (int16)ri.data.mouse.lLastX;
  263. input::cursor_rel[1] += (int16)ri.data.mouse.lLastY;
  264. }
  265. }
  266. return FALSE;
  267. }
  268. }
  269. return DefWindowProcA( hwnd, msg, wp, lp );
  270. }
  271. }