From 42a6e19e0d0351aff7333b4564221c2d7649b474 Mon Sep 17 00:00:00 2001 From: "simon.kagstrom" Date: Thu, 9 Apr 2009 13:42:49 +0000 Subject: [PATCH] Implemented sound transfer over the network (for Linux). This hasn't been even the least tested yet, so don't try this code. You have been warned! --- Src/C64_SDL.h | 9 +++++---- Src/Network.cpp | 49 +++++++++++++++++++++++++++++++++---------------- Src/Network.h | 8 +++++--- Src/SID.cpp | 1 + Src/SID.h | 8 ++++++++ Src/SID_linux.h | 19 +++++++++++++------ Src/SID_wii.h | 4 +++- 7 files changed, 68 insertions(+), 30 deletions(-) diff --git a/Src/C64_SDL.h b/Src/C64_SDL.h index 0c9f42e..ea7d3e9 100644 --- a/Src/C64_SDL.h +++ b/Src/C64_SDL.h @@ -608,7 +608,8 @@ void C64::network_vblank() /* Has the peer sent any data? */ if (remote->ReceiveUpdate() == true) { - if (remote->DecodeUpdate(remote->GetScreen(), js) == false) + if (remote->DecodeUpdate(remote->GetScreen(), + js, this->TheSID) == false) { /* Disconnect or sending crap, remove this guy! */ delete remote; @@ -621,16 +622,16 @@ void C64::network_vblank() remote->ResetNetworkUpdate(); if (this->network_connection_type == MASTER && - remote->ThrottleTraffic()) { + !remote->ThrottleTraffic()) { /* Skip this frame if the data rate is too high */ has_throttled = true; - return; + remote->EncodeDisplay(master, remote->GetScreen()); } /* Perhaps send updates to the other side (what is determined by * if this is the master or not) */ remote->EncodeJoystickUpdate(*js); - remote->EncodeDisplay(master, remote->GetScreen()); + remote->EncodeSound(); if (remote->SendUpdate() == false) { diff --git a/Src/Network.cpp b/Src/Network.cpp index c94a758..9eeff08 100644 --- a/Src/Network.cpp +++ b/Src/Network.cpp @@ -48,7 +48,7 @@ Network::Network(const char *remote_host, int port, bool is_master) this->InitNetwork(); - this->is_master = is_master; + Network::is_master = is_master; this->connected = false; /* "big enough" buffer */ @@ -262,7 +262,7 @@ bool Network::CompareSquare(Uint8 *a, Uint8 *b) void Network::EncodeDisplay(Uint8 *master, Uint8 *remote) { - if (!this->is_master) + if (!Network::is_master) return; for ( int sq = 0; sq < N_SQUARES_H * N_SQUARES_W; sq++ ) { @@ -408,8 +408,8 @@ size_t Network::EncodeSoundBuffer(struct NetworkUpdate *dst, Uint8 *buf, size_t printf("Not implemented\n"); dst->size = 0; /* Try encoding as RLE, but if it's too large, go for RAW */ - out = this->EncodeSoundRLE(dst, buf, len); - if (out > len) +// out = this->EncodeSoundRLE(dst, buf, len); +// if (out > len) out = this->EncodeSoundRaw(dst, buf, len); dst->size = out + sizeof(struct NetworkUpdate); @@ -418,14 +418,29 @@ size_t Network::EncodeSoundBuffer(struct NetworkUpdate *dst, Uint8 *buf, size_t void Network::EncodeSound() { + NetworkUpdate *dst = (NetworkUpdate *)this->cur_ud; + static Uint8 tmp_buf[NETWORK_SOUND_BUF_SIZE]; + int offset = 0; + /* Nothing to encode? */ - if (!this->is_master || + if (!Network::is_master || Network::sample_head == Network::sample_tail) return; - while (Network::sample_tail != Network::sample_head) + + if (Network::sample_tail > Network::sample_head) { - Network::sample_tail = (Network::sample_tail + 1) % NETWORK_SOUND_BUF_SIZE; + memcpy(tmp_buf + offset, Network::sample_buf + Network::sample_tail, + NETWORK_SOUND_BUF_SIZE - Network::sample_tail); + offset += NETWORK_SOUND_BUF_SIZE - Network::sample_tail; + Network::sample_tail = 0; } + memcpy(tmp_buf + offset, Network::sample_buf + Network::sample_tail, + Network::sample_head - Network::sample_tail); + offset += Network::sample_head - Network::sample_tail; + Network::sample_tail = Network::sample_head; + + this->EncodeSoundBuffer(dst, tmp_buf, offset); + this->AddNetworkUpdate(dst); } void Network::PushSound(uint8 vol) @@ -439,7 +454,7 @@ void Network::EncodeJoystickUpdate(Uint8 v) struct NetworkUpdate *dst = this->cur_ud; struct NetworkUpdateJoystick *j = (NetworkUpdateJoystick *)dst->data; - if (this->is_master || this->cur_joystick_data == v) + if (Network::is_master || this->cur_joystick_data == v) return; dst = InitNetworkUpdate(dst, JOYSTICK_UPDATE, sizeof(NetworkUpdate) + sizeof(NetworkUpdateJoystick)); @@ -450,14 +465,15 @@ void Network::EncodeJoystickUpdate(Uint8 v) } -size_t Network::DecodeSoundUpdate(struct NetworkUpdate *src, char *buf) +size_t Network::DecodeSoundUpdate(struct NetworkUpdate *src, MOS6581 *dst) { size_t out; if (src->type == SOUND_UPDATE_RAW) { out = src->size - sizeof(struct NetworkUpdate); - memcpy(buf, src->data, out); + for (int i = 0; i < out; i++) + dst->PushVolume(src->data[i]); } else out = 0; @@ -790,7 +806,7 @@ bool Network::DeMarshalAllData(NetworkUpdate *ud, size_t max_size, return this->DeMarshalData(p); } -bool Network::DecodeUpdate(uint8 *screen, uint8 *js) +bool Network::DecodeUpdate(uint8 *screen, uint8 *js, MOS6581 *dst) { NetworkUpdate *p = this->ud; bool out = true; @@ -803,14 +819,14 @@ bool Network::DecodeUpdate(uint8 *screen, uint8 *js) case DISPLAY_UPDATE_RLE: case DISPLAY_UPDATE_DIFF: /* No screen updates _to_ the master */ - if (this->is_master) + if (Network::is_master) break; if (this->DecodeDisplayUpdate(screen, p) == false) out = false; break; case JOYSTICK_UPDATE: /* No joystick updates _from_ the master */ - if (js && this->is_master) + if (js && Network::is_master) { NetworkUpdateJoystick *j = (NetworkUpdateJoystick *)p->data; *js = j->val; @@ -842,7 +858,7 @@ bool Network::ConnectToBroker() NetworkUpdatePeerInfo *pi = (NetworkUpdatePeerInfo *)ud->data; bool out; - pi->is_master = this->is_master; + pi->is_master = Network::is_master; pi->key = ThePrefs.NetworkKey; pi->version = FRODO_NETWORK_PROTOCOL_VERSION; strcpy((char*)pi->name, ThePrefs.NetworkName); @@ -1062,7 +1078,7 @@ network_connection_error_t Network::ConnectFSM() case CONN_CONNECT_TO_BROKER: if (this->ConnectToBroker() == true) { - if (this->is_master) + if (Network::is_master) this->network_connection_state = CONN_WAIT_FOR_PEER_ADDRESS; else this->network_connection_state = CONN_WAIT_FOR_PEER_LIST; @@ -1117,7 +1133,7 @@ bool Network::Connect() 0x00, 0x80, 0x80)); menu_print_font(real_screen, 255,255,0, 30, 30, "Connecting... Hold Esc or 1 to abort"); - if (this->is_master) + if (Network::is_master) menu_print_font(real_screen, 255,255,0, 30, 50, "(Waiting for client connection)"); SDL_Flip(real_screen); @@ -1186,6 +1202,7 @@ void Network::Disconnect() uint8 Network::sample_buf[NETWORK_SOUND_BUF_SIZE]; int Network::sample_head; int Network::sample_tail; +bool Network::is_master = true; /* Assume until set false */ #if defined(GEKKO) #include "NetworkWii.h" diff --git a/Src/Network.h b/Src/Network.h index dd88c1d..ef0e8e8 100644 --- a/Src/Network.h +++ b/Src/Network.h @@ -8,6 +8,8 @@ #endif #include +#include "SID.h" + #define FRODO_NETWORK_PROTOCOL_VERSION 2 #define FRODO_NETWORK_MAGIC 0x1976 @@ -150,7 +152,7 @@ public: void EncodeJoystickUpdate(Uint8 v); - bool DecodeUpdate(uint8 *screen, uint8 *js); + bool DecodeUpdate(uint8 *screen, uint8 *js, MOS6581 *dst); void ResetNetworkUpdate(void); @@ -199,12 +201,13 @@ public: static void PushSound(uint8 vol); + static bool is_master; /* Some peers are more equal than others */ protected: void InitNetwork(); void ShutdownNetwork(); - size_t DecodeSoundUpdate(struct NetworkUpdate *src, char *buf); + size_t DecodeSoundUpdate(struct NetworkUpdate *src, MOS6581 *dst); size_t EncodeSoundRLE(struct NetworkUpdate *dst, Uint8 *buffer, size_t len); @@ -339,7 +342,6 @@ protected: Uint8 *screen; int joystick_port; - bool is_master; /* Some peers are more equal than others */ bool connected; Uint8 cur_joystick_data; diff --git a/Src/SID.cpp b/Src/SID.cpp index 78aa2b4..cdb8412 100644 --- a/Src/SID.cpp +++ b/Src/SID.cpp @@ -363,6 +363,7 @@ public: virtual ~DigitalRenderer(); virtual void Reset(void); + virtual void PushVolume(uint8 volume); virtual void EmulateLine(void); virtual void WriteRegister(uint16 adr, uint8 byte); virtual void NewPrefs(Prefs *prefs); diff --git a/Src/SID.h b/Src/SID.h index 4286907..3523096 100644 --- a/Src/SID.h +++ b/Src/SID.h @@ -49,6 +49,7 @@ public: void GetState(MOS6581State *ss); void SetState(MOS6581State *ss); void EmulateLine(void); + void PushVolume(uint8); /* For the network */ private: void open_close_renderer(int old_type, int new_type); @@ -66,6 +67,7 @@ public: virtual ~SIDRenderer() {} virtual void Reset(void)=0; virtual void EmulateLine(void)=0; + virtual void PushVolume(uint8)=0; virtual void WriteRegister(uint16 adr, uint8 byte)=0; virtual void NewPrefs(Prefs *prefs)=0; virtual void Pause(void)=0; @@ -122,6 +124,12 @@ inline void MOS6581::EmulateLine(void) } +inline void MOS6581::PushVolume(uint8 vol) +{ + if (the_renderer != NULL) + the_renderer->PushVolume(vol); +} + /* * Read from register */ diff --git a/Src/SID_linux.h b/Src/SID_linux.h index 8a97869..cbe4e03 100644 --- a/Src/SID_linux.h +++ b/Src/SID_linux.h @@ -36,7 +36,7 @@ #define HAVE_CWSID 1 #include "VIC.h" - +#include "Network.h" /* * Initialization @@ -115,16 +115,13 @@ void DigitalRenderer::Resume(void) * Fill buffer, sample volume (for sampled voice) */ -void DigitalRenderer::EmulateLine(void) +void DigitalRenderer::PushVolume(uint8 vol) { static int divisor = 0; static int to_output = 0; static int buffer_pos = 0; - if (!ready) - return; - - sample_buf[sample_in_ptr] = volume; + sample_buf[sample_in_ptr] = vol; sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE; // Now see how many samples have to be added for this line @@ -143,6 +140,15 @@ void DigitalRenderer::EmulateLine(void) } } +void DigitalRenderer::EmulateLine(void) +{ + if (!ready) + return; + Network::PushSound(volume); + if (Network::is_master) + this->PushVolume(volume); +} + /* * Renderer for Catweasel card @@ -156,6 +162,7 @@ public: virtual void Reset(void); virtual void EmulateLine(void) {} + virtual void PushVolume(uint8) {} virtual void WriteRegister(uint16 adr, uint8 byte); virtual void NewPrefs(Prefs *prefs) {} virtual void Pause(void) {} diff --git a/Src/SID_wii.h b/Src/SID_wii.h index cdd652a..069b5b0 100644 --- a/Src/SID_wii.h +++ b/Src/SID_wii.h @@ -2,12 +2,13 @@ * SID_linux.i - 6581 emulation, Linux specific stuff * * Frodo (C) 1994-1997,2002 Christian Bauer - * Linux sound stuff by Bernd Schmidt + * Wii sound stuff by Simon Kagstrom */ #include "gcaudio.h" #include "VIC.h" +#include "Network.h" /* * Initialization @@ -69,6 +70,7 @@ void DigitalRenderer::EmulateLine(void) if (!ready) return; + Network::PushSound(volume); sample_buf[sample_in_ptr] = volume; sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE;