Fixed some of the memory leaks and Clang warnings.

DrMemory and Valgrind work with regular debug builds.
This commit is contained in:
Muzychenko Andrey 2021-09-14 15:33:18 +03:00
parent 28e2417ef9
commit c5b7c0ad16
25 changed files with 74 additions and 97 deletions

View File

@ -1,3 +0,0 @@
rc /Fo.\DrMem\SpaceCadetPinball.res ".\SpaceCadetPinball\SpaceCadetPinball.rc"
cl /Zi /MT /MP /EHsc /O /Ob0 /cgthreads4 /Fo.\DrMem\ /Fe.\DrMem\myapp.exe ".\SpaceCadetPinball\*.cpp" Comctl32.lib Winmm.lib Htmlhelp.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ".\DrMem\SpaceCadetPinball.res"

View File

@ -28,7 +28,7 @@ Compile with Visual Studio; tested with 2019.
On Linux:\
Install devel packages for `SDL2` and `SDL2_mixer`.\
Compile with CMake; tested with GCC 10.
Compile with CMake; tested with GCC 10, Clang 11.
**Plans:**
* ~~Decompile original game~~

View File

@ -44,9 +44,9 @@ void Sound::PlaySound(Mix_Chunk* wavePtr, int minChannel, int maxChannel, unsign
Mix_PlayChannel(-1, wavePtr, loops);
}
Mix_Chunk* Sound::LoadWaveFile(LPCSTR lpName)
Mix_Chunk* Sound::LoadWaveFile(std::string lpName)
{
return Mix_LoadWAV(lpName);
return Mix_LoadWAV(lpName.c_str());
}
void Sound::FreeSound(Mix_Chunk* wave)

View File

@ -10,7 +10,7 @@ public:
static void Deactivate();
static void Close();
static void PlaySound(Mix_Chunk* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, int16_t loops);
static Mix_Chunk* LoadWaveFile(LPCSTR lpName);
static Mix_Chunk* LoadWaveFile(std::string lpName);
static void FreeSound(Mix_Chunk* wave);
private:
static int num_channels;

View File

@ -29,22 +29,22 @@ TEdgeManager::~TEdgeManager()
int TEdgeManager::box_x(float x)
{
return static_cast<int>((max(0, min(floor((x - X) * AdvanceXInv), (MaxBoxX - 1)))));
return std::max(0, std::min(static_cast<int>(floor((x - X) * AdvanceXInv)), MaxBoxX - 1));
}
int TEdgeManager::box_y(float y)
{
return static_cast<int>((max(0, min(floor((y - Y) * AdvanceYInv), (MaxBoxY - 1)))));
return std::max(0, std::min(static_cast<int>(floor((y - Y) * AdvanceYInv)), MaxBoxY - 1));
}
int TEdgeManager::increment_box_x(int x)
{
return min(x + 1, MaxBoxX - 1);
return std::min(x + 1, MaxBoxX - 1);
}
int TEdgeManager::increment_box_y(int y)
{
return min(y + 1, MaxBoxY - 1);
return std::min(y + 1, MaxBoxY - 1);
}
void TEdgeManager::add_edge_to_box(int x, int y, TEdgeSegment* edge)

View File

@ -78,7 +78,7 @@ TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsi
auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT1->Z;
DistanceDivSq = distance1 * distance1;
float bmpCoef = min(BmpCoef1, BmpCoef2);
float bmpCoef = std::min(BmpCoef1, BmpCoef2);
auto distance = maths::Distance(vecT1, vecT2);
CollisionTimeAdvance = bmpCoef / (distance / CircleT1Radius + distance / CircleT1Radius);
@ -428,7 +428,7 @@ float TFlipperEdge::flipper_angle(float timeNow)
else
angle = 1.0;
angle = min(1, max(angle, 0));
angle = std::min(1.0f, std::max(angle, 0.0f));
if (FlipperFlag == 2)
angle = 1.0f - angle;
return angle * AngleMax;

View File

