From 5eca531105bd9ceda111275887d60552e954b542 Mon Sep 17 00:00:00 2001 From: "simon.kagstrom" Date: Mon, 26 Jan 2009 21:00:23 +0000 Subject: [PATCH] Corrected the diff implementation, refactored the networking implementation --- CHANGES.WII | 6 + Src/C64_SDL.h | 3 +- Src/Makefile | 2 +- Src/Network.cpp | 286 ++++++++++++++++++++++++++-------------------- Src/Network.h | 99 ++++++++-------- Src/NetworkUnix.h | 65 ++++++----- 6 files changed, 259 insertions(+), 202 deletions(-) diff --git a/CHANGES.WII b/CHANGES.WII index 7ffda16..1eedbdf 100644 --- a/CHANGES.WII +++ b/CHANGES.WII @@ -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 , version 6: diff --git a/Src/C64_SDL.h b/Src/C64_SDL.h index ae2312d..245d532 100644 --- a/Src/C64_SDL.h +++ b/Src/C64_SDL.h @@ -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(); diff --git a/Src/Makefile b/Src/Makefile index 0b0db09..a3b4fe9 100644 --- a/Src/Makefile +++ b/Src/Makefile @@ -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 diff --git a/Src/Network.cpp b/Src/Network.cpp index ad2a0aa..d86c24c 100644 --- a/Src/Network.cpp +++ b/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->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); diff --git a/Src/Network.h b/Src/Network.h index 7fa93be..c350739 100644 --- a/Src/Network.h +++ b/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 +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: diff --git a/Src/NetworkUnix.h b/Src/NetworkUnix.h index 94219c7..a2accfe 100644 --- a/Src/NetworkUnix.h +++ b/Src/NetworkUnix.h @@ -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; }