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();