Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 61 additions & 32 deletions code/netshare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

#include <algorithm>
#include <ctime>
#include <vector>


const COLORREF ColorSystem = RGB(255, 255, 255)|(255<<24); /// 0xFFFFFFFF
Expand Down Expand Up @@ -1346,6 +1347,62 @@ void Update_Network_Dialog_Preview(HWND win)
}


/// <summary>
/// Expands a downloaded preview file and makes it the multiplayer preview.
/// </summary>
/// <param name="filename">Name of the compressed preview file the host sent.</param>
/// <returns>bool; Was the preview replaced? A block that does not describe an image fitting
/// the bytes it arrived in is refused and the current preview is left alone.</returns>
static bool Load_Random_Map_Preview(char const * filename)
{
DebugString("Loading the compressed preview image\n");
CDFileClass file(filename);

int size = file.Size();
if (size <= (int)sizeof(int)) {
DebugString("Preview file size %d is too small\n", size);
return(false);
}

std::vector<char> buffer(size);
file.Read(buffer.data(), size);

int preview_size = ((int *)buffer.data())[0];
if (preview_size <= 0 || preview_size > MapPreviewClass::MAX_BLOCK_SIZE) {
DebugString("Preview decompressed size %d is out of range\n", preview_size);
return(false);
}

DebugString("Decompressing the preview image\n");

BufferStraw bstraw(buffer.data() + sizeof(int), size - (int)sizeof(int));
LZOStraw lzostraw(LZOStraw::DECOMPRESS);
lzostraw.Get_From(&bstraw);

std::vector<char> preview(preview_size);
int expanded = lzostraw.Get(preview.data(), preview_size);
if (expanded != preview_size) {
DebugString("Preview decompressed size %d doesn't match expected %d bytes\n", expanded, preview_size);
return(false);
}

DebugString("Creating the new preview surface\n");

MapPreviewClass * created = new MapPreviewClass;
if (!created->Create_Preview_Surface(preview.data(), preview_size)) {
DebugString("Preview surface could not be created\n");
delete created;
return(false);
}

if (MultiplayerMapPreview) {
delete MultiplayerMapPreview;
}
MultiplayerMapPreview = created;
return(true);
}


/// <summary>
/// Receives the random map preview image from the host.
/// This is the guest side of the preview handshake. The host is told that this machine is
Expand Down Expand Up @@ -1375,39 +1432,11 @@ void Receive_Random_Map_Preview(void)
Session.GAddress = Session.HostAddress;
DebugString("Calling Get_File_From_Host to receive the file download\n");
char preview_name[256];
bool got_file = Get_File_From_Host(preview_name, false);
if (!got_file) {
DebugString("got_file is false. Download failed\n");
Ipx.Set_Timing(TIMER_SECOND / 2, -1, 10 * TIMER_SECOND);
return;
}

DebugString("Loading the compressed preview image\n");
CDFileClass file(preview_name);
int size = file.Size();
char * buffer = new char[size];
file.Read(buffer, size);
int preview_size = ((int *)buffer)[0];

DebugString("Decompressing the preview image\n");

BufferStraw bstraw(&((int *)buffer)[1], size);
LZOStraw lzostraw(LZOStraw::DECOMPRESS);
lzostraw.Get_From(&bstraw);
char * preview = new char[2 * preview_size];
lzostraw.Get(preview, preview_size);

DebugString("Creating the new preview surface\n");
if (MultiplayerMapPreview) {
delete MultiplayerMapPreview;
if (!Get_File_From_Host(preview_name, false)) {
DebugString("Preview file download failed\n");
} else if (Load_Random_Map_Preview(preview_name)) {
InvalidateRect(WS_Top_Window(), NULL, FALSE);
}
MultiplayerMapPreview = new MapPreviewClass;
MultiplayerMapPreview->Create_Preview_Surface(preview);
InvalidateRect(WS_Top_Window(), NULL, FALSE);

DebugString("Cleaning up the temporary decompression buffers\n");
delete [] preview;
delete [] buffer;

Ipx.Set_Timing(TIMER_SECOND / 2, -1, 10 * TIMER_SECOND);
}
Expand Down
31 changes: 28 additions & 3 deletions code/preview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,29 +544,54 @@ unsigned * MapPreviewClass::Create_Paletted_Preview(int colorcount, int & size)
/// arrives already packed, rather than being rendered from the map that is loaded.
/// </summary>
/// <param name="buffer">Pointer to the paletted preview block to expand.</param>
void MapPreviewClass::Create_Preview_Surface(char * buffer)
/// <param name="length">Number of bytes the block occupies.</param>
/// <returns>bool; Was a preview surface created? A block whose geometry does not fit in the
/// length given is refused and the current preview is left alone.</returns>
bool MapPreviewClass::Create_Preview_Surface(char * buffer, int length)
{
if (buffer == NULL || length < (int)(sizeof(Header) + sizeof(int))) {
return(false);
}

int * header = (int *)buffer;

int width = *header++;
int height = *header++;
int colorcount = *header;
unsigned short *palette = (unsigned short *)header;

if (width <= 0 || height <= 0) {
return(false);
}
if (colorcount <= 0 || colorcount > MAX_COLOR_COUNT) {
return(false);
}

int offset = (colorcount * sizeof(unsigned short)) + sizeof(Header) + sizeof(int);

// Widened because the dimensions come off the wire and their product overflows an int.
long long const needed = (long long)offset + (long long)width * (long long)height;
if (needed > (long long)length) {
return(false);
}

if (SurfacePtr != NULL) {
delete SurfacePtr;
}
SurfacePtr = new DSurface(width, height);
SurfacePtr->Fill(TBLACK);

int offset = (colorcount * sizeof(unsigned short)) + sizeof(Header) + sizeof(int);
unsigned char * indexptr = (unsigned char *)buffer + offset;
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
unsigned short entry = palette[*indexptr++ + 2];
// The palette starts two shorts past the count that precedes it.
int index = *indexptr++;
unsigned short entry = (index < colorcount) ? palette[index + 2] : 0;
int color = DSurface::Build_Hicolor_Pixel((entry >> 4) & 0x00F0, entry & 0x00F0, 16 * (entry & 0x000F));

SurfacePtr->Put_Pixel_Clip(Point2D(x, y), color, SurfacePtr->Get_Rect());
}
}

return(true);
}
5 changes: 4 additions & 1 deletion code/preview.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class MapPreviewClass
void Blit_Preview(HWND window);

unsigned * Create_Paletted_Preview(int, int & size);
void Create_Preview_Surface(char * buffer);
bool Create_Preview_Surface(char * buffer, int length);
XSurface * Get_Preview_Surface(void) { return(SurfacePtr); }

private:
Expand All @@ -51,6 +51,9 @@ class MapPreviewClass
int Height;
};

static int const MAX_BLOCK_SIZE = 8 * 1024 * 1024;
static int const MAX_COLOR_COUNT = 4096;


private:
/*
Expand Down
Loading