diff --git a/Doc/FuncStats.xlsx b/Doc/FuncStats.xlsx
index 03d4a9f..bf9367d 100644
Binary files a/Doc/FuncStats.xlsx and b/Doc/FuncStats.xlsx differ
diff --git a/SpaceCadetPinball/SpaceCadetPinball.rc b/SpaceCadetPinball/SpaceCadetPinball.rc
index a955a6b..30ab4b3 100644
--- a/SpaceCadetPinball/SpaceCadetPinball.rc
+++ b/SpaceCadetPinball/SpaceCadetPinball.rc
@@ -337,6 +337,14 @@ BEGIN
END
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+splash_bitmap BITMAP "splash_bitmap.bmp"
+
+
/////////////////////////////////////////////////////////////////////////////
//
// String Table
diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj b/SpaceCadetPinball/SpaceCadetPinball.vcxproj
index 170af74..ebdf4b1 100644
--- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj
+++ b/SpaceCadetPinball/SpaceCadetPinball.vcxproj
@@ -176,6 +176,7 @@
+
@@ -247,6 +248,7 @@
+
@@ -302,6 +304,7 @@
+
diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters
index 6fcaf37..36d606f 100644
--- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters
+++ b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters
@@ -225,6 +225,9 @@
Header Files
+
+ Header Files
+
@@ -416,6 +419,9 @@
Source Files
+
+ Source Files
+
@@ -434,5 +440,8 @@
Resource Files
+
+ Resource Files
+
\ No newline at end of file
diff --git a/SpaceCadetPinball/loader.cpp b/SpaceCadetPinball/loader.cpp
index f3cd42f..6b4fbb7 100644
--- a/SpaceCadetPinball/loader.cpp
+++ b/SpaceCadetPinball/loader.cpp
@@ -7,7 +7,7 @@
#include "zdrv.h"
-errorMsg loader::loader_errors[] =
+errorMsg loader::loader_errors[] =
{
errorMsg{0, "Bad Handle"},
errorMsg{1, "No Type Field"},
@@ -365,15 +365,6 @@ int loader::kicker(int groupIndex, visualKickerStruct* kicker)
int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* visual)
{
- int shortVal;
- __int16* nextShortVal;
- int shortValSub100;
- int shortValSub300;
- int shortValSub304;
- int shortValSub602;
- int shortValSub1100;
- int shortValSub1101;
-
default_vsi(visual);
if (groupIndex < 0)
return error(0, 18);
@@ -396,75 +387,44 @@ int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* vis
unsigned int shortArrSize = partman::field_size(loader_table, stateId, datFieldTypes::ShortArray);
for (auto index = 0u; index < shortArrSize / 2;)
{
- shortVal = *shortArr;
- nextShortVal = shortArr + 1;
- if (shortVal <= 406)
+ switch (shortArr[0])
{
- if (shortVal == 406)
- {
- visual->Kicker.HardHitSoundId = get_sound_id(*nextShortVal);
- }
- else
- {
- shortValSub100 = shortVal - 100;
- if (shortValSub100)
- {
- shortValSub300 = shortValSub100 - 200;
- if (shortValSub300)
- {
- shortValSub304 = shortValSub300 - 4;
- if (shortValSub304)
- {
- if (shortValSub304 != 96)
- return error(9, 18);
- if (kicker(*nextShortVal, &visual->Kicker))
- return error(14, 18);
- }
- else
- {
- visual->SoftHitSoundId = get_sound_id(*nextShortVal);
- }
- }
- else if (material(*nextShortVal, visual))
- {
- return error(15, 18);
- }
- }
- else if (groupIndexOffset)
- {
- return error(7, 18);
- }
- }
- goto LABEL_31;
- }
- shortValSub602 = shortVal - 602;
- if (!shortValSub602)
- {
- visual->CollisionGroup |= 1 << *nextShortVal;
- goto LABEL_31;
- }
- shortValSub1100 = shortValSub602 - 498;
- if (!shortValSub1100)
- {
- visual->SoundIndex4 = get_sound_id(*nextShortVal);
- goto LABEL_31;
- }
- shortValSub1101 = shortValSub1100 - 1;
- if (!shortValSub1101)
- {
- visual->SoundIndex3 = get_sound_id(*nextShortVal);
- LABEL_31:
- shortArr = nextShortVal + 1;
- index = index + 2;
- goto LABEL_32;
- }
- if (shortValSub1101 != 399)
+ case 100:
+ if (groupIndexOffset)
+ return error(7, 18);
+ break;
+ case 300:
+ if (material(shortArr[1], visual))
+ return error(15, 18);
+ break;
+ case 304:
+ visual->SoftHitSoundId = get_sound_id(shortArr[1]);
+ break;
+ case 400:
+ if (kicker(shortArr[1], &visual->Kicker))
+ return error(14, 18);
+ break;
+ case 406:
+ visual->Kicker.HardHitSoundId = get_sound_id(shortArr[1]);
+ break;
+ case 602:
+ visual->CollisionGroup |= 1 << shortArr[1];
+ break;
+ case 1100:
+ visual->SoundIndex4 = get_sound_id(shortArr[1]);
+ break;
+ case 1101:
+ visual->SoundIndex3 = get_sound_id(shortArr[1]);
+ break;
+ case 1500:
+ shortArr += 7;
+ index += 7;
+ break;
+ default:
return error(9, 18);
- shortArr = nextShortVal + 8;
- index = index + 9;
- LABEL_32:
- {
}
+ shortArr += 2;
+ index += 2;
}
}
diff --git a/SpaceCadetPinball/splash.cpp b/SpaceCadetPinball/splash.cpp
new file mode 100644
index 0000000..632cc55
--- /dev/null
+++ b/SpaceCadetPinball/splash.cpp
@@ -0,0 +1,295 @@
+#include "pch.h"
+#include "splash.h"
+
+
+#include "memory.h"
+#include "pinball.h"
+
+HINSTANCE splash::HInstance;
+
+splash_struct* splash::splash_screen(HINSTANCE hInstance, LPCSTR bmpName1, LPCSTR bmpName2)
+{
+ WNDCLASSA WndClass{};
+ tagRECT Rect{};
+
+ auto splashStruct = reinterpret_cast(memory::allocate(0x1B0u));
+ if (!splashStruct)
+ return nullptr;
+
+ lstrcpyA(splashStruct->BmpName1, bmpName1);
+ lstrcpyA(splashStruct->BmpName2, bmpName2);
+ if (!HInstance)
+ {
+ HInstance = hInstance;
+ WndClass.style = 0;
+ WndClass.lpfnWndProc = splash_message_handler;
+ WndClass.cbClsExtra = 0;
+ WndClass.cbWndExtra = 4;
+ WndClass.hInstance = hInstance;
+ WndClass.hIcon = nullptr;
+ WndClass.hCursor = LoadCursorA(nullptr, IDC_ARROW);
+ WndClass.hbrBackground = nullptr;
+ WndClass.lpszMenuName = pinball::WindowName;
+ WndClass.lpszClassName = "3DPB_SPLASH_CLASS";
+ RegisterClassA(&WndClass);
+ }
+ splashStruct->Bitmap = nullptr;
+ HWND windowHandle = CreateWindowExA(0, "3DPB_SPLASH_CLASS", pinball::WindowName, 0x80000000, -10, -10, 1, 1,
+ nullptr, nullptr, HInstance, nullptr);
+ splashStruct->WindowHandle = windowHandle;
+ if (!windowHandle)
+ {
+ memory::free(splashStruct);
+ return nullptr;
+ }
+
+ SetWindowLongA(windowHandle, 0, reinterpret_cast(splashStruct));
+ GetWindowRect(GetDesktopWindow(), &Rect);
+ splash_bitmap_setup(splashStruct);
+ //MoveWindow(splashStruct->WindowHandle, 0, 0, Rect.right - Rect.left, Rect.bottom - Rect.top, 0);
+
+ /*Mod - less intrusive splash*/
+ auto centerX = (Rect.right - Rect.left - splashStruct->Width) / 2;
+ auto CenterY = (Rect.bottom - Rect.top - splashStruct->Height) / 2;
+ MoveWindow(splashStruct->WindowHandle, centerX, CenterY, splashStruct->Width, splashStruct->Height, 0);
+
+ ShowWindow(splashStruct->WindowHandle, 8);
+ SetFocus(splashStruct->WindowHandle);
+ UpdateWindow(splashStruct->WindowHandle);
+ return splashStruct;
+}
+
+void splash::splash_bitmap_setup(splash_struct* splashStruct)
+{
+ HBITMAP bmpHandle2;
+ BITMAP bmp;
+
+ HBITMAP bmpHandle1 = nullptr;
+ HDC desktopDC = GetDC(GetDesktopWindow());
+ if (desktopDC)
+ {
+ splashStruct->DrawingContext = CreateCompatibleDC(desktopDC);
+ bmpHandle1 = CreateCompatibleBitmap(desktopDC, 10, 10);
+ ReleaseDC(splashStruct->WindowHandle, desktopDC);
+ if (bmpHandle1)
+ {
+ if (splashStruct->DrawingContext)
+ {
+ SelectObject(splashStruct->DrawingContext, bmpHandle1);
+ if ((GetDeviceCaps(splashStruct->DrawingContext, RASTERCAPS) & RC_PALETTE) != 0
+ || GetDeviceCaps(splashStruct->DrawingContext, NUMCOLORS) >= 256)
+ {
+ bmpHandle2 = load_title_bitmap(HInstance, splashStruct->DrawingContext, splashStruct->BmpName1, 10,
+ 236, &splashStruct->Palette);
+ }
+ else
+ {
+ bmpHandle2 = LoadBitmapA(HInstance, splashStruct->BmpName2);
+ }
+ splashStruct->Bitmap = bmpHandle2;
+
+ if (bmpHandle2)
+ {
+ SelectObject(splashStruct->DrawingContext, bmpHandle2);
+ DeleteObject(bmpHandle1);
+ GetObjectA(splashStruct->Bitmap, 24, &bmp);
+ splashStruct->Width = bmp.bmWidth;
+ splashStruct->Height = bmp.bmHeight;
+ return;
+ }
+ }
+ }
+ else
+ {
+ GetLastError();
+ }
+ }
+
+ if (splashStruct->Palette)
+ DeleteObject(splashStruct->Palette);
+ if (splashStruct->WindowHandle)
+ DestroyWindow(splashStruct->WindowHandle);
+ if (bmpHandle1)
+ DeleteObject(bmpHandle1);
+ if (splashStruct->DrawingContext)
+ DeleteDC(splashStruct->DrawingContext);
+ splashStruct->Bitmap = nullptr;
+}
+
+HBITMAP splash::load_title_bitmap(HMODULE hModule, HDC hdc, LPCSTR lpName, UINT iStart, int iEnd, HPALETTE* palettePtr)
+{
+ LOGPALETTEx256 plpal;
+
+ auto resH = FindResourceA(hModule, lpName, RT_BITMAP);
+ if (!resH)
+ return nullptr;
+ auto resHGlobal = LoadResource(hModule, resH);
+ if (!resHGlobal)
+ return nullptr;
+
+ auto bmp = static_cast(LockResource(resHGlobal));
+ int numColors = bmp->bmiHeader.biClrUsed;
+ if (!numColors)
+ numColors = 1 << LOBYTE(bmp->bmiHeader.biBitCount);
+ if (bmp->bmiHeader.biBitCount > 4u)
+ {
+ *palettePtr = splash_init_palette(&plpal);
+ if (*palettePtr)
+ {
+ int cEntries = 0;
+ if (iEnd > 0)
+ {
+ auto dst = &plpal.palPalEntry[iStart];
+ auto src = &bmp->bmiColors[0];
+ for (; cEntries < iEnd && cEntries < numColors; ++cEntries)
+ {
+ dst->peRed = src->rgbRed;
+ dst->peGreen = src->rgbGreen;
+ dst->peBlue = src->rgbBlue;
+ dst->peFlags = 4;
+ src++;
+ dst++;
+ }
+ }
+ SetPaletteEntries(*palettePtr, iStart, cEntries, &plpal.palPalEntry[iStart]);
+ SelectPalette(hdc, *palettePtr, 0);
+ RealizePalette(hdc);
+ }
+ }
+
+ auto resBmp = CreateDIBitmap(hdc, &bmp->bmiHeader, 4u, &bmp->bmiColors[numColors], bmp, 0);
+ FreeResource(resHGlobal);
+ return resBmp;
+}
+
+HPALETTE splash::splash_init_palette(LOGPALETTEx256* plpal)
+{
+ plpal->palVersion = 768;
+ plpal->palNumEntries = 256;
+ auto hPalette = CreatePalette(reinterpret_cast(plpal));
+ auto dc = GetDC(GetDesktopWindow());
+ GetDeviceCaps(dc, RASTERCAPS);
+ if (GetDeviceCaps(dc, SIZEPALETTE) != 256)
+ {
+ if (hPalette)
+ DeleteObject(hPalette);
+ ReleaseDC(GetDesktopWindow(), dc);
+ return nullptr;
+ }
+
+ SetSystemPaletteUse(dc, 2u);
+ SetSystemPaletteUse(dc, 1u);
+ auto hPal = SelectPalette(dc, hPalette, 0);
+ RealizePalette(dc);
+ SelectPalette(dc, hPal, 0);
+ RealizePalette(dc);
+ GetSystemPaletteEntries(dc, 0, 256u, plpal->palPalEntry);
+ ReleaseDC(GetDesktopWindow(), dc);
+
+ auto dst = &plpal->palPalEntry[0];
+ for (auto index = 256; index; --index)
+ {
+ dst->peFlags = 0;
+ dst++;
+ }
+
+ dst = &plpal->palPalEntry[10];
+ for (auto index = 10; index < 246; ++index)
+ {
+ dst->peRed = index;
+ dst->peGreen = index;
+ dst->peBlue = index;
+ dst->peFlags = 4;
+ dst++;
+ }
+ ResizePalette(hPalette, 256u);
+ SetPaletteEntries(hPalette, 0, 256u, plpal->palPalEntry);
+ return hPalette;
+}
+
+void splash::splash_paint(splash_struct* splashStruct, HDC dc)
+{
+ tagRECT Rect{};
+
+ if (splashStruct->Bitmap)
+ {
+ GetWindowRect(GetDesktopWindow(), &Rect);
+ splashStruct->CenterX = (Rect.right - Rect.left - splashStruct->Width) / 2;
+ splashStruct->CenterY = (Rect.bottom - Rect.top - splashStruct->Height) / 2;
+ SelectPalette(dc, splashStruct->Palette, 0);
+ RealizePalette(dc);
+ SelectPalette(splashStruct->DrawingContext, splashStruct->Palette, 0);
+ RealizePalette(splashStruct->DrawingContext);
+ /*BitBlt(dc, splashStruct->CenterX, splashStruct->CenterY, splashStruct->Width,
+ splashStruct->Height, splashStruct->DrawingContext, 0, 0, SRCCOPY);*/
+
+ /*Mod - less intrusive splash*/
+ BitBlt(dc, 0, 0, splashStruct->Width, splashStruct->Height,
+ splashStruct->DrawingContext, 0, 0, SRCCOPY);
+ }
+}
+
+void splash::splash_destroy(splash_struct* splashStruct)
+{
+ if (splashStruct)
+ {
+ if (splashStruct->WindowHandle)
+ {
+ DestroyWindow(splashStruct->WindowHandle);
+ splashStruct->WindowHandle = nullptr;
+
+ if (splashStruct->Palette)
+ DeleteObject(splashStruct->Palette);
+ splashStruct->Palette = nullptr;
+
+ if (splashStruct->DrawingContext)
+ DeleteDC(splashStruct->DrawingContext);
+ if (splashStruct->Bitmap)
+ DeleteObject(splashStruct->Bitmap);
+ }
+ memory::free(splashStruct);
+ }
+ if (HInstance)
+ {
+ UnregisterClassA("3DPB_SPLASH_CLASS", HInstance);
+ HInstance = nullptr;
+ }
+}
+
+void splash::splash_hide(splash_struct* splashStruct)
+{
+ if (splashStruct && splashStruct->WindowHandle)
+ {
+ HDC dc = GetDC(splashStruct->WindowHandle);
+ BitBlt(dc, 0, 0, splashStruct->CenterX, splashStruct->CenterY, dc, 0, 0, 0x42u);
+ ReleaseDC(splashStruct->WindowHandle, dc);
+ }
+}
+
+LRESULT splash::splash_message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ tagPAINTSTRUCT Paint{};
+
+ switch (Msg)
+ {
+ case WM_PAINT:
+ {
+ auto splashStruct = reinterpret_cast(GetWindowLongA(hWnd, 0));
+ BeginPaint(hWnd, &Paint);
+ EndPaint(hWnd, &Paint);
+ auto dc = GetDC(hWnd);
+ if (dc && splashStruct)
+ {
+ BitBlt(dc, 0, 0, 10000, 10000, dc, 0, 0, BLACKNESS);
+ splash_paint(splashStruct, dc);
+ }
+ ReleaseDC(hWnd, dc);
+ break;
+ }
+ case WM_ERASEBKGND:
+ break;
+ default:
+ return DefWindowProcA(hWnd, Msg, wParam, lParam);
+ }
+ return 0;
+}
diff --git a/SpaceCadetPinball/splash.h b/SpaceCadetPinball/splash.h
new file mode 100644
index 0000000..e8f7d97
--- /dev/null
+++ b/SpaceCadetPinball/splash.h
@@ -0,0 +1,33 @@
+#pragma once
+
+struct LOGPALETTEx256;
+
+struct splash_struct
+{
+ HWND WindowHandle;
+ HPALETTE Palette;
+ HBITMAP Bitmap;
+ HDC DrawingContext;
+ int Width;
+ int Height;
+ int CenterX;
+ int CenterY;
+ char BmpName1[200];
+ char BmpName2[200];
+};
+
+
+class splash
+{
+public:
+ static splash_struct* splash_screen(HINSTANCE hInstance, LPCSTR bmpName1, LPCSTR bmpName2);
+ static void splash_bitmap_setup(splash_struct* splashStruct);
+ static HBITMAP load_title_bitmap(HMODULE hModule, HDC hdc, LPCSTR lpName, UINT iStart, int iEnd, HPALETTE* palettePtr);
+ static HPALETTE splash_init_palette(LOGPALETTEx256* plpal);
+ static void splash_paint(splash_struct* splashStruct, HDC dc);
+ static void splash_destroy(splash_struct* splashStruct);
+ static void splash_hide(splash_struct* splashStruct);
+ static LRESULT __stdcall splash_message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+private:
+ static HINSTANCE HInstance;
+};
diff --git a/SpaceCadetPinball/splash_bitmap.bmp b/SpaceCadetPinball/splash_bitmap.bmp
new file mode 100644
index 0000000..6b2b397
Binary files /dev/null and b/SpaceCadetPinball/splash_bitmap.bmp differ
diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp
index caa09ef..e63efff 100644
--- a/SpaceCadetPinball/winmain.cpp
+++ b/SpaceCadetPinball/winmain.cpp
@@ -9,6 +9,7 @@
#include "pb.h"
#include "Sound.h"
#include "resource.h"
+#include "splash.h"
HINSTANCE winmain::hinst = nullptr;
HWND winmain::hwnd_frame = nullptr;
@@ -143,7 +144,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
WndClass.hbrBackground = (HBRUSH)16;
WndClass.lpszMenuName = "MENU_1";
WndClass.lpszClassName = windowClass;
- //auto tmpBuf = splash_screen((int)hInstance, "splash_bitmap", "splash_bitmap"); // No splash for now
+ auto splash = splash::splash_screen(hInstance, "splash_bitmap", "splash_bitmap");
RegisterClassA(&WndClass);
pinball::FindShiftKeys();
@@ -174,11 +175,11 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
fullscrn::set_screen_mode(options::Options.FullScreen);
UpdateWindow(hwnd_frame);
- /*if (tmpBuf) //Close splash
+ if (splash)
{
- splash_hide(tmpBuf);
- splash_destroy(tmpBuf);
- }*/
+ splash::splash_hide(splash);
+ splash::splash_destroy(splash);
+ }
pinball::adjust_priority(options::Options.PriorityAdj);
const auto startTime = timeGetTime();