diff --git a/CMakeLists.txt b/CMakeLists.txt index 222ad42..a78cb54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,8 +39,8 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) endif() # Size - set(CFLAGS_SIZE "${CFLAGS} -Os -g0 -fomit-frame-pointer -ffast-math -fmerge-all-constants -funsafe-loop-optimizations -fmerge-all-constants -fsched-pressure -flto") - set(LDFLAGS_SIZE "${LDFLAGS} -s -fwhole-program -flto") + set(CFLAGS_SIZE "${CFLAGS} -Os -g0 -fomit-frame-pointer -ffast-math -fmerge-all-constants -funsafe-loop-optimizations -fmerge-all-constants -fsched-pressure") + set(LDFLAGS_SIZE "${LDFLAGS} -s -fwhole-program") # Speed set(CFLAGS_SPEED "${CFLAGS} -O3 -g0 -fomit-frame-pointer -ffast-math -fmerge-all-constants -funsafe-loop-optimizations -fmerge-all-constants -fsched-pressure -fmodulo-sched -fmodulo-sched-allow-regmoves -fgcse-sm -fgcse-las -fsched-spec-load -fsched-spec-load-dangerous -fsched-stalled-insns=0 -fsched-stalled-insns-dep -fsched2-use-superblocks -fipa-pta -fipa-matrix-reorg -ftree-loop-linear -floop-interchange -floop-strip-mine -floop-block -fgraphite-identity -floop-parallelize-all -ftree-loop-distribution -ftree-loop-im -ftree-loop-ivcanon -fivopts -fvect-cost-model -fvariable-expansion-in-unroller -fbranch-target-load-optimize -maccumulate-outgoing-args -flto") @@ -64,7 +64,7 @@ endif() enable_language(ASM) set(CMAKE_ASM_COMPILER "gcc") -set(CMAKE_ASM_FLAGS "${CFLAGS}") +set(CMAKE_ASM_FLAGS "-fno-strict-aliasing ${CFLAGS}") if(WIN32) set(DIST_NAME "windows" CACHE STRING "Output folder name for the _dist folder (no start or end slash)") diff --git a/Client/CMakeLists.txt b/Client/CMakeLists.txt index 95a2f22..cb659ad 100644 --- a/Client/CMakeLists.txt +++ b/Client/CMakeLists.txt @@ -13,6 +13,7 @@ if(WIN32) Graphics/Startup.cpp Graphics/Viewport.cpp resources/Resource.rc + Scene/LoginScreen/LoginScreen.cpp System/System.cpp Window/Window.cpp ) diff --git a/Client/Scene/LoginScreen/LoginScreen.cpp b/Client/Scene/LoginScreen/LoginScreen.cpp new file mode 100644 index 0000000..e94f4d7 --- /dev/null +++ b/Client/Scene/LoginScreen/LoginScreen.cpp @@ -0,0 +1,223 @@ +/* + Niotso - Copyright (C) 2012 Fatbag + + 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 . +*/ + +#include "../../EngineInterface.hpp" + +static const wchar_t * const StatusStrings[] = { + L"Extruding Terrain Web", + L"Adjusting Emotional Weights", + L"Calibrating Personality Matrix", + + L"Calculating Domestic Coefficients", + L"Readjusting Career Ladder", + L"Accessing Money Supply", + L"Hacking the Social Network", + L"Tweaking Chaos Control", + L"Downloading Reticulated Splines" +}; +static const char * const images[] = {"eagames.bmp", "maxis.png", "setup.bmp"}; + +static const char * const sounds[] = {"loadloop.wav"}; + +LoginScreen::LoginScreen() : Scene(0){ + Screen = Screen_EAGames; + Time = 0; + ScrollPos = -1; + memset(image, 0, IMG_COUNT * sizeof(Image_t *)); + memset(texture, 0, TEX_COUNT * sizeof(GLuint)); + memset(sound, 0, SND_COUNT * sizeof(PlayableSound_t *)); + + glMatrixMode(GL_TEXTURE); + glGenTextures(TEX_COUNT, texture); + + FT_Set_Char_Size(Graphics::FontFace, 0, 22*64, 0, 0); + + for(int i=TEX_EAGAMES; i<=TEX_SETUP; i++){ + Image_t * Image = File::ReadImageFile(images[i]); + if(!Image){ + const char * Message; + switch(File::Error){ + case FERR_NOT_FOUND: + Message = "%s does not exist."; + break; + case FERR_OPEN: + Message = "%s could not be opened for reading."; + break; + case FERR_BLANK: + case FERR_UNRECOGNIZED: + case FERR_INVALIDDATA: + Message = "%s is corrupt or invalid."; + break; + case FERR_MEMORY: + Message = "Memory for %s could not be allocated."; + break; + default: + Message = "%s could not be read."; + } + + char Buffer[1024]; + sprintf(Buffer, Message, images[i]); + MessageBox(Window::hWnd, Buffer, NULL, MB_OK | MB_ICONERROR); + EXIT_SCENE(); + } + + if(i == TEX_MAXIS){ + Graphics::DrawText(Image, L"Maxis\x2122 is an Electronic Arts\x2122 brand.", 0, 600-146, 800, 146, + Graphics::ALIGN_CENTER_CENTER, 0, RGB(0xef, 0xe3, 0x8c)); + } + + glBindTexture(GL_TEXTURE_2D, texture[i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Image->Width, Image->Height, 0, GL_BGR, GL_UNSIGNED_BYTE, Image->Data); + free(Image->Data); + free(Image); + } + + image[IMG_COPYRIGHT] = Graphics::StringImage(L"(c) 2002, 2003 Electronic Arts Inc. All rights reserved.", + 0, RGB(0xef, 0xe3, 0x8c)); + if(image[IMG_COPYRIGHT] == NULL){ + EXIT_SCENE(); + } + glBindTexture(GL_TEXTURE_2D, texture[TEX_COPYRIGHT]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image[IMG_COPYRIGHT]->Width, image[IMG_COPYRIGHT]->Height, 0, GL_BGRA, + GL_UNSIGNED_BYTE, image[IMG_COPYRIGHT]->Data); + free(image[IMG_COPYRIGHT]->Data); + + for(int i=0; i<9; i++){ + image[IMG_STATUS+i] = Graphics::StringImage(StatusStrings[i], 0, RGB(0xef, 0xe3, 0x8c)); + if(image[IMG_STATUS+i] == NULL){ + EXIT_SCENE(); + } + glBindTexture(GL_TEXTURE_2D, texture[TEX_STATUS+i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image[IMG_STATUS+i]->Width, image[IMG_STATUS+i]->Height, 0, GL_BGRA, + GL_UNSIGNED_BYTE, image[IMG_STATUS+i]->Data); + free(image[IMG_STATUS+i]->Data); + } + + for(int i=0; iData); + free(sound[i]); + } + } +} + +int LoginScreen::Run(float TimeDelta){ + Time += TimeDelta; + if(ScrollPos != 8){ + ScrollPos += TimeDelta*0.75; + if(ScrollPos > 8) ScrollPos = 8; + } + + if(Screen != Screen_Setup && Time >= 4.0){ + Screen = (Screen==Screen_EAGames) ? Screen_Maxis : Screen_Setup; + Time = 0; + } + + if(System::UserInput.CloseWindow){ + return SCENE_EXIT; + } + return SCENE_NEED_REDRAW; +} + +void LoginScreen::Render(){ + glMatrixMode(GL_TEXTURE); + + //Background + glBindTexture(GL_TEXTURE_2D, texture[Screen]); + glBegin(GL_QUADS); + glTexCoord2i(0,0); glVertex2i(0,0); + glTexCoord2i(1,0); glVertex2i(800,0); + glTexCoord2i(1,1); glVertex2i(800,600); + glTexCoord2i(0,1); glVertex2i(0,600); + glEnd(); + + if(Screen != Screen_Setup) return; + + glBindTexture(GL_TEXTURE_2D, texture[TEX_COPYRIGHT]); + glBegin(GL_QUADS); + glTexCoord2i(0,0); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2,58); + glTexCoord2i(1,0); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2 + image[IMG_COPYRIGHT]->Width,58); + glTexCoord2i(1,1); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2 + image[IMG_COPYRIGHT]->Width,image[IMG_COPYRIGHT]->Height + 58); + glTexCoord2i(0,1); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2,image[IMG_COPYRIGHT]->Height + 58); + glEnd(); + + for(int i=0; i<9; i++){ + glBindTexture(GL_TEXTURE_2D, texture[TEX_STATUS+i]); + glBegin(GL_QUADS); + glTexCoord2i(0,0); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2,20); + glTexCoord2i(1,0); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2 + image[IMG_STATUS+i]->Width,20); + glTexCoord2i(1,1); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2 + image[IMG_STATUS+i]->Width,image[IMG_STATUS+i]->Height + 20); + glTexCoord2i(0,1); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2,image[IMG_STATUS+i]->Height + 20); + glEnd(); + } +} \ No newline at end of file diff --git a/Client/Scene/LoginScreen/LoginScreen.hpp b/Client/Scene/LoginScreen/LoginScreen.hpp new file mode 100644 index 0000000..1ab2501 --- /dev/null +++ b/Client/Scene/LoginScreen/LoginScreen.hpp @@ -0,0 +1,53 @@ +/* + Niotso - Copyright (C) 2012 Fatbag + + 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 . +*/ + +class LoginScreen : public Scene { + enum { + IMG_COPYRIGHT, + IMG_STATUS, //value = 1..9 + IMG_COUNT = 10 + }; + + enum { + TEX_EAGAMES, + TEX_MAXIS, + TEX_SETUP, + TEX_COPYRIGHT, + TEX_STATUS, //value = 4..12 + TEX_COUNT = 13 + }; + + enum { + SND_LOADLOOP, + SND_COUNT + }; + + enum { Screen_EAGames, Screen_Maxis, Screen_Setup } Screen; + float Time; + float ScrollPos; + Image_t * image[IMG_COUNT]; + GLuint texture[TEX_COUNT]; + PlayableSound_t * sound[SND_COUNT]; + + public: + LoginScreen(); + ~LoginScreen(); + void Render(); + + private: + int Run(float TimeDelta); +}; \ No newline at end of file diff --git a/Client/Scene/Scene.hpp b/Client/Scene/Scene.hpp index e39f8ea..7b37b61 100644 --- a/Client/Scene/Scene.hpp +++ b/Client/Scene/Scene.hpp @@ -15,8 +15,6 @@ along with this program. If not, see . */ -#include - #define EXIT_SCENE() do { System::SceneFailed = true; delete this; return; } while(0) #define SCENE_EXIT 0 #define SCENE_NEED_REDRAW 1 @@ -53,237 +51,8 @@ class Scene { virtual ~Scene() {}; }; -static const wchar_t * const StatusStrings[] = { - L"Extruding Terrain Web", - L"Adjusting Emotional Weights", - L"Calibrating Personality Matrix", +/**** +** Scenes +*/ - L"Calculating Domestic Coefficients", - L"Readjusting Career Ladder", - L"Accessing Money Supply", - L"Hacking the Social Network", - L"Tweaking Chaos Control", - L"Downloading Reticulated Splines" -}; - -enum { - IMG_COPYRIGHT, - IMG_STATUS, //value = 1..9 - IMG_COUNT = 10 -}; - -enum { - TEX_EAGAMES, - TEX_MAXIS, - TEX_SETUP, - TEX_COPYRIGHT, - TEX_STATUS, //value = 4..12 - TEX_COUNT = 13 -}; -static const char * const images[] = {"eagames.bmp", "maxis.png", "setup.bmp"}; - -enum { - SND_LOADLOOP, - SND_COUNT -}; -static const char * const sounds[] = {"loadloop.wav"}; - -class LoginScreen : public Scene { - enum { Screen_EAGames, Screen_Maxis, Screen_Setup } Screen; - float Time; - float ScrollPos; - Image_t * image[IMG_COUNT]; - GLuint texture[TEX_COUNT]; - PlayableSound_t * sound[SND_COUNT]; - - public: - LoginScreen() : Scene(0){ - Screen = Screen_EAGames; - Time = 0; - ScrollPos = -1; - memset(image, 0, IMG_COUNT * sizeof(Image_t *)); - memset(texture, 0, TEX_COUNT * sizeof(GLuint)); - memset(sound, 0, SND_COUNT * sizeof(PlayableSound_t *)); - - glMatrixMode(GL_TEXTURE); - glGenTextures(TEX_COUNT, texture); - - for(int i=TEX_EAGAMES; i<=TEX_SETUP; i++){ - Image_t * Image = File::ReadImageFile(images[i]); - if(!Image){ - const char * Message; - switch(File::Error){ - case FERR_NOT_FOUND: - Message = "%s does not exist."; - break; - case FERR_OPEN: - Message = "%s could not be opened for reading."; - break; - case FERR_BLANK: - case FERR_UNRECOGNIZED: - case FERR_INVALIDDATA: - Message = "%s is corrupt or invalid."; - break; - case FERR_MEMORY: - Message = "Memory for %s could not be allocated."; - break; - default: - Message = "%s could not be read."; - } - - char Buffer[1024]; - sprintf(Buffer, Message, images[i]); - MessageBox(Window::hWnd, Buffer, NULL, MB_OK | MB_ICONERROR); - EXIT_SCENE(); - } - - if(i == TEX_MAXIS){ - FT_Set_Char_Size(Graphics::FontFace, 0, 22*64, 0, 0); - Graphics::DrawText(Image, L"Maxis\x2122 is an Electronic Arts\x2122 brand.", 0, 600-146, 800, 146, - Graphics::ALIGN_CENTER_CENTER, 0, RGB(0xef, 0xe3, 0x8c)); - } - - glBindTexture(GL_TEXTURE_2D, texture[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Image->Width, Image->Height, 0, GL_BGR, GL_UNSIGNED_BYTE, Image->Data); - free(Image->Data); - free(Image); - } - - image[IMG_COPYRIGHT] = Graphics::StringImage(L"(c) 2002, 2003 Electronic Arts Inc. All rights reserved.", - 0, RGB(0xef, 0xe3, 0x8c)); - if(image[IMG_COPYRIGHT] == NULL){ - EXIT_SCENE(); - } - glBindTexture(GL_TEXTURE_2D, texture[TEX_COPYRIGHT]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image[IMG_COPYRIGHT]->Width, image[IMG_COPYRIGHT]->Height, 0, GL_BGRA, - GL_UNSIGNED_BYTE, image[IMG_COPYRIGHT]->Data); - free(image[IMG_COPYRIGHT]->Data); - - for(int i=0; i<9; i++){ - image[IMG_STATUS+i] = Graphics::StringImage(StatusStrings[i], 0, RGB(0xef, 0xe3, 0x8c)); - if(image[IMG_STATUS+i] == NULL){ - EXIT_SCENE(); - } - glBindTexture(GL_TEXTURE_2D, texture[TEX_STATUS+i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image[IMG_STATUS+i]->Width, image[IMG_STATUS+i]->Height, 0, GL_BGRA, - GL_UNSIGNED_BYTE, image[IMG_STATUS+i]->Data); - free(image[IMG_STATUS+i]->Data); - } - - for(int i=0; iData); - free(sound[i]); - } - } - } - - private: - int Run(float TimeDelta){ - Time += TimeDelta; - if(ScrollPos != 8){ - ScrollPos += TimeDelta*0.75; - if(ScrollPos > 8) ScrollPos = 8; - } - - if(Screen != Screen_Setup && Time >= 4.0){ - Screen = (Screen==Screen_EAGames) ? Screen_Maxis : Screen_Setup; - Time = 0; - } - - if(System::UserInput.CloseWindow){ - return SCENE_EXIT; - } - return SCENE_NEED_REDRAW; - } - - public: - void Render(){ - glMatrixMode(GL_TEXTURE); - - //Background - glBindTexture(GL_TEXTURE_2D, texture[Screen]); - glBegin(GL_QUADS); - glTexCoord2i(0,0); glVertex2i(0,0); - glTexCoord2i(1,0); glVertex2i(800,0); - glTexCoord2i(1,1); glVertex2i(800,600); - glTexCoord2i(0,1); glVertex2i(0,600); - glEnd(); - - if(Screen != Screen_Setup) return; - - glBindTexture(GL_TEXTURE_2D, texture[TEX_COPYRIGHT]); - glBegin(GL_QUADS); - glTexCoord2i(0,0); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2,58); - glTexCoord2i(1,0); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2 + image[IMG_COPYRIGHT]->Width,58); - glTexCoord2i(1,1); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2 + image[IMG_COPYRIGHT]->Width,image[IMG_COPYRIGHT]->Height + 58); - glTexCoord2i(0,1); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2,image[IMG_COPYRIGHT]->Height + 58); - glEnd(); - - for(int i=0; i<9; i++){ - glBindTexture(GL_TEXTURE_2D, texture[TEX_STATUS+i]); - glBegin(GL_QUADS); - glTexCoord2i(0,0); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2,20); - glTexCoord2i(1,0); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2 + image[IMG_STATUS+i]->Width,20); - glTexCoord2i(1,1); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2 + image[IMG_STATUS+i]->Width,image[IMG_STATUS+i]->Height + 20); - glTexCoord2i(0,1); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2,image[IMG_STATUS+i]->Height + 20); - glEnd(); - } - } -}; \ No newline at end of file +#include "LoginScreen/LoginScreen.hpp" \ No newline at end of file diff --git a/Libraries/FileHandler/Audio.cpp b/Libraries/FileHandler/Audio.cpp index 8292b68..b036e54 100644 --- a/Libraries/FileHandler/Audio.cpp +++ b/Libraries/FileHandler/Audio.cpp @@ -17,7 +17,10 @@ #include #include #include +#include "libmpg123/mpg123.h" +#include "utk/read_utk.h" #include "wav/read_wav.h" +#include "xa/read_xa.h" #include "FileHandler.hpp" namespace File { @@ -103,8 +106,105 @@ static uint8_t * ReadWAV(Sound_t * Sound, const uint8_t * InData, size_t FileSiz } -static uint8_t * ReadXA(Sound_t * Sound, const uint8_t * InData, size_t FileSize){}; -static uint8_t * ReadUTK(Sound_t * Sound, const uint8_t * InData, size_t FileSize){}; -static uint8_t * ReadMP3(Sound_t * Sound, const uint8_t * InData, size_t FileSize){}; +static uint8_t * ReadXA(Sound_t * Sound, const uint8_t * InData, size_t FileSize){ + xaheader_t XAHeader; + if(!xa_read_header(&XAHeader, InData, FileSize)){ + return NULL; + } + + uint8_t * OutData = (uint8_t*) malloc(XAHeader.dwOutSize); + if(OutData == NULL){ + return NULL; + } + if(!xa_decode(InData+24, OutData, XAHeader.Frames, XAHeader.nChannels)){ + free(OutData); + return NULL; + } + + Sound->Channels = XAHeader.nChannels; + Sound->SamplingRate = XAHeader.nSamplesPerSec; + Sound->BitDepth = XAHeader.wBitsPerSample; + Sound->Duration = XAHeader.dwOutSize / XAHeader.nBlockAlign; + Sound->Data = OutData; + return OutData; +} + +static uint8_t * ReadUTK(Sound_t * Sound, const uint8_t * InData, size_t FileSize){ + utkheader_t UTKHeader; + if(!utk_read_header(&UTKHeader, InData, FileSize)){ + return NULL; + } + + uint8_t * OutData = (uint8_t*) malloc(UTKHeader.dwOutSize); + if(OutData == NULL){ + return NULL; + } + + static bool generated = false; + if(!generated){ + UTKGenerateTables(); + generated = true; + } + + if(!utk_decode(InData+32, OutData, UTKHeader.Frames)){ + free(OutData); + return NULL; + } + + Sound->Channels = 1; + Sound->SamplingRate = UTKHeader.nSamplesPerSec; + Sound->BitDepth = UTKHeader.wBitsPerSample; + Sound->Duration = UTKHeader.dwOutSize / UTKHeader.nBlockAlign; + Sound->Data = OutData; + return OutData; +} + +static uint8_t * ReadMP3(Sound_t * Sound, const uint8_t * InData, size_t FileSize){ + if(mpg123_init() != MPG123_OK){ + mpg123_exit(); + return NULL; + } + + long rate; + int channels, encoding; + unsigned samples; + size_t OutSize; + uint8_t * OutData; + + mpg123_handle *mh = mpg123_new(NULL, NULL); + if(mh == NULL || + mpg123_format_none(mh) != MPG123_OK || + mpg123_format(mh, 44100, MPG123_MONO | MPG123_STEREO, MPG123_ENC_SIGNED_16) != MPG123_OK || + mpg123_open_feed(mh) != MPG123_OK || + mpg123_feed(mh, InData, FileSize) != MPG123_OK || + mpg123_set_filesize(mh, FileSize) != MPG123_OK || + mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK || + (samples = mpg123_length(mh)) == 0 || + (OutData = (uint8_t*) malloc(OutSize = samples * channels * 2)) == NULL + ){ + mpg123_close(mh); + mpg123_delete(mh); + mpg123_exit(); + return NULL; + } + + size_t decoded; + mpg123_read(mh, OutData, OutSize, &decoded); + mpg123_close(mh); + mpg123_delete(mh); + mpg123_exit(); + + if(decoded != OutSize){ + free(OutData); + return NULL; + } + + Sound->Channels = channels; + Sound->SamplingRate = rate; + Sound->BitDepth = 16; + Sound->Duration = samples; + Sound->Data = OutData; + return OutData; +} } \ No newline at end of file diff --git a/Libraries/FileHandler/CMakeLists.txt b/Libraries/FileHandler/CMakeLists.txt index 10dd735..bf0bf2f 100644 --- a/Libraries/FileHandler/CMakeLists.txt +++ b/Libraries/FileHandler/CMakeLists.txt @@ -23,7 +23,9 @@ set(FILEHANDLER_SOURCES cst/cst.c iff/chunks.c iff/iff.c + utk/read_utk.c wav/read_wav.c + xa/read_xa.c ) include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler) @@ -42,4 +44,4 @@ set_target_properties(FileHandler_shared PROPERTIES PREFIX "" IMPORT_PREFIX "" CLEAN_DIRECT_OUTPUT 1) -target_link_libraries(FileHandler_shared kernel32 jpegturbo_static libpng_static zlib_static) \ No newline at end of file +target_link_libraries(FileHandler_shared kernel32 jpegturbo_static libmpg123_static libpng_static zlib_static) \ No newline at end of file diff --git a/Libraries/FileHandler/iff/chunks.c b/Libraries/FileHandler/iff/chunks.c index 39b93fb..0d2f6e8 100644 --- a/Libraries/FileHandler/iff/chunks.c +++ b/Libraries/FileHandler/iff/chunks.c @@ -19,23 +19,37 @@ #include #include "iff.h" -int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer){ - if( !strcmp(ChunkInfo->Type, "STR#") || - !strcmp(ChunkInfo->Type, "CTSS") || - !strcmp(ChunkInfo->Type, "FAMs") || - !strcmp(ChunkInfo->Type, "TTAs") ) - return iff_parse_str(ChunkInfo, Buffer); - if( !strcmp(ChunkInfo->Type, "BCON") ) - return iff_parse_bcon(ChunkInfo, Buffer); +/* All chunk-parsing functions */ +static int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize); +static int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer); +static int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer); +static int iff_parse_trcn(IFFChunk * ChunkInfo, const uint8_t * Buffer); +int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer){ + unsigned i; + const char chunktypes[] = + "STR#" "CTSS" "FAMs" "TTAs" + "BCON" + "TRCN" + ; + int (* const iff_parse_function[])(IFFChunk*, const uint8_t*) = { + iff_parse_str, iff_parse_str, iff_parse_str, iff_parse_str, + iff_parse_bcon, + iff_parse_trcn + }; + + for(i=0; chunktypes[i*4] != '\0'; i++){ + if(!memcmp(ChunkInfo->Type, chunktypes+i*4, 4)) + return iff_parse_function[i](ChunkInfo, Buffer); + } return 0; } -int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize){ +static int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize){ return 1; } -int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer){ +static int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFF_BCON *BCONData; unsigned Size = ChunkInfo->Size - 76; unsigned i; @@ -51,14 +65,14 @@ int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer){ BCONData->Flags = read_uint8le(Buffer + 1); if(BCONData->ConstantCount == 0) return 1; - if(BCONData->ConstantCount * 2 > 255*2){ - free(ChunkInfo->FormattedData); + if(BCONData->ConstantCount * 2 > Size - 2){ + free(BCONData); return 0; } BCONData->Constants = malloc(BCONData->ConstantCount * sizeof(uint16_t)); if(BCONData->Constants == NULL){ - free(ChunkInfo->FormattedData); + free(BCONData); return 0; } @@ -68,7 +82,7 @@ int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer){ return 1; } -int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){ +static int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){ /* No bounds checking yet */ IFF_STR * StringData; unsigned Size = ChunkInfo->Size - 76; @@ -78,8 +92,9 @@ int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){ ChunkInfo->FormattedData = malloc(sizeof(IFF_STR)); if(ChunkInfo->FormattedData == NULL) return 0; - memset(ChunkInfo->FormattedData, 0, sizeof(IFF_STR)); + StringData = (IFF_STR*) ChunkInfo->FormattedData; + memset(StringData, 0, sizeof(IFF_STR)); StringData->Format = read_int16le(Buffer); Buffer += 2; if(Size-2 < 2) /* TSO allows this; as seen in the animations chunk in personglobals.iff */ @@ -298,4 +313,39 @@ int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){ free(ChunkInfo->FormattedData); return 0; +} + +static int iff_parse_trcn(IFFChunk * ChunkInfo, const uint8_t * Buffer){ + IFF_TRCN * TRCNData; + unsigned Size = ChunkInfo->Size - 76; + unsigned i; + + if(Size < 16) + return 0; + ChunkInfo->FormattedData = malloc(sizeof(IFF_TRCN)); + if(ChunkInfo->FormattedData == NULL) + return 0; + + TRCNData = (IFF_TRCN*) ChunkInfo->FormattedData; + TRCNData->Reserved = read_uint32le(Buffer+0); + TRCNData->Version = read_uint32le(Buffer+4); + memcpy(TRCNData->MagicNumber, Buffer+8, 4); + TRCNData->MagicNumber[4] = 0x00; + TRCNData->EntryCount = read_uint32le(Buffer+12); + + if(TRCNData->Reserved != 0 || TRCNData->Version > 2 || strcmp(TRCNData->MagicNumber, "NCRT")){ + free(TRCNData); + return 0; + } + ChunkInfo->FormattedData = malloc(TRCNData->EntryCount * sizeof(IFFRangePair)); + if(ChunkInfo->FormattedData == NULL){ + free(TRCNData); + return 0; + } + + Buffer += 16; + for(i=0; iEntryCount; i++){/* + IsUnused = read_uint32le(Buffer+0); + Unknown = read_uint32le(Buffer+4);*/ + } } \ No newline at end of file diff --git a/Libraries/FileHandler/iff/iff.h b/Libraries/FileHandler/iff/iff.h index 6698600..4b99294 100644 --- a/Libraries/FileHandler/iff/iff.h +++ b/Libraries/FileHandler/iff/iff.h @@ -133,6 +133,28 @@ typedef struct IFF_STR_struct IFFLanguageSet LanguageSets[20]; } IFF_STR; +/* TRCN chunk */ + +typedef struct IFFRangePair_struct +{ + uint32_t IsUnused; + uint32_t Unknown; + char * Key; + char * Value; + uint8_t Enforced; + uint16_t RangeMin; + uint16_t RangeMax; +} IFFRangePair; + +typedef struct IFF_TRCN_struct +{ + uint32_t Reserved; + uint32_t Version; + char MagicNumber[5]; + uint32_t EntryCount; + IFFRangePair * Entries; +} IFF_TRCN; + #ifdef __cplusplus extern "C" { #endif @@ -157,9 +179,6 @@ void iff_delete(IFFFile * IFFFileInfo); */ int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer); -int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize); -int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer); -int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer); #ifdef __cplusplus } diff --git a/Libraries/FileHandler/utk/read_utk.c b/Libraries/FileHandler/utk/read_utk.c index 97ce876..f3aa953 100644 --- a/Libraries/FileHandler/utk/read_utk.c +++ b/Libraries/FileHandler/utk/read_utk.c @@ -33,7 +33,7 @@ #define round(x) ((x) >= 0 ? (x)+0.5 : (x)-0.5) #endif #ifndef min - #define min(x, y) ((x) > (y) ? (x) : (y)) + #define min(x, y) ((x) < (y) ? (x) : (y)) #endif #ifndef __inline @@ -57,7 +57,7 @@ float UTKTable4[29]; int utk_read_header(utkheader_t * UTKHeader, const uint8_t * Buffer, size_t FileSize) { - if(FileSize < 28) return 0; + if(FileSize < 32) return 0; memcpy(&UTKHeader->sID, Buffer, 4); UTKHeader->dwOutSize = read_uint32(Buffer+4); UTKHeader->dwWfxSize = read_uint32(Buffer+8); diff --git a/Tools/iff2html/iff2html.c b/Tools/iff2html/iff2html.c index 045aa08..84f01c3 100644 --- a/Tools/iff2html/iff2html.c +++ b/Tools/iff2html/iff2html.c @@ -28,7 +28,7 @@ #endif void printsize(FILE * hFile, size_t FileSize){ - /* For our purposes, our units are best described in kB and MB */ + /* For our purposes, our units are best described in kB and MB, if not bytes */ size_t temp = FileSize; unsigned position = 1; if(FileSize >= 1048576) @@ -357,7 +357,6 @@ int main(int argc, char *argv[]){ IFF_BCON * BCONData = (IFF_BCON*) ChunkNode->Chunk.FormattedData; fprintf(hFile, "\n"); fprintf(hFile, "\n", BCONData->Flags, BCONData->Flags); - fprintf(hFile, "\n", BCONData->ConstantCount); fprintf(hFile, "
Flags:%02X (%d)
Number of Constants:%u
\n"); if(BCONData->ConstantCount > 0){ unsigned ConstantIndex;