Skip to content

Commit 35b1a1c

Browse files
Merge pull request #23 from UnknownException/development
Improve OpenGL texture handling and fix some regressions
2 parents 6ceae51 + 6801bdf commit 35b1a1c

9 files changed

Lines changed: 107 additions & 56 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
## Question and Answers
3434
### How to update Submarine Titans to version 1.1?
35-
> Window: https://steamcommunity.com/sharedfiles/filedetails/?id=2129291420 \
35+
> Windows: https://steamcommunity.com/sharedfiles/filedetails/?id=2129291420 \
3636
> Linux: See [PROTON-v1_0-v_1_1.md](PROTON-v1_0-v1_1.md)
3737
3838
### Why am I getting MSVCP140.dll errors?
@@ -59,7 +59,7 @@
5959
6060
### How do I use the mission skip cheat?
6161
> Load the mission you want to skip and write 'orbiton' without quotes in the chatbox. \
62-
> Exit to the menu and select a random campaign to start the next mission. \
62+
> Exit to the menu and select a random campaign to start the next mission.
6363
6464
### How do I uninstall the patch?
6565
> Deleting SubTitans.dll will disable the in-game patches.

subtitans/iddraw4.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace DDraw {
3030
uint32_t colorKeyCaps;
3131
uint32_t effectCaps;
3232
uint32_t effectAlphaCaps;
33-
uint32_t palleteCaps;
33+
uint32_t paletteCaps;
3434
uint32_t stereoVisionCaps;
3535
uint32_t alphaBltConstantBitDepth;
3636
uint32_t alphaBltPixelBitDepth;

subtitans/openglrenderer.cpp

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ uint32_t CreateShader(const char* fragmentShader)
322322

323323
char errorBuffer[1024 - 16];
324324
glGetShaderInfoLog(vertexShaderId, sizeof(errorBuffer), NULL, errorBuffer);
325-
GetLogger()->Error(errorBuffer);
325+
GetLogger()->Error("%s", errorBuffer);
326326

327327
return 0;
328328
}
@@ -337,7 +337,7 @@ uint32_t CreateShader(const char* fragmentShader)
337337

338338
char errorBuffer[1024 - 16];
339339
glGetShaderInfoLog(fragmentShaderId, sizeof(errorBuffer), NULL, errorBuffer);
340-
GetLogger()->Error(errorBuffer);
340+
GetLogger()->Error("%s", errorBuffer);
341341

342342
return 0;
343343
}
@@ -353,7 +353,7 @@ uint32_t CreateShader(const char* fragmentShader)
353353

354354
char errorBuffer[1024 - 16];
355355
glGetProgramInfoLog(shaderProgramId, sizeof(errorBuffer), NULL, errorBuffer);
356-
GetLogger()->Error(errorBuffer);
356+
GetLogger()->Error("%s", errorBuffer);
357357

358358
return 0;
359359
}
@@ -445,6 +445,17 @@ void OpenGLRenderer::Run()
445445
glGenTextures(1, &surfaceTextureId);
446446
glGenTextures(1, &paletteTextureId);
447447

448+
glActiveTexture(GL_TEXTURE0);
449+
glBindTexture(GL_TEXTURE_2D, surfaceTextureId);
450+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
451+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
452+
453+
glActiveTexture(GL_TEXTURE1);
454+
glBindTexture(GL_TEXTURE_2D, paletteTextureId);
455+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
456+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
457+
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);
458+
448459
glViewport(0, 0, Global::MonitorWidth, Global::MonitorHeight);
449460

450461
uint32_t vboId = 0;
@@ -459,6 +470,9 @@ void OpenGLRenderer::Run()
459470
glEnableVertexAttribArray(0);
460471
glEnableVertexAttribArray(1);
461472

473+
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
474+
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)(12 * sizeof(float)));
475+
462476
GetLogger()->Informational("%s %s\n", __FUNCTION__, "is running");
463477

464478
InitImGui();
@@ -474,6 +488,7 @@ void OpenGLRenderer::Run()
474488
int32_t currentWidth = 0;
475489
int32_t currentHeight = 0;
476490
int32_t currentBitsPerPixel = 0;
491+
bool refreshGLTexture = false;
477492

478493
Mutex.lock();
479494
while (IsThreadRunning)
@@ -483,42 +498,39 @@ void OpenGLRenderer::Run()
483498
uint32_t drawTime = timeGetTime();
484499

485500
// Clear
486-
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
501+
glClear(GL_COLOR_BUFFER_BIT);
487502

