├── .gitignore ├── OS ├── Linux │ └── main.cpp └── win32 │ ├── main.cpp │ └── main.h ├── README.md ├── Resource.h ├── XLEngine ├── Graphics │ ├── CommonGL │ │ ├── graphicsDeviceGL.cpp │ │ ├── graphicsDeviceGL.h │ │ ├── indexBufferGL.cpp │ │ ├── indexBufferGL.h │ │ ├── renderTargetGL.cpp │ │ ├── renderTargetGL.h │ │ ├── shaderGL.cpp │ │ ├── shaderGL.h │ │ ├── streamingVertexBuffer.cpp │ │ ├── streamingVertexBuffer.h │ │ ├── textureGL.cpp │ │ ├── textureGL.h │ │ ├── vertexBufferGL.cpp │ │ └── vertexBufferGL.h │ ├── Devices │ │ ├── graphicsDeviceGL_1_3.cpp │ │ ├── graphicsDeviceGL_1_3.h │ │ ├── graphicsDeviceGL_2_0.cpp │ │ ├── graphicsDeviceGL_2_0.h │ │ ├── graphicsDeviceGL_3_2.cpp │ │ ├── graphicsDeviceGL_3_2.h │ │ ├── graphicsShadersGL_2_0.cpp │ │ └── graphicsShadersGL_2_0.h │ ├── Linux │ │ ├── graphicsDeviceGL_Linux.cpp │ │ └── graphicsDeviceGL_Linux.h │ ├── Win32 │ │ ├── graphicsDeviceGL_Win32.cpp │ │ └── graphicsDeviceGL_Win32.h │ ├── capabilities.h │ ├── graphicsDevice.cpp │ ├── graphicsDevice.h │ ├── graphicsDeviceList.cpp │ ├── graphicsDeviceList.h │ ├── graphicsDevice_Platform.h │ ├── graphicsGL_Inc.h │ ├── graphicsTypes.h │ └── samplerState.h ├── Linux │ ├── clockLinux.cpp │ └── osUtilLinux.cpp ├── Math │ ├── crc32.cpp │ ├── crc32.h │ └── math.h ├── PluginFramework │ ├── dynamicLibrary.cpp │ ├── dynamicLibrary.h │ ├── pluginManager.cpp │ └── pluginManager.h ├── Sound │ ├── fluidsynthDLL.cpp │ ├── fluidsynthDLL.h │ ├── midi.cpp │ ├── midi.h │ ├── oggVorbis.cpp │ ├── oggVorbis.h │ ├── sound.cpp │ ├── sound.h │ ├── sound_inl.h │ ├── vocFormat.cpp │ ├── vocFormat.h │ ├── wavFormat.cpp │ └── wavFormat.h ├── Text │ ├── Inconsolata.otf │ ├── textSystem.cpp │ └── textSystem.h ├── Threads │ ├── Linux │ │ ├── mutexLinux.cpp │ │ ├── mutexLinux.h │ │ ├── threadLinux.cpp │ │ └── threadLinux.h │ ├── Win32 │ │ ├── mutexWin32.cpp │ │ ├── mutexWin32.h │ │ ├── threadWin32.cpp │ │ └── threadWin32.h │ ├── mutex.h │ └── thread.h ├── UI │ ├── draw2D.cpp │ ├── draw2D.h │ ├── uiSystem.cpp │ └── uiSystem.h ├── Win32 │ ├── clockWin32.cpp │ └── osUtilWin32.cpp ├── clock.h ├── filestream.cpp ├── filestream.h ├── gameLoop.cpp ├── gameLoop.h ├── gameUI.cpp ├── gameUI.h ├── imageLoader.cpp ├── imageLoader.h ├── iniReader.cpp ├── iniReader.h ├── iniWriter.cpp ├── iniWriter.h ├── input.cpp ├── input.h ├── log.cpp ├── log.h ├── memoryPool.cpp ├── memoryPool.h ├── osUtil.h ├── services.cpp ├── services.h ├── settings.cpp ├── settings.h ├── stream.h ├── types.h └── xlServices.h ├── buildVersion.txt ├── small.ico ├── stdafx.cpp ├── stdafx.h └── targetver.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | -------------------------------------------------------------------------------- /OS/Linux/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../XLEngine/input.h" 4 | #include "../../XLEngine/clock.h" 5 | #include "../../XLEngine/services.h" 6 | #include "../../XLEngine/settings.h" 7 | #include "../../XLEngine/gameLoop.h" 8 | #include "../../XLEngine/gameUI.h" 9 | #include "../../XLEngine/log.h" 10 | 11 | #include // this includes the necessary X headers 12 | #include // X11 constant (e.g. TrueColor) 13 | #include 14 | #include 15 | 16 | static char s_title[256]; 17 | static Display* s_display = NULL; 18 | 19 | int getScreenSize(int& width, int& height) 20 | { 21 | int num_sizes; 22 | Rotation original_rotation; 23 | 24 | Window root = RootWindow(s_display, 0); 25 | XRRScreenSize *xrrs = XRRSizes(s_display, 0, &num_sizes); 26 | 27 | XRRScreenConfiguration *conf = XRRGetScreenInfo(s_display, root); 28 | short original_rate = XRRConfigCurrentRate(conf); 29 | SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation); 30 | 31 | //xrrs[2] is correct, so I have to figure out how to determine this programmatically. 32 | width = xrrs[original_size_id].width; 33 | height = xrrs[original_size_id].height; 34 | } 35 | 36 | int main(int argc, char **argv) 37 | { 38 | Log::open("Logs/log.txt"); 39 | LOG( LOG_MESSAGE, "Log opened." ); 40 | 41 | // open a connection to the X server 42 | s_display = XOpenDisplay(NULL); 43 | if (s_display == NULL) 44 | { 45 | LOG( LOG_ERROR, "could not open display."); 46 | return 0; 47 | } 48 | 49 | //this will give the resolution of the whole virtual screen if using multiple monitors. 50 | //I'm still looking for a way to get the actual monitor resolution - not the desktop resolution. 51 | //getScreenSize() above returns the same results. 52 | Screen* screen = DefaultScreenOfDisplay(s_display); 53 | int monitorWidth, monitorHeight; 54 | //getScreenSize(monitorWidth, monitorHeight); 55 | monitorWidth = screen->width; 56 | monitorHeight = screen->height; 57 | 58 | //read the settings from disk or apply the defaults and generate a new settings file. 59 | Settings::read(monitorWidth, monitorHeight); 60 | 61 | //get the engine version for display 62 | XLSettings* settings = Settings::get(); 63 | sprintf(s_title, "XL Engine %s", Settings::getVersion()); 64 | LOG( LOG_MESSAGE, s_title ); 65 | 66 | // initialize the game loop 67 | void *win_param[] = { s_display, (void*)settings->windowWidth, (void*)settings->windowHeight }; 68 | if ( !GameLoop::init(win_param, Settings::getGraphicsDeviceID()) ) 69 | { 70 | LOG( LOG_ERROR, "Engine initialization failed! Could not create a graphics device." ); 71 | return 0; 72 | } 73 | 74 | Clock::startTimer(); 75 | 76 | //unfortunately we need to get the display back in order to process window events. 77 | XEvent event; 78 | 79 | // dispatch X events 80 | while (1) 81 | { 82 | //process the window events (input). 83 | //while ( XEventsQueued(s_display, QueuedAlready) > 0 ) 84 | while (XPending(s_display) > 0) 85 | { 86 | XNextEvent(s_display, &event); 87 | switch (event.type) 88 | { 89 | case KeyPress: 90 | { 91 | KeySym keysym; 92 | XKeyEvent *kevent; 93 | char buffer[1]; 94 | 95 | /* It is necessary to convert the keycode to a 96 | * keysym before checking if it is an escape */ 97 | kevent = (XKeyEvent *)&event; 98 | XLookupString((XKeyEvent *)&event, buffer, 1, &keysym, NULL); 99 | //keysym contains the key, XK_Escape for example 100 | break; 101 | } 102 | case ButtonPress: 103 | switch (event.xbutton.button) 104 | { 105 | } 106 | break; 107 | case ConfigureNotify: 108 | break; 109 | case Expose: 110 | break; 111 | } 112 | }; /* loop to compress events */ 113 | 114 | //update 115 | GameLoop::update(); 116 | 117 | //exit if we're done. 118 | if (GameLoop::checkExitGame()) 119 | { 120 | break; 121 | } 122 | } 123 | 124 | return 0; 125 | } 126 | -------------------------------------------------------------------------------- /OS/win32/main.cpp: -------------------------------------------------------------------------------- 1 | // game.cpp : Defines the entry point for the application. 2 | // 3 | 4 | #include "main.h" 5 | #include "../../stdafx.h" 6 | #include "../../XLEngine/input.h" 7 | #include "../../XLEngine/clock.h" 8 | #include "../../XLEngine/services.h" 9 | #include "../../XLEngine/settings.h" 10 | #include "../../XLEngine/gameLoop.h" 11 | #include "../../XLEngine/gameUI.h" 12 | #include "../../XLEngine/log.h" 13 | #include 14 | 15 | #if XL_CHECK_MEMORY 16 | #include 17 | #endif 18 | 19 | #define MAX_LOADSTRING 100 20 | 21 | // Global Variables: 22 | HINSTANCE s_hInst; // current instance 23 | TCHAR s_title[MAX_LOADSTRING]; // The title bar text 24 | TCHAR s_windowClass[MAX_LOADSTRING]; // the main window class name 25 | 26 | // Forward declarations of functions included in this code module: 27 | ATOM MyRegisterClass(HINSTANCE hInstance); 28 | BOOL InitInstance(HWND& hWnd, HINSTANCE hInstance, int nCmdShow); 29 | LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 30 | 31 | int win32MapShiftAndControl( int vkey ); 32 | 33 | int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow) 34 | { 35 | #if XL_CHECK_MEMORY 36 | _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_ALWAYS_DF ); 37 | #endif 38 | 39 | UNREFERENCED_PARAMETER(hPrevInstance); 40 | UNREFERENCED_PARAMETER(lpCmdLine); 41 | 42 | // TODO: Place code here. 43 | MSG msg; 44 | HACCEL hAccelTable; 45 | 46 | Log::open("Logs/log.txt"); 47 | LOG( LOG_MESSAGE, "Log opened." ); 48 | 49 | //read the settings from disk or apply the defaults and generate a new settings file. 50 | int monitorWidth = GetSystemMetrics(SM_CXSCREEN); 51 | int monitorHeight = GetSystemMetrics(SM_CYSCREEN); 52 | Settings::read(monitorWidth, monitorHeight); 53 | 54 | //get the engine version for display 55 | XLSettings* settings = Settings::get(); 56 | sprintf(s_title, "XL Engine %s", Settings::getVersion()); 57 | LOG( LOG_MESSAGE, s_title ); 58 | 59 | LoadString(hInstance, IDC_XLENGINE, s_windowClass, MAX_LOADSTRING); 60 | MyRegisterClass(hInstance); 61 | 62 | // perform application initialization: 63 | HWND hWnd; 64 | if (!InitInstance(hWnd, hInstance, nCmdShow)) 65 | { 66 | Services::xlDebugMessage("InitInstance() failed."); 67 | return FALSE; 68 | } 69 | 70 | hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_XLENGINE)); 71 | 72 | // initialize the game loop 73 | void *win_param[] = { (void *)hWnd }; 74 | if ( !GameLoop::init(win_param, Settings::getGraphicsDeviceID()) ) 75 | { 76 | LOG( LOG_ERROR, "Engine initialization failed! Could not create a graphics device." ); 77 | return 0; 78 | } 79 | 80 | // main message loop: 81 | Clock::startTimer(); 82 | while (true) 83 | { 84 | if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) 85 | { 86 | if ( msg.message == WM_QUIT ) 87 | { 88 | GameLoop::stopGame(); 89 | break; 90 | } 91 | 92 | TranslateMessage(&msg); 93 | DispatchMessage(&msg); 94 | } 95 | else 96 | { 97 | GameLoop::update(); 98 | } 99 | 100 | if (GameLoop::checkExitGame()) 101 | { 102 | break; 103 | } 104 | }; 105 | 106 | GameLoop::destroy(); 107 | 108 | return (int)msg.wParam; 109 | } 110 | 111 | // 112 | // FUNCTION: MyRegisterClass() 113 | // 114 | // PURPOSE: Registers the window class. 115 | // 116 | ATOM MyRegisterClass(HINSTANCE hInstance) 117 | { 118 | WNDCLASSEX wcex; 119 | 120 | wcex.cbSize = sizeof(WNDCLASSEX); 121 | 122 | wcex.style = CS_HREDRAW | CS_VREDRAW; 123 | wcex.lpfnWndProc = WndProc; 124 | wcex.cbClsExtra = 0; 125 | wcex.cbWndExtra = 0; 126 | wcex.hInstance = hInstance; 127 | wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_XLENGINE)); 128 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 129 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 130 | wcex.lpszMenuName = 0; 131 | wcex.lpszClassName = s_windowClass; 132 | wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 133 | 134 | return RegisterClassEx(&wcex); 135 | } 136 | 137 | // 138 | // FUNCTION: InitInstance(HINSTANCE, int) 139 | // 140 | // PURPOSE: Saves instance handle and creates main window 141 | // 142 | // COMMENTS: 143 | // 144 | // In this function, we save the instance handle in a global variable and 145 | // create and display the main program window. 146 | // 147 | BOOL InitInstance(HWND& hWnd, HINSTANCE hInstance, int nCmdShow) 148 | { 149 | s_hInst = hInstance; // Store instance handle in our global variable 150 | 151 | //The window style. 152 | DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX; 153 | XLSettings* settings = Settings::get(); 154 | if ( settings->flags&XL_FLAG_FULLSCREEN ) 155 | { 156 | dwStyle = WS_POPUP; //for fullscreen just display the client area. 157 | settings->windowWidth = GetSystemMetrics(SM_CXSCREEN); 158 | settings->windowHeight = GetSystemMetrics(SM_CYSCREEN); 159 | } 160 | 161 | //compute the final window size to get a specific client window size. 162 | RECT desiredSize; 163 | desiredSize.left = 0; 164 | desiredSize.top = 0; 165 | desiredSize.right = settings->windowWidth; 166 | desiredSize.bottom = settings->windowHeight; 167 | AdjustWindowRect(&desiredSize, dwStyle, FALSE); 168 | 169 | hWnd = CreateWindow(s_windowClass, s_title, dwStyle, 0, 0, desiredSize.right-desiredSize.left, desiredSize.bottom-desiredSize.top, NULL, NULL, hInstance, NULL); 170 | if (!hWnd) 171 | { 172 | return FALSE; 173 | } 174 | 175 | ShowWindow(hWnd, nCmdShow); 176 | UpdateWindow(hWnd); 177 | 178 | GameUI::enableCursor( true ); 179 | return TRUE; 180 | } 181 | 182 | // 183 | // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) 184 | // 185 | // PURPOSE: Processes messages for the main window. 186 | // 187 | // WM_COMMAND - process the application menu 188 | // WM_PAINT - Paint the main window 189 | // WM_DESTROY - post a quit message and return 190 | // 191 | // 192 | LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 193 | { 194 | int wmId, wmEvent; 195 | PAINTSTRUCT ps; 196 | HDC hdc; 197 | 198 | XLEngineServices* services = Services::get(); 199 | 200 | switch (message) 201 | { 202 | case WM_COMMAND: 203 | wmId = LOWORD(wParam); 204 | wmEvent = HIWORD(wParam); 205 | // Parse the menu selections: 206 | switch (wmId) 207 | { 208 | case IDM_EXIT: 209 | DestroyWindow(hWnd); 210 | break; 211 | default: 212 | return DefWindowProc(hWnd, message, wParam, lParam); 213 | } 214 | break; 215 | case WM_PAINT: 216 | hdc = BeginPaint(hWnd, &ps); 217 | EndPaint(hWnd, &ps); 218 | break; 219 | case WM_KEYDOWN: 220 | case WM_KEYUP: 221 | { 222 | if (wParam >= 0 && wParam < 256) 223 | { 224 | Input::setKeyState(u32(wParam), (message==WM_KEYDOWN)); 225 | } 226 | 227 | int keyCode = win32MapShiftAndControl( (int)wParam ); 228 | if (services->keyEvent) 229 | { 230 | keyCode = Input::mapVirtualKey(keyCode); 231 | if (keyCode > 0) 232 | { 233 | services->keyEvent(0, keyCode, (message==WM_KEYDOWN) ? 1 : 0); 234 | } 235 | } 236 | } 237 | break; 238 | case WM_LBUTTONDOWN: 239 | case WM_LBUTTONUP: 240 | Input::setMouseButtonState(Input::MouseLeft, (message==WM_LBUTTONDOWN)); 241 | break; 242 | case WM_RBUTTONDOWN: 243 | case WM_RBUTTONUP: 244 | Input::setMouseButtonState(Input::MouseRight, (message==WM_RBUTTONDOWN)); 245 | break; 246 | case WM_MBUTTONDOWN: 247 | case WM_MBUTTONUP: 248 | Input::setMouseButtonState(Input::MouseMiddle, (message==WM_MBUTTONDOWN)); 249 | break; 250 | case WM_XBUTTONDOWN: 251 | case WM_XBUTTONUP: 252 | //to-do 253 | break; 254 | case WM_MOUSEMOVE: 255 | Input::setMousePos( s16(lParam), s16(lParam >> 16) ); 256 | break; 257 | case WM_MOUSEWHEEL: 258 | Input::incMouseWheel( ((short)HIWORD(wParam)) > 0 ? 1 : -1 ); 259 | break; 260 | case WM_CHAR: 261 | if (wParam > 0 && wParam < 128) 262 | { 263 | Input::addChar( char(wParam) ); 264 | } 265 | 266 | if (services->keyEvent) 267 | { 268 | services->keyEvent(wParam&0x7f, 0, 1); 269 | } 270 | break; 271 | case WM_DESTROY: 272 | PostQuitMessage(0); 273 | break; 274 | default: 275 | return DefWindowProc(hWnd, message, wParam, lParam); 276 | } 277 | return 0; 278 | } 279 | 280 | int win32MapShiftAndControl( int vkey ) 281 | { 282 | if ( vkey == VK_SHIFT ) 283 | { 284 | if ( GetAsyncKeyState(VK_LSHIFT) < 0 ) 285 | { 286 | vkey = VK_LSHIFT; 287 | } 288 | else if ( GetAsyncKeyState(VK_RSHIFT) < 0 ) 289 | { 290 | vkey = VK_RSHIFT; 291 | } 292 | } 293 | else if ( vkey == VK_CONTROL ) 294 | { 295 | if ( GetAsyncKeyState(VK_LCONTROL) < 0 ) 296 | { 297 | vkey = VK_LCONTROL; 298 | } 299 | else if ( GetAsyncKeyState(VK_RCONTROL) < 0 ) 300 | { 301 | vkey = VK_RCONTROL; 302 | } 303 | } 304 | return vkey; 305 | } 306 | -------------------------------------------------------------------------------- /OS/win32/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../resource.h" 4 | #define XL_CHECK_MEMORY 0 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Depracation & Replacement 2 | I am sure the few people who have looked at this repository have noticed that I have not made any commits in quite some time. The XL Engine, as it was previously known, has been retired. Development of the XL Engine had dropped off due to other "real life" commitments and a lack of time (and sometimes ability) to continue. Fortunately Daggerfall and Blood have high quality ports/projects that have carried on and given people a much improved experience, similar to what the XL Engine was trying to achieve. 3 | 4 | To be clear, this project has not been updated in years and will not be updated in the future - though some of the code will find its way elsewhere. 5 | 6 | Since those days (years ago now), things have changed drastically. The original idea behind DarkXL, which eventually led to the XL Engine, was never completely abandoned and a new project has been in development for a while that is more focused and better designed to achieve my original goals. I'm being intentionally vague because I want to deliver rather than promise and the project is likely still a few months out from a formal unveiling (and yes it will be open source from day 1). 7 | 8 | I notice that some people still star this repository and fork it from time to time, even now. That is what prompted me to post this update so people don't waste their time. I will leave the original text in place for 'historical' value. 9 | 10 | 11 | # XL-Engine 12 | The XL Engine provides support for first person DOS-era games running on modern operating systems such as Windows 10. The first Beta release will support the following games: 13 | ``` 14 | Daggerfall 15 | Dark Forces 16 | Blood 17 | ``` 18 | Source ports are a great way of keeping games such as Doom and Duke Nukem 3D working and even being enhanced on modern systems. While the XL Engine may support games with source available in the future, its primary goal is to support games with no source released with "source port accuracy." Many great older games may never see a source release but they still deserve to be preserved and enhanced. 19 | 20 | The XL Engine is designed to be easy to use, easy to play the supported games on modern systems. It handles modern GPUs, varying refresh rates, high resolutions with high performance. In the future, the engine will add support for easy modding and easy multiplayer support for those games that support it (such as Blood). In the future this will include built-in tools, including scripting and reviving the DarkXL sector editor so that games such as Dark Forces and Blood can be modded with modern tools. 21 | 22 | However this is only an engine, no games are bundled with the application. Games need to be legally acquired before they can be played using the XL Engine. The good news is that Daggerfall is now free and can be downloaded from Bethesda or using Daggerfall Setup. Blood and Dark Forces are available for purchase from GOG.com and Steam. 23 | 24 | # Availability 25 | This project has been depracated. 26 | Beta 1 is still in progress and is not yet available for download. Older builds are avaiable on the XL Engine website, however they are incomplete and buggy. I would suggest waiting for the Beta 1 release before downloading. 27 | 28 | 29 | # Short Term Roadmap 30 | Milestone | Content 31 | ------------- | ------------- 32 | Beta 1 | the initial release, all the games previously stated should be working at 100% with the exception of multi-player. As stated before only software rendering will be available but higher resolutions will be supported. 33 | Beta 2 | the OpenGL 3.2 device should be implemented and true 3D hardware rendering support added – basically Daggerfall will surpass previous builds visually in addition to being gameplay complete. 34 | Beta 3 | the “Unified Sector Theory” release – perspective correct hardware rendering for 2.5D games. At this point Dark Forces should surpass the current build visually in addition to being gameplay complete. 35 | Beta 4 | will add support for additional platforms – Linux and OS X. 36 | Beta 5 | the "Multiplayer" release - add multiplayer framework and support for certain games (such as Blood). 37 | -------------------------------------------------------------------------------- /Resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by ShadowWarriorXL.rc 4 | // 5 | 6 | #define IDS_APP_TITLE 103 7 | 8 | #define IDR_MAINFRAME 128 9 | #define IDD_XLENGINE_DIALOG 102 10 | #define IDD_ABOUTBOX 103 11 | #define IDM_ABOUT 104 12 | #define IDM_EXIT 105 13 | #define IDI_XLENGINE 107 14 | #define IDI_SMALL 108 15 | #define IDC_XLENGINE 109 16 | #define IDC_MYICON 2 17 | #ifndef IDC_STATIC 18 | #define IDC_STATIC -1 19 | #endif 20 | // Next default values for new objects 21 | // 22 | #ifdef APSTUDIO_INVOKED 23 | #ifndef APSTUDIO_READONLY_SYMBOLS 24 | 25 | #define _APS_NO_MFC 130 26 | #define _APS_NEXT_RESOURCE_VALUE 129 27 | #define _APS_NEXT_COMMAND_VALUE 32771 28 | #define _APS_NEXT_CONTROL_VALUE 1000 29 | #define _APS_NEXT_SYMED_VALUE 110 30 | #endif 31 | #endif 32 | -------------------------------------------------------------------------------- /XLEngine/Graphics/CommonGL/graphicsDeviceGL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../log.h" 3 | #include "graphicsDeviceGL.h" 4 | #include "../graphicsGL_Inc.h" 5 | #include "textureGL.h" 6 | #include "renderTargetGL.h" 7 | #include "shaderGL.h" 8 | 9 | #include 10 | 11 | ///////////////////////////////////////// 12 | // Implementation 13 | ///////////////////////////////////////// 14 | GraphicsDeviceGL::GraphicsDeviceGL(GraphicsDevicePlatform* platform) : GraphicsDevice(platform) 15 | { 16 | ShaderGL::init(); 17 | m_bufferIndex = 0; 18 | m_writeFrame = 0; 19 | m_renderFrame = 0; 20 | 21 | m_frameBuffer_32bpp[0] = NULL; 22 | m_frameBuffer_32bpp[1] = NULL; 23 | 24 | m_bufferMutex = Mutex::create(); 25 | } 26 | 27 | GraphicsDeviceGL::~GraphicsDeviceGL() 28 | { 29 | for (size_t r=0; rpresent(); 48 | } 49 | 50 | void GraphicsDeviceGL::queryExtensions() 51 | { 52 | if (!(m_caps.flags&CAP_RENDER_TARGET) && m_platform->queryExtension("GL_EXT_framebuffer_object")) 53 | { 54 | m_caps.flags |= CAP_RENDER_TARGET; 55 | LOG( LOG_MESSAGE, "glExtension enabled: \"GL_EXT_framebuffer_object\"" ); 56 | } 57 | 58 | if (!(m_caps.flags&CAP_NON_POWER_2_TEX) && m_platform->queryExtension("GL_ARB_texture_non_power_of_two")) 59 | { 60 | m_caps.flags |= CAP_NON_POWER_2_TEX; 61 | LOG( LOG_MESSAGE, "glExtension enabled: \"GL_ARB_texture_non_power_of_two\"" ); 62 | } 63 | 64 | glGetIntegerv(GL_MAX_TEXTURE_SIZE, (s32*)&m_caps.maxTextureSize2D); 65 | LOG( LOG_MESSAGE, "Maximum 2D Texture size: %u", m_caps.maxTextureSize2D ); 66 | } 67 | 68 | void GraphicsDeviceGL::setWindowData(int nParam, void** param) 69 | { 70 | m_platform->setWindowData(nParam, param, m_deviceID); 71 | glClearColor(0, 0, 0, 0); 72 | 73 | //default vsync to off for now. 74 | m_platform->enableVSync(false); 75 | } 76 | 77 | void GraphicsDeviceGL::clear() 78 | { 79 | glClear( GL_COLOR_BUFFER_BIT ); 80 | } 81 | 82 | void GraphicsDeviceGL::setBlendMode(BlendMode mode) 83 | { 84 | const u32 srcBlend[] = { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE }; //OVER, ALPHA ADD, ADD 85 | const u32 dstBlend[] = { GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE }; 86 | 87 | glBlendFunc(srcBlend[mode], dstBlend[mode]); 88 | } 89 | 90 | void GraphicsDeviceGL::enableBlending(bool enable) 91 | { 92 | if (enable) 93 | { 94 | glEnable(GL_BLEND); 95 | } 96 | else 97 | { 98 | glDisable(GL_BLEND); 99 | } 100 | } 101 | 102 | void GraphicsDeviceGL::lockBuffer() 103 | { 104 | m_bufferMutex->lock(); 105 | } 106 | 107 | void GraphicsDeviceGL::unlockBuffer() 108 | { 109 | m_bufferMutex->unlock(); 110 | } 111 | 112 | void GraphicsDeviceGL::convertFrameBufferTo32bpp(u8* source, u32* pal) 113 | { 114 | lockBuffer(); 115 | const s32 curIndex = m_bufferIndex; 116 | const u32 pixelCount = m_frameWidth*m_frameHeight; 117 | 118 | u32* dest = m_frameBuffer_32bpp[curIndex]; 119 | const u32* end = &dest[ pixelCount ]; 120 | 121 | for (; dest != end; dest++, source++) 122 | { 123 | *dest = pal[ *source ]; 124 | } 125 | 126 | m_writeBufferIndex = m_bufferIndex; 127 | m_bufferIndex = (m_bufferIndex+1)&1; 128 | m_writeFrame++; 129 | unlockBuffer(); 130 | } 131 | 132 | TextureHandle GraphicsDeviceGL::createTextureRGBA(u32 width, u32 height, const u32* data, const SamplerState& initSamplerState, bool dynamic) 133 | { 134 | TextureGL* texture = createTextureRGBA_Internal(width, height, data, initSamplerState, dynamic); 135 | return texture ? texture->getHandle() : INVALID_TEXTURE_HANDLE; 136 | } 137 | 138 | void GraphicsDeviceGL::destroyTexture(TextureHandle texHandle) 139 | { 140 | u32 index = u32( texHandle ); 141 | if (index >= m_textures.size()) 142 | { 143 | return; 144 | } 145 | 146 | destroyTexture_Internal(index); 147 | } 148 | 149 | RenderTargetHandle GraphicsDeviceGL::createRenderTarget(u32 width, u32 height, const SamplerState& initSamplerState) 150 | { 151 | u32 newID = m_renderTargets.size(); 152 | if (m_freeRenderTargets.size()) 153 | { 154 | newID = m_freeRenderTargets.back(); 155 | } 156 | 157 | TextureGL* texture = createTexture_Internal(); 158 | if (!texture) 159 | { 160 | return NULL; 161 | } 162 | 163 | RenderTargetGL* renderTarget = new RenderTargetGL(newID, texture); 164 | renderTarget->create(this, 0, width, height, initSamplerState); 165 | 166 | if (newID != m_renderTargets.size()) 167 | { 168 | m_renderTargets[newID] = renderTarget; 169 | m_freeRenderTargets.pop_back(); 170 | } 171 | else 172 | { 173 | m_renderTargets.push_back( renderTarget ); 174 | } 175 | 176 | return renderTarget->getHandle(); 177 | } 178 | 179 | void GraphicsDeviceGL::destroyRenderTarget(RenderTargetHandle rtHandle) 180 | { 181 | u32 index = u32( rtHandle ); 182 | if (index >= m_renderTargets.size()) 183 | { 184 | return; 185 | } 186 | 187 | destroyRenderTarget_Internal(index); 188 | } 189 | 190 | void GraphicsDeviceGL::bindRenderTarget(RenderTargetHandle handle) 191 | { 192 | if (handle == INVALID_TEXTURE_HANDLE) 193 | { 194 | return; 195 | } 196 | 197 | const u32 index = u32( handle ); 198 | RenderTargetGL* renderTarget = m_renderTargets[ index ]; 199 | assert( renderTarget ); 200 | 201 | //clear out the current texture 202 | setTexture( INVALID_TEXTURE_HANDLE, 0 ); 203 | setTexture( INVALID_TEXTURE_HANDLE, 1 ); 204 | 205 | renderTarget->bind(); 206 | glViewport( 0, 0, renderTarget->getWidth(), renderTarget->getHeight() ); 207 | } 208 | 209 | void GraphicsDeviceGL::unbindRenderTarget() 210 | { 211 | RenderTargetGL::unbind(); 212 | glViewport( m_fullViewport[0], m_fullViewport[1], m_fullViewport[2], m_fullViewport[3] ); 213 | } 214 | 215 | TextureHandle GraphicsDeviceGL::getRenderTargetTexture(RenderTargetHandle handle) 216 | { 217 | if (handle == INVALID_TEXTURE_HANDLE) 218 | { 219 | return NULL; 220 | } 221 | 222 | const u32 index = u32( handle ); 223 | RenderTargetGL* renderTarget = m_renderTargets[ index ]; 224 | assert( renderTarget ); 225 | 226 | TextureGL* texture = renderTarget->getTexture(); 227 | assert(texture); 228 | 229 | return texture->getHandle(); 230 | } 231 | 232 | void GraphicsDeviceGL::setTexture(TextureHandle handle, int slot/*=0*/) 233 | { 234 | if (handle == INVALID_TEXTURE_HANDLE) 235 | { 236 | TextureGL::unbind(slot); 237 | return; 238 | } 239 | 240 | const u32 index = u32( handle ); 241 | m_textures[index]->bind(slot); 242 | } 243 | 244 | void GraphicsDeviceGL::enableTexturing(bool enable) 245 | { 246 | if (enable) 247 | { 248 | glEnable(GL_TEXTURE_2D); 249 | } 250 | else 251 | { 252 | glDisable(GL_TEXTURE_2D); 253 | } 254 | } 255 | 256 | ///////////////////////////////////////// 257 | // Internal Functions 258 | ///////////////////////////////////////// 259 | TextureGL* GraphicsDeviceGL::createTexture_Internal(bool dynamic/*=false*/) 260 | { 261 | u32 newID = m_textures.size(); 262 | if (m_freeTextures.size()) 263 | { 264 | newID = m_freeTextures.back(); 265 | } 266 | 267 | TextureGL* texture = new TextureGL(newID, dynamic); 268 | 269 | if (newID != m_textures.size()) 270 | { 271 | m_textures[newID] = texture; 272 | m_freeTextures.pop_back(); 273 | } 274 | else 275 | { 276 | m_textures.push_back( texture ); 277 | } 278 | 279 | return texture; 280 | } 281 | 282 | TextureGL* GraphicsDeviceGL::createTextureRGBA_Internal(u32 width, u32 height, const u32* data, const SamplerState& initSamplerState, bool dynamic/*=false*/) 283 | { 284 | TextureGL* texture = createTexture_Internal(dynamic); 285 | if (!texture) 286 | { 287 | return NULL; 288 | } 289 | 290 | if (!texture->createRGBA(this, width, height, data, initSamplerState)) 291 | { 292 | destroyTexture( texture->getHandle() ); 293 | return NULL; 294 | } 295 | 296 | return texture; 297 | } 298 | 299 | void GraphicsDeviceGL::destroyTexture_Internal(u32 index) 300 | { 301 | delete m_textures[index]; 302 | 303 | m_textures[index] = NULL; 304 | m_freeTextures.push_back(index); 305 | } 306 | 307 | void GraphicsDeviceGL::destroyRenderTarget_Internal(u32 index) 308 | { 309 | TextureGL* texture = m_renderTargets[index]->getTexture(); 310 | if (texture) 311 | { 312 | destroyTexture( texture->getHandle() ); 313 | } 314 | 315 | delete m_renderTargets[index]; 316 | 317 | m_renderTargets[index] = NULL; 318 | m_freeRenderTargets.push_back(index); 319 | } 320 | -------------------------------------------------------------------------------- /XLEngine/Graphics/CommonGL/graphicsDeviceGL.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************************************** 2 | Common OpenGL functionality between all OpenGL based Graphics Devices. 3 | Anything that can be pulled into common code will reduce the amount of code duplication and the 4 | potential for errors. 5 | ******************************************************************************************************/ 6 | #pragma once 7 | 8 | #include "../graphicsDevice.h" 9 | #include "../../Threads/mutex.h" 10 | #include 11 | 12 | #define BUFFER_OFFSET(i) ((char *)NULL + (i)) 13 | class TextureGL; 14 | class RenderTargetGL; 15 | 16 | class GraphicsDeviceGL : public GraphicsDevice 17 | { 18 | friend class ShaderGL; 19 | 20 | public: 21 | GraphicsDeviceGL(GraphicsDevicePlatform* platform); 22 | virtual ~GraphicsDeviceGL(); 23 | 24 | //common functionality implemented by this class. 25 | virtual void setWindowData(int nParam, void** param); 26 | virtual void present(); 27 | virtual void clear(); 28 | virtual void setBlendMode(BlendMode mode); 29 | virtual void enableBlending(bool enable); 30 | virtual void enableTexturing(bool enable); 31 | virtual void convertFrameBufferTo32bpp(u8* source, u32* pal); 32 | 33 | virtual TextureHandle createTextureRGBA(u32 width, u32 height, const u32* data, const SamplerState& initSamplerState, bool dynamic=false); 34 | virtual void destroyTexture(TextureHandle texHandle); 35 | 36 | virtual RenderTargetHandle createRenderTarget(u32 width, u32 height, const SamplerState& initSamplerState); 37 | virtual void destroyRenderTarget(RenderTargetHandle rtHandle); 38 | 39 | virtual void queryExtensions(); 40 | 41 | virtual void bindRenderTarget(RenderTargetHandle handle); 42 | virtual void unbindRenderTarget(); 43 | virtual TextureHandle getRenderTargetTexture(RenderTargetHandle handle); 44 | 45 | //functionality that must be implemented by specific OpenGL based Graphics Devices. 46 | virtual void setShader(ShaderID shader)=0; 47 | 48 | virtual bool init(int w, int h, int& vw, int& vh)=0; 49 | virtual void drawVirtualScreen()=0; 50 | 51 | virtual void clearShaderParamCache()=0; 52 | virtual void setShaderResource(TextureHandle handle, u32 nameHash, u32 slot=0)=0; 53 | virtual void setShaderParameter(void* data, u32 size, u32 nameHash)=0; 54 | 55 | virtual void drawQuad(const Quad& quad)=0; 56 | virtual void drawFullscreenQuad(TextureGL* tex)=0; 57 | 58 | virtual void setVirtualViewport(bool reset, int x, int y, int w, int h)=0; 59 | 60 | //batching (not used by all devices) 61 | virtual void flush() {}; 62 | virtual u32 addQuad(const Quad& quad) { return 0; } 63 | virtual void drawQuadBatch(u32 vertexOffset, u32 count) {}; 64 | 65 | protected: 66 | typedef std::vector TextureList; 67 | typedef std::vector RenderTargetList; 68 | typedef std::vector FreeList; 69 | 70 | virtual void setTexture(TextureHandle handle, int slot=0); 71 | TextureGL* createTexture_Internal(bool dynamic=false); 72 | TextureGL* createTextureRGBA_Internal(u32 width, u32 height, const u32* data, const SamplerState& initSamplerState, bool dynamic=false); 73 | 74 | void destroyTexture_Internal(u32 index); 75 | void destroyRenderTarget_Internal(u32 index); 76 | 77 | void lockBuffer(); 78 | void unlockBuffer(); 79 | 80 | s32 m_windowWidth; 81 | s32 m_windowHeight; 82 | s32 m_frameWidth; 83 | s32 m_frameHeight; 84 | u32* m_frameBuffer_32bpp[2]; 85 | 86 | s32 m_bufferIndex; 87 | s32 m_writeBufferIndex; 88 | s32 m_writeFrame; 89 | s32 m_renderFrame; 90 | 91 | s32 m_virtualViewport[4]; 92 | s32 m_virtualViewportNoUI[4]; 93 | s32 m_fullViewport[4]; 94 | 95 | TextureGL* m_videoFrameBuffer; 96 | TextureList m_textures; 97 | RenderTargetList m_renderTargets; 98 | 99 | FreeList m_freeTextures; 100 | FreeList m_freeRenderTargets; 101 | 102 | Mutex* m_bufferMutex; 103 | private: 104 | }; 105 | -------------------------------------------------------------------------------- /XLEngine/Graphics/CommonGL/indexBufferGL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "indexBufferGL.h" 4 | #include "../graphicsGL_Inc.h" 5 | #include "../../log.h" 6 | 7 | #include 8 | 9 | IndexBufferGL::IndexBufferGL() 10 | { 11 | glGenBuffers(1, &m_glID); 12 | 13 | m_size = 0; 14 | m_stride = 0; 15 | m_count = 0; 16 | } 17 | 18 | IndexBufferGL::~IndexBufferGL() 19 | { 20 | glDeleteBuffers(1, &m_glID); 21 | } 22 | 23 | bool IndexBufferGL::allocate(u32 stride, u32 count, void* data/*=NULL*/) 24 | { 25 | m_size = stride*count; 26 | m_stride = stride; 27 | m_count = count; 28 | 29 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_glID); 30 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_size, data, GL_STATIC_DRAW); 31 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 32 | 33 | return true; 34 | } 35 | 36 | void IndexBufferGL::update(u32 size, void* data) 37 | { 38 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_glID); 39 | 40 | //cause the "discard" buffer behavior, which is done by first calling glBufferData() with NULL data. 41 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_size, NULL, GL_STATIC_DRAW); 42 | 43 | //now lock and update the buffer. 44 | void* mem = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); 45 | if ( mem ) 46 | { 47 | memcpy(mem, data, std::min(size, m_size)); 48 | } 49 | glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); 50 | 51 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 52 | } 53 | 54 | void IndexBufferGL::bind() 55 | { 56 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_glID); 57 | } 58 | 59 | void IndexBufferGL::clear() 60 | { 61 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 62 | } 63 | -------------------------------------------------------------------------------- /XLEngine/Graphics/CommonGL/indexBufferGL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "graphicsDeviceGL.h" 5 | 6 | class IndexBufferGL 7 | { 8 | public: 9 | IndexBufferGL(); 10 | virtual ~IndexBufferGL(); 11 | 12 | bool allocate(u32 stride, u32 count, void* data=NULL); 13 | void update(u32 size, void* data); 14 | 15 | void bind(); 16 | 17 | //clear the vertex data 18 | static void clear(); 19 | 20 | public: 21 | u32 m_glID; 22 | u32 m_size; 23 | u32 m_stride; 24 | u32 m_count; 25 | }; 26 | -------------------------------------------------------------------------------- /XLEngine/Graphics/CommonGL/renderTargetGL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "renderTargetGL.h" 3 | #include "../graphicsGL_Inc.h" 4 | #include "../../log.h" 5 | 6 | 7 | RenderTargetGL::RenderTargetGL(RenderTargetHandle handle, TextureGL* texture) 8 | { 9 | m_handle = handle; 10 | m_texture = texture; 11 | 12 | m_glID = 0; 13 | m_glDepthID = 0; 14 | } 15 | 16 | RenderTargetGL::~RenderTargetGL() 17 | { 18 | //make sure the render target is not current bound. 19 | unbind(); 20 | //the depth buffer 21 | if (m_glDepthID) 22 | { 23 | glDeleteRenderbuffersEXT(1, &m_glDepthID); 24 | } 25 | //and finally the frame buffer object itself. 26 | glDeleteFramebuffersEXT(1, &m_glID); 27 | } 28 | 29 | //the initial version will not support depth buffers. 30 | bool RenderTargetGL::create(const GraphicsDevice* gdev, u32 createFlags, u32 width, u32 height, const SamplerState& initSamplerState) 31 | { 32 | m_width = width; 33 | m_height = height; 34 | 35 | //create the color texture 36 | m_texture->createRGBA(gdev, width, height, NULL, initSamplerState); 37 | 38 | //create the frame buffer object 39 | glGenFramebuffersEXT(1, &m_glID); 40 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_glID); 41 | 42 | //attach 2D texture to this FBO 43 | glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture->m_glID, 0); 44 | 45 | //create the depth buffer if requested 46 | if (createFlags & RT_CREATE_DEPTH) 47 | { 48 | //create the depth buffer (render buffer, not texture) 49 | glGenRenderbuffersEXT(1, &m_glDepthID); 50 | glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_glDepthID); 51 | glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height); 52 | //attach depth buffer to FBO 53 | glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_glDepthID); 54 | } 55 | 56 | //Does the GPU support current FBO configuration? 57 | GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 58 | if (status != GL_FRAMEBUFFER_COMPLETE_EXT) 59 | { 60 | LOG( LOG_ERROR, "RenderTargetGL create failed! Status = %x", status ); 61 | return false; 62 | } 63 | 64 | return true; 65 | } 66 | 67 | void RenderTargetGL::bind() 68 | { 69 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_glID); 70 | } 71 | 72 | void RenderTargetGL::unbind() 73 | { 74 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 75 | } 76 | 77 | TextureGL* RenderTargetGL::getTexture() 78 | { 79 | return m_texture; 80 | } 81 | -------------------------------------------------------------------------------- /XLEngine/Graphics/CommonGL/renderTargetGL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | ////////////////////////////////////////////// 3 | // Very basic Render Target implementation 4 | // Currently only supports 1 RGBA color buffer 5 | // and no depth 6 | ////////////////////////////////////////////// 7 | 8 | #include "graphicsDeviceGL.h" 9 | #include "textureGL.h" 10 | #include "../samplerState.h" 11 | 12 | //TO-DO: 13 | //Add support for multiple color buffers 14 | //Add support for different formats 15 | //Add support for depth textures 16 | 17 | enum RenderTargetCreateFlags 18 | { 19 | RT_CREATE_DEPTH = (1<<0), 20 | }; 21 | 22 | class RenderTargetGL 23 | { 24 | public: 25 | RenderTargetGL(RenderTargetHandle handle, TextureGL* texture); 26 | virtual ~RenderTargetGL(); 27 | 28 | //the initial version will not support depth buffers. 29 | bool create(const GraphicsDevice* gdev, u32 createFlags, u32 width, u32 height, const SamplerState& initSamplerState); 30 | 31 | void bind(); 32 | static void unbind(); 33 | 34 | TextureGL* getTexture(); 35 | RenderTargetHandle getHandle() const { return m_handle; } 36 | 37 | u32 getWidth() const { return m_width; } 38 | u32 getHeight() const { return m_height; } 39 | 40 | private: 41 | u32 m_glID; 42 | u32 m_glDepthID; 43 | TextureGL* m_texture; 44 | 45 | u32 m_width; 46 | u32 m_height; 47 | 48 | RenderTargetHandle m_handle; 49 | }; 50 | -------------------------------------------------------------------------------- /XLEngine/Graphics/CommonGL/shaderGL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "graphicsDeviceGL.h" 4 | #include 5 | 6 | enum ShaderStage 7 | { 8 | SHADER_VERTEX = 0, 9 | SHADER_PIXEL, 10 | SHADER_STAGE_COUNT 11 | }; 12 | 13 | struct ShaderParam 14 | { 15 | u32 nameHash; 16 | s32 glID; 17 | 18 | u32 type; 19 | u32 size; 20 | void* data; 21 | 22 | TextureHandle texHandle; 23 | }; 24 | 25 | typedef std::map ParameterMap; 26 | 27 | class ShaderGL 28 | { 29 | public: 30 | ShaderGL(); 31 | virtual ~ShaderGL(); 32 | 33 | bool load(const char* vsShader, const char* psShader); 34 | 35 | void bind(); 36 | void uploadData(GraphicsDevice* device); 37 | 38 | s32 getParameter(const char* name) const; 39 | s32 getParameter(u32 nameHash) const; 40 | void updateParameter(s32 id, void* data, u32 size); 41 | void updateParameter(s32 id, TextureHandle texture, u32 slot, bool force=false); 42 | void clearParamCache(); 43 | 44 | u32 getRequiredVertexAttrib() const { return m_requiredVtxAttrib; } 45 | 46 | static void init(); 47 | static void destroy(); 48 | static void clear(); 49 | 50 | protected: 51 | u32 m_glShaderID; 52 | u32 m_shaderParamCount; 53 | u32 m_requiredVtxAttrib; 54 | 55 | ShaderParam* m_param; 56 | u64 m_stateDirty; //bitfield: which parameters are dirty (param 3 = 1<<3) 57 | 58 | ParameterMap m_paramMap; 59 | private: 60 | bool compileShader(const char* vsShader, const char* psShader); 61 | bool compileShaderStage(u32& handle, ShaderStage stage, const char *path); 62 | }; 63 | -------------------------------------------------------------------------------- /XLEngine/Graphics/CommonGL/streamingVertexBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "streamingVertexBuffer.h" 2 | #include "vertexBufferGL.h" 3 | #include "../../log.h" 4 | 5 | #include 6 | #include 7 | 8 | StreamingVertexBuffer::StreamingVertexBuffer(const VertexElement* vertexDecl, u32 declCount, u32 stride, u32 maxVertexCount) 9 | { 10 | m_bufferSize = stride*maxVertexCount; 11 | m_buffer = (u8*)malloc( m_bufferSize ); 12 | m_bufferIndex = 0; 13 | m_bufferOffset = 0; 14 | m_stride = stride; 15 | 16 | m_lastError = STREAMING_VERTEX_OK; 17 | 18 | for (s32 b=0; ballocate( stride, maxVertexCount, NULL ); 22 | m_glBuffers[b]->setVertexDecl( vertexDecl, declCount ); 23 | } 24 | } 25 | 26 | StreamingVertexBuffer::~StreamingVertexBuffer() 27 | { 28 | for (s32 b=0; bupdate( m_bufferOffset, m_buffer ); 39 | 40 | outVertexCount = m_bufferOffset / m_stride; 41 | 42 | m_bufferOffset = 0; 43 | m_bufferIndex = (m_bufferIndex+1)%STREAMING_BUFFER_COUNT; 44 | 45 | return buffer; 46 | } 47 | 48 | u32 StreamingVertexBuffer::addVertices(const void* vertices, u32 count) 49 | { 50 | const u32 size = m_stride * count; 51 | if (m_bufferOffset + size > m_bufferSize) 52 | { 53 | //Too many vertices. 54 | LOG( LOG_ERROR, "StreamingVertexBuffer - too many vertices requested, memory requested %u of %u.", m_bufferOffset+size, m_bufferSize ); 55 | return STREAMING_VERTEX_TOOMANY; 56 | } 57 | 58 | const u32 offset = m_bufferOffset; 59 | memcpy(&m_buffer[offset], vertices, size); 60 | m_bufferOffset += size; 61 | 62 | return offset / m_stride; 63 | } 64 | 65 | void* StreamingVertexBuffer::getWritePointer(u32 count, u32& outOffset) 66 | { 67 | const u32 size = m_stride * count; 68 | if (m_bufferOffset + size > m_bufferSize) 69 | { 70 | //Too many vertices. 71 | LOG( LOG_ERROR, "StreamingVertexBuffer - too many vertices requested, memory requested %u of %u.", m_bufferOffset+size, m_bufferSize ); 72 | return NULL; 73 | } 74 | 75 | outOffset = m_bufferOffset / m_stride; 76 | void* outBuffer = &m_buffer[ m_bufferOffset ]; 77 | m_bufferOffset += size; 78 | 79 | return outBuffer; 80 | } 81 | 82 | u32 StreamingVertexBuffer::getError() 83 | { 84 | u32 lastError = m_lastError; 85 | m_lastError = STREAMING_VERTEX_OK; 86 | return lastError; 87 | } 88 | -------------------------------------------------------------------------------- /XLEngine/Graphics/CommonGL/streamingVertexBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "graphicsDeviceGL.h" 4 | 5 | struct VertexElement; 6 | class VertexBufferGL; 7 | 8 | #define STREAMING_BUFFER_COUNT 2 9 | //Errors 10 | #define STREAMING_VERTEX_OK 0 11 | #define STREAMING_VERTEX_TOOMANY 0xffffffff 12 | 13 | class StreamingVertexBuffer 14 | { 15 | public: 16 | StreamingVertexBuffer(const VertexElement* vertexDecl, u32 declCount, u32 stride, u32 maxVertexCount); 17 | ~StreamingVertexBuffer(); 18 | 19 | VertexBufferGL* update(u32& outVertexCount); 20 | 21 | u32 addVertices(const void* vertices, u32 count); 22 | void* getWritePointer(u32 count, u32& outOffset); 23 | 24 | u32 getError(); 25 | 26 | private: 27 | u8* m_buffer; 28 | u32 m_bufferOffset; 29 | u32 m_bufferIndex; 30 | u32 m_stride; 31 | u32 m_bufferSize; 32 | u32 m_lastError; 33 | VertexBufferGL* m_glBuffers[STREAMING_BUFFER_COUNT]; 34 | }; -------------------------------------------------------------------------------- /XLEngine/Graphics/CommonGL/textureGL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "textureGL.h" 3 | #include "../../log.h" 4 | #include "../../Math/math.h" 5 | #include "../graphicsGL_Inc.h" 6 | 7 | #include 8 | #include 9 | 10 | TextureGL::TextureGL(TextureHandle handle, bool dynamic) 11 | { 12 | m_dynamic = dynamic; 13 | m_glID = 0; 14 | m_width = 0; 15 | m_height = 0; 16 | m_handle = handle; 17 | m_updateBuffer = NULL; 18 | } 19 | 20 | TextureGL::~TextureGL() 21 | { 22 | if (m_glID) 23 | { 24 | glDeleteTextures(1, &m_glID); 25 | } 26 | free(m_updateBuffer); 27 | } 28 | 29 | void TextureGL::bind(u32 slot) 30 | { 31 | glActiveTexture(GL_TEXTURE0 + slot); 32 | glBindTexture(GL_TEXTURE_2D, GLuint(m_glID)); 33 | } 34 | 35 | void TextureGL::unbind(u32 slot) 36 | { 37 | glActiveTexture(GL_TEXTURE0 + slot); 38 | glBindTexture(GL_TEXTURE_2D, 0); 39 | } 40 | 41 | bool TextureGL::createRGBA(const GraphicsDevice* gdev, u32 width, u32 height, const u32* data, const SamplerState& initSamplerState) 42 | { 43 | glGenTextures(1, &m_glID); 44 | glBindTexture(GL_TEXTURE_2D, m_glID); 45 | 46 | setSamplerState_Internal(initSamplerState); 47 | 48 | //if this device does not support non-power of 2 textures, we need to round up to the next power of 2. 49 | u32* finalData = (u32*)data; 50 | if ( !gdev->supportsFeature(CAP_NON_POWER_2_TEX) ) 51 | { 52 | u32 newWidth = Math::nextPow2(width); 53 | u32 newHeight = Math::nextPow2(height); 54 | 55 | if (data && (newWidth != width || newHeight != height)) 56 | { 57 | allocateUpdateBuffer(newWidth, newHeight); 58 | u32* buffer = m_updateBuffer; 59 | for (u32 y=0; y 6 | #include 7 | 8 | const char* VertexBufferGL::c_vertexAttrib[]= 9 | { 10 | "in_position", 11 | "in_normal", 12 | "in_color", 13 | "in_texcoord0", 14 | "in_texcoord1", 15 | "in_texcoord2", 16 | "in_texcoord3", 17 | }; 18 | 19 | const u32 c_vertexTypeSize[] = 20 | { 21 | //floating point types, can not be normalized. 22 | sizeof(s16)*1, //VTYPE_FLOAT16_1 = 0, 23 | sizeof(s16)*2, //VTYPE_FLOAT16_2, 24 | sizeof(s16)*3, //VTYPE_FLOAT16_3, 25 | sizeof(s16)*4, //VTYPE_FLOAT16_4, 26 | sizeof(f32)*1, //VTYPE_FLOAT32_1, 27 | sizeof(f32)*2, //VTYPE_FLOAT32_2, 28 | sizeof(f32)*3, //VTYPE_FLOAT32_3, 29 | sizeof(f32)*4, //VTYPE_FLOAT32_4, 30 | sizeof(f64)*1, //VTYPE_FLOAT64_1, 31 | sizeof(f64)*2, //VTYPE_FLOAT64_2, 32 | sizeof(f64)*3, //VTYPE_FLOAT64_3, 33 | sizeof(f64)*4, //VTYPE_FLOAT64_4, 34 | sizeof(s32)*1, //VTYPE_FIXED32_1, //16.16 fixed point 35 | sizeof(s32)*2, //VTYPE_FIXED32_2, 36 | sizeof(s32)*3, //VTYPE_FIXED32_3, 37 | sizeof(s32)*4, //VTYPE_FIXED32_4, 38 | //Integer types, may be normalized. 39 | sizeof(s8)*1, //VTYPE_INT8_1, 40 | sizeof(s8)*2, //VTYPE_INT8_2, 41 | sizeof(s8)*4, //VTYPE_INT8_4, 42 | sizeof(u8)*1, //VTYPE_UINT8_1, 43 | sizeof(u8)*2, //VTYPE_UINT8_2, 44 | sizeof(u8)*4, //VTYPE_UINT8_4, 45 | sizeof(s16)*1, //VTYPE_INT16_1, 46 | sizeof(s16)*2, //VTYPE_INT16_2, 47 | sizeof(s16)*4, //VTYPE_INT16_4, 48 | sizeof(u16)*1, //VTYPE_UINT16_1, 49 | sizeof(u16)*2, //VTYPE_UINT16_2, 50 | sizeof(u16)*4, //VTYPE_UINT16_4, 51 | sizeof(s32)*1, //VTYPE_INT32_1, 52 | sizeof(s32)*2, //VTYPE_INT32_2, 53 | sizeof(s32)*4, //VTYPE_INT32_4, 54 | sizeof(u32)*1, //VTYPE_UINT32_1, 55 | sizeof(u32)*2, //VTYPE_UINT32_2, 56 | sizeof(u32)*4, //VTYPE_UINT32_4, 57 | //Mixed types 58 | sizeof(u32)*1, //VTYPE_INT_2_10_10_10_REV, //4 signed components - 2 bits, 10 bits * 3 59 | sizeof(u32)*1, //VTYPE_UINT_2_10_10_10_REV, //4 unsigned components - 2 bits, 10 bits * 3 60 | }; 61 | 62 | const u32 c_vertexTypeCount[] = 63 | { 64 | //floating point types, can not be normalized. 65 | 1, //VTYPE_FLOAT16_1 = 0, 66 | 2, //VTYPE_FLOAT16_2, 67 | 3, //VTYPE_FLOAT16_3, 68 | 4, //VTYPE_FLOAT16_4, 69 | 1, //VTYPE_FLOAT32_1, 70 | 2, //VTYPE_FLOAT32_2, 71 | 3, //VTYPE_FLOAT32_3, 72 | 4, //VTYPE_FLOAT32_4, 73 | 1, //VTYPE_FLOAT64_1, 74 | 2, //VTYPE_FLOAT64_2, 75 | 3, //VTYPE_FLOAT64_3, 76 | 4, //VTYPE_FLOAT64_4, 77 | 1, //VTYPE_FIXED32_1, //16.16 fixed point 78 | 2, //VTYPE_FIXED32_2, 79 | 3, //VTYPE_FIXED32_3, 80 | 4, //VTYPE_FIXED32_4, 81 | //Integer types, may be normalized. 82 | 1, //VTYPE_INT8_1, 83 | 2, //VTYPE_INT8_2, 84 | 4, //VTYPE_INT8_4, 85 | 1, //VTYPE_UINT8_1, 86 | 2, //VTYPE_UINT8_2, 87 | 4, //VTYPE_UINT8_4, 88 | 1, //VTYPE_INT16_1, 89 | 2, //VTYPE_INT16_2, 90 | 4, //VTYPE_INT16_4, 91 | 1, //VTYPE_UINT16_1, 92 | 2, //VTYPE_UINT16_2, 93 | 4, //VTYPE_UINT16_4, 94 | 1, //VTYPE_INT32_1, 95 | 2, //VTYPE_INT32_2, 96 | 4, //VTYPE_INT32_4, 97 | 1, //VTYPE_UINT32_1, 98 | 2, //VTYPE_UINT32_2, 99 | 4, //VTYPE_UINT32_4, 100 | //Mixed types 101 | 4, //VTYPE_INT_2_10_10_10_REV, //4 signed components - 2 bits, 10 bits * 3 102 | 4, //VTYPE_UINT_2_10_10_10_REV, //4 unsigned components - 2 bits, 10 bits * 3 103 | }; 104 | 105 | const u32 c_vertexGLType[] = 106 | { 107 | //floating point types, can not be normalized. 108 | GL_HALF_FLOAT, //VTYPE_FLOAT16_1 = 0, 109 | GL_HALF_FLOAT, //VTYPE_FLOAT16_2, 110 | GL_HALF_FLOAT, //VTYPE_FLOAT16_3, 111 | GL_HALF_FLOAT, //VTYPE_FLOAT16_4, 112 | GL_FLOAT, //VTYPE_FLOAT32_1, 113 | GL_FLOAT, //VTYPE_FLOAT32_2, 114 | GL_FLOAT, //VTYPE_FLOAT32_3, 115 | GL_FLOAT, //VTYPE_FLOAT32_4, 116 | GL_DOUBLE, //VTYPE_FLOAT64_1, 117 | GL_DOUBLE, //VTYPE_FLOAT64_2, 118 | GL_DOUBLE, //VTYPE_FLOAT64_3, 119 | GL_DOUBLE, //VTYPE_FLOAT64_4, 120 | GL_FIXED, //VTYPE_FIXED32_1, //16.16 fixed point 121 | GL_FIXED, //VTYPE_FIXED32_2, 122 | GL_FIXED, //VTYPE_FIXED32_3, 123 | GL_FIXED, //VTYPE_FIXED32_4, 124 | //Integer types, may be normalized. 125 | GL_BYTE, //VTYPE_INT8_1, 126 | GL_BYTE, //VTYPE_INT8_2, 127 | GL_BYTE, //VTYPE_INT8_4, 128 | GL_UNSIGNED_BYTE, //VTYPE_UINT8_1, 129 | GL_UNSIGNED_BYTE, //VTYPE_UINT8_2, 130 | GL_UNSIGNED_BYTE, //VTYPE_UINT8_4, 131 | GL_SHORT, //VTYPE_INT16_1, 132 | GL_SHORT, //VTYPE_INT16_2, 133 | GL_SHORT, //VTYPE_INT16_4, 134 | GL_UNSIGNED_SHORT, //VTYPE_UINT16_1, 135 | GL_UNSIGNED_SHORT, //VTYPE_UINT16_2, 136 | GL_UNSIGNED_SHORT, //VTYPE_UINT16_4, 137 | GL_INT, //VTYPE_INT32_1, 138 | GL_INT, //VTYPE_INT32_2, 139 | GL_INT, //VTYPE_INT32_4, 140 | GL_UNSIGNED_INT, //VTYPE_UINT32_1, 141 | GL_UNSIGNED_INT, //VTYPE_UINT32_2, 142 | GL_UNSIGNED_INT, //VTYPE_UINT32_4, 143 | //Mixed types 144 | GL_INT_2_10_10_10_REV, //VTYPE_INT_2_10_10_10_REV, //4 signed components - 2 bits, 10 bits * 3 145 | GL_UNSIGNED_INT_2_10_10_10_REV, //VTYPE_UINT_2_10_10_10_REV, //4 unsigned components - 2 bits, 10 bits * 3 146 | }; 147 | 148 | VertexBufferGL::VertexBufferGL(bool dynamic) 149 | { 150 | glGenBuffers(1, &m_glID); 151 | m_dynamic = dynamic; 152 | 153 | m_vertexDecl = NULL; 154 | 155 | m_size = 0; 156 | m_stride = 0; 157 | m_count = 0; 158 | m_elemCount = 0; 159 | } 160 | 161 | VertexBufferGL::~VertexBufferGL() 162 | { 163 | glDeleteBuffers(1, &m_glID); 164 | delete [] m_vertexDecl; 165 | } 166 | 167 | bool VertexBufferGL::setVertexDecl(const VertexElement* vertexDecl, u32 count) 168 | { 169 | m_elemCount = count; 170 | m_vertexDecl = new VertexElement[ count ]; 171 | if (!m_vertexDecl) 172 | { 173 | return false; 174 | } 175 | 176 | u32 offset = 0; 177 | for (u32 v=0; v 0) 181 | { 182 | m_vertexDecl[v].offset = offset; 183 | } 184 | else 185 | { 186 | offset = m_vertexDecl[v].offset; 187 | } 188 | 189 | offset += c_vertexTypeSize[ m_vertexDecl[v].type ]; 190 | } 191 | 192 | return true; 193 | } 194 | 195 | bool VertexBufferGL::allocate(u32 stride, u32 count, void* data/*=NULL*/) 196 | { 197 | m_size = stride*count; 198 | m_stride = stride; 199 | m_count = count; 200 | 201 | glBindBuffer(GL_ARRAY_BUFFER, m_glID); 202 | glBufferData(GL_ARRAY_BUFFER, m_size, data, m_dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); 203 | glBindBuffer(GL_ARRAY_BUFFER, 0); 204 | 205 | return true; 206 | } 207 | 208 | void VertexBufferGL::update(u32 size, void* data) 209 | { 210 | glBindBuffer(GL_ARRAY_BUFFER, m_glID); 211 | 212 | //cause the "discard" buffer behavior, which is done by first calling glBufferData() with NULL data. 213 | glBufferData(GL_ARRAY_BUFFER, std::min(size, m_size), NULL, m_dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); 214 | 215 | //now lock and update the buffer. 216 | void* mem = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); 217 | if ( mem ) 218 | { 219 | memcpy(mem, data, std::min(size, m_size)); 220 | } 221 | glUnmapBuffer(GL_ARRAY_BUFFER); 222 | 223 | glBindBuffer(GL_ARRAY_BUFFER, 0); 224 | } 225 | 226 | void VertexBufferGL::bind(u32 requiredAttributes) 227 | { 228 | glBindBuffer(GL_ARRAY_BUFFER, m_glID); 229 | 230 | bool slotEnabled[ VATTR_COUNT ] = {false}; 231 | //enable used slots and setup the format. 232 | for (u32 v=0; v 5 | 6 | enum VertexAttributes 7 | { 8 | VATTR_POSITION = 0, 9 | VATTR_NORMAL, 10 | VATTR_COLOR, 11 | VATTR_TEXCOORD0, 12 | VATTR_TEXCOORD1, 13 | VATTR_TEXCOORD2, 14 | VATTR_TEXCOORD3, 15 | VATTR_COUNT 16 | }; 17 | 18 | enum VertexAttrFlags 19 | { 20 | VAFLAG_POSITION = (1<<0), 21 | VAFLAG_NORMAL = (1<<1), 22 | VAFLAG_COLOR = (1<<2), 23 | VAFLAG_TEXCOORD0 = (1<<3), 24 | VAFLAG_TEXCOORD1 = (1<<4), 25 | VAFLAG_TEXCOORD2 = (1<<5), 26 | VAFLAG_TEXCOORD3 = (1<<6), 27 | }; 28 | 29 | enum VertexAttrType 30 | { 31 | //floating point types, can not be normalized. 32 | VTYPE_FLOAT16_1 = 0, 33 | VTYPE_FLOAT16_2, 34 | VTYPE_FLOAT16_3, 35 | VTYPE_FLOAT16_4, 36 | VTYPE_FLOAT32_1, 37 | VTYPE_FLOAT32_2, 38 | VTYPE_FLOAT32_3, 39 | VTYPE_FLOAT32_4, 40 | VTYPE_FLOAT64_1, 41 | VTYPE_FLOAT64_2, 42 | VTYPE_FLOAT64_3, 43 | VTYPE_FLOAT64_4, 44 | VTYPE_FIXED32_1, //16.16 fixed point 45 | VTYPE_FIXED32_2, 46 | VTYPE_FIXED32_3, 47 | VTYPE_FIXED32_4, 48 | //Integer types, may be normalized. 49 | VTYPE_INT8_1, 50 | VTYPE_INT8_2, 51 | VTYPE_INT8_4, 52 | VTYPE_UINT8_1, 53 | VTYPE_UINT8_2, 54 | VTYPE_UINT8_4, 55 | VTYPE_INT16_1, 56 | VTYPE_INT16_2, 57 | VTYPE_INT16_4, 58 | VTYPE_UINT16_1, 59 | VTYPE_UINT16_2, 60 | VTYPE_UINT16_4, 61 | VTYPE_INT32_1, 62 | VTYPE_INT32_2, 63 | VTYPE_INT32_4, 64 | VTYPE_UINT32_1, 65 | VTYPE_UINT32_2, 66 | VTYPE_UINT32_4, 67 | //Mixed types 68 | VTYPE_INT_2_10_10_10_REV, //4 signed components - 2 bits, 10 bits * 3 69 | VTYPE_UINT_2_10_10_10_REV, //4 unsigned components - 2 bits, 10 bits * 3 70 | }; 71 | 72 | struct VertexElement 73 | { 74 | u32 offset; //offset from the base, use 0 to calculate automatically. 75 | VertexAttributes attr; 76 | VertexAttrType type; 77 | bool normalized; 78 | }; 79 | 80 | class VertexBufferGL 81 | { 82 | public: 83 | VertexBufferGL(bool dynamic); 84 | virtual ~VertexBufferGL(); 85 | 86 | bool setVertexDecl(const VertexElement* vertexDecl, u32 count); 87 | bool allocate(u32 stride, u32 count, void* data=NULL); 88 | void update(u32 size, void* data); 89 | 90 | void bind(u32 requiredAttributes); 91 | 92 | //clear the vertex data 93 | static void clear(); 94 | 95 | public: 96 | static const char* c_vertexAttrib[]; 97 | u32 m_vertexAttrFlags; 98 | u32 m_glID; 99 | u32 m_size; 100 | u32 m_stride; 101 | u32 m_count; 102 | 103 | bool m_dynamic; 104 | 105 | VertexElement* m_vertexDecl; 106 | u32 m_elemCount; 107 | }; 108 | -------------------------------------------------------------------------------- /XLEngine/Graphics/Devices/graphicsDeviceGL_1_3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "graphicsDeviceGL_1_3.h" 3 | #include "../CommonGL/textureGL.h" 4 | #include "../../log.h" 5 | #include "../graphicsGL_Inc.h" 6 | 7 | GraphicsDeviceGL_1_3::GraphicsDeviceGL_1_3(GraphicsDevicePlatform* platform) : GraphicsDeviceGL(platform) 8 | { 9 | m_deviceID = GDEV_OPENGL_1_3; 10 | } 11 | 12 | GraphicsDeviceGL_1_3::~GraphicsDeviceGL_1_3() 13 | { 14 | delete [] m_frameBuffer_32bpp[0]; 15 | delete [] m_frameBuffer_32bpp[1]; 16 | } 17 | 18 | void GraphicsDeviceGL_1_3::drawVirtualScreen() 19 | { 20 | glViewport( m_virtualViewport[0], m_virtualViewport[1], m_virtualViewport[2], m_virtualViewport[3] ); 21 | 22 | //update the video memory framebuffer. 23 | lockBuffer(); 24 | if (m_writeFrame > m_renderFrame) 25 | { 26 | m_videoFrameBuffer->update( m_frameWidth, m_frameHeight, m_frameBuffer_32bpp[m_writeBufferIndex] ); 27 | } 28 | m_renderFrame = m_writeFrame; 29 | unlockBuffer(); 30 | 31 | enableBlending(false); 32 | drawFullscreenQuad(m_videoFrameBuffer); 33 | 34 | glViewport( m_fullViewport[0], m_fullViewport[1], m_fullViewport[2], m_fullViewport[3] ); 35 | } 36 | 37 | void GraphicsDeviceGL_1_3::setVirtualViewport(bool reset, int x, int y, int w, int h) 38 | { 39 | if (reset) 40 | { 41 | for (int i=0; i<4; i++) { m_virtualViewport[i] = m_virtualViewportNoUI[i]; } 42 | } 43 | else 44 | { 45 | m_virtualViewport[0] = x; 46 | m_virtualViewport[1] = y; 47 | m_virtualViewport[2] = w; 48 | m_virtualViewport[3] = h; 49 | } 50 | } 51 | 52 | bool GraphicsDeviceGL_1_3::init(int w, int h, int& vw, int& vh) 53 | { 54 | m_platform->init(); 55 | queryExtensions(); 56 | 57 | //we need to support at least 512x512 textures in order to get 320x200 or 320x240 58 | if (m_caps.maxTextureSize2D < 512) 59 | { 60 | LOG( LOG_ERROR, "The OpenGL 1.3 graphics device does not support at least 512x512 textures which is required by the XL Engine." ); 61 | return false; 62 | } 63 | 64 | //clamp the virtual screen by the maximum texture size. 65 | while (vw > (s32)m_caps.maxTextureSize2D || vh > (s32)m_caps.maxTextureSize2D) 66 | { 67 | vw >>= 1; 68 | vh >>= 1; 69 | } 70 | 71 | glDisable(GL_DEPTH_TEST); /* enable depth buffering */ 72 | 73 | glMatrixMode(GL_MODELVIEW); 74 | glLoadIdentity(); 75 | 76 | glMatrixMode(GL_PROJECTION); 77 | glLoadIdentity(); 78 | 79 | /* establish initial viewport */ 80 | // fix the height to the actual screen height. 81 | // calculate the width such that wxh has a 4:3 aspect ratio (assume square pixels for modern LCD monitors). 82 | // offset the viewport by half the difference between the actual width and 4x3 width 83 | // to automatically pillar box the display. 84 | // Unfortunately, for modern monitors, only 1200p yields exact integer scaling. So we do all the scaling on 85 | // the horizontal axis, where there are more pixels, to limit the visible distortion. 86 | int w4x3 = (h<<2) / 3; 87 | int dw = w - w4x3; 88 | m_virtualViewportNoUI[0] = dw>>1; 89 | m_virtualViewportNoUI[1] = 0; 90 | m_virtualViewportNoUI[2] = w4x3; 91 | m_virtualViewportNoUI[3] = h; 92 | 93 | for (int i=0; i<4; i++) { m_virtualViewport[i] = m_virtualViewportNoUI[i]; } 94 | 95 | m_fullViewport[0] = 0; 96 | m_fullViewport[1] = 0; 97 | m_fullViewport[2] = w; 98 | m_fullViewport[3] = h; 99 | 100 | m_windowWidth = w; 101 | m_windowHeight = h; 102 | 103 | //frame size - this is the 32 bit version of the framebuffer. The 8 bit framebuffer, rendered by the software renderer, 104 | //is converted to 32 bit (using the current palette) - this buffer - before being uploaded to the video card. 105 | m_frameWidth = vw; 106 | m_frameHeight = vh; 107 | m_frameBuffer_32bpp[0] = new u32[ m_frameWidth*m_frameHeight ]; 108 | m_frameBuffer_32bpp[1] = new u32[ m_frameWidth*m_frameHeight ]; 109 | 110 | //Create a copy of the framebuffer on the GPU so we can upload the results there. 111 | const SamplerState samplerState= 112 | { 113 | WM_CLAMP, WM_CLAMP, WM_CLAMP, //clamp on every axis 114 | TEXFILTER_LINEAR, TEXFILTER_POINT, TEXFILTER_POINT, //filtering 115 | false //no mipmapping 116 | }; 117 | m_videoFrameBuffer = createTextureRGBA_Internal(m_frameWidth, m_frameHeight, NULL, samplerState); 118 | enableTexturing(true); 119 | 120 | glFlush(); 121 | 122 | return true; 123 | } 124 | 125 | void GraphicsDeviceGL_1_3::setShader(ShaderID shader) 126 | { 127 | shader; //do nothing 128 | } 129 | 130 | void GraphicsDeviceGL_1_3::clearShaderParamCache() 131 | { 132 | //do nothing. 133 | } 134 | 135 | void GraphicsDeviceGL_1_3::setShaderResource(TextureHandle handle, u32 nameHash, u32 slot) 136 | { 137 | setTexture(handle); 138 | } 139 | 140 | void GraphicsDeviceGL_1_3::setShaderParameter(void* data, u32 size, u32 nameHash) 141 | { 142 | data; //do nothing. 143 | } 144 | 145 | void GraphicsDeviceGL_1_3::drawQuad(const Quad& quad) 146 | { 147 | //scale and display. 148 | float posScale[] = {-1.0f, -1.0f, 2.0f, 2.0f}; 149 | float uvTop[] = { 0, 1 }; 150 | float uvBot[] = { 1, 0 }; 151 | 152 | posScale[0] = 2.0f * float(quad.p0.x) / float(m_windowWidth) - 1.0f; 153 | posScale[1] = -2.0f * float(quad.p0.y) / float(m_windowHeight) + 1.0f; 154 | 155 | posScale[2] = 2.0f * float(quad.p1.x) / float(m_windowWidth) - 1.0f; 156 | posScale[3] = -2.0f * float(quad.p1.y) / float(m_windowHeight) + 1.0f; 157 | 158 | uvTop[0] = quad.uv0.x; 159 | uvTop[1] = quad.uv0.y; 160 | uvBot[0] = quad.uv1.x; 161 | uvBot[1] = quad.uv1.y; 162 | 163 | glBegin(GL_QUADS); 164 | glColor4ubv((GLubyte*)&quad.color); 165 | 166 | glTexCoord2f(uvTop[0], uvTop[1]); 167 | glVertex3f(posScale[0], posScale[1], -1.0f); 168 | glTexCoord2f(uvBot[0], uvTop[1]); 169 | glVertex3f(posScale[2], posScale[1], -1.0f); 170 | 171 | glTexCoord2f(uvBot[0], uvBot[1]); 172 | glVertex3f(posScale[2], posScale[3], -1.0f); 173 | glTexCoord2f(uvTop[0], uvBot[1]); 174 | glVertex3f(posScale[0], posScale[3], -1.0f); 175 | glEnd(); 176 | } 177 | 178 | void GraphicsDeviceGL_1_3::drawFullscreenQuad(TextureGL* tex) 179 | { 180 | f32 u0 = 0.0f, v0 = 0.0f; 181 | f32 u1 = 1.0f, v1 = 1.0f; 182 | 183 | tex->bind(0); 184 | if ( !supportsFeature(CAP_NON_POWER_2_TEX) ) 185 | { 186 | u32 w, h; 187 | tex->getDimensions(w, h); 188 | u1 = f32(m_frameWidth) / f32(w); 189 | v1 = f32(m_frameHeight) / f32(h); 190 | } 191 | 192 | u32 white = 0xffffffff; 193 | glBegin(GL_QUADS); 194 | glColor4ubv((GLubyte*)&white); 195 | 196 | glTexCoord2f(u0, v0); 197 | glVertex3f(-1.0f, 1.0f, -1.0f); 198 | glTexCoord2f(u1, v0); 199 | glVertex3f( 1.0f, 1.0f, -1.0f); 200 | 201 | glTexCoord2f(u1, v1); 202 | glVertex3f( 1.0f, -1.0f, -1.0f); 203 | glTexCoord2f(u0, v1); 204 | glVertex3f(-1.0f, -1.0f, -1.0f); 205 | glEnd(); 206 | } 207 | -------------------------------------------------------------------------------- /XLEngine/Graphics/Devices/graphicsDeviceGL_1_3.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../CommonGL/graphicsDeviceGL.h" 4 | 5 | class GraphicsDeviceGL_1_3 : public GraphicsDeviceGL 6 | { 7 | public: 8 | GraphicsDeviceGL_1_3(GraphicsDevicePlatform* platform); 9 | virtual ~GraphicsDeviceGL_1_3(); 10 | 11 | bool init(int w, int h, int& vw, int& vh); 12 | 13 | void setShader(ShaderID shader); 14 | 15 | void clearShaderParamCache(); 16 | void setShaderResource(TextureHandle handle, u32 nameHash, u32 slot=0); 17 | void setShaderParameter(void* data, u32 size, u32 nameHash); 18 | 19 | void drawQuad(const Quad& quad); 20 | void drawFullscreenQuad(TextureGL* tex); 21 | 22 | void drawVirtualScreen(); 23 | void setVirtualViewport(bool reset, int x, int y, int w, int h); 24 | }; 25 | -------------------------------------------------------------------------------- /XLEngine/Graphics/Devices/graphicsDeviceGL_2_0.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../CommonGL/graphicsDeviceGL.h" 4 | 5 | class GraphicsShadersGL_2_0; 6 | class StreamingVertexBuffer; 7 | class VertexBufferGL; 8 | class IndexBufferGL; 9 | class ShaderGL; 10 | 11 | class GraphicsDeviceGL_2_0 : public GraphicsDeviceGL 12 | { 13 | public: 14 | GraphicsDeviceGL_2_0(GraphicsDevicePlatform* platform); 15 | virtual ~GraphicsDeviceGL_2_0(); 16 | 17 | bool init(int w, int h, int& vw, int& vh); 18 | 19 | void setShader(ShaderID shader); 20 | 21 | void clearShaderParamCache(); 22 | void setShaderResource(TextureHandle handle, u32 nameHash, u32 slot=0); 23 | void setShaderParameter(void* data, u32 size, u32 nameHash); 24 | void drawQuad(const Quad& quad); 25 | void drawFullscreenQuad(TextureGL* tex); 26 | 27 | void drawVirtualScreen(); 28 | void setVirtualViewport(bool reset, int x, int y, int w, int h); 29 | 30 | //batching 31 | void flush(); 32 | u32 addQuad(const Quad& quad); 33 | void drawQuadBatch(u32 vertexOffset, u32 count); 34 | protected: 35 | GraphicsShadersGL_2_0* m_shaders; 36 | StreamingVertexBuffer* m_quadVB; 37 | IndexBufferGL* m_quadIB; 38 | 39 | ShaderGL* m_curShader; 40 | u32 m_curShaderID; 41 | 42 | //batching 43 | VertexBufferGL* m_streamBuffer; 44 | u32 m_streamVertexCount; 45 | }; 46 | -------------------------------------------------------------------------------- /XLEngine/Graphics/Devices/graphicsDeviceGL_3_2.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////// 2 | // This is only a stub 3 | // TO-DO: implement 4 | ///////////////////////// 5 | #include 6 | #include "graphicsDeviceGL_3_2.h" 7 | #include "../../log.h" 8 | #include "../graphicsGL_Inc.h" 9 | 10 | 11 | GraphicsDeviceGL_3_2::GraphicsDeviceGL_3_2(GraphicsDevicePlatform* platform) : GraphicsDeviceGL(platform) 12 | { 13 | m_deviceID = GDEV_OPENGL_3_2; 14 | m_caps.flags |= CAP_SUPPORT_SHADERS; 15 | m_caps.flags |= CAP_RENDER_TARGET; 16 | m_caps.flags |= CAP_NON_POWER_2_TEX; 17 | } 18 | 19 | GraphicsDeviceGL_3_2::~GraphicsDeviceGL_3_2() 20 | { 21 | } 22 | 23 | void GraphicsDeviceGL_3_2::drawVirtualScreen() 24 | { 25 | } 26 | 27 | void GraphicsDeviceGL_3_2::setVirtualViewport(bool reset, int x, int y, int w, int h) 28 | { 29 | } 30 | 31 | bool GraphicsDeviceGL_3_2::init(int w, int h, int& vw, int& vh) 32 | { 33 | return false; 34 | } 35 | 36 | void GraphicsDeviceGL_3_2::setShader(ShaderID shader) 37 | { 38 | } 39 | 40 | void GraphicsDeviceGL_3_2::clearShaderParamCache() 41 | { 42 | } 43 | 44 | void GraphicsDeviceGL_3_2::setShaderResource(TextureHandle handle, u32 nameHash, u32 slot) 45 | { 46 | } 47 | 48 | void GraphicsDeviceGL_3_2::setShaderParameter(void* data, u32 size, u32 nameHash) 49 | { 50 | } 51 | 52 | void GraphicsDeviceGL_3_2::drawQuad(const Quad& quad) 53 | { 54 | } 55 | 56 | void GraphicsDeviceGL_3_2::drawFullscreenQuad(TextureGL* tex) 57 | { 58 | } 59 | -------------------------------------------------------------------------------- /XLEngine/Graphics/Devices/graphicsDeviceGL_3_2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../CommonGL/graphicsDeviceGL.h" 4 | 5 | class GraphicsDeviceGL_3_2 : public GraphicsDeviceGL 6 | { 7 | public: 8 | GraphicsDeviceGL_3_2(GraphicsDevicePlatform* platform); 9 | virtual ~GraphicsDeviceGL_3_2(); 10 | 11 | bool init(int w, int h, int& vw, int& vh); 12 | 13 | void setShader(ShaderID shader); 14 | 15 | void clearShaderParamCache(); 16 | void setShaderResource(TextureHandle handle, u32 nameHash, u32 slot=0); 17 | void setShaderParameter(void* data, u32 size, u32 nameHash); 18 | void drawQuad(const Quad& quad); 19 | void drawFullscreenQuad(TextureGL* tex); 20 | 21 | void drawVirtualScreen(); 22 | void setVirtualViewport(bool reset, int x, int y, int w, int h); 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /XLEngine/Graphics/Devices/graphicsShadersGL_2_0.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////// 2 | // This is only a stub 3 | // TO-DO: implement 4 | ///////////////////////// 5 | #include 6 | #include "graphicsShadersGL_2_0.h" 7 | #include "../../log.h" 8 | 9 | const char* GraphicsShadersGL_2_0::m_shaderVS[SHADER_COUNT]= 10 | { 11 | "Shaders/quadUI_20.vp", //SHADER_QUAD_UI 12 | "Shaders/quadUI_20.vp", //SHADER_QUAD_COLOR_CORRECT 13 | "Shaders/downSampleBlur.vp", //SHADER_BLUR 14 | "Shaders/uiGlow.vp", //SHADER_GLOW_UI 15 | }; 16 | 17 | const char* GraphicsShadersGL_2_0::m_shaderPS[SHADER_COUNT]= 18 | { 19 | "Shaders/quadUI_20.fp", //SHADER_QUAD_UI 20 | "Shaders/quadUI_ColorCorrect_20.fp", //SHADER_QUAD_COLOR_CORRECT 21 | "Shaders/downSampleBlur.fp", //SHADER_BLUR 22 | "Shaders/uiGlow.fp", //SHADER_GLOW_UI 23 | }; 24 | 25 | 26 | GraphicsShadersGL_2_0::GraphicsShadersGL_2_0() 27 | { 28 | for (u32 s=0; sload( m_shaderVS[s], m_shaderPS[s] ); 47 | } 48 | } 49 | 50 | ShaderGL* GraphicsShadersGL_2_0::getShader( ShaderID shader ) 51 | { 52 | if (shader < 0 || shader > SHADER_COUNT) 53 | { 54 | return NULL; 55 | } 56 | 57 | return m_shaders[ shader ]; 58 | } 59 | -------------------------------------------------------------------------------- /XLEngine/Graphics/Devices/graphicsShadersGL_2_0.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../CommonGL/graphicsDeviceGL.h" 4 | #include "../CommonGL/shaderGL.h" 5 | 6 | class GraphicsShadersGL_2_0 7 | { 8 | public: 9 | GraphicsShadersGL_2_0(); 10 | ~GraphicsShadersGL_2_0(); 11 | 12 | void loadShaders(); 13 | ShaderGL* getShader( ShaderID shader ); 14 | 15 | private: 16 | ShaderGL* m_shaders[SHADER_COUNT]; 17 | static const char* m_shaderVS[SHADER_COUNT]; 18 | static const char* m_shaderPS[SHADER_COUNT]; 19 | }; 20 | -------------------------------------------------------------------------------- /XLEngine/Graphics/Linux/graphicsDeviceGL_Linux.cpp: -------------------------------------------------------------------------------- 1 | #include "../../log.h" 2 | #include "../../Math/math.h" 3 | #include "graphicsDeviceGL_Linux.h" 4 | 5 | #include "../graphicsGL_Inc.h" 6 | 7 | //Linux stuff 8 | #include /* X11 constant (e.g. TrueColor) */ 9 | 10 | static int c_snglBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, None}; 11 | static int c_dblBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None}; 12 | 13 | PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = NULL; 14 | static const GLubyte* s_glExtensions; 15 | 16 | static Display* s_display; 17 | static Window s_win; 18 | static bool s_doubleBuffer; 19 | 20 | GraphicsDeviceGL_Linux::GraphicsDeviceGL_Linux() 21 | { 22 | m_exclusiveFullscreen = false; 23 | m_initialized = false; 24 | } 25 | 26 | GraphicsDeviceGL_Linux::~GraphicsDeviceGL_Linux() 27 | { 28 | } 29 | 30 | void GraphicsDeviceGL_Linux::present() 31 | { 32 | if (s_doubleBuffer) 33 | { 34 | glXSwapBuffers(s_display, s_win); 35 | } 36 | else 37 | { 38 | glFlush(); 39 | } 40 | 41 | //avoid buffering frames when vsync is enabled otherwise the input "lag" will be increased. 42 | if (m_vsyncEnabled) 43 | { 44 | glFinish(); 45 | } 46 | } 47 | 48 | void GraphicsDeviceGL_Linux::setWindowData(int nParam, void **param, GraphicsDeviceID deviceID, bool exclFullscreen/*=false*/) 49 | { 50 | if (m_initialized) 51 | { 52 | return; 53 | } 54 | 55 | m_exclusiveFullscreen = exclFullscreen; 56 | s_display = (Display*)param[0]; 57 | size_t windowWidth = size_t(param[1]); 58 | size_t windowHeight = size_t(param[2]); 59 | 60 | XVisualInfo *vi; 61 | Colormap cmap; 62 | XSetWindowAttributes swa; 63 | GLXContext cx; 64 | int dummy; 65 | 66 | // make sure OpenGL's GLX extension supported 67 | if(!glXQueryExtension(s_display, &dummy, &dummy)) 68 | { 69 | LOG( LOG_ERROR, "X server has no OpenGL GLX extension" ); 70 | return; 71 | } 72 | 73 | // find an appropriate visual 74 | 75 | // find an OpenGL-capable RGB visual with depth buffer 76 | s_doubleBuffer = true; 77 | vi = glXChooseVisual(s_display, DefaultScreen(s_display), c_dblBuf); 78 | if (vi == NULL) 79 | { 80 | vi = glXChooseVisual(s_display, DefaultScreen(s_display), c_snglBuf); 81 | if (vi == NULL) 82 | { 83 | LOG( LOG_ERROR, "no RGB visual with depth buffer" ); 84 | } 85 | s_doubleBuffer = false; 86 | } 87 | 88 | // create an OpenGL rendering context 89 | cx = glXCreateContext(s_display, vi, None, GL_TRUE); 90 | if (cx == NULL) 91 | { 92 | LOG( LOG_ERROR, "could not create rendering context" ); 93 | return; 94 | } 95 | 96 | // create an X window with the selected visual 97 | 98 | // create an X colormap since probably not using default visual 99 | cmap = XCreateColormap(s_display, RootWindow(s_display, vi->screen), vi->visual, AllocNone); 100 | swa.colormap = cmap; 101 | swa.border_pixel = 0; 102 | swa.event_mask = KeyPressMask | ExposureMask | ButtonPressMask | StructureNotifyMask; 103 | 104 | u32 windowAttr = CWBorderPixel | CWColormap | CWEventMask; 105 | s_win = XCreateWindow(s_display, RootWindow(s_display, vi->screen), 0, 0, windowWidth, windowHeight, 0, vi->depth, InputOutput, vi->visual, windowAttr, &swa); 106 | XSetStandardProperties(s_display, s_win, "main", "main", None, NULL, 0, NULL); 107 | 108 | // bind the rendering context to the window 109 | glXMakeCurrent(s_display, s_win, cx); 110 | 111 | // request the X window to be displayed on the screen 112 | XMapWindow(s_display, s_win); 113 | 114 | //platform extensions 115 | glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalEXT" ); 116 | 117 | LOG( LOG_MESSAGE, "OpenGL Window initialized." ); 118 | } 119 | 120 | bool GraphicsDeviceGL_Linux::init() 121 | { 122 | if (m_initialized) 123 | { 124 | return true; 125 | } 126 | 127 | const GLubyte* glVersion = glGetString(GL_VERSION); 128 | s_glExtensions = glGetString(GL_EXTENSIONS); 129 | 130 | LOG( LOG_MESSAGE, (const char*)glVersion ); 131 | 132 | //initialize GLEW for extension loading. 133 | /* 134 | const GLenum err = glewInit(); 135 | if (err != GLEW_OK) 136 | { 137 | LOG( LOG_ERROR, "GLEW failed to initialize, an OpenGL device cannot be created." ); 138 | return false; 139 | } 140 | 141 | LOG( LOG_MESSAGE, "glVersion: %s", (const char*)glVersion ); 142 | 143 | //check against the minimum version. 144 | if ( GLEW_VERSION_1_3 == GL_FALSE ) 145 | { 146 | LOG( LOG_ERROR, "OpenGL Version 1.3 is not supported. Aborting XL Engine startup." ); 147 | return false; 148 | } 149 | */ 150 | 151 | m_initialized = true; 152 | return true; 153 | } 154 | 155 | GraphicsDeviceID GraphicsDeviceGL_Linux::autodetect(int nParam, void **param) 156 | { 157 | GraphicsDeviceID devID = GDEV_OPENGL_1_3; 158 | 159 | setWindowData(nParam, param, GDEV_INVALID); 160 | if ( !init() ) 161 | { 162 | return GDEV_INVALID; 163 | } 164 | 165 | /* 166 | if ( GLEW_VERSION_3_2 == GL_TRUE ) 167 | { 168 | devID = GDEV_OPENGL_3_2; 169 | } 170 | else if ( GLEW_VERSION_2_0 == GL_TRUE ) 171 | { 172 | devID = GDEV_OPENGL_2_0; 173 | } 174 | */ 175 | 176 | //hack - this is here until the OpenGL 3.2 device is implemented. 177 | //remove as soon as the device is available! 178 | if (devID == GDEV_OPENGL_3_2) { devID = GDEV_OPENGL_2_0; } 179 | //end hack 180 | 181 | return devID; 182 | } 183 | 184 | void GraphicsDeviceGL_Linux::enableVSync(bool enable) 185 | { 186 | const s32 enableValue = 1;//m_adaptiveVsync ? -1 : 1; 187 | glXSwapIntervalEXT(s_display, s_win, enable ? enableValue : 0 ); 188 | 189 | m_vsyncEnabled = enable; 190 | } 191 | 192 | bool GraphicsDeviceGL_Linux::queryExtension(const char* name) 193 | { 194 | //will this work? 195 | return true;//strstr(s_glExtensions, name) != NULL; 196 | } 197 | -------------------------------------------------------------------------------- /XLEngine/Graphics/Linux/graphicsDeviceGL_Linux.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../graphicsDevice_Platform.h" 4 | #include "../graphicsDeviceList.h" 5 | 6 | class GraphicsDeviceGL_Linux : public GraphicsDevicePlatform 7 | { 8 | public: 9 | GraphicsDeviceGL_Linux(); 10 | virtual ~GraphicsDeviceGL_Linux(); 11 | 12 | void setWindowData(int nParam, void **param, GraphicsDeviceID deviceID, bool exclFullscreen=false); 13 | bool init(); 14 | void present(); 15 | 16 | GraphicsDeviceID autodetect(int nParam, void **param); 17 | void enableVSync(bool enable); 18 | 19 | bool queryExtension(const char* name); 20 | 21 | private: 22 | bool m_exclusiveFullscreen; 23 | bool m_initialized; 24 | bool m_adaptiveVsync; 25 | bool m_vsyncEnabled; 26 | }; 27 | -------------------------------------------------------------------------------- /XLEngine/Graphics/Win32/graphicsDeviceGL_Win32.cpp: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 2 | // Windows Header Files: 3 | #include "../../log.h" 4 | #include "graphicsDeviceGL_Win32.h" 5 | 6 | #include 7 | #include "../../Math/math.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | //WGL Extension crap... fortunately only on Windows. 15 | typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int interval); 16 | typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void); 17 | 18 | static HGLRC m_hRC; 19 | static HDC m_hDC; 20 | static HWND m_hWnd; 21 | 22 | static WORD m_GammaRamp_Default[3][256]; 23 | static WORD m_GammaRamp[3][256]; 24 | 25 | bool wglExtensionSupported(const char *extension_name) 26 | { 27 | // this is pointer to function which returns pointer to string with list of all wgl extensions 28 | PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglGetExtensionsStringEXT = NULL; 29 | 30 | // determine pointer to wglGetExtensionsStringEXT function 31 | _wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT"); 32 | 33 | if (strstr(_wglGetExtensionsStringEXT(), extension_name) == NULL) 34 | { 35 | // string was not found 36 | return false; 37 | } 38 | 39 | // extension is supported 40 | return true; 41 | } 42 | 43 | 44 | 45 | GraphicsDeviceGL_Win32::GraphicsDeviceGL_Win32() 46 | { 47 | m_exclusiveFullscreen = false; 48 | m_initialized = false; 49 | } 50 | 51 | GraphicsDeviceGL_Win32::~GraphicsDeviceGL_Win32() 52 | { 53 | //Restore the gamma ramp. 54 | if ( m_exclusiveFullscreen ) 55 | { 56 | HDC hdc = GetDC(NULL); 57 | SetDeviceGammaRamp(hdc, m_GammaRamp_Default); 58 | } 59 | } 60 | 61 | void GraphicsDeviceGL_Win32::present() 62 | { 63 | HDC hdc = GetDC(m_hWnd); 64 | SwapBuffers( hdc ); 65 | ReleaseDC( m_hWnd, hdc ); 66 | 67 | //avoid buffering frames when vsync is enabled otherwise the input "lag" will be increased. 68 | if (m_vsyncEnabled) 69 | { 70 | glFinish(); 71 | } 72 | } 73 | 74 | void GraphicsDeviceGL_Win32::setWindowData(int nParam, void **param, GraphicsDeviceID deviceID, bool exclFullscreen/*=false*/) 75 | { 76 | if (m_initialized) 77 | { 78 | return; 79 | } 80 | 81 | m_exclusiveFullscreen = exclFullscreen; 82 | 83 | m_hWnd = (HWND)param[0]; 84 | HDC m_hDC = GetDC(m_hWnd); 85 | 86 | BYTE bits = 32; 87 | static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be 88 | { 89 | sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 90 | 1, // Version Number 91 | PFD_DRAW_TO_WINDOW | // Format Must Support Window 92 | PFD_SUPPORT_OPENGL | // Format Must Support OpenGL 93 | PFD_DOUBLEBUFFER, // Must Support Double Buffering 94 | PFD_TYPE_RGBA, // Request An RGBA Format 95 | bits, // Select Our Color Depth 96 | 0, 0, 0, 0, 0, 0, // Color Bits Ignored 97 | 0, // No Alpha Buffer 98 | 0, // Shift Bit Ignored 99 | 0, // No Accumulation Buffer 100 | 0, 0, 0, 0, // Accumulation Bits Ignored 101 | 24, // 24Bit Z-Buffer (Depth Buffer) 102 | 8, // 8Bit Stencil Buffer 103 | 0, // No Auxiliary Buffer 104 | PFD_MAIN_PLANE, // Main Drawing Layer 105 | 0, // Reserved 106 | 0, 0, 0 // Layer Masks Ignored 107 | }; 108 | 109 | int PixelFormat; 110 | if ( !(PixelFormat=ChoosePixelFormat(m_hDC, &pfd)) ) // Did Windows find a matching Pixel Format? 111 | { 112 | return; 113 | } 114 | 115 | if ( !SetPixelFormat(m_hDC, PixelFormat, &pfd) ) // Are we able to set the Pixel Format? 116 | { 117 | return; 118 | } 119 | 120 | //TO-DO: create a proper (modern) context specific to the version of OpenGL trying the be used. 121 | m_hRC = wglCreateContext(m_hDC); 122 | if ( m_hRC == 0 ) 123 | { 124 | return; 125 | } 126 | 127 | if ( !wglMakeCurrent(m_hDC, m_hRC) ) // Try to activate the Rendering Context 128 | { 129 | return; 130 | } 131 | 132 | //Now enable or disable VSYNC based on settings. 133 | //If the extension can't be found then we're forced to use whatever the driver default is... 134 | //but this shouldn't happen. If it does, the engine will still run at least. :) 135 | if ( wglExtensionSupported("WGL_EXT_swap_control") ) 136 | { 137 | // Extension is supported, init pointer. 138 | // Save so that the swap interval can be changed later (to be implemented). 139 | wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); 140 | } 141 | 142 | m_adaptiveVsync = false; 143 | if ( wglExtensionSupported("EXT_swap_control_tear") ) 144 | { 145 | m_adaptiveVsync = true; 146 | } 147 | 148 | //Only setup the gamma ramp in fullscreen. 149 | if ( m_exclusiveFullscreen ) 150 | { 151 | //get the current gamma ramp so it can be restored on exit. 152 | GetDeviceGammaRamp(m_hDC, m_GammaRamp_Default); 153 | 154 | f32 fBrightness=1.0f, fContrast=1.0f, fGamma=1.0f; 155 | 156 | //apply brightness, contrast and gamma. 157 | f32 fIntensity = 0.0f; 158 | f32 fValue; 159 | const f32 fInc = 1.0f / 255.0f; 160 | for (int i=0; i<256; i++) 161 | { 162 | //apply contrast 163 | fValue = fContrast*(fIntensity - 0.5f) + 0.5f; 164 | //apply brightness 165 | fValue = fBrightness*fValue; 166 | //apply gamma 167 | fValue = powf(fValue, fGamma); 168 | //clamp. 169 | fValue = Math::saturate(fValue); 170 | 171 | int intValue = ((int)(fValue*255.0f)) << 8; 172 | 173 | m_GammaRamp[0][i] = intValue; 174 | m_GammaRamp[1][i] = intValue; 175 | m_GammaRamp[2][i] = intValue; 176 | 177 | fIntensity += fInc; 178 | } 179 | SetDeviceGammaRamp(m_hDC, m_GammaRamp); 180 | } 181 | } 182 | 183 | bool GraphicsDeviceGL_Win32::init() 184 | { 185 | if (m_initialized) 186 | { 187 | return true; 188 | } 189 | 190 | const GLubyte* glVersion = glGetString(GL_VERSION); 191 | const GLubyte* glExtensions = glGetString(GL_EXTENSIONS); 192 | 193 | //initialize GLEW for extension loading. 194 | const GLenum err = glewInit(); 195 | if (err != GLEW_OK) 196 | { 197 | LOG( LOG_ERROR, "GLEW failed to initialize, an OpenGL device cannot be created." ); 198 | return false; 199 | } 200 | 201 | LOG( LOG_MESSAGE, "glVersion: %s", (const char*)glVersion ); 202 | 203 | //check against the minimum version. 204 | if ( GLEW_VERSION_1_3 == GL_FALSE ) 205 | { 206 | LOG( LOG_ERROR, "OpenGL Version 1.3 is not supported. Aborting XL Engine startup." ); 207 | return false; 208 | } 209 | 210 | m_initialized = true; 211 | return true; 212 | } 213 | 214 | GraphicsDeviceID GraphicsDeviceGL_Win32::autodetect(int nParam, void **param) 215 | { 216 | GraphicsDeviceID devID = GDEV_OPENGL_1_3; 217 | 218 | setWindowData(nParam, param, GDEV_INVALID); 219 | if ( !init() ) 220 | { 221 | return GDEV_INVALID; 222 | } 223 | 224 | if ( GLEW_VERSION_3_2 == GL_TRUE ) 225 | { 226 | devID = GDEV_OPENGL_3_2; 227 | } 228 | else if ( GLEW_VERSION_2_0 == GL_TRUE ) 229 | { 230 | devID = GDEV_OPENGL_2_0; 231 | } 232 | 233 | //hack - this is here until the OpenGL 3.2 device is implemented. 234 | //remove as soon as the device is available! 235 | if (devID == GDEV_OPENGL_3_2) { devID = GDEV_OPENGL_2_0; } 236 | //end hack 237 | 238 | return devID; 239 | } 240 | 241 | void GraphicsDeviceGL_Win32::enableVSync(bool enable) 242 | { 243 | if (wglSwapIntervalEXT) 244 | { 245 | const s32 enableValue = m_adaptiveVsync ? -1 : 1; 246 | wglSwapIntervalEXT( enable ? enableValue : 0 ); 247 | } 248 | 249 | m_vsyncEnabled = enable; 250 | } 251 | 252 | bool GraphicsDeviceGL_Win32::queryExtension(const char* name) 253 | { 254 | return glewGetExtension(name)!=0; 255 | } 256 | -------------------------------------------------------------------------------- /XLEngine/Graphics/Win32/graphicsDeviceGL_Win32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../graphicsDevice_Platform.h" 4 | #include "../graphicsDeviceList.h" 5 | 6 | class GraphicsDeviceGL_Win32 : public GraphicsDevicePlatform 7 | { 8 | public: 9 | GraphicsDeviceGL_Win32(); 10 | virtual ~GraphicsDeviceGL_Win32(); 11 | 12 | void setWindowData(int nParam, void **param, GraphicsDeviceID deviceID, bool exclFullscreen=false); 13 | bool init(); 14 | void present(); 15 | 16 | GraphicsDeviceID autodetect(int nParam, void **param); 17 | void enableVSync(bool enable); 18 | 19 | bool queryExtension(const char* name); 20 | 21 | private: 22 | bool m_exclusiveFullscreen; 23 | bool m_initialized; 24 | bool m_adaptiveVsync; 25 | bool m_vsyncEnabled; 26 | }; 27 | -------------------------------------------------------------------------------- /XLEngine/Graphics/capabilities.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum CapabilityFlags 4 | { 5 | CAP_SUPPORT_SHADERS = (1<<0), 6 | CAP_NON_POWER_2_TEX = (1<<1), 7 | CAP_RENDER_TARGET = (1<<2), 8 | }; 9 | 10 | struct Capabilities 11 | { 12 | u32 flags; 13 | u32 maxTextureSize2D; 14 | }; -------------------------------------------------------------------------------- /XLEngine/Graphics/graphicsDevice.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "graphicsDevice.h" 3 | #include "../log.h" 4 | 5 | //specific implementations of this interface. 6 | #include "Devices/graphicsDeviceGL_1_3.h" 7 | #include "Devices/graphicsDeviceGL_2_0.h" 8 | #include "Devices/graphicsDeviceGL_3_2.h" 9 | 10 | GraphicsDevice* GraphicsDevice::createDevice(GraphicsDeviceID deviceID, GraphicsDevicePlatform* platform) 11 | { 12 | GraphicsDevice* gdev = NULL; 13 | switch (deviceID) 14 | { 15 | case GDEV_OPENGL_1_3: 16 | gdev = new GraphicsDeviceGL_1_3( platform ); 17 | break; 18 | case GDEV_OPENGL_2_0: 19 | gdev = new GraphicsDeviceGL_2_0( platform ); 20 | break; 21 | case GDEV_OPENGL_3_2: 22 | gdev = new GraphicsDeviceGL_3_2( platform ); 23 | break; 24 | } 25 | 26 | if (gdev == NULL) 27 | { 28 | LOG( LOG_ERROR, "Invalid device ID %u!", deviceID); 29 | } 30 | else 31 | { 32 | LOG( LOG_MESSAGE, "Graphics Device \"%s\" successfully created.", c_graphicsDeviceName[deviceID] ); 33 | } 34 | 35 | return gdev; 36 | } 37 | 38 | void GraphicsDevice::destroyDevice(GraphicsDevice* device) 39 | { 40 | delete device; 41 | } 42 | -------------------------------------------------------------------------------- /XLEngine/Graphics/graphicsDevice.h: -------------------------------------------------------------------------------- 1 | /************************************************************************************************************ 2 | Graphics Device interface. 3 | 4 | There are 2 components to the device: 5 | - The platform (graphicsDevice_Platform) which handles OS and platform specific implementations. 6 | - The API "level" such as OpenGL 1.3, OpenGL 2.0 or DirectX 9, DirectX 11 if DirectX is ever supported. 7 | By seperating the two and ensuring the platform implementation is as small as possible, the amount 8 | of per-platform code is reduced, the majority of the code goes into supporting the various 9 | features and improvements with each API "level" which is where it should go. 10 | 11 | It create a device, pass in the deviceID and platform implementation to the static createDevice() 12 | Similarly destroy the device using the static destroy() 13 | Graphics Devices can be changed at runtime, allowing the user to pick the API level or even API itself 14 | depending on driver compatibility (or just to test). 15 | **************************************************************************************************************/ 16 | #pragma once 17 | #include "graphicsDevice_Platform.h" 18 | #include "graphicsDeviceList.h" 19 | #include "graphicsTypes.h" 20 | #include "samplerState.h" 21 | #include "capabilities.h" 22 | 23 | class GraphicsDevice 24 | { 25 | public: 26 | virtual void setWindowData(int nParam, void **param)=0; 27 | virtual bool init(int w, int h, int& vw, int& vh)=0; 28 | virtual void drawVirtualScreen()=0; 29 | virtual void present()=0; 30 | virtual void clear()=0; 31 | virtual void queryExtensions()=0; 32 | 33 | virtual void setShader(ShaderID shader)=0; 34 | 35 | virtual void convertFrameBufferTo32bpp(u8* source, u32 *pal)=0; 36 | virtual void setBlendMode(BlendMode mode)=0; 37 | virtual void enableBlending(bool enable)=0; 38 | virtual void enableTexturing(bool enable)=0; 39 | 40 | virtual TextureHandle createTextureRGBA(u32 width, u32 height, const u32* data, const SamplerState& initSamplerStat, bool dynamic=false)=0; 41 | virtual RenderTargetHandle createRenderTarget(u32 width, u32 height, const SamplerState& initSamplerState)=0; 42 | virtual void destroyTexture(TextureHandle texHandle)=0; 43 | virtual void destroyRenderTarget(RenderTargetHandle rtHandle)=0; 44 | 45 | virtual void bindRenderTarget(RenderTargetHandle handle)=0; 46 | virtual void unbindRenderTarget()=0; 47 | virtual TextureHandle getRenderTargetTexture(RenderTargetHandle handle)=0; 48 | 49 | virtual void clearShaderParamCache()=0; 50 | virtual void setShaderResource(TextureHandle handle, u32 nameHash, u32 slot=0)=0; 51 | virtual void setShaderParameter(void* data, u32 size, u32 nameHash)=0; 52 | virtual void drawQuad(const Quad& quad)=0; 53 | 54 | virtual void setVirtualViewport(bool reset, int x, int y, int w, int h)=0; 55 | 56 | //batching (not used by all devices) 57 | virtual void flush()=0; 58 | virtual u32 addQuad(const Quad& quad)=0; 59 | virtual void drawQuadBatch(u32 vertexOffset, u32 count)=0; 60 | 61 | //It is expected that an implementation will fill out the 'm_caps' variable. 62 | bool supportsFeature(CapabilityFlags feature) const { return (m_caps.flags&feature)!=0; } 63 | u32 getMaximumTextureSize() const { return m_caps.maxTextureSize2D; } 64 | GraphicsDeviceID getDeviceID() const { return m_deviceID; } 65 | 66 | void enableVsync(bool enable) { m_platform->enableVSync(enable); } 67 | 68 | static GraphicsDevice* createDevice(GraphicsDeviceID deviceID, GraphicsDevicePlatform* platform); 69 | static void destroyDevice(GraphicsDevice* device); 70 | 71 | protected: 72 | GraphicsDevice(GraphicsDevicePlatform* platform) 73 | { 74 | m_platform = platform; 75 | m_deviceID = GDEV_INVALID; 76 | m_caps.flags = 0; 77 | m_caps.maxTextureSize2D = 0; 78 | } 79 | virtual ~GraphicsDevice() 80 | { 81 | delete m_platform; 82 | } 83 | 84 | virtual void setTexture(TextureHandle handle, int slot=0)=0; 85 | 86 | GraphicsDevicePlatform* m_platform; 87 | GraphicsDeviceID m_deviceID; 88 | Capabilities m_caps; //see CapabilityFlags 89 | private: 90 | }; 91 | -------------------------------------------------------------------------------- /XLEngine/Graphics/graphicsDeviceList.cpp: -------------------------------------------------------------------------------- 1 | #include "graphicsDeviceList.h" 2 | 3 | const char* c_graphicsDeviceName[]= 4 | { 5 | "OpenGL 1.3", 6 | "OpenGL 2.0", 7 | "OpenGL 3.2", 8 | }; 9 | -------------------------------------------------------------------------------- /XLEngine/Graphics/graphicsDeviceList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum GraphicsDeviceID 4 | { 5 | GDEV_OPENGL_1_3 = 0, 6 | GDEV_OPENGL_2_0, 7 | GDEV_OPENGL_3_2, 8 | GDEV_COUNT, 9 | GDEV_INVALID = GDEV_COUNT 10 | }; 11 | 12 | extern const char* c_graphicsDeviceName[GDEV_COUNT]; 13 | -------------------------------------------------------------------------------- /XLEngine/Graphics/graphicsDevice_Platform.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************************************** 2 | Platform specific implementation for the Graphics Device. 3 | With APIs such as OpenGL, most of the functionality can be shared between platforms, implementations 4 | of this interface handle the few details that are platform dependent. 5 | 6 | The implementation will be "composited" with the device implementation reducing the permutations 7 | between feature sets, APIs and platforms. 8 | ******************************************************************************************************/ 9 | #pragma once 10 | #include "../types.h" 11 | #include "graphicsDeviceList.h" 12 | 13 | class GraphicsDevicePlatform 14 | { 15 | public: 16 | GraphicsDevicePlatform() {} 17 | virtual ~GraphicsDevicePlatform() {} 18 | 19 | virtual void setWindowData(int nParam, void **param, GraphicsDeviceID deviceID, bool exclFullscreen=false)=0; 20 | virtual bool init()=0; 21 | virtual void present()=0; 22 | 23 | virtual GraphicsDeviceID autodetect(int nParam, void **param)=0; 24 | virtual void enableVSync(bool enable)=0; 25 | 26 | virtual bool queryExtension(const char* name)=0; 27 | }; 28 | -------------------------------------------------------------------------------- /XLEngine/Graphics/graphicsGL_Inc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | #include 5 | #include 6 | #include 7 | #else 8 | #define GL_GLEXT_PROTOTYPES 9 | #include 10 | #include 11 | #include 12 | #include "GL/glext.h" 13 | #endif 14 | -------------------------------------------------------------------------------- /XLEngine/Graphics/graphicsTypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../types.h" 3 | 4 | /////////////////////////////////////////////////// 5 | // Enums 6 | /////////////////////////////////////////////////// 7 | enum BlendMode 8 | { 9 | BLEND_OVER = 0, //src*Alpha + dst*(1-Alpha) 10 | BLEND_ALPHA_ADD, //src*Alpha + dst 11 | BLEND_ADD, //src + dst 12 | BLEND_COUNT 13 | }; 14 | 15 | enum ShaderID 16 | { 17 | SHADER_QUAD_UI = 0, 18 | SHADER_QUAD_COLOR_CORRECT, 19 | SHADER_BLUR, 20 | SHADER_GLOW_UI, 21 | SHADER_COUNT 22 | }; 23 | 24 | 25 | /////////////////////////////////////////////////// 26 | // Typedefs and structures 27 | /////////////////////////////////////////////////// 28 | typedef u32 Color; 29 | typedef u32 TextureHandle; 30 | typedef u32 RenderTargetHandle; 31 | 32 | struct iPoint 33 | { 34 | s32 x; 35 | s32 y; 36 | }; 37 | 38 | struct fPoint 39 | { 40 | f32 x; 41 | f32 y; 42 | }; 43 | 44 | struct Quad 45 | { 46 | iPoint p0; 47 | iPoint p1; 48 | fPoint uv0; 49 | fPoint uv1; 50 | Color color; 51 | }; 52 | 53 | 54 | /////////////////////////////////////////////////// 55 | // Defines 56 | /////////////////////////////////////////////////// 57 | #define INVALID_TEXTURE_HANDLE 0xffffffff 58 | -------------------------------------------------------------------------------- /XLEngine/Graphics/samplerState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum WrapMode 4 | { 5 | WM_WRAP = 0, 6 | WM_CLAMP, 7 | WM_MIRROR, 8 | WM_COUNT, 9 | }; 10 | 11 | enum TextureFilter 12 | { 13 | TEXFILTER_POINT = 0, 14 | TEXFILTER_LINEAR, 15 | TEXFILTER_ANISOTROPIC, 16 | TEXFILTER_COUNT 17 | }; 18 | 19 | struct SamplerState 20 | { 21 | WrapMode wrapU; 22 | WrapMode wrapV; 23 | WrapMode wrapW; 24 | 25 | TextureFilter minFilter; 26 | TextureFilter magFilter; 27 | TextureFilter mipFilter; 28 | 29 | bool enableMipMapping; 30 | }; 31 | -------------------------------------------------------------------------------- /XLEngine/Linux/clockLinux.cpp: -------------------------------------------------------------------------------- 1 | #include "../clock.h" 2 | #include "../log.h" 3 | #include 4 | #include 5 | #include 6 | 7 | const u64 c_secToNs = 1000000000ULL; 8 | const f64 c_nsToSec (1.0 / f64(c_secToNs)); 9 | 10 | f32 Clock::s_deltaTime; 11 | f32 Clock::s_realDeltaTime; 12 | s32 Clock::s_deltaTicks; 13 | 14 | static timespec s_timerFreq; 15 | static u64 s_startTick[16] = {0}; 16 | 17 | u64 getCurTickCnt(); 18 | 19 | bool Clock::init() 20 | { 21 | return (clock_getres(CLOCK_MONOTONIC, &s_timerFreq) == 0); 22 | } 23 | 24 | void Clock::destroy() 25 | { 26 | //nothing to do currently. 27 | } 28 | 29 | void Clock::startTimer(int timerID/*=0*/) 30 | { 31 | assert( timerID < 16 ); 32 | s_startTick[timerID] = getCurTickCnt(); 33 | } 34 | 35 | float Clock::getDeltaTime(float fMax, int timerID/*=0*/) 36 | { 37 | assert( timerID < 16 ); 38 | u64 End = getCurTickCnt(); 39 | 40 | f32 fTimeDelta = (f32)( (f64)(End - s_startTick[timerID]) * c_nsToSec ); 41 | if ( fTimeDelta > fMax ) 42 | { 43 | fTimeDelta = fMax; 44 | } 45 | 46 | return fTimeDelta; 47 | } 48 | 49 | u64 Clock::getDeltaTime_uS(int timerID/*=0*/) 50 | { 51 | u64 End = getCurTickCnt(); 52 | return (u64)( (f64)(End - s_startTick[timerID]) * c_nsToSec ); 53 | } 54 | 55 | f64 Clock::getDeltaTime_f64(int timerID/*=0*/) 56 | { 57 | u64 End = getCurTickCnt(); 58 | return f64(End - s_startTick[timerID]) * c_nsToSec; 59 | } 60 | 61 | u64 Clock::getTime_uS() 62 | { 63 | u64 value = getCurTickCnt(); 64 | return (u64)( (f64)value * 1000.0 ); 65 | } 66 | 67 | f64 Clock::getTime_uS_flt() 68 | { 69 | u64 value = getCurTickCnt(); 70 | return (f64)value * 1000.0; 71 | } 72 | 73 | u64 getCurTickCnt() 74 | { 75 | timespec timingRes; 76 | s32 res = clock_gettime(CLOCK_MONOTONIC, &timingRes); 77 | if (res != 0) 78 | { 79 | LOG( LOG_ERROR, "clock_gettime() failed, result = %d.", res ); 80 | return 0; 81 | } 82 | 83 | return u64(timingRes.tv_sec)*c_secToNs + u64(timingRes.tv_nsec); 84 | } 85 | -------------------------------------------------------------------------------- /XLEngine/Linux/osUtilLinux.cpp: -------------------------------------------------------------------------------- 1 | #include "../osUtil.h" 2 | #include 3 | #include 4 | #include 5 | 6 | namespace OS 7 | { 8 | void sleep(u32 sleepDeltaMS) 9 | { 10 | u32 sleepDeltaUS = sleepDeltaMS ? sleepDeltaMS * 1000 : 1; 11 | usleep( sleepDeltaUS ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /XLEngine/Math/crc32.cpp: -------------------------------------------------------------------------------- 1 | #include "crc32.h" 2 | #include 3 | 4 | namespace CRC32 5 | { 6 | static bool s_initCRC32 = false; 7 | static u32 s_crcTable[256]; 8 | 9 | u32 reflectCRC(s32 val, s32 bits) 10 | { 11 | s32 result = 0; 12 | for (s32 bit = 0; bit < bits; bit++) 13 | { 14 | if(val & 1) result |= 1 << (bits - 1 - bit); 15 | val >>= 1; 16 | } 17 | 18 | return result; 19 | } 20 | 21 | void initcrc32() 22 | { 23 | for (s32 byte = 0; byte < 256; ++ byte) 24 | { 25 | u32 crc = reflectCRC(byte, 8) << 24; 26 | for (s32 offset = 0; offset < 8; ++ offset) 27 | { 28 | if (crc & 0x80000000) 29 | { 30 | crc = (crc << 1) ^ 0x04c11db7; 31 | } 32 | else 33 | { 34 | crc <<= 1; 35 | } 36 | } 37 | s_crcTable[byte] = reflectCRC(crc, 32); 38 | } 39 | s_initCRC32 = true; 40 | } 41 | 42 | u32 get(const u8* buffer, size_t size) 43 | { 44 | u32 crc = 0xFFFFFFFF; 45 | if (!s_initCRC32) initcrc32(); 46 | 47 | const u8* data = buffer; 48 | const u8* dataEnd = &data[size]; 49 | while (data < dataEnd) 50 | { 51 | crc = (crc >> 8) ^ s_crcTable[(crc & 0xFF) ^ *data++]; 52 | } 53 | 54 | return ~crc; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /XLEngine/Math/crc32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../types.h" 3 | 4 | namespace CRC32 5 | { 6 | u32 get(const u8* buffer, size_t size); 7 | } -------------------------------------------------------------------------------- /XLEngine/Math/math.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../types.h" 3 | #include 4 | 5 | namespace Math 6 | { 7 | const f32 PI = 3.1415926535897932384626433832795f; 8 | const f32 twoPI = 6.283185307179586476925286766559f; 9 | const f32 PIoverTwo = 1.5707963267948966192313216916398f; 10 | const f32 degToRadScale = PI / 180.0f; 11 | const f32 radToDegScale = 180.0f / PI; 12 | 13 | inline bool isPow2(u32 x) 14 | { 15 | return ((x != 0) && !(x & (x - 1))) != 0; 16 | } 17 | 18 | inline u32 nextPow2(u32 x) 19 | { 20 | x = x-1; 21 | x = x | (x>>1); 22 | x = x | (x>>2); 23 | x = x | (x>>4); 24 | x = x | (x>>8); 25 | x = x | (x>>16); 26 | return x + 1; 27 | } 28 | 29 | template 30 | inline T clamp(T x, T a, T b) 31 | { 32 | if ( x < a ) x = a; 33 | if ( x > b ) x = b; 34 | 35 | return x; 36 | } 37 | 38 | template 39 | inline T saturate(T x) 40 | { 41 | return clamp(x, T(0), T(1)); 42 | } 43 | 44 | template 45 | inline T sign(T x) 46 | { 47 | return x >= T(0) ? T(1) : T(-1); 48 | } 49 | 50 | //simple templates to avoid code duplication. 51 | //expected inputs: floating point types (to use integers, use float inputs and then convert the result). 52 | template 53 | inline T lerp(T x, T a, T b) 54 | { 55 | return (T(1.0)-x)*a + x*b; 56 | } 57 | 58 | template 59 | inline T frac(T x) 60 | { 61 | T ax = (T)fabs(x); 62 | T s = x 67 | inline T degToRad(T degrees) 68 | { 69 | return degrees * T(degToRadScale); 70 | } 71 | 72 | template 73 | inline T radToDeg(T radians) 74 | { 75 | return radians * T(radToDegScale); 76 | } 77 | 78 | template 79 | inline T log2(T x) 80 | { 81 | return (T)log10(x) / T(0.30102999566398119521373889472449); 82 | } 83 | 84 | //Do the closed intervals [a0,a1] and [b0,b1] overlap? 85 | template 86 | inline bool intervalOverlap(T a0, T a1, T b0, T b1) 87 | { 88 | return a0 <= b1 && b0 <= a1; 89 | } 90 | 91 | //Do the half open intervals [a0,a1) and [b0,b1) overlap? 92 | template 93 | inline bool intervalOverlapOpen(T a0, T a1, T b0, T b1) 94 | { 95 | return a0 < b1 && b0 < a1; 96 | } 97 | 98 | //cubic polynomial that implements "hermite interpolation" if x is between 0 and 1 99 | inline f32 cubicPolynomial(f32 x) 100 | { 101 | return x*x*(3.0f-2.0f*x); 102 | } 103 | 104 | //quintic polynomial that implements "hermite interpolation" if x is between 0 and 1. 105 | inline f32 quinticPolynomial(f32 x) 106 | { 107 | return x*x*x*(x*(x*6.0f - 15.0f) + 10.0f); 108 | } 109 | 110 | //evaluates to 0 if x <= a and 1 if x >= b, linear interpolation between 0 to 1. 111 | inline f32 lineStep(f32 x, f32 a, f32 b) 112 | { 113 | return saturate( (x-a) / (b-a) ); 114 | } 115 | 116 | //standard smoothstep 117 | //evaluates to 0 if x <= a and 1 if x >= b, hermite cubic interpolation from 0 to 1 between. 118 | //1st order derivatives evaluate to 0 at a and b. 119 | inline f32 smoothStep(f32 x, f32 a, f32 b) 120 | { 121 | return cubicPolynomial( lineStep(x, a, b) ); 122 | } 123 | 124 | //"improved" smoothstep, C2 continuous. Obviously more expensive to evaluate than smoothstep() 125 | //evaluates to 0 if x <= a and 1 if x >= b, hermite quintic interpolation from 0 to 1 between. 126 | //1st and 2nd order derivatives evaluate to 0 at a and b. 127 | inline f32 smootherStep(f32 x, f32 a, f32 b) 128 | { 129 | return quinticPolynomial( lineStep(x, a, b) ); 130 | } 131 | 132 | //a cubic pulse centered on 'c' with width 'w' 133 | //the result is 0 when x less than c-w or greater than c+w 134 | //the result is 1 when x == c 135 | //the shape is Gaussian-like. 136 | inline f32 cubicPulse(f32 x, f32 c, f32 w) 137 | { 138 | x = fabsf(x - c); 139 | if (x > w) return 0.0f; 140 | 141 | return 1.0f - cubicPolynomial( x/w ); 142 | } 143 | 144 | //maps a 0..1 range to a power curve where (x=0) and (x=1) are mapped to 0. 145 | //a and b skew the shape of the curve such that the peak can be off-center. 146 | //the peak is not scaled to 1.0, use this version when custom scaling is required. 147 | inline f32 powerCurveNoScale(f32 x, f32 a, f32 b) 148 | { 149 | return powf( x, a ) * powf( 1.0f-x, b ); 150 | } 151 | 152 | //maps a 0..1 range to a power curve where (x=0) and (x=1) are mapped to 0. 153 | //a and b skew the shape of the curve such that the peak can be off-center. 154 | //the peak is exactly 1.0 155 | inline f32 powerCurve(f32 x, f32 a, f32 b) 156 | { 157 | const f32 k = powf(a+b,a+b) / (powf(a,a)*powf(b,b)); 158 | return k * powerCurveNoScale(x, a, b); 159 | } 160 | } -------------------------------------------------------------------------------- /XLEngine/PluginFramework/dynamicLibrary.cpp: -------------------------------------------------------------------------------- 1 | #if _WIN32 2 | #include 3 | #else 4 | #include 5 | #endif 6 | 7 | #include "dynamicLibrary.h" 8 | #include "../log.h" 9 | #include 10 | #include 11 | 12 | #if _OSX 13 | static string dynamicLibraryExtension("dylib"); 14 | #elif _WIN32 15 | static string dynamicLibraryExtension("dll"); 16 | #else 17 | static string dynamicLibraryExtension("so"); 18 | #endif 19 | 20 | DynamicLibrary::DynamicLibrary(void *handle) 21 | { 22 | m_handle = handle; 23 | } 24 | 25 | DynamicLibrary::~DynamicLibrary() 26 | { 27 | if (m_handle) 28 | { 29 | #if _WIN32 30 | FreeLibrary( (HMODULE)m_handle ); 31 | #else 32 | dlclose( m_handle ); 33 | #endif 34 | } 35 | } 36 | 37 | DynamicLibrary *DynamicLibrary::load(const string& name, string& errorString) 38 | { 39 | if (name.empty()) 40 | { 41 | LOG( LOG_ERROR, "DynamicLibrary: Empty path." ); 42 | return NULL; 43 | } 44 | 45 | void *handle = NULL; 46 | string path = name + "." + dynamicLibraryExtension; 47 | 48 | #if _WIN32 49 | handle = LoadLibraryA( path.c_str() ); 50 | if ( !handle ) 51 | { 52 | DWORD errorCode = GetLastError(); 53 | LOG( LOG_ERROR, "LoadLibrary(%s) failed, errorCode: %x", name.c_str(), errorCode ); 54 | return NULL; 55 | } 56 | #else 57 | handle = dlopen( path.c_str(), RTLD_NOW ); 58 | if (!handle) 59 | { 60 | string dlErrorString; 61 | const char *zErrorString = dlerror(); 62 | LOG( LOG_ERROR, "dlopen(%s) failed, error: %s", name.c_str(), zErrorString ? zErrorString : "unknown" ); 63 | return NULL; 64 | } 65 | #endif 66 | 67 | return new DynamicLibrary(handle); 68 | } 69 | 70 | void *DynamicLibrary::getSymbol(const std::string& symbol) 71 | { 72 | if ( !m_handle ) 73 | return NULL; 74 | 75 | #if _WIN32 76 | return GetProcAddress( (HMODULE)m_handle, symbol.c_str() ); 77 | #else 78 | return dlsym( m_handle, symbol.c_str() ); 79 | #endif 80 | } 81 | -------------------------------------------------------------------------------- /XLEngine/PluginFramework/dynamicLibrary.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | using namespace std; 5 | 6 | class DynamicLibrary 7 | { 8 | public: 9 | 10 | static DynamicLibrary *load(const string& path, string& errorString); 11 | ~DynamicLibrary(); 12 | 13 | void *getSymbol(const string& name); 14 | 15 | private: 16 | DynamicLibrary(); 17 | 18 | DynamicLibrary(void *handle); 19 | DynamicLibrary(const DynamicLibrary &); 20 | 21 | private: 22 | void *m_handle; 23 | }; 24 | -------------------------------------------------------------------------------- /XLEngine/PluginFramework/pluginManager.cpp: -------------------------------------------------------------------------------- 1 | #include "pluginManager.h" 2 | #include "dynamicLibrary.h" 3 | #include "../types.h" 4 | 5 | DynamicLibrary *PluginManager::m_gameLib; 6 | XL_RunFunc PluginManager::m_runFunc; 7 | 8 | bool PluginManager::init() 9 | { 10 | m_gameLib = NULL; 11 | return true; 12 | } 13 | 14 | void PluginManager::destroy() 15 | { 16 | //Unload the current game. 17 | unloadGame(); 18 | } 19 | 20 | XL_RunFunc PluginManager::initGame(const string& path) 21 | { 22 | //first unload the game, since we can only have one at a time right now. 23 | unloadGame(); 24 | 25 | //load the game lib. 26 | string errorString; 27 | m_gameLib = DynamicLibrary::load(path, errorString); 28 | if (!m_gameLib) // not a dynamic library? 29 | { 30 | return NULL; 31 | } 32 | 33 | //get the run function. 34 | m_runFunc = (XL_RunFunc)(m_gameLib->getSymbol("RunGame")); 35 | if (!m_runFunc) // dynamic library missing entry point? 36 | { 37 | return NULL; 38 | } 39 | 40 | return m_runFunc; 41 | } 42 | 43 | void PluginManager::unloadGame() 44 | { 45 | if ( m_gameLib ) 46 | { 47 | delete m_gameLib; 48 | m_gameLib = NULL; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /XLEngine/PluginFramework/pluginManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../xlServices.h" 5 | 6 | using namespace std; 7 | 8 | class DynamicLibrary; 9 | typedef void (*XL_RunFunc)(short int, char*[], XLEngineServices*); 10 | 11 | class PluginManager 12 | { 13 | public: 14 | 15 | static bool init(); 16 | static void destroy(); 17 | 18 | static XL_RunFunc initGame(const string& path); 19 | static void unloadGame(); 20 | 21 | private: 22 | static DynamicLibrary *m_gameLib; 23 | static XL_RunFunc m_runFunc; 24 | }; 25 | -------------------------------------------------------------------------------- /XLEngine/Sound/fluidsynthDLL.cpp: -------------------------------------------------------------------------------- 1 | #include "fluidsynthDLL.h" 2 | #include "../log.h" 3 | #include "../PluginFramework/dynamicLibrary.h" 4 | #include 5 | 6 | static DynamicLibrary* s_fluidsynthDLL = NULL; 7 | 8 | xl_new_fluid_settings_def xl_new_fluid_settings; 9 | xl_fluid_settings_setstr_def xl_fluid_settings_setstr; 10 | xl_new_fluid_synth_def xl_new_fluid_synth; 11 | xl_new_fluid_sequencer2_def xl_new_fluid_sequencer2; 12 | xl_fluid_settings_getnum_def xl_fluid_settings_getnum; 13 | xl_fluid_synth_sfload_def xl_fluid_synth_sfload; 14 | xl_fluid_sequencer_register_fluidsynth_def xl_fluid_sequencer_register_fluidsynth; 15 | xl_new_fluid_player_def xl_new_fluid_player; 16 | xl_delete_fluid_settings_def xl_delete_fluid_settings; 17 | xl_delete_fluid_synth_def xl_delete_fluid_synth; 18 | xl_delete_fluid_sequencer_def xl_delete_fluid_sequencer; 19 | xl_delete_fluid_player_def xl_delete_fluid_player; 20 | xl_fluid_player_stop_def xl_fluid_player_stop; 21 | xl_fluid_player_add_def xl_fluid_player_add; 22 | xl_fluid_player_get_status_def xl_fluid_player_get_status; 23 | xl_fluid_synth_write_s16_def xl_fluid_synth_write_s16; 24 | xl_fluid_player_play_def xl_fluid_player_play; 25 | xl_fluid_player_set_loop_def xl_fluid_player_set_loop; 26 | 27 | bool loadFluidsythDLL() 28 | { 29 | std::string errorString; 30 | s_fluidsynthDLL = DynamicLibrary::load("libfluidsynth", errorString); 31 | if (!s_fluidsynthDLL) 32 | { 33 | return false; 34 | } 35 | 36 | new_fluid_settings = (xl_new_fluid_settings_def)s_fluidsynthDLL->getSymbol("new_fluid_settings"); 37 | new_fluid_synth = (xl_new_fluid_synth_def)s_fluidsynthDLL->getSymbol("new_fluid_synth"); 38 | new_fluid_sequencer2 = (xl_new_fluid_sequencer2_def)s_fluidsynthDLL->getSymbol("new_fluid_sequencer2"); 39 | new_fluid_player = (xl_new_fluid_player_def)s_fluidsynthDLL->getSymbol("new_fluid_player"); 40 | delete_fluid_settings = (xl_delete_fluid_settings_def)s_fluidsynthDLL->getSymbol("delete_fluid_settings"); 41 | delete_fluid_synth = (xl_delete_fluid_synth_def)s_fluidsynthDLL->getSymbol("delete_fluid_synth"); 42 | delete_fluid_sequencer = (xl_delete_fluid_sequencer_def)s_fluidsynthDLL->getSymbol("delete_fluid_sequencer"); 43 | delete_fluid_player = (xl_delete_fluid_player_def)s_fluidsynthDLL->getSymbol("delete_fluid_player"); 44 | fluid_settings_setstr = (xl_fluid_settings_setstr_def)s_fluidsynthDLL->getSymbol("fluid_settings_setstr"); 45 | fluid_settings_getnum = (xl_fluid_settings_getnum_def)s_fluidsynthDLL->getSymbol("fluid_settings_getnum"); 46 | fluid_synth_sfload = (xl_fluid_synth_sfload_def)s_fluidsynthDLL->getSymbol("fluid_synth_sfload"); 47 | fluid_synth_write_s16 = (xl_fluid_synth_write_s16_def)s_fluidsynthDLL->getSymbol("fluid_synth_write_s16"); 48 | fluid_sequencer_register_fluidsynth = (xl_fluid_sequencer_register_fluidsynth_def)s_fluidsynthDLL->getSymbol("fluid_sequencer_register_fluidsynth"); 49 | fluid_player_stop = (xl_fluid_player_stop_def)s_fluidsynthDLL->getSymbol("fluid_player_stop"); 50 | fluid_player_add = (xl_fluid_player_add_def)s_fluidsynthDLL->getSymbol("fluid_player_add"); 51 | fluid_player_get_status = (xl_fluid_player_get_status_def)s_fluidsynthDLL->getSymbol("fluid_player_get_status"); 52 | fluid_player_play = (xl_fluid_player_play_def)s_fluidsynthDLL->getSymbol("fluid_player_play"); 53 | fluid_player_set_loop = (xl_fluid_player_set_loop_def)s_fluidsynthDLL->getSymbol("fluid_player_set_loop"); 54 | 55 | return true; 56 | } 57 | 58 | void unloadFluidsynthDLL() 59 | { 60 | delete s_fluidsynthDLL; 61 | s_fluidsynthDLL = NULL; 62 | } 63 | 64 | s32 fillFluidBuffer(u32 requestedChunkSize, u8* chunkData, f64 sampleRate, fluid_synth_t* synth, fluid_player_t* player) 65 | { 66 | if (fluid_player_get_status(player) != FLUID_PLAYER_PLAYING) 67 | { 68 | return 0; 69 | } 70 | 71 | s32 res = fluid_synth_write_s16(synth, requestedChunkSize/4, chunkData, 0, 2, chunkData, 1, 2); 72 | if (res != FLUID_OK) 73 | { 74 | LOG( LOG_WARNING, "error during midi synthesis: %d", res ); 75 | return 0; 76 | } 77 | 78 | return requestedChunkSize; 79 | } -------------------------------------------------------------------------------- /XLEngine/Sound/fluidsynthDLL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../types.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | bool loadFluidsythDLL(); 10 | void unloadFluidsynthDLL(); 11 | s32 fillFluidBuffer(u32 requestedChunkSize, u8* chunkData, f64 sampleRate, fluid_synth_t* synth, fluid_player_t* player); 12 | 13 | typedef fluid_settings_t* (*xl_new_fluid_settings_def)(void); 14 | typedef int (*xl_fluid_settings_setstr_def)(fluid_settings_t*, const char*, const char*); 15 | typedef fluid_synth_t* (*xl_new_fluid_synth_def)(fluid_settings_t*); 16 | typedef fluid_sequencer_t* (*xl_new_fluid_sequencer2_def)(int); 17 | typedef int (*xl_fluid_settings_getnum_def)(fluid_settings_t*, const char*, double*); 18 | typedef int (*xl_fluid_synth_sfload_def)(fluid_synth_t*, const char*, int); 19 | typedef short (*xl_fluid_sequencer_register_fluidsynth_def)(fluid_sequencer_t*, fluid_synth_t*); 20 | typedef fluid_player_t* (*xl_new_fluid_player_def)(fluid_synth_t*); 21 | typedef void (*xl_delete_fluid_settings_def)(fluid_settings_t*); 22 | typedef int (*xl_delete_fluid_synth_def)(fluid_synth_t*); 23 | typedef void (*xl_delete_fluid_sequencer_def)(fluid_sequencer_t*); 24 | typedef int (*xl_delete_fluid_player_def)(fluid_player_t*); 25 | typedef int (*xl_fluid_player_stop_def)(fluid_player_t*); 26 | typedef int (*xl_fluid_player_add_def)(fluid_player_t*, const char*); 27 | typedef int (*xl_fluid_player_get_status_def)(fluid_player_t*); 28 | typedef int (*xl_fluid_synth_write_s16_def)(fluid_synth_t*, int, void*, int, int, void*, int, int); 29 | typedef int (*xl_fluid_player_play_def)(fluid_player_t*); 30 | typedef int (*xl_fluid_player_set_loop_def)(fluid_player_t*, int); 31 | 32 | extern xl_new_fluid_settings_def xl_new_fluid_settings; 33 | extern xl_fluid_settings_setstr_def xl_fluid_settings_setstr; 34 | extern xl_new_fluid_synth_def xl_new_fluid_synth; 35 | extern xl_new_fluid_sequencer2_def xl_new_fluid_sequencer2; 36 | extern xl_fluid_settings_getnum_def xl_fluid_settings_getnum; 37 | extern xl_fluid_synth_sfload_def xl_fluid_synth_sfload; 38 | extern xl_fluid_sequencer_register_fluidsynth_def xl_fluid_sequencer_register_fluidsynth; 39 | extern xl_new_fluid_player_def xl_new_fluid_player; 40 | extern xl_delete_fluid_settings_def xl_delete_fluid_settings; 41 | extern xl_delete_fluid_synth_def xl_delete_fluid_synth; 42 | extern xl_delete_fluid_sequencer_def xl_delete_fluid_sequencer; 43 | extern xl_delete_fluid_player_def xl_delete_fluid_player; 44 | extern xl_fluid_player_stop_def xl_fluid_player_stop; 45 | extern xl_fluid_player_add_def xl_fluid_player_add; 46 | extern xl_fluid_player_get_status_def xl_fluid_player_get_status; 47 | extern xl_fluid_synth_write_s16_def xl_fluid_synth_write_s16; 48 | extern xl_fluid_player_play_def xl_fluid_player_play; 49 | extern xl_fluid_player_set_loop_def xl_fluid_player_set_loop; 50 | 51 | #define new_fluid_settings xl_new_fluid_settings 52 | #define fluid_settings_setstr xl_fluid_settings_setstr 53 | #define new_fluid_synth xl_new_fluid_synth 54 | #define new_fluid_sequencer2 xl_new_fluid_sequencer2 55 | #define fluid_settings_getnum xl_fluid_settings_getnum 56 | #define fluid_synth_sfload xl_fluid_synth_sfload 57 | #define fluid_sequencer_register_fluidsynth xl_fluid_sequencer_register_fluidsynth 58 | #define new_fluid_player xl_new_fluid_player 59 | #define delete_fluid_settings xl_delete_fluid_settings 60 | #define delete_fluid_synth xl_delete_fluid_synth 61 | #define delete_fluid_sequencer xl_delete_fluid_sequencer 62 | #define delete_fluid_player xl_delete_fluid_player 63 | #define fluid_player_stop xl_fluid_player_stop 64 | #define fluid_player_add xl_fluid_player_add 65 | #define fluid_player_get_status xl_fluid_player_get_status 66 | #define fluid_synth_write_s16 xl_fluid_synth_write_s16 67 | #define fluid_player_play xl_fluid_player_play 68 | #define fluid_player_set_loop xl_fluid_player_set_loop -------------------------------------------------------------------------------- /XLEngine/Sound/midi.cpp: -------------------------------------------------------------------------------- 1 | #define WILDMIDI_STATIC 1 2 | #define AUDIODRV_OPENAL 1 3 | 4 | #include "midi.h" 5 | #include "sound.h" 6 | #include "../log.h" 7 | #include "../Threads/mutex.h" 8 | #include "wildmidi_lib.h" 9 | #include "fluidsynthDLL.h" 10 | 11 | #include 12 | 13 | namespace Midi 14 | { 15 | #define LOCK() s_mutex->lock() 16 | #define UNLOCK() s_mutex->unlock() 17 | const f32 c_volumeScale[] = { 0.5f, 1.0f }; 18 | 19 | static MidiFormat s_midiFormat; 20 | 21 | static void* s_song = NULL; 22 | static fluid_settings_t* s_fluidSettings = NULL; 23 | static fluid_synth_t* s_fluidSynth = NULL; 24 | static fluid_sequencer_t* s_fluidSeq = NULL; 25 | static fluid_player_t* s_fluidPlayer = NULL; 26 | static bool s_fluidPlaying = false; 27 | 28 | static bool s_initialized = false; 29 | static Mutex* s_mutex = NULL; 30 | 31 | static f64 s_sampleRate = 0.0; 32 | static f32 s_volume = c_volumeScale[0]; 33 | 34 | void midiStreamCallback(void* userData, u32 requestedChunkSize, u8* chunkData); 35 | 36 | bool init(MidiFormat format, const char* patchLoc) 37 | { 38 | free(); 39 | s_mutex = Mutex::create(); 40 | s_midiFormat = format; 41 | 42 | if (s_midiFormat == MFMT_GUS_PATCH) 43 | { 44 | s_volume = c_volumeScale[0]; 45 | s_sampleRate = 32072.0; 46 | if (WildMidi_Init(patchLoc, 32072, WM_MO_ENHANCED_RESAMPLING) >= 0) 47 | { 48 | s_initialized = true; 49 | WildMidi_MasterVolume(100); 50 | 51 | return true; 52 | } 53 | } 54 | else if (s_midiFormat == MFMT_SOUND_FONT) 55 | { 56 | s_volume = c_volumeScale[1]; 57 | if (!loadFluidsythDLL()) 58 | { 59 | LOG( LOG_ERROR, "cannot find or load the \"libfluidsynth\" dynamic library." ); 60 | return false; 61 | } 62 | 63 | s_fluidSettings = new_fluid_settings(); 64 | fluid_settings_setstr(s_fluidSettings, "player.timing-source", "sample"); 65 | fluid_settings_setstr(s_fluidSettings, "synth.lock-memory", 0); 66 | fluid_settings_setstr(s_fluidSettings, "synth.chorus-active", "0"); 67 | 68 | s_fluidSynth = new_fluid_synth(s_fluidSettings); 69 | if (fluid_synth_sfload(s_fluidSynth, patchLoc, 1) < 0) 70 | { 71 | LOG( LOG_ERROR, "cannot load sound font \"%s\"", patchLoc ); 72 | unloadFluidsynthDLL(); 73 | return false; 74 | } 75 | 76 | s_fluidSeq = new_fluid_sequencer2(false); 77 | fluid_sequencer_register_fluidsynth(s_fluidSeq, s_fluidSynth); 78 | fluid_settings_getnum(s_fluidSettings, "synth.sample-rate", &s_sampleRate); 79 | 80 | s_initialized = true; 81 | s_fluidPlayer = new_fluid_player(s_fluidSynth); 82 | return true; 83 | } 84 | 85 | return false; 86 | } 87 | 88 | void free() 89 | { 90 | if (s_initialized) 91 | { 92 | stop(); 93 | if (s_midiFormat == MFMT_GUS_PATCH) 94 | { 95 | WildMidi_Shutdown(); 96 | } 97 | else if (s_midiFormat == MFMT_SOUND_FONT) 98 | { 99 | delete_fluid_settings(s_fluidSettings); 100 | delete_fluid_synth(s_fluidSynth); 101 | delete_fluid_sequencer(s_fluidSeq); 102 | delete_fluid_player(s_fluidPlayer); 103 | 104 | unloadFluidsynthDLL(); 105 | } 106 | 107 | s_initialized = false; 108 | 109 | delete s_mutex; 110 | } 111 | } 112 | 113 | void setVolume(u32 volume) 114 | { 115 | s_volume = f32(volume)*0.01f * c_volumeScale[ s_midiFormat ]; 116 | } 117 | 118 | void playResume() 119 | { 120 | Sound::startMusic( midiStreamCallback, NULL, s_volume, true, 16, u32(s_sampleRate) ); 121 | } 122 | 123 | void pause() 124 | { 125 | Sound::pauseMusic(); 126 | } 127 | 128 | void stop() 129 | { 130 | Sound::stopMusic(); 131 | LOCK(); 132 | if (s_song && s_midiFormat == MFMT_GUS_PATCH) 133 | { 134 | WildMidi_Close(s_song); 135 | } 136 | else if (s_song && s_midiFormat == MFMT_SOUND_FONT) 137 | { 138 | fluid_player_stop(s_fluidPlayer); 139 | s_fluidPlaying = false; 140 | } 141 | s_song = NULL; 142 | UNLOCK(); 143 | } 144 | 145 | //This is the proper way to handle midi in many cases (depending on the game) 146 | //Using this function the game can provide the midi data, for example when using iMuse. 147 | void addMidiData(u8* data, u32 size) 148 | { 149 | //Stub... 150 | //Obviously I need to fill this in, but I am going to wait until I have a test case. 151 | } 152 | 153 | bool loadMidiFile(const char* file) 154 | { 155 | LOCK(); 156 | if (s_midiFormat == MFMT_GUS_PATCH) 157 | { 158 | s_song = WildMidi_Open(file); 159 | } 160 | else if (s_midiFormat == MFMT_SOUND_FONT) 161 | { 162 | s_song = (void*)(fluid_player_add(s_fluidPlayer, file) >= 0 ? 1 : 0); 163 | s_fluidPlaying = false; 164 | } 165 | UNLOCK(); 166 | return (s_song!=NULL); 167 | } 168 | 169 | void midiStreamCallback(void* userData, u32 requestedChunkSize, u8* chunkData) 170 | { 171 | LOCK(); 172 | s32 soundSize = 0; 173 | s32 totalSize = 0; 174 | while (totalSize < (s32)requestedChunkSize) 175 | { 176 | if (s_midiFormat == MFMT_GUS_PATCH) 177 | { 178 | soundSize = WildMidi_GetOutput(s_song, (char*)&chunkData[totalSize], requestedChunkSize-totalSize); 179 | } 180 | else if (s_midiFormat == MFMT_SOUND_FONT) 181 | { 182 | if (!s_fluidPlaying) 183 | { 184 | fluid_player_play( s_fluidPlayer ); 185 | fluid_player_set_loop(s_fluidPlayer, -1); 186 | s_fluidPlaying = true; 187 | } 188 | soundSize = fillFluidBuffer(requestedChunkSize, chunkData, s_sampleRate, s_fluidSynth, s_fluidPlayer); 189 | } 190 | 191 | //we've finished the loop, start the song all over again. 192 | if (soundSize == 0) 193 | { 194 | if (s_midiFormat == MFMT_GUS_PATCH) 195 | { 196 | unsigned long beginning = 0; 197 | WildMidi_FastSeek(s_song, &beginning); 198 | soundSize = WildMidi_GetOutput(s_song, (char*)&chunkData[totalSize], requestedChunkSize-totalSize); 199 | } 200 | else if (s_midiFormat == MFMT_SOUND_FONT) 201 | { 202 | LOG( LOG_ERROR, "midi synthesizer should handle looping." ); 203 | } 204 | } 205 | 206 | totalSize += soundSize; 207 | }; 208 | UNLOCK(); 209 | } 210 | }; 211 | -------------------------------------------------------------------------------- /XLEngine/Sound/midi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../types.h" 3 | 4 | enum MidiFormat 5 | { 6 | MFMT_GUS_PATCH = 0, 7 | MFMT_SOUND_FONT, 8 | MFMT_COUNT 9 | }; 10 | 11 | namespace Midi 12 | { 13 | bool init(MidiFormat format, const char* patchLoc); 14 | void free(); 15 | 16 | void setVolume(u32 volume); 17 | void playResume(); 18 | void pause(); 19 | void stop(); 20 | 21 | void addMidiData(u8* data, u32 size); 22 | bool loadMidiFile(const char* file); 23 | }; 24 | -------------------------------------------------------------------------------- /XLEngine/Sound/oggVorbis.cpp: -------------------------------------------------------------------------------- 1 | #include "midi.h" 2 | #include "sound.h" 3 | #include "oggVorbis.h" 4 | #include "../log.h" 5 | #include "../filestream.h" 6 | #include "../Threads/mutex.h" 7 | #include 8 | #include 9 | 10 | namespace oggVorbis 11 | { 12 | #define LOCK() s_mutex->lock() 13 | #define UNLOCK() s_mutex->unlock() 14 | 15 | const f32 c_volumeScale = 0.5f; 16 | 17 | static bool s_initialized = false; 18 | static FileStream s_fileStream; 19 | static OggVorbis_File s_oggFile; 20 | static Bool s_stereo; 21 | static u32 s_samplingRate; 22 | static f32 s_volume = c_volumeScale; 23 | 24 | static Mutex* s_mutex = NULL; 25 | 26 | void oggStreamCallback(void* userData, u32 requestedChunkSize, u8* chunkData); 27 | 28 | bool init() 29 | { 30 | free(); 31 | s_mutex = Mutex::create(); 32 | 33 | return true; 34 | } 35 | 36 | void free() 37 | { 38 | if (s_initialized) 39 | { 40 | stop(); 41 | s_initialized = false; 42 | } 43 | delete s_mutex; 44 | } 45 | 46 | void setVolume(u32 volume) 47 | { 48 | s_volume = f32(volume) * 0.01f * c_volumeScale; 49 | } 50 | 51 | void playResume() 52 | { 53 | Sound::startMusic( oggStreamCallback, NULL, s_volume, s_stereo, 16, s_samplingRate ); 54 | } 55 | 56 | void pause() 57 | { 58 | Sound::pauseMusic(); 59 | } 60 | 61 | void stop() 62 | { 63 | Sound::stopMusic(); 64 | LOCK(); 65 | if (s_fileStream.isOpen()) 66 | { 67 | ov_clear(&s_oggFile); 68 | s_fileStream.close(); 69 | } 70 | UNLOCK(); 71 | } 72 | 73 | bool loadOGG(const char* file) 74 | { 75 | LOCK(); 76 | if (s_fileStream.open(file, FileStream::MODE_READ)) 77 | { 78 | void* dataSource = s_fileStream.getFileHandle(); 79 | if (ov_open_callbacks(dataSource, &s_oggFile, NULL, 0, OV_CALLBACKS_NOCLOSE) < 0) 80 | { 81 | LOG( LOG_ERROR, "The Ogg file \"%s\" is not a valid.", file); 82 | UNLOCK(); 83 | return false; 84 | } 85 | 86 | const vorbis_info* info = ov_info(&s_oggFile, -1); 87 | s_stereo = info->channels > 1; 88 | s_samplingRate = info->rate; 89 | 90 | UNLOCK(); 91 | return true; 92 | } 93 | 94 | UNLOCK(); 95 | return false; 96 | } 97 | 98 | void oggStreamCallback(void* userData, u32 requestedChunkSize, u8* chunkData) 99 | { 100 | LOCK(); 101 | 102 | s32 totalSize = 0; 103 | while (totalSize < (s32)requestedChunkSize) 104 | { 105 | s32 bitStream = 0; 106 | s32 soundSize = ov_read(&s_oggFile, (char*)&chunkData[totalSize], requestedChunkSize-totalSize, 0, 2, 1, &bitStream); 107 | 108 | //theoretically the sampling rate can change throughout the song... 109 | //however this is not supported by the XL Engine currently (it would require more work in the sound layer). 110 | 111 | //we've finished the loop, start the song all over again. 112 | if (soundSize == 0) 113 | { 114 | ov_time_seek(&s_oggFile, 0.0); 115 | soundSize = ov_read(&s_oggFile, (char*)&chunkData[totalSize], requestedChunkSize-totalSize, 0, 2, 1, &bitStream); 116 | } 117 | else if (soundSize < 0) //error in the bit stream. 118 | { 119 | LOG( LOG_ERROR, "ogg streaming error: %d", soundSize ); 120 | soundSize = 0; 121 | break; 122 | } 123 | 124 | totalSize += soundSize; 125 | }; 126 | 127 | UNLOCK(); 128 | } 129 | }; -------------------------------------------------------------------------------- /XLEngine/Sound/oggVorbis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../types.h" 3 | 4 | namespace oggVorbis 5 | { 6 | bool init(); 7 | void free(); 8 | 9 | void setVolume(u32 volume); 10 | void playResume(); 11 | void pause(); 12 | void stop(); 13 | 14 | bool loadOGG(const char* file); 15 | }; 16 | -------------------------------------------------------------------------------- /XLEngine/Sound/sound.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////// 2 | // XL Engine Sound System 3 | // The sound system manages resources such as 4 | // buffers and source (i.e. voices). 5 | // Fire and forget sounds, looping sounds and 6 | // sounds that are tweaked over time are supported. 7 | //////////////////////////////////////////////////// 8 | // The Sound System does not manage file I/O, sound 9 | // data is passed into the system directly. 10 | //////////////////////////////////////////////////// 11 | 12 | #pragma once 13 | #include "../types.h" 14 | #include "../xlServices.h" 15 | 16 | typedef u32 SoundHandle; 17 | #define INVALID_SOUND_HANDLE 0xffffffff 18 | 19 | typedef void (*MusicCallback)(void* userData, u32 requestedChunkSize, u8* chunkData); 20 | 21 | namespace Sound 22 | { 23 | //system setup 24 | bool init(); 25 | void free(); 26 | void update(); 27 | //stops all sources, marks all buffers as reusable. 28 | void reset(); 29 | //optional callback - called whenever sounds "end" 30 | void setCallback(XLSoundCallback callback); 31 | 32 | ////////////////////////////////////////////////////////////////// 33 | //Sets the global sound volume (affects all sounds). 34 | ////////////////////////////////////////////////////////////////// 35 | // Inputs: 36 | // volume - the volume level from 0 = no sound to 1 = max volume. 37 | ////////////////////////////////////////////////////////////////// 38 | void setGlobalVolume(f32 volume); 39 | 40 | ////////////////////////////////////////////////////////////////// 41 | //Starts streaming music playback. 42 | ////////////////////////////////////////////////////////////////// 43 | // Inputs: 44 | // streamCallback - this callback is called whenever data needs to 45 | // be loaded into the streaming sound buffers. 46 | ////////////////////////////////////////////////////////////////// 47 | bool startMusic(MusicCallback streamCallback, void* userData, f32 volume, Bool stereo, u32 bitsPerSample, u32 samplingRate); 48 | // Stops music playback and pauses music update. 49 | void stopMusic(); 50 | // Pause the music, it can be resumed from the same spot. 51 | void pauseMusic(); 52 | // Resume paused music. 53 | void resumeMusic(); 54 | 55 | ////////////////////////////////////////////////////////////////// 56 | //Generic 2D sound play function 57 | ////////////////////////////////////////////////////////////////// 58 | // Inputs: 59 | // name - unique name of the sound, used to share sound data. 60 | // data - the sound data to play. 61 | // size - the size of the sound data. 62 | // type - the type of sound data provided (see SoundType) 63 | // info - information required to play the sound, such as sampling 64 | // rate (see SoundInfo). 65 | // looping - if set to true, the sound will loop until stopped. 66 | //----------------------------------------------------------------- 67 | // Output: 68 | // SoundHandle - used by the client to check on, adjust, pause or 69 | // stop the sound. 70 | ////////////////////////////////////////////////////////////////// 71 | SoundHandle playSound2D(const char* name, const void* data, u32 size, u32 type, SoundInfo* info, Bool looping); 72 | 73 | ////////////////////////////////////////////////////////////////// 74 | //Play a "fire and forget" 2D sound. 75 | ////////////////////////////////////////////////////////////////// 76 | // Output: 77 | // bool - returns true if the sound was successfully played. 78 | ////////////////////////////////////////////////////////////////// 79 | Bool playOneShot2D(const char* name, const void* data, u32 size, u32 type, SoundInfo* info); 80 | 81 | ////////////////////////////////////////////////////////////////// 82 | //Play a looping 2D sound. 83 | ////////////////////////////////////////////////////////////////// 84 | SoundHandle playSoundLooping(const char* name, const void* data, u32 size, u32 type, SoundInfo* info); 85 | 86 | ////////////////////////////////////////////////////////////////// 87 | //Check sound state. 88 | ////////////////////////////////////////////////////////////////// 89 | Bool isActive(SoundHandle handle); 90 | Bool isPlaying(SoundHandle handle); 91 | Bool isLooping(SoundHandle handle); 92 | //get the number of sounds currently playing. 93 | s32 soundsPlaying(); 94 | 95 | ////////////////////////////////////////////////////////////////// 96 | //Change sound state. 97 | ////////////////////////////////////////////////////////////////// 98 | //stops the sound, after calling this function the handle will no 99 | //longer be valid. 100 | void stopSound(SoundHandle handle); 101 | void stopAllSounds(); 102 | 103 | //pauses a sound. The handle is still valid and the source still 104 | //used. Do not leave sounds paused for too long. 105 | void pauseSound(SoundHandle handle); 106 | void resumeSound(SoundHandle handle); 107 | 108 | //for 2D sounds, this allows the stereo panning to be adjusted. 109 | //pan: -1 = left, 0 = middle, 1 = right 110 | void setPan(SoundHandle handle, f32 pan); 111 | 112 | //change the sound volume (0 = not audible, 1 = full volume) 113 | void setVolume(SoundHandle handle, f32 volume); 114 | }; 115 | -------------------------------------------------------------------------------- /XLEngine/Sound/sound_inl.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////// 2 | // Internal inline functions used 3 | // by the sound system. 4 | // This should ONLY be included by 5 | // "sound.cpp" 6 | //////////////////////////////////// 7 | #pragma once 8 | #include "../types.h" 9 | 10 | namespace Sound 11 | { 12 | extern u32* s_activeSounds; 13 | 14 | inline u32 getHandleBuffer(u32 handle) { return handle&0xff; } 15 | inline u32 getHandleSource(u32 handle) { return (handle>>8)&0x1f; } 16 | inline u32 getHandleAllocID(u32 handle) { return (handle>>13)&0x7ffff; } 17 | 18 | inline u32 getActiveBuffer(u32 sourceID) { return s_activeSounds[sourceID]&0xff; } 19 | inline u32 getActiveAllocID(u32 sourceID) { return (s_activeSounds[sourceID]>>8)&0x7ffff; } 20 | inline bool checkActiveFlag(u32 sourceID, u32 flag) { return (s_activeSounds[sourceID]&flag)!=0; } 21 | 22 | inline void setActiveBuffer(u32 sourceID, u32 bufferID) { s_activeSounds[sourceID] &= ~0xff; s_activeSounds[sourceID] |= bufferID; } 23 | inline void setActiveAllocID(u32 sourceID, u32 allocID) { s_activeSounds[sourceID] &= ~(0x7ffff<<8); s_activeSounds[sourceID] |= (allocID<<8); } 24 | inline void setActiveFlag(u32 sourceID, u32 flag) { s_activeSounds[sourceID] |= flag; } 25 | inline void clearActiveFlag(u32 sourceID, u32 flag) { s_activeSounds[sourceID] &= ~flag; } 26 | }; 27 | -------------------------------------------------------------------------------- /XLEngine/Sound/vocFormat.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////// 2 | // Incomplete VOC format 3 | // (WIP) 4 | /////////////////////////// 5 | 6 | #include "vocFormat.h" 7 | #include "../log.h" 8 | #include 9 | 10 | namespace Voc 11 | { 12 | #pragma pack(push, 1) 13 | struct VocHeader 14 | { 15 | u8 Description[20]; 16 | u16 DataBlockOffset; 17 | u16 Version; 18 | u16 IDCode; 19 | }; 20 | 21 | struct VocBlock1_Header 22 | { 23 | u8 tc; 24 | u8 pack; 25 | }; 26 | 27 | struct VocBlock9_Header 28 | { 29 | u32 samplesPerSecond; 30 | u8 bitsPerSample; 31 | u8 channel; 32 | u16 format; 33 | u8 reserved[4]; 34 | }; 35 | 36 | enum VocType 37 | { 38 | VT_8BIT_UNSIGNED=0, 39 | VT_4BIT_ADPCM, 40 | VT_2_6BIT_ADPCM, 41 | VT_2_BIT_ADPCM, 42 | VT_COUNT 43 | }; 44 | #pragma pack(pop) 45 | 46 | void* s_rawData = NULL; 47 | u32 s_rawSize = 0; 48 | u32 s_sampleRate = 0; 49 | 50 | bool readVocBlock1(u8* soundData, u32& index, u8*& outData, u32& outLength, u32& sampleRate) 51 | { 52 | VocType type = VT_COUNT; 53 | u32 a = soundData[index]; index++; 54 | u32 b = soundData[index]; index++; 55 | u32 c = soundData[index]; index++; 56 | u32 len = (c<<16) | (b<<8) | a; 57 | 58 | VocBlock1_Header* header = (VocBlock1_Header*)&soundData[index]; index += sizeof(VocBlock1_Header); 59 | 60 | sampleRate = 1000000/256 - (u32)header->tc; 61 | len -= 2; 62 | 63 | u8* temp = &soundData[index]; index += len; 64 | 65 | switch (header->pack) 66 | { 67 | case 0: 68 | type = VT_8BIT_UNSIGNED; 69 | break; 70 | case 1: 71 | type = VT_4BIT_ADPCM; 72 | break; 73 | case 2: 74 | type = VT_2_6BIT_ADPCM; 75 | break; 76 | case 3: 77 | type = VT_2_BIT_ADPCM; 78 | break; 79 | } 80 | 81 | outLength = len; 82 | outData = temp; 83 | 84 | return true; 85 | } 86 | 87 | bool readVocBlock9(u8* soundData, u32& index, u8*& outData, u32& outLength, u32& sampleRate) 88 | { 89 | u32 a = soundData[index]; index++; 90 | u32 b = soundData[index]; index++; 91 | u32 c = soundData[index]; index++; 92 | u32 len = (c<<16) | (b<<8) | a; 93 | 94 | VocBlock9_Header* header = (VocBlock9_Header*)&soundData[index]; index += sizeof(VocBlock9_Header); 95 | sampleRate = header->samplesPerSecond; 96 | 97 | len -= 12; 98 | switch(header->format) 99 | { 100 | case 0x0000: 101 | //cout<<" PCM "; 102 | break; 103 | case 0x0001: 104 | case 0x0002: 105 | case 0x0200: 106 | case 0x0003: 107 | //cout<<" ADPCM "; 108 | break; 109 | case 0x0004: 110 | //cout<<" Signed "; 111 | break; 112 | case 0x0006: 113 | //cout<<" ALAW "; 114 | break; 115 | case 0x0007: 116 | //cout<<" MULAW "; 117 | break; 118 | default: 119 | //cout<<"Unsupported Format!\n"; 120 | break; 121 | } 122 | 123 | outData = &soundData[index]; 124 | outLength = len; 125 | 126 | return true; 127 | } 128 | 129 | bool read(u8* voc, u32 size) 130 | { 131 | u32 index = 0; 132 | VocHeader* header = (VocHeader*)&voc[index]; index += sizeof(VocHeader); 133 | index = header->DataBlockOffset; 134 | 135 | u8* rawData = NULL; 136 | u32 rawLen = 0; 137 | u32 sampleRate = 0; 138 | 139 | char eof = 0; 140 | while (eof == 0) 141 | { 142 | char blocktype = voc[index]; index++; 143 | switch (blocktype) 144 | { 145 | case 0: 146 | eof = 1; 147 | break; 148 | case 1: 149 | readVocBlock1(voc, index, rawData, rawLen, sampleRate); 150 | break; 151 | case 9: 152 | readVocBlock9(voc, index, rawData, rawLen, sampleRate); 153 | break; 154 | default: 155 | eof = 1; 156 | }; 157 | }; 158 | 159 | s_rawData = rawData; 160 | s_rawSize = rawLen; 161 | s_sampleRate = sampleRate; 162 | 163 | return true; 164 | } 165 | 166 | void free() 167 | { 168 | } 169 | 170 | void* getRawData() 171 | { 172 | return s_rawData; 173 | } 174 | 175 | u32 getRawSize() 176 | { 177 | return s_rawSize; 178 | } 179 | 180 | u32 getSampleRate() 181 | { 182 | return s_sampleRate; 183 | } 184 | }; 185 | -------------------------------------------------------------------------------- /XLEngine/Sound/vocFormat.h: -------------------------------------------------------------------------------- 1 | /////////////////////////// 2 | // Incomplete VOC format 3 | // (WIP) 4 | /////////////////////////// 5 | #pragma once 6 | #include "../types.h" 7 | 8 | namespace Voc 9 | { 10 | bool read(u8* voc, u32 size); 11 | void free(); 12 | 13 | void* getRawData(); 14 | u32 getRawSize(); 15 | u32 getSampleRate(); 16 | }; 17 | -------------------------------------------------------------------------------- /XLEngine/Sound/wavFormat.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////// 2 | // WAVE format. 3 | /////////////////////////// 4 | 5 | #include "wavFormat.h" 6 | #include "../log.h" 7 | #include 8 | #include 9 | 10 | namespace Wav 11 | { 12 | void* s_rawData = NULL; 13 | u32 s_rawSize = 0; 14 | u32 s_sampleRate = 0; 15 | 16 | bool s_isStereo = false; 17 | u32 s_bitsPerSample = 0; 18 | 19 | bool read(u8* wav, u32 size) 20 | { 21 | u32 index = 0; 22 | char* riff = (char*)&wav[index]; index += 4; 23 | if (riff[0] != 'R' || riff[1] != 'I' || riff[2] != 'F' || riff[3] != 'F') 24 | { 25 | //invalid wav format 26 | return false; 27 | } 28 | 29 | //skip 4 bytes? 30 | index +=4; 31 | 32 | char* wave = (char*)&wav[index]; index+=4; 33 | if (wave[0] != 'W' || wave[1] != 'A' || wave[2] != 'V' || wave[3] != 'E') 34 | { 35 | //invalid wav format 36 | return false; 37 | } 38 | 39 | char* fmt = (char*)&wav[index]; index+=4; 40 | if (fmt[0] != 'f' || fmt[1] != 'm' || fmt[2] != 't' || fmt[3] != ' ') 41 | { 42 | //invalid wav format 43 | return false; 44 | } 45 | 46 | //skip 4 bytes. 47 | index += 4; 48 | 49 | //read audio format. 50 | s16 audioFormat = *((u16*)&wav[index]); index +=2; 51 | s16 channels = *((u16*)&wav[index]); index +=2; 52 | s32 sampleRate = *((s32*)&wav[index]); index +=4; 53 | s32 byteRate = *((s32*)&wav[index]); index +=4; 54 | index += 2; 55 | s16 bitsPerSample = *((u16*)&wav[index]); index +=2; 56 | 57 | //search for the 'data' block 58 | while (index < size) 59 | { 60 | char* dataStr = (char*)&wav[index]; 61 | if (dataStr[0] == 'd' && dataStr[1] == 'a' && dataStr[2] == 't' && dataStr[3] == 'a') 62 | { 63 | index+=4; 64 | break; 65 | } 66 | else 67 | { 68 | index++; 69 | } 70 | } 71 | if (index >= size) 72 | { 73 | return false; 74 | } 75 | 76 | char* dataStr = (char*)&wav[index-4]; 77 | if (dataStr[0] != 'd' || dataStr[1] != 'a' || dataStr[2] != 't' || dataStr[3] != 'a') 78 | { 79 | //invalid wav format 80 | return false; 81 | } 82 | 83 | const s32 dataChunkSize = *((s32*)&wav[index]); index +=4; 84 | s_rawData = (void*)&wav[index]; 85 | s_rawSize = dataChunkSize; 86 | 87 | s_sampleRate = sampleRate; 88 | 89 | s_isStereo = (channels > 1); 90 | s_bitsPerSample = bitsPerSample; 91 | 92 | return true; 93 | } 94 | 95 | void free() 96 | { 97 | } 98 | 99 | void* getRawData() 100 | { 101 | return s_rawData; 102 | } 103 | 104 | u32 getRawSize() 105 | { 106 | return s_rawSize; 107 | } 108 | 109 | u32 getSampleRate() 110 | { 111 | return s_sampleRate; 112 | } 113 | 114 | bool isStereo() 115 | { 116 | return s_isStereo; 117 | } 118 | 119 | u32 getBitsPerSample() 120 | { 121 | return s_bitsPerSample; 122 | } 123 | }; 124 | -------------------------------------------------------------------------------- /XLEngine/Sound/wavFormat.h: -------------------------------------------------------------------------------- 1 | /////////////////////////// 2 | // Incomplete VOC format 3 | // (WIP) 4 | /////////////////////////// 5 | #pragma once 6 | #include "../types.h" 7 | 8 | namespace Wav 9 | { 10 | bool read(u8* wav, u32 size); 11 | void free(); 12 | 13 | void* getRawData(); 14 | u32 getRawSize(); 15 | u32 getSampleRate(); 16 | 17 | bool isStereo(); 18 | u32 getBitsPerSample(); 19 | }; 20 | -------------------------------------------------------------------------------- /XLEngine/Text/Inconsolata.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luciusDXL/XL-Engine/cd3b467b58d6c35f5d46cf481bc035da30ac21c3/XLEngine/Text/Inconsolata.otf -------------------------------------------------------------------------------- /XLEngine/Text/textSystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../types.h" 4 | #include "../Graphics/graphicsDevice.h" 5 | 6 | typedef u32 FontHandle; 7 | 8 | #define INVALID_FONT_HANDLE 0xffffffff 9 | #define PACK_RGBA_TEX(r, g, b, a) ( (b) | ((g)<<8) | ((r)<<16) | ((a)<<24) ) 10 | #define PACK_RGBA(r, g, b, a) ( (r) | ((g)<<8) | ((b)<<16) | ((a)<<24) ) 11 | 12 | namespace TextSystem 13 | { 14 | enum FontDrawFlags 15 | { 16 | FDRAW_NORMAL = 0, 17 | FDRAW_BOLD = (1<<0), 18 | FDRAW_ITALICS = (1<<1), 19 | }; 20 | 21 | bool init(GraphicsDevice* gdev); 22 | void destroy(); 23 | 24 | //load and cache a font 25 | FontHandle loadFontASCII(const char* name, int height, int drawFlags=FDRAW_NORMAL); 26 | 27 | void setFont(FontHandle handle); 28 | void setColor(Color color); 29 | void print(int x, int y, const char* msg, ...); 30 | u32 print_genQuads(u32& quadCount, int x, int y, const char* msg, ...); 31 | int getStringWidth(FontHandle font, const char* msg); 32 | 33 | void bindTexture(); 34 | }; 35 | -------------------------------------------------------------------------------- /XLEngine/Threads/Linux/mutexLinux.cpp: -------------------------------------------------------------------------------- 1 | #include "mutexLinux.h" 2 | 3 | MutexLinux::MutexLinux() : Mutex() 4 | { 5 | pthread_mutex_init(&m_handle, NULL); 6 | } 7 | 8 | MutexLinux::~MutexLinux() 9 | { 10 | pthread_mutex_destroy(&m_handle); 11 | } 12 | 13 | s32 MutexLinux::lock() 14 | { 15 | pthread_mutex_lock(&m_handle); 16 | return 0; 17 | } 18 | 19 | s32 MutexLinux::unlock() 20 | { 21 | pthread_mutex_unlock(&m_handle); 22 | return 0; 23 | } 24 | 25 | //factory 26 | Mutex* Mutex::create() 27 | { 28 | return new MutexLinux(); 29 | } 30 | -------------------------------------------------------------------------------- /XLEngine/Threads/Linux/mutexLinux.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../mutex.h" 4 | 5 | class MutexLinux : public Mutex 6 | { 7 | public: 8 | MutexLinux(); 9 | virtual ~MutexLinux(); 10 | 11 | virtual s32 lock(); 12 | virtual s32 unlock(); 13 | 14 | private: 15 | pthread_mutex_t m_handle; 16 | }; 17 | -------------------------------------------------------------------------------- /XLEngine/Threads/Linux/threadLinux.cpp: -------------------------------------------------------------------------------- 1 | #include "threadLinux.h" 2 | #include "../../log.h" 3 | 4 | ThreadLinux::ThreadLinux(const char* name, ThreadFunc func, void* userData) : Thread(name, func, userData) 5 | { 6 | m_handle = 0; 7 | } 8 | 9 | ThreadLinux::~ThreadLinux() 10 | { 11 | if (m_handle) 12 | { 13 | //terminate the thread. 14 | pthread_cancel(m_handle); 15 | } 16 | } 17 | 18 | bool ThreadLinux::run() 19 | { 20 | s32 res = pthread_create(&m_handle, NULL, m_func, m_userData); 21 | //create the thread. 22 | if (res == 0) 23 | { 24 | //setThreadName(m_win32Handle, m_name); 25 | } 26 | else 27 | { 28 | m_handle = 0; 29 | LOG( LOG_ERROR, "Thread \"%s\" cannot be run", m_name ); 30 | } 31 | 32 | return (res == 0); 33 | } 34 | 35 | void ThreadLinux::pause() 36 | { 37 | if (!m_handle) { return; } 38 | //to-do. 39 | } 40 | 41 | void ThreadLinux::resume() 42 | { 43 | if (!m_handle) { return; } 44 | //to-do. 45 | } 46 | 47 | //factory 48 | Thread* Thread::create(const char* name, ThreadFunc func, void* userData) 49 | { 50 | return new ThreadLinux(name, func, userData); 51 | } 52 | -------------------------------------------------------------------------------- /XLEngine/Threads/Linux/threadLinux.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../thread.h" 4 | 5 | class ThreadLinux : public Thread 6 | { 7 | public: 8 | ThreadLinux(const char* name, ThreadFunc func, void* userData); 9 | virtual ~ThreadLinux(); 10 | 11 | virtual bool run(); 12 | virtual void pause(); 13 | virtual void resume(); 14 | 15 | protected: 16 | pthread_t m_handle; 17 | }; 18 | -------------------------------------------------------------------------------- /XLEngine/Threads/Win32/mutexWin32.cpp: -------------------------------------------------------------------------------- 1 | #include "mutexWin32.h" 2 | 3 | MutexWin32::MutexWin32() : Mutex() 4 | { 5 | InitializeCriticalSection(&C); 6 | } 7 | 8 | MutexWin32::~MutexWin32() 9 | { 10 | DeleteCriticalSection(&C); 11 | } 12 | 13 | s32 MutexWin32::lock() 14 | { 15 | EnterCriticalSection(&C); 16 | return 0; 17 | } 18 | 19 | s32 MutexWin32::unlock() 20 | { 21 | LeaveCriticalSection(&C); 22 | return 0; 23 | } 24 | 25 | //factory 26 | Mutex* Mutex::create() 27 | { 28 | return new MutexWin32(); 29 | } 30 | -------------------------------------------------------------------------------- /XLEngine/Threads/Win32/mutexWin32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../mutex.h" 4 | 5 | class MutexWin32 : public Mutex 6 | { 7 | public: 8 | MutexWin32(); 9 | virtual ~MutexWin32(); 10 | 11 | virtual s32 lock(); 12 | virtual s32 unlock(); 13 | 14 | private: 15 | mutable CRITICAL_SECTION C; 16 | }; 17 | -------------------------------------------------------------------------------- /XLEngine/Threads/Win32/threadWin32.cpp: -------------------------------------------------------------------------------- 1 | #include "threadWin32.h" 2 | #include "../../log.h" 3 | 4 | void setThreadName(HANDLE threadHandle, const char* threadName); 5 | 6 | ThreadWin32::ThreadWin32(const char* name, ThreadFunc func, void* userData) : Thread(name, func, userData) 7 | { 8 | m_win32Handle = 0; 9 | } 10 | 11 | ThreadWin32::~ThreadWin32() 12 | { 13 | if (m_win32Handle) 14 | { 15 | TerminateThread(m_win32Handle, 0); // Dangerous source of errors! TO-DO: non-crappy solution. :D- 16 | CloseHandle(m_win32Handle); 17 | } 18 | } 19 | 20 | bool ThreadWin32::run() 21 | { 22 | m_win32Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)m_func, m_userData, 0, NULL); 23 | if (m_win32Handle) 24 | { 25 | setThreadName(m_win32Handle, m_name); 26 | } 27 | else 28 | { 29 | LOG( LOG_ERROR, "Thread \"%s\" cannot be run", m_name ); 30 | } 31 | 32 | return m_win32Handle!=0; 33 | } 34 | 35 | void ThreadWin32::pause() 36 | { 37 | if (!m_win32Handle) { return; } 38 | SuspendThread(m_win32Handle); 39 | } 40 | 41 | void ThreadWin32::resume() 42 | { 43 | if (!m_win32Handle) { return; } 44 | ResumeThread(m_win32Handle); 45 | } 46 | 47 | //factory 48 | Thread* Thread::create(const char* name, ThreadFunc func, void* userData) 49 | { 50 | return new ThreadWin32(name, func, userData); 51 | } 52 | 53 | ///////////////////////////////////////////////////////////// 54 | // Wonky Windows specific method for setting the thread name. 55 | ///////////////////////////////////////////////////////////// 56 | #define MS_VC_EXCEPTION 0x406D1388 57 | 58 | #pragma pack(push,8) 59 | typedef struct tagTHREADNAME_INFO 60 | { 61 | DWORD dwType; // Must be 0x1000. 62 | LPCSTR szName; // Pointer to name (in user addr space). 63 | DWORD dwThreadID; // Thread ID (-1=caller thread). 64 | DWORD dwFlags; // Reserved for future use, must be zero. 65 | } THREADNAME_INFO; 66 | #pragma pack(pop) 67 | 68 | void setThreadName(HANDLE threadHandle, const char* threadName) 69 | { 70 | u32 threadID = GetThreadId( threadHandle ); 71 | 72 | THREADNAME_INFO info; 73 | info.dwType = 0x1000; 74 | info.szName = threadName; 75 | info.dwThreadID = threadID; 76 | info.dwFlags = 0; 77 | 78 | //Wonky Windows stuff... (see https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx) 79 | #pragma warning(push) 80 | #pragma warning(disable: 6320 6322) 81 | __try 82 | { 83 | RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); 84 | } 85 | __except (EXCEPTION_EXECUTE_HANDLER) 86 | { 87 | } 88 | #pragma warning(pop) 89 | } 90 | -------------------------------------------------------------------------------- /XLEngine/Threads/Win32/threadWin32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../thread.h" 4 | 5 | class ThreadWin32 : public Thread 6 | { 7 | public: 8 | ThreadWin32(const char* name, ThreadFunc func, void* userData); 9 | virtual ~ThreadWin32(); 10 | 11 | virtual bool run(); 12 | virtual void pause(); 13 | virtual void resume(); 14 | 15 | protected: 16 | HANDLE m_win32Handle; 17 | }; 18 | -------------------------------------------------------------------------------- /XLEngine/Threads/mutex.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../types.h" 3 | 4 | class Mutex 5 | { 6 | public: 7 | virtual ~Mutex() {}; 8 | 9 | virtual s32 lock() = 0; 10 | virtual s32 unlock() = 0; 11 | 12 | protected: 13 | Mutex() {}; 14 | 15 | public: 16 | //static factory function - creates the correct platform dependent version 17 | static Mutex* create(); 18 | }; 19 | -------------------------------------------------------------------------------- /XLEngine/Threads/thread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../types.h" 3 | #include 4 | 5 | #ifdef _WIN32 6 | #define XL_THREADRET u32 7 | #else 8 | #define XL_THREADRET void* 9 | #endif 10 | 11 | typedef XL_THREADRET (XL_STDCALL *ThreadFunc)(void*); 12 | 13 | class Thread 14 | { 15 | public: 16 | virtual ~Thread() {}; 17 | 18 | virtual bool run() = 0; 19 | virtual void pause() = 0; 20 | virtual void resume() = 0; 21 | 22 | protected: 23 | Thread(const char* name, ThreadFunc func, void* userData) 24 | { 25 | m_func = func; 26 | m_userData = userData; 27 | strcpy(m_name, name); 28 | } 29 | 30 | public: 31 | //static factory function - creates the correct platform dependent version 32 | static Thread* create(const char* name, ThreadFunc func, void* userData); 33 | 34 | protected: 35 | ThreadFunc m_func; 36 | void* m_userData; 37 | char m_name[256]; 38 | }; 39 | -------------------------------------------------------------------------------- /XLEngine/UI/draw2D.cpp: -------------------------------------------------------------------------------- 1 | #include "draw2D.h" 2 | #include "../Math/crc32.h" 3 | #include 4 | #include 5 | 6 | namespace Draw2D 7 | { 8 | #define DRAW_POOL_SIZE 1024 9 | 10 | static GraphicsDevice* s_gdev; 11 | static DrawRectBuf s_rectPool[DRAW_POOL_SIZE]; 12 | static DrawTextBuf s_textPool[DRAW_POOL_SIZE]; 13 | static int s_rectIndex = 0; 14 | static int s_textIndex = 0; 15 | static u32 s_textureHash; 16 | 17 | void clearDraw(); 18 | 19 | bool init(GraphicsDevice* gdev) 20 | { 21 | s_gdev = gdev; 22 | const char* texName = "baseTex"; 23 | s_textureHash = CRC32::get( (u8*)texName, strlen(texName) ); 24 | return true; 25 | } 26 | 27 | void destroy() 28 | { 29 | } 30 | 31 | DrawRectBuf* getDrawRect() 32 | { 33 | DrawRectBuf* rect = NULL; 34 | if (s_rectIndex < DRAW_POOL_SIZE) 35 | { 36 | rect = &s_rectPool[s_rectIndex]; 37 | rect->texture = INVALID_TEXTURE_HANDLE; 38 | rect->color = 0xffffffff; 39 | rect->layer = 0; 40 | rect->u = 0.0f; 41 | rect->v = 0.0f; 42 | rect->du = 1.0f; 43 | rect->dv = 1.0f; 44 | s_rectIndex++; 45 | } 46 | 47 | return rect; 48 | } 49 | 50 | DrawTextBuf* getDrawText() 51 | { 52 | DrawTextBuf* text = NULL; 53 | if (s_textIndex < DRAW_POOL_SIZE) 54 | { 55 | text = &s_textPool[s_textIndex]; 56 | text->color = 0xffffffff; 57 | text->layer = 0; 58 | s_textIndex++; 59 | } 60 | 61 | return text; 62 | } 63 | 64 | void drawImmediate(const DrawRectBuf& rect) 65 | { 66 | const Quad quad= 67 | { 68 | { rect.x, rect.y }, 69 | { rect.x + rect.w, rect.y + rect.h }, 70 | { rect.u, 1.0f-rect.v }, 71 | { rect.u+rect.du, 1.0f-(rect.v+rect.dv) }, 72 | rect.color 73 | }; 74 | s_gdev->setShaderResource( rect.texture, s_textureHash ); 75 | s_gdev->drawQuad( quad ); 76 | } 77 | 78 | void drawBatch() 79 | { 80 | int curLayer = 255; 81 | if (s_rectIndex > 0) 82 | { 83 | curLayer = MIN(curLayer, s_rectPool[0].layer); 84 | } 85 | if (s_textIndex > 0) 86 | { 87 | curLayer = MIN(curLayer, s_textPool[0].layer); 88 | } 89 | 90 | //now fill the vertex data before drawing. 91 | static u32 vertexOffsetsRect[1024]; 92 | static u32 vertexOffsetsText[1024]; 93 | static u32 textQuadCount[1024]; 94 | 95 | s32 r=0, t=0; 96 | for (; raddQuad( quad ); 109 | } 110 | for (; tflush(); 120 | 121 | r = 0; t = 0; 122 | while (r < s_rectIndex || t < s_textIndex) 123 | { 124 | int nextLayerRect = 255; 125 | int nextLayerText = 255; 126 | for (; r < s_rectIndex; r++) 127 | { 128 | const DrawRectBuf& rect = s_rectPool[r]; 129 | 130 | if (rect.layer > curLayer) 131 | { 132 | nextLayerRect = rect.layer; 133 | break; 134 | } 135 | 136 | s_gdev->setShaderResource( rect.texture, s_textureHash ); 137 | s_gdev->drawQuadBatch( vertexOffsetsRect[r], 1 ); 138 | } 139 | 140 | FontHandle curFont = INVALID_FONT_HANDLE; 141 | u32 vertexOffset = 0; 142 | u32 quadCount = 0; 143 | for (; t < s_textIndex; t++) 144 | { 145 | const DrawTextBuf& text = s_textPool[t]; 146 | if (text.layer > curLayer) 147 | { 148 | nextLayerText = text.layer; 149 | break; 150 | } 151 | 152 | if (text.font != curFont) 153 | { 154 | if (quadCount) 155 | { 156 | TextSystem::setFont( curFont ); 157 | TextSystem::bindTexture(); 158 | 159 | s_gdev->drawQuadBatch( vertexOffset, quadCount ); 160 | } 161 | 162 | curFont = text.font; 163 | vertexOffset = vertexOffsetsText[t]; 164 | quadCount = textQuadCount[t]; 165 | } 166 | else 167 | { 168 | quadCount += textQuadCount[t]; 169 | } 170 | } 171 | 172 | //draw the last batch 173 | if (curFont != INVALID_FONT_HANDLE && quadCount) 174 | { 175 | TextSystem::setFont( curFont ); 176 | TextSystem::bindTexture(); 177 | 178 | s_gdev->drawQuadBatch( vertexOffset, quadCount ); 179 | } 180 | 181 | curLayer = MIN(nextLayerRect, nextLayerText); 182 | }; 183 | 184 | clearDraw(); 185 | s_gdev->enableBlending(false); 186 | } 187 | 188 | void draw() 189 | { 190 | s_gdev->enableBlending(true); 191 | s_gdev->setBlendMode( BLEND_OVER ); 192 | s_gdev->setShader( SHADER_QUAD_UI ); 193 | 194 | if ( s_gdev->getDeviceID() != GDEV_OPENGL_1_3 ) 195 | { 196 | drawBatch(); 197 | } 198 | 199 | int curLayer = 255; 200 | if (s_rectIndex > 0) 201 | { 202 | curLayer = MIN(curLayer, s_rectPool[0].layer); 203 | } 204 | if (s_textIndex > 0) 205 | { 206 | curLayer = MIN(curLayer, s_textPool[0].layer); 207 | } 208 | 209 | s32 r=0, t=0; 210 | while (r < s_rectIndex || t < s_textIndex) 211 | { 212 | int nextLayerRect = 255; 213 | int nextLayerText = 255; 214 | for (; r < s_rectIndex; r++) 215 | { 216 | const DrawRectBuf& rect = s_rectPool[r]; 217 | 218 | if (rect.layer > curLayer) 219 | { 220 | nextLayerRect = rect.layer; 221 | break; 222 | } 223 | 224 | const Quad quad= 225 | { 226 | { rect.x, rect.y }, 227 | { rect.x + rect.w, rect.y + rect.h }, 228 | { rect.u, 1.0f-rect.v }, 229 | { rect.u+rect.du, 1.0f-(rect.v+rect.dv) }, 230 | rect.color 231 | }; 232 | s_gdev->setShaderResource( rect.texture, s_textureHash ); 233 | s_gdev->drawQuad( quad ); 234 | } 235 | 236 | for (; t < s_textIndex; t++) 237 | { 238 | const DrawTextBuf& text = s_textPool[t]; 239 | if (text.layer > curLayer) 240 | { 241 | nextLayerText = text.layer; 242 | break; 243 | } 244 | 245 | TextSystem::setColor( text.color ); 246 | TextSystem::setFont( text.font ); 247 | TextSystem::print( text.x, text.y, text.msg ); 248 | } 249 | 250 | curLayer = MIN(nextLayerRect, nextLayerText); 251 | }; 252 | 253 | clearDraw(); 254 | s_gdev->enableBlending(false); 255 | } 256 | 257 | void clearDraw() 258 | { 259 | s_rectIndex = 0; 260 | s_textIndex = 0; 261 | } 262 | }; -------------------------------------------------------------------------------- /XLEngine/UI/draw2D.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Graphics/graphicsDevice.h" 4 | #include "../Text/textSystem.h" 5 | 6 | struct DrawRectBuf 7 | { 8 | TextureHandle texture; 9 | Color color; 10 | int layer; 11 | //pos 12 | int x, y; 13 | int w, h; 14 | //uvs 15 | float u, v; 16 | float du, dv; 17 | }; 18 | struct DrawTextBuf 19 | { 20 | Color color; 21 | FontHandle font; 22 | int layer; 23 | int x, y; 24 | char msg[4096]; 25 | }; 26 | 27 | #ifndef MIN 28 | #define MIN(a, b) (a)<(b) ? (a) : (b) 29 | #endif 30 | 31 | #ifndef MAX 32 | #define MAX(a, b) (a)>(b) ? (a) : (b) 33 | #endif 34 | 35 | namespace Draw2D 36 | { 37 | bool init(GraphicsDevice* gdev); 38 | void destroy(); 39 | 40 | DrawRectBuf* getDrawRect(); 41 | DrawTextBuf* getDrawText(); 42 | void draw(); 43 | void drawImmediate(const DrawRectBuf& rect); 44 | }; 45 | -------------------------------------------------------------------------------- /XLEngine/UI/uiSystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Graphics/graphicsDevice.h" 4 | #include "../types.h" 5 | #include "../Text/textSystem.h" 6 | 7 | enum IconID 8 | { 9 | ICON_VIDEO = 0, 10 | ICON_DASHBOARD, 11 | ICON_CONTROLS, 12 | ICON_SETTINGS, 13 | ICON_SEARCH, 14 | ICON_TOOLS, 15 | }; 16 | 17 | struct UI_Sound 18 | { 19 | const char* filename; 20 | void* data; 21 | u32 size; 22 | }; 23 | 24 | namespace UISystem 25 | { 26 | bool init(GraphicsDevice* gdev, int screenWidth, int screenHeight); 27 | void destroy(); 28 | 29 | //general 30 | void begin(); 31 | void finish(); 32 | void clear(); 33 | FontHandle getFont(int size); 34 | void setCurrentLayer(int layer=0); 35 | void setMouseOverSound(UI_Sound* sound); 36 | 37 | //controls 38 | bool window(int id, int layer, const char* caption, int x, int y, int w, int h); 39 | bool button(s32 id, s32 layer, const char* caption, s32 x, s32 y, s32 w, s32 h); 40 | bool buttonImage(s32 id, s32 layer, TextureHandle image, s32 x, s32 y, s32 w, s32 h); 41 | bool buttonIcon(s32 id, s32 layer, s32 iconID, s32 x, s32 y); 42 | 43 | void staticText(int layer, const char* str, int x, int y, Color color=PACK_RGBA(190, 255, 255, 255)); 44 | 45 | s32 addIcon(const char* imageName); 46 | 47 | // 48 | void predraw(); 49 | }; 50 | -------------------------------------------------------------------------------- /XLEngine/Win32/clockWin32.cpp: -------------------------------------------------------------------------------- 1 | #include "../clock.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define SEC_TO_uS 1000000.0 7 | 8 | f32 Clock::s_deltaTime; 9 | f32 Clock::s_realDeltaTime; 10 | s32 Clock::s_deltaTicks; 11 | 12 | static LARGE_INTEGER s_timerFreq; 13 | static u64 s_startTick[16] = {0}; 14 | 15 | u64 getCurTickCnt(); 16 | 17 | bool Clock::init() 18 | { 19 | BOOL ret = QueryPerformanceFrequency(&s_timerFreq); 20 | return (ret) ? true : false; 21 | } 22 | 23 | void Clock::destroy() 24 | { 25 | //nothing to do currently. 26 | } 27 | 28 | void Clock::startTimer(int timerID/*=0*/) 29 | { 30 | assert( timerID < 16 ); 31 | s_startTick[timerID] = getCurTickCnt(); 32 | } 33 | 34 | float Clock::getDeltaTime(float fMax, int timerID/*=0*/) 35 | { 36 | assert( timerID < 16 ); 37 | u64 End = getCurTickCnt(); 38 | 39 | f32 fTimeDelta = (f32)( (f64)(End - s_startTick[timerID]) / (f64)(s_timerFreq.QuadPart) ); 40 | if ( fTimeDelta > fMax ) 41 | { 42 | fTimeDelta = fMax; 43 | } 44 | 45 | return fTimeDelta; 46 | } 47 | 48 | u64 Clock::getDeltaTime_uS(int timerID/*=0*/) 49 | { 50 | u64 End = getCurTickCnt(); 51 | f64 quadPart_uS = (f64)(s_timerFreq.QuadPart) / SEC_TO_uS; 52 | return (u64)( (f64)(End - s_startTick[timerID]) / quadPart_uS ); 53 | } 54 | 55 | f64 Clock::getDeltaTime_f64(int timerID/*=0*/) 56 | { 57 | u64 End = getCurTickCnt(); 58 | return f64(End - s_startTick[timerID]) / (f64)(s_timerFreq.QuadPart); 59 | } 60 | 61 | u64 Clock::getTime_uS() 62 | { 63 | u64 value = getCurTickCnt(); 64 | f64 quadPart_uS = (f64)(s_timerFreq.QuadPart) / SEC_TO_uS; 65 | return (u64)( (f64)value / quadPart_uS ); 66 | } 67 | 68 | f64 Clock::getTime_uS_flt() 69 | { 70 | u64 value = getCurTickCnt(); 71 | f64 quadPart_uS = (f64)(s_timerFreq.QuadPart) / SEC_TO_uS; 72 | return (f64)value / quadPart_uS; 73 | } 74 | 75 | u64 getCurTickCnt() 76 | { 77 | LARGE_INTEGER lcurtick; 78 | QueryPerformanceCounter(&lcurtick); 79 | 80 | return lcurtick.QuadPart; 81 | } 82 | -------------------------------------------------------------------------------- /XLEngine/Win32/osUtilWin32.cpp: -------------------------------------------------------------------------------- 1 | #include "../osUtil.h" 2 | #include 3 | #include 4 | #include 5 | 6 | namespace OS 7 | { 8 | void sleep(u32 sleepDeltaMS) 9 | { 10 | Sleep(sleepDeltaMS); 11 | } 12 | } -------------------------------------------------------------------------------- /XLEngine/clock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | class Clock 5 | { 6 | public: 7 | static bool init(); 8 | static void destroy(); 9 | static void startTimer(s32 timerID=0); 10 | static float getDeltaTime(f32 fMax, s32 timerID=0); 11 | static f64 getDeltaTime_f64(int timerID=0); 12 | static u64 getDeltaTime_uS(s32 timeID=0); 13 | static u64 getTime_uS(); 14 | static f64 getTime_uS_flt(); 15 | 16 | private: 17 | static f32 s_deltaTime; 18 | static f32 s_realDeltaTime; 19 | static s32 s_deltaTicks; 20 | }; 21 | -------------------------------------------------------------------------------- /XLEngine/filestream.cpp: -------------------------------------------------------------------------------- 1 | #include "filestream.h" 2 | #include 3 | #include 4 | 5 | //Work buffers for handling special cases like std::string without allocating memory (beyond what the strings needs itself). 6 | static u32 s_workBufferU32[1024]; //4k buffer. 7 | static char s_workBufferChar[32768]; //32k buffer. 8 | 9 | FileStream::FileStream() : Stream() 10 | { 11 | m_file = NULL; 12 | m_mode = MODE_INVALID; 13 | } 14 | 15 | FileStream::~FileStream() 16 | { 17 | close(); 18 | } 19 | 20 | bool FileStream::exists(const char* filename) 21 | { 22 | bool res = open(filename, MODE_READ); 23 | close(); 24 | 25 | return res; 26 | } 27 | 28 | bool FileStream::open(const char* filename, FileMode mode) 29 | { 30 | const char* modeStrings[] = { "rb", "wb", "rb+" }; 31 | m_file = fopen(filename, modeStrings[mode]); 32 | m_mode = mode; 33 | 34 | return m_file != NULL; 35 | } 36 | 37 | void FileStream::close() 38 | { 39 | if (m_file) 40 | { 41 | if (m_mode == MODE_WRITE || m_mode == MODE_READWRITE) 42 | { 43 | fflush(m_file); 44 | } 45 | 46 | fclose(m_file); 47 | m_file = NULL; 48 | m_mode = MODE_INVALID; 49 | } 50 | } 51 | 52 | bool FileStream::isOpen() const 53 | { 54 | return (m_file != NULL); 55 | } 56 | 57 | void FileStream::flush() 58 | { 59 | if (m_file) 60 | { 61 | fflush(m_file); 62 | } 63 | } 64 | 65 | void* FileStream::getFileHandle() 66 | { 67 | return m_file; 68 | } 69 | 70 | //derived from Stream 71 | void FileStream::seek(u32 offset, Origin origin/*=ORIGIN_START*/) 72 | { 73 | const s32 forigin[] = { SEEK_SET, SEEK_END, SEEK_CUR }; 74 | if (m_file) 75 | { 76 | fseek(m_file, offset, forigin[origin]); 77 | } 78 | } 79 | 80 | size_t FileStream::getLoc() 81 | { 82 | if (!m_file) 83 | { 84 | return 0; 85 | } 86 | return ftell(m_file); 87 | } 88 | 89 | size_t FileStream::getSize() 90 | { 91 | if (!m_file) 92 | { 93 | return 0; 94 | } 95 | 96 | seek(0, FileStream::ORIGIN_END); 97 | size_t filesize = getLoc(); 98 | seek(0, FileStream::ORIGIN_START); 99 | 100 | return filesize; 101 | } 102 | 103 | void FileStream::readBuffer(void* ptr, u32 size, u32 count) 104 | { 105 | assert(m_mode == MODE_READ || m_mode == MODE_READWRITE); 106 | fread(ptr, size, count, m_file); 107 | } 108 | 109 | void FileStream::writeBuffer(const void* ptr, u32 size, u32 count) 110 | { 111 | assert(m_mode == MODE_WRITE || m_mode == MODE_READWRITE); 112 | fwrite(ptr, size, count, m_file); 113 | } 114 | 115 | //internal 116 | void FileStream::readTypeString(std::string* ptr, u32 count) 117 | { 118 | assert(m_mode == MODE_READ || m_mode == MODE_READWRITE); 119 | assert(count <= 256); 120 | //first read the length. 121 | fread(s_workBufferU32, sizeof(u32), count, m_file); 122 | 123 | //then read the string data. 124 | for (u32 s=0; s 4 | 5 | class FileStream : public Stream 6 | { 7 | public: 8 | enum FileMode 9 | { 10 | MODE_READ = 0, //read-only (will fail if the file doesn't exist) 11 | MODE_WRITE, //write (will overwrite the file) 12 | MODE_READWRITE, //read-write (will create a new file if it doesn't exist, the file can be read from and written to). 13 | MODE_COUNT, 14 | MODE_INVALID = MODE_COUNT 15 | }; 16 | public: 17 | FileStream(); 18 | ~FileStream(); 19 | 20 | bool exists(const char* filename); 21 | bool open(const char* filename, FileMode mode); 22 | void close(); 23 | 24 | bool isOpen() const; 25 | void flush(); 26 | 27 | void* getFileHandle(); 28 | 29 | //derived functions. 30 | void seek(u32 offset, Origin origin=ORIGIN_START); 31 | size_t getLoc(); 32 | size_t getSize(); 33 | 34 | void read(s8* ptr, u32 count=1) { readType(ptr, count); } 35 | void read(u8* ptr, u32 count=1) { readType(ptr, count); } 36 | void read(s16* ptr, u32 count=1) { readType(ptr, count); } 37 | void read(u16* ptr, u32 count=1) { readType(ptr, count); } 38 | void read(s32* ptr, u32 count=1) { readType(ptr, count); } 39 | void read(u32* ptr, u32 count=1) { readType(ptr, count); } 40 | void read(s64* ptr, u32 count=1) { readType(ptr, count); } 41 | void read(u64* ptr, u32 count=1) { readType(ptr, count); } 42 | void read(f32* ptr, u32 count=1) { readType(ptr, count); } 43 | void read(f64* ptr, u32 count=1) { readType(ptr, count); } 44 | void read(std::string* ptr, u32 count=1) { readTypeString(ptr, count); } 45 | void readBuffer(void* ptr, u32 size, u32 count=1); 46 | 47 | void write(const s8* ptr, u32 count=1) { writeType(ptr, count); } 48 | void write(const u8* ptr, u32 count=1) { writeType(ptr, count); } 49 | void write(const s16* ptr, u32 count=1) { writeType(ptr, count); } 50 | void write(const u16* ptr, u32 count=1) { writeType(ptr, count); } 51 | void write(const s32* ptr, u32 count=1) { writeType(ptr, count); } 52 | void write(const u32* ptr, u32 count=1) { writeType(ptr, count); } 53 | void write(const s64* ptr, u32 count=1) { writeType(ptr, count); } 54 | void write(const u64* ptr, u32 count=1) { writeType(ptr, count); } 55 | void write(const f32* ptr, u32 count=1) { writeType(ptr, count); } 56 | void write(const f64* ptr, u32 count=1) { writeType(ptr, count); } 57 | void write(const std::string* ptr, u32 count=1) { writeTypeString(ptr, count); } 58 | void writeBuffer(const void* ptr, u32 size, u32 count=1); 59 | 60 | private: 61 | template 62 | void readType(T* ptr, u32 count); 63 | 64 | void readTypeString(std::string* ptr, u32 count); 65 | 66 | template 67 | void writeType(const T* ptr, u32 count); 68 | 69 | void writeTypeString(const std::string* ptr, u32 count); 70 | 71 | private: 72 | FILE* m_file; 73 | FileMode m_mode; 74 | }; 75 | 76 | //templates need to be defined in the header in GCC (for Release anyway) 77 | template 78 | void FileStream::readType(T* ptr, u32 count) 79 | { 80 | fread(ptr, sizeof(T), count, m_file); 81 | } 82 | 83 | template 84 | void FileStream::writeType(const T* ptr, u32 count) 85 | { 86 | fwrite(ptr, sizeof(T), count, m_file); 87 | } 88 | 89 | 90 | -------------------------------------------------------------------------------- /XLEngine/gameLoop.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include "Graphics/graphicsDeviceList.h" 4 | #include "Graphics/graphicsDevice.h" 5 | 6 | namespace GameLoop 7 | { 8 | bool init(void* win_param[], GraphicsDeviceID deviceID); 9 | void destroy(); 10 | 11 | bool startGame(s32 gameID); 12 | void stopGame(); 13 | 14 | bool checkExitGame(); 15 | void update(); 16 | }; -------------------------------------------------------------------------------- /XLEngine/gameUI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include "UI/uiSystem.h" 4 | #include "UI/draw2D.h" 5 | 6 | typedef bool (*StartGameFunc)(s32); 7 | typedef void (*StopGameFunc)(); 8 | 9 | namespace GameUI 10 | { 11 | void init(StartGameFunc startGame, StopGameFunc stopGame); 12 | void update(GraphicsDevice* gdev, int winWidth, int winHeight, s32& gameRunning); 13 | 14 | bool getShowUI(); 15 | void setShowUI(bool show, GraphicsDevice* gdev); 16 | 17 | void enableCursor(bool enable); 18 | }; -------------------------------------------------------------------------------- /XLEngine/imageLoader.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luciusDXL/XL-Engine/cd3b467b58d6c35f5d46cf481bc035da30ac21c3/XLEngine/imageLoader.cpp -------------------------------------------------------------------------------- /XLEngine/imageLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | #include 5 | using namespace std; 6 | 7 | class ImageLoader 8 | { 9 | public: 10 | ImageLoader(); 11 | ~ImageLoader(); 12 | 13 | bool loadImage(const char* image); 14 | bool saveImageRGBA(const char* image, u8* data, u32 width, u32 height); 15 | void freeImageData(); 16 | 17 | const u8* getImageData() const { return m_imageData; } 18 | const u32 getWidth() const { return m_width; } 19 | const u32 getHeight() const { return m_height; } 20 | const u32 getOffsetX() const { return m_offsX; } 21 | const u32 getOffsetY() const { return m_offsY; } 22 | 23 | void setPath(const char* path); 24 | const char* getPath() const { return m_path; } 25 | 26 | private: 27 | char m_path[260]; 28 | u32 m_width; 29 | u32 m_height; 30 | u32 m_offsX; 31 | u32 m_offsY; 32 | u8* m_imageData; 33 | u8* m_imageData_Work; 34 | }; 35 | -------------------------------------------------------------------------------- /XLEngine/iniReader.cpp: -------------------------------------------------------------------------------- 1 | #include "iniReader.h" 2 | #include "filestream.h" 3 | 4 | #include 5 | 6 | namespace iniReader 7 | { 8 | bool getKey(char** fileData, char* keyName, const char* fileEnd); 9 | bool readValue(char** fileData, char* value, const char* fileEnd,bool liberal); 10 | 11 | //////////////////////////////////// 12 | // API 13 | //////////////////////////////////// 14 | 15 | bool readIni(const char* filename, ReadIniCallback callback, bool liberal) 16 | { 17 | if (!callback) 18 | { 19 | return false; 20 | } 21 | 22 | bool res = false; 23 | FileStream file; 24 | if ( file.open(filename, FileStream::MODE_READ) ) 25 | { 26 | size_t size = file.getSize(); 27 | char* fileData = new char[size+1]; 28 | if (fileData) 29 | { 30 | file.read(fileData, (u32)size); 31 | res = true; 32 | } 33 | file.close(); 34 | 35 | if (res) 36 | { 37 | const char* fileEnd = &fileData[size]; 38 | char* readPos = fileData; 39 | 40 | //now read the data. 41 | while (1) 42 | { 43 | char keyName[512], keyValue[512]; 44 | 45 | //we are done here. 46 | if (!getKey(&readPos, keyName, fileEnd)) 47 | { 48 | break; 49 | } 50 | 51 | if (!readValue(&readPos, keyValue, fileEnd, liberal)) 52 | { 53 | break; 54 | } 55 | 56 | //remove preceding or trailing spaces, remove exterior quotation marks. 57 | fixupString(keyName); 58 | fixupString(keyValue); 59 | 60 | res &= callback(keyName, keyValue); 61 | }; 62 | } 63 | 64 | delete [] fileData; 65 | } 66 | 67 | return res; 68 | } 69 | 70 | void fixupSlashes(char* value, bool addSlashAtEnd, bool removeSlashFromEnd) 71 | { 72 | size_t len = strlen(value); 73 | for (size_t c=0; c ' ' && firstNonSpaceChar < 0 ) 112 | { 113 | firstNonSpaceChar = (s32)c; 114 | lastNonSpaceChar = (s32)c; 115 | } 116 | else if (value[c] > ' ') 117 | { 118 | lastNonSpaceChar = (s32)c; 119 | } 120 | } 121 | 122 | if (firstNonSpaceChar < 0 || lastNonSpaceChar < 0 || firstNonSpaceChar == lastNonSpaceChar) 123 | { 124 | return; 125 | } 126 | 127 | if (value[ firstNonSpaceChar ] == '"') 128 | { 129 | firstNonSpaceChar++; 130 | } 131 | if (value[ lastNonSpaceChar ] == '"') 132 | { 133 | lastNonSpaceChar--; 134 | } 135 | if (lastNonSpaceChar <= firstNonSpaceChar) 136 | { 137 | return; 138 | } 139 | 140 | s32 c=firstNonSpaceChar; 141 | for (; c<=lastNonSpaceChar; c++) 142 | { 143 | value[c-firstNonSpaceChar] = copy[c]; 144 | } 145 | value[c-firstNonSpaceChar] = 0; 146 | } 147 | 148 | bool readCmdLine(const char *cmdline, ReadIniCallback callback) 149 | { 150 | static char* empty = ""; 151 | char* buf = new char[strlen(cmdline)+1]; 152 | strcpy(buf,cmdline); 153 | 154 | char* ps = buf; 155 | while(*ps && *ps != ';') 156 | { 157 | ps++; 158 | } 159 | *ps = 0; 160 | ps = buf; 161 | 162 | bool res = true; 163 | while (*ps && res) 164 | { 165 | char* parg = NULL; 166 | while (*ps && (*ps == ' ' || *ps == '\t')) 167 | { 168 | ps++; 169 | } 170 | 171 | if (*ps == '"') 172 | { 173 | parg = ++ps; 174 | while(*ps && *ps != '"') 175 | { 176 | ps++; 177 | } 178 | if (*ps) 179 | { 180 | *ps++ = '\0'; 181 | } 182 | } 183 | else if (*ps) 184 | { 185 | parg = ps; 186 | while(*ps && *ps != ' ' && *ps != '\t') 187 | { 188 | ps++; 189 | } 190 | if (*ps) 191 | { 192 | *ps++ = '\0'; 193 | } 194 | } 195 | 196 | if (parg) 197 | { 198 | char* value = parg; 199 | for (; *value && *value != '='; value++) {;} 200 | 201 | if (*value == '=') 202 | { 203 | *value++ = '\0'; 204 | fixupString(parg); 205 | fixupString(value); 206 | 207 | } 208 | else 209 | { 210 | fixupString(parg); 211 | value = empty; 212 | } 213 | res &= callback(parg, value); 214 | } 215 | } 216 | 217 | delete buf; 218 | return res; 219 | } 220 | 221 | 222 | //////////////////////////////////// 223 | // Internal Functions. 224 | //////////////////////////////////// 225 | 226 | bool getKey(char** fileData, char* keyName, const char* fileEnd) 227 | { 228 | u32 keyIndex = 0; 229 | keyName[0] = 0; 230 | 231 | bool inComment = false; 232 | char* curPos = *fileData; 233 | while (curPos < fileEnd) 234 | { 235 | if (*curPos == '#') 236 | { 237 | inComment = true; 238 | } 239 | else if (inComment) 240 | { 241 | //we stay in the comment until the end of the line. 242 | if (*curPos == '\r' || *curPos == '\n') 243 | { 244 | inComment = false; 245 | } 246 | } 247 | else if (*curPos != '=' && *curPos >= 32) 248 | { 249 | if (keyIndex != 0 || *curPos != ' ') 250 | { 251 | keyName[ keyIndex++ ] = *curPos; 252 | } 253 | } 254 | else if (*curPos == '=') 255 | { 256 | break; 257 | } 258 | 259 | curPos++; 260 | }; 261 | 262 | keyName[keyIndex] = 0; 263 | *fileData = (curPos= 32 && !inComment) 287 | { 288 | if (valueIndex != 0 || *curPos != ' ') 289 | { 290 | value[ valueIndex++ ] = *curPos; 291 | } 292 | } 293 | 294 | curPos++; 295 | }; 296 | 297 | value[valueIndex] = 0; 298 | *fileData = (curPos 5 | #include 6 | 7 | namespace iniWriter 8 | { 9 | FileStream s_stream; 10 | char s_workBuffer[1024]; 11 | 12 | bool open(const char* filename) 13 | { 14 | return s_stream.open(filename, FileStream::MODE_WRITE); 15 | } 16 | 17 | void close() 18 | { 19 | s_stream.close(); 20 | } 21 | 22 | void comment(const char* comment) 23 | { 24 | sprintf(s_workBuffer, "#%s\r\n", comment); 25 | 26 | size_t len = strlen(s_workBuffer); 27 | s_stream.write(s_workBuffer, (u32)len); 28 | } 29 | 30 | void newLine() 31 | { 32 | strcpy(s_workBuffer, "\r\n"); 33 | 34 | size_t len = strlen(s_workBuffer); 35 | s_stream.write(s_workBuffer, (u32)len); 36 | } 37 | 38 | void write(const char* key, const char* value) 39 | { 40 | sprintf(s_workBuffer, "%s=\"%s\"\r\n", key, value); 41 | 42 | size_t len = strlen(s_workBuffer); 43 | s_stream.write(s_workBuffer, (u32)len); 44 | } 45 | 46 | void writeStrNoQuotes(const char* key, const char* value) 47 | { 48 | sprintf(s_workBuffer, "%s=%s\r\n", key, value); 49 | 50 | size_t len = strlen(s_workBuffer); 51 | s_stream.write(s_workBuffer, (u32)len); 52 | } 53 | 54 | void write(const char* key, s8 value) 55 | { 56 | sprintf(s_workBuffer, "%s=%d\r\n", key, value); 57 | 58 | size_t len = strlen(s_workBuffer); 59 | s_stream.write(s_workBuffer, (u32)len); 60 | } 61 | 62 | void write(const char* key, u8 value) 63 | { 64 | sprintf(s_workBuffer, "%s=%u\r\n", key, value); 65 | 66 | size_t len = strlen(s_workBuffer); 67 | s_stream.write(s_workBuffer, (u32)len); 68 | } 69 | 70 | void write(const char* key, s16 value) 71 | { 72 | sprintf(s_workBuffer, "%s=%d\r\n", key, value); 73 | 74 | size_t len = strlen(s_workBuffer); 75 | s_stream.write(s_workBuffer, (u32)len); 76 | } 77 | 78 | void write(const char* key, u16 value) 79 | { 80 | sprintf(s_workBuffer, "%s=%u\r\n", key, value); 81 | 82 | size_t len = strlen(s_workBuffer); 83 | s_stream.write(s_workBuffer, (u32)len); 84 | } 85 | 86 | void write(const char* key, s32 value) 87 | { 88 | sprintf(s_workBuffer, "%s=%d\r\n", key, value); 89 | 90 | size_t len = strlen(s_workBuffer); 91 | s_stream.write(s_workBuffer, (u32)len); 92 | } 93 | 94 | void write(const char* key, u32 value) 95 | { 96 | sprintf(s_workBuffer, "%s=%u\r\n", key, value); 97 | 98 | size_t len = strlen(s_workBuffer); 99 | s_stream.write(s_workBuffer, (u32)len); 100 | } 101 | 102 | void write(const char* key, f32 value) 103 | { 104 | sprintf(s_workBuffer, "%s=%f\r\n", key, value); 105 | 106 | size_t len = strlen(s_workBuffer); 107 | s_stream.write(s_workBuffer, (u32)len); 108 | } 109 | 110 | void write(const char* key, f64 value) 111 | { 112 | sprintf(s_workBuffer, "%s=%f\r\n", key, value); 113 | 114 | size_t len = strlen(s_workBuffer); 115 | s_stream.write(s_workBuffer, (u32)len); 116 | } 117 | 118 | void write(const char* key, bool value) 119 | { 120 | sprintf(s_workBuffer, "%s=%s\r\n", key, value ? "true" : "false"); 121 | 122 | size_t len = strlen(s_workBuffer); 123 | s_stream.write(s_workBuffer, (u32)len); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /XLEngine/iniWriter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace iniWriter 4 | { 5 | bool open(const char* filename); 6 | void close(); 7 | 8 | void writeStrNoQuotes(const char* key, const char* value); 9 | void write(const char* key, const char* value); 10 | void write(const char* key, s8 value); 11 | void write(const char* key, u8 value); 12 | void write(const char* key, s16 value); 13 | void write(const char* key, u16 value); 14 | void write(const char* key, s32 value); 15 | void write(const char* key, u32 value); 16 | void write(const char* key, f32 value); 17 | void write(const char* key, f64 value); 18 | void write(const char* key, bool value); 19 | 20 | void comment(const char* comment); 21 | void newLine(); 22 | }; -------------------------------------------------------------------------------- /XLEngine/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | #include "settings.h" 3 | #include 4 | #include 5 | #ifdef _WIN32 6 | #define WIN32_LEAN_AND_MEAN 1 7 | #include 8 | #endif 9 | 10 | namespace Input 11 | { 12 | static char s_inputCharacters[4096] = { 0 }; 13 | static bool s_mouseDown[3] = { false }; 14 | static bool s_keyState[256] = { 0 }; 15 | static u8 s_keyPressed[256] = { 0 }; 16 | static u8 s_keyPressedWithRepeat[256] = { 0 }; 17 | static s32 s_mouseWheel = 0; 18 | static s32 s_mouseX = 0; 19 | static s32 s_mouseY = 0; 20 | static void* s_winData = NULL; 21 | 22 | static bool s_active = false; 23 | void init(void* winData) 24 | { 25 | s_winData = winData; 26 | } 27 | 28 | //////////////////////////////////////////////// 29 | //Reset state for the next frame. 30 | //////////////////////////////////////////////// 31 | void finish() 32 | { 33 | s_mouseWheel = 0; 34 | s_inputCharacters[0] = 0; 35 | memset(s_keyPressed, 0, 256); 36 | memset(s_keyPressedWithRepeat, 0, 256); 37 | } 38 | 39 | //////////////////////////////////////////////// 40 | //Windowing system input. 41 | //////////////////////////////////////////////// 42 | void setMouseButtonState(MouseButton button, bool buttonIsDown) 43 | { 44 | if (button >= MouseCount) { return; } 45 | s_mouseDown[button] = buttonIsDown; 46 | } 47 | 48 | void setKeyState(u32 key, bool keyIsDown) 49 | { 50 | if (key >= 256) { return; } 51 | 52 | if (keyIsDown && !s_keyState[key]) 53 | { 54 | s_keyPressed[key] = 1; 55 | } 56 | s_keyPressedWithRepeat[key] = keyIsDown; 57 | 58 | s_keyState[key] = keyIsDown; 59 | } 60 | 61 | void addChar(char c) 62 | { 63 | const size_t n = strlen(s_inputCharacters); 64 | 65 | //these are proper characters but should be processed by other systems. 66 | if (c < 0x20 || c == 0x7f) 67 | { 68 | return; 69 | } 70 | 71 | if (n + 1 < arraysize(s_inputCharacters)) 72 | { 73 | s_inputCharacters[n] = c; 74 | s_inputCharacters[n+1] = 0; 75 | } 76 | } 77 | 78 | void incMouseWheel(s32 change) 79 | { 80 | s_mouseWheel += change; 81 | } 82 | 83 | void overrideMousePos(s32 x, s32 y) 84 | { 85 | #ifdef _WIN32 86 | POINT pt = { x, y }; 87 | ClientToScreen((HWND)s_winData, &pt); 88 | SetCursorPos(pt.x,pt.y); 89 | #endif 90 | setMousePos(x, y); 91 | } 92 | 93 | void getMouseDelta(s32* dx, s32* dy) 94 | { 95 | #ifdef _WIN32 96 | POINT pt = {0, 0}; 97 | GetCursorPos(&pt); 98 | ScreenToClient((HWND)s_winData, &pt); 99 | 100 | s32 wh = Settings::get()->windowWidth >> 1; 101 | s32 hh = Settings::get()->windowHeight >> 1; 102 | 103 | *dx = pt.x - wh; 104 | *dy = pt.y - hh; 105 | 106 | pt.x = wh; pt.y = hh; 107 | ClientToScreen((HWND)s_winData, &pt); 108 | SetCursorPos(pt.x, pt.y); 109 | #endif 110 | } 111 | 112 | void setMousePos(s32 x, s32 y) 113 | { 114 | s_mouseX = x; 115 | s_mouseY = y; 116 | } 117 | 118 | void setActive( bool active ) 119 | { 120 | s_active = active; 121 | 122 | if (!s_active) 123 | { 124 | // Reset all the keys that are down. 125 | memset( s_keyState,0,sizeof(bool)*256 ); 126 | memset( s_mouseDown,0,sizeof(bool)*3 ); 127 | } 128 | } 129 | 130 | bool isActive() 131 | { 132 | return s_active; 133 | } 134 | 135 | //////////////////////////////////////////////// 136 | //App interface. 137 | //////////////////////////////////////////////// 138 | //is the key down 139 | bool keyDown(u32 key) 140 | { 141 | return s_keyState[key]; 142 | } 143 | 144 | //has the key been 'pressed' (i.e. just pressed down) 145 | //'WithRepeat' will trigger a key pressed on every key down event 146 | //generated by the OS. 147 | bool keyPressedWithRepeat(u32 key) 148 | { 149 | return s_keyPressedWithRepeat[key]!=0; 150 | } 151 | 152 | bool keyPressed(u32 key) 153 | { 154 | return s_keyPressed[key]!=0; 155 | } 156 | 157 | //get the characters input since last frame. 158 | char* getCharInput() 159 | { 160 | return s_inputCharacters; 161 | } 162 | 163 | //mouse 164 | bool getMouseButtonState(MouseButton button) 165 | { 166 | return s_mouseDown[button]; 167 | } 168 | 169 | void getMousePos(s32& x, s32& y) 170 | { 171 | x = s_mouseX; 172 | y = s_mouseY; 173 | } 174 | 175 | s32 getMouseWheelDelta() 176 | { 177 | return s_mouseWheel; 178 | } 179 | 180 | int mapVirtualKey(int keyCode) 181 | { 182 | #ifdef _WIN32 183 | if (keyCode == VK_UP) 184 | { 185 | keyCode = 0x5a; 186 | } 187 | else if (keyCode == VK_DOWN) 188 | { 189 | keyCode = 0x6a; 190 | } 191 | else if (keyCode == VK_LEFT) 192 | { 193 | keyCode = 0x6b; 194 | } 195 | else if (keyCode == VK_RIGHT) 196 | { 197 | keyCode = 0x6c; 198 | } 199 | else if (keyCode == VK_INSERT) 200 | { 201 | keyCode = 0x5e; 202 | } 203 | else if (keyCode == VK_DELETE) 204 | { 205 | keyCode = 0x5f; 206 | } 207 | else if (keyCode == VK_HOME) 208 | { 209 | keyCode = 0x61; 210 | } 211 | else if (keyCode == VK_END) 212 | { 213 | keyCode = 0x62; 214 | } 215 | else if (keyCode == VK_PRIOR) 216 | { 217 | keyCode = 0x63; 218 | } 219 | else if (keyCode == VK_NEXT) 220 | { 221 | keyCode = 0x64; 222 | } 223 | else if (keyCode == VK_LSHIFT) 224 | { 225 | keyCode = 0x2a; 226 | } 227 | else if (keyCode == VK_RSHIFT) 228 | { 229 | keyCode = 0x36; 230 | } 231 | else if (keyCode == VK_LCONTROL) 232 | { 233 | keyCode = 0x1d; 234 | } 235 | else if (keyCode == VK_RCONTROL) 236 | { 237 | keyCode = 0x66; 238 | } 239 | else 240 | { 241 | keyCode = MapVirtualKey(keyCode, MAPVK_VK_TO_VSC); 242 | } 243 | /* 244 | TO-DO - Add these... 245 | #define sc_RightAlt 0x65 246 | #define sc_RightControl 0x66 247 | #define sc_kpad_Slash 0x67 248 | #define sc_kpad_Enter 0x68 249 | #define sc_PrintScreen 0x69 250 | #define sc_LastScanCode 0x6e 251 | */ 252 | #endif 253 | return keyCode; 254 | } 255 | }; 256 | -------------------------------------------------------------------------------- /XLEngine/input.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include "memoryPool.h" 4 | 5 | namespace Input 6 | { 7 | enum MouseButton 8 | { 9 | MouseLeft = 0, 10 | MouseRight, 11 | MouseMiddle, 12 | MouseCount 13 | }; 14 | 15 | enum Keys 16 | { 17 | KEY_BACKSPACE = 8, 18 | KEY_TAB = 9, 19 | KEY_DELETE = 127, 20 | KEY_SHIFT = 16, 21 | KEY_RETURN = 13, 22 | KEY_ESC = 27, 23 | KEY_CONTROL = 17, 24 | 25 | KEY_LEFT = 37, 26 | KEY_UP = 38, 27 | KEY_RIGHT = 39, 28 | KEY_DOWN = 40, 29 | 30 | KEY_F1 = 112, 31 | KEY_F2 = 113, 32 | KEY_F3 = 114, 33 | KEY_F4 = 115, 34 | KEY_F5 = 116, 35 | KEY_F6 = 117, 36 | KEY_F7 = 118, 37 | KEY_F8 = 119, 38 | KEY_F9 = 120, 39 | KEY_F10 = 121, 40 | KEY_F11 = 122, 41 | KEY_F12 = 123, 42 | }; 43 | 44 | void init(void* winData); 45 | //call at the end of the frame to clear out buffers [handled by the engine if using the default renderer] 46 | void finish(); 47 | 48 | //OS interface (set from the windowing system). 49 | void setMouseButtonState(MouseButton button, bool buttonIsDown); 50 | void setKeyState(u32 key, bool keyIsDown); 51 | void addChar(char c); 52 | 53 | void incMouseWheel(s32 change); 54 | void setMousePos(s32 x, s32 y); 55 | void getMouseDelta(s32* dx, s32* dy); 56 | 57 | void setActive(bool active); 58 | bool isActive(); 59 | 60 | //////////////////////////////////////////////// 61 | //App interface. 62 | //////////////////////////////////////////////// 63 | //is the key down 64 | bool keyDown(u32 key); 65 | //has the key been 'pressed' (i.e. just pressed down) 66 | //'WithRepeat' will trigger a key pressed on every key down event 67 | //generated by the OS. 68 | bool keyPressedWithRepeat(u32 key); 69 | bool keyPressed(u32 key); 70 | //get the characters input since last frame. 71 | char* getCharInput(); 72 | //mouse 73 | bool getMouseButtonState(MouseButton button); 74 | void getMousePos(s32& x, s32& y); 75 | s32 getMouseWheelDelta(); 76 | 77 | int mapVirtualKey(int keyCode); 78 | }; -------------------------------------------------------------------------------- /XLEngine/log.cpp: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include "filestream.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef _WIN32 10 | #define WIN32_LEAN_AND_MEAN 1 11 | #include 12 | #define debugMessage OutputDebugStringA 13 | #else 14 | #define debugMessage printf 15 | #endif 16 | 17 | namespace Log 18 | { 19 | const char* c_logMsgType[]= 20 | { 21 | "[Error]", 22 | "[Warning]", 23 | "", 24 | }; 25 | 26 | static FileStream s_logFile; 27 | static char s_tmpBuffer[4096]; 28 | static char s_printString[4096]; 29 | 30 | bool open(const char* filename) 31 | { 32 | #if XL_LOGGING_ENABLED 33 | return s_logFile.open(filename, FileStream::MODE_WRITE); 34 | #else 35 | return true; 36 | #endif 37 | } 38 | 39 | void close() 40 | { 41 | #if XL_LOGGING_ENABLED 42 | s_logFile.close(); 43 | #endif 44 | } 45 | 46 | void write(LogMessageType type, const char* msg, ...) 47 | { 48 | #if XL_LOGGING_ENABLED || XL_DEBUG_OUT_ENABLED 49 | assert(type < LOG_COUNT); 50 | 51 | //first build up the string. 52 | va_list arg; 53 | va_start(arg, msg); 54 | vsprintf(s_tmpBuffer, msg, arg); 55 | va_end(arg); 56 | #endif 57 | 58 | #if XL_LOGGING_ENABLED 59 | sprintf(s_printString, "%s%s\r\n", c_logMsgType[type], s_tmpBuffer); 60 | const size_t len = strlen(s_printString); 61 | 62 | s_logFile.write(s_printString, (u32)len); 63 | s_logFile.flush(); //flush to disk in case of a crash. 64 | #endif 65 | 66 | #if XL_DEBUG_OUT_ENABLED 67 | sprintf(s_printString, "%s%s\n", c_logMsgType[type], s_tmpBuffer); 68 | debugMessage(s_printString); 69 | #endif 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /XLEngine/log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | #define XL_LOGGING_ENABLED 1 5 | #define XL_DEBUG_OUT_ENABLED 1 6 | 7 | enum LogMessageType 8 | { 9 | LOG_ERROR = 0, 10 | LOG_WARNING, 11 | LOG_MESSAGE, 12 | LOG_COUNT 13 | }; 14 | 15 | #if XL_LOGGING_ENABLED || XL_DEBUG_OUT_ENABLED 16 | #define LOG Log::write 17 | #else 18 | #define LOG 19 | #endif 20 | 21 | namespace Log 22 | { 23 | bool open(const char* filename); 24 | void close(); 25 | 26 | void write(LogMessageType type, const char* msg, ...); 27 | }; -------------------------------------------------------------------------------- /XLEngine/memoryPool.cpp: -------------------------------------------------------------------------------- 1 | #include "memoryPool.h" 2 | #include "log.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | namespace MemoryPool 11 | { 12 | /////////////////////////////////////////////// 13 | // Structures 14 | /////////////////////////////////////////////// 15 | //TO-DO: I could remove the next pointer and calculate it when needed, saving 4-8 bytes in the header. 16 | //However the prev pointer would add a fair amount of overhead to calculate [jump to the beginning of the list and 17 | //iterate until it is found], but could be changed to an offset fixing the size to 4 bytes even in 64bit. 18 | //This would fix the size at 8 bytes (verus 12 in 32bit and 20 in 64bit). 19 | struct Header 20 | { 21 | u32 size; 22 | Header* next; 23 | Header* prev; 24 | }; 25 | 26 | struct MemPool 27 | { 28 | size_t allocCount; 29 | Header* head; 30 | u8* top; 31 | }; 32 | 33 | /////////////////////////////////////////////// 34 | // Constants and Defines 35 | /////////////////////////////////////////////// 36 | const u32 c_topBit = 1<<31; 37 | const u32 c_clearMask = ~c_topBit; 38 | const u32 c_sizeMask = c_topBit - 1; 39 | const size_t c_memChunkSize = 32 * 1024 * 1024; //32MB 40 | const size_t c_headerSize = sizeof(Header); 41 | 42 | #define IS_USED(s) ( (s)->size & c_topBit ) 43 | #define GET_SIZE(s) ( (s)->size & c_sizeMask ) 44 | #define SET_USED(s) ( (s)->size |= c_topBit ) 45 | #define CLEAR_USED(s) ( (s)->size &= c_clearMask ) 46 | #define SET_SIZE_USED(s, n) (s)->size = ( (n) | c_topBit ) 47 | #define GET_POINTER(p) (void*)( (u8*)p + c_headerSize); 48 | #define GET_HEADER(p) (Header*)((u8*)p - c_headerSize); 49 | 50 | /////////////////////////////////////////////// 51 | // Internal Variables 52 | /////////////////////////////////////////////// 53 | static vector s_memPools; 54 | static s32 s_memUsed; 55 | static s32 s_lastReported; 56 | 57 | /////////////////////////////////////////////// 58 | // Forward Declarations 59 | /////////////////////////////////////////////// 60 | Header* getAllocation(MemPool* pool, u32 size); 61 | MemPool* allocatePool(); 62 | void deallocatePools(); 63 | 64 | 65 | /////////////////////////////////////////////// 66 | // API Implementation 67 | /////////////////////////////////////////////// 68 | bool init() 69 | { 70 | //allocate a single chunk to start out with. 71 | s_memPools.reserve( 16 ); 72 | s_memUsed = 0; 73 | s_lastReported = 0; 74 | MemPool* pool = allocatePool(); 75 | return (pool != NULL); 76 | } 77 | 78 | void destroy() 79 | { 80 | deallocatePools(); 81 | } 82 | 83 | //Reset the memory pool 84 | void reset() 85 | { 86 | LOG( LOG_MESSAGE, "Memory Pool Reset [previous allocations = %d bytes]", s_memUsed ); 87 | s_memUsed = 0; 88 | s_lastReported = 0; 89 | 90 | const size_t poolCount = s_memPools.size(); 91 | MemPool** poolList = s_memPools.data(); 92 | for (size_t p=0; ptop, 0, c_memChunkSize); 97 | pool->allocCount = 1; 98 | pool->head = NULL; 99 | 100 | getAllocation(pool, c_memChunkSize - c_headerSize); 101 | } 102 | } 103 | 104 | u32 getMemUsed() 105 | { 106 | assert(s_memUsed >= 0); 107 | return u32( s_memUsed ); 108 | } 109 | 110 | void* xlMalloc(size_t size) 111 | { 112 | if (size == 0) { return NULL; } 113 | 114 | //find the first pool with a large enough slot... 115 | void* out = NULL; 116 | 117 | const size_t poolCount = s_memPools.size(); 118 | MemPool** poolList = s_memPools.data(); 119 | for (size_t p=0; p= size) 187 | { 188 | return ptr; 189 | } 190 | else if (header->next && !IS_USED(header->next) && GET_SIZE(header)+GET_SIZE(header->next)+c_headerSize >= size) 191 | { 192 | s_memUsed += GET_SIZE(header->next); 193 | 194 | SET_SIZE_USED( header, GET_SIZE(header) + GET_SIZE(header->next) + c_headerSize ); 195 | header->next = header->next->next; 196 | header->next->prev = header; 197 | 198 | return ptr; 199 | } 200 | 201 | void* newPtr = xlMalloc(size); 202 | memcpy(newPtr, ptr, GET_SIZE(header)); 203 | 204 | xlFree(ptr); 205 | return newPtr; 206 | } 207 | 208 | void xlFree(void* ptr) 209 | { 210 | if (ptr == NULL) 211 | return; 212 | 213 | Header* header = GET_HEADER(ptr); 214 | s_memUsed -= GET_SIZE(header); 215 | assert( s_memUsed >= 0 ); 216 | 217 | //merge blocks 218 | if (header->next && !IS_USED(header->next)) 219 | { 220 | s_memUsed -= c_headerSize; 221 | assert( s_memUsed >= 0 ); 222 | 223 | header->size = GET_SIZE(header) + GET_SIZE(header->next) + c_headerSize; 224 | header->next = header->next->next; 225 | if (header->next) 226 | { 227 | header->next->prev = header; 228 | } 229 | } 230 | if (header->prev && !IS_USED(header->prev)) 231 | { 232 | s_memUsed -= c_headerSize; 233 | assert( s_memUsed >= 0 ); 234 | 235 | const u32 newSize = GET_SIZE(header) + GET_SIZE(header->prev) + c_headerSize; 236 | 237 | Header* n = header->next; 238 | header = header->prev; 239 | header->next = n; 240 | header->size = newSize; 241 | if (n) 242 | { 243 | n->prev = header; 244 | } 245 | } 246 | 247 | //make it available for allocations. 248 | CLEAR_USED(header); 249 | } 250 | 251 | void test() 252 | { 253 | void* ptr0 = xlMalloc( 295 ); 254 | void* ptr1 = xlMalloc( 3095 ); 255 | xlFree(ptr1); 256 | ptr1 = xlMalloc(3056); 257 | ptr0 = xlRealloc(ptr0, 406); 258 | } 259 | 260 | ///////////////////////////////////// 261 | // Internal 262 | ///////////////////////////////////// 263 | Header* getAllocation(MemPool* pool, u32 size) 264 | { 265 | Header* alloc = NULL; 266 | if (pool->head == NULL) 267 | { 268 | alloc = (Header*)pool->top; 269 | alloc->size = size; 270 | alloc->next = NULL; 271 | alloc->prev = NULL; 272 | pool->head = alloc; 273 | 274 | s_memUsed += c_headerSize; 275 | } 276 | else 277 | { 278 | alloc = pool->head; 279 | while (alloc) 280 | { 281 | const u32 allocSize = GET_SIZE(alloc); 282 | if (allocSize >= size && !IS_USED(alloc)) 283 | { 284 | //decide whether to split or not... 285 | if (allocSize >= size+c_headerSize) 286 | { 287 | Header* n = alloc->next; 288 | Header* newAlloc = (Header*)( (u8*)alloc + c_headerSize + size ); 289 | s_memUsed += c_headerSize; 290 | 291 | newAlloc->size = allocSize - size - c_headerSize; 292 | newAlloc->next = n; 293 | newAlloc->prev = alloc; 294 | if (n) 295 | { 296 | n->prev = newAlloc; 297 | } 298 | 299 | alloc->next = newAlloc; 300 | alloc->size = size; 301 | } 302 | 303 | SET_USED(alloc); 304 | s_memUsed += GET_SIZE(alloc); 305 | 306 | //Log memory usage every 1MB 307 | if ( s_memUsed >= s_lastReported+(1<<20) ) 308 | { 309 | LOG( LOG_MESSAGE, "Memory watermark - used = %d bytes", s_memUsed ); 310 | s_lastReported = s_memUsed; 311 | } 312 | 313 | return alloc; 314 | } 315 | 316 | alloc = alloc->next; 317 | }; 318 | } 319 | 320 | return alloc; 321 | } 322 | 323 | MemPool* allocatePool() 324 | { 325 | MemPool* pool = new MemPool; 326 | pool->allocCount = 1; 327 | pool->head = NULL; 328 | pool->top = (u8*)malloc( c_memChunkSize ); 329 | 330 | getAllocation(pool, c_memChunkSize - c_headerSize); 331 | s_memPools.push_back( pool ); 332 | 333 | LOG( LOG_MESSAGE, "Memory Pool Allocated, count = %u.", (u32)s_memPools.size() ); 334 | return pool; 335 | } 336 | 337 | void deallocatePools() 338 | { 339 | const size_t poolCount = s_memPools.size(); 340 | MemPool** poolList = s_memPools.data(); 341 | for (size_t p=0; ptop); 344 | delete poolList[p]; 345 | } 346 | s_memPools.clear(); 347 | } 348 | }; 349 | -------------------------------------------------------------------------------- /XLEngine/memoryPool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 | // Memory Pool used by the Games 6 | // Freeing a game consists of resetting the whole memory pool. 7 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | //wacky template magic, used to safely determine array size or generate a compile error if used incorrectly. 10 | template 11 | inline u32 arraysize(const T (&v)[S]) { return S; } 12 | 13 | namespace MemoryPool 14 | { 15 | bool init(); 16 | void destroy(); 17 | 18 | //Reset the memory pool 19 | void reset(); 20 | 21 | void* xlMalloc(size_t size); 22 | void* xlCalloc(size_t size, size_t num); 23 | void* xlRealloc(void* ptr, size_t size); 24 | void xlFree(void* ptr); 25 | 26 | u32 getMemUsed(); 27 | 28 | void test(); 29 | }; -------------------------------------------------------------------------------- /XLEngine/osUtil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | namespace OS 5 | { 6 | void sleep(u32 sleepDeltaMS); 7 | } -------------------------------------------------------------------------------- /XLEngine/services.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include "xlServices.h" 4 | 5 | class GraphicsDevice; 6 | 7 | namespace Services 8 | { 9 | void setup(int gameWidth, int gameHeight, GraphicsDevice* gdev); 10 | XLEngineServices* get(); 11 | 12 | void setTime(u64 time); 13 | void xlDebugMessage(const char* msg, ...); 14 | 15 | void reset(); 16 | }; 17 | -------------------------------------------------------------------------------- /XLEngine/settings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include "xlServices.h" 4 | #include "Sound/midi.h" 5 | #include "Graphics/graphicsDeviceList.h" 6 | 7 | enum XLSettingsFlags 8 | { 9 | XL_FLAG_NONE = 0, 10 | XL_FLAG_FULLSCREEN = (1<<0), //full screen 11 | XL_FLAG_VSYNC = (1<<1), //vsync 12 | XL_FLAG_IMMEDIATE_EXIT = (1<<2), //exit the application when a game is exited. 13 | XL_FLAG_SHOW_ALL_GAMES = (1<<3), //show all games even if they can't be run on the users system. 14 | XL_FLAG_UI_GLOW = (1<<4), //enable the UI glow effect (visual only). 15 | XL_FLAG_COLOR_CORRECT = (1<<5), //enable color correction for the game view (slightly slower). 16 | XL_FLAG_REDUCE_CPU = (1<<6), //reduce CPU usage 17 | }; 18 | 19 | struct XLSettings 20 | { 21 | u32 flags; 22 | s32 launchGameID; //Game to launch on XL Engine startup (-1 to show the UI where the user can select a game) 23 | s32 frameLimit; //Framerate limit (for the main thread) 24 | 25 | s32 windowScale; //Window 4:3 scale, resolution = 320x240 x windowScale (not used when in fullscreen) 26 | s32 gameScale; //Game scale, resolution = 320x200 x gameScale for 16:10 in 4:3 or 320x240 x gameScale for 4:3 27 | 28 | s32 windowWidth; //Final window width after taking into account fullscreen and window scale 29 | s32 windowHeight; //Final window height after taking into account fullscreen and window scale 30 | 31 | s32 gameWidth; //Final virtual game width after taking into account game scale 32 | s32 gameHeight; //Final virtual game height after taking into account game scale 33 | 34 | f32 colorCorrect[4];//Color correction values: brightness, saturation, contrast, gamma 35 | 36 | //Sound 37 | MidiFormat midiformat; 38 | char patchDataLoc[256]; 39 | u32 musicVolume; 40 | u32 soundVolume; 41 | }; 42 | 43 | namespace Settings 44 | { 45 | const char* getVersion(); 46 | 47 | bool read(int monitorWidth, int monitorHeight); 48 | void write(); 49 | void initGameData(); 50 | 51 | XLSettings* get(); 52 | 53 | s32 getGameCount(); 54 | GameInfo* getGameInfo(s32 id); 55 | 56 | void setGameID(s32 id); 57 | s32 getGameID(); 58 | 59 | GraphicsDeviceID getGraphicsDeviceID(); 60 | void setGraphicsDeviceID(GraphicsDeviceID deviceID); 61 | }; 62 | -------------------------------------------------------------------------------- /XLEngine/stream.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include 4 | #include 5 | 6 | class Stream 7 | { 8 | public: 9 | enum Origin 10 | { 11 | ORIGIN_START = 0, 12 | ORIGIN_END, 13 | ORIGIN_CURRENT, 14 | ORIGIN_COUNT 15 | }; 16 | public: 17 | Stream() {}; 18 | ~Stream() {}; 19 | 20 | virtual void seek(u32 offset, Origin origin=ORIGIN_START)=0; 21 | virtual size_t getLoc()=0; 22 | virtual size_t getSize()=0; 23 | 24 | virtual void read(s8* ptr, u32 count=1)=0; 25 | virtual void read(u8* ptr, u32 count=1)=0; 26 | virtual void read(s16* ptr, u32 count=1)=0; 27 | virtual void read(u16* ptr, u32 count=1)=0; 28 | virtual void read(s32* ptr, u32 count=1)=0; 29 | virtual void read(u32* ptr, u32 count=1)=0; 30 | virtual void read(s64* ptr, u32 count=1)=0; 31 | virtual void read(u64* ptr, u32 count=1)=0; 32 | virtual void read(f32* ptr, u32 count=1)=0; 33 | virtual void read(f64* ptr, u32 count=1)=0; 34 | virtual void read(std::string* ptr, u32 count=1)=0; 35 | virtual void readBuffer(void* ptr, u32 size, u32 count=1)=0; 36 | 37 | virtual void write(const s8* ptr, u32 count=1)=0; 38 | virtual void write(const u8* ptr, u32 count=1)=0; 39 | virtual void write(const s16* ptr, u32 count=1)=0; 40 | virtual void write(const u16* ptr, u32 count=1)=0; 41 | virtual void write(const s32* ptr, u32 count=1)=0; 42 | virtual void write(const u32* ptr, u32 count=1)=0; 43 | virtual void write(const s64* ptr, u32 count=1)=0; 44 | virtual void write(const u64* ptr, u32 count=1)=0; 45 | virtual void write(const f32* ptr, u32 count=1)=0; 46 | virtual void write(const f64* ptr, u32 count=1)=0; 47 | virtual void write(const std::string* ptr, u32 count=1)=0; 48 | virtual void writeBuffer(const void* ptr, u32 size, u32 count=1)=0; 49 | }; -------------------------------------------------------------------------------- /XLEngine/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _WIN32 4 | #include 5 | #include 6 | #endif 7 | 8 | typedef unsigned long long u64; 9 | typedef unsigned int u32; 10 | typedef unsigned short u16; 11 | typedef unsigned char u8; 12 | 13 | typedef long long s64; 14 | typedef int s32; 15 | typedef short s16; 16 | typedef char s8; 17 | 18 | typedef float f32; 19 | typedef double f64; 20 | 21 | #ifdef _WIN32 22 | #define XL_STDCALL __stdcall 23 | #else 24 | #define XL_STDCALL 25 | #endif 26 | -------------------------------------------------------------------------------- /XLEngine/xlServices.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include 8 | 9 | #define XL_SOUND_NO_CALLBACK 0xffffffff 10 | 11 | #define MAX_MAPPING_COUNT 16 12 | #define MAX_ACTION_COUNT 128 13 | 14 | #define XL_FILE_READ 0 15 | #define XL_FILE_WRITE 1 16 | #define XL_FILE_READWRITE 2 17 | 18 | #define XL_FILE_ORIGIN_START 0 19 | #define XL_FILE_ORIGIN_END 1 20 | #define XL_FILE_ORIGIN_CURRENT 2 21 | 22 | typedef int Bool; 23 | 24 | enum XLSoundType 25 | { 26 | STYPE_RAW = 0, 27 | STYPE_VOC, 28 | STYPE_WAV, 29 | STYPE_COUNT 30 | }; 31 | 32 | enum XLMusicType 33 | { 34 | MUSIC_TYPE_UNKNOWN = 0, 35 | MUSIC_TYPE_MIDI, 36 | MUSIC_TYPE_OGG, 37 | MUSIC_TYPE_COUNT 38 | }; 39 | 40 | typedef struct ActionMapping 41 | { 42 | char action[256]; 43 | int mappingCount; 44 | char keys[MAX_MAPPING_COUNT][256]; 45 | } ActionMapping; 46 | 47 | typedef struct GameInfo 48 | { 49 | char name[256]; //Proper game name (for example "Dark Forces") 50 | char lib[512]; //Game library name with no extension 51 | char iconFile[512]; //Icon file name 52 | char path[4096]; //Game Data absolute path (original source data only) 53 | int iconID; //Icon ID used for rendering the UI icon. 54 | 55 | //key mapping. 56 | int actionCount; 57 | ActionMapping actionMapping[MAX_ACTION_COUNT]; 58 | } GameInfo; 59 | 60 | typedef struct SoundInfo 61 | { 62 | unsigned int samplingRate; //11025, ... 63 | unsigned int bitRate; //8 or 16 64 | unsigned int userValue; //used for optional callbacks 65 | float volume; //volume, range: [0, 1] 66 | float pan; //stereo pan, range: [-1, 1] 67 | Bool stereo; //true for stereo, else mono 68 | } SoundInfo; 69 | 70 | typedef void (*XLSoundCallback)(unsigned int); 71 | 72 | typedef void (*XLSetPalette)(unsigned char*, int); 73 | typedef void (*XLGetPalette)(unsigned char*); 74 | typedef void (*XLCopyToFramebuffer)(unsigned char*); 75 | 76 | typedef int (*XLGetClock)(void); 77 | typedef void (*XLSetClock)(int); 78 | typedef void (*XLResetClock)(void); 79 | typedef void (*XLYield)(void); 80 | typedef int (*XLGetScreenSize)(void); 81 | 82 | typedef void* (*XLMalloc)(size_t); 83 | typedef void* (*XLCalloc)(size_t, size_t); 84 | typedef void* (*XLRealloc)(void*, size_t); 85 | typedef void (*XLFree)(void*); 86 | 87 | typedef void (*XLDebugMessage)(const char*, ...); 88 | typedef void (*XLKeyEvent)(int, int, int); 89 | typedef void (*XLGetMouseDelta)(int*, int*); 90 | typedef void (*XLGetMouseButtons)(int*); 91 | 92 | typedef const char* (*XLBuildGamePath)(const char*); 93 | typedef const GameInfo* (*XLGetGameInfo)(void); 94 | 95 | typedef void (*XLSoundSetCallback)(XLSoundCallback); 96 | typedef unsigned int (*XLSoundPlay2D)(const char*, const void*, unsigned int, unsigned int, SoundInfo*, Bool); 97 | typedef int (*XLSoundIsPlaying)(unsigned int); 98 | typedef void (*XLSoundSetPan)(unsigned int, float); 99 | typedef void (*XLStopSound)(unsigned int); 100 | typedef void (*XLStopAllSounds)(void); 101 | typedef int (*XLSoundsPlaying)(void); 102 | 103 | typedef int (*XLFileOpen)(const char*, int); 104 | typedef void (*XLFileClose)(int); 105 | typedef size_t (*XLFileRead)(void*, size_t, size_t, int); 106 | typedef size_t (*XLFileWrite)(const void*, size_t, size_t, int); 107 | typedef void (*XLFileSeek)(int, int, int); 108 | typedef size_t (*XLFileTell)(int); 109 | 110 | typedef int (*XLMusicIsPlaying)(void); 111 | typedef void (*XLMusicVoid)(void); 112 | typedef int (*XLMusicPlay)(const char*, int); 113 | 114 | typedef struct 115 | { 116 | //video 117 | XLSetPalette setPalette; 118 | XLGetPalette getPalette; 119 | XLCopyToFramebuffer copyToFramebuffer; 120 | 121 | //virtual screen 122 | XLGetScreenSize getScreenWidth; 123 | XLGetScreenSize getScreenHeight; 124 | 125 | //timing 126 | XLGetClock getClock; 127 | XLSetClock setClock; 128 | XLResetClock resetClock; 129 | XLYield yield; 130 | 131 | //input 132 | XLKeyEvent keyEvent; 133 | XLGetMouseDelta getMouseDelta; 134 | XLGetMouseButtons getMouseButtons; 135 | 136 | //memory 137 | XLMalloc malloc; 138 | XLCalloc calloc; 139 | XLRealloc realloc; 140 | XLFree free; 141 | 142 | //debug 143 | XLDebugMessage debugMsg; 144 | 145 | //file I/O 146 | XLBuildGamePath buildGamePath; 147 | //file I/O functions automatically remap paths to the game root path. 148 | XLFileOpen fileOpen; 149 | XLFileClose fileClose; 150 | XLFileRead fileRead; 151 | XLFileWrite fileWrite; 152 | XLFileSeek fileSeek; 153 | XLFileTell fileTell; 154 | 155 | //game info 156 | XLGetGameInfo getGameInfo; 157 | 158 | //sound 159 | XLSoundSetCallback soundSetCallback; 160 | XLSoundPlay2D soundPlay2D; 161 | XLSoundIsPlaying soundIsPlaying; 162 | XLSoundSetPan soundSetVolume; 163 | XLSoundSetPan soundSetPan; 164 | XLStopSound stopSound; 165 | XLStopAllSounds stopAllSounds; 166 | XLSoundsPlaying soundsPlaying; 167 | 168 | XLMusicPlay music_play; 169 | XLMusicVoid music_stop; 170 | XLMusicIsPlaying music_isPlaying; 171 | XLMusicVoid music_pause; 172 | XLMusicVoid music_resume; 173 | } XLEngineServices; 174 | 175 | #ifdef __cplusplus 176 | }; 177 | #endif 178 | -------------------------------------------------------------------------------- /buildVersion.txt: -------------------------------------------------------------------------------- 1 | 962 2 | -------------------------------------------------------------------------------- /small.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luciusDXL/XL-Engine/cd3b467b58d6c35f5d46cf481bc035da30ac21c3/small.ico -------------------------------------------------------------------------------- /stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // ShadowWarriorXL.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files: 12 | #include 13 | 14 | // C RunTime Header Files 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | // TODO: reference additional headers your program requires here 22 | -------------------------------------------------------------------------------- /targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | --------------------------------------------------------------------------------