mirror of
https://github.com/Oibaf66/frodo-wii.git
synced 2024-11-10 21:55:11 +01:00
Corrected the diff implementation, refactored the networking
implementation
This commit is contained in:
parent
f693404434
commit
5eca531105
@ -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:
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
252
Src/Network.cpp
252
Src/Network.cpp
@ -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 = p + len;
|
||||
|
||||
switch (p[0])
|
||||
p->size = htons(p->size);
|
||||
switch (p->type)
|
||||
{
|
||||
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_RAW:
|
||||
case SOUND_UPDATE_RLE:
|
||||
{
|
||||
NetworkDisplayUpdate *tmp = (NetworkDisplayUpdate *)p;
|
||||
|
||||
len += tmp->size;
|
||||
tmp->size = htons(tmp->size);
|
||||
} break;
|
||||
case JOYSTICK_UPDATE:
|
||||
len = sizeof(NetworkJoystickUpdate);
|
||||
case STOP:
|
||||
break;
|
||||
default:
|
||||
/* Unknown data... */
|
||||
return;
|
||||
}
|
||||
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])
|
||||
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: /* Not really true, but looks the same */
|
||||
case SOUND_UPDATE_RAW:
|
||||
case SOUND_UPDATE_RLE:
|
||||
{
|
||||
NetworkDisplayUpdate *tmp = (NetworkDisplayUpdate *)p;
|
||||
|
||||
tmp->size = ntohs(tmp->size);
|
||||
len += tmp->size;
|
||||
} break;
|
||||
case JOYSTICK_UPDATE:
|
||||
len = sizeof(NetworkJoystickUpdate);
|
||||
case STOP:
|
||||
/* Nothing to do, just bytes */
|
||||
break;
|
||||
default:
|
||||
/* Unknown data... */
|
||||
return;
|
||||
}
|
||||
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);
|
||||
|
101
Src/Network.h
101
Src/Network.h
@ -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
|
||||
{
|
||||
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;
|
||||
Uint8 type;
|
||||
|
||||
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:
|
||||
|
@ -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);
|
||||
@ -153,29 +184,7 @@ bool Network::ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv)
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user