488503
if (surfaceBuffer)
489504
{
490-
// Set images
505+
// Upload the surface. Re-allocate only when the resolution or bit depth changed
491506
if (currentBitsPerPixel == 8 && paletteBuffer)
492507
{
493508
glActiveTexture(GL_TEXTURE0);
494509
glBindTexture(GL_TEXTURE_2D, surfaceTextureId);
495-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
496-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
497-
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, currentWidth, currentHeight, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, surfaceBuffer);
510+
if (refreshGLTexture)
511+
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, currentWidth, currentHeight, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, surfaceBuffer);
512+
else
513+
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, currentWidth, currentHeight, GL_RED_INTEGER, GL_UNSIGNED_BYTE, surfaceBuffer);
498514

499515
glActiveTexture(GL_TEXTURE1);
500516
glBindTexture(GL_TEXTURE_2D, paletteTextureId);
501-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
502-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
503-
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, paletteBuffer);
517+
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 1, GL_BGRA, GL_UNSIGNED_BYTE, paletteBuffer);
504518
}
505519
else if (currentBitsPerPixel == 32)
506520
{
507521
glActiveTexture(GL_TEXTURE0);
508522
glBindTexture(GL_TEXTURE_2D, surfaceTextureId);
509-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
510-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
511-
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, currentWidth, currentHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceBuffer);
523+
if (refreshGLTexture)
524+
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, currentWidth, currentHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceBuffer);
525+
else
526+
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, currentWidth, currentHeight, GL_BGRA, GL_UNSIGNED_BYTE, surfaceBuffer);
512527

513528
glActiveTexture(GL_TEXTURE1);
514529
glBindTexture(GL_TEXTURE_2D, 0);
515530
}
516531

517-
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
518-
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)(12 * sizeof(float)));
519-
520-
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId);
521532
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
533+
refreshGLTexture = false;
522534
}
523535

524536
#ifdef _IMGUI_ENABLED
@@ -552,7 +564,7 @@ void OpenGLRenderer::Run()
552564
continue;
553565

554566
// Prevent flickering caused by palette changes
555-
if (PrimarySurface->PrimaryInvalid)
567+
if (!PrimarySurface->IsPrimaryValid)
556568
continue;
557569

558570
// Can't render without palette
@@ -567,6 +579,7 @@ void OpenGLRenderer::Run()
567579

568580
RecalculateGLSurface();
569581
RecalculateSurface = false;
582+
refreshGLTexture = true;
570583
}
571584
else if (RecalculateSurface)
572585
{
@@ -580,6 +593,7 @@ void OpenGLRenderer::Run()
580593

581594
RecalculateGLSurface();
582595
RecalculateSurface = false;
596+
refreshGLTexture = true;
583597
}
584598

585599
PrimarySurface->PrimaryDrawMutex.lock();
@@ -597,9 +611,6 @@ void OpenGLRenderer::Run()
597611

598612
PrimarySurface->PrimaryDrawMutex.unlock();
599613

600-
currentWidth = PrimarySurface->Width;
601-
currentHeight = PrimarySurface->Height;
602-
603614
if (currentBitsPerPixel != PrimarySurface->BitsPerPixel)
604615
{
605616
// BBP switched
@@ -616,8 +627,12 @@ void OpenGLRenderer::Run()
616627

617628
glUniform1i(glGetUniformLocation(shaderProgram32BitId, "surface"), 0);
618629
}
630+
631+
refreshGLTexture = true;
619632
}
620633

634+
currentWidth = PrimarySurface->Width;
635+
currentHeight = PrimarySurface->Height;
621636
currentBitsPerPixel = PrimarySurface->BitsPerPixel;
622637
}
623638
Mutex.unlock();

subtitans/palette.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,18 @@ uint32_t __stdcall Palette::GetEntries(uint32_t shouldBeZero, uint32_t index, ui
5555
return ResultCode::InvalidArgument;
5656
}
5757

58+
if (index > 255 || count > 256 - index)
59+
{
60+
GetLogger()->Error("%s %s index:%i count:%i\n", __FUNCTION__, "requested palette range is out of bounds", index, count);
61+
return ResultCode::InvalidArgument;
62+
}
63+
5864
Mutex.lock();
5965

6066
// BGR -> RGB
6167
for (uint32_t i = 0; i < count; ++i)
6268
{
63-
const uint32_t pixel = RawPalette[i];
69+
const uint32_t pixel = RawPalette[index + i];
6470
result[i] = (pixel & 0xFF00FF00)
6571
| ((pixel << 16) & 0x00FF0000)
6672
| ((pixel >> 16) & 0x000000FF);
@@ -83,6 +89,12 @@ uint32_t __stdcall Palette::SetEntries(uint32_t shouldBeZero, uint32_t index, ui
8389
return ResultCode::InvalidArgument;
8490
}
8591

92+
if (index > 255 || count > 256 - index)
93+
{
94+
GetLogger()->Error("%s %s index:%i count:%i\n", __FUNCTION__, "requested palette range is out of bounds", index, count);
95+
return ResultCode::InvalidArgument;
96+
}
97+
8698
Mutex.lock();
8799

88100
// RGB -> BGR

subtitans/pescalpel.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ static bool UpdateChecksum(const wchar_t* applicationPath, BYTE* base)
6565
return false;
6666
}
6767

