mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
added cl_layershot. fixed some bugs in the network
This commit is contained in:
parent
d1282138cd
commit
16912026db
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in a new issue