@ -90,10 +90,10 @@ TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
auto pVec2 = reinterpret_cast<vector_type*>(&plane->V2);
auto pVec3 = reinterpret_cast<vector_type*>(&plane->V3);
xMin = min(min(min(plane->V3.X, plane->V1.X), plane->V2.X), xMin);
yMin = min(min(min(plane->V3.Y, plane->V1.Y), plane->V2.Y), xMin); // Sic
xMax = max(max(max(plane->V3.X, plane->V1.X), plane->V2.X), xMin);
yMax = max(max(max(plane->V3.Y, plane->V1.Y), plane->V2.Y), xMin);
xMin = std::min(std::min(std::min(plane->V3.X, plane->V1.X), plane->V2.X), xMin);
yMin = std::min(std::min(std::min(plane->V3.Y, plane->V1.Y), plane->V2.Y), xMin); // Sic
xMax = std::max(std::max(std::max(plane->V3.X, plane->V1.X), plane->V2.X), xMin);
yMax = std::max(std::max(std::max(plane->V3.Y, plane->V1.Y), plane->V2.Y), xMin);
vector_type* pointOrder[4] = {pVec1, pVec2, pVec3, pVec1};
for (auto pt = 0; pt < 3; pt++)

View File

@ -71,10 +71,10 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f
Boost = 15.0f;
auto visArrPtr = visual.FloatArr;
Unknown1F = min(visArrPtr[0], min(visArrPtr[2], visArrPtr[4]));
Unknown2F = min(visArrPtr[1], min(visArrPtr[3], visArrPtr[5]));
Unknown3F = max(visArrPtr[0], max(visArrPtr[2], visArrPtr[4]));
Unknown4F = max(visArrPtr[1], max(visArrPtr[3], visArrPtr[5]));
Unknown1F = std::min(visArrPtr[0], std::min(visArrPtr[2], visArrPtr[4]));
Unknown2F = std::min(visArrPtr[1], std::min(visArrPtr[3], visArrPtr[5]));
Unknown3F = std::max(visArrPtr[0], std::max(visArrPtr[2], visArrPtr[4]));
Unknown4F = std::max(visArrPtr[1], std::max(visArrPtr[3], visArrPtr[5]));
auto a2 = Unknown4F - Unknown2F;
auto a1 = Unknown3F - Unknown1F;
edge_manager = new TEdgeManager(Unknown1F, Unknown2F, a1, a2);

View File

@ -183,7 +183,7 @@ void TTextBox::Draw()
}
else if (Message1->TimeLeft() >= -2.0f)
{
Timer = timer::set(max(Message1->TimeLeft(), 0.25f), this, TimerExpired);
Timer = timer::set(std::max(Message1->TimeLeft(), 0.25f), this, TimerExpired);
display = true;
break;
}

View File

@ -1929,7 +1929,7 @@ void control::GravityWellKickoutControl(int code, TPinballComponent* caller)
}
else
{
snprintf(Buffer, sizeof Buffer, pinball::get_rc_string(45, 0));
snprintf(Buffer, sizeof Buffer, "%s", pinball::get_rc_string(45, 0));
}
control_info_text_box_tag.Component->Display(Buffer, 2.0);
control_lite62_tag.Component->Message(4, 0.0);

View File

@ -93,12 +93,12 @@ int fullscrn::GetResolution()
return resolution;
}
void fullscrn::SetResolution(int resolution)
void fullscrn::SetResolution(int value)
{
if (!pb::FullTiltMode)
resolution = 0;
assertm(resolution >= 0 && resolution <= 2, "Resolution value out of bounds");
fullscrn::resolution = resolution;
value = 0;
assertm(value >= 0 && value <= 2, "Resolution value out of bounds");
resolution = value;
}
int fullscrn::GetMaxResolution()
@ -106,10 +106,10 @@ int fullscrn::GetMaxResolution()
return maxResolution;
}
void fullscrn::SetMaxResolution(int resolution)
void fullscrn::SetMaxResolution(int value)
{
assertm(resolution >= 0 && resolution <= 2, "Resolution value out of bounds");
maxResolution = resolution;
assertm(value >= 0 && value <= 2, "Resolution value out of bounds");
maxResolution = value;
}
int fullscrn::get_max_supported_resolution()
@ -153,7 +153,7 @@ void fullscrn::window_size_changed()
if (options::Options.UniformScaling)
{
ScaleY = ScaleX = min(ScaleX, ScaleY);
ScaleY = ScaleX = std::min(ScaleX, ScaleY);
OffsetX = static_cast<int>(floor((width - res->TableWidth * ScaleX) / 2));
OffsetY = static_cast<int>(floor((height - res->TableHeight * ScaleY) / 2));
}

