mirror of
https://gitlab.com/Nanolx/homebrewfilter.git
synced 2024-11-01 07:05:10 +01:00
remove all network code from installer
This commit is contained in:
parent
a91b71105b
commit
fbeb63b582
@ -18,7 +18,6 @@ include $(DEVKITPPC)/wii_rules
|
||||
TARGET := installer
|
||||
BUILD := build
|
||||
SOURCES := source \
|
||||
source/Network \
|
||||
../svnrev
|
||||
DATA := data
|
||||
INCLUDES :=
|
||||
|
@ -1,122 +0,0 @@
|
||||
#include "dns.h"
|
||||
|
||||
/**
|
||||
* Resolves a domainname to an ip address
|
||||
* It makes use of net_gethostbyname from libogc, which in turn makes use of a Wii BIOS function
|
||||
* Just like the net_gethostbyname function this function is NOT threadsafe!
|
||||
*
|
||||
* @param char* The domain name to resolve
|
||||
* @return u32 The ipaddress represented by four bytes inside an u32 (in network order)
|
||||
*/
|
||||
u32 getipbyname(char *domain)
|
||||
{
|
||||
//Care should be taken when using net_gethostbyname,
|
||||
//it returns a static buffer which makes it not threadsafe
|
||||
//TODO: implement some locking mechanism to make below code atomic
|
||||
struct hostent *host = net_gethostbyname(domain);
|
||||
|
||||
if(host == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 *ip = (u32*)host->h_addr_list[0];
|
||||
return *ip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Defines how many DNS entries should be cached by getipbynamecached()
|
||||
#define MAX_DNS_CACHE_ENTRIES 20
|
||||
|
||||
//The cache is defined as a linked list,
|
||||
//The last resolved domain name will always be at the front
|
||||
//This will allow heavily used domainnames to always stay cached
|
||||
struct dnsentry {
|
||||
char *domain;
|
||||
u32 ip;
|
||||
struct dnsentry *nextnode;
|
||||
} ;
|
||||
|
||||
static struct dnsentry *firstdnsentry = NULL;
|
||||
static int dnsentrycount = 0;
|
||||
|
||||
/**
|
||||
* Performs the same function as getipbyname(),
|
||||
* except that it will prevent extremely expensive net_gethostbyname() calls by caching the result
|
||||
*/
|
||||
u32 getipbynamecached(char *domain)
|
||||
{
|
||||
//Search if this domainname is already cached
|
||||
struct dnsentry *node = firstdnsentry;
|
||||
struct dnsentry *previousnode = NULL;
|
||||
|
||||
while(node != NULL)
|
||||
{
|
||||
if(strcmp(node->domain, domain) == 0)
|
||||
{
|
||||
//DNS node found in the cache, move it to the front of the list
|
||||
if(previousnode != NULL)
|
||||
previousnode->nextnode = node->nextnode;
|
||||
|
||||
if(node != firstdnsentry)
|
||||
node->nextnode = firstdnsentry;
|
||||
firstdnsentry = node;
|
||||
|
||||
return node->ip;
|
||||
}
|
||||
//Go to the next element in the list
|
||||
previousnode = node;
|
||||
node = node->nextnode;
|
||||
}
|
||||
u32 ip = getipbyname(domain);
|
||||
|
||||
//No cache of this domain could be found, create a cache node and add it to the front of the cache
|
||||
struct dnsentry *newnode = malloc(sizeof(struct dnsentry));
|
||||
if(newnode == NULL) {
|
||||
return ip;
|
||||
}
|
||||
|
||||
newnode->ip = ip;
|
||||
newnode->domain = malloc(strlen(domain)+1);
|
||||
if(newnode->domain == NULL)
|
||||
{
|
||||
free(newnode);
|
||||
return ip;
|
||||
}
|
||||
strcpy(newnode->domain, domain);
|
||||
|
||||
newnode->nextnode = firstdnsentry;
|
||||
firstdnsentry = newnode;
|
||||
dnsentrycount++;
|
||||
|
||||
//If the cache grows too big delete the last (and probably least important) node of the list
|
||||
if(dnsentrycount > MAX_DNS_CACHE_ENTRIES)
|
||||
{
|
||||
struct dnsentry *node = firstdnsentry;
|
||||
struct dnsentry *previousnode = NULL;
|
||||
|
||||
//Fetch the last two elements of the list
|
||||
while(node->nextnode != NULL)
|
||||
{
|
||||
previousnode = node;
|
||||
node = node->nextnode;
|
||||
}
|
||||
|
||||
if(node == NULL)
|
||||
{
|
||||
printf("Configuration error, MAX_DNS_ENTRIES reached while the list is empty\n");
|
||||
exit(1);
|
||||
} else if(previousnode == NULL)
|
||||
{
|
||||
firstdnsentry = NULL;
|
||||
} else {
|
||||
previousnode->nextnode = NULL;
|
||||
}
|
||||
|
||||
free(node->domain);
|
||||
free(node);
|
||||
dnsentrycount--;
|
||||
}
|
||||
|
||||
return newnode->ip;
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
#ifndef _DNS_H_
|
||||
#define _DNS_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h> //usleep
|
||||
|
||||
#include <network.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
u32 getipbyname(char *domain);
|
||||
u32 getipbynamecached(char *domain);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DNS_H_ */
|
@ -1,256 +0,0 @@
|
||||
#include "http.h"
|
||||
|
||||
/**
|
||||
* Emptyblock is a statically defined variable for functions to return if they are unable
|
||||
* to complete a request
|
||||
*/
|
||||
const struct block emptyblock = {0, NULL};
|
||||
|
||||
//The maximum amount of bytes to send per net_write() call
|
||||
#define NET_BUFFER_SIZE 1024
|
||||
|
||||
// Write our message to the server
|
||||
static s32 send_message(s32 server, char *msg) {
|
||||
s32 bytes_transferred = 0;
|
||||
s32 remaining = strlen(msg);
|
||||
while (remaining) {
|
||||
if ((bytes_transferred = net_write(server, msg, remaining > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : remaining)) > 0) {
|
||||
remaining -= bytes_transferred;
|
||||
usleep (20 * 1000);
|
||||
} else if (bytes_transferred < 0) {
|
||||
return bytes_transferred;
|
||||
} else {
|
||||
return -ENODATA;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a remote server via TCP on a specified port
|
||||
*
|
||||
* @param u32 ip address of the server to connect to
|
||||
* @param u32 the port to connect to on the server
|
||||
* @return s32 The connection to the server (negative number if connection could not be established)
|
||||
*/
|
||||
static s32 server_connect(u32 ipaddress, u32 socket_port) {
|
||||
//Initialize socket
|
||||
s32 connection = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
||||
if (connection < 0) return connection;
|
||||
|
||||
struct sockaddr_in connect_addr;
|
||||
memset(&connect_addr, 0, sizeof(connect_addr));
|
||||
connect_addr.sin_family = AF_INET;
|
||||
connect_addr.sin_port = socket_port;
|
||||
connect_addr.sin_addr.s_addr= ipaddress;
|
||||
|
||||
//Attemt to open the socket
|
||||
if (net_connect(connection, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) == -1) {
|
||||
net_close(connection);
|
||||
return -1;
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
//The amount of memory in bytes reserved initially to store the HTTP response in
|
||||
//Be careful in increasing this number, reading from a socket on the Wii
|
||||
//will fail if you request more than 20k or so
|
||||
#define HTTP_BUFFER_SIZE 1024 * 5
|
||||
|
||||
//The amount of memory the buffer should expanded with if the buffer is full
|
||||
#define HTTP_BUFFER_GROWTH 1024 * 5
|
||||
|
||||
/**
|
||||
* This function reads all the data from a connection into a buffer which it returns.
|
||||
* It will return an empty buffer if something doesn't go as planned
|
||||
*
|
||||
* @param s32 connection The connection identifier to suck the response out of
|
||||
* @return block A 'block' struct (see http.h) in which the buffer is located
|
||||
*/
|
||||
struct block read_message(s32 connection)
|
||||
{
|
||||
//Create a block of memory to put in the response
|
||||
struct block buffer;
|
||||
buffer.data = malloc(HTTP_BUFFER_SIZE);
|
||||
buffer.size = HTTP_BUFFER_SIZE;
|
||||
|
||||
if(buffer.data == NULL) {
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//The offset variable always points to the first byte of memory that is free in the buffer
|
||||
u32 offset = 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
//Fill the buffer with a new batch of bytes from the connection,
|
||||
//starting from where we left of in the buffer till the end of the buffer
|
||||
s32 bytes_read = net_read(connection, buffer.data + offset, buffer.size - offset);
|
||||
|
||||
//Anything below 0 is an error in the connection
|
||||
if(bytes_read < 0)
|
||||
{
|
||||
//printf("Connection error from net_read() Errorcode: %i\n", bytes_read);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//No more bytes were read into the buffer,
|
||||
//we assume this means the HTTP response is done
|
||||
if(bytes_read == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
offset += bytes_read;
|
||||
|
||||
//Check if we have enough buffer left over,
|
||||
//if not expand it with an additional HTTP_BUFFER_GROWTH worth of bytes
|
||||
if(offset >= buffer.size)
|
||||
{
|
||||
buffer.size += HTTP_BUFFER_GROWTH;
|
||||
buffer.data = realloc(buffer.data, buffer.size);
|
||||
|
||||
if(buffer.data == NULL)
|
||||
{
|
||||
return emptyblock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//At the end of above loop offset should be precisely the amount of bytes that were read from the connection
|
||||
buffer.size = offset;
|
||||
|
||||
//Shrink the size of the buffer so the data fits exactly in it
|
||||
realloc(buffer.data, buffer.size);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the contents of a URL to memory
|
||||
* This method is not threadsafe (because networking is not threadsafe on the Wii)
|
||||
*/
|
||||
struct block downloadfile(const char *url)
|
||||
{
|
||||
//Check if the url starts with "http://", if not it is not considered a valid url
|
||||
if(strncmp(url, "http://", strlen("http://")) != 0)
|
||||
{
|
||||
//printf("URL '%s' doesn't start with 'http://'\n", url);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//Locate the path part of the url by searching for '/' past "http://"
|
||||
char *path = strchr(url + strlen("http://"), '/');
|
||||
|
||||
//At the very least the url has to end with '/', ending with just a domain is invalid
|
||||
if(path == NULL)
|
||||
{
|
||||
//printf("URL '%s' has no PATH part\n", url);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//Extract the domain part out of the url
|
||||
int domainlength = path - url - strlen("http://");
|
||||
|
||||
if(domainlength == 0)
|
||||
{
|
||||
//printf("No domain part in URL '%s'\n", url);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
char domain[domainlength + 1];
|
||||
strncpy(domain, url + strlen("http://"), domainlength);
|
||||
domain[domainlength] = '\0';
|
||||
|
||||
//Parsing of the URL is done, start making an actual connection
|
||||
u32 ipaddress = getipbynamecached(domain);
|
||||
|
||||
if(ipaddress == 0)
|
||||
{
|
||||
//printf("\ndomain %s could not be resolved", domain);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
|
||||
s32 connection = server_connect(ipaddress, 80);
|
||||
|
||||
if(connection < 0) {
|
||||
//printf("Error establishing connection");
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//Form a nice request header to send to the webserver
|
||||
char* headerformat = "GET %s HTTP/1.0\r\nHost: %s\r\nReferer: %s\r\nCache-Control: no-cache\r\n\r\n";
|
||||
char header[strlen(headerformat) + strlen(path) + strlen(domain)*2 + 1];
|
||||
sprintf(header, headerformat, path, domain, domain);
|
||||
|
||||
//Do the request and get the response
|
||||
send_message(connection, header);
|
||||
struct block response = read_message(connection);
|
||||
net_close(connection);
|
||||
|
||||
//Search for the 4-character sequence \r\n\r\n in the response which signals the start of the http payload (file)
|
||||
unsigned char *filestart = NULL;
|
||||
u32 filesize = 0;
|
||||
int i;
|
||||
for(i = 3; i < response.size; i++)
|
||||
{
|
||||
if(response.data[i] == '\n' &&
|
||||
response.data[i-1] == '\r' &&
|
||||
response.data[i-2] == '\n' &&
|
||||
response.data[i-3] == '\r' &&
|
||||
response.data[9] == 50 ) // hamachi-mp.bplaced.net / 50 vorhanden | 52 nicht vorhanden
|
||||
{
|
||||
filestart = response.data + i + 1;
|
||||
filesize = response.size - i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(filestart == NULL)
|
||||
{
|
||||
//printf("HTTP Response was without a file\n");
|
||||
free(response.data);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
//Copy the file part of the response into a new memoryblock to return
|
||||
struct block file;
|
||||
file.data = malloc(filesize);
|
||||
file.size = filesize;
|
||||
|
||||
if(file.data == NULL)
|
||||
{
|
||||
//printf("No more memory to copy file from HTTP response\n");
|
||||
free(response.data);
|
||||
return emptyblock;
|
||||
}
|
||||
|
||||
memcpy(file.data, filestart, filesize);
|
||||
|
||||
//Dispose of the original response
|
||||
free(response.data);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
int network_read(int connection, u8 *buf, u32 len)
|
||||
{
|
||||
u32 read = 0;
|
||||
s32 ret = -1;
|
||||
|
||||
while (read < len)
|
||||
{
|
||||
ret = net_read(connection, buf + read, len - read);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!ret)
|
||||
break;
|
||||
|
||||
read += ret;
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#ifndef _HTTP_H_
|
||||
#define _HTTP_H_
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "dns.h"
|
||||
|
||||
/**
|
||||
* A simple structure to keep track of the size of a malloc()ated block of memory
|
||||
*/
|
||||
struct block
|
||||
{
|
||||
u32 size;
|
||||
unsigned char *data;
|
||||
};
|
||||
|
||||
extern const struct block emptyblock;
|
||||
|
||||
struct block downloadfile(const char *url);
|
||||
|
||||
int network_read(int connection, u8 *buf, u32 len);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _HTTP_H_ */
|
@ -1,187 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009
|
||||
* by Dimok
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* networkops.cpp
|
||||
*
|
||||
* Network operations
|
||||
* for Wii-Xplorer 2009
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ogcsys.h>
|
||||
#include <ogc/machine/processor.h>
|
||||
|
||||
#include "http.h"
|
||||
#include <malloc.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//static NetReceiver Receiver;
|
||||
static bool networkinit = false;
|
||||
static bool networkerror = false;
|
||||
static char IP[16];
|
||||
static u8 * ThreadStack = NULL;
|
||||
static bool firstRun = false;
|
||||
|
||||
static lwp_t networkthread = LWP_THREAD_NULL;
|
||||
static bool networkHalt = true;
|
||||
static bool exitRequested = false;
|
||||
|
||||
/****************************************************************************
|
||||
* Initialize_Network
|
||||
***************************************************************************/
|
||||
void Initialize_Network(void)
|
||||
{
|
||||
if(networkinit)
|
||||
return;
|
||||
|
||||
s32 result;
|
||||
|
||||
result = if_config(IP, NULL, NULL, true);
|
||||
|
||||
if(result < 0) {
|
||||
networkinit = false;
|
||||
networkerror = true;
|
||||
return;
|
||||
}
|
||||
|
||||
networkinit = true;
|
||||
networkerror = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DeInit_Network
|
||||
***************************************************************************/
|
||||
void DeInit_Network(void)
|
||||
{
|
||||
net_deinit();
|
||||
}
|
||||
/****************************************************************************
|
||||
* Check if network was initialised
|
||||
***************************************************************************/
|
||||
bool IsNetworkInit(void)
|
||||
{
|
||||
return networkinit;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Check that network has error
|
||||
***************************************************************************/
|
||||
bool IsNetworkError(void)
|
||||
{
|
||||
return networkerror;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Get network IP
|
||||
***************************************************************************/
|
||||
char * GetNetworkIP(void)
|
||||
{
|
||||
return IP;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* HaltNetwork
|
||||
***************************************************************************/
|
||||
void HaltNetworkThread()
|
||||
{
|
||||
networkHalt = true;
|
||||
|
||||
// wait for thread to finish
|
||||
while(!LWP_ThreadIsSuspended(networkthread))
|
||||
{
|
||||
usleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ResumeNetworkThread
|
||||
***************************************************************************/
|
||||
void ResumeNetworkThread()
|
||||
{
|
||||
networkHalt = false;
|
||||
LWP_ResumeThread(networkthread);
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
* Networkthread for background network initialize and update check with idle prio
|
||||
*********************************************************************************/
|
||||
static void * networkinitcallback(void *arg)
|
||||
{
|
||||
while(!exitRequested)
|
||||
{
|
||||
if(networkHalt)
|
||||
{
|
||||
LWP_SuspendThread(networkthread);
|
||||
usleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!networkinit)
|
||||
Initialize_Network();
|
||||
|
||||
if(!firstRun)
|
||||
{
|
||||
LWP_SetThreadPriority(networkthread, 0);
|
||||
firstRun = true;
|
||||
}
|
||||
|
||||
usleep(200000);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* InitNetworkThread with priority 0 (idle)
|
||||
***************************************************************************/
|
||||
void InitNetworkThread()
|
||||
{
|
||||
ThreadStack = (u8 *) memalign(32, 16384);
|
||||
if(!ThreadStack)
|
||||
return;
|
||||
|
||||
LWP_CreateThread (&networkthread, networkinitcallback, NULL, ThreadStack, 16384, 30);
|
||||
ResumeNetworkThread();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ShutdownThread
|
||||
***************************************************************************/
|
||||
void ShutdownNetworkThread()
|
||||
{
|
||||
exitRequested = true;
|
||||
networkinit = false;
|
||||
networkerror = false;
|
||||
|
||||
if(networkthread != LWP_THREAD_NULL)
|
||||
{
|
||||
ResumeNetworkThread();
|
||||
LWP_JoinThread (networkthread, NULL);
|
||||
networkthread = LWP_THREAD_NULL;
|
||||
}
|
||||
|
||||
if(ThreadStack)
|
||||
free(ThreadStack);
|
||||
ThreadStack = NULL;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2010
|
||||
* by Dimok
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* for WiiXplorer 2010
|
||||
***************************************************************************/
|
||||
#ifndef _NETWORKOPS_H_
|
||||
#define _NETWORKOPS_H_
|
||||
|
||||
void Initialize_Network(void);
|
||||
void DeInit_Network(void);
|
||||
bool IsNetworkInit(void);
|
||||
bool IsNetworkError(void);
|
||||
char * GetNetworkIP(void);
|
||||
void HaltNetworkThread();
|
||||
void ResumeNetworkThread();
|
||||
void InitNetworkThread();
|
||||
void ShutdownNetworkThread();
|
||||
|
||||
#endif
|
@ -6,7 +6,6 @@
|
||||
#include "menu.h"
|
||||
#include "video.h"
|
||||
#include "wad.h"
|
||||
#include "Network/network.h"
|
||||
|
||||
#define HAVE_AHBPROT ((*(vu32*)0xcd800064 == 0xFFFFFFFF) ? 1 : 0)
|
||||
|
||||
@ -15,7 +14,6 @@ int main(int argc, char **argv) {
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
// Initialise the video system
|
||||
InitNetworkThread();
|
||||
VIDEO_Init();
|
||||
Video_SetMode();
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "title.h"
|
||||
#include "video.h"
|
||||
#include "wad.h"
|
||||
#include "Network/http.h"
|
||||
#include "../../svnrev/svnrev.h"
|
||||
|
||||
#define round_up(x,n) (-(-(x) & -(n)))
|
||||
|
Loading…
Reference in New Issue
Block a user