Corrected the diff implementation, refactored the networking

implementation
This commit is contained in:
simon.kagstrom 2009-01-26 21:00:23 +00:00
parent f693404434
commit 5eca531105
6 changed files with 259 additions and 202 deletions

View File

@ -1,6 +1,12 @@
version 7:
TODO: Multiple frodo versions, switch between
TODO: D-pad less responsive in v6 than v5
TODO: Crash on + in "Other" menu
TODO: Fix two-controller issue
-- Simon Kagstrom <simon.kagstrom@gmail.com>,
version 6:

View File

@ -610,7 +610,8 @@ void C64::VBlank(bool draw_frame)
NetworkClient *remote = this->network_server->clients[i];
remote->EncodeDisplay(master, remote->screen);
remote->SendUpdate();
if (remote->SendUpdate() == false)
printf("Oh no! Could not send update\n");
remote->ResetNetworkUpdate();
bytes_sent += remote->GetBytesSent();

View File

@ -17,7 +17,7 @@ DESTDIR =
CXX = g++
CC = gcc
CFLAGS =-DFRODO_SC -g -I/usr/include/SDL -I$(DEVKITPRO)/libogc/include -D_GNU_SOURCE=1 -D_REENTRANT -DHAVE_SDL -DORBIT2=1 -pthread -I/usr/include/libglade-2.0 -I/usr/include/gtk-2.0 -I/usr/include/libxml2 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/pixman-1 -I/usr/include/libgnomeui-2.0 -I/usr/include/libart-2.0 -I/usr/include/gconf/2 -I/usr/include/gnome-keyring-1 -I/usr/include/libgnome-2.0 -I/usr/include/libbonoboui-2.0 -I/usr/include/libgnomecanvas-2.0 -I/usr/include/gnome-vfs-2.0 -I/usr/lib/gnome-vfs-2.0/include -I/usr/include/orbit-2.0 -I/usr/include/libbonobo-2.0 -I/usr/include/bonobo-activation-2.0 -I/usr/include/gail-1.0 -I./ -DKBD_LANG=0
CFLAGS =-DFRODO_SC -O2 -g -I/usr/include/SDL -I$(DEVKITPRO)/libogc/include -D_GNU_SOURCE=1 -D_REENTRANT -DHAVE_SDL -DORBIT2=1 -pthread -I/usr/include/libglade-2.0 -I/usr/include/gtk-2.0 -I/usr/include/libxml2 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/pixman-1 -I/usr/include/libgnomeui-2.0 -I/usr/include/libart-2.0 -I/usr/include/gconf/2 -I/usr/include/gnome-keyring-1 -I/usr/include/libgnome-2.0 -I/usr/include/libbonoboui-2.0 -I/usr/include/libgnomecanvas-2.0 -I/usr/include/gnome-vfs-2.0 -I/usr/lib/gnome-vfs-2.0/include -I/usr/include/orbit-2.0 -I/usr/include/libbonobo-2.0 -I/usr/include/bonobo-activation-2.0 -I/usr/include/gail-1.0 -I./ -DKBD_LANG=0
DEFS = -DHAVE_CONFIG_H -DDATADIR=\"$(datadir)/frodo/\" -DBINDIR=\"$(bindir)/\" -DHAVE_SDL
LDFLAGS = -Wl,-E
LIBS = -L/usr/lib -lSDL -lSDL_ttf -pthread -lglade-2.0 -lxml2 -lgnomeui-2 -lSM -lICE -lbonoboui-2 -lgnomevfs-2 -lgnomecanvas-2 -lgnome-2 -lpopt -lbonobo-2 -lbonobo-activation -lORBit-2 -lart_lgpl_2 -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lgconf-2 -lgthread-2.0 -lrt -lgmodule-2.0 -ldl -lgobject-2.0 -lglib-2.0

View File

