From 275791139922a6c67627ee2004a5cb4a651baaa7 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 7 Jun 2013 04:10:31 +1000 Subject: [PATCH] Libraries are building correctly --- .gitignore | 18 + README.md | 29 ++ libs/Codebase/button.cpp | 103 +++++ libs/Codebase/button.hpp | 80 ++++ libs/Codebase/config_utility.cpp | 76 ++++ libs/Codebase/config_utility.hpp | 68 ++++ libs/Codebase/frame_rate.cpp | 26 ++ libs/Codebase/frame_rate.hpp | 48 +++ libs/Codebase/image.cpp | 54 +++ libs/Codebase/image.hpp | 58 +++ libs/Codebase/makefile | 37 ++ libs/Codebase/raster_font.cpp | 49 +++ libs/Codebase/raster_font.hpp | 46 +++ libs/Codebase/sprite_sheet.cpp | 44 +++ libs/Codebase/sprite_sheet.hpp | 66 ++++ libs/Codebase/surface_manager.cpp | 85 +++++ libs/Codebase/surface_manager.hpp | 49 +++ libs/Codebase/udp_network_utility.cpp | 148 ++++++++ libs/Codebase/udp_network_utility.hpp | 79 ++++ libs/Codebase/vector2.hpp | 77 ++++ libs/SDL_net/SDL_net.h | 452 ++++++++++++++++++++++ libs/SDL_net/SDLnet.c | 269 +++++++++++++ libs/SDL_net/SDLnetTCP.c | 295 ++++++++++++++ libs/SDL_net/SDLnetUDP.c | 528 ++++++++++++++++++++++++++ libs/SDL_net/SDLnetselect.c | 163 ++++++++ libs/SDL_net/SDLnetsys.h | 94 +++++ libs/SDL_net/makefile | 37 ++ libs/makefile | 13 + makefile | 7 + 29 files changed, 3098 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 libs/Codebase/button.cpp create mode 100644 libs/Codebase/button.hpp create mode 100644 libs/Codebase/config_utility.cpp create mode 100644 libs/Codebase/config_utility.hpp create mode 100644 libs/Codebase/frame_rate.cpp create mode 100644 libs/Codebase/frame_rate.hpp create mode 100644 libs/Codebase/image.cpp create mode 100644 libs/Codebase/image.hpp create mode 100644 libs/Codebase/makefile create mode 100644 libs/Codebase/raster_font.cpp create mode 100644 libs/Codebase/raster_font.hpp create mode 100644 libs/Codebase/sprite_sheet.cpp create mode 100644 libs/Codebase/sprite_sheet.hpp create mode 100644 libs/Codebase/surface_manager.cpp create mode 100644 libs/Codebase/surface_manager.hpp create mode 100644 libs/Codebase/udp_network_utility.cpp create mode 100644 libs/Codebase/udp_network_utility.hpp create mode 100644 libs/Codebase/vector2.hpp create mode 100644 libs/SDL_net/SDL_net.h create mode 100644 libs/SDL_net/SDLnet.c create mode 100644 libs/SDL_net/SDLnetTCP.c create mode 100644 libs/SDL_net/SDLnetUDP.c create mode 100644 libs/SDL_net/SDLnetselect.c create mode 100644 libs/SDL_net/SDLnetsys.h create mode 100644 libs/SDL_net/makefile create mode 100644 libs/makefile create mode 100644 makefile diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24cc19a --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +#Editor generated files +#*.sln +#*.vcproj +*.suo +*.ncb +*.user + +#Directories +Release/ +Debug/ +Out/ + +#Project generated files +*.db + +#Shell files +*.bat +*.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..e001b5f --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +Tortuga is a 3/4 top down multiplayer RPG set in a large archipelago occupied by warring pirate clans. The emphasis of this game is on multiplayer competition, exploration in an open world, and solo adventuring. The game runs on a Minecraft like server system with a goal of about 50-100 players on a single server. The player characters are tied to the server where they are created, and are susceptible to permadeath: deletion of a character upon death. The servers are designed to allow a large amount of modification by the hosts. + +## Libraries + +* [SDL](http://www.libsdl.org/) - Simple DirectMedia Layer API +* [SDL_net](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension, modified; libs/SDL_net +* [Codebase](https://github.com/Ratstail91/Codebase) - generic reusable code modules; libs/Codebase + +## Instructions + +* This project uses C++11, which is available via GNU (or MinGW) 4.7, or Visual Studio 2012. Personally, I'm using MinGW 4.7.2. +* I'm trying to keep this as IDE agnostic as possible, so if you use an IDE, please add it's files to .gitignore. +* You can read more details on the GitHub wiki [here](https://github.com/Ratstail91/Tortuga/wiki). + +## Copyright + +Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License). + +Copyright (c) 2013 Kayne Ruse + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. diff --git a/libs/Codebase/button.cpp b/libs/Codebase/button.cpp new file mode 100644 index 0000000..f9f066c --- /dev/null +++ b/libs/Codebase/button.cpp @@ -0,0 +1,103 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "button.hpp" + +#include + +Button::Button(): + Button(0,0, nullptr, nullptr) +{ +} + +Button::Button(Sint16 i, Sint16 j, SDL_Surface* imageSurface, SDL_Surface* fontSurface, std::string s) { + x = i; + y = j; + state = State::NORMAL; + + SetSurfaces(imageSurface, fontSurface); + + SetText(s); +} + +Button::State Button::MouseMotion(SDL_MouseMotionEvent const& motion) { + if (motion.state & SDL_BUTTON_LMASK) { + return CalcState(motion.x, motion.y, true); + } + else { + return CalcState(motion.x, motion.y, false); + } + return state; +} + +Button::State Button::MouseButtonDown(SDL_MouseButtonEvent const& button) { + if (button.button == SDL_BUTTON_LEFT) { + return CalcState(button.x, button.y, true); + } + return state; +} + +Button::State Button::MouseButtonUp(SDL_MouseButtonEvent const& button) { + if (button.button == SDL_BUTTON_LEFT) { + return CalcState(button.x, button.y, false); + } + return state; +} + +void Button::DrawTo(SDL_Surface* const dest) { + image.DrawTo(dest, x, y); + font.DrawStringTo(text, dest, textX + x, textY + y); +} + +void Button::SetSurfaces(SDL_Surface* imageSurface, SDL_Surface* fontSurface) { + //graphical stuff + image.SetSurface(imageSurface); + image.SetClipH(image.GetClipH() / 3); //3 phases + font.SetSurface(fontSurface); + + //reset textX & textY + SetText(text); +} + +std::string Button::SetText(std::string s) { + //one line + text = s; + textX = (image.GetClipW() / 2) - (font.GetCharW() * text.size() / 2); + textY = (image.GetClipH() / 2) - (font.GetCharH() / 2); + return text; +} + +Button::State Button::CalcState(Sint16 i, Sint16 j, bool leftPressed) { + if (i < x || i > (x + image.GetClipW()) || + j < y || j > (y + image.GetClipH()) + ) { + image.SetClipY(0); + return state = State::NORMAL; + } + if (leftPressed) { + image.SetClipY(image.GetClipH()*2); + return state = State::PRESSED; + } + else { + image.SetClipY(image.GetClipH()); + return state = State::HOVER; + } +} diff --git a/libs/Codebase/button.hpp b/libs/Codebase/button.hpp new file mode 100644 index 0000000..14d47cd --- /dev/null +++ b/libs/Codebase/button.hpp @@ -0,0 +1,80 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef BUTTON_HPP_ +#define BUTTON_HPP_ + +#include "image.hpp" +#include "raster_font.hpp" + +#include + +//3-phases, no toggle, centred text +class Button { +public: + enum class State { + NORMAL, HOVER, PRESSED + }; + + Button(); + Button(Sint16 x, Sint16 y, SDL_Surface* imageSurface, SDL_Surface* fontSurface, std::string text = ""); + + //return the current state + State MouseMotion(SDL_MouseMotionEvent const&); + State MouseButtonDown(SDL_MouseButtonEvent const&); + State MouseButtonUp(SDL_MouseButtonEvent const&); + State GetState() const { + return state; + } + + //yet another draw function + void DrawTo(SDL_Surface* const); + + //simple accessors and mutators + Sint16 SetX(Sint16 i) { return x = i; } + Sint16 SetY(Sint16 i) { return y = i; } + Sint16 GetX() const { return x; } + Sint16 GetY() const { return y; } + + void SetSurfaces(SDL_Surface* image, SDL_Surface* font); + + std::string SetText(std::string s); + std::string GetText() const { return text; } + + //raw access, be careful + Image* GetImage() { return ℑ } + RasterFont* GetFont() { return &font; } + + //debug + Sint16 GetTextX() const { return textX; } + Sint16 GetTextY() const { return textY; } +private: + State CalcState(Sint16 x, Sint16 y, bool leftPressed); + + Sint16 x, y; + Sint16 textX, textY; //prevent recalc every loop + Image image; + RasterFont font; + State state; + std::string text; +}; + +#endif diff --git a/libs/Codebase/config_utility.cpp b/libs/Codebase/config_utility.cpp new file mode 100644 index 0000000..d6cc812 --- /dev/null +++ b/libs/Codebase/config_utility.cpp @@ -0,0 +1,76 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "config_utility.hpp" + +#include +#include + +using namespace std; + +void ConfigUtility::Load(string fname) { + ifstream is(fname); + + if (!is.is_open()) { + throw(runtime_error("Failed to open config file")); + } + + string key, val; + + for (;;) { //forever + //eat whitespace + while(isspace(is.peek())) + is.ignore(); + + //end of file + if (is.eof()) + break; + + //skip comment lines + if (is.peek() == '#') { + while(is.peek() != '\n' && !is.eof()) { + is.ignore(); + } + continue; + } + + //read in the pair + getline(is, key,'='); + getline(is, val); + + //trim the strings at the start & end + while(key.size() && isspace(*key.begin())) key.erase(0, 1); + while(val.size() && isspace(*val.begin())) val.erase(0, 1); + + while(key.size() && isspace(*(key.end()-1))) key.erase(key.end() - 1); + while(val.size() && isspace(*(val.end()-1))) val.erase(val.end() - 1); + + //allow empty/wiped values + if (key.size() == 0) { + continue; + } + + //save the pair + table[key] = val; + } + + is.close(); +} diff --git a/libs/Codebase/config_utility.hpp b/libs/Codebase/config_utility.hpp new file mode 100644 index 0000000..c5e0977 --- /dev/null +++ b/libs/Codebase/config_utility.hpp @@ -0,0 +1,68 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef CONFIGUTILITY_HPP_ +#define CONFIGUTILITY_HPP_ + +#include +#include +#include + +class ConfigUtility { +public: + ConfigUtility() {} + ConfigUtility(std::string s) { Load(s); } + + void Load(std::string fname); + + std::string String(std::string s) { + return table[s]; + } + const char* CString(std::string s) { + return table[s].c_str(); + } + int Integer(std::string s) { + return atoi(table[s].c_str()); + } + double Double(std::string s) { + return atof(table[s].c_str()); + } + bool Boolean(std::string s) { + return table[s] == "true"; + } + + std::string& operator[](std::string s) { + return table[s]; + } + int Int(std::string s) { + return Integer(s); + } + int Bool(std::string s) { + return Boolean(s); + } + std::map* GetMap() { + return &table; + } +private: + std::map table; +}; + +#endif diff --git a/libs/Codebase/frame_rate.cpp b/libs/Codebase/frame_rate.cpp new file mode 100644 index 0000000..e0be7a7 --- /dev/null +++ b/libs/Codebase/frame_rate.cpp @@ -0,0 +1,26 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "frame_rate.hpp" + +int FrameRate::frameCount = 0; +int FrameRate::lastFrameRate = 0; +FrameRate::Clock::time_point FrameRate::tick = FrameRate::Clock::now(); diff --git a/libs/Codebase/frame_rate.hpp b/libs/Codebase/frame_rate.hpp new file mode 100644 index 0000000..078139a --- /dev/null +++ b/libs/Codebase/frame_rate.hpp @@ -0,0 +1,48 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef FRAMERATE_HPP_ +#define FRAMERATE_HPP_ + +#include + +class FrameRate { +public: + typedef std::chrono::high_resolution_clock Clock; + + FrameRate() = delete; + static int Calculate() { + frameCount++; + if (Clock::now() - tick >= std::chrono::duration(1)) { + lastFrameRate = frameCount; + frameCount = 0; + tick = Clock::now(); + } + return lastFrameRate; + } + static int GetFrameRate() { return lastFrameRate; } +private: + static int frameCount; + static int lastFrameRate; + static Clock::time_point tick; +}; + +#endif diff --git a/libs/Codebase/image.cpp b/libs/Codebase/image.cpp new file mode 100644 index 0000000..b7cdb95 --- /dev/null +++ b/libs/Codebase/image.cpp @@ -0,0 +1,54 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "image.hpp" + +Image::Image(SDL_Surface* p) { + SetSurface(p); +} + +Image::Image(SDL_Surface* p, SDL_Rect r) { + SetSurface(p, r); +} + +SDL_Surface* Image::SetSurface(SDL_Surface* p) { + if (!(surface = p)) { + clip = {0, 0, 0, 0}; + } + else { + clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h}; + } + return surface; +} + +SDL_Surface* Image::SetSurface(SDL_Surface* const p, SDL_Rect r) { + surface = p; + clip = r; + return surface; +} + +void Image::DrawTo(SDL_Surface* dest, Sint16 x, Sint16 y) { + if (!surface) { + return; + } + SDL_Rect sclip = clip, dclip = {x,y}; + SDL_BlitSurface(surface, &sclip, dest, &dclip); +} diff --git a/libs/Codebase/image.hpp b/libs/Codebase/image.hpp new file mode 100644 index 0000000..710b842 --- /dev/null +++ b/libs/Codebase/image.hpp @@ -0,0 +1,58 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef IMAGE_HPP_ +#define IMAGE_HPP_ + +#include "SDL/SDL.h" + +class Image { +public: + Image() = default; + Image(SDL_Surface*); + Image(SDL_Surface*, SDL_Rect); + ~Image() = default; + + SDL_Surface* SetSurface(SDL_Surface*); + SDL_Surface* SetSurface(SDL_Surface*, SDL_Rect); + SDL_Surface* GetSurface() const { return surface; } + + void DrawTo(SDL_Surface* const, Sint16 x, Sint16 y); + + //Clip handlers + SDL_Rect SetClip(SDL_Rect r) { return clip = r; } + SDL_Rect GetClip() const { return clip; } + + Sint16 SetClipX(Sint16 x) { return clip.x = x; } + Sint16 SetClipY(Sint16 y) { return clip.y = y; } + Uint16 SetClipW(Uint16 w) { return clip.w = w; } + Uint16 SetClipH(Uint16 h) { return clip.h = h; } + + Sint16 GetClipX() const { return clip.x; } + Sint16 GetClipY() const { return clip.y; } + Uint16 GetClipW() const { return clip.w; } + Uint16 GetClipH() const { return clip.h; } +protected: + SDL_Surface* surface = nullptr; + SDL_Rect clip = {0, 0, 0, 0}; +}; + +#endif diff --git a/libs/Codebase/makefile b/libs/Codebase/makefile new file mode 100644 index 0000000..97e0fa0 --- /dev/null +++ b/libs/Codebase/makefile @@ -0,0 +1,37 @@ +#config +INCLUDES= +CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES)) +LIB= + +#source +SRC=$(wildcard *.cpp) + +#objects +OBJDIR=obj +OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o)) + +#output +OUTDIR=../out +OUT=$(addprefix $(OUTDIR)/,Codebase.a) + +#targets +all: $(OBJ) $(OUT) + ar -crs $(OUT) $(OBJ) + +$(OBJ): | $(OBJDIR) + +$(OUT): | $(OUTDIR) + +$(OBJDIR): + mkdir $(OBJDIR) + +$(OUTDIR): + mkdir $(OUTDIR) + +$(OBJDIR)/%.o: %.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +clean: + $(RM) *.o *.a *.exe + +rebuild: clean all diff --git a/libs/Codebase/raster_font.cpp b/libs/Codebase/raster_font.cpp new file mode 100644 index 0000000..71f1f04 --- /dev/null +++ b/libs/Codebase/raster_font.cpp @@ -0,0 +1,49 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "raster_font.hpp" + +#include + +RasterFont::RasterFont(SDL_Surface* p) { + SetSurface(p); +} + +void RasterFont::DrawStringTo(std::string s, SDL_Surface* const dest, Sint16 x, Sint16 y) { + if (!image.GetSurface()) { + throw(std::runtime_error("RasterFont not loaded")); + } + const Uint16 w = image.GetClipW(); + const Uint16 h = image.GetClipH(); + for (int i = 0; i < s.size(); i++) { + image.SetClipX(s[i] % w * w); + image.SetClipY(s[i] / h * h); + image.DrawTo(dest, x + i * w, y); + } +} + +SDL_Surface* RasterFont::SetSurface(SDL_Surface* p) { + if (image.SetSurface(p)) { + image.SetClipW(image.GetSurface()->w/16); + image.SetClipH(image.GetSurface()->h/16); + } + return image.GetSurface(); +} diff --git a/libs/Codebase/raster_font.hpp b/libs/Codebase/raster_font.hpp new file mode 100644 index 0000000..643dde6 --- /dev/null +++ b/libs/Codebase/raster_font.hpp @@ -0,0 +1,46 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef RASTERFONT_HPP_ +#define RASTERFONT_HPP_ + +#include "image.hpp" + +#include + +class RasterFont { +public: + RasterFont() = default; + RasterFont(SDL_Surface* p); + ~RasterFont() = default; + + void DrawStringTo(std::string, SDL_Surface* const, Sint16 x, Sint16 y); + + //Accessors and Mutators + SDL_Surface* SetSurface(SDL_Surface*); + SDL_Surface* GetSurface() const { return image.GetSurface(); } + Uint16 GetCharW() { return image.GetClipW(); } + Uint16 GetCharH() { return image.GetClipH(); } +private: + Image image; +}; + +#endif diff --git a/libs/Codebase/sprite_sheet.cpp b/libs/Codebase/sprite_sheet.cpp new file mode 100644 index 0000000..c387f79 --- /dev/null +++ b/libs/Codebase/sprite_sheet.cpp @@ -0,0 +1,44 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "sprite_sheet.hpp" + +SpriteSheet::SpriteSheet(SDL_Surface* s, Uint16 w, Uint16 h) { + SetSurface(s, w, h); +} + +void SpriteSheet::Update(double delta) { + if (interval && (ticks += delta) >= interval) { + if (++currentFrame >= maxFrames) { + currentFrame = 0; + } + ticks = 0; + } + image.SetClipX(currentFrame * image.GetClipW()); + image.SetClipY(currentStrip * image.GetClipH()); +} + +SDL_Surface* SpriteSheet::SetSurface(SDL_Surface* const s, Uint16 w, Uint16 h) { + image.SetSurface(s, {0, 0, w, h}); + currentFrame = 0; maxFrames = image.GetSurface()->w / image.GetClipW(); + currentStrip = 0; maxStrips = image.GetSurface()->h / image.GetClipH(); + interval = ticks = 0; +} diff --git a/libs/Codebase/sprite_sheet.hpp b/libs/Codebase/sprite_sheet.hpp new file mode 100644 index 0000000..c86dea9 --- /dev/null +++ b/libs/Codebase/sprite_sheet.hpp @@ -0,0 +1,66 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef SPRITESHEET_HPP_ +#define SPRITESHEET_HPP_ + +#include "image.hpp" + +#include "SDL/SDL.h" + +class SpriteSheet { +public: + SpriteSheet() = default; + SpriteSheet(SDL_Surface*, Uint16 w, Uint16 h); + ~SpriteSheet() = default; + + void Update(double delta); + + SDL_Surface* SetSurface(SDL_Surface* const, Uint16 w, Uint16 h); + SDL_Surface* GetSurface() const { + return image.GetSurface(); + } + + void DrawTo(SDL_Surface* const dest, Sint16 x, Sint16 y) { + image.DrawTo(dest, x, y); + } + + //Accessors and Mutators + double SetInterval(double i) { return interval = i; } + double GetInterval() const { return interval; } + + int SetCurrentFrame(int i) { return currentFrame = i; } + int SetCurrentStrip(int i) { return currentStrip = i; } + + Uint16 GetFrameWidth() const { return image.GetClipW(); } + Uint16 GetFrameHeight() const { return image.GetClipH(); } + int GetCurrentFrame() const { return currentFrame; }; + int GetCurrentStrip() const { return currentStrip; }; + int GetMaxFrames() const { return maxFrames; } + int GetMaxStrips() const { return maxStrips; } +private: + Image image; + int currentFrame = 0, maxFrames = 0; + int currentStrip = 0, maxStrips = 0; + double interval = 0, ticks = 0; +}; + +#endif diff --git a/libs/Codebase/surface_manager.cpp b/libs/Codebase/surface_manager.cpp new file mode 100644 index 0000000..a56afd3 --- /dev/null +++ b/libs/Codebase/surface_manager.cpp @@ -0,0 +1,85 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "surface_manager.hpp" + +#include + +SurfaceManager::~SurfaceManager() noexcept { + FreeAll(); +} + +SDL_Surface* SurfaceManager::Load(std::string key, std::string fname) { + MapType::iterator it = surfaceMap.find(key); + if (it != surfaceMap.end()) { + throw(std::runtime_error(std::string("Surface already loaded: ") + key + std::string(", ") + fname)); + } + return LoadSurface(key, fname); +} + +SDL_Surface* SurfaceManager::Reload(std::string key, std::string fname) { + MapType::iterator it = surfaceMap.find(key); + if (it != surfaceMap.end()) { + SDL_FreeSurface(it->second); + surfaceMap.erase(it); + } + return LoadSurface(key, fname); +} + +SDL_Surface* SurfaceManager::Get(std::string key) { + MapType::iterator it = surfaceMap.find(key); + if (it == surfaceMap.end()) { + throw(std::runtime_error(std::string("Could not find key: ") + key)); + } + return it->second; +} + +SDL_Surface* SurfaceManager::Set(std::string key, SDL_Surface* ptr) { + MapType::iterator it = surfaceMap.find(key); + if (it != surfaceMap.end()) { + throw(std::runtime_error(std::string("Key already exists: ") + key)); + } + return surfaceMap[key] = ptr; +} + +void SurfaceManager::Free(std::string key) { + MapType::iterator it = surfaceMap.find(key); + if (it != surfaceMap.end()) { + SDL_FreeSurface(it->second); + surfaceMap.erase(it); + } +} + +void SurfaceManager::FreeAll() { + for (auto it : surfaceMap) { + SDL_FreeSurface(it.second); + } + surfaceMap.clear(); +} + +SDL_Surface* SurfaceManager::LoadSurface(std::string key, std::string fname) { + SDL_Surface* ptr = SDL_LoadBMP(fname.c_str()); + if (!ptr) { + throw(std::runtime_error(std::string("Failed to load file: ") + fname)); + } + SDL_SetColorKey(ptr, SDL_SRCCOLORKEY, SDL_MapRGB(ptr->format, 255, 0, 255)); //default + return surfaceMap[key] = ptr; +} diff --git a/libs/Codebase/surface_manager.hpp b/libs/Codebase/surface_manager.hpp new file mode 100644 index 0000000..8499a83 --- /dev/null +++ b/libs/Codebase/surface_manager.hpp @@ -0,0 +1,49 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef SURFACEMANAGER_HPP_ +#define SURFACEMANAGER_HPP_ + +#include "SDL/SDL.h" + +#include +#include + +class SurfaceManager { +public: + SurfaceManager() = default; + ~SurfaceManager() noexcept; + + SDL_Surface* Load(std::string key, std::string fname); + SDL_Surface* Reload(std::string key, std::string fname); + SDL_Surface* Get(std::string key); + SDL_Surface* Set(std::string key, SDL_Surface* ptr); + void Free(std::string key); + void FreeAll(); + + SDL_Surface* operator[](std::string key) { return Get(key); }; +private: + SDL_Surface* LoadSurface(std::string key, std::string fname); + typedef std::map MapType; + MapType surfaceMap; +}; + +#endif diff --git a/libs/Codebase/udp_network_utility.cpp b/libs/Codebase/udp_network_utility.cpp new file mode 100644 index 0000000..5f828c7 --- /dev/null +++ b/libs/Codebase/udp_network_utility.cpp @@ -0,0 +1,148 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "udp_network_utility.hpp" + +#include + +void UDPNetworkUtility::Open(int port, int packSize) { + if (!(socket = SDLNet_UDP_Open(port))) { + Close(); + throw(std::runtime_error("Failed to open a UDP socket")); + } + + if (!(packOut = SDLNet_AllocPacket(packSize))) { + Close(); + throw(std::runtime_error("Failed to allocate the out packet")); + } + + if (!(packIn = SDLNet_AllocPacket(packSize))) { + Close(); + throw(std::runtime_error("Failed to allocate the in packet")); + } +} + +void UDPNetworkUtility::Close() { + SDLNet_UDP_Close(socket); + SDLNet_FreePacket(packOut); + SDLNet_FreePacket(packIn); + socket = nullptr; + packOut = nullptr; + packIn = nullptr; +} + +int UDPNetworkUtility::Bind(const char* ip, int port, int channel) { + IPaddress add; + if (SDLNet_ResolveHost(&add, ip, port) == -1) { + throw(std::runtime_error("Failed to resolve a host")); + } + + return Bind(&add, channel); +} + +int UDPNetworkUtility::Bind(IPaddress* add, int channel) { + int ret = SDLNet_UDP_Bind(socket, channel, add); + + if (ret == -1) { + throw(std::runtime_error("Failed to bind to a channel")); + } + + return ret; +} + +void UDPNetworkUtility::Unbind(int channel) { + SDLNet_UDP_Unbind(socket, channel); +} + +int UDPNetworkUtility::Send(const char* ip, int port, void* data, int len) { + IPaddress add; + if (SDLNet_ResolveHost(&add, ip, port) == -1) { + throw(std::runtime_error("Failed to resolve a host")); + } + + Send(&add, data, len); +} + +int UDPNetworkUtility::Send(IPaddress* add, void* data, int len) { + if (len > packOut->maxlen) { + throw(std::runtime_error("Failed to copy the data into the packet")); + } + memset(packOut->data, 0, packOut->maxlen); + memcpy(packOut->data, data, len); + packOut->len = len; + packOut->address = *add; + + int ret = SDLNet_UDP_Send(socket, -1, packOut); + + if (ret <= 0) { + throw(std::runtime_error("Failed to send a packet")); + } + + return ret; +} + +int UDPNetworkUtility::Send(int channel, void* data, int len) { + if (len > packOut->maxlen) { + throw(std::runtime_error("Failed to copy the data into the packet")); + } + memset(packOut->data, 0, packOut->maxlen); + memcpy(packOut->data, data, len); + packOut->len = len; + + int ret = SDLNet_UDP_Send(socket, channel, packOut); + + if (ret <= 0) { + throw(std::runtime_error("Failed to send a packet")); + } + + return ret; +} + +int UDPNetworkUtility::SendAll(void* data, int len) { + if (len > packOut->maxlen) { + throw(std::runtime_error("Failed to copy the data into the packet")); + } + memset(packOut->data, 0, packOut->maxlen); + memcpy(packOut->data, data, len); + packOut->len = len; + + int sent = 0; + + //send to all bound channels + for (int i = 0; i < SDLNET_MAX_UDPCHANNELS; i++) { + if (SDLNet_UDP_GetPeerAddress(socket, i)) { + sent += SDLNet_UDP_Send(socket, i, packOut); + } + } + + return sent; +} + +int UDPNetworkUtility::Receive() { + memset(packIn->data, 0, packIn->maxlen); + int ret = SDLNet_UDP_Recv(socket, packIn); + + if (ret < 0) { + throw(std::runtime_error("Unknown network error occured")); + } + + return ret; +} diff --git a/libs/Codebase/udp_network_utility.hpp b/libs/Codebase/udp_network_utility.hpp new file mode 100644 index 0000000..dbd752e --- /dev/null +++ b/libs/Codebase/udp_network_utility.hpp @@ -0,0 +1,79 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef UDPNETWORKUTILITY_HPP_ +#define UDPNETWORKUTILITY_HPP_ + +#include "SDL_net/SDL_net.h" + +class UDPNetworkUtility { +public: + UDPNetworkUtility() = default; + ~UDPNetworkUtility() = default; + + void Open(int port, int packSize); + void Close(); + + //bind to an available channel + int Bind(const char* ip, int port) { + Bind(ip, port, -1); + } + int Bind(IPaddress* add) { + Bind(add, -1); + } + + //bind to certain channel + int Bind(const char* ip, int port, int channel); + int Bind(IPaddress* add, int channel); + void Unbind(int channel); + + IPaddress* GetIPAddress(int channel) { + return SDLNet_UDP_GetPeerAddress(socket, channel); + } + + int Send(const char* ip, int port, void* data, int len); + int Send(IPaddress* add, void* data, int len); + int Send(int channel, void* data, int len); + int SendAll(void* data, int len); + int Receive(); + + void* GetOutData() const { + return reinterpret_cast(packOut->data); + }; + void* GetInData() const { + return reinterpret_cast(packIn->data); + }; + UDPpacket* GetOutPacket() const { + return packOut; + } + UDPpacket* GetInPacket() const { + return packIn; + } + UDPsocket GetSocket() const { + return socket; + } +private: + UDPsocket socket = nullptr; + UDPpacket* packOut = nullptr; + UDPpacket* packIn = nullptr; +}; + +#endif diff --git a/libs/Codebase/vector2.hpp b/libs/Codebase/vector2.hpp new file mode 100644 index 0000000..36c6186 --- /dev/null +++ b/libs/Codebase/vector2.hpp @@ -0,0 +1,77 @@ +/* Copyright: (c) Kayne Ruse 2013 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef VECTOR2_HPP_ +#define VECTOR2_HPP_ + +#include +#include + +class Vector2 { +public: + double x = 0, y = 0; + Vector2() = default; + Vector2(double i, double j) { + x = i; y = j; + } + double Length() const { + return sqrt(x*x+y*y); + } + double SquaredLength() const { + return x*x+y*y; + } + + double operator[](size_t i) { + if (i >= 2) + throw(std::runtime_error("Out of range")); + return *(&x+i); + } + + //Arithmetic operators + Vector2 operator+(Vector2 v) const { return Vector2(x + v.x, y + v.y); } + Vector2 operator-(Vector2 v) const { return Vector2(x - v.x, y - v.y); } + Vector2 operator*(Vector2 v) const { return Vector2(x * v.x, y * v.y); } + Vector2 operator*(double d) const { return Vector2(x * d, y * d); } + + Vector2 operator/(Vector2 v) { + if (!v.x || !v.y) + throw(std::runtime_error("Divide by zero")); + return Vector2(x / v.x, y / v.y); + } + Vector2 operator/(double d) { + if (!d) + throw(std::runtime_error("Divide by zero")); + return Vector2(x / d, y / d); + } + + bool operator==(Vector2 v) { return (x == v.x && y == v.y); } + bool operator!=(Vector2 v) { return (x != v.x || y != v.y); } + + //templates + template Vector2 operator+=(T t) { return *this = *this + t; } + template Vector2 operator-=(T t) { return *this = *this - t; } + template Vector2 operator*=(T t) { return *this = *this * t; } + template Vector2 operator/=(T t) { return *this = *this / t; } + template bool operator==(T t) { return (x == t && y == t); } + template bool operator!=(T t) { return (x != t || y != t); } +}; + +#endif diff --git a/libs/SDL_net/SDL_net.h b/libs/SDL_net/SDL_net.h new file mode 100644 index 0000000..9258f86 --- /dev/null +++ b/libs/SDL_net/SDL_net.h @@ -0,0 +1,452 @@ +/* + SDL_net: An example cross-platform network library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* $Id$ */ + +#ifndef _SDL_NET_H +#define _SDL_NET_H + +#include "SDL/SDL.h" +#include "SDL/SDL_endian.h" +#include "SDL/SDL_version.h" +#include "SDL/begin_code.h" + + + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL +*/ +#define SDL_NET_MAJOR_VERSION 1 +#define SDL_NET_MINOR_VERSION 2 +#define SDL_NET_PATCHLEVEL 8 + +/* This macro can be used to fill a version structure with the compile-time + * version of the SDL_net library. + */ +#define SDL_NET_VERSION(X) \ +{ \ + (X)->major = SDL_NET_MAJOR_VERSION; \ + (X)->minor = SDL_NET_MINOR_VERSION; \ + (X)->patch = SDL_NET_PATCHLEVEL; \ +} + +/* This function gets the version of the dynamically linked SDL_net library. + it should NOT be used to fill a version structure, instead you should + use the SDL_NET_VERSION() macro. + */ +extern DECLSPEC const SDL_version * SDLCALL SDLNet_Linked_Version(void); + +/* Initialize/Cleanup the network API + SDL must be initialized before calls to functions in this library, + because this library uses utility functions from the SDL library. +*/ +extern DECLSPEC int SDLCALL SDLNet_Init(void); +extern DECLSPEC void SDLCALL SDLNet_Quit(void); + +/***********************************************************************/ +/* IPv4 hostname resolution API */ +/***********************************************************************/ + +typedef struct { + Uint32 host; /* 32-bit IPv4 host address */ + Uint16 port; /* 16-bit protocol port */ +} IPaddress; + +/* Resolve a host name and port to an IP address in network form. + If the function succeeds, it will return 0. + If the host couldn't be resolved, the host portion of the returned + address will be INADDR_NONE, and the function will return -1. + If 'host' is NULL, the resolved host will be set to INADDR_ANY. + */ +#ifndef INADDR_ANY +#define INADDR_ANY 0x00000000 +#endif +#ifndef INADDR_NONE +#define INADDR_NONE 0xFFFFFFFF +#endif +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK 0x7f000001 +#endif +#ifndef INADDR_BROADCAST +#define INADDR_BROADCAST 0xFFFFFFFF +#endif +extern DECLSPEC int SDLCALL SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port); + +/* Resolve an ip address to a host name in canonical form. + If the ip couldn't be resolved, this function returns NULL, + otherwise a pointer to a static buffer containing the hostname + is returned. Note that this function is not thread-safe. +*/ +extern DECLSPEC const char * SDLCALL SDLNet_ResolveIP(const IPaddress *ip); + +/* Get the addresses of network interfaces on this system. + This returns the number of addresses saved in 'addresses' + */ +extern DECLSPEC int SDLCALL SDLNet_GetLocalAddresses(IPaddress *addresses, int maxcount); + +/***********************************************************************/ +/* TCP network API */ +/***********************************************************************/ + +typedef struct _TCPsocket *TCPsocket; + +/* Open a TCP network socket + If ip.host is INADDR_NONE or INADDR_ANY, this creates a local server + socket on the given port, otherwise a TCP connection to the remote + host and port is attempted. The address passed in should already be + swapped to network byte order (addresses returned from + SDLNet_ResolveHost() are already in the correct form). + The newly created socket is returned, or NULL if there was an error. +*/ +extern DECLSPEC TCPsocket SDLCALL SDLNet_TCP_Open(IPaddress *ip); + +/* Accept an incoming connection on the given server socket. + The newly created socket is returned, or NULL if there was an error. +*/ +extern DECLSPEC TCPsocket SDLCALL SDLNet_TCP_Accept(TCPsocket server); + +/* Get the IP address of the remote system associated with the socket. + If the socket is a server socket, this function returns NULL. +*/ +extern DECLSPEC IPaddress * SDLCALL SDLNet_TCP_GetPeerAddress(TCPsocket sock); + +/* Send 'len' bytes of 'data' over the non-server socket 'sock' + This function returns the actual amount of data sent. If the return value + is less than the amount of data sent, then either the remote connection was + closed, or an unknown socket error occurred. +*/ +extern DECLSPEC int SDLCALL SDLNet_TCP_Send(TCPsocket sock, const void *data, + int len); + +/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock', + and store them in the buffer pointed to by 'data'. + This function returns the actual amount of data received. If the return + value is less than or equal to zero, then either the remote connection was + closed, or an unknown socket error occurred. +*/ +extern DECLSPEC int SDLCALL SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen); + +/* Close a TCP network socket */ +extern DECLSPEC void SDLCALL SDLNet_TCP_Close(TCPsocket sock); + + +/***********************************************************************/ +/* UDP network API */ +/***********************************************************************/ + +/* The maximum channels on a a UDP socket */ +#define SDLNET_MAX_UDPCHANNELS 150 +/* The maximum addresses bound to a single UDP socket channel */ +#define SDLNET_MAX_UDPADDRESSES 1 + +typedef struct _UDPsocket *UDPsocket; +typedef struct { + int channel; /* The src/dst channel of the packet */ + Uint8 *data; /* The packet data */ + int len; /* The length of the packet data */ + int maxlen; /* The size of the data buffer */ + int status; /* packet status after sending */ + IPaddress address; /* The source/dest address of an incoming/outgoing packet */ +} UDPpacket; + +/* Allocate/resize/free a single UDP packet 'size' bytes long. + The new packet is returned, or NULL if the function ran out of memory. + */ +extern DECLSPEC UDPpacket * SDLCALL SDLNet_AllocPacket(int size); +extern DECLSPEC int SDLCALL SDLNet_ResizePacket(UDPpacket *packet, int newsize); +extern DECLSPEC void SDLCALL SDLNet_FreePacket(UDPpacket *packet); + +/* Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets, + each 'size' bytes long. + A pointer to the first packet in the array is returned, or NULL if the + function ran out of memory. + */ +extern DECLSPEC UDPpacket ** SDLCALL SDLNet_AllocPacketV(int howmany, int size); +extern DECLSPEC void SDLCALL SDLNet_FreePacketV(UDPpacket **packetV); + + +/* Open a UDP network socket + If 'port' is non-zero, the UDP socket is bound to a local port. + The 'port' should be given in native byte order, but is used + internally in network (big endian) byte order, in addresses, etc. + This allows other systems to send to this socket via a known port. +*/ +extern DECLSPEC UDPsocket SDLCALL SDLNet_UDP_Open(Uint16 port); + +/* Set the percentage of simulated packet loss for packets sent on the socket. +*/ +extern DECLSPEC void SDLCALL SDLNet_UDP_SetPacketLoss(UDPsocket sock, int percent); + +/* Bind the address 'address' to the requested channel on the UDP socket. + If the channel is -1, then the first unbound channel will be bound with + the given address as it's primary address. + If the channel is already bound, this new address will be added to the + list of valid source addresses for packets arriving on the channel. + If the channel is not already bound, then the address becomes the primary + address, to which all outbound packets on the channel are sent. + This function returns the channel which was bound, or -1 on error. +*/ +extern DECLSPEC int SDLCALL SDLNet_UDP_Bind(UDPsocket sock, int channel, const IPaddress *address); + +/* Unbind all addresses from the given channel */ +extern DECLSPEC void SDLCALL SDLNet_UDP_Unbind(UDPsocket sock, int channel); + +/* Get the primary IP address of the remote system associated with the + socket and channel. If the channel is -1, then the primary IP port + of the UDP socket is returned -- this is only meaningful for sockets + opened with a specific port. + If the channel is not bound and not -1, this function returns NULL. + */ +extern DECLSPEC IPaddress * SDLCALL SDLNet_UDP_GetPeerAddress(UDPsocket sock, int channel); + +/* Send a vector of packets to the the channels specified within the packet. + If the channel specified in the packet is -1, the packet will be sent to + the address in the 'src' member of the packet. + Each packet will be updated with the status of the packet after it has + been sent, -1 if the packet send failed. + This function returns the number of packets sent. +*/ +extern DECLSPEC int SDLCALL SDLNet_UDP_SendV(UDPsocket sock, UDPpacket **packets, int npackets); + +/* Send a single packet to the specified channel. + If the channel specified in the packet is -1, the packet will be sent to + the address in the 'src' member of the packet. + The packet will be updated with the status of the packet after it has + been sent. + This function returns 1 if the packet was sent, or 0 on error. + + NOTE: + The maximum size of the packet is limited by the MTU (Maximum Transfer Unit) + of the transport medium. It can be as low as 250 bytes for some PPP links, + and as high as 1500 bytes for ethernet. +*/ +extern DECLSPEC int SDLCALL SDLNet_UDP_Send(UDPsocket sock, int channel, UDPpacket *packet); + +/* Receive a vector of pending packets from the UDP socket. + The returned packets contain the source address and the channel they arrived + on. If they did not arrive on a bound channel, the the channel will be set + to -1. + The channels are checked in highest to lowest order, so if an address is + bound to multiple channels, the highest channel with the source address + bound will be returned. + This function returns the number of packets read from the network, or -1 + on error. This function does not block, so can return 0 packets pending. +*/ +extern DECLSPEC int SDLCALL SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packets); + +/* Receive a single packet from the UDP socket. + The returned packet contains the source address and the channel it arrived + on. If it did not arrive on a bound channel, the the channel will be set + to -1. + The channels are checked in highest to lowest order, so if an address is + bound to multiple channels, the highest channel with the source address + bound will be returned. + This function returns the number of packets read from the network, or -1 + on error. This function does not block, so can return 0 packets pending. +*/ +extern DECLSPEC int SDLCALL SDLNet_UDP_Recv(UDPsocket sock, UDPpacket *packet); + +/* Close a UDP network socket */ +extern DECLSPEC void SDLCALL SDLNet_UDP_Close(UDPsocket sock); + + +/***********************************************************************/ +/* Hooks for checking sockets for available data */ +/***********************************************************************/ + +typedef struct _SDLNet_SocketSet *SDLNet_SocketSet; + +/* Any network socket can be safely cast to this socket type */ +typedef struct _SDLNet_GenericSocket { + int ready; +} *SDLNet_GenericSocket; + +/* Allocate a socket set for use with SDLNet_CheckSockets() + This returns a socket set for up to 'maxsockets' sockets, or NULL if + the function ran out of memory. + */ +extern DECLSPEC SDLNet_SocketSet SDLCALL SDLNet_AllocSocketSet(int maxsockets); + +/* Add a socket to a set of sockets to be checked for available data */ +#define SDLNet_TCP_AddSocket(set, sock) \ + SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) +#define SDLNet_UDP_AddSocket(set, sock) \ + SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) +extern DECLSPEC int SDLCALL SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock); + +/* Remove a socket from a set of sockets to be checked for available data */ +#define SDLNet_TCP_DelSocket(set, sock) \ + SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) +#define SDLNet_UDP_DelSocket(set, sock) \ + SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) +extern DECLSPEC int SDLCALL SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock); + +/* This function checks to see if data is available for reading on the + given set of sockets. If 'timeout' is 0, it performs a quick poll, + otherwise the function returns when either data is available for + reading, or the timeout in milliseconds has elapsed, which ever occurs + first. This function returns the number of sockets ready for reading, + or -1 if there was an error with the select() system call. +*/ +extern DECLSPEC int SDLCALL SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout); + +/* After calling SDLNet_CheckSockets(), you can use this function on a + socket that was in the socket set, to find out if data is available + for reading. +*/ +#define SDLNet_SocketReady(sock) \ + ((sock != NULL) && SDL_reinterpret_cast(SDLNet_GenericSocket, sock)->ready) + +/* Free a set of sockets allocated by SDL_NetAllocSocketSet() */ +extern DECLSPEC void SDLCALL SDLNet_FreeSocketSet(SDLNet_SocketSet set); + + +/***********************************************************************/ +/* Platform-independent data conversion functions */ +/***********************************************************************/ + +/* Write a 16/32 bit value to network packet buffer */ +extern DECLSPEC void SDLCALL SDLNet_Write16(Uint16 value, void *area); +extern DECLSPEC void SDLCALL SDLNet_Write32(Uint32 value, void *area); + +/* Read a 16/32 bit value from network packet buffer */ +extern DECLSPEC Uint16 SDLCALL SDLNet_Read16(void *area); +extern DECLSPEC Uint32 SDLCALL SDLNet_Read32(void *area); + +/***********************************************************************/ +/* Error reporting functions */ +/***********************************************************************/ + +/* We'll use SDL's functions for error reporting */ +#define SDLNet_SetError SDL_SetError +#define SDLNet_GetError SDL_GetError + +/* I'm eventually going to try to disentangle SDL_net from SDL, thus making + SDL_net an independent X-platform networking toolkit. Not today though.... + +extern no_parse_DECLSPEC void SDLCALL SDLNet_SetError(const char *fmt, ...); +extern no_parse_DECLSPEC char * SDLCALL SDLNet_GetError(void); +*/ + + +/* Inline macro functions to read/write network data */ + +/* Warning, some systems have data access alignment restrictions */ +#if defined(sparc) || defined(mips) +#define SDL_DATA_ALIGNED 1 +#endif +#ifndef SDL_DATA_ALIGNED +#define SDL_DATA_ALIGNED 0 +#endif + +/* Write a 16 bit value to network packet buffer */ +#if !SDL_DATA_ALIGNED +#define SDLNet_Write16(value, areap) \ + (*SDL_reinterpret_cast(Uint16 *, areap) = SDL_SwapBE16(value)) +#else +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define SDLNet_Write16(value, areap) \ +do \ +{ \ + Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ + area[0] = (value >> 8) & 0xFF; \ + area[1] = value & 0xFF; \ +} while ( 0 ) +#else +#define SDLNet_Write16(value, areap) \ +do \ +{ \ + Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ + area[1] = (value >> 8) & 0xFF; \ + area[0] = value & 0xFF; \ +} while ( 0 ) +#endif +#endif /* !SDL_DATA_ALIGNED */ + +/* Write a 32 bit value to network packet buffer */ +#if !SDL_DATA_ALIGNED +#define SDLNet_Write32(value, areap) \ + *SDL_reinterpret_cast(Uint32 *, areap) = SDL_SwapBE32(value); +#else +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define SDLNet_Write32(value, areap) \ +do \ +{ \ + Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ + area[0] = (value >> 24) & 0xFF; \ + area[1] = (value >> 16) & 0xFF; \ + area[2] = (value >> 8) & 0xFF; \ + area[3] = value & 0xFF; \ +} while ( 0 ) +#else +#define SDLNet_Write32(value, areap) \ +do \ +{ \ + Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ + area[3] = (value >> 24) & 0xFF; \ + area[2] = (value >> 16) & 0xFF; \ + area[1] = (value >> 8) & 0xFF; \ + area[0] = value & 0xFF; \ +} while ( 0 ) +#endif +#endif /* !SDL_DATA_ALIGNED */ + +/* Read a 16 bit value from network packet buffer */ +#if !SDL_DATA_ALIGNED +#define SDLNet_Read16(areap) \ + (SDL_SwapBE16(*SDL_reinterpret_cast(Uint16 *, areap))) +#else +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define SDLNet_Read16(areap) \ + (((SDL_reinterpret_cast(Uint8 *, areap))[0] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[1] << 0) +#else +#define SDLNet_Read16(areap) \ + (((SDL_reinterpret_cast(Uint8 *, areap))[1] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[0] << 0) +#endif +#endif /* !SDL_DATA_ALIGNED */ + +/* Read a 32 bit value from network packet buffer */ +#if !SDL_DATA_ALIGNED +#define SDLNet_Read32(areap) \ + (SDL_SwapBE32(*SDL_reinterpret_cast(Uint32 *, areap))) +#else +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define SDLNet_Read32(areap) \ + (((SDL_reinterpret_cast(Uint8 *, areap))[0] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[1] << 16) | \ + ((SDL_reinterpret_cast(Uint8 *, areap))[2] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[3] << 0) +#else +#define SDLNet_Read32(areap) \ + (((SDL_reinterpret_cast(Uint8 *, areap))[3] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[2] << 16) | \ + ((SDL_reinterpret_cast(Uint8 *, areap))[1] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[0] << 0) +#endif +#endif /* !SDL_DATA_ALIGNED */ + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "SDL/close_code.h" + +#endif /* _SDL_NET_H */ diff --git a/libs/SDL_net/SDLnet.c b/libs/SDL_net/SDLnet.c new file mode 100644 index 0000000..310c0cd --- /dev/null +++ b/libs/SDL_net/SDLnet.c @@ -0,0 +1,269 @@ +/* + SDL_net: An example cross-platform network library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* $Id$ */ + +#include + +#include "SDL/SDL_endian.h" + +#include "SDLnetsys.h" +#include "SDL_net.h" + + +const SDL_version *SDLNet_Linked_Version(void) +{ + static SDL_version linked_version; + SDL_NET_VERSION(&linked_version); + return(&linked_version); +} + +/* Since the UNIX/Win32/BeOS code is so different from MacOS, + we'll just have two completely different sections here. +*/ +static int SDLNet_started = 0; + +#ifndef __USE_W32_SOCKETS +#include +#endif + +#ifndef __USE_W32_SOCKETS + +int SDLNet_GetLastError(void) +{ + return errno; +} + +void SDLNet_SetLastError(int err) +{ + errno = err; +} + +#endif + +/* Initialize/Cleanup the network API */ +int SDLNet_Init(void) +{ + if ( !SDLNet_started ) { +#ifdef __USE_W32_SOCKETS + /* Start up the windows networking */ + WORD version_wanted = MAKEWORD(1,1); + WSADATA wsaData; + + if ( WSAStartup(version_wanted, &wsaData) != 0 ) { + SDLNet_SetError("Couldn't initialize Winsock 1.1\n"); + return(-1); + } +#else + /* SIGPIPE is generated when a remote socket is closed */ + void (*handler)(int); + handler = signal(SIGPIPE, SIG_IGN); + if ( handler != SIG_DFL ) { + signal(SIGPIPE, handler); + } +#endif + } + ++SDLNet_started; + return(0); +} +void SDLNet_Quit(void) +{ + if ( SDLNet_started == 0 ) { + return; + } + if ( --SDLNet_started == 0 ) { +#ifdef __USE_W32_SOCKETS + /* Clean up windows networking */ + if ( WSACleanup() == SOCKET_ERROR ) { + if ( WSAGetLastError() == WSAEINPROGRESS ) { +#ifndef _WIN32_WCE + WSACancelBlockingCall(); +#endif + WSACleanup(); + } + } +#else + /* Restore the SIGPIPE handler */ + void (*handler)(int); + handler = signal(SIGPIPE, SIG_DFL); + if ( handler != SIG_IGN ) { + signal(SIGPIPE, handler); + } +#endif + } +} + +/* Resolve a host name and port to an IP address in network form */ +int SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port) +{ + int retval = 0; + + /* Perform the actual host resolution */ + if ( host == NULL ) { + address->host = INADDR_ANY; + } else { + address->host = inet_addr(host); + if ( address->host == INADDR_NONE ) { + struct hostent *hp; + + hp = gethostbyname(host); + if ( hp ) { + memcpy(&address->host,hp->h_addr,hp->h_length); + } else { + retval = -1; + } + } + } + address->port = SDL_SwapBE16(port); + + /* Return the status */ + return(retval); +} + +/* Resolve an ip address to a host name in canonical form. + If the ip couldn't be resolved, this function returns NULL, + otherwise a pointer to a static buffer containing the hostname + is returned. Note that this function is not thread-safe. +*/ +/* Written by Miguel Angel Blanch. + * Main Programmer of Arianne RPG. + * http://come.to/arianne_rpg + */ +const char *SDLNet_ResolveIP(const IPaddress *ip) +{ + struct hostent *hp; + struct in_addr in; + + hp = gethostbyaddr((const char *)&ip->host, sizeof(ip->host), AF_INET); + if ( hp != NULL ) { + return hp->h_name; + } + + in.s_addr = ip->host; + return inet_ntoa(in); +} + +int SDLNet_GetLocalAddresses(IPaddress *addresses, int maxcount) +{ + int count = 0; +#ifdef SIOCGIFCONF +/* Defined on Mac OS X */ +#ifndef _SIZEOF_ADDR_IFREQ +#define _SIZEOF_ADDR_IFREQ sizeof +#endif + SOCKET sock; + struct ifconf conf; + char data[4096]; + struct ifreq *ifr; + struct sockaddr_in *sock_addr; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if ( sock == INVALID_SOCKET ) { + return 0; + } + + conf.ifc_len = sizeof(data); + conf.ifc_buf = (caddr_t) data; + if ( ioctl(sock, SIOCGIFCONF, &conf) < 0 ) { + closesocket(sock); + return 0; + } + + ifr = (struct ifreq*)data; + while ((char*)ifr < data+conf.ifc_len) { + if (ifr->ifr_addr.sa_family == AF_INET) { + if (count < maxcount) { + sock_addr = (struct sockaddr_in*)&ifr->ifr_addr; + addresses[count].host = sock_addr->sin_addr.s_addr; + addresses[count].port = sock_addr->sin_port; + } + ++count; + } + ifr = (struct ifreq*)((char*)ifr + _SIZEOF_ADDR_IFREQ(*ifr)); + } + closesocket(sock); +#elif defined(__WIN32__) + PIP_ADAPTER_INFO pAdapterInfo; + PIP_ADAPTER_INFO pAdapter; + PIP_ADDR_STRING pAddress; + DWORD dwRetVal = 0; + ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO); + + pAdapterInfo = (IP_ADAPTER_INFO *) SDL_malloc(sizeof (IP_ADAPTER_INFO)); + if (pAdapterInfo == NULL) { + return 0; + } + + if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == ERROR_BUFFER_OVERFLOW) { + pAdapterInfo = (IP_ADAPTER_INFO *) SDL_realloc(pAdapterInfo, ulOutBufLen); + if (pAdapterInfo == NULL) { + return 0; + } + dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); + } + + if (dwRetVal == NO_ERROR) { + for (pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next) { + for (pAddress = &pAdapterInfo->IpAddressList; pAddress; pAddress = pAddress->Next) { + if (count < maxcount) { + addresses[count].host = inet_addr(pAddress->IpAddress.String); + addresses[count].port = 0; + } + ++count; + } + } + } + SDL_free(pAdapterInfo); +#endif + return count; +} + +#if !SDL_DATA_ALIGNED /* function versions for binary compatibility */ + +/* Write a 16 bit value to network packet buffer */ +#undef SDLNet_Write16 +void SDLNet_Write16(Uint16 value, void *areap) +{ + (*(Uint16 *)(areap) = SDL_SwapBE16(value)); +} + +/* Write a 32 bit value to network packet buffer */ +#undef SDLNet_Write32 +void SDLNet_Write32(Uint32 value, void *areap) +{ + *(Uint32 *)(areap) = SDL_SwapBE32(value); +} + +/* Read a 16 bit value from network packet buffer */ +#undef SDLNet_Read16 +Uint16 SDLNet_Read16(void *areap) +{ + return (SDL_SwapBE16(*(Uint16 *)(areap))); +} + +/* Read a 32 bit value from network packet buffer */ +#undef SDLNet_Read32 +Uint32 SDLNet_Read32(void *areap) +{ + return (SDL_SwapBE32(*(Uint32 *)(areap))); +} + +#endif /* !SDL_DATA_ALIGNED */ diff --git a/libs/SDL_net/SDLnetTCP.c b/libs/SDL_net/SDLnetTCP.c new file mode 100644 index 0000000..e68f208 --- /dev/null +++ b/libs/SDL_net/SDLnetTCP.c @@ -0,0 +1,295 @@ +/* + SDL_net: An example cross-platform network library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* $Id$ */ + +#include "SDLnetsys.h" +#include "SDL_net.h" + +/* The network API for TCP sockets */ + +/* Since the UNIX/Win32/BeOS code is so different from MacOS, + we'll just have two completely different sections here. +*/ + +struct _TCPsocket { + int ready; + SOCKET channel; + IPaddress remoteAddress; + IPaddress localAddress; + int sflag; +}; + +/* Open a TCP network socket + If 'remote' is NULL, this creates a local server socket on the given port, + otherwise a TCP connection to the remote host and port is attempted. + The newly created socket is returned, or NULL if there was an error. +*/ +TCPsocket SDLNet_TCP_Open(IPaddress *ip) +{ + TCPsocket sock; + struct sockaddr_in sock_addr; + + /* Allocate a TCP socket structure */ + sock = (TCPsocket)malloc(sizeof(*sock)); + if ( sock == NULL ) { + SDLNet_SetError("Out of memory"); + goto error_return; + } + + /* Open the socket */ + sock->channel = socket(AF_INET, SOCK_STREAM, 0); + if ( sock->channel == INVALID_SOCKET ) { + SDLNet_SetError("Couldn't create socket"); + goto error_return; + } + + /* Connect to remote, or bind locally, as appropriate */ + if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) ) { + + // ######### Connecting to remote + + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = ip->host; + sock_addr.sin_port = ip->port; + + /* Connect to the remote host */ + if ( connect(sock->channel, (struct sockaddr *)&sock_addr, + sizeof(sock_addr)) == SOCKET_ERROR ) { + SDLNet_SetError("Couldn't connect to remote host"); + goto error_return; + } + sock->sflag = 0; + } else { + + // ########## Binding locally + + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = INADDR_ANY; + sock_addr.sin_port = ip->port; + +/* + * Windows gets bad mojo with SO_REUSEADDR: + * http://www.devolution.com/pipermail/sdl/2005-September/070491.html + * --ryan. + */ +#ifndef WIN32 + /* allow local address reuse */ + { int yes = 1; + setsockopt(sock->channel, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)); + } +#endif + + /* Bind the socket for listening */ + if ( bind(sock->channel, (struct sockaddr *)&sock_addr, + sizeof(sock_addr)) == SOCKET_ERROR ) { + SDLNet_SetError("Couldn't bind to local port"); + goto error_return; + } + if ( listen(sock->channel, 5) == SOCKET_ERROR ) { + SDLNet_SetError("Couldn't listen to local port"); + goto error_return; + } + + /* Set the socket to non-blocking mode for accept() */ +#if defined(__BEOS__) && defined(SO_NONBLOCK) + /* On BeOS r5 there is O_NONBLOCK but it's for files only */ + { + long b = 1; + setsockopt(sock->channel, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); + } +#elif defined(O_NONBLOCK) + { + fcntl(sock->channel, F_SETFL, O_NONBLOCK); + } +#elif defined(WIN32) + { + unsigned long mode = 1; + ioctlsocket (sock->channel, FIONBIO, &mode); + } +#elif defined(__OS2__) + { + int dontblock = 1; + ioctl(sock->channel, FIONBIO, &dontblock); + } +#else +#warning How do we set non-blocking mode on other operating systems? +#endif + sock->sflag = 1; + } + sock->ready = 0; + +#ifdef TCP_NODELAY + /* Set the nodelay TCP option for real-time games */ + { int yes = 1; + setsockopt(sock->channel, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes)); + } +#endif /* TCP_NODELAY */ + + /* Fill in the channel host address */ + sock->remoteAddress.host = sock_addr.sin_addr.s_addr; + sock->remoteAddress.port = sock_addr.sin_port; + + /* The socket is ready */ + return(sock); + +error_return: + SDLNet_TCP_Close(sock); + return(NULL); +} + +/* Accept an incoming connection on the given server socket. + The newly created socket is returned, or NULL if there was an error. +*/ +TCPsocket SDLNet_TCP_Accept(TCPsocket server) +{ + TCPsocket sock; + struct sockaddr_in sock_addr; + socklen_t sock_alen; + + /* Only server sockets can accept */ + if ( ! server->sflag ) { + SDLNet_SetError("Only server sockets can accept()"); + return(NULL); + } + server->ready = 0; + + /* Allocate a TCP socket structure */ + sock = (TCPsocket)malloc(sizeof(*sock)); + if ( sock == NULL ) { + SDLNet_SetError("Out of memory"); + goto error_return; + } + + /* Accept a new TCP connection on a server socket */ + sock_alen = sizeof(sock_addr); + sock->channel = accept(server->channel, (struct sockaddr *)&sock_addr, + &sock_alen); + if ( sock->channel == INVALID_SOCKET ) { + SDLNet_SetError("accept() failed"); + goto error_return; + } +#ifdef WIN32 + { + /* passing a zero value, socket mode set to block on */ + unsigned long mode = 0; + ioctlsocket (sock->channel, FIONBIO, &mode); + } +#elif defined(O_NONBLOCK) + { + int flags = fcntl(sock->channel, F_GETFL, 0); + fcntl(sock->channel, F_SETFL, flags & ~O_NONBLOCK); + } +#endif /* WIN32 */ + sock->remoteAddress.host = sock_addr.sin_addr.s_addr; + sock->remoteAddress.port = sock_addr.sin_port; + + sock->sflag = 0; + sock->ready = 0; + + /* The socket is ready */ + return(sock); + +error_return: + SDLNet_TCP_Close(sock); + return(NULL); +} + +/* Get the IP address of the remote system associated with the socket. + If the socket is a server socket, this function returns NULL. +*/ +IPaddress *SDLNet_TCP_GetPeerAddress(TCPsocket sock) +{ + if ( sock->sflag ) { + return(NULL); + } + return(&sock->remoteAddress); +} + +/* Send 'len' bytes of 'data' over the non-server socket 'sock' + This function returns the actual amount of data sent. If the return value + is less than the amount of data sent, then either the remote connection was + closed, or an unknown socket error occurred. +*/ +int SDLNet_TCP_Send(TCPsocket sock, const void *datap, int len) +{ + const Uint8 *data = (const Uint8 *)datap; /* For pointer arithmetic */ + int sent, left; + + /* Server sockets are for accepting connections only */ + if ( sock->sflag ) { + SDLNet_SetError("Server sockets cannot send"); + return(-1); + } + + /* Keep sending data until it's sent or an error occurs */ + left = len; + sent = 0; + SDLNet_SetLastError(0); + do { + len = send(sock->channel, (const char *) data, left, 0); + if ( len > 0 ) { + sent += len; + left -= len; + data += len; + } + } while ( (left > 0) && ((len > 0) || (SDLNet_GetLastError() == EINTR)) ); + + return(sent); +} + +/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock', + and store them in the buffer pointed to by 'data'. + This function returns the actual amount of data received. If the return + value is less than or equal to zero, then either the remote connection was + closed, or an unknown socket error occurred. +*/ +int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen) +{ + int len; + + /* Server sockets are for accepting connections only */ + if ( sock->sflag ) { + SDLNet_SetError("Server sockets cannot receive"); + return(-1); + } + + SDLNet_SetLastError(0); + do { + len = recv(sock->channel, (char *) data, maxlen, 0); + } while ( SDLNet_GetLastError() == EINTR ); + + sock->ready = 0; + return(len); +} + +/* Close a TCP network socket */ +void SDLNet_TCP_Close(TCPsocket sock) +{ + if ( sock != NULL ) { + if ( sock->channel != INVALID_SOCKET ) { + closesocket(sock->channel); + } + free(sock); + } +} diff --git a/libs/SDL_net/SDLnetUDP.c b/libs/SDL_net/SDLnetUDP.c new file mode 100644 index 0000000..b81c00e --- /dev/null +++ b/libs/SDL_net/SDLnetUDP.c @@ -0,0 +1,528 @@ +/* + SDL_net: An example cross-platform network library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* $Id$ */ + +#include "SDLnetsys.h" +#include "SDL_net.h" + +#ifdef __WIN32__ +#define srandom srand +#define random rand +#endif + +struct UDP_channel { + int numbound; + IPaddress address[SDLNET_MAX_UDPADDRESSES]; +}; + +struct _UDPsocket { + int ready; + SOCKET channel; + IPaddress address; + + struct UDP_channel binding[SDLNET_MAX_UDPCHANNELS]; + + /* For debugging purposes */ + int packetloss; +}; + +/* Allocate/free a single UDP packet 'size' bytes long. + The new packet is returned, or NULL if the function ran out of memory. + */ +extern UDPpacket *SDLNet_AllocPacket(int size) +{ + UDPpacket *packet; + int error; + + + error = 1; + packet = (UDPpacket *)malloc(sizeof(*packet)); + if ( packet != NULL ) { + packet->maxlen = size; + packet->data = (Uint8 *)malloc(size); + if ( packet->data != NULL ) { + error = 0; + } + } + if ( error ) { + SDLNet_SetError("Out of memory"); + SDLNet_FreePacket(packet); + packet = NULL; + } + return(packet); +} +int SDLNet_ResizePacket(UDPpacket *packet, int newsize) +{ + Uint8 *newdata; + + newdata = (Uint8 *)malloc(newsize); + if ( newdata != NULL ) { + free(packet->data); + packet->data = newdata; + packet->maxlen = newsize; + } + return(packet->maxlen); +} +extern void SDLNet_FreePacket(UDPpacket *packet) +{ + if ( packet ) { + if ( packet->data ) + free(packet->data); + free(packet); + } +} + +/* Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets, + each 'size' bytes long. + A pointer to the packet array is returned, or NULL if the function ran out + of memory. + */ +UDPpacket **SDLNet_AllocPacketV(int howmany, int size) +{ + UDPpacket **packetV; + + packetV = (UDPpacket **)malloc((howmany+1)*sizeof(*packetV)); + if ( packetV != NULL ) { + int i; + for ( i=0; ichannel = socket(AF_INET, SOCK_DGRAM, 0); + if ( sock->channel == INVALID_SOCKET ) + { + SDLNet_SetError("Couldn't create socket"); + goto error_return; + } + + /* Bind locally, if appropriate */ + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = INADDR_ANY; + sock_addr.sin_port = SDL_SwapBE16(port); + + /* Bind the socket for listening */ + if ( bind(sock->channel, (struct sockaddr *)&sock_addr, + sizeof(sock_addr)) == SOCKET_ERROR ) { + SDLNet_SetError("Couldn't bind to local port"); + goto error_return; + } + + /* Get the bound address and port */ + sock_len = sizeof(sock_addr); + if ( getsockname(sock->channel, (struct sockaddr *)&sock_addr, &sock_len) < 0 ) { +perror("getsockname"); + SDLNet_SetError("Couldn't get socket address"); + goto error_return; + } + + /* Fill in the channel host address */ + sock->address.host = sock_addr.sin_addr.s_addr; + sock->address.port = sock_addr.sin_port; + +#ifdef SO_BROADCAST + /* Allow LAN broadcasts with the socket */ + { int yes = 1; + setsockopt(sock->channel, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(yes)); + } +#endif +#ifdef IP_ADD_MEMBERSHIP + /* Receive LAN multicast packets on 224.0.0.1 + This automatically works on Mac OS X, Linux and BSD, but needs + this code on Windows. + */ + /* A good description of multicast can be found here: + http://www.docs.hp.com/en/B2355-90136/ch05s05.html + */ + /* FIXME: Add support for joining arbitrary groups to the API */ + { + struct ip_mreq g; + + g.imr_multiaddr.s_addr = inet_addr("224.0.0.1"); + g.imr_interface.s_addr = INADDR_ANY; + setsockopt(sock->channel, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (char*)&g, sizeof(g)); + } +#endif + + /* The socket is ready */ + + return(sock); + +error_return: + SDLNet_UDP_Close(sock); + + return(NULL); +} + +void SDLNet_UDP_SetPacketLoss(UDPsocket sock, int percent) +{ + /* FIXME: We may want this behavior to be reproducible + but there isn't a portable reentrant random + number generator with good randomness. + */ + srandom(SDL_GetTicks()); + + if (percent < 0) { + percent = 0; + } else if (percent > 100) { + percent = 100; + } + sock->packetloss = percent; +} + +/* Verify that the channel is in the valid range */ +static int ValidChannel(int channel) +{ + if ( (channel < 0) || (channel >= SDLNET_MAX_UDPCHANNELS) ) { + SDLNet_SetError("Invalid channel"); + return(0); + } + return(1); +} + +/* Bind the address 'address' to the requested channel on the UDP socket. + If the channel is -1, then the first unbound channel will be bound with + the given address as it's primary address. + If the channel is already bound, this new address will be added to the + list of valid source addresses for packets arriving on the channel. + If the channel is not already bound, then the address becomes the primary + address, to which all outbound packets on the channel are sent. + This function returns the channel which was bound, or -1 on error. +*/ +int SDLNet_UDP_Bind(UDPsocket sock, int channel, const IPaddress *address) +{ + struct UDP_channel *binding; + + if ( sock == NULL ) { + SDLNet_SetError("Passed a NULL socket"); + return(-1); + } + + if ( channel == -1 ) { + for ( channel=0; channel < SDLNET_MAX_UDPCHANNELS; ++channel ) { + binding = &sock->binding[channel]; + if ( binding->numbound < SDLNET_MAX_UDPADDRESSES ) { + break; + } + } + } else { + if ( ! ValidChannel(channel) ) { + return(-1); + } + binding = &sock->binding[channel]; + } + if ( binding->numbound == SDLNET_MAX_UDPADDRESSES ) { + SDLNet_SetError("No room for new addresses"); + return(-1); + } + binding->address[binding->numbound++] = *address; + return(channel); +} + +/* Unbind all addresses from the given channel */ +void SDLNet_UDP_Unbind(UDPsocket sock, int channel) +{ + if ( (channel >= 0) && (channel < SDLNET_MAX_UDPCHANNELS) ) { + sock->binding[channel].numbound = 0; + } +} + +/* Get the primary IP address of the remote system associated with the + socket and channel. + If the channel is not bound, this function returns NULL. + */ +IPaddress *SDLNet_UDP_GetPeerAddress(UDPsocket sock, int channel) +{ + IPaddress *address; + + address = NULL; + switch (channel) { + case -1: + /* Return the actual address of the socket */ + address = &sock->address; + break; + default: + /* Return the address of the bound channel */ + if ( ValidChannel(channel) && + (sock->binding[channel].numbound > 0) ) { + address = &sock->binding[channel].address[0]; + } + break; + } + return(address); +} + +/* Send a vector of packets to the the channels specified within the packet. + If the channel specified in the packet is -1, the packet will be sent to + the address in the 'src' member of the packet. + Each packet will be updated with the status of the packet after it has + been sent, -1 if the packet send failed. + This function returns the number of packets sent. +*/ +int SDLNet_UDP_SendV(UDPsocket sock, UDPpacket **packets, int npackets) +{ + int numsent, i, j; + struct UDP_channel *binding; + int status; + int sock_len; + struct sockaddr_in sock_addr; + + if ( sock == NULL ) { + SDLNet_SetError("Passed a NULL socket"); + return(0); + } + + /* Set up the variables to send packets */ + sock_len = sizeof(sock_addr); + + numsent = 0; + for ( i=0; ipacketloss) { + if ((random()%100) <= sock->packetloss) { + packets[i]->status = packets[i]->len; + ++numsent; + continue; + } + } + + /* if channel is < 0, then use channel specified in sock */ + + if ( packets[i]->channel < 0 ) + { + sock_addr.sin_addr.s_addr = packets[i]->address.host; + sock_addr.sin_port = packets[i]->address.port; + sock_addr.sin_family = AF_INET; + status = sendto(sock->channel, + packets[i]->data, packets[i]->len, 0, + (struct sockaddr *)&sock_addr,sock_len); + if ( status >= 0 ) + { + packets[i]->status = status; + ++numsent; + } + } + else + { + /* Send to each of the bound addresses on the channel */ +#ifdef DEBUG_NET + printf("SDLNet_UDP_SendV sending packet to channel = %d\n", packets[i]->channel ); +#endif + + binding = &sock->binding[packets[i]->channel]; + + for ( j=binding->numbound-1; j>=0; --j ) + { + sock_addr.sin_addr.s_addr = binding->address[j].host; + sock_addr.sin_port = binding->address[j].port; + sock_addr.sin_family = AF_INET; + status = sendto(sock->channel, + packets[i]->data, packets[i]->len, 0, + (struct sockaddr *)&sock_addr,sock_len); + if ( status >= 0 ) + { + packets[i]->status = status; + ++numsent; + } + } + } + } + + return(numsent); +} + +int SDLNet_UDP_Send(UDPsocket sock, int channel, UDPpacket *packet) +{ + /* This is silly, but... */ + packet->channel = channel; + return(SDLNet_UDP_SendV(sock, &packet, 1)); +} + +/* Returns true if a socket is has data available for reading right now */ +static int SocketReady(SOCKET sock) +{ + int retval = 0; + struct timeval tv; + fd_set mask; + + /* Check the file descriptors for available data */ + do { + SDLNet_SetLastError(0); + + /* Set up the mask of file descriptors */ + FD_ZERO(&mask); + FD_SET(sock, &mask); + + /* Set up the timeout */ + tv.tv_sec = 0; + tv.tv_usec = 0; + + /* Look! */ + retval = select(sock+1, &mask, NULL, NULL, &tv); + } while ( SDLNet_GetLastError() == EINTR ); + + return(retval == 1); +} + +/* Receive a vector of pending packets from the UDP socket. + The returned packets contain the source address and the channel they arrived + on. If they did not arrive on a bound channel, the the channel will be set + to -1. + This function returns the number of packets read from the network, or -1 + on error. This function does not block, so can return 0 packets pending. +*/ +extern int SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packets) +{ + int numrecv, i, j; + struct UDP_channel *binding; + socklen_t sock_len; + struct sockaddr_in sock_addr; + + if ( sock == NULL ) { + return(0); + } + + numrecv = 0; + while ( packets[numrecv] && SocketReady(sock->channel) ) + { + UDPpacket *packet; + + packet = packets[numrecv]; + + sock_len = sizeof(sock_addr); + packet->status = recvfrom(sock->channel, + packet->data, packet->maxlen, 0, + (struct sockaddr *)&sock_addr, + &sock_len); + if ( packet->status >= 0 ) { + packet->len = packet->status; + packet->address.host = sock_addr.sin_addr.s_addr; + packet->address.port = sock_addr.sin_port; + packet->channel = -1; + + for (i=(SDLNET_MAX_UDPCHANNELS-1); i>=0; --i ) + { + binding = &sock->binding[i]; + + for ( j=binding->numbound-1; j>=0; --j ) + { + if ( (packet->address.host == binding->address[j].host) && + (packet->address.port == binding->address[j].port) ) + { + packet->channel = i; + goto foundit; /* break twice */ + } + } + } +foundit: + ++numrecv; + } + + else + { + packet->len = 0; + } + } + + sock->ready = 0; + + return(numrecv); +} + +/* Receive a single packet from the UDP socket. + The returned packet contains the source address and the channel it arrived + on. If it did not arrive on a bound channel, the the channel will be set + to -1. + This function returns the number of packets read from the network, or -1 + on error. This function does not block, so can return 0 packets pending. +*/ +int SDLNet_UDP_Recv(UDPsocket sock, UDPpacket *packet) +{ + UDPpacket *packets[2]; + + /* Receive a packet array of 1 */ + packets[0] = packet; + packets[1] = NULL; + return(SDLNet_UDP_RecvV(sock, packets)); +} + +/* Close a UDP network socket */ +extern void SDLNet_UDP_Close(UDPsocket sock) +{ + if ( sock != NULL ) + { + if ( sock->channel != INVALID_SOCKET ) + { + closesocket(sock->channel); + } + + free(sock); + } +} + diff --git a/libs/SDL_net/SDLnetselect.c b/libs/SDL_net/SDLnetselect.c new file mode 100644 index 0000000..e14e0c3 --- /dev/null +++ b/libs/SDL_net/SDLnetselect.c @@ -0,0 +1,163 @@ +/* + SDL_net: An example cross-platform network library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* $Id$ */ + +#include "SDLnetsys.h" +#include "SDL_net.h" + +/* The select() API for network sockets */ + +struct SDLNet_Socket { + int ready; + SOCKET channel; +}; + +struct _SDLNet_SocketSet { + int numsockets; + int maxsockets; + struct SDLNet_Socket **sockets; +}; + +/* Allocate a socket set for use with SDLNet_CheckSockets() + This returns a socket set for up to 'maxsockets' sockets, or NULL if + the function ran out of memory. + */ +SDLNet_SocketSet SDLNet_AllocSocketSet(int maxsockets) +{ + struct _SDLNet_SocketSet *set; + int i; + + set = (struct _SDLNet_SocketSet *)malloc(sizeof(*set)); + if ( set != NULL ) { + set->numsockets = 0; + set->maxsockets = maxsockets; + set->sockets = (struct SDLNet_Socket **)malloc + (maxsockets*sizeof(*set->sockets)); + if ( set->sockets != NULL ) { + for ( i=0; isockets[i] = NULL; + } + } else { + free(set); + set = NULL; + } + } + return(set); +} + +/* Add a socket to a set of sockets to be checked for available data */ +int SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock) +{ + if ( sock != NULL ) { + if ( set->numsockets == set->maxsockets ) { + SDLNet_SetError("socketset is full"); + return(-1); + } + set->sockets[set->numsockets++] = (struct SDLNet_Socket *)sock; + } + return(set->numsockets); +} + +/* Remove a socket from a set of sockets to be checked for available data */ +int SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock) +{ + int i; + + if ( sock != NULL ) { + for ( i=0; inumsockets; ++i ) { + if ( set->sockets[i] == (struct SDLNet_Socket *)sock ) { + break; + } + } + if ( i == set->numsockets ) { + SDLNet_SetError("socket not found in socketset"); + return(-1); + } + --set->numsockets; + for ( ; inumsockets; ++i ) { + set->sockets[i] = set->sockets[i+1]; + } + } + return(set->numsockets); +} + +/* This function checks to see if data is available for reading on the + given set of sockets. If 'timeout' is 0, it performs a quick poll, + otherwise the function returns when either data is available for + reading, or the timeout in milliseconds has elapsed, which ever occurs + first. This function returns the number of sockets ready for reading, + or -1 if there was an error with the select() system call. +*/ +int SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout) +{ + int i; + SOCKET maxfd; + int retval; + struct timeval tv; + fd_set mask; + + /* Find the largest file descriptor */ + maxfd = 0; + for ( i=set->numsockets-1; i>=0; --i ) { + if ( set->sockets[i]->channel > maxfd ) { + maxfd = set->sockets[i]->channel; + } + } + + /* Check the file descriptors for available data */ + do { + SDLNet_SetLastError(0); + + /* Set up the mask of file descriptors */ + FD_ZERO(&mask); + for ( i=set->numsockets-1; i>=0; --i ) { + FD_SET(set->sockets[i]->channel, &mask); + } + + /* Set up the timeout */ + tv.tv_sec = timeout/1000; + tv.tv_usec = (timeout%1000)*1000; + + /* Look! */ + retval = select(maxfd+1, &mask, NULL, NULL, &tv); + } while ( SDLNet_GetLastError() == EINTR ); + + /* Mark all file descriptors ready that have data available */ + if ( retval > 0 ) { + for ( i=set->numsockets-1; i>=0; --i ) { + if ( FD_ISSET(set->sockets[i]->channel, &mask) ) { + set->sockets[i]->ready = 1; + } + } + } + return(retval); +} + +/* Free a set of sockets allocated by SDL_NetAllocSocketSet() */ +extern void SDLNet_FreeSocketSet(SDLNet_SocketSet set) +{ + if ( set ) { + free(set->sockets); + free(set); + } +} + diff --git a/libs/SDL_net/SDLnetsys.h b/libs/SDL_net/SDLnetsys.h new file mode 100644 index 0000000..b5cd95b --- /dev/null +++ b/libs/SDL_net/SDLnetsys.h @@ -0,0 +1,94 @@ +/* + SDL_net: An example cross-platform network library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* $Id$ */ + +/* Include normal system headers */ +#include +#include +#include + +#ifndef _WIN32_WCE +#include +#endif + +/* Include system network headers */ +#if defined(__WIN32__) || defined(WIN32) +#define __USE_W32_SOCKETS +#ifdef _WIN64 +#include +#include +#else +#include +/* NOTE: windows socklen_t is signed + * and is defined only for winsock2. */ +typedef int socklen_t; +#endif /* W64 */ +#include +#else /* UNIX */ +#include +#ifdef __FreeBSD__ +#include +#endif +#include +#include +#include +#include +#include +#ifndef __BEOS__ +#include +#endif +#ifdef linux /* FIXME: what other platforms have this? */ +#include +#endif +#include +#include +#include +#endif /* WIN32 */ + +/* FIXME: What platforms need this? */ +#if 0 +typedef Uint32 socklen_t; +#endif + +/* System-dependent definitions */ +#ifndef __USE_W32_SOCKETS +#ifdef __OS2__ +#define closesocket soclose +#else /* !__OS2__ */ +#define closesocket close +#endif /* __OS2__ */ +#define SOCKET int +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#endif /* __USE_W32_SOCKETS */ + +#ifdef __USE_W32_SOCKETS +#define SDLNet_GetLastError WSAGetLastError +#define SDLNet_SetLastError WSASetLastError +#ifndef EINTR +#define EINTR WSAEINTR +#endif +#else +int SDLNet_GetLastError(void); +void SDLNet_SetLastError(int err); +#endif + diff --git a/libs/SDL_net/makefile b/libs/SDL_net/makefile new file mode 100644 index 0000000..796541b --- /dev/null +++ b/libs/SDL_net/makefile @@ -0,0 +1,37 @@ +#config +INCLUDES= +CFLAGS+=$(addprefix -I,$(INCLUDES)) +LIB= + +#source +SRC=$(wildcard *.c) + +#objects +OBJDIR=obj +OBJ=$(addprefix $(OBJDIR)/,$(SRC:.c=.o)) + +#output +OUTDIR=../out +OUT=$(addprefix $(OUTDIR)/,libSDL_net.a) + +#targets +all: $(OBJ) $(OUT) + ar -crs $(OUT) $(OBJ) + +$(OBJ): | $(OBJDIR) + +$(OUT): | $(OUTDIR) + +$(OBJDIR): + mkdir $(OBJDIR) + +$(OUTDIR): + mkdir $(OUTDIR) + +$(OBJDIR)/%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + $(RM) *.o *.a *.exe + +rebuild: clean all \ No newline at end of file diff --git a/libs/makefile b/libs/makefile new file mode 100644 index 0000000..8599d44 --- /dev/null +++ b/libs/makefile @@ -0,0 +1,13 @@ +OUTDIR=out + +all: $(OUTDIR) + $(MAKE) -C codebase + $(MAKE) -C SDL_net + +$(OUTDIR): + mkdir $(OUTDIR) + +clean: + $(RM) *.o *.a *.exe + +rebuild: clean all diff --git a/makefile b/makefile new file mode 100644 index 0000000..e18e99b --- /dev/null +++ b/makefile @@ -0,0 +1,7 @@ +all: + $(MAKE) -C libs + +clean: + $(RM) *.o *.a *.exe + +rebuild: clean all