diff --git a/Doc/FuncStats.xlsx b/Doc/FuncStats.xlsx index bfd49e4..b5acbe9 100644 Binary files a/Doc/FuncStats.xlsx and b/Doc/FuncStats.xlsx differ diff --git a/SpaceCadetPinball/SpaceCadetPinball.cpp b/SpaceCadetPinball/SpaceCadetPinball.cpp index ba9a1f9..e3107f1 100644 --- a/SpaceCadetPinball/SpaceCadetPinball.cpp +++ b/SpaceCadetPinball/SpaceCadetPinball.cpp @@ -22,6 +22,7 @@ int main() char cmdLine[1]{}; //WinMain(pinball::hinst, 0, cmdLine, 10); + gdrv::init(0, 0); auto dib = gdrv::DibCreate(8, 1, 1); gdrv::DibSetUsage(dib, 0, 1); diff --git a/SpaceCadetPinball/gdrv.cpp b/SpaceCadetPinball/gdrv.cpp index 5d7ab17..d1915ad 100644 --- a/SpaceCadetPinball/gdrv.cpp +++ b/SpaceCadetPinball/gdrv.cpp @@ -1,69 +1,91 @@ #include "pch.h" #include "gdrv.h" #include "memory.h" +#include "winmain.h" -HPALETTE gdrv::palette_handle=0; +HPALETTE gdrv::palette_handle = nullptr; +HINSTANCE gdrv::hinst; +HWND gdrv::hwnd; +LOGPALETTEx256 gdrv::current_palette{}; +int gdrv::sequence_handle; +HDC gdrv::sequence_hdc; +int gdrv::use_wing = 0; + + +int gdrv::init(HINSTANCE hInst, HWND hWnd) +{ + hinst = hInst; + hwnd = hWnd; + if (!palette_handle) + palette_handle = CreatePalette((LOGPALETTE*)¤t_palette); + return 0; +} + +int gdrv::uninit() +{ + if (palette_handle) + DeleteObject(palette_handle); + return 0; +} void gdrv::get_focus() { } -gdrv_dib* gdrv::DibCreate(__int16 bpp, int width, int height) +BITMAPINFO* gdrv::DibCreate(__int16 bpp, int width, int height) { auto sizeBytes = height * ((width * bpp / 8 + 3) & 0xFFFFFFFC); auto buf = GlobalAlloc(0x42u, sizeBytes + 1064); - auto dib = static_cast(GlobalLock(buf)); + auto dib = static_cast(GlobalLock(buf)); if (!dib) return nullptr; - dib->BufferSize = sizeBytes; - dib->Width = width; - dib->PaletteOffset = 40; - dib->Height = height; - dib->Unknown3_1 = 1; - dib->Bpp = bpp; - dib->Unknown4 = 0; - dib->Unknown6 = 0; - dib->Unknown7 = 0; - dib->NumberOfColors = 0; - dib->Unknown9 = 0; + dib->bmiHeader.biSizeImage = sizeBytes; + dib->bmiHeader.biWidth = width; + dib->bmiHeader.biSize = 40; + dib->bmiHeader.biHeight = height; + dib->bmiHeader.biPlanes = 1; + dib->bmiHeader.biBitCount = bpp; + dib->bmiHeader.biCompression = 0; + dib->bmiHeader.biXPelsPerMeter = 0; + dib->bmiHeader.biYPelsPerMeter = 0; + dib->bmiHeader.biClrUsed = 0; + dib->bmiHeader.biClrImportant = 0; if (bpp == 4) { - dib->NumberOfColors = 16; + dib->bmiHeader.biClrUsed = 16; } else if (bpp == 8) { - dib->NumberOfColors = 256; + dib->bmiHeader.biClrUsed = 256; } - auto pltPtr = &dib->Palette0; - for (auto index = 0; index < dib->NumberOfColors / 16; ++index, pltPtr++) + int index = 0; + for (auto i = (int*)dib->bmiColors; index < static_cast(dib->bmiHeader.biClrUsed) / 16; ++index) { - *pltPtr = gdrv_dib_palette{ - {0}, - {0x800000}, - {0x8000}, - {8421376}, - {128}, - {8388736}, - {32896}, - {12632256}, - {8421504}, - {16711680}, - {65280}, - {16776960}, - {255}, - {16711935}, - {0xFFFF}, - {0xFFFFFF}, - }; + *i++ = 0; + *i++ = 0x800000; + *i++ = 0x8000; + *i++ = 8421376; + *i++ = 128; + *i++ = 8388736; + *i++ = 32896; + *i++ = 12632256; + *i++ = 8421504; + *i++ = 16711680; + *i++ = 65280; + *i++ = 16776960; + *i++ = 255; + *i++ = 16711935; + *i++ = 0xFFFF; + *i++ = 0xFFFFFF; } return dib; } -void gdrv::DibSetUsage(gdrv_dib* dib, HPALETTE hpal, int someFlag) +void gdrv::DibSetUsage(BITMAPINFO* dib, HPALETTE hpal, int someFlag) { tagPALETTEENTRY pPalEntries[256]; // [esp+4h] [ebp-400h] @@ -71,18 +93,18 @@ void gdrv::DibSetUsage(gdrv_dib* dib, HPALETTE hpal, int someFlag) hpal = static_cast(GetStockObject(DEFAULT_PALETTE)); if (!dib) return; - int numOfColors = dib->NumberOfColors; + int numOfColors = dib->bmiHeader.biClrUsed; if (!numOfColors) { - auto bpp = dib->Bpp; + auto bpp = dib->bmiHeader.biBitCount; if (bpp <= 8u) numOfColors = 1 << bpp; } - if (numOfColors > 0 && (dib->Unknown4 != 3 || numOfColors == 3)) + if (numOfColors > 0 && (dib->bmiHeader.biCompression != 3 || numOfColors == 3)) { if (someFlag && someFlag <= 2) { - auto pltPtr = (short*)((char*)dib + dib->PaletteOffset); + auto pltPtr = (short*)((char*)dib + dib->bmiHeader.biSize); for (int i = 0; i < numOfColors; ++i) { *pltPtr++ = i; @@ -91,7 +113,7 @@ void gdrv::DibSetUsage(gdrv_dib* dib, HPALETTE hpal, int someFlag) else { assertm(false, "Entered bad code"); - char* dibPtr = (char*)dib + dib->PaletteOffset; + char* dibPtr = (char*)dib + dib->bmiHeader.biSize; if (numOfColors >= 256) numOfColors = 256; GetPaletteEntries(hpal, 0, numOfColors, pPalEntries); @@ -115,7 +137,7 @@ void gdrv::DibSetUsage(gdrv_dib* dib, HPALETTE hpal, int someFlag) int gdrv::create_bitmap_dib(gdrv_bitmap8* bmp, int width, int height) { char* bmpBufPtr; // ecx - gdrv_dib* dib = DibCreate(8, width, height); + auto dib = DibCreate(8, width, height); DibSetUsage(dib, palette_handle, 1); bmp->Dib = dib; @@ -123,14 +145,14 @@ int gdrv::create_bitmap_dib(gdrv_bitmap8* bmp, int width, int height) bmp->Stride = width; if (width % 4) bmp->Stride = 4 - width % 4 + width; - gdrv_dib* dib2 = bmp->Dib; - bmp->Height = height; - bmp->SomeByte = 2; - if (dib2->Unknown4 == 3) - bmpBufPtr = (char*)&dib2->Unknown3_1 + dib2->PaletteOffset; + bmp->Height = height; + bmp->BitmapType = BitmapType::DibBitmap; + + if (dib->bmiHeader.biCompression == 3) + bmpBufPtr = (char*)&dib->bmiHeader.biPlanes + dib->bmiHeader.biSize; else - bmpBufPtr = (char*)&dib2->PaletteOffset + 4 * dib2->NumberOfColors + dib2->PaletteOffset; + bmpBufPtr = (char*)&dib->bmiHeader.biSize + 4 * dib->bmiHeader.biClrUsed + dib->bmiHeader.biSize; bmp->BmpBufPtr1 = bmpBufPtr; bmp->BmpBufPtr2 = bmpBufPtr; return 0; @@ -150,7 +172,7 @@ int gdrv::create_raw_bitmap(gdrv_bitmap8* bmp, int width, int height, int flag) bmp->Stride = width - width % 4 + 4; unsigned int sizeInBytes = height * bmp->Stride; bmp->Height = height; - bmp->SomeByte = 1; + bmp->BitmapType = BitmapType::RawBitmap; char* buf = memory::allocate(sizeInBytes); bmp->BmpBufPtr1 = buf; if (!buf) @@ -158,3 +180,212 @@ int gdrv::create_raw_bitmap(gdrv_bitmap8* bmp, int width, int height, int flag) bmp->BmpBufPtr2 = buf; return 0; } + + +int gdrv::display_palette(PALETTEENTRY* plt) +{ + if (palette_handle) + DeleteObject(palette_handle); + palette_handle = CreatePalette((LOGPALETTE*)¤t_palette); + auto windowHandle = GetDesktopWindow(); + auto dc = winmain::_GetDC(windowHandle); + SetSystemPaletteUse(dc, 2u); + SetSystemPaletteUse(dc, 1u); + auto pltHandle = SelectPalette(dc, palette_handle, 0); + RealizePalette(dc); + SelectPalette(dc, pltHandle, 0); + GetSystemPaletteEntries(dc, 0, 0x100u, current_palette.palPalEntry); + for (int i = 0; i < 256; i++) + { + current_palette.palPalEntry[i].peFlags = 0; + } + + auto pltSrc = &plt[10]; + auto pltDst = ¤t_palette.palPalEntry[10]; + for (int index = 236; index > 0; --index) + { + if (plt) + { + pltDst->peRed = pltSrc->peRed; + pltDst->peGreen = pltSrc->peGreen; + pltDst->peBlue = pltSrc->peBlue; + } + pltDst->peFlags = 4; + pltSrc++; + pltDst++; + } + + if (!(GetDeviceCaps(dc, 38) & 0x100)) + { + current_palette.palPalEntry[255].peBlue = -1; + current_palette.palPalEntry[255].peGreen = -1; + current_palette.palPalEntry[255].peRed = -1; + } + + ResizePalette(palette_handle, 0x100u); + SetPaletteEntries(palette_handle, 0, 0x100u, current_palette.palPalEntry); + windowHandle = GetDesktopWindow(); + ReleaseDC(windowHandle, dc); + return 0; +} + + +int gdrv::destroy_bitmap(gdrv_bitmap8* bmp) +{ + if (!bmp) + return -1; + if (bmp->BitmapType == BitmapType::RawBitmap) + { + memory::free(bmp->BmpBufPtr1); + } + else if (bmp->BitmapType == BitmapType::DibBitmap) + { + GlobalUnlock(GlobalHandle(bmp->Dib)); + GlobalFree(GlobalHandle(bmp->Dib)); + } + memset(bmp, 0, sizeof(gdrv_bitmap8)); + return 0; +} + +UINT gdrv::start_blit_sequence() +{ + HDC dc = winmain::_GetDC(hwnd); + sequence_handle = 0; + sequence_hdc = dc; + SelectPalette(dc, palette_handle, 0); + return RealizePalette(sequence_hdc); +} + +void gdrv::blit_sequence(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth, int DestHeight) +{ + if (!use_wing) + StretchDIBits( + sequence_hdc, + xDest, + yDest, + DestWidth, + DestHeight, + xSrc, + bmp->Height - ySrcOff - DestHeight, + DestWidth, + DestHeight, + bmp->BmpBufPtr1, + bmp->Dib, + 1u, + SRCCOPY); +} + + +void gdrv::end_blit_sequence() +{ + ReleaseDC(hwnd, sequence_hdc); +} + +void gdrv::blit(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth, int DestHeight) +{ + HDC dc = winmain::_GetDC(hwnd); + if (dc) + { + SelectPalette(dc, palette_handle, 0); + RealizePalette(dc); + if (!use_wing) + StretchDIBits( + dc, + xDest, + yDest, + DestWidth, + DestHeight, + xSrc, + bmp->Height - ySrcOff - DestHeight, + DestWidth, + DestHeight, + bmp->BmpBufPtr1, + bmp->Dib, + 1u, + SRCCOPY); + ReleaseDC(hwnd, dc); + } +} + +void gdrv::blat(gdrv_bitmap8* bmp, int xDest, int yDest) +{ + HDC dc = winmain::_GetDC(hwnd); + SelectPalette(dc, palette_handle, 0); + RealizePalette(dc); + if (!use_wing) + StretchDIBits( + dc, + xDest, + yDest, + bmp->Width, + bmp->Height, + 0, + 0, + bmp->Width, + bmp->Height, + bmp->BmpBufPtr1, + bmp->Dib, + 1u, + SRCCOPY); + ReleaseDC(hwnd, dc); +} + +void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, char fillChar) +{ + int bmpHeight = bmp->Height; + if (bmpHeight < 0) + bmpHeight = -bmpHeight; + char* bmpPtr = &bmp->BmpBufPtr1[bmp->Width * (bmpHeight - height - yOff) + xOff]; + if (height > 0) + { + do + { + if (width > 0) + memset(bmpPtr, fillChar, width); + bmpPtr += bmp->Stride; + --height; + } + while (height); + } +} + +void gdrv::copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp, + int srcXOff, int srcYOff) +{ + int dstHeight = abs(dstBmp->Height); + int srcHeight = abs(srcBmp->Height); + char* srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeight - height - srcYOff) + srcXOff]; + char* dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeight - height - yOff) + xOff]; + + for (int y = height; y > 0; --y) + { + for (int x = width; x > 0; --x) + *dstPtr++ = *srcPtr++; + + srcPtr += srcBmp->Stride - width; + dstPtr += dstBmp->Stride - width; + } +} + +void gdrv::copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, + gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff) +{ + int dstHeight = abs(dstBmp->Height); + int srcHeight = abs(srcBmp->Height); + char* srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeight - height - srcYOff) + srcXOff]; + char* dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeight - height - yOff) + xOff]; + + for (int y = height; y > 0; --y) + { + for (int x = width; x > 0; --x) + { + if (*srcPtr) + *dstPtr = *srcPtr; + ++srcPtr; + ++dstPtr; + } + + srcPtr += srcBmp->Stride - width; + dstPtr += dstBmp->Stride - width; + } +} diff --git a/SpaceCadetPinball/gdrv.h b/SpaceCadetPinball/gdrv.h index 10312aa..697e84e 100644 --- a/SpaceCadetPinball/gdrv.h +++ b/SpaceCadetPinball/gdrv.h @@ -1,93 +1,74 @@ #pragma once -union tagPALETTEENTRY2 +enum class BitmapType : char { - unsigned __int32 PltInt; - tagPALETTEENTRY Plt; + None = 0, + RawBitmap = 1, + DibBitmap=2, }; -struct gdrv_dib_palette -{ - tagPALETTEENTRY2 Color0; - tagPALETTEENTRY2 Color1; - tagPALETTEENTRY2 Color2; - tagPALETTEENTRY2 Color3; - tagPALETTEENTRY2 Color4; - tagPALETTEENTRY2 Color5; - tagPALETTEENTRY2 Color6; - tagPALETTEENTRY2 Color7; - tagPALETTEENTRY2 Color8; - tagPALETTEENTRY2 Color9; - tagPALETTEENTRY2 Color10; - tagPALETTEENTRY2 Color11; - tagPALETTEENTRY2 Color12; - tagPALETTEENTRY2 Color13; - tagPALETTEENTRY2 Color14; - tagPALETTEENTRY2 Color15; -}; - -struct __declspec(align(4)) gdrv_dib -{ - int PaletteOffset; - int Width; - int Height; - __int16 Unknown3_1; - unsigned __int16 Bpp; - int Unknown4; - int BufferSize; - int Unknown6; - int Unknown7; - int NumberOfColors; - int Unknown9; - gdrv_dib_palette Palette0; - gdrv_dib_palette Palette1; - gdrv_dib_palette Palette2; - gdrv_dib_palette Palette3; - gdrv_dib_palette Palette4; - gdrv_dib_palette Palette5; - gdrv_dib_palette Palette6; - gdrv_dib_palette Palette7; - gdrv_dib_palette Palette8; - gdrv_dib_palette Palette9; - gdrv_dib_palette Palette10; - gdrv_dib_palette Palette11; - gdrv_dib_palette Palette12; - gdrv_dib_palette Palette13; - gdrv_dib_palette Palette14; - gdrv_dib_palette Palette15; - char BmpBuffer[1]; -}; #pragma pack(push, 1) struct __declspec(align(1)) gdrv_bitmap8 { - gdrv_dib* Dib; + BITMAPINFO* Dib; char* BmpBufPtr2; char* BmpBufPtr1; int Width; int Height; int Stride; - char SomeByte; + BitmapType BitmapType; int Color6; int XPosition; int YPosition; }; #pragma pack(pop) -static_assert(sizeof(tagPALETTEENTRY2) == 4, "Wrong size of tagPALETTEENTRY2"); -static_assert(sizeof(gdrv_dib_palette) == 4 * 16, "Wrong size of gdrv_dib_palette"); -static_assert(sizeof(gdrv_dib) == (10 * 4) + sizeof(gdrv_dib_palette) * 16 + 4, "Wrong size of gdrv_dib"); + +struct LOGPALETTEx256 +{ + WORD palVersion; + WORD palNumEntries; + PALETTEENTRY palPalEntry[256]; + + LOGPALETTEx256() : palVersion(0x300), palNumEntries(256), palPalEntry{} + { + } +}; + static_assert(sizeof(gdrv_bitmap8) == 37, "Wrong size of gdrv_bitmap8"); class gdrv { public: static HPALETTE palette_handle; + static HINSTANCE hinst; + static HWND hwnd; + static LOGPALETTEx256 current_palette; + static int sequence_handle; + static HDC sequence_hdc; + static int use_wing; + + static int init(HINSTANCE hInst, HWND hWnd); + static int uninit(); static void get_focus(); - static gdrv_dib* DibCreate(__int16 bpp, int width, int height); - static void DibSetUsage(gdrv_dib* dib, HPALETTE hpal, int someFlag); + static BITMAPINFO* DibCreate(__int16 bpp, int width, int height); + static void DibSetUsage(BITMAPINFO* dib, HPALETTE hpal, int someFlag); static int create_bitmap_dib(gdrv_bitmap8* bmp, int width, int height); static int create_bitmap(gdrv_bitmap8* bmp, int width, int height); static int create_raw_bitmap(gdrv_bitmap8* bmp, int width, int height, int flag); + static int destroy_bitmap(gdrv_bitmap8* bmp); + static int display_palette(PALETTEENTRY* plt); + static UINT start_blit_sequence(); + static void blit_sequence(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth, + int DestHeight); + static void end_blit_sequence(); + static void blit(gdrv_bitmap8* bmp, int xSrc, int ySrcOff, int xDest, int yDest, int DestWidth, int DestHeight); + static void blat(gdrv_bitmap8* bmp, int xDest, int yDest); + static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, char fillChar); + static void copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp, + int srcXOff, int srcYOff); + static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, + gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff); private: }; diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index f83ecef..13aec7b 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -160,6 +160,25 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi while (true) { + if(false) + { + auto plt = (PALETTEENTRY*)malloc(1024u); + auto gg = sizeof(LOGPALETTEx256); + auto pltPtr = &plt[10]; + for (int i1 = 0, i2 = 0; i1 < 256 - 10; ++i1, i2 += 8) + { + unsigned char blue = i2, redGreen = i2; + if (i2 > 255) + { + blue = 255; + redGreen = i1; + } + + *pltPtr++ = { redGreen, redGreen, blue }; + } + gdrv::display_palette(plt); + } + if (!ProcessWindowMessages() || bQuit) break; Sleep(8); @@ -205,8 +224,8 @@ int winmain::ProcessWindowMessages() void winmain::memalloc_failure() { /*midi_music_stop(); - Sound_Close(); - gdrv_uninit();*/ + Sound_Close();*/ + gdrv::uninit(); char* caption = pinball::get_rc_string(170, 0); char* text = pinball::get_rc_string(179, 0); MessageBoxA(nullptr, text, caption, 0x2030u);