mirror of
https://github.com/simtactics/niotso.git
synced 2025-03-22 10:52:20 +00:00
Split off the Windows message handler into a separate thread.
This commit is contained in:
parent
d9afae7022
commit
4294cb41f7
11 changed files with 547 additions and 217 deletions
|
@ -7,7 +7,6 @@ include_directories(${CMAKE_SOURCE_DIR}/Libraries/freetype/include)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(NIOTSOCLIENT_SOURCES
|
set(NIOTSOCLIENT_SOURCES
|
||||||
Client.cpp
|
Client.cpp
|
||||||
MessageHandler.cpp
|
|
||||||
Audio/Startup.cpp
|
Audio/Startup.cpp
|
||||||
Audio/windows/XAudio2.cpp
|
Audio/windows/XAudio2.cpp
|
||||||
Graphics/Font.cpp
|
Graphics/Font.cpp
|
||||||
|
@ -15,7 +14,8 @@ if(WIN32)
|
||||||
Graphics/Viewport.cpp
|
Graphics/Viewport.cpp
|
||||||
resources/Resource.rc
|
resources/Resource.rc
|
||||||
System/System.cpp
|
System/System.cpp
|
||||||
|
Window/Window.cpp
|
||||||
)
|
)
|
||||||
add_executable(TSO WIN32 ${NIOTSOCLIENT_SOURCES})
|
add_executable(TSO ${NIOTSOCLIENT_SOURCES})
|
||||||
target_link_libraries(TSO FileHandler_shared freetype_shared ole32 opengl32)
|
target_link_libraries(TSO FileHandler_shared freetype_shared ole32 opengl32)
|
||||||
endif()
|
endif()
|
|
@ -17,15 +17,7 @@
|
||||||
|
|
||||||
#include "EngineInterface.hpp"
|
#include "EngineInterface.hpp"
|
||||||
|
|
||||||
namespace Window {
|
|
||||||
unsigned Width, Height;
|
|
||||||
bool Fullscreen = false;
|
|
||||||
HWND hWnd = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CreateWindowInvisible(HINSTANCE hInst, unsigned Width, unsigned Height, bool Fullscreen);
|
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
Scene * CurrentScene;
|
Scene * CurrentScene;
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
|
||||||
|
@ -33,18 +25,22 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
//Disallow multiple instances of the game from running
|
//Disallow multiple instances of the game from running
|
||||||
CreateMutex(NULL, TRUE, "TSO_NIOTSO_MUTEX");
|
if(CreateMutex(NULL, TRUE, "TSO_NIOTSO_MUTEX") == NULL){
|
||||||
if(GetLastError() == ERROR_ALREADY_EXISTS){
|
|
||||||
HWND hWnd = FindWindow("TSO_NIOTSO", "The Sims Online");
|
HWND hWnd = FindWindow("TSO_NIOTSO", "The Sims Online");
|
||||||
if(hWnd != NULL){
|
if(hWnd != NULL){
|
||||||
ShowWindowAsync(hWnd, SW_RESTORE);
|
ShowWindow(hWnd, SW_RESTORE);
|
||||||
SetForegroundWindow(hWnd);
|
SetForegroundWindow(hWnd);
|
||||||
SetFocus(hWnd);
|
SetFocus(hWnd);
|
||||||
}
|
}
|
||||||
return ERROR_INIT_ANOTHERINSTRUNNING;
|
return ERROR_INIT_ANOTHERINSTRUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = CreateWindowInvisible(hInstance, 800, 600, false);
|
Window::Width = 800;
|
||||||
|
Window::Height = 600;
|
||||||
|
Window::Fullscreen = false;
|
||||||
|
System::hInst = hInstance;
|
||||||
|
|
||||||
|
result = Window::Initialize();
|
||||||
if(result != 0){
|
if(result != 0){
|
||||||
Shutdown();
|
Shutdown();
|
||||||
return ERROR_INIT | ERROR_INIT_WINDOW | result;
|
return ERROR_INIT | ERROR_INIT_WINDOW | result;
|
||||||
|
@ -82,17 +78,15 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
|
||||||
QueryPerformanceCounter(&PreviousTime);
|
QueryPerformanceCounter(&PreviousTime);
|
||||||
|
|
||||||
while(true){
|
while(true){
|
||||||
MSG msg;
|
|
||||||
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
LARGE_INTEGER CurrentTime;
|
LARGE_INTEGER CurrentTime;
|
||||||
QueryPerformanceCounter(&CurrentTime);
|
QueryPerformanceCounter(&CurrentTime);
|
||||||
float TimeDelta = (float)(CurrentTime.QuadPart-PreviousTime.QuadPart)/System::ClockFreq.QuadPart;
|
float TimeDelta = (float)(CurrentTime.QuadPart-PreviousTime.QuadPart)/System::ClockFreq.QuadPart;
|
||||||
if(TimeDelta < 0 || TimeDelta >= 5) //Invalid TimeDelta
|
if(TimeDelta < 0 || TimeDelta >= 5){ //Invalid TimeDelta
|
||||||
|
PreviousTime.QuadPart = CurrentTime.QuadPart;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&System::UserInput, (const void*) &System::UserInput_v, sizeof(System::UserInput_t));
|
||||||
|
|
||||||
int result = CurrentScene->RunFor(TimeDelta);
|
int result = CurrentScene->RunFor(TimeDelta);
|
||||||
if(result == System::SHUTDOWN)
|
if(result == System::SHUTDOWN)
|
||||||
|
@ -117,89 +111,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CreateWindowInvisible(HINSTANCE hInst, unsigned Width, unsigned Height, bool Fullscreen)
|
|
||||||
{
|
|
||||||
const WNDCLASS wc = {
|
|
||||||
CS_OWNDC, //style
|
|
||||||
WndProc, //lpfnWndProc
|
|
||||||
0, //cbClsExtra
|
|
||||||
0, //cbWndExtra
|
|
||||||
hInst, //hInstance
|
|
||||||
(HICON) LoadImage(hInst, MAKEINTRESOURCE(IDI_TSO), //hIcon
|
|
||||||
IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE),
|
|
||||||
NULL, //hCursor
|
|
||||||
NULL, //hbrBackground
|
|
||||||
NULL, //lpszMenuName
|
|
||||||
"TSO_NIOTSO" //lpszClassName
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!RegisterClass(&wc)){
|
|
||||||
MessageBox(NULL, "Failed to register the window class.", NULL, MB_OK | MB_ICONERROR);
|
|
||||||
return ERROR_REGISTER_CLASS;
|
|
||||||
}
|
|
||||||
SetCursor(NULL);
|
|
||||||
|
|
||||||
HWND hWnd = NULL;
|
|
||||||
if(Fullscreen){
|
|
||||||
DEVMODE dmScreenSettings;
|
|
||||||
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
|
|
||||||
dmScreenSettings.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT|DM_BITSPERPEL;
|
|
||||||
dmScreenSettings.dmPelsWidth = Width;
|
|
||||||
dmScreenSettings.dmPelsHeight = Height;
|
|
||||||
dmScreenSettings.dmBitsPerPel = 32;
|
|
||||||
|
|
||||||
if(ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL){
|
|
||||||
MessageBox(NULL, "Fullscreen mode is not supported by your setup. It has been turned off.", NULL,
|
|
||||||
MB_OK | MB_ICONERROR);
|
|
||||||
Fullscreen = 0;
|
|
||||||
}else{
|
|
||||||
hWnd = CreateWindowEx(WS_EX_APPWINDOW, "TSO_NIOTSO", "The Sims Online", WS_POPUP,
|
|
||||||
0, 0, Width, Height, 0, 0, hInst, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(hWnd == NULL){
|
|
||||||
Fullscreen = false;
|
|
||||||
RECT WindowRect = {0, 0, Width, Height};
|
|
||||||
|
|
||||||
//Use a style of WS_OVERLAPPEDWINDOW to allow resizing
|
|
||||||
AdjustWindowRectEx(&WindowRect, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE,
|
|
||||||
WS_EX_APPWINDOW); //This finds the dimensions of a window with a client area of our specified dimensions
|
|
||||||
|
|
||||||
//Note: Windows can be positioned anywhere, even outside the visible workspace,
|
|
||||||
//but their sizes are limited to the size of the workspace on the primary display.
|
|
||||||
unsigned WindowWidth = WindowRect.right-WindowRect.left, WindowHeight = WindowRect.bottom-WindowRect.top;
|
|
||||||
RECT WorkspaceRect;
|
|
||||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &WorkspaceRect, 0);
|
|
||||||
|
|
||||||
hWnd = CreateWindowEx(WS_EX_APPWINDOW, "TSO_NIOTSO", "The Sims Online",
|
|
||||||
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
|
|
||||||
((WorkspaceRect.right-WorkspaceRect.left - WindowWidth)>>1) + WorkspaceRect.left,
|
|
||||||
((WorkspaceRect.bottom-WorkspaceRect.top - WindowHeight)>>1) + WorkspaceRect.top,
|
|
||||||
WindowWidth, WindowHeight, 0, 0, hInst, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hWnd == NULL){
|
|
||||||
MessageBox(NULL, "Failed to create the window.", NULL, MB_OK | MB_ICONERROR);
|
|
||||||
return ERROR_CREATE_WINDOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
Window::hWnd = hWnd;
|
|
||||||
Window::Width = Width;
|
|
||||||
Window::Height = Height;
|
|
||||||
Window::Fullscreen = Fullscreen;
|
|
||||||
System::hInst = hInst;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
{
|
{
|
||||||
Audio::Shutdown();
|
Audio::Shutdown();
|
||||||
Graphics::Shutdown();
|
Graphics::Shutdown();
|
||||||
System::Shutdown();
|
System::Shutdown();
|
||||||
|
Window::Shutdown();
|
||||||
if(Window::hWnd){
|
|
||||||
DestroyWindow(Window::hWnd);
|
|
||||||
Window::hWnd = NULL;
|
|
||||||
}
|
|
||||||
UnregisterClass("TSO_NIOTSO", System::hInst);
|
|
||||||
}
|
}
|
|
@ -15,18 +15,25 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//Compiler/platform constants
|
||||||
#define WINVER 0x0502
|
#define WINVER 0x0502
|
||||||
#define _WIN32_WINNT 0x0502
|
#define _WIN32_WINNT 0x0502
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
|
||||||
|
//Standard libraries
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <memory.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#undef NULL
|
#undef NULL
|
||||||
#define NULL 0
|
#define NULL 0
|
||||||
|
|
||||||
|
//Codebase libraries
|
||||||
#include "FileHandler.hpp"
|
#include "FileHandler.hpp"
|
||||||
#include "ft2build.h"
|
#include "ft2build.h"
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
//Macro definitions
|
||||||
#ifndef min
|
#ifndef min
|
||||||
#define min(x,y) ((x)<(y)?(x):(y))
|
#define min(x,y) ((x)<(y)?(x):(y))
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,20 +41,14 @@
|
||||||
#define max(x,y) ((x)>(y)?(x):(y))
|
#define max(x,y) ((x)>(y)?(x):(y))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//IsometricEngine.cpp
|
//Codebase version, branding, linker resources
|
||||||
namespace Window {
|
|
||||||
extern unsigned Width, Height;
|
|
||||||
extern bool Fullscreen;
|
|
||||||
extern HWND hWnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
//MessageHandler.cpp
|
|
||||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
||||||
|
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "System/System.hpp"
|
|
||||||
#include "Resources/Resource.h"
|
#include "Resources/Resource.h"
|
||||||
|
|
||||||
|
//Components
|
||||||
#include "Audio/Audio.hpp"
|
#include "Audio/Audio.hpp"
|
||||||
#include "Graphics/Graphics.hpp"
|
#include "Graphics/Graphics.hpp"
|
||||||
|
#include "System/System.hpp"
|
||||||
|
#include "Window/Window.hpp"
|
||||||
|
|
||||||
#include "Scene/Scene.hpp"
|
#include "Scene/Scene.hpp"
|
|
@ -1,59 +0,0 @@
|
||||||
/*
|
|
||||||
Niotso - Copyright (C) 2012 Fatbag <X-Fi6@phppoll.org>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "EngineInterface.hpp"
|
|
||||||
|
|
||||||
/****
|
|
||||||
For the sake of performance **all throughout the game**,
|
|
||||||
order the cases in order from most frequently occurred to less frequently occurred
|
|
||||||
except making adjustments where tiny response latency is essential
|
|
||||||
*/
|
|
||||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
switch(uMsg)
|
|
||||||
{
|
|
||||||
case WM_SETCURSOR: //Occurs often
|
|
||||||
SetCursor(NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_SYSCOMMAND: //Occurs often
|
|
||||||
switch(wParam){
|
|
||||||
case SC_MONITORPOWER:
|
|
||||||
case SC_SCREENSAVE:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_KEYDOWN:
|
|
||||||
case WM_KEYUP:
|
|
||||||
System::UserInput.Keys[wParam] = (uMsg == WM_KEYDOWN);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case WM_CLOSE:
|
|
||||||
System::UserInput.CloseWindow = true;
|
|
||||||
PostQuitMessage(0);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case WM_DEVMODECHANGE: {
|
|
||||||
DEVMODE dm;
|
|
||||||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
|
|
||||||
System::FramePeriod = 1.0f/dm.dmDisplayFrequency;
|
|
||||||
} return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
|
||||||
}
|
|
|
@ -18,15 +18,17 @@
|
||||||
#include "../EngineInterface.hpp"
|
#include "../EngineInterface.hpp"
|
||||||
|
|
||||||
namespace System {
|
namespace System {
|
||||||
HINSTANCE hInst = NULL;
|
|
||||||
HANDLE Process;
|
|
||||||
HANDLE ProcessHeap;
|
|
||||||
LARGE_INTEGER ClockFreq;
|
|
||||||
float FramePeriod;
|
|
||||||
UserInput_t UserInput;
|
|
||||||
bool SceneFailed = false;
|
|
||||||
|
|
||||||
int Initialize(){
|
HINSTANCE hInst = NULL;
|
||||||
|
HANDLE Process;
|
||||||
|
HANDLE ProcessHeap;
|
||||||
|
LARGE_INTEGER ClockFreq;
|
||||||
|
volatile float FramePeriod;
|
||||||
|
UserInput_t UserInput;
|
||||||
|
volatile UserInput_t UserInput_v;
|
||||||
|
bool SceneFailed = false;
|
||||||
|
|
||||||
|
int Initialize(){
|
||||||
memset(&UserInput, 0, sizeof(UserInput));
|
memset(&UserInput, 0, sizeof(UserInput));
|
||||||
|
|
||||||
QueryPerformanceFrequency(&ClockFreq);
|
QueryPerformanceFrequency(&ClockFreq);
|
||||||
|
@ -50,9 +52,9 @@ namespace System {
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown(){
|
void Shutdown(){
|
||||||
if(Graphics::FontFace){
|
if(Graphics::FontFace){
|
||||||
FT_Done_Face(Graphics::FontFace);
|
FT_Done_Face(Graphics::FontFace);
|
||||||
Graphics::FontFace = NULL;
|
Graphics::FontFace = NULL;
|
||||||
|
@ -61,5 +63,6 @@ namespace System {
|
||||||
FT_Done_FreeType(Graphics::FreeTypeLibrary);
|
FT_Done_FreeType(Graphics::FreeTypeLibrary);
|
||||||
Graphics::FreeTypeLibrary = NULL;
|
Graphics::FreeTypeLibrary = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -15,15 +15,15 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//System/System.cpp
|
|
||||||
namespace System {
|
namespace System {
|
||||||
int Initialize();
|
int Initialize();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
extern HINSTANCE hInst;
|
extern HINSTANCE hInst;
|
||||||
extern HANDLE Process;
|
extern HANDLE Process;
|
||||||
extern HANDLE ProcessHeap;
|
extern HANDLE ProcessHeap;
|
||||||
extern LARGE_INTEGER ClockFreq;
|
extern LARGE_INTEGER ClockFreq;
|
||||||
extern float FramePeriod;
|
extern volatile float FramePeriod;
|
||||||
|
|
||||||
struct UserInput_t {
|
struct UserInput_t {
|
||||||
bool Keys[256];
|
bool Keys[256];
|
||||||
|
@ -31,6 +31,7 @@ namespace System {
|
||||||
bool CloseWindow;
|
bool CloseWindow;
|
||||||
};
|
};
|
||||||
extern UserInput_t UserInput;
|
extern UserInput_t UserInput;
|
||||||
|
extern volatile UserInput_t UserInput_v;
|
||||||
|
|
||||||
extern bool SceneFailed;
|
extern bool SceneFailed;
|
||||||
|
|
||||||
|
@ -52,8 +53,12 @@ namespace System {
|
||||||
//Use: return ERROR_INIT | result;
|
//Use: return ERROR_INIT | result;
|
||||||
#define ERROR_INIT_WINDOW 0x0100
|
#define ERROR_INIT_WINDOW 0x0100
|
||||||
enum {
|
enum {
|
||||||
ERROR_REGISTER_CLASS = 1,
|
ERROR_WINDOW_SYNCOBJECT = 1,
|
||||||
ERROR_CREATE_WINDOW
|
ERROR_WINDOW_CREATE_THREAD,
|
||||||
|
ERROR_WINDOW_SYNCHRONIZE,
|
||||||
|
ERROR_WINDOW_REGISTER_CLASS,
|
||||||
|
ERROR_WINDOW_CREATE,
|
||||||
|
ERROR_WINDOW_HANDLE
|
||||||
};
|
};
|
||||||
#define ERROR_INIT_SYSTEM 0x0200
|
#define ERROR_INIT_SYSTEM 0x0200
|
||||||
enum {
|
enum {
|
||||||
|
|
210
Client/Window/Window.cpp
Normal file
210
Client/Window/Window.cpp
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
Niotso - Copyright (C) 2012 Fatbag <X-Fi6@phppoll.org>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../EngineInterface.hpp"
|
||||||
|
|
||||||
|
namespace Window {
|
||||||
|
|
||||||
|
unsigned Width, Height;
|
||||||
|
bool Fullscreen;
|
||||||
|
HWND hWnd;
|
||||||
|
|
||||||
|
static HANDLE Response = NULL;
|
||||||
|
static HANDLE Thread = NULL;
|
||||||
|
static volatile int Result;
|
||||||
|
|
||||||
|
static DWORD WINAPI Procedure(LPVOID);
|
||||||
|
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
static int CreateWindowInvisible(HINSTANCE hInst, unsigned Width, unsigned Height, bool Fullscreen);
|
||||||
|
|
||||||
|
int Initialize(){
|
||||||
|
Response = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
if(Response == NULL){
|
||||||
|
MessageBox(NULL, "Failed to create the message loop synchronization object.", NULL, MB_OK | MB_ICONERROR);
|
||||||
|
Shutdown();
|
||||||
|
return ERROR_WINDOW_SYNCOBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread = CreateThread(NULL, 1024 /* very tiny stack size is needed */, Window::Procedure, NULL, 0, NULL);
|
||||||
|
if(Thread == NULL){
|
||||||
|
MessageBox(NULL, "Failed to create the message loop thread.", NULL, MB_OK | MB_ICONERROR);
|
||||||
|
Shutdown();
|
||||||
|
return ERROR_WINDOW_CREATE_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(WaitForSingleObject(Window::Response, INFINITE) != WAIT_OBJECT_0){
|
||||||
|
MessageBox(NULL, "Failed to synchronize with the message loop thread.", NULL, MB_OK | MB_ICONERROR);
|
||||||
|
Shutdown();
|
||||||
|
return ERROR_WINDOW_SYNCHRONIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Result != 0){
|
||||||
|
Shutdown();
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
hWnd = FindWindow("TSO_NIOTSO", "The Sims Online");
|
||||||
|
if(hWnd == NULL){
|
||||||
|
MessageBox(NULL, "Failed to obtain a handle for the window.", NULL, MB_OK | MB_ICONERROR);
|
||||||
|
Shutdown();
|
||||||
|
return ERROR_WINDOW_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown(){
|
||||||
|
if(hWnd){
|
||||||
|
DestroyWindow(hWnd);
|
||||||
|
hWnd = NULL;
|
||||||
|
}
|
||||||
|
if(Thread){
|
||||||
|
DWORD value;
|
||||||
|
while(GetExitCodeThread(Thread, &value) && value){
|
||||||
|
//PostQuitMessage() doesn't reliably work from a separate thread
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
|
Thread = NULL;
|
||||||
|
}
|
||||||
|
if(Response){
|
||||||
|
CloseHandle(Response);
|
||||||
|
Response = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnregisterClass("TSO_NIOTSO", System::hInst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
|
||||||
|
switch(uMsg){
|
||||||
|
|
||||||
|
case WM_SETCURSOR:
|
||||||
|
SetCursor(NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_KEYUP:
|
||||||
|
System::UserInput_v.Keys[wParam] = (uMsg == WM_KEYDOWN);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_CLOSE:
|
||||||
|
System::UserInput_v.CloseWindow = true;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_SHOWWINDOW:
|
||||||
|
//Once the window is hidden (we cannot safely destroy the window while we have the OpenGL context),
|
||||||
|
//WM_QUIT and WM_DESTROY won't show up when a separate thread calls DestroyWindow() or PostQuitMessage().
|
||||||
|
if(wParam == FALSE) PostQuitMessage(0);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_DEVMODECHANGE: {
|
||||||
|
DEVMODE dm;
|
||||||
|
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
|
||||||
|
System::FramePeriod = 1.0f/dm.dmDisplayFrequency;
|
||||||
|
} return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI Procedure(LPVOID){
|
||||||
|
int result = CreateWindowInvisible(System::hInst, Window::Width, Window::Height, Window::Fullscreen);
|
||||||
|
if(result != 0){
|
||||||
|
Window::Result = result;
|
||||||
|
SetEvent(Window::Response);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SetEvent(Window::Response);
|
||||||
|
|
||||||
|
MSG msg;
|
||||||
|
while(GetMessage(&msg, NULL, 0, 0)){
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CreateWindowInvisible(HINSTANCE hInst, unsigned Width, unsigned Height, bool Fullscreen)
|
||||||
|
{
|
||||||
|
const WNDCLASS wc = {
|
||||||
|
CS_OWNDC, //style
|
||||||
|
WndProc, //lpfnWndProc
|
||||||
|
0, //cbClsExtra
|
||||||
|
0, //cbWndExtra
|
||||||
|
hInst, //hInstance
|
||||||
|
(HICON) LoadImage(hInst, MAKEINTRESOURCE(IDI_TSO), //hIcon
|
||||||
|
IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE),
|
||||||
|
NULL, //hCursor
|
||||||
|
NULL, //hbrBackground
|
||||||
|
NULL, //lpszMenuName
|
||||||
|
"TSO_NIOTSO" //lpszClassName
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!RegisterClass(&wc)){
|
||||||
|
MessageBox(NULL, "Failed to register the window class.", NULL, MB_OK | MB_ICONERROR);
|
||||||
|
return ERROR_WINDOW_REGISTER_CLASS;
|
||||||
|
}
|
||||||
|
SetCursor(NULL);
|
||||||
|
|
||||||
|
HWND hWnd = NULL;
|
||||||
|
if(Fullscreen){
|
||||||
|
DEVMODE dmScreenSettings;
|
||||||
|
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
|
||||||
|
dmScreenSettings.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT|DM_BITSPERPEL;
|
||||||
|
dmScreenSettings.dmPelsWidth = Width;
|
||||||
|
dmScreenSettings.dmPelsHeight = Height;
|
||||||
|
dmScreenSettings.dmBitsPerPel = 32;
|
||||||
|
|
||||||
|
if(ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL){
|
||||||
|
MessageBox(NULL, "Fullscreen mode is not supported by your setup. It has been turned off.", NULL,
|
||||||
|
MB_OK | MB_ICONERROR);
|
||||||
|
Fullscreen = 0;
|
||||||
|
}else{
|
||||||
|
hWnd = CreateWindowEx(WS_EX_APPWINDOW, "TSO_NIOTSO", "The Sims Online", WS_POPUP,
|
||||||
|
0, 0, Width, Height, 0, 0, hInst, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(hWnd == NULL){
|
||||||
|
Fullscreen = false;
|
||||||
|
RECT WindowRect = {0, 0, Width, Height};
|
||||||
|
|
||||||
|
//Use a style of WS_OVERLAPPEDWINDOW to allow resizing
|
||||||
|
AdjustWindowRectEx(&WindowRect, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE,
|
||||||
|
WS_EX_APPWINDOW); //This finds the dimensions of a window with a client area of our specified dimensions
|
||||||
|
|
||||||
|
//Note: Windows can be positioned anywhere, even outside the visible workspace,
|
||||||
|
//but their sizes are limited to the size of the workspace on the primary display.
|
||||||
|
unsigned WindowWidth = WindowRect.right-WindowRect.left, WindowHeight = WindowRect.bottom-WindowRect.top;
|
||||||
|
RECT WorkspaceRect;
|
||||||
|
SystemParametersInfo(SPI_GETWORKAREA, 0, &WorkspaceRect, 0);
|
||||||
|
|
||||||
|
hWnd = CreateWindowEx(WS_EX_APPWINDOW, "TSO_NIOTSO", "The Sims Online",
|
||||||
|
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
|
||||||
|
((WorkspaceRect.right-WorkspaceRect.left - WindowWidth)>>1) + WorkspaceRect.left,
|
||||||
|
((WorkspaceRect.bottom-WorkspaceRect.top - WindowHeight)>>1) + WorkspaceRect.top,
|
||||||
|
WindowWidth, WindowHeight, 0, 0, hInst, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hWnd == NULL){
|
||||||
|
MessageBox(NULL, "Failed to create the window.", NULL, MB_OK | MB_ICONERROR);
|
||||||
|
return ERROR_WINDOW_CREATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
Client/Window/Window.hpp
Normal file
25
Client/Window/Window.hpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
Niotso - Copyright (C) 2012 Fatbag <X-Fi6@phppoll.org>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Window {
|
||||||
|
int Initialize();
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
extern unsigned Width, Height;
|
||||||
|
extern bool Fullscreen;
|
||||||
|
extern HWND hWnd;
|
||||||
|
}
|
221
Libraries/FileHandler/Audio.cpp
Normal file
221
Libraries/FileHandler/Audio.cpp
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
/*
|
||||||
|
FileHandler - Copyright (c) 2012 Fatbag <X-Fi6@phppoll.org>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <setjmp.h> //Used by libpng
|
||||||
|
#include "bmp/read_bmp.h"
|
||||||
|
#include "libjpeg-turbo/jpeglib.h"
|
||||||
|
#include "libpng/png.h"
|
||||||
|
#define NOWINDOWS
|
||||||
|
#include "FileHandler.hpp"
|
||||||
|
|
||||||
|
namespace File {
|
||||||
|
|
||||||
|
enum SoundType {
|
||||||
|
FSND_WAV,
|
||||||
|
FSND_XA,
|
||||||
|
FSND_UTK,
|
||||||
|
FSND_MP3,
|
||||||
|
FSND_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t * ReadWAV(Image_t * Image, const uint8_t * InData, size_t FileSize);
|
||||||
|
static uint8_t * ReadXA(Image_t * Image, const uint8_t * InData, size_t FileSize);
|
||||||
|
static uint8_t * ReadUTK(Image_t * Image, const uint8_t * InData, size_t FileSize);
|
||||||
|
static uint8_t * ReadMP3(Image_t * Image, const uint8_t * InData, size_t FileSize);
|
||||||
|
|
||||||
|
static const uint8_t Signature[] = {
|
||||||
|
'R', //WAV
|
||||||
|
'X', //XA
|
||||||
|
'U', //UTK
|
||||||
|
0xFF //MP3
|
||||||
|
};
|
||||||
|
static uint8_t* (* const ImageFunction[])(Image_t*, const uint8_t*, size_t) = {
|
||||||
|
ReadWAV,
|
||||||
|
ReadXA,
|
||||||
|
ReadUTK,
|
||||||
|
ReadMP3
|
||||||
|
};
|
||||||
|
|
||||||
|
Image_t * ReadImageFile(const char * Filename){
|
||||||
|
uint8_t * InData = File::ReadFile(Filename);
|
||||||
|
if(InData == NULL) return NULL;
|
||||||
|
|
||||||
|
if(File::FileSize < 4){
|
||||||
|
free(InData);
|
||||||
|
File::Error = FERR_INVALIDDATA;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image_t * Image = (Image_t*) malloc(sizeof(Image_t));
|
||||||
|
if(Image == NULL){
|
||||||
|
free(InData);
|
||||||
|
File::Error = FERR_MEMORY;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t * OutData = NULL;
|
||||||
|
for(int i=0; i<FIMG_COUNT; i++){
|
||||||
|
if(InData[0] == Signature[i]){
|
||||||
|
OutData = ImageFunction[i](Image, InData, File::FileSize);
|
||||||
|
free(InData);
|
||||||
|
if(OutData == NULL){
|
||||||
|
File::Error = FERR_INVALIDDATA;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return Image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(InData);
|
||||||
|
File::Error = FERR_UNRECOGNIZED;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t * ReadBMP(Image_t * Image, const uint8_t * InData, size_t FileSize){
|
||||||
|
bmpheader_t BMPHeader;
|
||||||
|
if(!bmp_read_header(&BMPHeader, InData, FileSize)){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t * OutData = (uint8_t*) malloc(BMPHeader.DecompressedSize);
|
||||||
|
if(OutData == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(!bmp_read_data(&BMPHeader, InData, OutData)){
|
||||||
|
free(OutData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image->Width = BMPHeader.biWidth;
|
||||||
|
Image->Height = BMPHeader.biHeight;
|
||||||
|
Image->Format = FIMG_BGR24;
|
||||||
|
Image->Data = OutData;
|
||||||
|
return OutData;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t * ReadJPG(Image_t * Image, const uint8_t * InData, size_t FileSize){
|
||||||
|
//Initialize
|
||||||
|
jpeg_decompress_struct cinfo;
|
||||||
|
jpeg_error_mgr jerr;
|
||||||
|
cinfo.err = jpeg_std_error(&jerr);
|
||||||
|
jpeg_create_decompress(&cinfo);
|
||||||
|
jpeg_mem_src(&cinfo, (unsigned char*) InData, FileSize);
|
||||||
|
if(jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK){
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
cinfo.out_color_space = JCS_EXT_BGR;
|
||||||
|
if(!jpeg_start_decompress(&cinfo)){
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read
|
||||||
|
unsigned row_stride = cinfo.output_width * cinfo.output_components;
|
||||||
|
uint8_t * OutData = (uint8_t*) malloc(cinfo.output_width * cinfo.output_height * cinfo.output_components);
|
||||||
|
if(OutData == NULL){
|
||||||
|
jpeg_finish_decompress(&cinfo);
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for(unsigned i=cinfo.output_height; i; i--){
|
||||||
|
//According to the libjpeg documentation,
|
||||||
|
//jpeg_read_scanlines can only really read 1 scanline at a time.
|
||||||
|
//We need to convert to bottom-up format anyway.
|
||||||
|
uint8_t * Location = OutData + (i-1)*row_stride;
|
||||||
|
if(!jpeg_read_scanlines(&cinfo, &Location, 1)){
|
||||||
|
free(OutData);
|
||||||
|
jpeg_finish_decompress(&cinfo);
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Close up
|
||||||
|
jpeg_finish_decompress(&cinfo);
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
if(Image){
|
||||||
|
Image->Width = cinfo.output_width;
|
||||||
|
Image->Height = cinfo.output_height;
|
||||||
|
Image->Format = FIMG_BGR24;
|
||||||
|
Image->Data = OutData;
|
||||||
|
}
|
||||||
|
return OutData;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pngdata_t {
|
||||||
|
const uint8_t * buffer;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length){
|
||||||
|
pngdata_t *pngdata = (pngdata_t *) png_get_io_ptr(png_ptr);
|
||||||
|
if(length > pngdata->size) png_error(png_ptr, "");
|
||||||
|
memcpy(data, pngdata->buffer, length);
|
||||||
|
pngdata->buffer += length;
|
||||||
|
pngdata->size -= length;
|
||||||
|
}
|
||||||
|
static uint8_t * ReadPNG(Image_t * Image, const uint8_t * InData, size_t FileSize){
|
||||||
|
pngdata_t pngdata;
|
||||||
|
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
|
if(png_ptr == NULL) return 0;
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if(info_ptr == NULL){
|
||||||
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(setjmp(png_jmpbuf(png_ptr))){
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pngdata.buffer = InData;
|
||||||
|
pngdata.size = FileSize;
|
||||||
|
png_set_read_fn(png_ptr, &pngdata, user_read_data);
|
||||||
|
png_set_user_limits(png_ptr, 4096, 4096);
|
||||||
|
png_read_png(png_ptr, info_ptr,
|
||||||
|
PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_STRIP_ALPHA |
|
||||||
|
PNG_TRANSFORM_PACKING | PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_BGR, NULL);
|
||||||
|
|
||||||
|
//png_get_IHDR does not work in high-level mode.
|
||||||
|
unsigned width = png_get_image_width(png_ptr, info_ptr);
|
||||||
|
unsigned height = png_get_image_height(png_ptr, info_ptr);
|
||||||
|
uint8_t * OutData = (uint8_t *) malloc(width*height*3);
|
||||||
|
if(OutData == NULL){
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t **Scanlines = png_get_rows(png_ptr, info_ptr);
|
||||||
|
for(unsigned i=0; i<height; i++)
|
||||||
|
memcpy(OutData + i*width*3, Scanlines[height-i-1], width*3);
|
||||||
|
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
Image->Width = width;
|
||||||
|
Image->Height = height;
|
||||||
|
Image->Format = FIMG_BGR24;
|
||||||
|
Image->Data = OutData;
|
||||||
|
return OutData;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t * ReadTGA(Image_t * Image, const uint8_t * InData, size_t FileSize){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -51,6 +51,14 @@ struct Image_t {
|
||||||
uint8_t * Data;
|
uint8_t * Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Audio_t {
|
||||||
|
unsigned Channels;
|
||||||
|
unsigned SamplingRate;
|
||||||
|
unsigned BitDepth;
|
||||||
|
unsigned Duration;
|
||||||
|
uint8_t * Data;
|
||||||
|
};
|
||||||
|
|
||||||
namespace File {
|
namespace File {
|
||||||
|
|
||||||
extern int Error;
|
extern int Error;
|
||||||
|
@ -58,6 +66,7 @@ extern size_t FileSize;
|
||||||
|
|
||||||
uint8_t * ReadFile(const char * Filename);
|
uint8_t * ReadFile(const char * Filename);
|
||||||
Image_t * ReadImageFile(const char * Filename);
|
Image_t * ReadImageFile(const char * Filename);
|
||||||
|
Audio_t * ReadAudioFile(const char * Filename);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
0
Libraries/FileHandler/wav/read_wav.h
Normal file
0
Libraries/FileHandler/wav/read_wav.h
Normal file
Loading…
Add table
Reference in a new issue