68-
GetLogger()->Debug("Header sum: %i, Check sum: %i\n", &headerSum, &checkSum);
68+
GetLogger()->Debug("Header sum: 0x%08X, Check sum: 0x%08X\n", headerSum, checkSum);
6969

7070
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)base;
7171
if (dos->e_magic != IMAGE_DOS_SIGNATURE)
@@ -81,7 +81,7 @@ static bool UpdateChecksum(const wchar_t* applicationPath, BYTE* base)
8181
return false;
8282
}
8383

84-
GetLogger()->Debug("PE header check sum: %i\n", nt->OptionalHeader.CheckSum);
84+
GetLogger()->Debug("PE header check sum: 0x%08X\n", nt->OptionalHeader.CheckSum);
8585

8686
// Original PE contains a value of 0, GOG seems to contain an incorrect value?
8787
// For now we'll just skip updating the check sum...

subtitans/softwarerenderer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ void SoftwareRenderer::Run()
107107
continue;
108108

109109
// Prevent flickering caused by palette changes
110-
if (PrimarySurface->PrimaryInvalid)
110+
if (!PrimarySurface->IsPrimaryValid)
111111
continue;
112112

113113
if (PrimarySurface->BitsPerPixel == 8)

subtitans/subtitans.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ static void StackTrace()
4949

5050
while (ebpRegister != nullptr)
5151
{
52-
if ((uint32_t)ebpRegister >= (uint32_t)stackHighLimit || (uint32_t)ebpRegister < (uint32_t)stackLowLimit)
52+
if ((uint32_t)ebpRegister + 8 >= (uint32_t)stackHighLimit || (uint32_t)ebpRegister < (uint32_t)stackLowLimit)
5353
{
5454
GetLogger()->Informational("Address out of range!\n");
5555
break;
@@ -76,29 +76,38 @@ static void StackTrace()
7676
&& _splitpath_s(modulePath, nullptr, 0, nullptr, 0, name, _MAX_FNAME, ext, _MAX_EXT) == 0)
7777
{
7878
modulePaths.push_back(std::make_pair(std::string(name) + ext, modulePath));
79-
GetLogger()->Informational("[%i] Absolute 0x%04X Relative 0x%04X (%s%s)\n", depth++, returnAddress, returnAddress - (uint32_t)hMod, name, ext);
79+
GetLogger()->Informational("[%i] Absolute 0x%08X Relative 0x%08X (%s%s)\n", depth++, returnAddress, returnAddress - (uint32_t)hMod, name, ext);
8080
}
8181
else
8282
{
83-
GetLogger()->Informational("[%i] Absolute 0x%04X Relative 0x%04X\n", depth++, returnAddress, returnAddress - (uint32_t)hMod);
83+
GetLogger()->Informational("[%i] Absolute 0x%08X Relative 0x%08X\n", depth++, returnAddress, returnAddress - (uint32_t)hMod);
8484
}
8585
}
8686
else
8787
{
88-
GetLogger()->Informational("[%i] Address 0x%04X\n", depth++, returnAddress);
88+
GetLogger()->Informational("[%i] Address 0x%08X\n", depth++, returnAddress);
8989
}
9090

91-
ebpRegister = (uint32_t*)(*ebpRegister);
92-
if (ebpRegister == nullptr)
91+
uint32_t* nextEbp = (uint32_t*)(*ebpRegister);
92+
if ((uint32_t)nextEbp <= (uint32_t)ebpRegister)
93+
{
94+
if (nextEbp == nullptr)
95+
GetLogger()->Informational("Reached base of stack\n");
96+
else
97+
GetLogger()->Informational("Possible stack corruption\n");
98+
9399
break;
94100
}
95101

102+
ebpRegister = nextEbp;
103+
}
104+
96105
GetLogger()->Informational("End of stack trace\n");
97106

98107
for (const auto& modulePath : modulePaths)
99108
{
100109
uint32_t checksum = File::CalculateChecksumA(modulePath.second.c_str());
101-
GetLogger()->Informational("%s CRC32 %04X\n", modulePath.first.c_str(), checksum);
110+
GetLogger()->Informational("%s CRC32 %08X\n", modulePath.first.c_str(), checksum);
102111
}
103112
}
104113

0 commit comments

Comments
 (0)