View File

@ -25,9 +25,9 @@ public:
static int set_screen_mode(int isFullscreen);
static void activate(int flag);
static int GetResolution();
static void SetResolution(int resolution);
static void SetResolution(int value);
static int GetMaxResolution();
static void SetMaxResolution(int resolution);
static void SetMaxResolution(int value);
static int get_max_supported_resolution();
static int get_screen_resolution(int* width, int* height);
static void window_size_changed();

View File

@ -1,9 +1,7 @@
#include "pch.h"
#include "gdrv.h"
#include "fullscrn.h"
#include "memory.h"
#include "render.h"
#include "winmain.h"
SDL_Texture* gdrv::vScreenTex = nullptr;
@ -239,8 +237,8 @@ int gdrv::StretchDIBitsScaled(int xSrc, int ySrc, int xDst, int yDst,
int width, int height, gdrv_bitmap8* bmp)
{
// Y is inverted, X normal left to right
ySrc = max(0, min(bmp->Height - height, bmp->Height)) - ySrc;
yDst = max(0, min(vScreenHeight - height, vScreenHeight)) - yDst;
ySrc = std::max(0, std::min(bmp->Height - height, bmp->Height)) - ySrc;
yDst = std::max(0, std::min(vScreenHeight - height, vScreenHeight)) - yDst;
// Negative dst == positive src offset
if (xDst < 0)
@ -255,15 +253,15 @@ int gdrv::StretchDIBitsScaled(int xSrc, int ySrc, int xDst, int yDst,
}
// Clamp out of bounds rectangles
xSrc = max(0, min(xSrc, bmp->Width));
ySrc = max(0, min(ySrc, bmp->Height));
xSrc = std::max(0, std::min(xSrc, bmp->Width));
ySrc = std::max(0, std::min(ySrc, bmp->Height));
if (xSrc + width > bmp->Width)
width = bmp->Width - xSrc;
if (ySrc + height > bmp->Height)
height = bmp->Height - ySrc;
xDst = max(0, min(xDst, vScreenWidth));
yDst = max(0, min(yDst, vScreenHeight));
xDst = std::max(0, std::min(xDst, vScreenWidth));
yDst = std::max(0, std::min(yDst, vScreenHeight));
if (xDst + width > vScreenWidth)
width = vScreenWidth - xDst;
if (yDst + height > vScreenHeight)
@ -288,7 +286,6 @@ int gdrv::StretchDIBitsScaled(int xSrc, int ySrc, int xDst, int yDst,
void gdrv::BlitScreen()
{
auto bmp = &render::vscreen;
unsigned char* lockedPixels = nullptr;
int pitch = 0;
SDL_LockTexture

View File

@ -1,11 +1,8 @@
#include "pch.h"
#include "high_score.h"
#include "fullscrn.h"
#include "memory.h"
#include "options.h"
#include "resource.h"
#include "winmain.h"
int high_score::dlg_enter_name;
int high_score::dlg_score;

View File

@ -145,7 +145,6 @@ int loader::get_sound_id(int groupIndex)
datFieldTypes::ShortValue));
if (value && *value == 202)
{
char filePath[300]{};
std::string fileName = partman::field(loader_table, soundGroupId, datFieldTypes::String);
// File name is in lower case, while game data is in upper case.
@ -157,9 +156,8 @@ int loader::get_sound_id(int groupIndex)
fileName.insert(0, "SOUND");
}
pinball::make_path_name(filePath, fileName.c_str());
FILE* file = fopen(filePath, "rb");
auto filePath = pinball::make_path_name(fileName);
auto file = fopen(filePath.c_str(), "rb");
if (file)
{
fread(&wavHeader, 1, sizeof wavHeader, file);

View File

@ -7,7 +7,10 @@
Mix_Music* midi::currentMidi;
#define FOURCC(a,b,c,d) ( (uint32_t) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a)) )
constexpr uint32_t FOURCC(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
return static_cast<uint32_t>((d << 24) | (c << 16) | (b << 8) | a);
}
int ToVariableLen(uint32_t value, uint32_t& dst)
{
@ -107,7 +110,7 @@ void midi::music_shutdown_ft()
Mix_Music* midi::load_track(std::string fileName)
{
char filePath[256];
auto origFile = fileName;
// File name is in lower case, while game data is in upper case.
std::transform(fileName.begin(), fileName.end(), fileName.begin(), [](unsigned char c) { return std::toupper(c); });
@ -119,24 +122,22 @@ Mix_Music* midi::load_track(std::string fileName)
}
fileName += ".MDS";
pinball::make_path_name(filePath, fileName.c_str(), 254u);
auto filePath = pinball::make_path_name(fileName);
auto midi = MdsToMidi(filePath);
if (!midi)
return nullptr;
// Dump converted MIDI file
/*origFile += ".midi";
FILE* fileHandle = fopen(origFile.c_str(), "wb");
fwrite(midi->data(), 1, midi->size(), fileHandle);
fclose(fileHandle);*/
auto rw = SDL_RWFromMem(midi->data(), static_cast<int>(midi->size()));
auto audio = Mix_LoadMUS_RW(rw, 0);
SDL_FreeRW(rw);
auto audio = Mix_LoadMUS_RW(rw, 1); // This call seems to leak memory no matter what.
delete midi;
if (!audio)
return nullptr;
// Dump converted MIDI file
/*strncpy(fileName2, fileName, sizeof fileName2);
strcat(fileName2, ".midi");
FILE* fileHandle = fopen(fileName2, "wb");
fwrite(midi->data(), 1, midi->size(), fileHandle);
fclose(fileHandle);*/
TrackList->Add(audio);
return audio;
@ -181,9 +182,9 @@ int midi::stop_ft()
/// </summary>
/// <param name="file">Path to .MDS file</param>
/// <returns>Vector that contains MIDI file</returns>
std::vector<uint8_t>* midi::MdsToMidi(char* file)
std::vector<uint8_t>* midi::MdsToMidi(std::string file)
{
FILE* fileHandle = fopen(file, "rb");
auto fileHandle = fopen(file.c_str(), "rb");
if (!fileHandle)
return nullptr;
@ -328,7 +329,9 @@ std::vector<uint8_t>* midi::MdsToMidi(char* file)
midiBytes.insert(midiBytes.end(), metaEndTrack, metaEndTrack + 4);
// Set final MTrk size
*(uint32_t*)&midiBytes[lengthPos] = SwapByteOrderInt((uint32_t)midiBytes.size() - sizeof header - sizeof track);
auto lengthBE = SwapByteOrderInt((uint32_t)midiBytes.size() - sizeof header - sizeof track);
auto lengthData = reinterpret_cast<const uint8_t*>(&lengthBE);
std::copy_n(lengthData, 4, midiBytes.begin() + lengthPos);
}
while (false);

View File

@ -102,5 +102,5 @@ private:
static Mix_Music* load_track(std::string fileName);
static int play_ft(Mix_Music* midi);
static int stop_ft();
static std::vector<uint8_t>* MdsToMidi(char* file);
static std::vector<uint8_t>* MdsToMidi(std::string file);
};

View File

@ -15,7 +15,7 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful
dat8BitBmpHeader bmpHeader{};
dat16BitBmpHeader zMapHeader{};
FILE* fileHandle = fopen(lpFileName, "rb");
auto fileHandle = fopen(lpFileName, "rb");
if (fileHandle == nullptr)
return nullptr;
fread(&header, 1, sizeof header, fileHandle);

View File

@ -36,13 +36,10 @@ bool pb::FullTiltMode = false;
int pb::init()
{
float projMat[12], zMin = 0, zScaler = 0;
char datFileName[300];
char dataFilePath[300];
++memory::critical_allocation;
strncpy(datFileName, winmain::DatFileName, sizeof datFileName);
pinball::make_path_name(dataFilePath, datFileName, 300);
record_table = partman::load_records(dataFilePath, fullscrn::GetResolution(), FullTiltMode);
auto dataFilePath = pinball::make_path_name(winmain::DatFileName);
record_table = partman::load_records(dataFilePath.c_str(), fullscrn::GetResolution(), FullTiltMode);
auto useBmpFont = 0;
pinball::get_rc_int(158, &useBmpFont);

View File

@ -42,12 +42,6 @@ typedef uint32_t DWORD;
typedef char* LPSTR;
typedef const char* LPCSTR;
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
//
//#define min(a,b) (((a)<(b))?(a):(b))
//#define max(a,b) (((a)>(b))?(a):(b))
constexpr char PathSeparator =
#ifdef _WIN32
'\\';
@ -70,7 +64,7 @@ inline size_t pgm_save(int width, int height, char* data, FILE* outfile)
inline float RandFloat()
{
return static_cast<float>(std::rand()) / (RAND_MAX);
return static_cast<float>(std::rand() / static_cast<double>(RAND_MAX));
}
#endif //PCH_H

View File

@ -246,15 +246,7 @@ int pinball::get_rc_int(int uID, int* dst)
return 1;
}
int pinball::make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize)
std::string pinball::make_path_name(const std::string& fileName)
{
auto base_path = SDL_GetBasePath();
if (!base_path)
{
strcat(lpFilename,"?");
return 1;
}
strncpy(lpFilename, base_path, nSize);
strcat(lpFilename, lpString2);
return 0;
return winmain::BasePath + fileName;
}

View File

@ -18,7 +18,7 @@ public:
static char* get_rc_string(int uID, int a2);
static int get_rc_int(int uID, int* dst);
static int make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize = 0x12Cu);
static std::string make_path_name(const std::string& fileName);
private:
static char getRcBuffer[256 * 6];
static int rc_string_slot;

