From 49f6132d2336b0fbd01474ab8529c968d803929c Mon Sep 17 00:00:00 2001 From: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com> Date: Sun, 31 Jan 2021 17:29:53 +0300 Subject: [PATCH] Added loader for Full Tilt .dat files, v1. Works with some data hacks in lowest resolution. Seems to work ok, even though BL is still 3DPB. --- Doc/.dat file format.txt | 18 +++++++--- SpaceCadetPinball/TBall.cpp | 4 +++ SpaceCadetPinball/TFlipper.cpp | 6 ++++ SpaceCadetPinball/THole.cpp | 19 +++++----- SpaceCadetPinball/TPinballComponent.cpp | 13 +++++++ SpaceCadetPinball/TRamp.cpp | 12 ++----- SpaceCadetPinball/TTableLayer.cpp | 13 +++---- SpaceCadetPinball/TTableLayer.h | 2 +- SpaceCadetPinball/gdrv.cpp | 15 ++++++++ SpaceCadetPinball/gdrv.h | 2 ++ SpaceCadetPinball/loader.cpp | 31 +++++++++++++++++ SpaceCadetPinball/loader.h | 1 + SpaceCadetPinball/partman.cpp | 44 +++++++++++++++++------ SpaceCadetPinball/partman.h | 7 ++-- SpaceCadetPinball/pb.cpp | 9 +++-- SpaceCadetPinball/pch.h | 9 +++++ SpaceCadetPinball/zdrv.cpp | 46 +++++++++++++++++++++++++ SpaceCadetPinball/zdrv.h | 2 ++ 18 files changed, 205 insertions(+), 48 deletions(-) diff --git a/Doc/.dat file format.txt b/Doc/.dat file format.txt index 623d4b6..3253c75 100644 --- a/Doc/.dat file format.txt +++ b/Doc/.dat file format.txt @@ -39,21 +39,21 @@ Type Meaning/comments 9 String (content) 10 Array of 16bits integer values 11 Array of 32bits floating point values (collision box, ...) -12 16 bpp bitmap (Heightmap?) +12 16 bpp bitmap (zMap) //-- 8bpp bitmap data header --// -+0: Unknown (0) BYTE ++0: Resolution BYTE 0=640x480, 1=800x600, 2=1024x768, -1=Load in all resolutions +1: Width WORD +3: Height WORD +5: X position WORD +7 Y position WORD +9: Size of bitmap DWORD -+13: Unknown (1) BYTE ++13: Flags BYTE bit0=Raw bmp align; bit1=DibBitmap, raw when 0; bit2=Spliced bitmap (aka skipline), combines bmp and zMap in RLE-like way +14: Bitmap data BYTE*(DWORD@+9) -//-- 16bpp bitmap data header --// +//-- 16bpp zMap data header --// +0: Width WORD +2: Height WORD +4: Pitch/2 WORD @@ -62,6 +62,16 @@ Type Meaning/comments +12: Unknown (80) WORD +14: Bitmap data BYTE*(DWORD@+9) +//-- 16bpp zMap data header full tilt --// ++0: Resolution BYTE 0=640x480, 1=800x600, 2=1024x768, -1=Load in all resolutions ++1: Width WORD ++3: Height WORD ++5: Pitch/2 WORD ++7: Unknown (0) DWORD ++11: Unknown (0) WORD ++13: Unknown (80) WORD ++15: Bitmap data BYTE*(DWORD@+9) + //-- Pinball 3D remarkable groups --// diff --git a/SpaceCadetPinball/TBall.cpp b/SpaceCadetPinball/TBall.cpp index e6c5659..edc7c04 100644 --- a/SpaceCadetPinball/TBall.cpp +++ b/SpaceCadetPinball/TBall.cpp @@ -31,6 +31,10 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false) ListBitmap = new objlist_class(0, 4); auto groupIndex = loader::query_handle("ball"); + + /*Full tilt hack - ball is ball0*/ + if (groupIndex < 0) + groupIndex = loader::query_handle("ball0"); Offset = *loader::query_float_attribute(groupIndex, 0, 500); auto visualCount = loader::query_visual_states(groupIndex); auto index = 0; diff --git a/SpaceCadetPinball/TFlipper.cpp b/SpaceCadetPinball/TFlipper.cpp index b3c7133..97856e3 100644 --- a/SpaceCadetPinball/TFlipper.cpp +++ b/SpaceCadetPinball/TFlipper.cpp @@ -27,6 +27,12 @@ TFlipper::TFlipper(TPinballTable* table, int groupIndex) : TCollisionComponent(t auto collMult = *floatArr; auto bmpCoef2 = *floatArr2; auto bmpCoef1 = *floatArr3; + + /*Full tilt hack: different flipper speed*/ + if (bmpCoef2 > 1) + bmpCoef2 = 0.08f; + if (bmpCoef1 > 1) + bmpCoef1 = 0.04f; auto vecT2 = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 802)); auto vecT1 = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 801)); auto origin = reinterpret_cast(loader::query_float_attribute(groupIndex, 0, 800)); diff --git a/SpaceCadetPinball/THole.cpp b/SpaceCadetPinball/THole.cpp index 8c35186..40c6a49 100644 --- a/SpaceCadetPinball/THole.cpp +++ b/SpaceCadetPinball/THole.cpp @@ -19,16 +19,8 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table, MessageField = 0; Timer = 0; BallCapturedFlag = 0; - auto floatArr1 = loader::query_float_attribute(groupIndex, 0, 407); - if (floatArr1) - Unknown3 = *floatArr1; - else - Unknown3 = 0.25; - auto floatArr2 = loader::query_float_attribute(groupIndex, 0, 701); - if (floatArr2) - GravityMult = *floatArr2; - else - GravityMult = 0.5; + Unknown3 = loader::query_float_attribute(groupIndex, 0, 407, 0.25f); + GravityMult = loader::query_float_attribute(groupIndex, 0, 701, 0.2f); GravityPull = *loader::query_float_attribute(groupIndex, 0, 305); loader::query_visual(groupIndex, 0, &visual); @@ -38,7 +30,8 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table, if (Circle.RadiusSq == 0.0) Circle.RadiusSq = 0.001f; - auto tCircle = new TCircle(this, &ActiveFlag, visual.CollisionGroup, reinterpret_cast(visual.FloatArr), + auto tCircle = new TCircle(this, &ActiveFlag, visual.CollisionGroup, + reinterpret_cast(visual.FloatArr), Circle.RadiusSq); if (tCircle) { @@ -49,6 +42,10 @@ THole::THole(TPinballTable* table, int groupIndex) : TCollisionComponent(table, ZSetValue = loader::query_float_attribute(groupIndex, 0, 408)[2]; FieldFlag = static_cast(floor(*loader::query_float_attribute(groupIndex, 0, 1304))); + /*Full tilt hack - FieldFlag should be on*/ + if (!FieldFlag) + FieldFlag = 1; + Circle.RadiusSq = visual.FloatArr[2] * visual.FloatArr[2]; circle.RadiusSq = Circle.RadiusSq; circle.Center.X = Circle.Center.X; diff --git a/SpaceCadetPinball/TPinballComponent.cpp b/SpaceCadetPinball/TPinballComponent.cpp index 0b81713..816f2da 100644 --- a/SpaceCadetPinball/TPinballComponent.cpp +++ b/SpaceCadetPinball/TPinballComponent.cpp @@ -48,6 +48,19 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool zMap = ListZMap->Get(0); if (ListBitmap) { + /* Full tilt hack - spliced bitmap includes zMap + * Users access bitmap-zMap in pairs, pad zMap list with 0 for such users + * zdrv does not access zMap when drawing spliced bitmap*/ + if (!ListZMap) + { + ListZMap = new objlist_class(0, 4); + for (int index = 0; index < ListBitmap->GetCount(); index++) + { + assertm(ListBitmap->Get(index)->BitmapType == BitmapType::Spliced, "Wrong zMap padding"); + ListZMap->Add(visual.ZMap); + } + } + rectangle_type bmp1Rect{}, tmpRect{}; auto rootBmp = ListBitmap->Get(0); bmp1Rect.XPosition = rootBmp->XPosition - table->XOffset; diff --git a/SpaceCadetPinball/TRamp.cpp b/SpaceCadetPinball/TRamp.cpp index ba520ed..e51677c 100644 --- a/SpaceCadetPinball/TRamp.cpp +++ b/SpaceCadetPinball/TRamp.cpp @@ -22,16 +22,8 @@ TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table, loader::query_visual(groupIndex, 0, &visual); CollisionGroup = visual.CollisionGroup; - auto floatArr1 = loader::query_float_attribute(groupIndex, 0, 701); - if (floatArr1) - BallFieldMult = *floatArr1; - else - BallFieldMult = 0.2f; - auto floatArr2 = loader::query_float_attribute(groupIndex, 0, 1305); - if (floatArr2) - RampFlag1 = static_cast(floor(*floatArr2)); - else - RampFlag1 = 0; + BallFieldMult = loader::query_float_attribute(groupIndex, 0, 701, 0.2f); + RampFlag1 = static_cast(loader::query_float_attribute(groupIndex, 0, 1305, 0)); auto floatArr3Plane = loader::query_float_attribute(groupIndex, 0, 1300); RampPlaneCount = static_cast(floor(*floatArr3Plane)); diff --git a/SpaceCadetPinball/TTableLayer.cpp b/SpaceCadetPinball/TTableLayer.cpp index 941e0d7..70ec6fb 100644 --- a/SpaceCadetPinball/TTableLayer.cpp +++ b/SpaceCadetPinball/TTableLayer.cpp @@ -49,11 +49,12 @@ TTableLayer::TTableLayer(TPinballTable* table): TCollisionComponent(table, -1, f PinballTable->GravityAnglY = 1.570796f; } - auto table3 = PinballTable; - GraityDirX = cos(table3->GravityAnglY) * sin(table3->GravityAngleX) * table3->GravityDirVectMult; - GraityDiY = sin(table3->GravityAnglY) * sin(table3->GravityAngleX) * table3->GravityDirVectMult; + GraityDirX = cos(PinballTable->GravityAnglY) * sin(PinballTable->GravityAngleX) * PinballTable->GravityDirVectMult; + GraityDirY = sin(PinballTable->GravityAnglY) * sin(PinballTable->GravityAngleX) * PinballTable->GravityDirVectMult; auto angleMultArr = loader::query_float_attribute(groupIndex, 0, 701); - if (angleMultArr) + + /*Full tilt hack - GraityMult should be 0.2*/ + if (angleMultArr && *angleMultArr < 1) GraityMult = *angleMultArr; else GraityMult = 0.2f; @@ -109,7 +110,7 @@ int TTableLayer::FieldEffect(TBall* ball, vector_type* vecDst) { vecDst->X = GraityDirX - (0.5f - static_cast(rand()) * 0.00003051850947599719f + ball->Acceleration.X) * ball->Speed * GraityMult; - vecDst->Y = GraityDiY - ball->Acceleration.Y * ball->Speed * GraityMult; + vecDst->Y = GraityDirY - ball->Acceleration.Y * ball->Speed * GraityMult; return 1; } @@ -254,7 +255,7 @@ void TTableLayer::edges_insert_circle(circle_type* circle, TEdgeSegment* edge, f ray.Origin.Y = ray.Origin.Y - edge_manager->AdvanceY; if (maths::ray_intersect_circle(&ray, circle) < 1000000000.0) break; - + collision = false; } while (false); diff --git a/SpaceCadetPinball/TTableLayer.h b/SpaceCadetPinball/TTableLayer.h index d858ab0..52d53d8 100644 --- a/SpaceCadetPinball/TTableLayer.h +++ b/SpaceCadetPinball/TTableLayer.h @@ -26,7 +26,7 @@ public: float Unknown3F; float Unknown4F; float GraityDirX; - float GraityDiY; + float GraityDirY; int Unknown7; float GraityMult; field_effect_type Field; diff --git a/SpaceCadetPinball/gdrv.cpp b/SpaceCadetPinball/gdrv.cpp index c7a62f8..47bc550 100644 --- a/SpaceCadetPinball/gdrv.cpp +++ b/SpaceCadetPinball/gdrv.cpp @@ -185,6 +185,21 @@ int gdrv::create_raw_bitmap(gdrv_bitmap8* bmp, int width, int height, int flag) return 0; } +int gdrv::create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int size) +{ + bmp->Dib = nullptr; + bmp->Width = width; + bmp->Stride = width; + bmp->BitmapType = BitmapType::Spliced; + bmp->Height = height; + char* buf = memory::allocate(size); + bmp->BmpBufPtr1 = buf; + if (!buf) + return -1; + bmp->BmpBufPtr2 = bmp->BmpBufPtr1; + return 0; +} + int gdrv::display_palette(PALETTEENTRY* plt) { diff --git a/SpaceCadetPinball/gdrv.h b/SpaceCadetPinball/gdrv.h index edb4789..16befb5 100644 --- a/SpaceCadetPinball/gdrv.h +++ b/SpaceCadetPinball/gdrv.h @@ -5,6 +5,7 @@ enum class BitmapType : char None = 0, RawBitmap = 1, DibBitmap = 2, + Spliced = 4, }; struct gdrv_bitmap8 @@ -50,6 +51,7 @@ public: 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 create_spliced_bitmap(gdrv_bitmap8* bmp, int width, int height, int size); static int destroy_bitmap(gdrv_bitmap8* bmp); static int display_palette(PALETTEENTRY* plt); static UINT start_blit_sequence(); diff --git a/SpaceCadetPinball/loader.cpp b/SpaceCadetPinball/loader.cpp index edf6d4a..0debf70 100644 --- a/SpaceCadetPinball/loader.cpp +++ b/SpaceCadetPinball/loader.cpp @@ -242,6 +242,37 @@ float* loader::query_float_attribute(int groupIndex, int groupIndexOffset, int f return nullptr; } +float loader::query_float_attribute(int groupIndex, int groupIndexOffset, int firstValue, float defVal) +{ + if (groupIndex < 0) + { + error(0, 22); + return NAN; + } + + int stateId = state_id(groupIndex, groupIndexOffset); + if (stateId < 0) + { + error(16, 22); + return NAN; + } + + for (auto skipIndex = 0;; ++skipIndex) + { + auto floatArr = reinterpret_cast(partman::field_nth(loader_table, stateId, + datFieldTypes::FloatArray,skipIndex)); + if (!floatArr) + break; + if (static_cast<__int16>(floor(*floatArr)) == firstValue) + return floatArr[1]; + } + + if (!isnan(defVal)) + return defVal; + error(13, 22); + return NAN; +} + int loader::material(int groupIndex, visualStruct* visual) { if (groupIndex < 0) diff --git a/SpaceCadetPinball/loader.h b/SpaceCadetPinball/loader.h index 294eb49..61c6bea 100644 --- a/SpaceCadetPinball/loader.h +++ b/SpaceCadetPinball/loader.h @@ -65,6 +65,7 @@ public: static int query_visual(int groupIndex, int groupIndexOffset, visualStruct* visual); static char* query_name(int groupIndex); static float* query_float_attribute(int groupIndex, int groupIndexOffset, int firstValue); + static float query_float_attribute(int groupIndex, int groupIndexOffset, int firstValue, float defVal); static __int16* query_iattribute(int groupIndex, int firstValue, int* arraySize); static float play_sound(int soundIndex); static datFileStruct* loader_table; diff --git a/SpaceCadetPinball/partman.cpp b/SpaceCadetPinball/partman.cpp index ec4f567..7fdf44f 100644 --- a/SpaceCadetPinball/partman.cpp +++ b/SpaceCadetPinball/partman.cpp @@ -9,8 +9,7 @@ short partman::_field_size[] = 2, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 }; - -datFileStruct* partman::load_records(LPCSTR lpFileName) +datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool fullTiltMode) { _OFSTRUCT ReOpenBuff{}; datFileHeader header{}; @@ -86,10 +85,10 @@ datFileStruct* partman::load_records(LPCSTR lpFileName) if (!groupData) break; - groupData->EntryCount = entryCount; - datEntryData* entryData = groupData->Entries; + groupData->EntryCount = 0; for (auto entryIndex = 0; entryIndex < entryCount; ++entryIndex) { + auto entryData = &groupData->Entries[groupData->EntryCount]; auto entryType = static_cast(_lread_char(fileHandle)); entryData->EntryType = entryType; @@ -100,6 +99,12 @@ datFileStruct* partman::load_records(LPCSTR lpFileName) if (entryType == datFieldTypes::Bitmap8bit) { _hread(fileHandle, &bmpHeader, sizeof(dat8BitBmpHeader)); + if (bmpHeader.Resolution != resolution && bmpHeader.Resolution != -1) + { + _llseek(fileHandle, bmpHeader.Size, 1); + continue; + } + auto bmp = reinterpret_cast(memory::allocate(sizeof(gdrv_bitmap8))); entryData->Buffer = reinterpret_cast(bmp); if (!bmp) @@ -107,10 +112,15 @@ datFileStruct* partman::load_records(LPCSTR lpFileName) abort = true; break; } - if (bmpHeader.IsFlagSet(bmp8Flags::DibBitmap) - ? gdrv::create_bitmap(bmp, bmpHeader.Width, bmpHeader.Height) - : gdrv::create_raw_bitmap(bmp, bmpHeader.Width, bmpHeader.Height, - bmpHeader.IsFlagSet(bmp8Flags::RawBmpUnaligned))) + int bmpRez; + if (bmpHeader.IsFlagSet(bmp8Flags::Spliced)) + bmpRez = gdrv::create_spliced_bitmap(bmp, bmpHeader.Width, bmpHeader.Height, bmpHeader.Size); + else if (bmpHeader.IsFlagSet(bmp8Flags::DibBitmap)) + bmpRez = gdrv::create_bitmap(bmp, bmpHeader.Width, bmpHeader.Height); + else + bmpRez = gdrv::create_raw_bitmap(bmp, bmpHeader.Width, bmpHeader.Height, + bmpHeader.IsFlagSet(bmp8Flags::RawBmpUnaligned)); + if (bmpRez) { abort = true; break; @@ -121,9 +131,21 @@ datFileStruct* partman::load_records(LPCSTR lpFileName) } else if (entryType == datFieldTypes::Bitmap16bit) { + /*Full tilt has extra byte(@0:resolution) in zMap*/ + if (fullTiltMode) + { + char zMapResolution = _lread_char(fileHandle); + fieldSize--; + if (zMapResolution != resolution && zMapResolution != -1) + { + _llseek(fileHandle, fieldSize, 1); + continue; + } + } + _hread(fileHandle, &zMapHeader, sizeof(dat16BitBmpHeader)); int length = fieldSize - sizeof(dat16BitBmpHeader); - + auto zmap = reinterpret_cast(memory::allocate(sizeof(zmap_header_type) + length)); zmap->Width = zMapHeader.Width; zmap->Height = zMapHeader.Height; @@ -144,9 +166,9 @@ datFileStruct* partman::load_records(LPCSTR lpFileName) } entryData->FieldSize = fieldSize; - datFile->NumberOfGroups = groupIndex + 1; - ++entryData; + groupData->EntryCount++; } + datFile->NumberOfGroups = groupIndex + 1; } _lclose(fileHandle); diff --git a/SpaceCadetPinball/partman.h b/SpaceCadetPinball/partman.h index 006e6b8..7ce0bd8 100644 --- a/SpaceCadetPinball/partman.h +++ b/SpaceCadetPinball/partman.h @@ -28,7 +28,8 @@ enum class datFieldTypes : __int16 enum class bmp8Flags : unsigned char { RawBmpUnaligned = 1 << 0, - DibBitmap = 1 << 1, + DibBitmap = 1 << 1, + Spliced = 1 << 2, }; @@ -71,7 +72,7 @@ struct datFileStruct #pragma pack(1) struct dat8BitBmpHeader { - char Unknown1; + char Resolution; __int16 Width; __int16 Height; __int16 XPosition; @@ -108,7 +109,7 @@ static_assert(sizeof(dat16BitBmpHeader) == 14, "Wrong size of zmap_header_type") class partman { public: - static datFileStruct* load_records(LPCSTR lpFileName); + static datFileStruct* load_records(LPCSTR lpFileName, int resolution, bool fullTiltMode); static void unload_records(datFileStruct* datFile); static char* field_nth(datFileStruct* datFile, int groupIndex, datFieldTypes targetEntryType, int skipFirstN); static char* field(datFileStruct* datFile, int groupIndex, datFieldTypes entryType); diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index cb39852..1021ca4 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -37,8 +37,9 @@ int pb::init() ++memory::critical_allocation; lstrcpyA(datFileName, winmain::DatFileName); + //lstrcpyA(datFileName, "cadet.dat"); pinball::make_path_name(dataFilePath, datFileName, 300); - record_table = partman::load_records(dataFilePath); + record_table = partman::load_records(dataFilePath, 0, strstr(datFileName, "cadet")); auto useBmpFont = 0; pinball::get_rc_int(158, &useBmpFont); @@ -55,6 +56,10 @@ int pb::init() auto backgroundBmp = (gdrv_bitmap8*)partman::field_labeled(record_table, "background", datFieldTypes::Bitmap8bit); auto cameraInfo = (float*)partman::field_labeled(record_table, "camera_info", datFieldTypes::FloatArray); + /*Full tilt hack - table size is hardcoded*/ + if (!tableSize) + tableSize = new short[2]{600, 800}; + if (cameraInfo) { memcpy(&projMat, cameraInfo, sizeof(float) * 4 * 3); @@ -545,7 +550,7 @@ void pb::end_game() scores[j] = scores[i]; scores[i] = score; - int index = scoreIndex[j]; + int index = scoreIndex[j]; scoreIndex[j] = scoreIndex[i]; scoreIndex[i] = index; } diff --git a/SpaceCadetPinball/pch.h b/SpaceCadetPinball/pch.h index 7c74e54..dcbdb38 100644 --- a/SpaceCadetPinball/pch.h +++ b/SpaceCadetPinball/pch.h @@ -25,4 +25,13 @@ /*Sound uses PlaySound*/ #undef PlaySound + +inline size_t pgm_save(int width, int height, char* data, FILE* outfile) +{ + size_t n = 0; + n += fprintf(outfile, "P5\n%d %d\n%d\n", width, height, 0xFF); + n += fwrite(data, 1, width * height, outfile); + return n; +} + #endif //PCH_H diff --git a/SpaceCadetPinball/zdrv.cpp b/SpaceCadetPinball/zdrv.cpp index ae93468..6ab815b 100644 --- a/SpaceCadetPinball/zdrv.cpp +++ b/SpaceCadetPinball/zdrv.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "zdrv.h" #include "memory.h" +#include "pb.h" int zdrv::create_zmap(zmap_header_type* zmap, int width, int height) @@ -59,6 +60,13 @@ void zdrv::paint(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOff, in int dstZMapXOff, int dstZMapYOff, gdrv_bitmap8* srcBmp, int srcBmpXOff, int srcBmpYOff, zmap_header_type* srcZMap, int srcZMapXOff, int srcZMapYOff) { + if (srcBmp->BitmapType == BitmapType::Spliced) + { + /*Spliced bitmap is also a zMap, how convenient*/ + paint_spliced_bmp(srcBmp->XPosition, srcBmp->YPosition, dstBmp, dstZMap, srcBmp); + return; + } + int dstHeightAbs = abs(dstBmp->Height); int srcHeightAbs = abs(srcBmp->Height); auto srcPtr = &srcBmp->BmpBufPtr1[srcBmp->Stride * (srcHeightAbs - height - srcBmpYOff) + srcBmpXOff]; @@ -116,3 +124,41 @@ void zdrv::paint_flat(int width, int height, gdrv_bitmap8* dstBmp, int dstBmpXOf zPtr += zMap->Stride - width; } } + +void zdrv::paint_spliced_bmp(int xPos, int yPos, gdrv_bitmap8* dstBmp, zmap_header_type* dstZmap, gdrv_bitmap8* srcBmp) +{ + assertm(srcBmp->BitmapType == BitmapType::Spliced, "Wrong bmp type"); + int xOffset = xPos - pb::MainTable->XOffset; + int yOffset = dstBmp->Height - srcBmp->Height - (yPos - pb::MainTable->YOffset); + if (yOffset < 0) + return; + + auto bmpDstPtr = &dstBmp->BmpBufPtr2[xOffset + yOffset * dstBmp->Stride]; + auto zMapDstPtr = &dstZmap->ZPtr2[xOffset + yOffset * dstZmap->Stride]; + auto bmpSrcPtr = reinterpret_cast(srcBmp->BmpBufPtr2); + + while (true) + { + auto stride = static_cast(*bmpSrcPtr++); + if (stride < 0) + break; + + /*Stride is in terms of dst stride, hardcoded to match vScreen width in current resolution*/ + zMapDstPtr += stride; + bmpDstPtr += stride; + for (auto count = *bmpSrcPtr++; count; count--) + { + auto depth = *bmpSrcPtr++; + auto charPtr = reinterpret_cast(&bmpSrcPtr); + if (*zMapDstPtr >= depth) + { + *bmpDstPtr = **charPtr; + *zMapDstPtr = depth; + } + + (*charPtr)++; + ++zMapDstPtr; + ++bmpDstPtr; + } + } +} diff --git a/SpaceCadetPinball/zdrv.h b/SpaceCadetPinball/zdrv.h index 579e296..b9a544e 100644 --- a/SpaceCadetPinball/zdrv.h +++ b/SpaceCadetPinball/zdrv.h @@ -24,4 +24,6 @@ public: 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); + static void paint_spliced_bmp(int xPos, int yPos, gdrv_bitmap8* dstBmp, zmap_header_type* dstZmap, + gdrv_bitmap8* srcBmp); };