diff options
Diffstat (limited to 'src/engine/client')
| -rw-r--r-- | src/engine/client/client.c (renamed from src/engine/client/client.cpp) | 288 | ||||
| -rw-r--r-- | src/engine/client/gfx.c (renamed from src/engine/client/gfx.cpp) | 322 | ||||
| -rw-r--r-- | src/engine/client/inp.c | 95 | ||||
| -rw-r--r-- | src/engine/client/pnglite/pnglite.c | 877 | ||||
| -rw-r--r-- | src/engine/client/pnglite/pnglite.h | 227 | ||||
| -rw-r--r-- | src/engine/client/snd.c (renamed from src/engine/client/snd.cpp) | 446 | ||||
| -rw-r--r-- | src/engine/client/ui.c (renamed from src/engine/client/ui.cpp) | 11 | ||||
| -rw-r--r-- | src/engine/client/ui.h | 16 |
8 files changed, 615 insertions, 1667 deletions
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.c index a4cb4509..ab4b7109 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.c @@ -1,29 +1,25 @@ -#include <baselib/system.h> -#include <baselib/config.h> -#include <baselib/input.h> -#include <baselib/audio.h> -#include <baselib/stream/file.h> #include <string.h> #include <stdarg.h> #include <stdlib.h> #include <stdio.h> #include <math.h> -#include <engine/interface.h> -#include <engine/packet.h> -#include <engine/snapshot.h> +#include <engine/system.h> +#include <engine/interface.h> #include "ui.h" +#include <engine/versions.h> + +#include <engine/protocol.h> +#include <engine/snapshot.h> #include <engine/compression.h> #include <engine/network.h> -#include <engine/versions.h> #include <engine/config.h> +#include <engine/packer.h> #include <mastersrv/mastersrv.h> -using namespace baselib; - static int info_request_begin; static int info_request_end; static int snapshot_part; @@ -33,42 +29,15 @@ static float latency = 0; static int extra_polating = 0; static int debug_font; static float frametime = 0.0001f; -static net_client net; -static netaddr4 master_server; -static netaddr4 server_address; +static NETCLIENT *net; +static NETADDR4 master_server; +static NETADDR4 server_address; static int window_must_refocus = 0; static int snaploss = 0; static int current_tick = 0; static float intratick = 0; - -// --- input wrappers --- -static int keyboard_state[2][input::last]; -static int keyboard_current = 0; -static int keyboard_first = 1; - -void inp_mouse_relative(int *x, int *y) { input::mouse_position(x, y); } -int inp_mouse_scroll() { return input::mouse_scroll(); } -int inp_key_pressed(int key) { return keyboard_state[keyboard_current][key]; } -int inp_key_was_pressed(int key) { return keyboard_state[keyboard_current^1][key]; } -int inp_key_down(int key) { return inp_key_pressed(key)&&!inp_key_was_pressed(key); } -int inp_button_pressed(int button) { return input::pressed(button); } - -void inp_update() -{ - if(keyboard_first) - { - // make sure to reset - keyboard_first = 0; - inp_update(); - } - - keyboard_current = keyboard_current^1; - for(int i = 0; i < input::last; i++) - keyboard_state[keyboard_current][i] = input::pressed(i); -} - // --- input snapping --- static int input_data[MAX_INPUT_SIZE] = {0}; static int input_data_size; @@ -87,94 +56,31 @@ enum NUM_SNAPSHOT_TYPES=2, }; -struct snapshot_info -{ - snapshot_info *prev; - snapshot_info *next; - - int tick; - int64 recvtime; - snapshot *snap; -}; - -static snapshot_info *first_snapshot = 0; -static snapshot_info *last_snapshot = 0; - -static snapshot_info *client_snapshot_add(int tick, int64 time, void *data, int data_size) -{ - snapshot_info *holder = (snapshot_info*)mem_alloc(sizeof(snapshot_info) + data_size, 1); - holder->tick = tick; - holder->recvtime = time; - holder->snap = (snapshot *)(holder+1); - mem_copy(holder->snap, data, data_size); - - holder->next =0x0; - holder->prev = last_snapshot; - if(last_snapshot) - last_snapshot->next = holder; - else - first_snapshot = holder; - last_snapshot = holder; - - return holder; -} - -static snapshot_info *client_snapshot_find(int tick) -{ - snapshot_info *current = first_snapshot; - while(current) - { - if(current->tick == tick) - return current; - current = current->next; - } - - return 0; -} - -static void client_snapshot_purge_until(int tick) -{ - snapshot_info *current = first_snapshot; - while(current) - { - snapshot_info *next = current->next; - if(current->tick < tick) - mem_free(current); - else - break; - - current = next; - current->prev = 0; - first_snapshot = current; - } - - if(!first_snapshot) - last_snapshot = 0; -} - -static snapshot_info *snapshots[NUM_SNAPSHOT_TYPES]; +SNAPSTORAGE snapshot_storage; +static SNAPSTORAGE_HOLDER *snapshots[NUM_SNAPSHOT_TYPES]; static int recived_snapshots; static char snapshot_incomming_data[MAX_SNAPSHOT_SIZE]; // --- -const void *snap_get_item(int snapid, int index, snap_item *item) +const void *snap_get_item(int snapid, int index, SNAP_ITEM *item) { dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid"); - snapshot::item *i = snapshots[snapid]->snap->get_item(index); - item->type = i->type(); - item->id = i->id(); - return (void *)i->data(); + SNAPSHOT_ITEM *i = snapshot_get_item(snapshots[snapid]->snap, index); + item->type = snapitem_type(i); + item->id = snapitem_id(i); + return (void *)snapitem_data(i); } const void *snap_find_item(int snapid, int type, int id) { // TODO: linear search. should be fixed. - for(int i = 0; i < snapshots[snapid]->snap->num_items; i++) + int i; + for(i = 0; i < snapshots[snapid]->snap->num_items; i++) { - snapshot::item *itm = snapshots[snapid]->snap->get_item(i); - if(itm->type() == type && itm->id() == id) - return (void *)itm->data(); + SNAPSHOT_ITEM *itm = snapshot_get_item(snapshots[snapid]->snap, i); + if(snapitem_type(itm) == type && snapitem_id(itm) == id) + return (void *)snapitem_data(itm); } return 0x0; } @@ -225,7 +131,7 @@ int menu_loop(); // TODO: what is this? // ----- send functions ----- int client_send_msg() { - const msg_info *info = msg_get_info(); + const MSG_INFO *info = msg_get_info(); NETPACKET packet; mem_zero(&packet, sizeof(NETPACKET)); @@ -236,7 +142,7 @@ int client_send_msg() if(info->flags&MSGFLAG_VITAL) packet.flags = PACKETFLAG_VITAL; - net.send(&packet); + netclient_send(net, &packet); return 0; } @@ -265,9 +171,6 @@ static void client_send_entergame() static void client_send_error(const char *error) { /* - pack(NETMSG_CLIENT_ERROR, "s", error); - */ - /* packet p(NETMSG_CLIENT_ERROR); p.write_str(error); send_packet(&p); @@ -280,7 +183,8 @@ static void client_send_input() { msg_pack_start_system(NETMSG_INPUT, 0); msg_pack_int(input_data_size); - for(int i = 0; i < input_data_size/4; i++) + int i; + for(i = 0; i < input_data_size/4; i++) msg_pack_int(input_data[i]); msg_pack_end(); client_send_msg(); @@ -290,14 +194,15 @@ static void client_send_input() // ------ server browse ---- static struct { - server_info infos[MAX_SERVERS]; + SERVER_INFO infos[MAX_SERVERS]; int64 request_times[MAX_SERVERS]; - netaddr4 addresses[MAX_SERVERS]; + NETADDR4 addresses[MAX_SERVERS]; int num; } servers; + static int serverlist_lan = 1; -int client_serverbrowse_getlist(server_info **serverlist) +int client_serverbrowse_getlist(SERVER_INFO **serverlist) { *serverlist = servers.infos; return servers.num; @@ -327,7 +232,7 @@ void client_serverbrowse_refresh(int lan) packet.flags = PACKETFLAG_CONNLESS; packet.data_size = sizeof(SERVERBROWSE_GETINFO); packet.data = SERVERBROWSE_GETINFO; - net.send(&packet); + netclient_send(net, &packet); // reset the list servers.num = 0; @@ -343,7 +248,7 @@ void client_serverbrowse_refresh(int lan) packet.flags = PACKETFLAG_CONNLESS; packet.data_size = sizeof(SERVERBROWSE_GETLIST); packet.data = SERVERBROWSE_GETLIST; - net.send(&packet); + netclient_send(net, &packet); // reset the list servers.num = 0; @@ -365,7 +270,7 @@ static void client_serverbrowse_request(int id) packet.flags = PACKETFLAG_CONNLESS; packet.data_size = sizeof(SERVERBROWSE_GETINFO); packet.data = SERVERBROWSE_GETINFO; - net.send(&packet); + netclient_send(net, &packet); servers.request_times[id] = time_get(); } @@ -413,7 +318,8 @@ void client_connect(const char *server_address_str) strncpy(buf, server_address_str, 512); const char *port_str = 0; - for(int k = 0; buf[k]; k++) + int k; + for(k = 0; buf[k]; k++) { if(buf[k] == ':') { @@ -430,7 +336,7 @@ void client_connect(const char *server_address_str) if(net_host_lookup(buf, port, &server_address) != 0) dbg_msg("client", "could not find the address of %s, connecting to localhost", buf); - net.connect(&server_address); + netclient_connect(net, &server_address); client_set_state(CLIENTSTATE_CONNECTING); current_tick = 0; } @@ -438,15 +344,15 @@ void client_connect(const char *server_address_str) void client_disconnect() { client_send_error("disconnected"); - net.disconnect("disconnected"); + netclient_disconnect(net, "disconnected"); client_set_state(CLIENTSTATE_OFFLINE); map_unload(); } -static bool client_load_data() +static int client_load_data() { debug_font = gfx_load_texture("data/debug_font.png"); - return true; + return 1; } static void client_debug_render() @@ -464,7 +370,7 @@ static void client_debug_render() { last_snap = time_get(); prev = current; - net.stats(¤t); + netclient_stats(net, ¤t); } static float frametime_avg = 0; @@ -488,7 +394,7 @@ void client_quit() const char *client_error_string() { - return net.error_string(); + return netclient_error_string(net); } static void client_render() @@ -521,7 +427,8 @@ static void client_process_packet(NETPACKET *packet) info_request_begin = 0; info_request_end = 0; - for(int i = 0; i < servers.num; i++) + int i; + for(i = 0; i < servers.num; i++) { servers.infos[i].num_players = 0; servers.infos[i].max_players = 0; @@ -543,18 +450,18 @@ static void client_process_packet(NETPACKET *packet) memcmp(packet->data, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0) { // we got ze info - data_unpacker unpacker; - unpacker.reset((unsigned char*)packet->data+sizeof(SERVERBROWSE_INFO), packet->data_size-sizeof(SERVERBROWSE_INFO)); + UNPACKER up; + unpacker_reset(&up, (unsigned char*)packet->data+sizeof(SERVERBROWSE_INFO), packet->data_size-sizeof(SERVERBROWSE_INFO)); if(serverlist_lan) { if(servers.num != MAX_SERVERS) { int i = servers.num; - strncpy(servers.infos[i].name, unpacker.get_string(), 128); - strncpy(servers.infos[i].map, unpacker.get_string(), 128); - servers.infos[i].max_players = unpacker.get_int(); - servers.infos[i].num_players = unpacker.get_int(); + strncpy(servers.infos[i].name, unpacker_get_string(&up), 128); + strncpy(servers.infos[i].map, unpacker_get_string(&up), 128); + servers.infos[i].max_players = unpacker_get_int(&up); + servers.infos[i].num_players = unpacker_get_int(&up); servers.infos[i].latency = 0; sprintf(servers.infos[i].address, "%d.%d.%d.%d:%d", @@ -569,14 +476,15 @@ static void client_process_packet(NETPACKET *packet) } else { - for(int i = 0; i < servers.num; i++) + int i; + for(i = 0; i < servers.num; i++) { if(net_addr4_cmp(&servers.addresses[i], &packet->address) == 0) { - strncpy(servers.infos[i].name, unpacker.get_string(), 128); - strncpy(servers.infos[i].map, unpacker.get_string(), 128); - servers.infos[i].max_players = unpacker.get_int(); - servers.infos[i].num_players = unpacker.get_int(); + strncpy(servers.infos[i].name, unpacker_get_string(&up), 128); + strncpy(servers.infos[i].map, unpacker_get_string(&up), 128); + servers.infos[i].max_players = unpacker_get_int(&up); + servers.infos[i].num_players = unpacker_get_int(&up); servers.infos[i].latency = ((time_get() - servers.request_times[i])*1000)/time_freq(); if(config.debug) dbg_msg("client", "got server info"); @@ -637,21 +545,20 @@ static void client_process_packet(NETPACKET *packet) snapshot_part = 0; // find snapshot that we should use as delta - static snapshot emptysnap; + static SNAPSHOT emptysnap; emptysnap.data_size = 0; emptysnap.num_items = 0; - snapshot *deltashot = &emptysnap; + SNAPSHOT *deltashot = &emptysnap; // find delta if(delta_tick >= 0) { //void *delta_data; - snapshot_info *delta_info = client_snapshot_find(delta_tick); - //deltashot_size = snapshots_new.get(delta_tick, 0, &delta_data); - if(delta_info) - deltashot = delta_info->snap; - else + + int deltashot_size = snapstorage_get(&snapshot_storage, delta_tick, 0, &deltashot); + + if(deltashot_size < 0) { // couldn't find the delta snapshots that the server used // to compress this snapshot. force the server to resync @@ -684,7 +591,7 @@ static void client_process_packet(NETPACKET *packet) //dbg_msg("UNPACK", "%d unpacked with %d", game_tick, delta_tick); unsigned char tmpbuffer3[MAX_SNAPSHOT_SIZE]; - int snapsize = snapshot_unpack_delta(deltashot, (snapshot*)tmpbuffer3, deltadata, deltasize); + int snapsize = snapshot_unpack_delta(deltashot, (SNAPSHOT*)tmpbuffer3, deltadata, deltasize); // purge old snapshots int purgetick = delta_tick; @@ -692,11 +599,12 @@ static void client_process_packet(NETPACKET *packet) purgetick = snapshots[SNAP_PREV]->tick; if(snapshots[SNAP_CURRENT] && snapshots[SNAP_CURRENT]->tick < purgetick) purgetick = snapshots[SNAP_PREV]->tick; - client_snapshot_purge_until(purgetick); + snapstorage_purge_until(&snapshot_storage, purgetick); //client_snapshot_purge_until(game_tick-50); // add new - snapshot_info *snap = client_snapshot_add(game_tick, time_get(), tmpbuffer3, snapsize); + snapstorage_add(&snapshot_storage, game_tick, time_get(), snapsize, (SNAPSHOT*)tmpbuffer3); + //SNAPSTORAGE_HOLDER *snap = client_snapshot_add(game_tick, time_get(), tmpbuffer3, snapsize); //int ncrc = snapshot_crc((snapshot*)tmpbuffer3); //if(crc != ncrc) @@ -708,22 +616,17 @@ static void client_process_packet(NETPACKET *packet) if(current_tick > 0) snaploss += game_tick-current_tick-1; - current_tick = game_tick; // we got two snapshots until we see us self as connected - if(recived_snapshots <= 2) - { - snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT]; - snapshots[SNAP_CURRENT] = snap; - } - if(recived_snapshots == 2) { + snapshots[SNAP_PREV] = snapshot_storage.first; + snapshots[SNAP_CURRENT] = snapshot_storage.last; local_start_time = time_get(); client_set_state(CLIENTSTATE_ONLINE); } - + int64 now = time_get(); int64 t = now - game_tick*time_freq()/50; if(game_start_time == -1 || t < game_start_time) @@ -762,18 +665,18 @@ static void client_process_packet(NETPACKET *packet) static void client_pump_network() { - net.update(); + netclient_update(net); // check for errors - if(client_state() != CLIENTSTATE_OFFLINE && net.state() == NETSTATE_OFFLINE) + if(client_state() != CLIENTSTATE_OFFLINE && netclient_state(net) == NETSTATE_OFFLINE) { // TODO: add message to the user there client_set_state(CLIENTSTATE_OFFLINE); - dbg_msg("client", "offline error='%s'", net.error_string()); + dbg_msg("client", "offline error='%s'", netclient_error_string(net)); } // - if(client_state() == CLIENTSTATE_CONNECTING && net.state() == NETSTATE_ONLINE) + if(client_state() == CLIENTSTATE_CONNECTING && netclient_state(net) == NETSTATE_ONLINE) { // we switched to online dbg_msg("client", "connected, sending info"); @@ -783,7 +686,7 @@ static void client_pump_network() // process packets NETPACKET packet; - while(net.recv(&packet)) + while(netclient_recv(net, &packet)) client_process_packet(&packet); } @@ -818,7 +721,7 @@ static void client_run(const char *direct_connect_server) // open socket NETADDR4 bindaddr; mem_zero(&bindaddr, sizeof(bindaddr)); - net.open(bindaddr, 0); + net = netclient_open(bindaddr, 0); // net_host_lookup(config.masterserver, MASTERSERVER_PORT, &master_server); @@ -827,8 +730,6 @@ static void client_run(const char *direct_connect_server) if(direct_connect_server) client_connect(direct_connect_server); - //int64 inputs_per_second = 50; - //int64 time_per_input = time_freq()/inputs_per_second; int64 game_starttime = time_get(); int64 last_input = game_starttime; @@ -836,7 +737,7 @@ static void client_run(const char *direct_connect_server) int64 reportinterval = time_freq()*1; int frames = 0; - input::set_mouse_mode(input::mode_relative); + inp_mouse_mode_relative(); while (1) { @@ -849,7 +750,7 @@ static void client_run(const char *direct_connect_server) int64 now = time_get(); while(1) { - snapshot_info *cur = snapshots[SNAP_CURRENT]; + SNAPSTORAGE_HOLDER *cur = snapshots[SNAP_CURRENT]; int64 tickstart = game_start_time + (cur->tick+1)*time_freq()/50; int64 t = tickstart; if(latency > 0) @@ -857,7 +758,7 @@ static void client_run(const char *direct_connect_server) if(t < now) { - snapshot_info *next = snapshots[SNAP_CURRENT]->next; + SNAPSTORAGE_HOLDER *next = snapshots[SNAP_CURRENT]->next; if(next) { snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT]; @@ -913,12 +814,12 @@ static void client_run(const char *direct_connect_server) inp_update(); // refocus + // TODO: fixme + if(!gfx_window_active()) { if(window_must_refocus == 0) - { - input::set_mouse_mode(input::mode_absolute); - } + inp_mouse_mode_absolute(); window_must_refocus = 1; } @@ -926,13 +827,13 @@ static void client_run(const char *direct_connect_server) { if(window_must_refocus < 3) { - input::set_mouse_mode(input::mode_absolute); + inp_mouse_mode_absolute(); window_must_refocus++; } - if(inp_button_pressed(input::mouse_1)) + if(inp_key_pressed(KEY_MOUSE_1)) { - input::set_mouse_mode(input::mode_relative); + inp_mouse_mode_relative(); window_must_refocus = 0; } } @@ -944,15 +845,15 @@ static void client_run(const char *direct_connect_server) // panic button if(config.debug) { - if(input::pressed(input::f1)) - input::set_mouse_mode(input::mode_absolute); - if(input::pressed(input::f2)) - input::set_mouse_mode(input::mode_relative); + if(inp_key_pressed(KEY_F1)) + inp_mouse_mode_absolute(); + if(inp_key_pressed(KEY_F2)) + inp_mouse_mode_relative(); - if(input::pressed(input::lctrl) && input::pressed('Q')) + if(inp_key_pressed(KEY_LCTRL) && inp_key_pressed('Q')) break; - if(input::pressed(input::f5)) + if(inp_key_pressed(KEY_F5)) { // ack snapshot msg_pack_start_system(NETMSG_SNAPACK, 0); @@ -996,7 +897,7 @@ static void client_run(const char *direct_connect_server) if(config.debug) { dbg_msg("client/report", "fps=%.02f netstate=%d", - frames/(float)(reportinterval/time_freq()), net.state()); + frames/(float)(reportinterval/time_freq()), netclient_state(net)); } frames = 0; reporttime += reportinterval; @@ -1032,7 +933,8 @@ int main(int argc, char **argv) const char *config_filename = "default.cfg"; #endif - for(int i = 1; i < argc; i++) + int i; + for(i = 1; i < argc; i++) { if(argv[i][0] == '-' && argv[i][1] == 'f' && argv[i][2] == 0 && argc - i > 1) { @@ -1045,13 +947,13 @@ int main(int argc, char **argv) const char *direct_connect_server = 0x0; snd_set_master_volume(config.volume / 255.0f); - bool editor = false; + int editor = 0; // init network, need to be done first so we can do lookups net_init(); // parse arguments - for(int i = 1; i < argc; i++) + for(i = 1; i < argc; i++) { if(argv[i][0] == '-' && argv[i][1] == 'c' && argv[i][2] == 0 && argc - i > 1) { @@ -1061,7 +963,7 @@ int main(int argc, char **argv) } else if(argv[i][0] == '-' && argv[i][1] == 'e' && argv[i][2] == 0) { - editor = true; + editor = 1; } else config_set(argv[i]); diff --git a/src/engine/client/gfx.cpp b/src/engine/client/gfx.c index 6a096139..b48740b6 100644 --- a/src/engine/client/gfx.cpp +++ b/src/engine/client/gfx.c @@ -1,38 +1,41 @@ -#include <baselib/opengl.h> -#include <baselib/math.h> -#include <baselib/vmath.h> -#include <baselib/stream/file.h> -#include <engine/interface.h> +#include <engine/external/glfw/include/GL/glfw.h> +#include <engine/external/pnglite/pnglite.h> -#include "pnglite/pnglite.h" +#include <engine/system.h> +#include <engine/interface.h> +#include <engine/config.h> +#include <engine/keys.h> #include <string.h> #include <stdio.h> +#include <math.h> -#include <engine/config.h> - +// compressed textures +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RGBA_ARB 0x84EE -using namespace baselib; +// +typedef struct { float x, y, z; } VEC3; +typedef struct { float u, v; } TEXCOORD; +typedef struct { float r, g, b, a; } COLOR; -static opengl::context context; - -struct custom_vertex +typedef struct { - vec3 pos; - vec2 tex; - vec4 color; -}; + VEC3 pos; + TEXCOORD tex; + COLOR color; +} VERTEX; const int vertex_buffer_size = 32*1024; -static custom_vertex *vertices = 0; +static VERTEX *vertices = 0; static int num_vertices = 0; -static vec4 color[4]; -static vec2 texture[4]; + +static COLOR color[4]; +static TEXCOORD texture[4]; static int do_screenshot = 0; -static opengl::vertex_buffer vertex_buffer; static int screen_width = -1; static int screen_height = -1; static float rotation = 0; @@ -43,17 +46,21 @@ static float screen_y0 = 0; static float screen_x1 = 0; static float screen_y1 = 0; -struct texture_holder +typedef struct { - opengl::texture tex; + GLuint tex; int memsize; int flags; int next; -}; +} TEXTURE; -static const int MAX_TEXTURES = 128; -static texture_holder textures[MAX_TEXTURES]; +enum +{ + MAX_TEXTURES = 128 +}; + +static TEXTURE textures[MAX_TEXTURES]; static int first_free_texture; static int memory_usage = 0; @@ -64,7 +71,7 @@ static const unsigned char null_texture_data[] = { 0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, }; -static void draw_quad(bool _bflush = false) +static void draw_quad(int _bflush) { if (!_bflush && ((num_vertices + 4) < vertex_buffer_size)) { @@ -80,33 +87,15 @@ static void draw_quad(bool _bflush = false) //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - /* - if(GLEW_ARB_vertex_buffer_object) - { - // set the data - vertex_buffer.data(vertices, num_vertices * sizeof(custom_vertex), GL_DYNAMIC_DRAW); - opengl::stream_vertex(&vertex_buffer, 3, GL_FLOAT, sizeof(custom_vertex), 0); - opengl::stream_texcoord(&vertex_buffer, 0, 2, GL_FLOAT, - sizeof(custom_vertex), - sizeof(vec3)); - opengl::stream_color(&vertex_buffer, 4, GL_FLOAT, - sizeof(custom_vertex), - sizeof(vec3)+sizeof(vec2)); - - //glDrawElements(GL_TRIANGLES, num_vertices, GL_UNSIGNED_SHORT, indecies); - opengl::draw_arrays(GL_QUADS, 0, num_vertices); - } - else - {*/ glVertexPointer(3, GL_FLOAT, - sizeof(custom_vertex), + sizeof(VERTEX), (char*)vertices); glTexCoordPointer(2, GL_FLOAT, - sizeof(custom_vertex), - (char*)vertices + sizeof(vec3)); + sizeof(VERTEX), + (char*)vertices + sizeof(float)*3); glColorPointer(4, GL_FLOAT, - sizeof(custom_vertex), - (char*)vertices + sizeof(vec3) + sizeof(vec2)); + sizeof(VERTEX), + (char*)vertices + sizeof(float)*5); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); @@ -117,11 +106,13 @@ static void draw_quad(bool _bflush = false) } } -bool gfx_init() +int gfx_init() { screen_width = config.gfx_screen_width; screen_height = config.gfx_screen_height; + glfwInit(); + if(config.stress) { screen_width = 320; @@ -130,31 +121,33 @@ bool gfx_init() if(config.gfx_fullscreen) { - if(!context.create(screen_width, screen_height, 24, 0, 0, 0, opengl::context::FLAG_FULLSCREEN)) + int result = glfwOpenWindow(screen_width, screen_height, 8, 8, 8, 0, 0, 0, GLFW_FULLSCREEN); + if(result != GL_TRUE) { dbg_msg("game", "failed to create gl context"); - return false; + return 0; } } else { - if(!context.create(screen_width, screen_height, 0, 0, 0, 0, 0)) + int result = glfwOpenWindow(screen_width, screen_height, 0, 0, 0, 0, 0, 0, GLFW_WINDOW); + if(result != GL_TRUE) { dbg_msg("game", "failed to create gl context"); - return false; + return 0; } } - context.set_title("Teewars"); + glfwSetWindowTitle("Teewars"); // We don't want to see the window when we run the stress testing if(config.stress) - context.iconify(); + glfwIconifyWindow(); // Init vertices if (vertices) mem_free(vertices); - vertices = (custom_vertex*)mem_alloc(sizeof(custom_vertex) * vertex_buffer_size, 1); + vertices = (VERTEX*)mem_alloc(sizeof(VERTEX) * vertex_buffer_size, 1); num_vertices = 0; @@ -169,49 +162,26 @@ bool gfx_init() glEnable(GL_BLEND); // model - mat4 mat = mat4::identity; - opengl::matrix_modelview(&mat); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); // Set all z to -5.0f - for (int i = 0; i < vertex_buffer_size; i++) + int i; + for (i = 0; i < vertex_buffer_size; i++) vertices[i].pos.z = -5.0f; -/* - if(GLEW_ARB_vertex_buffer_object) - { - // set the streams - vertex_buffer.data(vertices, sizeof(vertex_buffer_size), GL_DYNAMIC_DRAW); - opengl::stream_vertex(&vertex_buffer, 3, GL_FLOAT, sizeof(custom_vertex), 0); - opengl::stream_texcoord(&vertex_buffer, 0, 2, GL_FLOAT, - sizeof(custom_vertex), - sizeof(vec3)); - opengl::stream_color(&vertex_buffer, 4, GL_FLOAT, - sizeof(custom_vertex), - sizeof(vec3)+sizeof(vec2)); - }*/ - // init textures first_free_texture = 0; - for(int i = 0; i < MAX_TEXTURES; i++) + for(i = 0; i < MAX_TEXTURES; i++) textures[i].next = i+1; textures[MAX_TEXTURES-1].next = -1; - // init indecies - /* - for(int i = 0; i < vertex_buffer_size; i++) - { - indecies[i*6 + 0] = i+0; - indecies[i*6 + 1] = i+1; - indecies[i*6 + 2] = i+2; - - indecies[i*6 + 3] = i+1; - indecies[i*6 + 4] = i+3; - indecies[i*6 + 5] = i+2; - }*/ - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // init input + inp_init(); // create null texture, will get id=0 gfx_load_texture_raw(4,4,IMG_RGBA,null_texture_data); @@ -219,17 +189,17 @@ bool gfx_init() // set vsync as needed gfx_set_vsync(config.gfx_vsync); - return true; + return 1; } int gfx_window_active() { - return context.active()?1:0; + return glfwGetWindowParam(GLFW_ACTIVE) == GL_TRUE ? 1 : 0; } -video_mode fakemodes[] = { +VIDEO_MODE fakemodes[] = { {320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8}, {720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8}, {1024,600,8,8,8}, {1024,768,8,8,8}, {1152,864,8,8,8}, @@ -253,25 +223,28 @@ video_mode fakemodes[] = { {2048,1536,5,6,5} }; -int gfx_get_video_modes(video_mode *list, int maxcount) +int gfx_get_video_modes(VIDEO_MODE *list, int maxcount) { if(config.gfx_display_all_modes) { mem_copy(list, fakemodes, sizeof(fakemodes)); - return min((int)(sizeof(fakemodes)/sizeof(video_mode)), maxcount); + int count = sizeof(fakemodes)/sizeof(VIDEO_MODE); + if(maxcount < count) + count = maxcount; + return count; } - return context.getvideomodes((opengl::videomode *)list, maxcount); + return glfwGetVideoModes((GLFWvidmode *)list, maxcount); } void gfx_set_vsync(int val) { - context.set_vsync(val); + glfwSwapInterval(val); } int gfx_unload_texture(int index) { - textures[index].tex.clear(); + glDeleteTextures(1, &textures[index].tex); textures[index].next = first_free_texture; memory_usage -= textures[index].memsize; first_free_texture = index; @@ -302,7 +275,7 @@ static unsigned char sample(int w, int h, const unsigned char *data, int u, int int gfx_load_texture_raw(int w, int h, int format, const void *data) { - bool mipmap = true; + int mipmap = 1; // grab texture int tex = first_free_texture; @@ -320,8 +293,9 @@ int gfx_load_texture_raw(int w, int h, int format, const void *data) h/=2; unsigned char *tmpdata = (unsigned char *)mem_alloc(w*h*4, 1); int c = 0; - for(int y = 0; y < h; y++) - for(int x = 0; x < w; x++, c++) + int x, y; + for(y = 0; y < h; y++) + for(x = 0; x < w; x++, c++) { tmpdata[c*4] = sample(w*2, h*2, texdata, x*2,y*2, 0); tmpdata[c*4+1] = sample(w*2, h*2, texdata, x*2,y*2, 1); @@ -335,22 +309,28 @@ int gfx_load_texture_raw(int w, int h, int format, const void *data) if(config.debug) dbg_msg("gfx", "%d = %dx%d", tex, w, h); - // set data and return - if(config.gfx_texture_compression && GLEW_ARB_texture_compression) + // upload texture + int oglformat = 0; + if(config.gfx_texture_compression) { + oglformat = GL_COMPRESSED_RGBA_ARB; if(format == IMG_RGB) - textures[tex].tex.data2d(w, h, GL_COMPRESSED_RGB_ARB, GL_RGB, GL_UNSIGNED_BYTE, texdata); - else if(format == IMG_RGBA) - textures[tex].tex.data2d(w, h, GL_COMPRESSED_RGBA_ARB, GL_RGBA, GL_UNSIGNED_BYTE, texdata); + oglformat = GL_COMPRESSED_RGB_ARB; } else { + oglformat = GL_RGBA; if(format == IMG_RGB) - textures[tex].tex.data2d(w, h, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, texdata); - else if(format == IMG_RGBA) - textures[tex].tex.data2d(w, h, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, texdata); + oglformat = GL_RGB; } + + glGenTextures(1, &textures[tex].tex); + glBindTexture(GL_TEXTURE_2D, textures[tex].tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + gluBuild2DMipmaps(GL_TEXTURE_2D, oglformat, w, h, oglformat, GL_UNSIGNED_BYTE, texdata); + // calculate memory usage textures[tex].memsize = w*h*4; if(mipmap) { @@ -363,9 +343,7 @@ int gfx_load_texture_raw(int w, int h, int format, const void *data) } memory_usage += textures[tex].memsize; - mem_free(tmpdata); - return tex; } /* @@ -403,7 +381,7 @@ int gfx_load_texture(const char *filename) int l = strlen(filename); if(l < 3) return 0; - image_info img; + IMAGE_INFO img; if(gfx_load_png(&img, filename)) { int id = gfx_load_texture_raw(img.width, img.height, img.format, img.data); @@ -414,7 +392,7 @@ int gfx_load_texture(const char *filename) return 0; } -int gfx_load_png(image_info *img, const char *filename) +int gfx_load_png(IMAGE_INFO *img, const char *filename) { // open file for reading png_init(0,0); @@ -450,7 +428,8 @@ void gfx_shutdown() { if (vertices) mem_free(vertices); - context.destroy(); + glfwCloseWindow(); + glfwTerminate(); } void gfx_screenshot() @@ -470,7 +449,8 @@ void gfx_swap() glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixel_data); // flip the pixel because opengl works from bottom left corner - for(int y = 0; y < h/2; y++) + int y; + 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); @@ -503,7 +483,8 @@ void gfx_swap() do_screenshot = 0; } - context.swap(); + glfwSwapBuffers(); + glfwPollEvents(); } int gfx_screenwidth() @@ -520,15 +501,18 @@ void gfx_texture_set(int slot) { dbg_assert(quads_drawing == 0, "called gfx_texture_set within quads_begin"); if(slot == -1) - opengl::texture_disable(0); + glDisable(GL_TEXTURE_2D); else - opengl::texture_2d(0, &textures[slot].tex); + { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, textures[slot].tex); + } } void gfx_clear(float r, float g, float b) { glClearColor(r,g,b,1.0f); - opengl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void gfx_mapscreen(float tl_x, float tl_y, float br_x, float br_y) @@ -537,9 +521,9 @@ void gfx_mapscreen(float tl_x, float tl_y, float br_x, float br_y) screen_y0 = tl_y; screen_x1 = br_x; screen_y1 = br_y; - mat4 mat; - mat.ortho(tl_x, br_x, br_y, tl_y, 1.0f, 10.f); - opengl::matrix_projection(&mat); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(tl_x, br_x, br_y, tl_y, 1.0f, 10.f); } void gfx_getscreen(float *tl_x, float *tl_y, float *br_x, float *br_y) @@ -552,20 +536,19 @@ void gfx_getscreen(float *tl_x, float *tl_y, float *br_x, float *br_y) void gfx_setoffset(float x, float y) { - //const float scale = 0.75f; - const float scale = 1.0f; - mat4 mat = mat4::identity; - mat.m[0] = scale; - mat.m[5] = scale; - mat.m[10] = scale; - mat.m[12] = x*scale; - mat.m[13] = y*scale; - opengl::matrix_modelview(&mat); + //const float scale = 1.0f; + //mat4 mat = mat4::identity; + //mat.m[0] = scale; + //mat.m[5] = scale; + //mat.m[10] = scale; + //mat.m[12] = x*scale; + //mat.m[13] = y*scale; + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(x, y, 0); } - - void gfx_quads_begin() { dbg_assert(quads_drawing == 0, "called quads_begin twice"); @@ -579,7 +562,7 @@ void gfx_quads_begin() void gfx_quads_end() { dbg_assert(quads_drawing == 1, "called quads_end without quads_begin"); - draw_quad(true); + draw_quad(1); quads_drawing--; } @@ -602,42 +585,43 @@ void gfx_quads_setcolorvertex(int i, float r, float g, float b, float a) void gfx_quads_setcolor(float r, float g, float b, float a) { dbg_assert(quads_drawing == 1, "called gfx_quads_setcolor without quads_begin"); - color[0] = vec4(r,g,b,a); - color[1] = vec4(r,g,b,a); - color[2] = vec4(r,g,b,a); - color[3] = vec4(r,g,b,a); + gfx_quads_setcolorvertex(0, r, g, b, a); + gfx_quads_setcolorvertex(1, r, g, b, a); + gfx_quads_setcolorvertex(2, r, g, b, a); + gfx_quads_setcolorvertex(3, r, g, b, a); } void gfx_quads_setsubset(float tl_u, float tl_v, float br_u, float br_v) { dbg_assert(quads_drawing == 1, "called gfx_quads_setsubset without quads_begin"); - texture[0].x = tl_u; - texture[0].y = tl_v; + texture[0].u = tl_u; + texture[0].v = tl_v; //g_pVertices[g_iVertexEnd].tex.u = tl_u; //g_pVertices[g_iVertexEnd].tex.v = tl_v; - texture[1].x = br_u; - texture[1].y = tl_v; + texture[1].u = br_u; + texture[1].v = tl_v; //g_pVertices[g_iVertexEnd + 2].tex.u = br_u; //g_pVertices[g_iVertexEnd + 2].tex.v = tl_v; - texture[2].x = br_u; - texture[2].y = br_v; + texture[2].u = br_u; + texture[2].v = br_v; //g_pVertices[g_iVertexEnd + 1].tex.u = tl_u; //g_pVertices[g_iVertexEnd + 1].tex.v = br_v; - texture[3].x = tl_u; - texture[3].y = br_v; + texture[3].u = tl_u; + texture[3].v = br_v; //g_pVertices[g_iVertexEnd + 3].tex.u = br_u; //g_pVertices[g_iVertexEnd + 3].tex.v = br_v; } -static void rotate(vec3 ¢er, vec3 &point) +static void rotate(VEC3 *center, VEC3 *point) { - vec3 p = point-center; - point.x = p.x * cosf(rotation) - p.y * sinf(rotation) + center.x; - point.y = p.x * sinf(rotation) + p.y * cosf(rotation) + center.y; + float x = point->x - center->x; + float y = point->y - center->y; + point->x = x * cosf(rotation) - y * sinf(rotation) + center->x; + point->y = x * sinf(rotation) + y * cosf(rotation) + center->y; } void gfx_quads_draw(float x, float y, float w, float h) @@ -649,40 +633,36 @@ void gfx_quads_drawTL(float x, float y, float width, float height) { dbg_assert(quads_drawing == 1, "called quads_draw without quads_begin"); - vec3 center; + VEC3 center; center.x = x + width/2; center.y = y + height/2; center.z = 0; vertices[num_vertices].pos.x = x; vertices[num_vertices].pos.y = y; - vertices[num_vertices].tex.u = texture[0].x; - vertices[num_vertices].tex.v = texture[0].y; + vertices[num_vertices].tex = texture[0]; vertices[num_vertices].color = color[0]; - rotate(center, vertices[num_vertices].pos); + rotate(¢er, &vertices[num_vertices].pos); vertices[num_vertices + 1].pos.x = x+width; vertices[num_vertices + 1].pos.y = y; - vertices[num_vertices + 1].tex.u = texture[1].x; - vertices[num_vertices + 1].tex.v = texture[1].y; + vertices[num_vertices + 1].tex = texture[1]; vertices[num_vertices + 1].color = color[1]; - rotate(center, vertices[num_vertices + 1].pos); + rotate(¢er, &vertices[num_vertices + 1].pos); vertices[num_vertices + 2].pos.x = x + width; vertices[num_vertices + 2].pos.y = y+height; - vertices[num_vertices + 2].tex.u = texture[2].x; - vertices[num_vertices + 2].tex.v = texture[2].y; + vertices[num_vertices + 2].tex = texture[2]; vertices[num_vertices + 2].color = color[2]; - rotate(center, vertices[num_vertices + 2].pos); + rotate(¢er, &vertices[num_vertices + 2].pos); vertices[num_vertices + 3].pos.x = x; vertices[num_vertices + 3].pos.y = y+height; - vertices[num_vertices + 3].tex.u = texture[3].x; - vertices[num_vertices + 3].tex.v = texture[3].y; + vertices[num_vertices + 3].tex = texture[3]; vertices[num_vertices + 3].color = color[3]; - rotate(center, vertices[num_vertices + 3].pos); + rotate(¢er, &vertices[num_vertices + 3].pos); - draw_quad(); + draw_quad(0); } void gfx_quads_draw_freeform( @@ -695,29 +675,25 @@ void gfx_quads_draw_freeform( vertices[num_vertices].pos.x = x0; vertices[num_vertices].pos.y = y0; - vertices[num_vertices].tex.u = texture[0].x; - vertices[num_vertices].tex.v = texture[0].y; + vertices[num_vertices].tex = texture[0]; vertices[num_vertices].color = color[0]; vertices[num_vertices + 1].pos.x = x1; vertices[num_vertices + 1].pos.y = y1; - vertices[num_vertices + 1].tex.u = texture[1].x; - vertices[num_vertices + 1].tex.v = texture[1].y; + vertices[num_vertices + 1].tex = texture[1]; vertices[num_vertices + 1].color = color[1]; vertices[num_vertices + 2].pos.x = x3; vertices[num_vertices + 2].pos.y = y3; - vertices[num_vertices + 2].tex.u = texture[2].x; - vertices[num_vertices + 2].tex.v = texture[2].y; + vertices[num_vertices + 2].tex = texture[2]; vertices[num_vertices + 2].color = color[2]; vertices[num_vertices + 3].pos.x = x2; vertices[num_vertices + 3].pos.y = y2; - vertices[num_vertices + 3].tex.u = texture[3].x; - vertices[num_vertices + 3].tex.v = texture[3].y; + vertices[num_vertices + 3].tex = texture[3]; vertices[num_vertices + 3].color = color[3]; - draw_quad(); + draw_quad(0); } void gfx_quads_text(float x, float y, float size, const char *text) @@ -750,12 +726,12 @@ void gfx_quads_text(float x, float y, float size, const char *text) gfx_quads_end(); } -struct pretty_font +typedef struct { float m_CharStartTable[256]; float m_CharEndTable[256]; int font_texture; -}; +} pretty_font; pretty_font default_font = { diff --git a/src/engine/client/inp.c b/src/engine/client/inp.c new file mode 100644 index 00000000..6583c53f --- /dev/null +++ b/src/engine/client/inp.c @@ -0,0 +1,95 @@ +#include <engine/external/glfw/include/GL/glfw.h> + +#include <engine/system.h> +#include <engine/interface.h> + +static int keyboard_state[2][1024]; // TODO: fix this!! +static int keyboard_current = 0; +static int keyboard_first = 1; + +void inp_mouse_relative(int *x, int *y) +{ + static int last_x = 0, last_y = 0; + int nx, ny; + glfwGetMousePos(&nx, &ny); + *x = nx-last_x; + *y = ny-last_y; + last_x = nx; + last_y = ny; +} + +static char last_c = 0; +static int last_k = 0; + +static void char_callback(int character, int action) +{ + if(action == GLFW_PRESS && character < 256) + last_c = (char)character; +} + +static void key_callback(int key, int action) +{ + if(action == GLFW_PRESS) + last_k = key; +} + +void inp_init() +{ + glfwEnable(GLFW_KEY_REPEAT); + glfwSetCharCallback(char_callback); + glfwSetKeyCallback(key_callback); +} + +char inp_last_char() +{ + return last_c; +} + +int inp_last_key() +{ + return last_k; +} + +void inp_clear() +{ + last_k = 0; + last_c = 0; +} + +void inp_mouse_mode_absolute() +{ + glfwEnable(GLFW_MOUSE_CURSOR); +} + +void inp_mouse_mode_relative() +{ + glfwDisable(GLFW_MOUSE_CURSOR); +} + +//int inp_mouse_scroll() { return input::mouse_scroll(); } +int inp_key_pressed(int key) { return keyboard_state[keyboard_current][key]; } +int inp_key_was_pressed(int key) { return keyboard_state[keyboard_current^1][key]; } +int inp_key_down(int key) { return inp_key_pressed(key)&&!inp_key_was_pressed(key); } +int inp_button_pressed(int button) { return keyboard_state[keyboard_current][button]; } + +void inp_update() +{ + if(keyboard_first) + { + // make sure to reset + keyboard_first = 0; + inp_update(); + } + + keyboard_current = keyboard_current^1; + int i, v; + for(i = 0; i < KEY_LAST; i++) + { + if (i >= KEY_MOUSE_FIRST) + v = glfwGetMouseButton(i-KEY_MOUSE_FIRST) == GLFW_PRESS ? 1 : 0; + else + v = glfwGetKey(i) == GLFW_PRESS ? 1 : 0; + keyboard_state[keyboard_current][i] = v; + } + +} diff --git a/src/engine/client/pnglite/pnglite.c b/src/engine/client/pnglite/pnglite.c deleted file mode 100644 index b33f60ba..00000000 --- a/src/engine/client/pnglite/pnglite.c +++ /dev/null @@ -1,877 +0,0 @@ -/* pnglite.c - pnglite library - For conditions of distribution and use, see copyright notice in pnglite.h -*/ -#define DO_CRC_CHECKS 1 -#define USE_ZLIB 1 - -#if USE_ZLIB -#include <zlib.h> -#else -#include "zlite.h" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "pnglite.h" - - - -static png_alloc_t png_alloc; -static png_free_t png_free; - -static size_t file_read(png_t* png, void* out, size_t size, size_t numel) -{ - size_t result; - if(png->read_fun) - { - result = png->read_fun(out, size, numel, png->user_pointer); - } - else - { - if(!out) - { - result = fseek(png->user_pointer, (long)(size*numel), SEEK_CUR); - } - else - { - result = fread(out, size, numel, png->user_pointer); - } - } - - return result; -} - -static size_t file_write(png_t* png, void* p, size_t size, size_t numel) -{ - size_t result; - - if(png->write_fun) - { - result = png->write_fun(p, size, numel, png->user_pointer); - } - else - { - result = fwrite(p, size, numel, png->user_pointer); - } - - return result; -} - -static int file_read_ul(png_t* png, unsigned *out) -{ - unsigned char buf[4]; - - if(file_read(png, buf, 1, 4) != 4) - return PNG_FILE_ERROR; - - *out = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; - - return PNG_NO_ERROR; -} - -static int file_write_ul(png_t* png, unsigned in) -{ - unsigned char buf[4]; - - buf[0] = (in>>24) & 0xff; - buf[1] = (in>>16) & 0xff; - buf[2] = (in>>8) & 0xff; - buf[3] = (in) & 0xff; - - if(file_write(png, buf, 1, 4) != 4) - return PNG_FILE_ERROR; - - return PNG_NO_ERROR; -} - - -static unsigned get_ul(unsigned char* buf) -{ - unsigned result; - unsigned char foo[4]; - - memcpy(foo, buf, 4); - - result = (foo[0]<<24) | (foo[1]<<16) | (foo[2]<<8) | foo[3]; - - return result; -} - -static unsigned set_ul(unsigned char* buf, unsigned in) -{ - buf[0] = (in>>24) & 0xff; - buf[1] = (in>>16) & 0xff; - buf[2] = (in>>8) & 0xff; - buf[3] = (in) & 0xff; - - return PNG_NO_ERROR; -} - -int png_init(png_alloc_t pngalloc, png_free_t pngfree) -{ - if(pngalloc) - png_alloc = pngalloc; - else - png_alloc = &malloc; - - if(pngfree) - png_free = pngfree; - else - png_free = &free; - - return PNG_NO_ERROR; -} - -static int png_get_bpp(png_t* png) -{ - int bpp; - - switch(png->color_type) - { - case PNG_GREYSCALE: - bpp = 1; break; - case PNG_TRUECOLOR: - bpp = 3; break; - case PNG_INDEXED: - bpp = 1; break; - case PNG_GREYSCALE_ALPHA: - bpp = 2; break; - case PNG_TRUECOLOR_ALPHA: - bpp = 4; break; - default: - return PNG_FILE_ERROR; - } - - bpp *= png->depth/8; - - return bpp; -} - -static int png_read_ihdr(png_t* png) -{ - unsigned length; -#if DO_CRC_CHECKS - unsigned orig_crc; - unsigned calc_crc; -#endif - unsigned char ihdr[13+4]; /* length should be 13, make room for type (IHDR) */ - - file_read_ul(png, &length); - - if(length != 13) - { - printf("%d\n", length); - return PNG_CRC_ERROR; - } - - if(file_read(png, ihdr, 1, 13+4) != 13+4) - return PNG_EOF_ERROR; -#if DO_CRC_CHECKS - file_read_ul(png, &orig_crc); - - calc_crc = crc32(0L, 0, 0); - calc_crc = crc32(calc_crc, ihdr, 13+4); - - if(orig_crc != calc_crc) - return PNG_CRC_ERROR; -#else - file_read_ul(png); -#endif - - png->width = get_ul(ihdr+4); - png->height = get_ul(ihdr+8); - png->depth = ihdr[12]; - png->color_type = ihdr[13]; - png->compression_method = ihdr[14]; - png->filter_method = ihdr[15]; - png->interlace_method = ihdr[16]; - - if(png->color_type == PNG_INDEXED) - return PNG_NOT_SUPPORTED; - - if(png->depth != 8 && png->depth != 16) - return PNG_NOT_SUPPORTED; - - if(png->interlace_method) - return PNG_NOT_SUPPORTED; - - return PNG_NO_ERROR; -} - -static int png_write_ihdr(png_t* png) -{ - unsigned char ihdr[13+4]; - unsigned char *p = ihdr; - unsigned crc; - - file_write(png, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 1, 8); - - file_write_ul(png, 13); - - *p = 'I'; p++; - *p = 'H'; p++; - *p = 'D'; p++; - *p = 'R'; p++; - set_ul(p, png->width); p+=4; - set_ul(p, png->height); p+=4; - *p = png->depth; p++; - *p = png->color_type; p++; - *p = 0; p++; - *p = 0; p++; - *p = 0; p++; - - file_write(png, ihdr, 1, 13+4); - - crc = crc32(0L, 0, 0); - crc = crc32(crc, ihdr, 13+4); - - file_write_ul(png, crc); - - return PNG_NO_ERROR; -} - -void png_print_info(png_t* png) -{ - printf("PNG INFO:\n"); - printf("\twidth:\t\t%d\n", png->width); - printf("\theight:\t\t%d\n", png->height); - printf("\tdepth:\t\t%d\n", png->depth); - printf("\tcolor:\t\t"); - - switch(png->color_type) - { - case PNG_GREYSCALE: printf("greyscale\n"); break; - case PNG_TRUECOLOR: printf("truecolor\n"); break; - case PNG_INDEXED: printf("palette\n"); break; - case PNG_GREYSCALE_ALPHA: printf("greyscale with alpha\n"); break; - case PNG_TRUECOLOR_ALPHA: printf("truecolor with alpha\n"); break; - default: printf("unknown, this is not good\n"); break; - } - - printf("\tcompression:\t%s\n", png->compression_method?"unknown, this is not good":"inflate/deflate"); - printf("\tfilter:\t\t%s\n", png->filter_method?"unknown, this is not good":"adaptive"); - printf("\tinterlace:\t%s\n", png->interlace_method?"interlace":"no interlace"); -} - -int png_open_read(png_t* png, png_read_callback_t read_fun, void* user_pointer) -{ - char header[8]; - int result; - - png->read_fun = read_fun; - png->write_fun = 0; - png->user_pointer = user_pointer; - - if(!read_fun && !user_pointer) - return PNG_WRONG_ARGUMENTS; - - if(file_read(png, header, 1, 8) != 8) - return PNG_EOF_ERROR; - - if(memcmp(header, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) != 0) - return PNG_HEADER_ERROR; - - result = png_read_ihdr(png); - - png->bpp = (unsigned char)png_get_bpp(png); - - return result; -} - -int png_open_write(png_t* png, png_write_callback_t write_fun, void* user_pointer) -{ - png->write_fun = write_fun; - png->read_fun = 0; - png->user_pointer = user_pointer; - - if(!write_fun && !user_pointer) - return PNG_WRONG_ARGUMENTS; - - return PNG_NO_ERROR; -} - -int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer) -{ - return png_open_read(png, read_fun, user_pointer); -} - -int png_open_file_read(png_t *png, const char* filename) -{ - FILE* fp = fopen(filename, "rb"); - - if(!fp) - return PNG_FILE_ERROR; - - return png_open_read(png, 0, fp); -} - -int png_open_file_write(png_t *png, const char* filename) -{ - FILE* fp = fopen(filename, "wb"); - - if(!fp) - return PNG_FILE_ERROR; - - return png_open_write(png, 0, fp); -} - -int png_open_file(png_t *png, const char* filename) -{ - return png_open_file_read(png, filename); -} - -int png_close_file(png_t* png) -{ - fclose(png->user_pointer); - - return PNG_NO_ERROR; -} - -static int png_init_deflate(png_t* png, unsigned char* data, int datalen) -{ - z_stream *stream; - png->zs = png_alloc(sizeof(z_stream)); - - stream = png->zs; - - if(!stream) - return PNG_MEMORY_ERROR; - - memset(stream, 0, sizeof(z_stream)); - - if(deflateInit(stream, Z_DEFAULT_COMPRESSION) != Z_OK) - return PNG_ZLIB_ERROR; - - stream->next_in = data; - stream->avail_in = datalen; - - return PNG_NO_ERROR; -} - -static int png_init_inflate(png_t* png) -{ -#if USE_ZLIB - z_stream *stream; - png->zs = png_alloc(sizeof(z_stream)); -#else - zl_stream *stream; - png->zs = png_alloc(sizeof(zl_stream)); -#endif - - stream = png->zs; - - if(!stream) - return PNG_MEMORY_ERROR; - - - -#if USE_ZLIB - memset(stream, 0, sizeof(z_stream)); - if(inflateInit(stream) != Z_OK) - return PNG_ZLIB_ERROR; -#else - memset(stream, 0, sizeof(zl_stream)); - if(z_inflateInit(stream) != Z_OK) - return PNG_ZLIB_ERROR; -#endif - - stream->next_out = png->png_data; - stream->avail_out = png->png_datalen; - - return PNG_NO_ERROR; -} - -static int png_end_deflate(png_t* png) -{ - z_stream *stream = png->zs; - - if(!stream) - return PNG_MEMORY_ERROR; - - deflateEnd(stream); - - png_free(png->zs); - - return PNG_NO_ERROR; -} - -static int png_end_inflate(png_t* png) -{ -#if USE_ZLIB - z_stream *stream = png->zs; -#else - zl_stream *stream = png->zs; -#endif - - if(!stream) - return PNG_MEMORY_ERROR; - -#if USE_ZLIB - if(inflateEnd(stream) != Z_OK) -#else - if(z_inflateEnd(stream) != Z_OK) -#endif - { - printf("ZLIB says: %s\n", stream->msg); - return PNG_ZLIB_ERROR; - } - - png_free(png->zs); - - return PNG_NO_ERROR; -} - -static int png_inflate(png_t* png, char* data, int len) -{ - int result; -#if USE_ZLIB - z_stream *stream = png->zs; -#else - zl_stream *stream = png->zs; -#endif - - if(!stream) - return PNG_MEMORY_ERROR; - - stream->next_in = (unsigned char*)data; - stream->avail_in = len; - -#if USE_ZLIB - result = inflate(stream, Z_SYNC_FLUSH); -#else - result = z_inflate(stream); -#endif - - if(result != Z_STREAM_END && result != Z_OK) - { - printf("%s\n", stream->msg); - return PNG_ZLIB_ERROR; - } - - if(stream->avail_in != 0) - return PNG_ZLIB_ERROR; - - return PNG_NO_ERROR; -} - -static int png_deflate(png_t* png, char* outdata, int outlen, int *outwritten) -{ - int result; - - z_stream *stream = png->zs; - - - if(!stream) - return PNG_MEMORY_ERROR; - - stream->next_out = (unsigned char*)outdata; - stream->avail_out = outlen; - - result = deflate(stream, Z_SYNC_FLUSH); - - *outwritten = outlen - stream->avail_out; - - if(result != Z_STREAM_END && result != Z_OK) - { - printf("%s\n", stream->msg); - return PNG_ZLIB_ERROR; - } - - return result; -} - -static int png_write_idats(png_t* png, unsigned char* data) -{ - unsigned char *chunk; - unsigned long written; - unsigned long crc; - unsigned size = png->width * png->height * png->bpp + png->height; - - (void)png_init_deflate; - (void)png_end_deflate; - (void)png_deflate; - - chunk = png_alloc(size); - memcpy(chunk, "IDAT", 4); - - written = size; - compress(chunk+4, &written, data, size); - - crc = crc32(0L, Z_NULL, 0); - crc = crc32(crc, chunk, written+4); - set_ul(chunk+written+4, crc); - file_write_ul(png, written); - file_write(png, chunk, 1, written+8); - png_free(chunk); - - file_write_ul(png, 0); - file_write(png, "IEND", 1, 4); - crc = crc32(0L, (const unsigned char *)"IEND", 4); - file_write_ul(png, crc); - - return PNG_NO_ERROR; -} - -static int png_read_idat(png_t* png, unsigned firstlen) -{ - unsigned type = 0; - char *chunk; - int result; - unsigned length = firstlen; - unsigned old_len = length; - -#if DO_CRC_CHECKS - unsigned orig_crc; - unsigned calc_crc; -#endif - - chunk = png_alloc(firstlen); - - result = png_init_inflate(png); - - if(result != PNG_NO_ERROR) - { - png_end_inflate(png); - png_free(chunk); - return result; - } - - do - { - if(file_read(png, chunk, 1, length) != length) - { - png_end_inflate(png); - png_free(chunk); - return PNG_FILE_ERROR; - } - -#if DO_CRC_CHECKS - calc_crc = crc32(0L, Z_NULL, 0); - calc_crc = crc32(calc_crc, (unsigned char*)"IDAT", 4); - calc_crc = crc32(calc_crc, (unsigned char*)chunk, length); - - file_read_ul(png, &orig_crc); - - if(orig_crc != calc_crc) - { - result = PNG_CRC_ERROR; - break; - } -#else - file_read_ul(png); -#endif - - result = png_inflate(png, chunk, length); - - if(result != PNG_NO_ERROR) break; - - file_read_ul(png, &length); - - if(length > old_len) - { - png_free(chunk); - chunk = png_alloc(length); - old_len = length; - } - - if(file_read(png, &type, 1, 4) != 4) - { - result = PNG_FILE_ERROR; - break; - } - - }while(type == *(unsigned int*)"IDAT"); - - if(type == *(unsigned int*)"IEND") - result = PNG_DONE; - - png_free(chunk); - png_end_inflate(png); - - return result; -} - -static int png_process_chunk(png_t* png) -{ - int result = PNG_NO_ERROR; - unsigned type; - unsigned length; - - file_read_ul(png, &length); - - if(file_read(png, &type, 1, 4) != 4) - return PNG_FILE_ERROR; - - if(type == *(unsigned int*)"IDAT") /* if we found an idat, all other idats should be followed with no other chunks in between */ - { - png->png_datalen = png->width * png->height * png->bpp + png->height; - png->png_data = png_alloc(png->png_datalen); - - if(!png->png_data) - return PNG_MEMORY_ERROR; - - return png_read_idat(png, length); - } - else if(type == *(unsigned int*)"IEND") - { - return PNG_DONE; - } - else - { - file_read(png, 0, 1, length + 4); /* unknown chunk */ - } - - return result; -} - -static void png_filter_sub(int stride, unsigned char* in, unsigned char* out, int len) -{ - int i; - unsigned char a = 0; - - for(i = 0; i < len; i++) - { - if(i >= stride) - a = out[i - stride]; - - out[i] = in[i] + a; - } -} - -static void png_filter_up(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len) -{ - int i; - - if(prev_line) - { - for(i = 0; i < len; i++) - out[i] = in[i] + prev_line[i]; - } - else - memcpy(out, in, len); -} - -static void png_filter_average(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len) -{ - int i; - unsigned char a = 0; - unsigned char b = 0; - unsigned int sum = 0; - - for(i = 0; i < len; i++) - { - if(prev_line) - b = prev_line[i]; - - if(i >= stride) - a = out[i - stride]; - - sum = a; - sum += b; - - out[i] = (char)(in[i] + sum/2); - } -} - -static unsigned char png_paeth(unsigned char a, unsigned char b, unsigned char c) -{ - int p = (int)a + b - c; - int pa = abs(p - a); - int pb = abs(p - b); - int pc = abs(p - c); - - int pr; - - if(pa <= pb && pa <= pc) - pr = a; - else if(pb <= pc) - pr = b; - else - pr = c; - - return (char)pr; -} - -static void png_filter_paeth(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len) -{ - int i; - unsigned char a; - unsigned char b; - unsigned char c; - - for(i = 0; i < len; i++) - { - if(prev_line && i >= stride) - { - a = out[i - stride]; - b = prev_line[i]; - c = prev_line[i - stride]; - } - else - { - if(prev_line) - b = prev_line[i]; - else - b = 0; - - if(i >= stride) - a = out[i - stride]; - else - a = 0; - - c = 0; - } - - out[i] = in[i] + png_paeth(a, b, c); - } -} - -static int png_filter(png_t* png, unsigned char* data) -{ - - - return PNG_NO_ERROR; -} - -static int png_unfilter(png_t* png, unsigned char* data) -{ - unsigned i; - unsigned pos = 0; - unsigned outpos = 0; - unsigned char *filtered = png->png_data; - - int stride = png->bpp; - - while(pos < png->png_datalen) - { - unsigned char filter = filtered[pos]; - - pos++; - - if(png->depth == 16) - { - for(i = 0; i < png->width * stride; i+=2) - { - *(short*)(filtered+pos+i) = (filtered[pos+i] << 8) | filtered[pos+i+1]; - } - } - - switch(filter) - { - case 0: /* none */ - memcpy(data+outpos, filtered+pos, png->width * stride); - break; - case 1: /* sub */ - png_filter_sub(stride, filtered+pos, data+outpos, png->width * stride); - break; - case 2: /* up */ - if(outpos) - png_filter_up(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride); - else - png_filter_up(stride, filtered+pos, data+outpos, 0, png->width*stride); - break; - case 3: /* average */ - if(outpos) - png_filter_average(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride); - else - png_filter_average(stride, filtered+pos, data+outpos, 0, png->width*stride); - break; - case 4: /* paeth */ - if(outpos) - png_filter_paeth(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride); - else - png_filter_paeth(stride, filtered+pos, data+outpos, 0, png->width*stride); - break; - default: - return PNG_UNKNOWN_FILTER; - } - - outpos += png->width * stride; - pos += png->width * stride; - } - - return PNG_NO_ERROR; -} - -int png_get_data(png_t* png, unsigned char* data) -{ - int result = PNG_NO_ERROR; - - while(result == PNG_NO_ERROR) - { - result = png_process_chunk(png); - } - - if(result != PNG_DONE) - { - png_free(png->png_data); - return result; - } - - result = png_unfilter(png, data); - - png_free(png->png_data); - - return result; -} - -int png_set_data(png_t* png, unsigned width, unsigned height, char depth, int color, unsigned char* data) -{ - int i; - unsigned char *filtered; - png->width = width; - png->height = height; - png->depth = depth; - png->color_type = color; - png->bpp = png_get_bpp(png); - - filtered = png_alloc(width * height * png->bpp + height); - - for(i = 0; i < png->height; i++) - { - filtered[i*png->width*png->bpp+i] = 0; - memcpy(&filtered[i*png->width*png->bpp+i+1], data + i * png->width*png->bpp, png->width*png->bpp); - } - - png_filter(png, filtered); - png_write_ihdr(png); - png_write_idats(png, filtered); - - png_free(filtered); - return PNG_NO_ERROR; -} - - -char* png_error_string(int error) -{ - switch(error) - { - case PNG_NO_ERROR: - return "No error"; - case PNG_FILE_ERROR: - return "Unknown file error."; - case PNG_HEADER_ERROR: - return "No PNG header found. Are you sure this is a PNG?"; - case PNG_IO_ERROR: - return "Failure while reading file."; - case PNG_EOF_ERROR: - return "Reached end of file."; - case PNG_CRC_ERROR: - return "CRC or chunk length error."; - case PNG_MEMORY_ERROR: - return "Could not allocate memory."; - case PNG_ZLIB_ERROR: - return "zlib reported an error."; - case PNG_UNKNOWN_FILTER: - return "Unknown filter method used in scanline."; - case PNG_DONE: - return "PNG done"; - case PNG_NOT_SUPPORTED: - return "The PNG is unsupported by pnglite, too bad for you!"; - case PNG_WRONG_ARGUMENTS: - return "Wrong combination of arguments passed to png_open. You must use either a read_function or supply a file pointer to use."; - default: - return "Unknown error."; - }; -} diff --git a/src/engine/client/pnglite/pnglite.h b/src/engine/client/pnglite/pnglite.h deleted file mode 100644 index f464c46b..00000000 --- a/src/engine/client/pnglite/pnglite.h +++ /dev/null @@ -1,227 +0,0 @@ -/* pnglite.h - Interface for pnglite library - Copyright (c) 2007 Daniel Karling - - 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. - - Daniel Karling - daniel.karling@gmail.com - */ - - -#ifndef _PNGLITE_H_ -#define _PNGLITE_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -/* - Enumerations for pnglite. - Negative numbers are error codes and 0 and up are okay responses. -*/ - -enum -{ - PNG_DONE = 1, - PNG_NO_ERROR = 0, - PNG_FILE_ERROR = -1, - PNG_HEADER_ERROR = -2, - PNG_IO_ERROR = -3, - PNG_EOF_ERROR = -4, - PNG_CRC_ERROR = -5, - PNG_MEMORY_ERROR = -6, - PNG_ZLIB_ERROR = -7, - PNG_UNKNOWN_FILTER = -8, - PNG_NOT_SUPPORTED = -9, - PNG_WRONG_ARGUMENTS = -10 -}; - -/* - The five different kinds of color storage in PNG files. -*/ - -enum -{ - PNG_GREYSCALE = 0, - PNG_TRUECOLOR = 2, - PNG_INDEXED = 3, - PNG_GREYSCALE_ALPHA = 4, - PNG_TRUECOLOR_ALPHA = 6 -}; - -/* - Typedefs for callbacks. -*/ - -typedef unsigned (*png_write_callback_t)(void* input, size_t size, size_t numel, void* user_pointer); -typedef unsigned (*png_read_callback_t)(void* output, size_t size, size_t numel, void* user_pointer); -typedef void (*png_free_t)(void* p); -typedef void * (*png_alloc_t)(size_t s); - -typedef struct -{ - void* zs; /* pointer to z_stream */ - png_read_callback_t read_fun; - png_write_callback_t write_fun; - void* user_pointer; - - unsigned char* png_data; - unsigned png_datalen; - - unsigned width; - unsigned height; - unsigned char depth; - unsigned char color_type; - unsigned char compression_method; - unsigned char filter_method; - unsigned char interlace_method; - unsigned char bpp; -}png_t; - -/* - Function: png_init - - This function initializes pnglite. The parameters can be used to set your own memory allocation routines following these formats: - - > void* (*custom_alloc)(size_t s) - > void (*custom_free)(void* p) - Parameters: - pngalloc - Pointer to custom allocation routine. If 0 is passed, malloc from libc will be used. - pngfree - Pointer to custom free routine. If 0 is passed, free from libc will be used. - - Returns: - Always returns PNG_NO_ERROR. -*/ - -int png_init(png_alloc_t pngalloc, png_free_t pngfree); - -/* - Function: png_open_file - - This function is used to open a png file with the internal file IO system. This function should be used instead of - png_open if no custom read function is used. - - Parameters: - png - Empty png_t struct. - filename - Filename of the file to be opened. - - Returns: - PNG_NO_ERROR on success, otherwise an error code. -*/ - -int png_open_file(png_t *png, const char* filename); - -int png_open_file_read(png_t *png, const char* filename); -int png_open_file_write(png_t *png, const char* filename); - -/* - Function: png_open - - This function reads or writes a png from/to the specified callback. The callbacks should be of the format: - - > size_t (*png_write_callback_t)(void* input, size_t size, size_t numel, void* user_pointer); - > size_t (*png_read_callback_t)(void* output, size_t size, size_t numel, void* user_pointer). - - Only one callback has to be specified. The read callback in case of PNG reading, otherwise the write callback. - - Writing: - The callback will be called like fwrite. - - Reading: - The callback will be called each time pnglite needs more data. The callback should read as much data as requested, - or return 0. This should always be possible if the PNG is sane. If the output-buffer is a null-pointer the callback - should only skip ahead the specified number of elements. If the callback is a null-pointer the user_pointer will be - treated as a file pointer (use png_open_file instead). - - Parameters: - png - png_t struct - read_fun - Callback function for reading. - user_pointer - User pointer to be passed to read_fun. - - Returns: - PNG_NO_ERROR on success, otherwise an error code. -*/ - -int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer); - -int png_open_read(png_t* png, png_read_callback_t read_fun, void* user_pointer); -int png_open_write(png_t* png, png_write_callback_t write_fun, void* user_pointer); - -/* - Function: png_print_info - - This function prints some info about the opened png file to stdout. - - Parameters: - png - png struct to get info from. -*/ - -void png_print_info(png_t* png); - -/* - Function: png_error_string - - This function translates an error code to a human readable string. - - Parameters: - error - Error code. - - Returns: - Pointer to string. -*/ - -char* png_error_string(int error); - -/* - Function: png_get_data - - This function decodes the opened png file and stores the result in data. data should be big enough to hold the decoded png. Required size will be: - - > width*height*(bytes per pixel) - - Parameters: - data - Where to store result. - - Returns: - PNG_NO_ERROR on success, otherwise an error code. -*/ - -int png_get_data(png_t* png, unsigned char* data); - -int png_set_data(png_t* png, unsigned width, unsigned height, char depth, int color, unsigned char* data); - -/* - Function: png_close_file - - Closes an open png file pointer. Should only be used when the png has been opened with png_open_file. - - Parameters: - png - png to close. - - Returns: - PNG_NO_ERROR -*/ - -int png_close_file(png_t* png); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/engine/client/snd.cpp b/src/engine/client/snd.c index 2fefd6f2..6b490f72 100644 --- a/src/engine/client/snd.cpp +++ b/src/engine/client/snd.c @@ -1,19 +1,17 @@ -#include <baselib/system.h> -#include <baselib/audio.h> -#include <baselib/stream/file.h> - +#include <engine/system.h> #include <engine/interface.h> #include <engine/config.h> -extern "C" { -#include "../../wavpack/wavpack.h" -} +#include <engine/external/portaudio/portaudio.h> +#include <engine/external/wavpack/wavpack.h> -using namespace baselib; +enum +{ + NUM_FRAMES_STOP = 512, + NUM_FRAMES_LERP = 512, +}; -static const int NUM_FRAMES_STOP = 512; static const float NUM_FRAMES_STOP_INV = 1.0f/(float)NUM_FRAMES_STOP; -static const int NUM_FRAMES_LERP = 512; static const float NUM_FRAMES_LERP_INV = 1.0f/(float)NUM_FRAMES_LERP; static const float GLOBAL_VOLUME_SCALE = 0.75f; @@ -22,8 +20,9 @@ static float master_volume = 1.0f; static const float GLOBAL_SOUND_DELAY = 0.05f; // --- sound --- -class sound_data +typedef struct { + /* public: sound_data() : data(0x0), @@ -33,7 +32,7 @@ public: sustain_start(-1), sustain_end(-1), last_played(0) - { } + { }*/ short *data; int num_samples; @@ -42,8 +41,28 @@ public: int sustain_start; int sustain_end; int64 last_played; -}; +} SOUND_DATA; + + +static float clampf(float val, float lower, float upper) +{ + if(val > upper) + return upper; + if(val < lower) + return lower; + return val; +} + +static int clampi(int val, int lower, int upper) +{ + if(val > upper) + return upper; + if(val < lower) + return lower; + return val; +} +/* template<typename T> inline const T clamp(const T val, const T lower, const T upper) { @@ -52,201 +71,264 @@ inline const T clamp(const T val, const T lower, const T upper) if(val < lower) return lower; return val; -} +}*/ -static class mixer : public audio_stream + +typedef struct { +/* public: - class channel - { - public: - channel() - { data = 0; lerp = -1; stop = -1; } - - sound_data *data; - int tick; - int loop; - float pan; - float vol; - float old_vol; - float new_vol; - int lerp; - int stop; - }; + channel() + { data = 0; lerp = -1; stop = -1; } +*/ - enum - { - MAX_CHANNELS=32, - MAX_FILL_FRAMES=256, - }; + SOUND_DATA *data; + int tick; + int loop; + float pan; + float vol; + float old_vol; + float new_vol; + int lerp; + int stop; +} MIXER_CHANNEL; + +enum +{ + MAX_CHANNELS=32, + MAX_FILL_FRAMES=256, +}; - channel channels[MAX_CHANNELS]; - int buffer[MAX_FILL_FRAMES*2]; +static MIXER_CHANNEL channels[MAX_CHANNELS]; +static int buffer[MAX_FILL_FRAMES*2]; - void fill_mono(int *out, unsigned long frames, channel *c, float dv = 0.0f) - { - float pl = clamp(1.0f - c->pan, 0.0f, 1.0f); - float pr = clamp(1.0f + c->pan, 0.0f, 1.0f); +static void mixer_fill_mono(int *out, unsigned long frames, MIXER_CHANNEL *c, float dv) +{ + float pl = clampf(1.0f - c->pan, 0.0f, 1.0f); + float pr = clampf(1.0f + c->pan, 0.0f, 1.0f); + unsigned long i; - for(unsigned long i = 0; i < frames; i++) - { - float val = c->vol * master_volume * c->data->data[c->tick]; + for(i = 0; i < frames; i++) + { + float val = c->vol * master_volume * c->data->data[c->tick]; - out[i<<1] += (int)(pl*val); - out[(i<<1)+1] += (int)(pr*val); - c->tick++; - c->vol += dv; - if(c->vol < 0.0f) c->vol = 0.0f; - } + out[i<<1] += (int)(pl*val); + out[(i<<1)+1] += (int)(pr*val); + c->tick++; + c->vol += dv; + if(c->vol < 0.0f) c->vol = 0.0f; } +} - void fill_stereo(int *out, unsigned long frames, channel *c, float dv = 0.0f) - { - float pl = clamp(1.0f - c->pan, 0.0f, 1.0f); - float pr = clamp(1.0f + c->pan, 0.0f, 1.0f); +static void mixer_fill_stereo(int *out, unsigned long frames, MIXER_CHANNEL *c, float dv) +{ + float pl = clampf(1.0f - c->pan, 0.0f, 1.0f); + float pr = clampf(1.0f + c->pan, 0.0f, 1.0f); + unsigned long i; - for(unsigned long i = 0; i < frames; i++) - { - int vl = (int)(pl*c->vol * master_volume * c->data->data[c->tick]); - int vr = (int)(pr*c->vol * master_volume * c->data->data[c->tick + 1]); - out[i<<1] += vl; - out[(i<<1)+1] += vr; - c->tick += 2; - c->vol += dv; - if(c->vol < 0.0f) c->vol = 0.0f; - } + for(i = 0; i < frames; i++) + { + int vl = (int)(pl*c->vol * master_volume * c->data->data[c->tick]); + int vr = (int)(pr*c->vol * master_volume * c->data->data[c->tick + 1]); + out[i<<1] += vl; + out[(i<<1)+1] += vr; + c->tick += 2; + c->vol += dv; + if(c->vol < 0.0f) c->vol = 0.0f; } +} - virtual void fill(void *output, unsigned long frames) - { - short *out = (short*)output; +static void mixer_fill(void *output, unsigned long frames) +{ + short *out = (short*)output; - dbg_assert(frames <= MAX_FILL_FRAMES, "not enough fill frames in buffer"); + dbg_assert(frames <= MAX_FILL_FRAMES, "not enough fill frames in buffer"); + unsigned long i; + int c; - for(unsigned long i = 0; i < frames; i++) - { - buffer[i<<1] = 0; - buffer[(i<<1)+1] = 0; - } + for(i = 0; i < frames; i++) + { + buffer[i<<1] = 0; + buffer[(i<<1)+1] = 0; + } - for(int c = 0; c < MAX_CHANNELS; c++) + for(c = 0; c < MAX_CHANNELS; c++) + { + unsigned long filled = 0; + while(channels[c].data && filled < frames) { - unsigned long filled = 0; - while(channels[c].data && filled < frames) + unsigned long frames_left = (channels[c].data->num_samples - channels[c].tick) >> (channels[c].data->channels-1); + unsigned long to_fill = frames>frames_left?frames_left:frames; + float dv = 0.0f; + + if(channels[c].stop >= 0) + to_fill = (unsigned)channels[c].stop>frames_left?frames:channels[c].stop; + if(channels[c].loop >= 0 && + channels[c].data->sustain_start >= 0) { - unsigned long frames_left = (channels[c].data->num_samples - channels[c].tick) >> (channels[c].data->channels-1); - unsigned long to_fill = frames>frames_left?frames_left:frames; - float dv = 0.0f; - - if(channels[c].stop >= 0) - to_fill = (unsigned)channels[c].stop>frames_left?frames:channels[c].stop; - if(channels[c].loop >= 0 && - channels[c].data->sustain_start >= 0) - { - unsigned long tmp = channels[c].data->sustain_end - channels[c].tick; - to_fill = tmp>frames?frames:tmp; - } - - if(channels[c].lerp >= 0) - { - dv = (channels[c].new_vol - channels[c].old_vol) * NUM_FRAMES_LERP_INV; - } + unsigned long tmp = channels[c].data->sustain_end - channels[c].tick; + to_fill = tmp>frames?frames:tmp; + } - if(channels[c].data->channels == 1) - fill_mono(buffer, to_fill, &channels[c], dv); - else - fill_stereo(buffer, to_fill, &channels[c], dv); + if(channels[c].lerp >= 0) + { + dv = (channels[c].new_vol - channels[c].old_vol) * NUM_FRAMES_LERP_INV; + } - if(channels[c].loop >= 0 && - channels[c].data->sustain_start >= 0 && - channels[c].tick >= channels[c].data->sustain_end) - channels[c].tick = channels[c].data->sustain_start; + if(channels[c].data->channels == 1) + mixer_fill_mono(buffer, to_fill, &channels[c], dv); + else + mixer_fill_stereo(buffer, to_fill, &channels[c], dv); - if(channels[c].stop >= 0) - channels[c].stop -= to_fill; - if(channels[c].tick >= channels[c].data->num_samples || - channels[c].stop == 0) - channels[c].data = 0; + if(channels[c].loop >= 0 && + channels[c].data->sustain_start >= 0 && + channels[c].tick >= channels[c].data->sustain_end) + channels[c].tick = channels[c].data->sustain_start; - channels[c].lerp -= to_fill; - if(channels[c].lerp < 0) - channels[c].lerp = -1; + if(channels[c].stop >= 0) + channels[c].stop -= to_fill; + if(channels[c].tick >= channels[c].data->num_samples || + channels[c].stop == 0) + channels[c].data = 0; + channels[c].lerp -= to_fill; + if(channels[c].lerp < 0) + channels[c].lerp = -1; - filled += to_fill; - } - } - for(unsigned long i = 0; i < frames; i++) - { - out[i<<1] = (short)clamp(buffer[i<<1], -0x7fff, 0x7fff); - out[(i<<1)+1] = (short)clamp(buffer[(i<<1)+1], -0x7fff, 0x7fff); + filled += to_fill; } } - - int play(sound_data *sound, unsigned loop, float vol, float pan) - { - if(time_get() - sound->last_played < (int64)(time_freq()*GLOBAL_SOUND_DELAY)) - return -1; - for(int c = 0; c < MAX_CHANNELS; c++) - { - if(channels[c].data == 0) - { - channels[c].data = sound; - channels[c].tick = 0; - channels[c].loop = loop; - channels[c].vol = vol * GLOBAL_VOLUME_SCALE; - channels[c].pan = pan; - channels[c].stop = -1; - channels[c].lerp = -1; - sound->last_played = time_get(); - return c; - } - } + for(i = 0; i < frames; i++) + { + out[i<<1] = (short)clampi(buffer[i<<1], -0x7fff, 0x7fff); + out[(i<<1)+1] = (short)clampi(buffer[(i<<1)+1], -0x7fff, 0x7fff); + } +} +int mixer_play(SOUND_DATA *sound, unsigned loop, float vol, float pan) +{ + if(time_get() - sound->last_played < (int64)(time_freq()*GLOBAL_SOUND_DELAY)) return -1; - } - void stop(int id) + int c; + for(c = 0; c < MAX_CHANNELS; c++) { - dbg_assert(id >= 0 && id < MAX_CHANNELS, "id out of bounds"); - channels[id].old_vol = channels[id].vol; - channels[id].stop = NUM_FRAMES_STOP; + if(channels[c].data == 0) + { + channels[c].data = sound; + channels[c].tick = 0; + channels[c].loop = loop; + channels[c].vol = vol * GLOBAL_VOLUME_SCALE; + channels[c].pan = pan; + channels[c].stop = -1; + channels[c].lerp = -1; + sound->last_played = time_get(); + return c; + } } - void set_vol(int id, float vol) - { - dbg_assert(id >= 0 && id < MAX_CHANNELS, "id out of bounds"); - channels[id].new_vol = vol * GLOBAL_VOLUME_SCALE; - channels[id].old_vol = channels[id].vol; - channels[id].lerp = NUM_FRAMES_LERP; - } -} mixer; + return -1; +} + +static void mixer_stop(int id) +{ + dbg_assert(id >= 0 && id < MAX_CHANNELS, "id out of bounds"); + channels[id].old_vol = channels[id].vol; + channels[id].stop = NUM_FRAMES_STOP; +} + +static void mixer_set_vol(int id, float vol) +{ + dbg_assert(id >= 0 && id < MAX_CHANNELS, "id out of bounds"); + channels[id].new_vol = vol * GLOBAL_VOLUME_SCALE; + channels[id].old_vol = channels[id].vol; + channels[id].lerp = NUM_FRAMES_LERP; +} -struct sound_holder +typedef struct { - sound_data sound; + SOUND_DATA sound; int next; +} SOUND; + +enum +{ + MAX_SOUNDS = 1024, }; -static const int MAX_SOUNDS = 1024; -static sound_holder sounds[MAX_SOUNDS]; +static SOUND sounds[MAX_SOUNDS]; static int first_free_sound; -bool snd_init() +static PaStream *stream = 0; + +static int pacallback(const void *in, void *out, unsigned long frames, const PaStreamCallbackTimeInfo* time, PaStreamCallbackFlags status, void *user) +{ + mixer_fill(out, frames); + return 0; +} + +int snd_init() { + int i; first_free_sound = 0; - for(int i = 0; i < MAX_SOUNDS; i++) + for(i = 0; i < MAX_SOUNDS; i++) sounds[i].next = i+1; sounds[MAX_SOUNDS-1].next = -1; - return mixer.create(); + + // init PA + PaStreamParameters params; + PaError err = Pa_Initialize(); + if(err != paNoError) + { + dbg_msg("audio_stream", "portaudio error: %s", Pa_GetErrorText(err)); + return 0; + } + + params.device = Pa_GetDefaultOutputDevice(); + if(params.device == -1) + { + dbg_msg("audio_stream", "no default output device"); + return 0; + } + params.channelCount = 2; + params.sampleFormat = paInt16; + params.suggestedLatency = Pa_GetDeviceInfo(params.device)->defaultLowOutputLatency; + params.hostApiSpecificStreamInfo = 0x0; + + err = Pa_OpenStream( + &stream, /* passes back stream pointer */ + 0, /* no input channels */ + ¶ms, /* pointer to parameters */ + 44100, /* sample rate */ + 128, /* frames per buffer */ + paClipOff, /* no clamping */ + pacallback, /* specify our custom callback */ + 0); /* pass our data through to callback */ + + if(err != paNoError) + { + dbg_msg("audio_stream", "portaudio error: %s", Pa_GetErrorText(err)); + return 0; + } + + err = Pa_StartStream(stream); + if(err != paNoError) + { + dbg_msg("audio_stream", "portaudio error: %s", Pa_GetErrorText(err)); + return 0; + } + + return 1; } -bool snd_shutdown() +int snd_shutdown() { - mixer.destroy(); - return true; + Pa_StopStream(stream); + stream = NULL; + Pa_Terminate(); + return 1; } float snd_get_master_volume() @@ -283,12 +365,12 @@ static int read_data(void *buffer, int size) int snd_load_wv(const char *filename) { - sound_data snd; + SOUND_DATA snd; int id = -1; char error[100]; - file = fopen(filename, "rb"); + file = fopen(filename, "rb"); // TODO: use system.h stuff for this WavpackContext *context = WavpackOpenFileInput(read_data, error); if (context) @@ -326,7 +408,8 @@ int snd_load_wv(const char *filename) snd.data = (short *)mem_alloc(2*samples*channels, 1); short *dst = snd.data; - for (int i = 0; i < samples*channels; i++) + int i; + for (i = 0; i < samples*channels; i++) *dst++ = (short)*src++; mem_free(data); @@ -361,11 +444,12 @@ int snd_load_wv(const char *filename) int snd_load_wav(const char *filename) { - sound_data snd; + SOUND_DATA snd; // open file for reading - file_stream file; - if(!file.open_r(filename)) + IOHANDLE file; + file = io_open(filename, IOFLAG_READ); + if(!file) { dbg_msg("sound/wav", "failed to open file. filename='%s'", filename); return -1; @@ -377,7 +461,7 @@ int snd_load_wav(const char *filename) { // read chunk header unsigned char head[8]; - if(file.read(head, sizeof(head)) != 8) + if(io_read(file, head, sizeof(head)) != 8) { break; } @@ -395,7 +479,7 @@ int snd_load_wav(const char *filename) } unsigned char type[4]; - file.read(type, 4); + io_read(file, type, 4); if(type[0] != 'W' || type[1] != 'A' || type[2] != 'V' || type[3] != 'E') { @@ -411,7 +495,7 @@ int snd_load_wav(const char *filename) if(head[0] == 'f' && head[1] == 'm' && head[2] == 't' && head[3] == ' ') { unsigned char fmt[16]; - if(file.read(fmt, sizeof(fmt)) != sizeof(fmt)) + if(io_read(file, fmt, sizeof(fmt)) != sizeof(fmt)) { dbg_msg("sound/wav", "failed to read format. filename='%s'", filename); return -1; @@ -451,7 +535,7 @@ int snd_load_wav(const char *filename) state++; } else - file.skip(chunk_size); + io_skip(file, chunk_size); } else if(state == 2) { @@ -459,7 +543,7 @@ int snd_load_wav(const char *filename) if(head[0] == 'd' && head[1] == 'a' && head[2] == 't' && head[3] == 'a') { snd.data = (short*)mem_alloc(chunk_size, 1); - file.read(snd.data, chunk_size); + io_read(file, snd.data, chunk_size); snd.num_samples = chunk_size/(2); #if defined(CONF_ARCH_ENDIAN_BIG) for(unsigned i = 0; i < (unsigned)snd.num_samples; i++) @@ -476,7 +560,7 @@ int snd_load_wav(const char *filename) state++; } else - file.skip(chunk_size); + io_skip(file, chunk_size); } else if(state == 3) { @@ -487,13 +571,13 @@ int snd_load_wav(const char *filename) if(config.debug) dbg_msg("sound/wav", "got sustain"); - file.read(smpl, sizeof(smpl)); + io_read(file, smpl, sizeof(smpl)); unsigned num_loops = (smpl[28] | (smpl[29]<<8) | (smpl[30]<<16) | (smpl[31]<<24)); unsigned skip = (smpl[32] | (smpl[33]<<8) | (smpl[34]<<16) | (smpl[35]<<24)); if(num_loops > 0) { - file.read(loop, sizeof(loop)); + io_read(file, loop, sizeof(loop)); unsigned start = (loop[8] | (loop[9]<<8) | (loop[10]<<16) | (loop[11]<<24)); unsigned end = (loop[12] | (loop[13]<<8) | (loop[14]<<16) | (loop[15]<<24)); sounds[id].sound.sustain_start = start * sounds[id].sound.channels; @@ -501,16 +585,16 @@ int snd_load_wav(const char *filename) } if(num_loops > 1) - file.skip((num_loops-1) * sizeof(loop)); + io_skip(file, (num_loops-1) * sizeof(loop)); - file.skip(skip); + io_skip(file, skip); state++; } else - file.skip(chunk_size); + io_skip(file, chunk_size); } else - file.skip(chunk_size); + io_skip(file, chunk_size); } if(id >= 0) @@ -534,17 +618,17 @@ int snd_play(int id, int loop, float vol, float pan) dbg_assert(sounds[id].sound.data != 0, "null sound"); dbg_assert(sounds[id].next == -1, "sound isn't allocated"); - return mixer.play(&sounds[id].sound, loop, vol, pan); + return mixer_play(&sounds[id].sound, loop, vol, pan); } void snd_stop(int id) { if(id >= 0) - mixer.stop(id); + mixer_stop(id); } void snd_set_vol(int id, float vol) { if(id >= 0) - mixer.set_vol(id, vol); + mixer_set_vol(id, vol); } diff --git a/src/engine/client/ui.cpp b/src/engine/client/ui.c index 7b309539..c67b1b13 100644 --- a/src/engine/client/ui.cpp +++ b/src/engine/client/ui.c @@ -1,4 +1,4 @@ -#include <baselib/system.h> +#include <engine/system.h> #include <engine/interface.h> #include "ui.h" @@ -14,7 +14,7 @@ struct pretty_font int font_texture; }; -extern pretty_font *current_font; +extern struct pretty_font *current_font; static void *hot_item = 0; static void *active_item = 0; @@ -84,7 +84,7 @@ void ui_do_label(float x, float y, const char *text, float size) { gfx_blend_normal(); gfx_texture_set(current_font->font_texture); - gfx_pretty_text(x, y, size, text); + gfx_pretty_text(x, y, size, text, -1); } int ui_do_button(void *id, const char *text, int checked, float x, float y, float w, float h, draw_button_callback draw_func, void *extra) @@ -115,8 +115,3 @@ int ui_do_button(void *id, const char *text, int checked, float x, float y, floa return r; } -int ui_do_button(void *id, const char *text, int checked, float x, float y, float w, float h, draw_button_callback draw_func) -{ - return ui_do_button(id, text, checked, x, y, w, h, draw_func, 0x0); -} - diff --git a/src/engine/client/ui.h b/src/engine/client/ui.h index fb9208c1..31757b3b 100644 --- a/src/engine/client/ui.h +++ b/src/engine/client/ui.h @@ -1,12 +1,9 @@ #ifndef _UI_H #define _UI_H -/* -extern void *hot_item; -extern void *active_item; -extern void *becomming_hot_item; -extern float mouse_x, mouse_y; // in gui space -extern float mouse_wx, mouse_wy; // in world space -extern unsigned mouse_buttons;*/ + +#ifdef __cplusplus +extern "C" { +#endif int ui_update(float mx, float my, float mwx, float mwy, int buttons); @@ -30,6 +27,9 @@ typedef void (*draw_button_callback)(void *id, const char *text, int checked, fl void ui_do_image(int texture, float x, float y, float w, float h); void ui_do_label(float x, float y, const char *text, float size); int ui_do_button(void *id, const char *text, int checked, float x, float y, float w, float h, draw_button_callback draw_func, void *extra); -int ui_do_button(void *id, const char *text, int checked, float x, float y, float w, float h, draw_button_callback draw_func); + +#ifdef __cplusplus +} +#endif #endif |