View File

@ -288,13 +288,13 @@ void score::string_format(int score, char* str)
if (static_cast<int>(scoreMillions) <= 0)
{
if (score % 1000000 / 1000 <= 0)
snprintf(str, 36, "%ld", score);
snprintf(str, 36, "%d", score);
else
snprintf(str, 36, "%ld%s%03ld", score % 1000000 / 1000, separator, score % 1000);
snprintf(str, 36, "%d%s%03d", score % 1000000 / 1000, separator, score % 1000);
}
else
{
snprintf(str, 36, "%ld%s%03ld%s%03ld", scoreMillions, separator, score % 1000000 / 1000, separator,
snprintf(str, 36, "%d%s%03d%s%03d", scoreMillions, separator, score % 1000000 / 1000, separator,
score % 1000);
}
}
@ -303,7 +303,7 @@ void score::string_format(int score, char* str)
snprintf(
str,
36,
"%ld%s%03ld%s%03ld%s%03ld",
"%d%s%03d%s%03d%s%03d",
score / 1000000000,
separator,
scoreMillions,

View File

@ -39,6 +39,7 @@ bool winmain::ShowImGuiDemo = false;
bool winmain::LaunchBallEnabled = true;
bool winmain::HighScoresEnabled = true;
bool winmain::DemoActive = false;
char* winmain::BasePath;
uint32_t timeGetTimeAlt()
@ -64,15 +65,15 @@ int winmain::WinMain(LPCSTR lpCmdLine)
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not initialize SDL2", SDL_GetError(), nullptr);
return 1;
}
BasePath = SDL_GetBasePath();
pinball::quickFlag = strstr(lpCmdLine, "-quick") != nullptr;
auto regSpaceCadet = pinball::get_rc_string(166, 0);
options::get_string(regSpaceCadet, "Pinball Data", DatFileName, pinball::get_rc_string(168, 0), 300);
/*Check for full tilt .dat file and switch to it automatically*/
char cadetFilePath[300]{};
pinball::make_path_name(cadetFilePath, "CADET.DAT", 300);
FILE* cadetDat = fopen(cadetFilePath, "r");
auto cadetFilePath = pinball::make_path_name("CADET.DAT");
auto cadetDat = fopen(cadetFilePath.c_str(), "r");
if (cadetDat)
{
fclose(cadetDat);
@ -270,7 +271,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
if (elapsedMs >= TargetFrameTime)
{
// Keep track of remainder, limited to one frame time.
frameStart = frameEnd - min(elapsedMs - TargetFrameTime, TargetFrameTime) / sdlTimerResMs;
frameStart = frameEnd - std::min(elapsedMs - TargetFrameTime, TargetFrameTime) / sdlTimerResMs;
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();

View File

@ -12,6 +12,7 @@ public:
static bool LaunchBallEnabled;
static bool HighScoresEnabled;
static bool DemoActive;
static char* BasePath;
static int WinMain(LPCSTR lpCmdLine);
static int event_handler(const SDL_Event* event);