@ -37,9 +37,11 @@ Network::Network()
{
const size_t size = NETWORK_UPDATE_SIZE;
/* "big enough" static buffer */
/* "big enough" buffer */
this->ud = (NetworkUpdate*)malloc( size );
this->tmp_ud = (NetworkUpdate*)malloc( size );
assert(this->ud && this->tmp_ud);
this->ResetNetworkUpdate();
this->bytes_sent = 0;
@ -51,14 +53,15 @@ Network::Network()
Network::~Network()
{
free(this->ud);
free(this->tmp_ud);
}
size_t Network::EncodeDisplayRaw(struct NetworkDisplayUpdate *dst, Uint8 *screen,
size_t Network::EncodeDisplayRaw(struct NetworkUpdate *dst, Uint8 *screen,
int x_start, int y_start)
{
const int raw_w = SQUARE_W / 2;
dst->type = DISPLAY_UPDATE_RAW;
dst->type = DISPLAY_UPDATE_RAW;
for (int y = y_start; y < y_start + SQUARE_H; y++)
{
for (int x = x_start; x < x_start + SQUARE_W; x += 2)
@ -74,7 +77,7 @@ size_t Network::EncodeDisplayRaw(struct NetworkDisplayUpdate *dst, Uint8 *screen
return RAW_SIZE;
}
size_t Network::EncodeDisplayDiff(struct NetworkDisplayUpdate *dst, Uint8 *screen,
size_t Network::EncodeDisplayDiff(struct NetworkUpdate *dst, Uint8 *screen,
Uint8 *remote, int x_start, int y_start)
{
size_t out = 0;
@ -103,7 +106,7 @@ size_t Network::EncodeDisplayDiff(struct NetworkDisplayUpdate *dst, Uint8 *scree
return out;
}
size_t Network::EncodeDisplayRLE(struct NetworkDisplayUpdate *dst, Uint8 *screen,
size_t Network::EncodeDisplayRLE(struct NetworkUpdate *dst, Uint8 *screen,
int x_start, int y_start)
{
size_t out = 0;
@ -140,7 +143,7 @@ size_t Network::EncodeDisplayRLE(struct NetworkDisplayUpdate *dst, Uint8 *screen
return out;
}
size_t Network::EncodeSoundRLE(struct NetworkSoundUpdate *dst,
size_t Network::EncodeSoundRLE(struct NetworkUpdate *dst,
Uint8 *buffer, size_t buf_len)
{
size_t out = 0;
@ -163,11 +166,18 @@ size_t Network::EncodeSoundRLE(struct NetworkSoundUpdate *dst,
}
len++;
}
if (len != 0)
{
dst->data[out] = len;
dst->data[out + 1] = volume;
out += 2;
}
return out;
}
size_t Network::EncodeSoundRaw(struct NetworkSoundUpdate *dst,
size_t Network::EncodeSoundRaw(struct NetworkUpdate *dst,
Uint8 *buffer, size_t len)
{
dst->type = SOUND_UPDATE_RAW;
@ -176,13 +186,13 @@ size_t Network::EncodeSoundRaw(struct NetworkSoundUpdate *dst,
return len;
}
bool Network::DecodeDisplayDiff(Uint8 *screen, struct NetworkDisplayUpdate *src,
bool Network::DecodeDisplayDiff(Uint8 *screen, struct NetworkUpdate *src,
int x_start, int y_start)
{
int p = 0;
int x = x_start;
int y = y_start;
int sz = src->size - sizeof(NetworkDisplayUpdate);
int sz = src->size - sizeof(NetworkUpdate);
/* Something is wrong if this is true... */
if (sz % 2 != 0)
@ -204,13 +214,13 @@ bool Network::DecodeDisplayDiff(Uint8 *screen, struct NetworkDisplayUpdate *src,
return true;
}
bool Network::DecodeDisplayRLE(Uint8 *screen, struct NetworkDisplayUpdate *src,
bool Network::DecodeDisplayRLE(Uint8 *screen, struct NetworkUpdate *src,
int x_start, int y_start)
{
int p = 0;
int x = x_start;
int y = y_start;
int sz = src->size - sizeof(NetworkDisplayUpdate);
int sz = src->size - sizeof(NetworkUpdate);
/* Something is wrong if this is true... */
if (sz % 2 != 0)
@ -238,7 +248,7 @@ bool Network::DecodeDisplayRLE(Uint8 *screen, struct NetworkDisplayUpdate *src,
return true;
}
bool Network::DecodeDisplayRaw(Uint8 *screen, struct NetworkDisplayUpdate *src,
bool Network::DecodeDisplayRaw(Uint8 *screen, struct NetworkUpdate *src,
int x_start, int y_start)
{
const int raw_w = SQUARE_W / 2;
@ -260,32 +270,35 @@ bool Network::DecodeDisplayRaw(Uint8 *screen, struct NetworkDisplayUpdate *src,
}
/* Public methods */
size_t Network::EncodeDisplaySquare(struct NetworkDisplayUpdate *dst,
size_t Network::EncodeDisplaySquare(struct NetworkUpdate *dst,
Uint8 *screen, Uint8 *remote, int square)
{
const int square_x = SQUARE_TO_X(square);
const int square_y = SQUARE_TO_Y(square);
size_t out, diff_out;
dst->square = square;
dst->u.display.square = square;
/* Try encoding as RLE and diff, but if it's too large, go for RAW */
diff_out = this->EncodeDisplayDiff((NetworkDisplayUpdate*)this->tmp_ud, screen,
diff_out = this->EncodeDisplayDiff(tmp_ud, screen,
remote, square_x, square_y);
this->square_updated[square] = out | (2 << 16);
out = this->EncodeDisplayRLE(dst, screen, square_x, square_y);
this->square_updated[square] = out | (1 << 16);
if (out > diff_out) {
/* The diff is best, use that */
this->square_updated[square] = out | (2 << 16);
memcpy(dst, this->tmp_ud, out + sizeof(NetworkDisplayUpdate));
memcpy(dst->data, this->tmp_ud->data, out);
dst->type = this->tmp_ud->type;
out = diff_out;
}
if (out > RAW_SIZE) {
out = this->EncodeDisplayRaw(dst, screen, square_x, square_y);
this->square_updated[square] = out;
}
dst->size = out + sizeof(struct NetworkDisplayUpdate);
dst->size = out + sizeof(struct NetworkUpdate);
return dst->size;
}
@ -312,29 +325,27 @@ size_t Network::EncodeDisplay(Uint8 *master, Uint8 *remote)
for ( int sq = 0; sq < N_SQUARES_H * N_SQUARES_W; sq++ )
{
Uint8 *p_master = &master[ SQUARE_TO_Y(sq) * DISPLAY_X + SQUARE_TO_X(sq) ];
Uint8 *p_remote= &remote[ SQUARE_TO_Y(sq) * DISPLAY_X + SQUARE_TO_X(sq) ];
Uint8 *p_remote = &remote[ SQUARE_TO_Y(sq) * DISPLAY_X + SQUARE_TO_X(sq) ];
if (this->CompareSquare(p_master, p_remote) == false)
{
NetworkDisplayUpdate *dst = (NetworkDisplayUpdate *)this->cur_ud;
NetworkUpdate *dst = (NetworkUpdate *)this->cur_ud;
/* Updated, encode this */
this->EncodeDisplaySquare(dst, master, remote, sq);
this->AddNetworkUpdate((NetworkUpdate*)dst);
this->AddNetworkUpdate(dst);
}
else
this->square_updated[sq] = 0;
}
/* Everything encoded, store in remote */
memcpy(remote, master, DISPLAY_X * DISPLAY_Y);
}
bool Network::DecodeDisplayUpdate(Uint8 *screen,
struct NetworkDisplayUpdate *src)
struct NetworkUpdate *src)
{
int square = src->square;
int square = src->u.display.square;
const int square_x = SQUARE_TO_X(square);
const int square_y = SQUARE_TO_Y(square);
@ -349,7 +360,7 @@ bool Network::DecodeDisplayUpdate(Uint8 *screen,
return false;
}
size_t Network::EncodeSoundBuffer(struct NetworkSoundUpdate *dst, Uint8 *buf, size_t len)
size_t Network::EncodeSoundBuffer(struct NetworkUpdate *dst, Uint8 *buf, size_t len)
{
size_t out;
@ -358,26 +369,25 @@ size_t Network::EncodeSoundBuffer(struct NetworkSoundUpdate *dst, Uint8 *buf, si
out = this->EncodeSoundRLE(dst, buf, len);
if (out > len)
out = this->EncodeSoundRaw(dst, buf, len);
dst->size = out + sizeof(struct NetworkSoundUpdate);
dst->size = out + sizeof(struct NetworkUpdate);
return dst->size;
}
void Network::EncodeJoystickUpdate(struct NetworkJoystickUpdate *dst, Uint8 which, Uint8 v)
void Network::EncodeJoystickUpdate(struct NetworkUpdate *dst, Uint8 which, Uint8 v)
{
dst->type = JOYSTICK_UPDATE;
dst->which = which;
dst->data = v;
dst->u.joystick.val = v;
}
size_t Network::DecodeSoundUpdate(struct NetworkSoundUpdate *src, char *buf)
size_t Network::DecodeSoundUpdate(struct NetworkUpdate *src, char *buf)
{
size_t out;
if (src->type == SOUND_UPDATE_RAW)
{
out = src->size - sizeof(struct NetworkSoundUpdate);
out = src->size - sizeof(struct NetworkUpdate);
memcpy(buf, src->data, out);
}
else
@ -391,9 +401,9 @@ void Network::ResetNetworkUpdate(void)
memset(this->ud, 0, NETWORK_UPDATE_SIZE);
memset(this->tmp_ud, 0, NETWORK_UPDATE_SIZE);
this->ud->type = HEADER;
this->ud->type = STOP;
this->ud->size = sizeof(NetworkUpdate);
this->cur_ud = (Uint8*)(this->ud->data);
this->cur_ud = this->ud;
}
void Network::DrawTransferredBlocks(SDL_Surface *screen)
@ -415,7 +425,7 @@ void Network::DrawTransferredBlocks(SDL_Surface *screen)
SDL_Rect u = {x, y, w, 1};
SDL_Rect d = {x, y + h, w, 1};
Uint32 raw = this->square_updated[sq];
SDL_Rect size = {x, y, (raw & 0xffff) / 17, 4};
SDL_Rect size = {x, y, 2 * ((raw & 0xffff) / 17), 4};
Uint32 color = 4;
if ((raw >> 16) == 1)
@ -447,131 +457,159 @@ bool Network::ReceiveUpdateBlock(int sock)
return this->ReceiveUpdate(this->ud, sock, NULL);
}
bool Network::ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv)
{
Uint8 *pp = (Uint8*)dst;
NetworkUpdate *p;
if (this->Select(sock, tv) == false)
return false;
/* Receive until the stop */
do
{
p = (NetworkUpdate*)pp;
/* Receive the header */
if (this->ReceiveData((void*)p, sock, sizeof(NetworkUpdate)) == false)
return false;
pp = pp + sizeof(NetworkUpdate);
/* And the rest of the update */
size_t sz = ntohs(p->size);
if (sz > sizeof(NetworkUpdate))
{
size_t sz_diff = sz - sizeof(NetworkUpdate);
if (this->ReceiveData((void*)pp, sock, sz_diff) == false)
return false;
pp = pp + sz_diff;
}
if (this->DeMarshalData(p) == false)
return false;
} while ( !(p->type == STOP && p->u.stop.val == STOP) );
return true;
}
bool Network::SendUpdate(int sock)
{
NetworkUpdate *src = this->ud;
NetworkUpdate *stop = this->cur_ud;
size_t sz;
/* Add a stop at the end of the update */
stop->type = STOP;
stop->u.stop.val = STOP;
stop->size = sizeof(NetworkUpdate);
this->AddNetworkUpdate(stop);
if (this->MarshalAllData(src) == false)
return false;
sz = this->GetNetworkUpdateSize();
if (sz <= 0)
return false;
if (this->SendData((void*)src, sock, sz) == false)
return false;
this->bytes_sent += sz;
return true;
}
void Network::AddNetworkUpdate(NetworkUpdate *update)
{
size_t sz = update->size;
Uint8 *next = (Uint8*)this->cur_ud + update->size;
this->cur_ud += sz;
this->ud->size += sz;
this->cur_ud = (NetworkUpdate*)next;
}
void Network::MarshalData(NetworkUpdate *ud)
bool Network::MarshalData(NetworkUpdate *p)
{
Uint8 *p = ud->data;
int len = 0;
int sz = ud->size;
ud->size = htons(ud->size);
while (len < sz)
p->size = htons(p->size);
switch (p->type)
{
p = p + len;
switch (p[0])
{
case DISPLAY_UPDATE_RAW:
case DISPLAY_UPDATE_RLE:
case DISPLAY_UPDATE_DIFF:
case SOUND_UPDATE_RAW: /* Not really true, but looks the same */
case SOUND_UPDATE_RLE:
{
NetworkDisplayUpdate *tmp = (NetworkDisplayUpdate *)p;
len += tmp->size;
tmp->size = htons(tmp->size);
} break;
case JOYSTICK_UPDATE:
len = sizeof(NetworkJoystickUpdate);
break;
default:
/* Unknown data... */
return;
}
case DISPLAY_UPDATE_RAW:
case DISPLAY_UPDATE_RLE:
case DISPLAY_UPDATE_DIFF:
case SOUND_UPDATE_RAW:
case SOUND_UPDATE_RLE:
case JOYSTICK_UPDATE:
case STOP:
break;
default:
/* Unknown data... */
fprintf(stderr, "Got unknown data %d while marshalling. Something is wrong\n",
p->type);
return false;
}
return true;
}
void Network::DeMarshalData(NetworkUpdate *ud)
bool Network::MarshalAllData(NetworkUpdate *ud)
{
Uint8 *p = ud->data;
int len = 0;
NetworkUpdate *p = ud;
ud->size = ntohs(ud->size);
while (len < ud->size)
while (p->type != STOP)
{
p = p + len;
NetworkUpdate *nxt = this->GetNext(p);
switch (p[0])
{
case DISPLAY_UPDATE_RAW:
case DISPLAY_UPDATE_RLE:
case DISPLAY_UPDATE_DIFF:
case SOUND_UPDATE_RAW: /* Not really true, but looks the same */
case SOUND_UPDATE_RLE:
{
NetworkDisplayUpdate *tmp = (NetworkDisplayUpdate *)p;
tmp->size = ntohs(tmp->size);
len += tmp->size;
} break;
case JOYSTICK_UPDATE:
len = sizeof(NetworkJoystickUpdate);
break;
default:
/* Unknown data... */
return;
}
if (this->MarshalData(p) == false)
return false;
p = nxt;
}
/* The stop tag */
return this->MarshalData(p);
}
bool Network::DeMarshalData(NetworkUpdate *p)
{
p->size = ntohs(p->size);
switch (p->type)
{
case DISPLAY_UPDATE_RAW:
case DISPLAY_UPDATE_RLE:
case DISPLAY_UPDATE_DIFF:
case SOUND_UPDATE_RAW:
case SOUND_UPDATE_RLE:
case JOYSTICK_UPDATE:
case STOP:
/* Nothing to do, just bytes */
break;
default:
/* Unknown data... */
return false;
}
return true;
}
bool Network::DecodeUpdate(uint8 *screen)
{
unsigned int cookie;
NetworkUpdate *p;
int i = 0;
NetworkUpdate *p = this->ud;
for (p = this->IterateFirst(this->ud, &cookie); p;
p = this->IterateNext(this->ud, &cookie))
while (p->type != STOP)
{
switch(p->type)
{
case DISPLAY_UPDATE_RAW:
case DISPLAY_UPDATE_RLE:
case DISPLAY_UPDATE_DIFF:
this->DecodeDisplayUpdate(screen, (NetworkDisplayUpdate*)p);
this->DecodeDisplayUpdate(screen, p);
break;
default:
break;
}
i++;
p = this->GetNext(p);
}
}
NetworkUpdate *Network::IterateFirst(NetworkUpdate *p, unsigned int *cookie)
{
Uint8 *p8 = (Uint8*)p;
NetworkUpdate *cur = (NetworkUpdate *)p->data;
*cookie = (unsigned int)(p->data - p8);
if ( *cookie >= p->size )
return NULL;
*cookie = *cookie + cur->size;
return cur;
}
NetworkUpdate *Network::IterateNext(NetworkUpdate *p, unsigned int *cookie)
{
NetworkUpdate *cur = (NetworkUpdate *)(((Uint8*)p) + *cookie);
/* End of iteration */
if ( *cookie >= p->size || cur->size == 0)
return NULL;
*cookie = *cookie + cur->size;
return cur;
}
void NetworkServer::AddClient(int sock)
{
NetworkClient *cli = new NetworkClient(sock);

View File

@ -7,7 +7,7 @@
#define NETWORK_UPDATE_SIZE (256 * 1024)
enum
{
HEADER = 0,
STOP = 99,
DISPLAY_UPDATE_RAW = 1,
DISPLAY_UPDATE_RLE = 2,
DISPLAY_UPDATE_DIFF= 3,
@ -17,40 +17,28 @@ enum
JOYSTICK_UPDATE = 7,
};
struct NetworkDisplayUpdate
struct NetworkUpdate
{
Uint8 type; /* raw data or RLE */
Uint8 square;
Uint16 size;
Uint8 data[];
};
struct NetworkSoundUpdate
{
Uint8 type; /* raw data or RLE */
Uint8 dummy;
Uint16 size;
Uint8 data[];
};
struct NetworkJoystickUpdate
{
Uint8 type;
Uint8 which;
Uint16 size;
Uint8 data; /* New value */
};
struct NetworkUpdate
{
Uint8 type;
Uint8 dummy;
Uint16 size;
union {
struct {
Uint8 square;
} display;
struct {
Uint8 val;
} joystick;
struct {
Uint8 val; /* Should be STOP */
} stop;
} u;
/* The rest is just data of some type */
Uint8 data[];
};
class Network
{
public:
@ -81,7 +69,7 @@ public:
bool ReceiveUpdateBlock(int sock);
protected:
size_t DecodeSoundUpdate(struct NetworkSoundUpdate *src, char *buf);
size_t DecodeSoundUpdate(struct NetworkUpdate *src, char *buf);
/** Encode part of a screen into @a dst
*
@ -91,21 +79,21 @@ protected:
*
* @return the size of the encoded message
*/
size_t EncodeDisplaySquare(struct NetworkDisplayUpdate *dst,
size_t EncodeDisplaySquare(struct NetworkUpdate *dst,
Uint8 *screen, Uint8 *remote, int square);
size_t EncodeDisplayDiff(struct NetworkDisplayUpdate *dst, Uint8 *screen,
size_t EncodeDisplayDiff(struct NetworkUpdate *dst, Uint8 *screen,
int x, int y);
size_t EncodeDisplayDiff(struct NetworkDisplayUpdate *dst, Uint8 *screen,
size_t EncodeDisplayDiff(struct NetworkUpdate *dst, Uint8 *screen,
Uint8 *remote, int x, int y);
size_t EncodeDisplayRLE(struct NetworkDisplayUpdate *dst, Uint8 *screen,
size_t EncodeDisplayRLE(struct NetworkUpdate *dst, Uint8 *screen,
int x, int y);
size_t EncodeDisplayRaw(struct NetworkDisplayUpdate *dst, Uint8 *screen,
size_t EncodeDisplayRaw(struct NetworkUpdate *dst, Uint8 *screen,
int x, int y);
size_t EncodeSoundRLE(struct NetworkSoundUpdate *dst,
size_t EncodeSoundRLE(struct NetworkUpdate *dst,
Uint8 *buffer, size_t len);
size_t EncodeSoundRaw(struct NetworkSoundUpdate *dst,
size_t EncodeSoundRaw(struct NetworkUpdate *dst,
Uint8 *buffer, size_t len);
/**
@ -117,10 +105,10 @@ protected:
*
* @return the size of the encoded message
*/
size_t EncodeSoundBuffer(struct NetworkSoundUpdate *dst,
size_t EncodeSoundBuffer(struct NetworkUpdate *dst,
Uint8 *buf, size_t len);
void EncodeJoystickUpdate(struct NetworkJoystickUpdate *dst,
void EncodeJoystickUpdate(struct NetworkUpdate *dst,
Uint8 which, Uint8 v);
/**
@ -129,14 +117,15 @@ protected:
* @param screen the screen to draw to
* @param src the message to decode
*/
bool DecodeDisplayUpdate(Uint8 *screen, struct NetworkDisplayUpdate *src);
NetworkUpdate *IterateFirst(NetworkUpdate *p, unsigned int *cookie);
NetworkUpdate *IterateNext(NetworkUpdate *p, unsigned int *cookie);
bool DecodeDisplayUpdate(Uint8 *screen, struct NetworkUpdate *src);
void AddNetworkUpdate(struct NetworkUpdate *update);
size_t GetNetworkUpdateSize(void)
{
return (Uint8*)this->cur_ud - (Uint8*)this->ud;
}
/**
* Compare two display squares.
*
@ -147,22 +136,35 @@ protected:
*/
bool CompareSquare(Uint8 *a, Uint8 *b);
bool DecodeDisplayDiff(Uint8 *screen, struct NetworkDisplayUpdate *src,
bool DecodeDisplayDiff(Uint8 *screen, struct NetworkUpdate *src,
int x, int y);
bool DecodeDisplayRLE(Uint8 *screen, struct NetworkDisplayUpdate *src,
bool DecodeDisplayRLE(Uint8 *screen, struct NetworkUpdate *src,
int x, int y);
bool DecodeDisplayRaw(Uint8 *screen, struct NetworkDisplayUpdate *src,
bool DecodeDisplayRaw(Uint8 *screen, struct NetworkUpdate *src,
int x, int y);
bool ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv);
void MarshalData(NetworkUpdate *ud);
bool ReceiveData(void *dst, int sock, size_t sz);
void DeMarshalData(NetworkUpdate *ud);
bool SendData(void *src, int sock, size_t sz);
virtual bool Select(int sock, struct timeval *tv);
bool MarshalData(NetworkUpdate *ud);
bool MarshalAllData(NetworkUpdate *p);
bool DeMarshalData(NetworkUpdate *ud);
NetworkUpdate *GetNext(NetworkUpdate *p)
{
return (NetworkUpdate*)((Uint8*)p + p->size);
}
NetworkUpdate *ud;
NetworkUpdate *tmp_ud;
Uint8 *cur_ud;
NetworkUpdate *cur_ud;
size_t bytes_sent;
Uint32 *square_updated;
};
@ -191,12 +193,13 @@ public:
return ((Network*)this)->ReceiveUpdate(this->sock);
}
bool ReceiveUpdateBlock()
{
return ((Network*)this)->ReceiveUpdateBlock(this->sock);
}
bool ReceiveData(void *dst, int sock, size_t sz);
Uint8 *screen;
int joystick_port;
private:

View File

@ -138,10 +138,41 @@ NetworkClient::NetworkClient(const char *hostname, int port)
memset(this->screen, 0, DISPLAY_X * DISPLAY_Y);
}
bool Network::ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv)
bool Network::ReceiveData(void *dst, int sock, size_t sz)
{
size_t received_sz = 0;
while (received_sz < sz)
{
int v = read(sock, dst, sz);
if (v < 0)
return false;
received_sz += v;
}
return sz > 0;
}
bool Network::SendData(void *src, int sock, size_t sz)
{
size_t sent_sz = 0;
while (sent_sz < sz)
{
int v = write(sock, (void*)src, sz);
if (v < 0)
return false;
sent_sz += v;
}
return true;
}
bool Network::Select(int sock, struct timeval *tv)
{
fd_set fds;
int sz;
int v;
FD_ZERO(&fds);
@ -150,32 +181,10 @@ bool Network::ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv)
v = select(sock + 1, &fds, NULL, NULL, tv);
if (v < 0)
{
fprintf(stderr, "Select failed\n");
return false;
fprintf(stderr, "Select failed\n");
return false;
}
sz = read(sock, (void*)dst, NETWORK_UPDATE_SIZE);
if (sz < 0)
return false;
/* Byte swap stuff */
this->DeMarshalData(dst);
return true;
}
bool Network::SendUpdate(int sock)
{
NetworkUpdate *src = this->ud;
int sz = src->size;
bool out = true;
this->bytes_sent += sz;
this->MarshalData(src);
sz = write(sock, (void*)src, sz);
if (sz < src->size)
out = false;
return out;
/* v is 0 if the sock is not ready */
return v > 0;
}