added cl_layershot. fixed some bugs in the network

This commit is contained in:
Magnus Auvinen 2008-08-17 07:05:16 +00:00
parent d1282138cd
commit 16912026db
14 changed files with 457 additions and 464 deletions

View file

@ -36,6 +36,15 @@ if "client_content_source" in sys.argv: gen_client_content_source = True
if "server_content_header" in sys.argv: gen_server_content_header = True
if "server_content_source" in sys.argv: gen_server_content_source = True
if gen_client_content_header:
print "#ifndef CLIENT_CONTENT_HEADER"
print "#define CLIENT_CONTENT_HEADER"
if gen_server_content_header:
print "#ifndef SERVER_CONTENT_HEADER"
print "#define SERVER_CONTENT_HEADER"
if gen_client_content_header or gen_server_content_header:
# emit the type declarations
contentlines = file("datasrc/content.py").readlines()
@ -210,3 +219,5 @@ if gen_network_source:
for l in lines:
print l
if gen_client_content_header or gen_server_content_header:
print "#endif"

View file

@ -302,7 +302,10 @@ function build(settings)
masterserver = Compile(settings, Collect("src/mastersrv/*.cpp"))
game_shared = Compile(settings, Collect("src/game/*.cpp"), nethash, network_source)
game_client = Compile(settings, Collect("src/game/client/*.cpp"), client_content_source)
game_server = Compile(settings, Collect("src/game/server/*.cpp"), server_content_source)
game_server = Compile(settings, Collect(
"src/game/server/*.cpp",
"src/game/server/entities/*.cpp",
"src/game/server/gamemodes/*.cpp"), server_content_source)
game_editor = Compile(settings, Collect("src/game/editor/*.cpp"))
-- build tools (TODO: fix this so we don't get double _d_d stuff)

View file

@ -479,6 +479,7 @@ static void sockaddr_to_netaddr(const struct sockaddr *src, NETADDR *dst)
{
/* TODO: IPv6 support */
unsigned int ip = htonl(((struct sockaddr_in*)src)->sin_addr.s_addr);
mem_zero(dst, sizeof(NETADDR));
dst->type = NETTYPE_IPV4;
dst->port = htons(((struct sockaddr_in*)src)->sin_port);
dst->ip[0] = (unsigned char)((ip>>24)&0xFF);
@ -492,6 +493,21 @@ int net_addr_comp(const NETADDR *a, const NETADDR *b)
return mem_comp(a, b, sizeof(NETADDR));
}
void net_addr_str(const NETADDR *addr, char *string, int max_length)
{
if(addr->type == NETTYPE_IPV4)
str_format(string, max_length, "%d.%d.%d.%d:%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3], addr->port);
else if(addr->type == NETTYPE_IPV6)
{
str_format(string, max_length, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d",
(addr->ip[0]<<8)|addr->ip[1], (addr->ip[2]<<8)|addr->ip[3], (addr->ip[4]<<8)|addr->ip[5], (addr->ip[6]<<8)|addr->ip[7],
(addr->ip[8]<<8)|addr->ip[9], (addr->ip[10]<<8)|addr->ip[11], (addr->ip[12]<<8)|addr->ip[13], (addr->ip[14]<<8)|addr->ip[15],
addr->port);
}
else
str_format(string, max_length, "unknown type %d", addr->type);
}
int net_host_lookup(const char *hostname, NETADDR *addr, int types)
{
/* TODO: IPv6 support */
@ -554,7 +570,16 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size
netaddr_to_sockaddr(addr, &sa);
d = sendto((int)sock, (const char*)data, size, 0, &sa, sizeof(sa));
if(d < 0)
{
char addrstr[256];
net_addr_str(addr, addrstr, sizeof(addrstr));
dbg_msg("net", "sendto error %d %x", d, d);
dbg_msg("net", "\tsock = %d %x", sock, sock);
dbg_msg("net", "\tsize = %d %x", size, size);
dbg_msg("net", "\taddr = %s", addrstr);
}
network_stats.sent_bytes += size;
network_stats.sent_packets++;
return d;

View file

@ -478,7 +478,7 @@ int net_addr_comp(const NETADDR *a, const NETADDR *b);
- The string will always be zero terminated
*/
int net_addr_str(const NETADDR *addr, char *string, int max_length);
void net_addr_str(const NETADDR *addr, char *string, int max_length);
/* Group: Network UDP */

View file

@ -168,7 +168,7 @@ int gfx_init()
/* open window */
if(config.gfx_fullscreen)
{
int result = glfwOpenWindow(screen_width, screen_height, 8, 8, 8, 0, 24, 0, GLFW_FULLSCREEN);
int result = glfwOpenWindow(screen_width, screen_height, 8, 8, 8, config.gfx_alphabits, 24, 0, GLFW_FULLSCREEN);
if(result != GL_TRUE)
{
dbg_msg("game", "failed to create gl context");
@ -177,7 +177,7 @@ int gfx_init()
}
else
{
int result = glfwOpenWindow(screen_width, screen_height, 0, 0, 0, 0, 24, 0, GLFW_WINDOW);
int result = glfwOpenWindow(screen_width, screen_height, 0, 0, 0, 8, 24, 0, GLFW_WINDOW);
if(result != GL_TRUE)
{
dbg_msg("game", "failed to create gl context");
@ -600,28 +600,10 @@ void gfx_swap()
if(do_screenshot)
{
/* fetch image data */
int y;
int w = screen_width;
int h = screen_height;
unsigned char *pixel_data = (unsigned char *)mem_alloc(w*(h+1)*3, 1);
unsigned char *temp_row = pixel_data+w*h*3;
glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixel_data);
/* flip the pixel because opengl works from bottom left corner */
for(y = 0; y < h/2; y++)
{
mem_copy(temp_row, pixel_data+y*w*3, w*3);
mem_copy(pixel_data+y*w*3, pixel_data+(h-y-1)*w*3, w*3);
mem_copy(pixel_data+(h-y-1)*w*3, temp_row,w*3);
}
/* find filename */
{
char wholepath[1024];
char filename[128];
static int index = 1;
png_t png;
for(; index < 1000; index++)
{
@ -636,15 +618,8 @@ void gfx_swap()
break;
}
/* save png */
dbg_msg("client", "saved screenshot to '%s'", wholepath);
png_open_file_write(&png, wholepath);
png_set_data(&png, w, h, 8, PNG_TRUECOLOR, (unsigned char *)pixel_data);
png_close_file(&png);
}
gfx_screenshot_direct(filename);
/* clean up */
mem_free(pixel_data);
do_screenshot = 0;
}
@ -666,6 +641,42 @@ void gfx_swap()
}
}
void gfx_screenshot_direct(const char *filename)
{
/* fetch image data */
int y;
int w = screen_width;
int h = screen_height;
unsigned char *pixel_data = (unsigned char *)mem_alloc(w*(h+1)*4, 1);
unsigned char *temp_row = pixel_data+w*h*4;
glReadPixels(0,0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixel_data);
/* flip the pixel because opengl works from bottom left corner */
for(y = 0; y < h/2; y++)
{
mem_copy(temp_row, pixel_data+y*w*4, w*4);
mem_copy(pixel_data+y*w*4, pixel_data+(h-y-1)*w*4, w*4);
mem_copy(pixel_data+(h-y-1)*w*4, temp_row,w*4);
}
/* find filename */
{
char wholepath[1024];
png_t png;
engine_savepath(filename, wholepath, sizeof(wholepath));
/* save png */
dbg_msg("client", "saved screenshot to '%s'", wholepath);
png_open_file_write(&png, wholepath);
png_set_data(&png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pixel_data);
png_close_file(&png);
}
/* clean up */
mem_free(pixel_data);
}
int gfx_screenwidth()
{
return screen_width;
@ -690,7 +701,7 @@ void gfx_texture_set(int slot)
void gfx_clear(float r, float g, float b)
{
glClearColor(r,g,b,1.0f);
glClearColor(r,g,b,0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

View file

@ -35,6 +35,7 @@ MACRO_CONFIG_INT(snd_nonactive_mute, 0, 0, 1)
MACRO_CONFIG_INT(gfx_screen_width, 800, 0, 0)
MACRO_CONFIG_INT(gfx_screen_height, 600, 0, 0)
MACRO_CONFIG_INT(gfx_fullscreen, 1, 0, 1)
MACRO_CONFIG_INT(gfx_alphabits, 0, 0, 0)
MACRO_CONFIG_INT(gfx_color_depth, 24, 16, 24)
MACRO_CONFIG_INT(gfx_clear, 0, 0, 1)
MACRO_CONFIG_INT(gfx_vsync, 1, 0, 1)

View file

@ -1,383 +1,262 @@
#include <base/system.h>
#include <stdlib.h>
#include <string.h>
#include <engine/e_huffman.h>
#include <stdlib.h> /* qsort */
#include <memory.h> /* memset */
#include "e_huffman.h"
void huffman_init(HUFFSTATE *huff)
typedef struct HUFFMAN_CONSTRUCT_NODE
{
mem_zero(huff, sizeof(HUFFSTATE));
huff->nodes[0].frequency = 1;
huff->nodes[0].symbol_size = -1;
huff->num_symbols++;
huff->num_nodes++;
}
void huffman_add_symbol(HUFFSTATE *huff, int frequency, int size, unsigned char *symbol)
{
huff->nodes[huff->num_nodes].frequency = frequency;
huff->nodes[huff->num_nodes].symbol_size = size;
mem_copy(huff->nodes[huff->num_nodes].symbol, symbol, size);
huff->num_nodes++;
huff->num_symbols++;
}
unsigned short node_id;
int frequency;
} HUFFMAN_CONSTRUCT_NODE;
static int sort_func(const void *a, const void *b)
{
if((*(HUFFNODE **)a)->frequency > (*(HUFFNODE **)b)->frequency)
if((*(HUFFMAN_CONSTRUCT_NODE **)a)->frequency > (*(HUFFMAN_CONSTRUCT_NODE **)b)->frequency)
return -1;
if((*(HUFFNODE **)a)->frequency < (*(HUFFNODE **)b)->frequency)
if((*(HUFFMAN_CONSTRUCT_NODE **)a)->frequency < (*(HUFFMAN_CONSTRUCT_NODE **)b)->frequency)
return 1;
return 0;
}
void huffman_setbits_r(HUFFNODE *node, int bits, int depth)
static void huffman_setbits_r(HUFFMAN_STATE *huff, HUFFMAN_NODE *node, int bits, int depth)
{
if(node->one)
huffman_setbits_r(node->one, (bits<<1)|1, depth+1);
if(node->zero)
huffman_setbits_r(node->zero, (bits<<1), depth+1);
if(node->leafs[1] != 0xffff)
huffman_setbits_r(huff, &huff->nodes[node->leafs[1]], bits|(1<<depth), depth+1);
if(node->leafs[0] != 0xffff)
huffman_setbits_r(huff, &huff->nodes[node->leafs[0]], bits, depth+1);
if(node->symbol_size)
if(node->num_bits)
{
node->bits = bits;
node->num_bits = depth;
}
}
void huffman_checktree_r(HUFFNODE *node, int bits, int depth)
static void huffman_construct_tree(HUFFMAN_STATE *huff, const unsigned *frequencies)
{
if(node->one)
huffman_checktree_r(node->one, (bits<<1)|1, depth+1);
if(node->zero)
huffman_checktree_r(node->zero, (bits<<1), depth+1);
HUFFMAN_CONSTRUCT_NODE nodes_left_storage[HUFFMAN_MAX_NODES];
HUFFMAN_CONSTRUCT_NODE *nodes_left[HUFFMAN_MAX_NODES];
int num_nodes_left = HUFFMAN_MAX_SYMBOLS;
int i;
if(node->symbol_size)
/* add the symbols */
for(i = 0; i < HUFFMAN_MAX_SYMBOLS; i++)
{
/*dbg_msg("", "%p %p %d %d %d", node->one, node->zero, node->symbol[0], node->bits, node->num_bits);*/
huff->nodes[i].num_bits = -1;
huff->nodes[i].symbol = i;
huff->nodes[i].leafs[0] = -1;
huff->nodes[i].leafs[1] = -1;
if(node->bits != bits || node->num_bits != depth)
{
dbg_msg("", "crap! %d %d=%d %d!=%d", node->bits>>1, node->bits, bits, node->num_bits , depth);
/*dbg_msg("", "%p %p %d", node->one, node->zero, node->symbol[0]);*/
}
}
if(i == HUFFMAN_EOF_SYMBOL)
nodes_left_storage[i].frequency = 1;
else
nodes_left_storage[i].frequency = frequencies[i];
nodes_left_storage[i].node_id = i;
nodes_left[i] = &nodes_left_storage[i];
}
void huffman_construct_tree(HUFFSTATE *huff)
{
HUFFNODE *nodes_left[MAX_NODES];
int num_nodes_left = huff->num_nodes;
int i, k;
for(i = 0; i < num_nodes_left; i++)
nodes_left[i] = &huff->nodes[i];
huff->num_nodes = HUFFMAN_MAX_SYMBOLS;
/* construct the table */
while(num_nodes_left > 1)
{
qsort(nodes_left, num_nodes_left, sizeof(HUFFNODE *), sort_func);
qsort(nodes_left, num_nodes_left, sizeof(HUFFMAN_CONSTRUCT_NODE *), sort_func);
huff->nodes[huff->num_nodes].symbol_size = 0;
huff->nodes[huff->num_nodes].frequency = nodes_left[num_nodes_left-1]->frequency + nodes_left[num_nodes_left-2]->frequency;
huff->nodes[huff->num_nodes].zero = nodes_left[num_nodes_left-1];
huff->nodes[huff->num_nodes].one = nodes_left[num_nodes_left-2];
nodes_left[num_nodes_left-1]->parent = &huff->nodes[huff->num_nodes];
nodes_left[num_nodes_left-2]->parent = &huff->nodes[huff->num_nodes];
nodes_left[num_nodes_left-2] = &huff->nodes[huff->num_nodes];
huff->nodes[huff->num_nodes].num_bits = 0;
huff->nodes[huff->num_nodes].leafs[0] = nodes_left[num_nodes_left-1]->node_id;
huff->nodes[huff->num_nodes].leafs[1] = nodes_left[num_nodes_left-2]->node_id;
nodes_left[num_nodes_left-2]->node_id = huff->num_nodes;
nodes_left[num_nodes_left-2]->frequency = nodes_left[num_nodes_left-1]->frequency + nodes_left[num_nodes_left-2]->frequency;
huff->num_nodes++;
num_nodes_left--;
}
dbg_msg("", "%d", huff->num_nodes);
for(i = 0; i < huff->num_nodes; i++)
{
if(huff->nodes[i].symbol_size && (huff->nodes[i].one || huff->nodes[i].zero))
dbg_msg("", "tree strangeness");
/* set start node */
huff->start_node = &huff->nodes[huff->num_nodes-1];
if(!huff->nodes[i].parent)
{
dbg_msg("", "root %p %p", huff->nodes[i].one, huff->nodes[i].zero);
huff->start_node = &huff->nodes[i];
}
/* build symbol bits */
huffman_setbits_r(huff, huff->start_node, 0, 0);
}
huffman_setbits_r(huff->start_node, 0, 0);
/*
for(i = 0; i < huff->num_symbols; i++)
{
unsigned bits = 0;
int num_bits = 0;
HUFFNODE *n = &huff->nodes[i];
HUFFNODE *p = n;
HUFFNODE *c = n->parent;
while(c)
{
num_bits++;
if(c->one == p)
bits |= 1;
bits <<= 1;
p = c;
c = c->parent;
}
n->bits = bits;
n->num_bits = num_bits;
}*/
huffman_checktree_r(huff->start_node, 0, 0);
for(i = 0; i < huff->num_symbols; i++)
{
for(k = 0; k < huff->num_symbols; k++)
{
if(k == i)
continue;
if(huff->nodes[i].num_bits == huff->nodes[k].num_bits && huff->nodes[i].bits == huff->nodes[k].bits)
dbg_msg("", "tree error %d %d %d", i, k, huff->nodes[i].num_bits);
}
}
}
typedef struct
{
unsigned char *data;
unsigned char current_bits;
int num;
} HUFFBITIO;
int debug_count = 0;
static void bitio_init(HUFFBITIO *bitio, unsigned char *data)
{
bitio->data = data;
bitio->num = 0;
bitio->current_bits = 0;
}
static void bitio_flush(HUFFBITIO *bitio)
{
if(bitio->num == 8)
*bitio->data = bitio->current_bits << (8-bitio->num);
else
*bitio->data = bitio->current_bits;
bitio->data++;
bitio->num = 0;
bitio->current_bits = 0;
}
static void bitio_write(HUFFBITIO *bitio, int bit)
{
bitio->current_bits = (bitio->current_bits<<1)|bit;
bitio->num++;
if(bitio->num == 8)
bitio_flush(bitio);
if(debug_count)
{
debug_count--;
dbg_msg("", "out %d", bit);
}
}
static int bitio_read(HUFFBITIO *bitio)
{
int bit;
if(!bitio->num)
{
bitio->current_bits = *bitio->data;
bitio->data++;
bitio->num = 8;
}
bitio->num--;
bit = (bitio->current_bits>>bitio->num)&1;
if(debug_count)
{
debug_count--;
dbg_msg("", "in %d", bit);
}
return bit;
}
int huffman_compress(HUFFSTATE *huff, const void *input, int input_size, void *output, int output_size)
{
const unsigned char *src = (const unsigned char *)input;
int ret = 0;
int quit = 0;
HUFFBITIO io;
bitio_init(&io, (unsigned char *)output);
while(!quit)
void huffman_init(HUFFMAN_STATE *huff, const unsigned *frequencies)
{
int i;
int best_match = -1;
int best_match_size = 0;
/* make sure to cleanout every thing */
memset(huff, 0, sizeof(HUFFMAN_STATE));
/* construct the tree */
huffman_construct_tree(huff, frequencies);
/* build decode LUT */
for(i = 0; i < HUFFMAN_LUTSIZE; i++)
{
unsigned bits = i;
int k;
HUFFMAN_NODE *node = huff->start_node;
for(k = 0; k < HUFFMAN_LUTBITS; k++)
{
node = &huff->nodes[node->leafs[bits&1]];
bits >>= 1;
if(!node)
break;
if(node->num_bits)
{
huff->decode_lut[i] = node;
break;
}
}
if(k == HUFFMAN_LUTBITS)
huff->decode_lut[i] = node;
}
}
/*****************************************************************/
int huffman_compress(HUFFMAN_STATE *huff, const void *input, int input_size, void *output, int output_size)
{
/* this macro loads a symbol for a byte into bits and bitcount */
#define HUFFMAN_MACRO_LOADSYMBOL(sym) \
bits |= huff->nodes[sym].bits << bitcount; \
bitcount += huff->nodes[sym].num_bits;
/* this macro writes the symbol stored in bits and bitcount to the dst pointer */
#define HUFFMAN_MACRO_WRITE() \
while(bitcount >= 8) \
{ \
*dst++ = (unsigned char)(bits&0xff); \
if(dst == dst_end) \
return -1; \
bits >>= 8; \
bitcount -= 8; \
}
/* setup buffer pointers */
const unsigned char *src = (const unsigned char *)input;
const unsigned char *src_end = src + input_size;
unsigned char *dst = (unsigned char *)output;
unsigned char *dst_end = dst + output_size;
/* symbol variables */
unsigned bits = 0;
unsigned bitcount = 0;
/* make sure that we have data that we want to compress */
if(input_size)
{
for(i = 0; i < huff->num_symbols; i++)
/* {A} load the first symbol */
int symbol = *src++;
while(src != src_end)
{
if(huff->nodes[i].symbol_size <= input_size && huff->nodes[i].symbol_size > best_match_size)
/* {B} load the symbol */
HUFFMAN_MACRO_LOADSYMBOL(symbol)
/* {C} fetch next symbol, this is done here because it will reduce dependency in the code */
symbol = *src++;
/* {B} write the symbol loaded at */
HUFFMAN_MACRO_WRITE()
}
/* write the last symbol loaded from {C} or {A} in the case of only 1 byte input buffer */
HUFFMAN_MACRO_LOADSYMBOL(symbol)
HUFFMAN_MACRO_WRITE()
}
/* write EOF symbol */
HUFFMAN_MACRO_LOADSYMBOL(HUFFMAN_EOF_SYMBOL)
HUFFMAN_MACRO_WRITE()
/* write out the last bits */
*dst++ = bits;
/* return the size of the output */
return (int)(dst - (const unsigned char *)output);
/* remove macros */
#undef HUFFMAN_MACRO_LOADSYMBOL
#undef HUFFMAN_MACRO_WRITE
}
/*****************************************************************/
int huffman_decompress(HUFFMAN_STATE *huff, const void *input, int input_size, void *output, int output_size)
{
if(memcmp(src, huff->nodes[i].symbol, huff->nodes[i].symbol_size) == 0)
/* setup buffer pointers */
unsigned char *dst = (unsigned char *)output;
unsigned char *src = (unsigned char *)input;
unsigned char *dst_end = dst + output_size;
unsigned char *src_end = src + input_size;
unsigned bits = 0;
unsigned bitcount = 0;
HUFFMAN_NODE *eof = &huff->nodes[HUFFMAN_EOF_SYMBOL];
HUFFMAN_NODE *node = 0;
while(1)
{
best_match = i;
best_match_size = huff->nodes[i].symbol_size;
}
}
/* {A} try to load a node now, this will reduce dependency at location {D} */
node = 0;
if(bitcount >= HUFFMAN_LUTBITS)
node = huff->decode_lut[bits&HUFFMAN_LUTMASK];
/* {B} fill with new bits */
while(bitcount < 24 && src != src_end)
{
bits |= (*src++) << bitcount;
bitcount += 8;
}
/* {C} load symbol now if we didn't that earlier at location {A} */
if(!node)
node = huff->decode_lut[bits&HUFFMAN_LUTMASK];
/* {D} check if we hit a symbol already */
if(node->num_bits)
{
/* remove the bits for that symbol */
bits >>= node->num_bits;
bitcount -= node->num_bits;
}
else
{
best_match = 0;
best_match_size = 0;
quit = 1;
}
/* remove the bits that the lut checked up for us */
bits >>= HUFFMAN_LUTBITS;
bitcount -= HUFFMAN_LUTBITS;
if(best_match == -1)
/* walk the tree bit by bit */
while(1)
{
dbg_msg("huffman", "couldn't find symbol! %d left", input_size);
/* traverse tree */
node = &huff->nodes[node->leafs[bits&1]];
/* remove bit */
bitcount--;
bits >>= 1;
/* check if we hit a symbol */
if(node->num_bits)
break;
/* no more bits, decoding error */
if(bitcount == 0)
return -1;
}
i = huff->nodes[best_match].num_bits;
for(i = huff->nodes[best_match].num_bits-1; i >= 0; i--)
bitio_write(&io, (huff->nodes[best_match].bits>>i)&1);
if(debug_count)
dbg_msg("", "--");
ret += huff->nodes[best_match].num_bits;
input_size -= best_match_size;
src += best_match_size;
}
bitio_flush(&io);
return ret;
}
int huffman_decompress(HUFFSTATE *huff, const void *input, int input_size, void *output, int output_size)
{
unsigned char *dst = (unsigned char *)output;
HUFFBITIO io;
int size = 0;
bitio_init(&io, (unsigned char *)input);
while(size < 1401)
{
HUFFNODE *node = huff->start_node;
int i;
while(node)
{
if(node->symbol_size)
break;
if(bitio_read(&io))
node = node->one;
else
node = node->zero;
}
if(debug_count)
dbg_msg("", "-- %d %d", node->bits, node->num_bits);
/* check for eof */
if(node == &huff->nodes[0])
if(node == eof)
break;
for(i = 0; i < node->symbol_size; i++)
{
*dst++ = node->symbol[i];
size++;
}
/* output character */
if(dst == dst_end)
return -1;
*dst++ = node->symbol;
}
return size;
}
unsigned char test_data[1024*64];
int test_data_size;
unsigned char compressed_data[1024*64];
int compressed_data_size;
unsigned char output_data[1024*64];
int output_data_size;
HUFFSTATE state;
int huffman_test()
{
huffman_init(&state);
dbg_msg("", "test test");
/* bitio testing */
{
char bits[] = {1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1,1,1,1,1,1,1,0};
unsigned char buf[64];
int i;
HUFFBITIO io;
bitio_init(&io, buf);
for(i = 0; i < sizeof(bits); i++)
bitio_write(&io, bits[i]);
bitio_flush(&io);
bitio_init(&io, buf);
for(i = 0; i < sizeof(bits); i++)
{
if(bitio_read(&io) != bits[i])
dbg_msg("", "bitio failed at %d", i);
}
}
/* read test data */
{
IOHANDLE io = io_open("license.txt", IOFLAG_READ);
test_data_size = io_read(io, test_data, sizeof(test_data));
io_close(io);
}
/* add symbols */
{
int counts[256] = {0};
int i;
for(i = 0; i < test_data_size; i++)
counts[test_data[i]]++;
for(i = 0; i < 256; i++)
{
unsigned char symbol = (unsigned char )i;
if(counts[i])
huffman_add_symbol(&state, counts[i], 1, &symbol);
}
}
huffman_construct_tree(&state);
/*debug_count = 20;*/
compressed_data_size = huffman_compress(&state, test_data, test_data_size, compressed_data, sizeof(compressed_data));
/*debug_count = 20;*/
output_data_size = huffman_decompress(&state, compressed_data, compressed_data_size, output_data, sizeof(output_data));
dbg_msg("huffman", "%d -> %d -> %d", test_data_size, compressed_data_size/8, output_data_size);
/* write test data */
{
IOHANDLE io = io_open("out.txt", IOFLAG_WRITE);
io_write(io, output_data, output_data_size);
io_close(io);
}
return 0;
/* return the size of the decompressed buffer */
return (int)(dst - (const unsigned char *)output);
}

View file

@ -1,43 +1,91 @@
#ifndef __HUFFMAN_HEADER__
#define __HUFFMAN_HEADER__
#ifdef __cplusplus
extern "C" {
#endif
enum
{
MAX_SYMBOL_SIZE=8,
MAX_NODES=1024*8
HUFFMAN_EOF_SYMBOL = 256,
HUFFMAN_MAX_SYMBOLS=HUFFMAN_EOF_SYMBOL+1,
HUFFMAN_MAX_NODES=HUFFMAN_MAX_SYMBOLS*2-1,
HUFFMAN_LUTBITS = 10,
HUFFMAN_LUTSIZE = (1<<HUFFMAN_LUTBITS),
HUFFMAN_LUTMASK = (HUFFMAN_LUTSIZE-1)
};
typedef struct
typedef struct HUFFMAN_NODE
{
int i;
} HUFFSYMBOL;
typedef struct HUFFNODE_t
{
int frequency;
int symbol_size;
unsigned char symbol[MAX_SYMBOL_SIZE];
int num_bits;
/* symbol */
unsigned bits;
unsigned num_bits;
struct HUFFNODE_t *parent;
struct HUFFNODE_t *zero;
struct HUFFNODE_t *one;
} HUFFNODE;
/* don't use pointers for this. shorts are smaller so we can fit more data into the cache */
unsigned short leafs[2];
typedef struct
/* what the symbol represents */
unsigned char symbol;
} HUFFMAN_NODE;
typedef struct HUFFMAN_STATE
{
HUFFNODE nodes[MAX_NODES];
HUFFNODE *start_node;
int num_symbols;
HUFFMAN_NODE nodes[HUFFMAN_MAX_NODES];
HUFFMAN_NODE *decode_lut[HUFFMAN_LUTSIZE];
HUFFMAN_NODE *start_node;
int num_nodes;
} HUFFSTATE;
} HUFFMAN_STATE;
/*
Function: huffman_init
Inits the compressor/decompressor.
void huffman_add_symbol(HUFFSTATE *huff, int frequency, int size, unsigned char *symbol);
void huffman_init(HUFFSTATE *huff);
void huffman_construct_tree(HUFFSTATE *huff);
int huffman_compress(HUFFSTATE *huff, const void *input, int input_size, void *output, int output_size);
int huffman_decompress(HUFFSTATE *huff, const void *input, int input_size, void *output, int output_size);
Parameters:
huff - Pointer to the state to init
frequencies - A pointer to an array of 256 entries of the frequencies of the bytes
int huffman_test();
Remarks:
- Does no allocation what so ever.
- You don't have to call any cleanup functions when you are done with it
*/
void huffman_init(HUFFMAN_STATE *huff, const unsigned *frequencies);
/*
Function: huffman_compress
Compresses a buffer and outputs a compressed buffer.
Parameters:
huff - Pointer to the huffman state
input - Buffer to compress
input_size - Size of the buffer to compress
output - Buffer to put the compressed data into
output_size - Size of the output buffer
Returns:
Returns the size of the compressed data. Negative value on failure.
*/
int huffman_compress(HUFFMAN_STATE *huff, const void *input, int input_size, void *output, int output_size);
/*
Function: huffman_decompress
Decompresses a buffer
Parameters:
huff - Pointer to the huffman state
input - Buffer to decompress
input_size - Size of the buffer to decompress
output - Buffer to put the uncompressed data into
output_size - Size of the output buffer
Returns:
Returns the size of the uncompressed data. Negative value on failure.
*/
int huffman_decompress(HUFFMAN_STATE *huff, const void *input, int input_size, void *output, int output_size);
#ifdef __cplusplus
}
#endif
#endif /* __HUFFMAN_HEADER__ */

View file

@ -557,7 +557,7 @@ int gfx_memory_usage();
TODO
Arguments:
arg1 - desc
filename - desc
Returns:
@ -566,6 +566,20 @@ int gfx_memory_usage();
*/
void gfx_screenshot();
/*
Function: gfx_screenshot_direct
TODO
Arguments:
filename - desc
Returns:
See Also:
<other_func>
*/
void gfx_screenshot_direct(const char *filename);
/*
Function: gfx_clip_enable
TODO

View file

@ -154,12 +154,8 @@ typedef struct
unsigned state;
int token;
int remote_closed;
int connected;
int disconnected;
RINGBUFFER buffer;
int64 last_update_time;
@ -213,27 +209,10 @@ struct NETCLIENT_t
};
static IOHANDLE datalog = 0;
static HUFFSTATE huffmanstate;
static HUFFMAN_STATE huffmanstate;
#define COMPRESSION 1
typedef struct pcap_hdr_s {
unsigned magic_number; /* magic number */
short version_major; /* major version number */
short version_minor; /* minor version number */
int thiszone; /* GMT to local correction */
unsigned sigfigs; /* accuracy of timestamps */
unsigned snaplen; /* max length of captured packets, in octets */
unsigned network; /* data link type */
} pcap_hdr_t;
typedef struct pcaprec_hdr_s {
unsigned ts_sec; /* timestamp seconds */
unsigned ts_usec; /* timestamp microseconds */
unsigned incl_len; /* number of octets of packet saved in file */
unsigned orig_len; /* actual length of packet */
} pcaprec_hdr_t;
/* packs the data tight and sends it */
static void send_packet(NETSOCKET socket, NETADDR *addr, NETPACKETCONSTRUCT *packet)
{
@ -249,7 +228,7 @@ static void send_packet(NETSOCKET socket, NETADDR *addr, NETPACKETCONSTRUCT *pac
if(COMPRESSION)
{
int compressed_size = (huffman_compress(&huffmanstate, packet->chunk_data, packet->data_size, &buffer[3], NET_MAX_PACKETSIZE-4)+7)/8;
int compressed_size = huffman_compress(&huffmanstate, packet->chunk_data, packet->data_size, &buffer[3], NET_MAX_PACKETSIZE-4);
net_udp_send(socket, addr, buffer, NET_PACKETHEADERSIZE+compressed_size);
}
else
@ -276,9 +255,7 @@ static int unpack_packet(unsigned char *buffer, int size, NETPACKETCONSTRUCT *pa
packet->data_size = size - NET_PACKETHEADERSIZE;
if(COMPRESSION)
{
huffman_decompress(&huffmanstate, &buffer[3], packet->data_size, packet->chunk_data, sizeof(packet->chunk_data));
}
else
mem_copy(packet->chunk_data, &buffer[3], packet->data_size);
@ -326,12 +303,7 @@ static void conn_reset(NETCONNECTION *conn)
conn->ack = 0;
conn->remote_closed = 0;
if(conn->state == NET_CONNSTATE_ONLINE ||
conn->state == NET_CONNSTATE_ERROR)
{
conn->disconnected++;
}
conn->state = NET_CONNSTATE_OFFLINE;
conn->state = NET_CONNSTATE_OFFLINE;
conn->last_send_time = 0;
conn->last_recv_time = 0;
@ -340,6 +312,8 @@ static void conn_reset(NETCONNECTION *conn)
mem_zero(&conn->peeraddr, sizeof(conn->peeraddr));
rb_clear(&conn->buffer);
mem_zero(&conn->construct, sizeof(conn->construct));
}
@ -358,8 +332,6 @@ static void conn_init(NETCONNECTION *conn, NETSOCKET socket)
conn_reset(conn);
conn_reset_stats(conn);
conn->socket = socket;
conn->connected = 0;
conn->disconnected = 0;
rb_init(&conn->buffer);
mem_zero(conn->error_string, sizeof(conn->error_string));
}
@ -489,6 +461,9 @@ static int conn_connect(NETCONNECTION *conn, NETADDR *addr)
static void conn_disconnect(NETCONNECTION *conn, const char *reason)
{
if(conn->state == NET_CONNSTATE_OFFLINE)
return;
if(conn->remote_closed == 0)
{
if(reason)
@ -518,8 +493,6 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETCONSTRUCT *packet, NETADDR *a
{
int ctrlmsg = packet->chunk_data[0];
dbg_msg("connection", "\tgot control message %d", ctrlmsg);
if(ctrlmsg == NET_CTRLMSG_CLOSE)
{
conn->state = NET_CONNSTATE_ERROR;
@ -554,7 +527,6 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETCONSTRUCT *packet, NETADDR *a
/* send response and init connection */
conn_reset(conn);
conn->state = NET_CONNSTATE_ONLINE;
conn->connected++;
conn->peeraddr = *addr;
conn->last_send_time = now;
conn->last_recv_time = now;
@ -571,7 +543,6 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETCONSTRUCT *packet, NETADDR *a
{
conn_send_control(conn, NET_CTRLMSG_ACCEPT, 0, 0);
conn->state = NET_CONNSTATE_ONLINE;
conn->connected++;
if(config.debug)
dbg_msg("connection", "got connect+accept, sending accept. connection online");
}
@ -1088,7 +1059,7 @@ void netcommon_openlog(const char *filename)
}
static const int freq_table[256+1] = {
static const unsigned freq_table[256+1] = {
1<<30,4545,2657,431,1950,919,444,482,2244,617,838,542,715,1814,304,240,754,212,647,186,
283,131,146,166,543,164,167,136,179,859,363,113,157,154,204,108,137,180,202,176,
872,404,168,134,151,111,113,109,120,126,129,100,41,20,16,22,18,18,17,19,
@ -1105,13 +1076,5 @@ static const int freq_table[256+1] = {
void netcommon_init()
{
int i;
huffman_init(&huffmanstate);
for(i = 0; i < 256; i++)
{
unsigned char sym = (unsigned char)i;
huffman_add_symbol(&huffmanstate, freq_table[i], 1, &sym);
}
huffman_construct_tree(&huffmanstate);
huffman_init(&huffmanstate, freq_table);
}

View file

@ -594,6 +594,7 @@ static void server_process_client_packet(NETCHUNK *packet)
int cid = packet->client_id;
int sys;
int msg = msg_unpack_start(packet->data, packet->data_size, &sys);
if(sys)
{
/* system message */

View file

@ -16,6 +16,25 @@
static float sprite_w_scale;
static float sprite_h_scale;
static void layershot_begin()
{
if(!config.cl_layershot)
return;
gfx_clear(0,0,0);
}
static void layershot_end()
{
if(!config.cl_layershot)
return;
char buf[256];
str_format(buf, sizeof(buf), "screenshots/layers_%04d.png", config.cl_layershot);
gfx_screenshot_direct(buf);
config.cl_layershot++;
}
void select_sprite(SPRITE *spr, int flags, int sx, int sy)
{
int x = spr->x+sx;
@ -353,6 +372,8 @@ void render_layers(float center_x, float center_y, int pass)
if(render && !is_game_layer)
{
layershot_begin();
if(layer->type == LAYERTYPE_TILES)
{
MAPITEM_LAYER_TILEMAP *tmap = (MAPITEM_LAYER_TILEMAP *)layer;
@ -381,8 +402,9 @@ void render_layers(float center_x, float center_y, int pass)
render_quads(quads, qlayer->num_quads, envelope_eval, LAYERRENDERFLAG_OPAQUE);
gfx_blend_normal();
render_quads(quads, qlayer->num_quads, envelope_eval, LAYERRENDERFLAG_TRANSPARENT);
}
layershot_end();
}
}
@ -502,25 +524,39 @@ void render_world(float center_x, float center_y, float zoom)
gfx_clip_disable();
// render trails
layershot_begin();
particle_render(PARTGROUP_PROJECTILE_TRAIL);
layershot_end();
// render items
layershot_begin();
render_items();
layershot_end();
// render players above all
layershot_begin();
render_players();
layershot_end();
// render particles
layershot_begin();
particle_render(PARTGROUP_EXPLOSIONS);
particle_render(PARTGROUP_GENERAL);
layershot_end();
if(config.dbg_flow)
flow_dbg_render();
// render foreground layers
layershot_begin();
render_layers(center_x, center_y, 1);
layershot_end();
gfx_clip_disable();
// render damage indications
layershot_begin();
render_damage_indicators();
layershot_end();
config.cl_layershot = 0;
}

View file

@ -16,6 +16,7 @@ MACRO_CONFIG_INT(cl_mouse_deadzone, 300, 0, 0)
MACRO_CONFIG_INT(cl_mouse_followfactor, 60, 0, 200)
MACRO_CONFIG_INT(cl_mouse_max_distance, 800, 0, 0)
MACRO_CONFIG_INT(cl_layershot, 0, 0, 1)
MACRO_CONFIG_INT(ed_showkeys, 0, 0, 1)