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!
This commit is contained in:
simon.kagstrom 2009-04-09 13:42:49 +00:00
parent 189833e30f
commit 42a6e19e0d
7 changed files with 68 additions and 30 deletions

View File

@ -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)
{

View File

@ -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"

View File

@ -8,6 +8,8 @@
#endif
#include <SDL.h>
#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;

View File

@ -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);

View File

@ -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
*/

View File

@ -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) {}

View File

@ -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;