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
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,8 @@ class WorldHeightMap : public RefCountClass,
public: // height map info.
static Int getMinHeightValue() {return K_MIN_HEIGHT;}
static Int getMaxHeightValue() {return K_MAX_HEIGHT;}
static Bool isValidMapSize(Int width, Int height, Int borderSize); ///< Within MAX_MAP_DIMENSION and MAX_MAP_AREA, width and height include the border
static Bool isValidTotalMapSize(Int width, Int height, Int borderSize); ///< Within MAX_MAP_DIMENSION and MAX_MAP_AREA, width and height include the border
static Bool isValidPlayableMapSize(Int width, Int height, Int borderSize); ///< Width and height exclude the border

UnsignedByte *getDataPtr() {return m_data;}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "windows.h"
#include "stdlib.h"
#include <limits.h>
#include "Common/STLTypedefs.h"

#include "Common/DataChunk.h"
Expand Down Expand Up @@ -849,19 +850,39 @@ Bool WorldHeightMap::ParseObjectsDataChunk(DataChunkInput &file, DataChunkInfo *
return (file.parse(userData));
}

Bool WorldHeightMap::isValidMapSize(Int width, Int height, Int borderSize)
Bool WorldHeightMap::isValidTotalMapSize(Int width, Int height, Int borderSize)
{
if (width <= 0 || width > MAX_MAP_DIMENSION)
return false;
if (height <= 0 || height > MAX_MAP_DIMENSION)
return false;
if (width * height > MAX_MAP_AREA)

if (borderSize < 0 ||
borderSize > (width - 1) / 2 ||
borderSize > (height - 1) / 2)
return false;
if (borderSize < 0 || borderSize > (width - 1) / 2 || borderSize > (height - 1) / 2)

if (width * height > MAX_MAP_AREA)
return false;

return true;
}

Bool WorldHeightMap::isValidPlayableMapSize(Int width, Int height, Int borderSize)
{
if (width <= 0 || height <= 0 || borderSize < 0)
return false;

if (borderSize > (INT_MAX - width) / 2 ||
borderSize > (INT_MAX - height) / 2)
return false;

return isValidTotalMapSize(
width + 2 * borderSize,
height + 2 * borderSize,
borderSize);
}

