From 83d797ede36800aa9d2d3da728bc9c9563e69478 Mon Sep 17 00:00:00 2001 From: "simon.kagstrom" Date: Sat, 24 Jan 2009 20:57:23 +0000 Subject: [PATCH] Somewhat working networking (hey - hardcoding!) --- Src/C64_SDL.h | 76 ++++++++++++++++++++++++++++----------------- Src/Display.h | 1 + Src/Display_SDL.h | 7 +++-- Src/Makefile | 2 +- Src/Network.cpp | 79 +++++++++++++++++++++++++++++++++++------------ Src/Network.h | 18 ++++++++--- Src/NetworkUnix.h | 20 +++++++++--- Src/main_x.h | 10 ++++-- 8 files changed, 150 insertions(+), 63 deletions(-) diff --git a/Src/C64_SDL.h b/Src/C64_SDL.h index 39bd8a4..03a42ed 100644 --- a/Src/C64_SDL.h +++ b/Src/C64_SDL.h @@ -24,6 +24,11 @@ #define TMP_PATH "tmp" #endif +/* TODO: */ +extern int fixme_tmp_network_client; +extern int fixme_tmp_network_server; + + static struct timeval tv_start; static const char *main_menu_messages[] = { "Invoke key sequence", /* 0 */ @@ -96,6 +101,12 @@ void C64::c64_ctor1(void) strncpy(this->server_hostname, "localhost", sizeof(this->server_hostname)); this->server_port = 19760; + + if (fixme_tmp_network_server) + this->network_server = new NetworkServer(this->server_port); + if (fixme_tmp_network_client) + this->network_client = new NetworkClient(this->server_hostname, + this->server_port); } void C64::c64_ctor2(void) @@ -549,6 +560,10 @@ void C64::Run(void) void C64::VBlank(bool draw_frame) { + /* From Acorn port */ + static uint64_t lastFrame; + static uint32_t now; + #if defined(GEKKO) WPAD_ScanPads(); #endif @@ -577,33 +592,17 @@ void C64::VBlank(bool draw_frame) TheCIA2->CountTOD(); // Update window if needed - if (draw_frame) { + if (draw_frame && this->network_client == NULL) { TheDisplay->Update(); -#if 0 - // Calculate time between VBlanks, display speedometer - struct timeval tv; - gettimeofday(&tv, NULL); - if ((tv.tv_usec -= tv_start.tv_usec) < 0) { - tv.tv_usec += 1000000; - tv.tv_sec -= 1; - } - tv.tv_sec -= tv_start.tv_sec; - double elapsed_time = (double)tv.tv_sec * 1000000 + tv.tv_usec; - speed_index = 20000 / (elapsed_time + 1) * 100; - - // Limit speed to 100% if desired - if ((speed_index > 100)) { - usleep((unsigned long)(20000 - elapsed_time)); - speed_index = 100; - } - - gettimeofday(&tv_start, NULL); - - TheDisplay->Speedometer((int)speed_index); -#endif } - if (this->network_server) { - /* Perhaps accept a new connection */ + static int frms = 1; + frms--; + if (this->network_server && frms == 0) { + static uint32_t last_time_update; + static size_t bytes_sent; + + frms = 6; + /* Perhaps accept a new connection */ this->network_server->CheckNewConnection(); for (int i = 0; i < this->network_server->n_clients; i++) { @@ -613,6 +612,27 @@ void C64::VBlank(bool draw_frame) remote->EncodeDisplay(master, remote->screen); remote->SendUpdate(); remote->ResetNetworkUpdate(); + + bytes_sent += remote->GetBytesSent(); + } + if (now - last_time_update > 1000) + { + printf("%.2f kbytes / second\n", + ((bytes_sent * 1000.0) / ((float)now - last_time_update)) / 1024.0); + for (int i = 0; i < this->network_server->n_clients; i++) + this->network_server->clients[i]->ResetBytesSent(); + bytes_sent = 0; + last_time_update = now; + } + } + else if (this->network_client) { + /* Got something? */ + if (this->network_client->ReceiveUpdateBlock()) + { + this->network_client->DecodeUpdate( + this->network_client->screen); + TheDisplay->Update(this->network_client->screen); + this->network_client->ResetNetworkUpdate(); } } if (this->have_a_break) { @@ -676,12 +696,10 @@ void C64::VBlank(bool draw_frame) if (this->quit_thyself) ThePrefs.Save(PREFS_PATH); } - /* From Acorn port */ - static uint64_t lastFrame; #if defined(GEKKO) - uint32_t now = ticks_to_millisecs(gettime()); + now = ticks_to_millisecs(gettime()); #else - uint32_t now = SDL_GetTicks(); + now = SDL_GetTicks(); #endif if ( (now - lastFrame) < ThePrefs.MsPerFrame) { diff --git a/Src/Display.h b/Src/Display.h index 80824ff..a5ec532 100644 --- a/Src/Display.h +++ b/Src/Display.h @@ -82,6 +82,7 @@ public: void FakeKeyPress(int kc, uint8 *CIA_key_matrix, uint8 *CIA_rev_matrix); void TranslateKey(SDLKey key, bool key_up, uint8 *key_matrix, uint8 *rev_matrix, uint8 *joystick); void UpdateKeyMatrix(int c64_key, bool key_up, uint8 *key_matrix, uint8 *rev_matrix); + void Update(uint8 *src_pixels); #endif bool NumLock(void); void InitColors(uint8 *colors); diff --git a/Src/Display_SDL.h b/Src/Display_SDL.h index 781b57e..056ff4d 100644 --- a/Src/Display_SDL.h +++ b/Src/Display_SDL.h @@ -176,9 +176,8 @@ void C64Display::NewPrefs(Prefs *prefs) * Redraw bitmap */ -void C64Display::Update(void) +void C64Display::Update(uint8 *src_pixels) { - Uint8 *src_pixels = (Uint8*)screen; const Uint16 src_pitch = DISPLAY_X; if (ThePrefs.DisplayOption == 0) { @@ -228,6 +227,10 @@ void C64Display::Update(void) SDL_Flip(real_screen); } +void C64Display::Update() +{ + this->Update((Uint8*)screen); +} /* * Draw string into surface using the C64 ROM font diff --git a/Src/Makefile b/Src/Makefile index 22fc98b..0b0db09 100644 --- a/Src/Makefile +++ b/Src/Makefile @@ -17,7 +17,7 @@ DESTDIR = CXX = g++ CC = gcc -CFLAGS =-DFRODO_SC -g -O2 -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 -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 33e3baa..70230e6 100644 --- a/Src/Network.cpp +++ b/Src/Network.cpp @@ -22,8 +22,8 @@ #include "Network.h" #include "Display.h" -#define N_SQUARES_W 20 -#define N_SQUARES_H 20 +#define N_SQUARES_W 16 +#define N_SQUARES_H 8 #define SQUARE_W (DISPLAY_X / N_SQUARES_W) #define SQUARE_H (DISPLAY_Y / N_SQUARES_H) @@ -40,6 +40,7 @@ Network::Network() /* "big enough" static buffer */ this->ud = (NetworkUpdate*)malloc( size ); this->ResetNetworkUpdate(); + this->bytes_sent = 0; } Network::~Network() @@ -53,9 +54,9 @@ size_t Network::EncodeDisplayRaw(struct NetworkDisplayUpdate *dst, Uint8 *screen const int raw_w = SQUARE_W / 2; dst->type = DISPLAY_UPDATE_RAW; - for (int y = y_start; y < y_start + SQUARE_W; y++) + for (int y = y_start; y < y_start + SQUARE_H; y++) { - for (int x = x_start; x < x_start + SQUARE_H; x += 2) + for (int x = x_start; x < x_start + SQUARE_W; x += 2) { Uint8 a = screen[ y * DISPLAY_X + x ]; Uint8 b = screen[ y * DISPLAY_X + (x + 1) ]; @@ -77,9 +78,9 @@ size_t Network::EncodeDisplayRLE(struct NetworkDisplayUpdate *dst, Uint8 *screen dst->type = DISPLAY_UPDATE_RLE; - for (int y = y_start; y < y_start + SQUARE_W; y++) + for (int y = y_start; y < y_start + SQUARE_H; y++) { - for (int x = x_start; x < x_start + SQUARE_H; x++) + for (int x = x_start; x < x_start + SQUARE_W; x++) { if (color != screen[ y * DISPLAY_X + x ] || len >= 255) @@ -94,6 +95,13 @@ size_t Network::EncodeDisplayRLE(struct NetworkDisplayUpdate *dst, Uint8 *screen len++; } } + if (len != 0) + { + dst->data[out] = len; + dst->data[out + 1] = color; + + out += 2; + } return out; } @@ -141,12 +149,13 @@ bool Network::DecodeDisplayRLE(Uint8 *screen, struct NetworkDisplayUpdate *src, int p = 0; int x = x_start; int y = y_start; + int sz = src->size - sizeof(NetworkDisplayUpdate); /* Something is wrong if this is true... */ - if (src->size % 2 != 0) + if (sz % 2 != 0) return false; - while (p < src->size) + while (p < sz) { Uint8 len = src->data[p]; Uint8 color = src->data[p+1]; @@ -173,9 +182,9 @@ bool Network::DecodeDisplayRaw(Uint8 *screen, struct NetworkDisplayUpdate *src, { const int raw_w = SQUARE_W / 2; - for (int y = y_start; y < y_start + SQUARE_W; y++) + for (int y = y_start; y < y_start + SQUARE_H; y++) { - for (int x = x_start; x < x_start + SQUARE_H; x += 2) + for (int x = x_start; x < x_start + SQUARE_W; x += 2) { Uint8 v = src->data[(y - y_start) * raw_w + (x - x_start) / 2]; Uint8 a = v >> 4; @@ -216,7 +225,7 @@ bool Network::CompareSquare(Uint8 *a, Uint8 *b) Uint8 va = a[ y * DISPLAY_X + x ]; Uint8 vb = b[ y * DISPLAY_X + x ]; - if (va == vb) + if (va != vb) return false; } } @@ -305,7 +314,7 @@ void Network::ResetNetworkUpdate(void) this->ud->type = HEADER; this->ud->size = sizeof(NetworkUpdate); - this->cur_ud = (Uint8*)(this->ud + sizeof(NetworkUpdate)); + this->cur_ud = (Uint8*)(this->ud->data); } @@ -323,6 +332,15 @@ bool Network::ReceiveUpdateBlock(int sock) return this->ReceiveUpdate(this->ud, sock, NULL); } +void Network::AddNetworkUpdate(NetworkUpdate *update) +{ + size_t sz = update->size; + + this->cur_ud += sz; + this->ud->size += sz; +} + + void Network::MarshalData(NetworkUpdate *ud) { Uint8 *p = ud->data; @@ -330,7 +348,7 @@ void Network::MarshalData(NetworkUpdate *ud) int sz = ud->size; ud->size = htons(ud->size); - while (len < ud->size) + while (len < sz) { p = p + len; @@ -343,7 +361,7 @@ void Network::MarshalData(NetworkUpdate *ud) { NetworkDisplayUpdate *tmp = (NetworkDisplayUpdate *)p; - len = tmp->size; + len += tmp->size; tmp->size = htons(tmp->size); } break; case JOYSTICK_UPDATE: @@ -375,8 +393,8 @@ void Network::DeMarshalData(NetworkUpdate *ud) { NetworkDisplayUpdate *tmp = (NetworkDisplayUpdate *)p; - len = tmp->size; - tmp->size = ntohl(tmp->size); + tmp->size = ntohs(tmp->size); + len += tmp->size; } break; case JOYSTICK_UPDATE: len = sizeof(NetworkJoystickUpdate); @@ -388,6 +406,28 @@ void Network::DeMarshalData(NetworkUpdate *ud) } } +bool Network::DecodeUpdate(uint8 *screen) +{ + unsigned int cookie; + NetworkUpdate *p; + int i = 0; + + for (p = this->IterateFirst(this->ud, &cookie); p; + p = this->IterateNext(this->ud, &cookie)) + { + switch(p->type) + { + case DISPLAY_UPDATE_RAW: + case DISPLAY_UPDATE_RLE: + this->DecodeDisplayUpdate(screen, (NetworkDisplayUpdate*)p); + break; + default: + break; + } + i++; + } +} + NetworkUpdate *Network::IterateFirst(NetworkUpdate *p, unsigned int *cookie) { Uint8 *p8 = (Uint8*)p; @@ -398,15 +438,15 @@ NetworkUpdate *Network::IterateFirst(NetworkUpdate *p, unsigned int *cookie) return NULL; *cookie = *cookie + cur->size; - return (NetworkUpdate *)p->data; + return cur; } NetworkUpdate *Network::IterateNext(NetworkUpdate *p, unsigned int *cookie) { - NetworkUpdate *cur = (NetworkUpdate *)(p->data + *cookie); + NetworkUpdate *cur = (NetworkUpdate *)(((Uint8*)p) + *cookie); /* End of iteration */ - if ( *cookie >= p->size ) + if ( *cookie >= p->size || cur->size == 0) return NULL; *cookie = *cookie + cur->size; @@ -439,5 +479,4 @@ NetworkClient::~NetworkClient() free(this->screen); } - #include "NetworkUnix.h" diff --git a/Src/Network.h b/Src/Network.h index a225ea9..1809637 100644 --- a/Src/Network.h +++ b/Src/Network.h @@ -95,6 +95,8 @@ public: size_t DecodeSoundUpdate(struct NetworkSoundUpdate *src, char *buf); + bool DecodeUpdate(uint8 *screen); + void ResetNetworkUpdate(void); bool SendUpdate(int sock); @@ -103,6 +105,14 @@ public: bool ReceiveUpdateBlock(int sock); + size_t GetBytesSent() { + return this->bytes_sent; + } + + void ResetBytesSent() { + this->bytes_sent = 0; + } + private: size_t EncodeDisplayRLE(struct NetworkDisplayUpdate *dst, Uint8 *screen, int x, int y); @@ -117,11 +127,8 @@ private: NetworkUpdate *IterateNext(NetworkUpdate *p, unsigned int *cookie); - void AddNetworkUpdate(struct NetworkUpdate *update) - { - this->cur_ud += update->size; - this->ud->size += update->size; - } + void AddNetworkUpdate(struct NetworkUpdate *update); + /** * Compare two display squares. * @@ -145,6 +152,7 @@ private: NetworkUpdate *ud; Uint8 *cur_ud; + size_t bytes_sent; }; class NetworkClient : public Network diff --git a/Src/NetworkUnix.h b/Src/NetworkUnix.h index 7bc12fb..3095820 100644 --- a/Src/NetworkUnix.h +++ b/Src/NetworkUnix.h @@ -7,8 +7,9 @@ /* From glibc docs */ static int make_socket (uint16_t port) { - int sock; struct sockaddr_in name; + int sock; + int d = 1; /* Create the socket. */ sock = socket (PF_INET, SOCK_STREAM, 0); @@ -18,6 +19,11 @@ static int make_socket (uint16_t port) exit (EXIT_FAILURE); } + if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR, &d, sizeof(int)) < 0) { + perror("setsockopt"); + exit(1); + } + /* Give the socket a name. */ name.sin_family = AF_INET; name.sin_port = htons (port); @@ -89,6 +95,7 @@ bool NetworkServer::CheckNewConnection() else if ( v == 0 ) return false; + size = sizeof(client_name); client_sock = accept(this->listen_sock, (struct sockaddr*)&client_name, &size); if (client_sock < 0) { @@ -96,7 +103,6 @@ bool NetworkServer::CheckNewConnection() return false; } - printf("Nej men vobb! En klient har konnektat!\n"); /* And add the new one! */ this->AddClient(client_sock); @@ -125,7 +131,11 @@ NetworkClient::NetworkClient(const char *hostname, int port) return; } - NetworkClient::NetworkClient(this->sock); + this->screen = (Uint8 *)malloc(DISPLAY_X * DISPLAY_Y); + assert(this->screen); + + /* Assume black screen */ + memset(this->screen, 0, DISPLAY_X * DISPLAY_Y); } bool Network::ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv) @@ -137,7 +147,7 @@ bool Network::ReceiveUpdate(NetworkUpdate *dst, int sock, struct timeval *tv) FD_ZERO(&fds); FD_SET(sock, &fds); - v = select(1, &fds, NULL, NULL, tv); + v = select(sock + 1, &fds, NULL, NULL, tv); if (v < 0) { fprintf(stderr, "Select failed\n"); @@ -160,6 +170,8 @@ bool Network::SendUpdate(int sock) int sz = src->size; bool out = true; + this->bytes_sent += sz; + this->MarshalData(src); sz = write(sock, (void*)src, sz); if (sz < src->size) diff --git a/Src/main_x.h b/Src/main_x.h index 9ee8d3a..30bf3f6 100644 --- a/Src/main_x.h +++ b/Src/main_x.h @@ -100,11 +100,17 @@ Frodo::Frodo() /* * Process command line arguments */ +int fixme_tmp_network_client = 0; +int fixme_tmp_network_server = 0; void Frodo::ArgvReceived(int argc, char **argv) { - if (argc == 2) - strncpy(prefs_path, argv[1], 255); + if (argc == 2 && + strcmp(argv[1], "-s") == 0) + fixme_tmp_network_server = 1; + if (argc == 2 && + strcmp(argv[1], "-c") == 0) + fixme_tmp_network_client = 1; }