diff --git a/Doc/FuncStats.xlsx b/Doc/FuncStats.xlsx index b5acbe9..ea9f0bd 100644 Binary files a/Doc/FuncStats.xlsx and b/Doc/FuncStats.xlsx differ diff --git a/SpaceCadetPinball/loader.cpp b/SpaceCadetPinball/loader.cpp index fb7ba3b..0daf74f 100644 --- a/SpaceCadetPinball/loader.cpp +++ b/SpaceCadetPinball/loader.cpp @@ -451,8 +451,8 @@ int loader::query_visual(int groupIndex, int groupIndexOffset, visualStruct* vi visual->ZMap = bitmap16; if (bitmap16) { - bitmap16->BmpBufPtr1 = bitmap16->BmpBuffer; - visual->ZMap->bmpBufPtr2 = visual->ZMap->BmpBufPtr1; + bitmap16->ZPtr1 = bitmap16->ZBuffer; + visual->ZMap->ZPtr2 = visual->ZMap->ZPtr1; } shortArr = (__int16*)partman::field(loader_table, groupIndexSum2, datFieldTypes::ShortArray); if (shortArr) diff --git a/SpaceCadetPinball/memory.h b/SpaceCadetPinball/memory.h index d7e4a50..e42d53c 100644 --- a/SpaceCadetPinball/memory.h +++ b/SpaceCadetPinball/memory.h @@ -11,3 +11,12 @@ public: static int critical_allocation; static void (*critical_callback)(); }; + + +// Fill memory block with an integer value +inline void memset32(void* ptr, unsigned int value, int count) +{ + auto p = (unsigned int*)ptr; + for (int i = 0; i < count; i++) + *p++ = value; +} \ No newline at end of file diff --git a/SpaceCadetPinball/render.h b/SpaceCadetPinball/render.h index 78c85ed..f56fcc1 100644 --- a/SpaceCadetPinball/render.h +++ b/SpaceCadetPinball/render.h @@ -20,8 +20,7 @@ struct __declspec(align(4)) render_sprite_type_struct zmap_header_type* ZMap; char Unknown6_0; VisualType VisualType; - char Unknown6_2; - char Unknown6_3; + short Depth; int XPosition2; int YPosition2; int Bmp8Width2; @@ -37,6 +36,8 @@ struct __declspec(align(4)) render_sprite_type_struct visual_rect Rect; }; +static_assert(sizeof(render_sprite_type_struct) == 0x5c, "Wrong size render_sprite_type_struct"); + class render { public: diff --git a/SpaceCadetPinball/zdrv.cpp b/SpaceCadetPinball/zdrv.cpp index 01f2c4d..8abcb7c 100644 --- a/SpaceCadetPinball/zdrv.cpp +++ b/SpaceCadetPinball/zdrv.cpp @@ -1,2 +1,122 @@ #include "pch.h" #include "zdrv.h" +#include "memory.h" + + +int zdrv::create_zmap(zmap_header_type* zmap, int width, int height) +{ + int stride = pad(width); + zmap->Stride = stride; + auto bmpBuf = (unsigned short*)memory::allocate(2 * height * stride); + zmap->ZPtr1 = bmpBuf; + if (!bmpBuf) + return -1; + zmap->ZPtr2 = bmpBuf; + zmap->Width = width; + zmap->Height = height; + return 0; +} + +int zdrv::pad(int width) +{ + int result = width; + if (width & 3) + result = width - (width & 3) + 4; + return result; +} + +int zdrv::destroy_zmap(zmap_header_type* zmap) +{ + if (!zmap) + return -1; + if (zmap->ZPtr1) + memory::free(zmap->ZPtr1); + zmap->Width = 0; + zmap->Height = 0; + zmap->Stride = 0; + zmap->ZPtr1 = nullptr; + zmap->ZPtr2 = nullptr; + return 0; +} + +void zdrv::fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, __int16 fillChar) +{ + int fillCharInt = fillChar | (fillChar << 16); + auto zmapPtr = &zmap->ZPtr1[2 * (xOff + zmap->Stride * (zmap->Height - height - yOff))]; + + for (int y = height; width > 0 && y > 0; y--) + { + char widthMod2 = width & 1; + unsigned int widthDiv2 = static_cast(width) >> 1; + memset32(zmapPtr, fillCharInt, widthDiv2); + + __int16* lastShort = (__int16*)&zmapPtr[2 * widthDiv2]; + for (int i = widthMod2; i; --i) + *lastShort++ = fillChar; + + zmapPtr += zmap->Stride; + } +} + + +void zdrv::paint(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, int dstBmpYOff, zmap_header_type* dstZMap, + int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, int srcBmpXOff, int srcBmpYOff, + zmap_header_type* srcZMap, int srcZMapXOff, int srcZMapYOff) +{ + int dstHeightAbs = abs(dstBmp->Height); + int srcHeightAbs = abs(srcBmp->Height); + auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeightAbs - height - srcBmpYOff) + srcBmpXOff]; + auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeightAbs - height - dstBmpYOff) + dstBmpXOff]; + auto srcPtrZ = &srcZMap->ZPtr1[srcZMap->Stride * (srcZMap->Height - height - srcZMapYOff) + srcZMapXOff]; + auto dstPtrZ = &dstZMap->ZPtr1[dstZMap->Stride * (dstZMap->Height - height - dstZMapYOff) + dstZMapXOff]; + + for (int y = height; y > 0; y--) + { + for (int x = width; x > 0; --x) + { + if (*dstPtrZ >= *srcPtrZ) + { + *dstPtr = *srcPtr; + *dstPtrZ = *srcPtrZ; + } + ++srcPtr; + ++dstPtr; + ++srcPtrZ; + ++dstPtrZ; + } + + srcPtr += srcBmp->Stride - width; + dstPtr += dstBmp->Stride - width; + srcPtrZ += srcZMap->Stride - width; + dstPtrZ += dstZMap->Stride - width; + } +} + +void zdrv::paint_flat(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, int dstBmpYOff, + zmap_header_type* zMap, int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, int srcBmpXOff, + int srcBmpYOff, unsigned __int16 depth) +{ + int dstHeightAbs = abs(dstBmp->Height); + int srcHeightAbs = abs(srcBmp->Height); + auto dstPtr = &dstBmp->BmpBufPtr1[dstBmp->Stride * (dstHeightAbs - height - dstBmpYOff) + dstBmpXOff]; + auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeightAbs - height - srcBmpYOff) + srcBmpXOff]; + auto zPtr = &zMap->ZPtr1[zMap->Stride * (zMap->Height - height - dstZMapYOff) + dstZMapXOff]; + + for (int y = height; y > 0; y--) + { + for (int x = width; x > 0; --x) + { + if (*srcPtr && *zPtr > depth) + { + *dstPtr = *srcPtr; + } + ++srcPtr; + ++dstPtr; + ++zPtr; + } + + srcPtr += srcBmp->Stride - width; + dstPtr += dstBmp->Stride - width; + zPtr += zMap->Stride - width; + } +} diff --git a/SpaceCadetPinball/zdrv.h b/SpaceCadetPinball/zdrv.h index cd26bdf..92d23ce 100644 --- a/SpaceCadetPinball/zdrv.h +++ b/SpaceCadetPinball/zdrv.h @@ -1,4 +1,5 @@ #pragma once +#include "gdrv.h" #pragma pack(push, 1) struct __declspec(align(1)) zmap_header_type @@ -6,17 +7,26 @@ struct __declspec(align(1)) zmap_header_type __int16 Width; __int16 Height; __int16 Stride; - char* BmpBufPtr1; - char* bmpBufPtr2; - char BmpBuffer[1]; + unsigned __int16* ZPtr1; + unsigned __int16* ZPtr2; + unsigned __int16 ZBuffer[1]; }; + #pragma pack(pop) -static_assert(sizeof(zmap_header_type) == 15, "Wrong size of zmap_header_type"); +static_assert(sizeof(zmap_header_type) == 16, "Wrong size of zmap_header_type"); class zdrv { public: - + static int pad(int width); + static int create_zmap(zmap_header_type* zmap, int width, int height); + static int destroy_zmap(zmap_header_type* zmap); + static void fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, __int16 fillChar); + static void paint(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, int dstBmpYOff, + zmap_header_type* dstZMap, int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, int srcBmpXOff, + int srcBmpYOff, zmap_header_type* srcZMap, int srcZMapXOff, int srcZMapYOff); + static void paint_flat(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, int dstBmpYOff, + zmap_header_type* zMap, int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, + int srcBmpXOff, int srcBmpYOff, unsigned __int16 depth); }; -