static Bool isValidHeightDataSize(DataChunkInput &file, Int dataSize, Int width, Int height)
{
return dataSize > 0 && dataSize == width * height && (UnsignedInt)dataSize <= file.getChunkDataSizeLeft();
Expand Down Expand Up @@ -897,7 +918,7 @@ Bool WorldHeightMap::ParseHeightMapData(DataChunkInput &file, DataChunkInfo *inf
m_borderSize = 0;
}

if (!isValidMapSize(m_width, m_height, m_borderSize)) {
if (!isValidTotalMapSize(m_width, m_height, m_borderSize)) {
throw ERROR_CORRUPT_FILE_FORMAT;
}

Expand Down Expand Up @@ -976,7 +997,7 @@ Bool WorldHeightMap::ParseSizeOnly(DataChunkInput &file, DataChunkInfo *info, vo
m_borderSize = 0;
}

if (!isValidMapSize(m_width, m_height, m_borderSize)) {
if (!isValidTotalMapSize(m_width, m_height, m_borderSize)) {
throw ERROR_CORRUPT_FILE_FORMAT;
}

Expand Down
21 changes: 21 additions & 0 deletions Generals/Code/Tools/WorldBuilder/src/NewHeightMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
#include "StdAfx.h"
#include "WorldBuilder.h"
#include "NewHeightMap.h"
#include "WHeightMapEdit.h"
#include "Common/MapReaderWriterInfo.h"

static constexpr const Int LARGE_MAP_SIDE = 2048; ///< Memory warning above this squared

/////////////////////////////////////////////////////////////////////////////
// CNewHeightMap dialog
Expand Down Expand Up @@ -209,6 +213,23 @@ void CNewHeightMap::OnOK()
edit->GetWindowText(val);
mHeightInfo.borderWidth = atoi(val);
}

if (!WorldHeightMapEdit::isValidPlayableMapSize(mHeightInfo.xExtent, mHeightInfo.yExtent, mHeightInfo.borderWidth)) {
CString msg;
msg.Format("Map sides including the border must be 1 to %d, with an area of at most %d cells.", MAX_MAP_DIMENSION, MAX_MAP_AREA);
AfxMessageBox(msg);
return;
}

const Int width = mHeightInfo.xExtent + 2*mHeightInfo.borderWidth;
const Int height = mHeightInfo.yExtent + 2*mHeightInfo.borderWidth;
if (width * height > sqr(LARGE_MAP_SIDE)) {
CString msg;
msg.Format("Maps with more than %d tiles including the border can run out of memory in WorldBuilder. Continue?", sqr(LARGE_MAP_SIDE));
if (AfxMessageBox(msg, MB_YESNO) != IDYES)
return;
}

CDialog::OnOK();
}

Expand Down
24 changes: 15 additions & 9 deletions Generals/Code/Tools/WorldBuilder/src/WHeightMapEdit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ WorldHeightMapEdit::WorldHeightMapEdit(Int width, Int height, UnsignedByte initi
m_sourceTiles[i]=nullptr;
m_edgeTiles[i]=nullptr;
}
if (width<0 || height < 0) {
if (!isValidPlayableMapSize(width, height, border)) {
AfxMessageBox(IDS_BAD_VALUE);
return;
}
Expand Down Expand Up @@ -1786,6 +1786,10 @@ Bool WorldHeightMapEdit::resize(Int newXSize, Int newYSize, Int newHeight, Int n
Bool anchorLeft, Bool anchorRight, Coord3D *pObjOffset)
{
if (newBorder<0) newBorder = 0;
if (!isValidPlayableMapSize(newXSize, newYSize, newBorder)) {
AfxMessageBox(IDS_BAD_VALUE);
return(false);
}
newXSize += 2*newBorder;
newYSize += 2*newBorder;
Int newDataSize = newXSize*newYSize;
Expand Down Expand Up @@ -1824,7 +1828,7 @@ Bool WorldHeightMapEdit::resize(Int newXSize, Int newYSize, Int newHeight, Int n
Short *tileNdxes = new Short[newDataSize];
Short *blendTileNdxes = new Short[newDataSize];
Short *extraBlendTileNdxes = new Short[newDataSize];
UnsignedByte *data = new UnsignedByte[newDataSize];
UnsignedByte *data = new UnsignedByte[newDataSize + newXSize+1];
Short *cliffInfoNdxes = new Short[newDataSize];

Int i, j;
Expand Down Expand Up @@ -1867,11 +1871,11 @@ Bool WorldHeightMapEdit::resize(Int newXSize, Int newYSize, Int newHeight, Int n
}
}

delete(m_tileNdxes);
delete(m_cliffInfoNdxes);
delete(m_blendTileNdxes);
delete(m_extraBlendTileNdxes);
delete(m_data);
delete[] m_tileNdxes;
delete[] m_cliffInfoNdxes;
delete[] m_blendTileNdxes;
delete[] m_extraBlendTileNdxes;
delete[] m_data;
m_tileNdxes = tileNdxes;
m_blendTileNdxes = blendTileNdxes;
m_extraBlendTileNdxes = extraBlendTileNdxes;
Expand All @@ -1881,13 +1885,15 @@ Bool WorldHeightMapEdit::resize(Int newXSize, Int newYSize, Int newHeight, Int n
m_height = newYSize;
m_borderSize = newBorder;
m_dataSize = newDataSize;
delete(m_cellCliffState);
delete(m_cellFlipState);
delete[] m_cellCliffState;
delete[] m_cellFlipState;
Int numBytesX = (m_width+7)/8; //how many bytes to fit all bitflags
m_flipStateWidth=numBytesX;

m_cellFlipState = MSGNEW("WorldHeightMapEdit::resize") UnsignedByte[numBytesX*m_height];
m_cellCliffState = MSGNEW("WorldHeightMapEdit::resize") UnsignedByte[numBytesX*m_height];
memset(m_cellFlipState,0,numBytesX*m_height);
memset(m_cellCliffState,0,numBytesX*m_height);

// Verify index remapping
for(i=0; i<m_dataSize; i++) {
Expand Down
5 changes: 5 additions & 0 deletions Generals/Code/Tools/WorldBuilder/src/WorldBuilderDoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,11 @@ BOOL CWorldBuilderDoc::OnNewDocument()
hi.xExtent = AfxGetApp()->GetProfileInt("GameOptions", "Default Map X-size", 100);
hi.yExtent = AfxGetApp()->GetProfileInt("GameOptions", "Default Map Y-size", 100);
hi.borderWidth = AfxGetApp()->GetProfileInt("GameOptions", "Default Map Border", 30);
if (!WorldHeightMapEdit::isValidPlayableMapSize(hi.xExtent, hi.yExtent, hi.borderWidth)) {
hi.xExtent = 100;
hi.yExtent = 100;
hi.borderWidth = 30;
}
hi.forResize = false;
if (!firstTime) {
CString label;
Expand Down
13 changes: 11 additions & 2 deletions Generals/Code/Tools/WorldBuilder/src/wbview3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ static Real theLightYOffset = 0.07f;
static Int theFlashCount = 0;
#endif

static const Int MAX_DRAWABLE_MAP_AREA = 1024*1024; ///< Larger maps draw the partial terrain window

static Bool canDrawEntireMap(const WorldHeightMap *htMap)
{
return htMap != nullptr && htMap->getXExtent() * htMap->getYExtent() <= MAX_DRAWABLE_MAP_AREA;
}

// ----------------------------------------------------------------------------
// Global Variables:
// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -1508,7 +1515,7 @@ void WbView3d::updateHeightMapInView(WorldHeightMap *htMap, Bool partial, const
if (partial) {
m_heightMapRenderObj->doPartialUpdate(partialRange, htMap, &lightListIt);
} else {
if (m_showEntireMap) {
if (m_showEntireMap && canDrawEntireMap(htMap)) {
htMap->setDrawOrg(0, 0);
htMap->setDrawWidth(htMap->getXExtent());
htMap->setDrawHeight(htMap->getYExtent());
Expand Down Expand Up @@ -2690,7 +2697,9 @@ void WbView3d::OnViewShowentire3dmap()

void WbView3d::OnUpdateViewShowentire3dmap(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_showEntireMap?1:0);
const Bool canDraw = canDrawEntireMap(WbDoc() ? WbDoc()->GetHeightMap() : nullptr);
pCmdUI->Enable(canDraw);
pCmdUI->SetCheck(m_showEntireMap && canDraw ? 1 : 0);
}

void WbView3d::OnViewShowtopdownview()
Expand Down
21 changes: 21 additions & 0 deletions GeneralsMD/Code/Tools/WorldBuilder/src/NewHeightMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
#include "StdAfx.h"
#include "WorldBuilder.h"
#include "NewHeightMap.h"
#include "WHeightMapEdit.h"
#include "Common/MapReaderWriterInfo.h"

static constexpr const Int LARGE_MAP_SIDE = 2048; ///< Memory warning above this squared

/////////////////////////////////////////////////////////////////////////////
// CNewHeightMap dialog
Expand Down Expand Up @@ -209,6 +213,23 @@ void CNewHeightMap::OnOK()
edit->GetWindowText(val);
mHeightInfo.borderWidth = atoi(val);
}

if (!WorldHeightMapEdit::isValidPlayableMapSize(mHeightInfo.xExtent, mHeightInfo.yExtent, mHeightInfo.borderWidth)) {
CString msg;
msg.Format("Map sides including the border must be 1 to %d, with an area of at most %d cells.", MAX_MAP_DIMENSION, MAX_MAP_AREA);
AfxMessageBox(msg);
return;
}

const Int width = mHeightInfo.xExtent + 2*mHeightInfo.borderWidth;
const Int height = mHeightInfo.yExtent + 2*mHeightInfo.borderWidth;
if (width * height > sqr(LARGE_MAP_SIDE)) {
CString msg;
msg.Format("Maps with more than %d tiles including the border can run out of memory in WorldBuilder. Continue?", sqr(LARGE_MAP_SIDE));
if (AfxMessageBox(msg, MB_YESNO) != IDYES)
return;
}

CDialog::OnOK();
}

Expand Down
24 changes: 15 additions & 9 deletions GeneralsMD/Code/Tools/WorldBuilder/src/WHeightMapEdit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ WorldHeightMapEdit::WorldHeightMapEdit(Int width, Int height, UnsignedByte initi
m_sourceTiles[i]=nullptr;
m_edgeTiles[i]=nullptr;
}
if (width<0 || height < 0) {
if (!isValidPlayableMapSize(width, height, border)) {
AfxMessageBox(IDS_BAD_VALUE);
return;
}
Expand Down Expand Up @@ -1786,6 +1786,10 @@ Bool WorldHeightMapEdit::resize(Int newXSize, Int newYSize, Int newHeight, Int n
Bool anchorLeft, Bool anchorRight, Coord3D *pObjOffset)
{
if (newBorder<0) newBorder = 0;
if (!isValidPlayableMapSize(newXSize, newYSize, newBorder)) {
AfxMessageBox(IDS_BAD_VALUE);
return(false);
}
newXSize += 2*newBorder;
newYSize += 2*newBorder;
Int newDataSize = newXSize*newYSize;
Expand Down Expand Up @@ -1824,7 +1828,7 @@ Bool WorldHeightMapEdit::resize(Int newXSize, Int newYSize, Int newHeight, Int n
Short *tileNdxes = new Short[newDataSize];
Short *blendTileNdxes = new Short[newDataSize];
Short *extraBlendTileNdxes = new Short[newDataSize];
UnsignedByte *data = new UnsignedByte[newDataSize];
UnsignedByte *data = new UnsignedByte[newDataSize + newXSize+1];
Short *cliffInfoNdxes = new Short[newDataSize];

Int i, j;
Expand Down Expand Up @@ -1867,11 +1871,11 @@ Bool WorldHeightMapEdit::resize(Int newXSize, Int newYSize, Int newHeight, Int n
}
}

delete(m_tileNdxes);
delete(m_cliffInfoNdxes);
delete(m_blendTileNdxes);
delete(m_extraBlendTileNdxes);
delete(m_data);
delete[] m_tileNdxes;
delete[] m_cliffInfoNdxes;
delete[] m_blendTileNdxes;
delete[] m_extraBlendTileNdxes;
delete[] m_data;
m_tileNdxes = tileNdxes;
m_blendTileNdxes = blendTileNdxes;
m_extraBlendTileNdxes = extraBlendTileNdxes;
Expand All @@ -1881,13 +1885,15 @@ Bool WorldHeightMapEdit::resize(Int newXSize, Int newYSize, Int newHeight, Int n
m_height = newYSize;
m_borderSize = newBorder;
m_dataSize = newDataSize;
delete(m_cellCliffState);
delete(m_cellFlipState);
delete[] m_cellCliffState;
delete[] m_cellFlipState;
Int numBytesX = (m_width+7)/8; //how many bytes to fit all bitflags
m_flipStateWidth=numBytesX;

m_cellFlipState = MSGNEW("WorldHeightMapEdit::resize") UnsignedByte[numBytesX*m_height];
m_cellCliffState = MSGNEW("WorldHeightMapEdit::resize") UnsignedByte[numBytesX*m_height];
memset(m_cellFlipState,0,numBytesX*m_height);
memset(m_cellCliffState,0,numBytesX*m_height);

// Verify index remapping
for(i=0; i<m_dataSize; i++) {
Expand Down
5 changes: 5 additions & 0 deletions GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilderDoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,11 @@ BOOL CWorldBuilderDoc::OnNewDocument()
hi.xExtent = AfxGetApp()->GetProfileInt("GameOptions", "Default Map X-size", 100);
hi.yExtent = AfxGetApp()->GetProfileInt("GameOptions", "Default Map Y-size", 100);
hi.borderWidth = AfxGetApp()->GetProfileInt("GameOptions", "Default Map Border", 30);
if (!WorldHeightMapEdit::isValidPlayableMapSize(hi.xExtent, hi.yExtent, hi.borderWidth)) {
hi.xExtent = 100;
hi.yExtent = 100;
hi.borderWidth = 30;
}
hi.forResize = false;
if (!firstTime) {
CString label;
Expand Down
13 changes: 11 additions & 2 deletions GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ static Real theLightYOffset = 0.07f;
static Int theFlashCount = 0;
#endif

static const Int MAX_DRAWABLE_MAP_AREA = 1024*1024; ///< Larger maps draw the partial terrain window

static Bool canDrawEntireMap(const WorldHeightMap *htMap)
{
return htMap != nullptr && htMap->getXExtent() * htMap->getYExtent() <= MAX_DRAWABLE_MAP_AREA;
}

// ----------------------------------------------------------------------------
// Global Variables:
// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -1590,7 +1597,7 @@ void WbView3d::updateHeightMapInView(WorldHeightMap *htMap, Bool partial, const
if (partial) {
m_heightMapRenderObj->doPartialUpdate(partialRange, htMap, &lightListIt);
} else {
if (m_showEntireMap) {
if (m_showEntireMap && canDrawEntireMap(htMap)) {
htMap->setDrawOrg(0, 0);
htMap->setDrawWidth(htMap->getXExtent());
htMap->setDrawHeight(htMap->getYExtent());
Expand Down Expand Up @@ -2888,7 +2895,9 @@ void WbView3d::OnViewShowentire3dmap()

void WbView3d::OnUpdateViewShowentire3dmap(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_showEntireMap?1:0);
const Bool canDraw = canDrawEntireMap(WbDoc() ? WbDoc()->GetHeightMap() : nullptr);
pCmdUI->Enable(canDraw);
pCmdUI->SetCheck(m_showEntireMap && canDraw ? 1 : 0);
}

void WbView3d::OnViewShowtopdownview()
Expand Down
Loading