diff --git a/Doc/FuncStats.xlsx b/Doc/FuncStats.xlsx index ea9f0bd..2337dfb 100644 Binary files a/Doc/FuncStats.xlsx and b/Doc/FuncStats.xlsx differ diff --git a/SpaceCadetPinball/SpaceCadetPinball.cpp b/SpaceCadetPinball/SpaceCadetPinball.cpp index e3107f1..a31a780 100644 --- a/SpaceCadetPinball/SpaceCadetPinball.cpp +++ b/SpaceCadetPinball/SpaceCadetPinball.cpp @@ -61,7 +61,7 @@ int main() visualKickerStruct kicker1{}; loader::kicker(509, &kicker1); - auto score1 = score::create("score1", 117); + auto score1 = score::create("score1", nullptr); auto pinballTable = new TPinballTable(); //pinballTable->find_component(1); diff --git a/SpaceCadetPinball/TPinballComponent.cpp b/SpaceCadetPinball/TPinballComponent.cpp index cc777b2..26447d9 100644 --- a/SpaceCadetPinball/TPinballComponent.cpp +++ b/SpaceCadetPinball/TPinballComponent.cpp @@ -47,7 +47,7 @@ TPinballComponent::TPinballComponent(TPinballTable* table, int groupIndex, bool zMap = static_cast(ListZMap->Get(0)); if (ListBitmap) { - visual_rect bmp1Rect{}, tmpRect{}; + rectangle_type bmp1Rect{}, tmpRect{}; auto rootBmp = static_cast(ListBitmap->Get(0)); bmp1Rect.XPosition = rootBmp->XPosition - table->XOffset; bmp1Rect.YPosition = rootBmp->YPosition - table->YOffset; diff --git a/SpaceCadetPinball/TPinballTable.cpp b/SpaceCadetPinball/TPinballTable.cpp index 733844b..8a87c05 100644 --- a/SpaceCadetPinball/TPinballTable.cpp +++ b/SpaceCadetPinball/TPinballTable.cpp @@ -58,7 +58,7 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false) TLightGroup* lightGroupObj = new TLightGroup(this, 0); this->LightGroup = lightGroupObj; - auto score1 = score::create("score1", pinball::render_background_bitmap); + auto score1 = score::create("score1", render::background_bitmap); this->Score1 = score1; this->Score2 = score1; int scoreIndex = 1; @@ -71,8 +71,8 @@ TPinballTable::TPinballTable(): TPinballComponent(nullptr, -1, false) while (scoreIndex < 4); this->UnknownP45 = 0; this->UnknownP73 = 3; - this->ScoreBallcount = (int*)score::create("ballcount1", pinball::render_background_bitmap); - this->ScorePlayerNumber1 = (int*)score::create("player_number1", pinball::render_background_bitmap); + this->ScoreBallcount = (int*)score::create("ballcount1", render::background_bitmap); + this->ScorePlayerNumber1 = (int*)score::create("player_number1", render::background_bitmap); int groupIndexObjects = loader::query_handle("table_objects"); short* shortArr = loader::query_iattribute(groupIndexObjects, 1025, &shortArrLength); diff --git a/SpaceCadetPinball/maths.cpp b/SpaceCadetPinball/maths.cpp index 7171477..8541f1b 100644 --- a/SpaceCadetPinball/maths.cpp +++ b/SpaceCadetPinball/maths.cpp @@ -2,35 +2,117 @@ #include "maths.h" -void maths::enclosing_box(visual_rect* rect1, visual_rect* rect2, visual_rect* dstRect) +void maths::enclosing_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect) { int xPos1 = rect1->XPosition; - int yPos1 = rect1->YPosition; - int width1 = rect1->Width; - int height1 = rect1->Height; - int xPos2 = rect2->XPosition; - bool rect2XPosLessRect1 = rect2->XPosition < rect1->XPosition; - int yPos2 = rect2->YPosition; - int width2 = rect2->Width; - int height2 = rect2->Height; - int xPos2_2 = rect2->XPosition; - if (rect2XPosLessRect1) - { - width1 += xPos1 - xPos2; - xPos1 = xPos2; - } - if (yPos2 < yPos1) - { - height1 += yPos1 - yPos2; - yPos1 = yPos2; - } - if (width2 + xPos2 > xPos1 + width1) - width1 = xPos2_2 + width2 - xPos1; - int height1_2 = height1; - if (height2 + yPos2 > height1 + yPos1) - height1_2 = yPos2 + height2 - yPos1; - dstRect->YPosition = yPos1; - dstRect->Height = height1_2; - dstRect->XPosition = xPos1; - dstRect->Width = width1; -} \ No newline at end of file + int yPos1 = rect1->YPosition; + int width1 = rect1->Width; + int height1 = rect1->Height; + int xPos2 = rect2->XPosition; + bool rect2XPosLessRect1 = rect2->XPosition < rect1->XPosition; + int yPos2 = rect2->YPosition; + int width2 = rect2->Width; + int height2 = rect2->Height; + int xPos2_2 = rect2->XPosition; + if (rect2XPosLessRect1) + { + width1 += xPos1 - xPos2; + xPos1 = xPos2; + } + if (yPos2 < yPos1) + { + height1 += yPos1 - yPos2; + yPos1 = yPos2; + } + if (width2 + xPos2 > xPos1 + width1) + width1 = xPos2_2 + width2 - xPos1; + int height1_2 = height1; + if (height2 + yPos2 > height1 + yPos1) + height1_2 = yPos2 + height2 - yPos1; + dstRect->YPosition = yPos1; + dstRect->Height = height1_2; + dstRect->XPosition = xPos1; + dstRect->Width = width1; +} + + +int maths::rectangle_clip(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect) +{ + int xPos1 = rect1->XPosition; + int yPos1 = rect1->YPosition; + int height1 = rect1->Height; + int xRight2 = rect2->XPosition + rect2->Width; + int width1 = rect1->Width; + int yRight2 = rect2->YPosition + rect2->Height; + if (xPos1 + width1 < rect2->XPosition) + return 0; + if (xPos1 >= xRight2) + return 0; + int yPos2 = yPos1; + if (yPos1 + height1 < rect2->YPosition || yPos1 >= yRight2) + return 0; + if (xPos1 < rect2->XPosition) + { + width1 += xPos1 - rect2->XPosition; + xPos1 = rect2->XPosition; + } + if (xPos1 + width1 > xRight2) + width1 = xRight2 - xPos1; + int height2 = height1; + if (yPos1 < rect2->YPosition) + { + height2 = yPos1 - rect2->YPosition + height1; + yPos2 = rect2->YPosition; + } + if (height2 + yPos2 > yRight2) + height2 = yRight2 - yPos2; + if (!width1 || !height2) + return 0; + if (dstRect) + { + dstRect->XPosition = xPos1; + dstRect->YPosition = yPos2; + dstRect->Width = width1; + dstRect->Height = height2; + } + return 1; +} + + +int maths::overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect) +{ + int v3; // esi + int v4; // edi + int v5; // esi + int v6; // esi + int v7; // edi + + if (rect1->XPosition >= rect2->XPosition) + { + dstRect->XPosition = rect2->XPosition; + v3 = rect1->Width - rect2->XPosition; + v4 = rect1->XPosition; + } + else + { + dstRect->XPosition = rect1->XPosition; + v3 = rect2->Width - rect1->XPosition; + v4 = rect2->XPosition; + } + dstRect->Width = v3 + v4 + 1; + v5 = rect1->YPosition; + if (v5 >= rect2->YPosition) + { + dstRect->YPosition = rect2->YPosition; + v6 = rect1->Height - rect2->YPosition; + v7 = rect1->YPosition; + } + else + { + dstRect->YPosition = v5; + v6 = rect2->Height - rect1->YPosition; + v7 = rect2->YPosition; + } + dstRect->Height = v6 + v7 + 1; + return dstRect->Width <= rect2->Width + rect1->Width && dstRect->Height <= rect2->Height + rect1->Height; +} diff --git a/SpaceCadetPinball/maths.h b/SpaceCadetPinball/maths.h index 18e6c26..c3433e9 100644 --- a/SpaceCadetPinball/maths.h +++ b/SpaceCadetPinball/maths.h @@ -1,7 +1,7 @@ #pragma once -struct __declspec(align(4)) visual_rect +struct __declspec(align(4)) rectangle_type { int XPosition; int YPosition; @@ -12,7 +12,7 @@ struct __declspec(align(4)) visual_rect class maths { public: - static void enclosing_box(visual_rect* rect1, visual_rect* rect2, visual_rect* dstRect); - + static void enclosing_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect); + static int rectangle_clip(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect); + static int overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect); }; - diff --git a/SpaceCadetPinball/pinball.cpp b/SpaceCadetPinball/pinball.cpp index edd7b39..d3a35e7 100644 --- a/SpaceCadetPinball/pinball.cpp +++ b/SpaceCadetPinball/pinball.cpp @@ -4,7 +4,6 @@ int pinball::quickFlag = 0; -int pinball::render_background_bitmap = 0; TTextBox* pinball::InfoTextBox; TTextBox* pinball::MissTextBox; char pinball::getRcBuffer[6 * 256]; diff --git a/SpaceCadetPinball/pinball.h b/SpaceCadetPinball/pinball.h index f9571c2..d7cf97a 100644 --- a/SpaceCadetPinball/pinball.h +++ b/SpaceCadetPinball/pinball.h @@ -5,7 +5,6 @@ class pinball { public: static int quickFlag; - static int render_background_bitmap; static TTextBox* InfoTextBox; static TTextBox* MissTextBox; static HINSTANCE hinst; diff --git a/SpaceCadetPinball/render.cpp b/SpaceCadetPinball/render.cpp index 68548d2..7884145 100644 --- a/SpaceCadetPinball/render.cpp +++ b/SpaceCadetPinball/render.cpp @@ -1,75 +1,256 @@ #include "pch.h" #include "render.h" - #include "memory.h" int render::blit = 0; int render::many_dirty, render::many_sprites, render::many_balls; -render_sprite_type_struct **render::dirty_list = new render_sprite_type_struct*[1000], **render::sprite_list = new - render_sprite_type_struct* [1000], **render::ball_list = new render_sprite_type_struct* [ - 1000]; +render_sprite_type_struct **render::dirty_list, **render::sprite_list, **render::ball_list; zmap_header_type* render::background_zmap; -int render::zmap_offset, render::zmap_offsetY; +int render::zmap_offset, render::zmap_offsetY, render::offset_x, render::offset_y; +float render::zscaler, render::zmin, render::zmax; +rectangle_type render::vscreen_rect; +gdrv_bitmap8 render::vscreen, *render::background_bitmap, render::ball_bitmap[20]; +zmap_header_type render::zscreen; + +void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height) +{ + ++memory::critical_allocation; + zscaler = zScaler; + zmin = zMin; + zmax = 4294967300.0f / zScaler + zMin; + sprite_list = (render_sprite_type_struct**)memory::allocate(0xFA0u); + dirty_list = (render_sprite_type_struct**)memory::allocate(0xFA0u); + ball_list = (render_sprite_type_struct**)memory::allocate(0x50u); + gdrv::create_bitmap(&vscreen, width, height); + zdrv::create_zmap(&zscreen, width, height); + zdrv::fill(&zscreen, zscreen.Width, zscreen.Height, 0, 0, 0xFFFF); + vscreen_rect.YPosition = 0; + vscreen_rect.XPosition = 0; + vscreen_rect.Width = width; + vscreen_rect.Height = height; + vscreen.YPosition = 0; + vscreen.XPosition = 0; + gdrv_bitmap8* ballBmp = ball_bitmap; + while (ballBmp <= &ball_bitmap[20]) + { + gdrv::create_raw_bitmap(ballBmp, 64, 64, 1); + ++ballBmp; + } + background_bitmap = bmp; + if (bmp) + gdrv::copy_bitmap(&vscreen, width, height, 0, 0, bmp, 0, 0); + else + gdrv::fill_bitmap(&vscreen, vscreen.Width, vscreen.Height, 0, 0, 0); + --memory::critical_allocation; +} + +void render::uninit() +{ + gdrv::destroy_bitmap(&vscreen); + zdrv::destroy_zmap(&zscreen); + for (int i = 0; i < many_sprites; ++i) + remove_sprite(sprite_list[i]); + for (int j = 0; j < many_balls; ++j) + remove_ball(ball_list[j]); + memory::free(ball_list); + memory::free(dirty_list); + memory::free(sprite_list); + many_sprites = 0; + many_dirty = 0; + many_balls = 0; +} void render::update() { + rectangle_type overlapRect{}; + + auto dirtyPtr = dirty_list; + for (int index = 0; index < many_dirty; ++dirtyPtr, ++index) + { + auto curSprite = *dirtyPtr; + if ((*dirtyPtr)->VisualType != VisualType::None) + { + if ((*dirtyPtr)->VisualType == VisualType::Sprite) + { + if (curSprite->BmpRectCopy.Width > 0) + maths::enclosing_box(&curSprite->BmpRectCopy, &curSprite->BmpRect, &curSprite->DirtyRect); + + if (!maths::rectangle_clip(&curSprite->DirtyRect, &vscreen_rect, &curSprite->DirtyRect)) + { + curSprite->DirtyRect.Width = -1; + continue; + } + + auto yPos = curSprite->DirtyRect.YPosition; + auto width = curSprite->DirtyRect.Width; + auto xPos = curSprite->DirtyRect.XPosition; + auto height = curSprite->DirtyRect.Height; + zdrv::fill(&zscreen, width, height, xPos, yPos, 0xFFFF); + if (background_bitmap) + gdrv::copy_bitmap(&vscreen, width, height, xPos, yPos, background_bitmap, xPos, yPos); + else + gdrv::fill_bitmap(&vscreen, width, height, xPos, yPos, 0); + } + } + else + { + if (!maths::rectangle_clip(&curSprite->BmpRect, &vscreen_rect, &curSprite->DirtyRect)) + { + curSprite->DirtyRect.Width = -1; + continue; + } + if (!curSprite->Bmp) + { + auto yPos = curSprite->DirtyRect.YPosition; + auto width = curSprite->DirtyRect.Width; + auto xPos = curSprite->DirtyRect.XPosition; + auto height = curSprite->DirtyRect.Height; + zdrv::fill(&zscreen, width, height, xPos, yPos, 0xFFFF); + if (background_bitmap) + gdrv::copy_bitmap(&vscreen, width, height, xPos, yPos, background_bitmap, xPos, yPos); + else + gdrv::fill_bitmap(&vscreen, width, height, xPos, yPos, 0); + } + } + } + + dirtyPtr = dirty_list; + for (int index = 0; index < many_dirty; ++index) + { + auto sprite = *dirtyPtr; + if ((*dirtyPtr)->DirtyRect.Width > 0 && (sprite->VisualType == VisualType::None || sprite->VisualType == + VisualType::Sprite)) + repaint(*dirtyPtr); + ++dirtyPtr; + } + + paint_balls(); + if (blit) + { + gdrv::start_blit_sequence(); + + auto xPos = vscreen.XPosition + offset_x; + auto yPos = vscreen.YPosition + offset_y; + dirtyPtr = dirty_list; + for (int index = 0; index < many_dirty; ++dirtyPtr, ++index) + { + auto sprite = *dirtyPtr; + auto dirtyRect = &(*dirtyPtr)->DirtyRect; + auto width2 = (*dirtyPtr)->DirtyRect.Width; + if (width2 > 0) + gdrv::blit_sequence( + &vscreen, + dirtyRect->XPosition, + dirtyRect->YPosition, + dirtyRect->XPosition + xPos, + dirtyRect->YPosition + yPos, + width2, + dirtyRect->Height); + + auto rect = &sprite->BmpRectCopy; + rect->XPosition = dirtyRect->XPosition; + rect->YPosition = dirtyRect->YPosition; + rect->Width = dirtyRect->Width; + rect->Height = dirtyRect->Height; + + if (sprite->Unknown6_0 != 0) + remove_sprite(sprite); + } + + dirtyPtr = ball_list; + for (int index = 0; index < many_balls; ++dirtyPtr, ++index) + { + auto rectCopy = &(*dirtyPtr)->BmpRectCopy; + auto dirtyRect = &(*dirtyPtr)->DirtyRect; + if (maths::overlapping_box(dirtyRect, rectCopy, &overlapRect) && dirtyRect->Width > 0) + { + if (overlapRect.Width > 0) + gdrv::blit_sequence( + &vscreen, + overlapRect.XPosition, + overlapRect.YPosition, + overlapRect.XPosition + xPos, + overlapRect.YPosition + yPos, + overlapRect.Width, + overlapRect.Height); + } + else + { + if (dirtyRect->Width > 0) + gdrv::blit_sequence( + &vscreen, + dirtyRect->XPosition, + dirtyRect->YPosition, + dirtyRect->XPosition + xPos, + dirtyRect->YPosition + yPos, + dirtyRect->Width, + dirtyRect->Height); + if (rectCopy->Width > 0) + gdrv::blit_sequence( + &vscreen, + rectCopy->XPosition, + rectCopy->YPosition, + rectCopy->XPosition + xPos, + rectCopy->YPosition + yPos, + rectCopy->Width, + rectCopy->Height); + } + } + + gdrv::end_blit_sequence(); + } + + many_dirty = 0; + unpaint_balls(); } void render::paint() { - /*render_paint_balls(); - gdrv_blat((int)&vscreen, xDest, yDest); - render_unpaint_balls();*/ + paint_balls(); + gdrv::blat(&vscreen, vscreen.XPosition, vscreen.YPosition); + unpaint_balls(); } - -int render::sprite_modified(render_sprite_type_struct* sprite) +void render::sprite_modified(render_sprite_type_struct* sprite) { - int result = 0; // eax - - if (sprite->VisualType == VisualType::Ball) - return result; - result = many_dirty; - if (many_dirty < 999) + if (sprite->VisualType != VisualType::Ball && many_dirty < 999) dirty_list[many_dirty++] = sprite; - return result; } -render_sprite_type_struct* render::create_sprite(VisualType visualType, gdrv_bitmap8* rootBmp8, zmap_header_type* zMap, - int xPosition, int yPosition, visual_rect* rect) +render_sprite_type_struct* render::create_sprite(VisualType visualType, gdrv_bitmap8* bmp, zmap_header_type* zMap, + int xPosition, int yPosition, rectangle_type* rect) { - render_sprite_type_struct* sprite = (render_sprite_type_struct*)memory::allocate(0x5Cu); - render_sprite_type_struct* result = nullptr; + auto sprite = (render_sprite_type_struct*)memory::allocate(sizeof(render_sprite_type_struct)); if (!sprite) - return result; - sprite->YPosition = yPosition; - sprite->RootBmp8 = rootBmp8; - sprite->XPosition = xPosition; + return nullptr; + sprite->BmpRect.YPosition = yPosition; + sprite->BmpRect.XPosition = xPosition; + sprite->Bmp = bmp; sprite->VisualType = visualType; sprite->Unknown6_0 = 0; - sprite->Unknown17 = 0; - sprite->Unknown18 = 0; + sprite->SpriteArray = nullptr; + sprite->SpriteCount = 0; if (rect) { - sprite->Rect = *rect; + sprite->BoundingRect = *rect; } else { - sprite->Rect.Width = -1; - sprite->Rect.Height = -1; - sprite->Rect.XPosition = 0; - sprite->Rect.YPosition = 0; + sprite->BoundingRect.Width = -1; + sprite->BoundingRect.Height = -1; + sprite->BoundingRect.XPosition = 0; + sprite->BoundingRect.YPosition = 0; } - if (rootBmp8) + if (bmp) { - sprite->Bmp8Width = rootBmp8->Width; - sprite->Bmp8Height = rootBmp8->Height; + sprite->BmpRect.Width = bmp->Width; + sprite->BmpRect.Height = bmp->Height; } else { - sprite->Bmp8Width = 0; - sprite->Bmp8Height = 0; + sprite->BmpRect.Width = 0; + sprite->BmpRect.Height = 0; } sprite->ZMap = zMap; sprite->ZMapOffestX = 0; @@ -80,10 +261,7 @@ render_sprite_type_struct* render::create_sprite(VisualType visualType, gdrv_bit sprite->ZMapOffestY = xPosition - zmap_offset; sprite->ZMapOffestX = yPosition - zmap_offsetY; } - sprite->XPosition2 = sprite->XPosition; - sprite->YPosition2 = sprite->YPosition; - sprite->Bmp8Width2 = sprite->Bmp8Width; - sprite->Bmp8Height2 = sprite->Bmp8Height; + sprite->BmpRectCopy = sprite->BmpRect; if (visualType == VisualType::Ball) { ball_list[many_balls++] = sprite; @@ -93,6 +271,255 @@ render_sprite_type_struct* render::create_sprite(VisualType visualType, gdrv_bit sprite_list[many_sprites++] = sprite; sprite_modified(sprite); } - result = sprite; - return result; + return sprite; +} + + +void render::remove_sprite(render_sprite_type_struct* sprite) +{ + int spriteCount = many_sprites; + int index = 0; + if (many_sprites > 0) + { + while (sprite_list[index] != sprite) + { + if (++index >= many_sprites) + return; + } + while (index < spriteCount) + { + sprite_list[index] = sprite_list[index + 1]; + spriteCount = many_sprites; + ++index; + } + many_sprites = spriteCount - 1; + if (sprite->SpriteArray) + memory::free(sprite->SpriteArray); + memory::free(sprite); + } +} + +void render::remove_ball(struct render_sprite_type_struct* ball) +{ + int ballCount = many_balls; + int index = 0; + if (many_balls > 0) + { + while (ball_list[index] != ball) + { + if (++index >= many_balls) + return; + } + while (index < ballCount) + { + ball_list[index] = ball_list[index + 1]; + ballCount = many_balls; + ++index; + } + many_balls = ballCount - 1; + memory::free(ball); + } +} + +void render::sprite_set(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp, zmap_header_type* zMap, int xPos, + int yPos) +{ + if (sprite) + { + sprite->BmpRect.XPosition = xPos; + sprite->BmpRect.YPosition = yPos; + sprite->Bmp = bmp; + if (bmp) + { + sprite->BmpRect.Width = bmp->Width; + sprite->BmpRect.Height = bmp->Height; + } + sprite->ZMap = zMap; + sprite_modified(sprite); + } +} + +void render::sprite_set_bitmap(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp) +{ + if (sprite && sprite->Bmp != bmp) + { + sprite->Bmp = bmp; + if (bmp) + { + sprite->BmpRect.Width = bmp->Width; + sprite->BmpRect.Height = bmp->Height; + } + sprite_modified(sprite); + } +} + +void render::set_background_zmap(struct zmap_header_type* zMap, int offsetX, int offsetY) +{ + background_zmap = zMap; + zmap_offset = offsetX; + zmap_offsetY = offsetY; +} + +void render::ball_set(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp, float depth, int xPos, int yPos) +{ + if (sprite) + { + sprite->Bmp = bmp; + if (bmp) + { + sprite->BmpRect.XPosition = xPos; + sprite->BmpRect.YPosition = yPos; + sprite->BmpRect.Width = bmp->Width; + sprite->BmpRect.Height = bmp->Height; + } + if (depth >= zmin) + { + float depth2 = (depth - zmin) * zscaler; + if (depth2 <= zmax) + sprite->Depth = static_cast(depth2); + else + sprite->Depth = -1; + } + else + { + sprite->Depth = 0; + } + } +} + +void render::repaint(struct render_sprite_type_struct* sprite) +{ + rectangle_type clipRect{}; + if (!sprite->SpriteArray) + return; + for (int index = 0; index < sprite->SpriteCount; index++) + { + render_sprite_type_struct* curSprite = sprite->SpriteArray[index]; + if (!curSprite->Unknown6_0 && curSprite->Bmp) + { + if (maths::rectangle_clip(&curSprite->BmpRect, &sprite->DirtyRect, &clipRect)) + zdrv::paint( + clipRect.Width, + clipRect.Height, + &vscreen, + clipRect.XPosition, + clipRect.YPosition, + &zscreen, + clipRect.XPosition, + clipRect.YPosition, + curSprite->Bmp, + clipRect.XPosition - curSprite->BmpRect.XPosition, + clipRect.YPosition - curSprite->BmpRect.YPosition, + curSprite->ZMap, + clipRect.XPosition + curSprite->ZMapOffestY - curSprite->BmpRect.XPosition, + clipRect.YPosition + curSprite->ZMapOffestX - curSprite->BmpRect.YPosition); + } + } +} + + +void render::paint_balls() +{ + int ballCount = many_balls; + if (many_balls > 1) + { + for (int index = 0; index < ballCount; index++) + { + for (int i = index; i < ballCount / 2; ++i) + { + auto curBall = ball_list[i]; + auto firstBallPtr = &ball_list[index]; + if ((*firstBallPtr)->Depth > curBall->Depth) + { + auto firstBall = *firstBallPtr; + *firstBallPtr = curBall; + ball_list[i] = firstBall; + } + } + } + } + + auto ballPtr = ball_list; + auto ballBmpPtr = ball_bitmap; + for (int index2 = 0; index2 < many_balls; ++index2) + { + struct render_sprite_type_struct* sprite = *ballPtr; + rectangle_type* rect2 = &(*ballPtr)->DirtyRect; + if ((*ballPtr)->Bmp && maths::rectangle_clip(&sprite->BmpRect, &vscreen_rect, &(*ballPtr)->DirtyRect)) + { + int xPos = rect2->XPosition; + int yPos = rect2->YPosition; + gdrv::copy_bitmap(ballBmpPtr, rect2->Width, rect2->Height, 0, 0, &vscreen, xPos, yPos); + zdrv::paint_flat( + rect2->Width, + rect2->Height, + &vscreen, + xPos, + yPos, + &zscreen, + xPos, + yPos, + sprite->Bmp, + xPos - sprite->BmpRect.XPosition, + yPos - sprite->BmpRect.YPosition, + sprite->Depth); + } + else + { + rect2->Width = -1; + } + + ++ballBmpPtr; + ++ballPtr; + } +} + +void render::unpaint_balls() +{ + auto ballPtr = &ball_list[many_balls - 1]; + if (many_balls - 1 >= 0) + { + gdrv_bitmap8* bitmapPtr = &ball_bitmap[many_balls - 1]; + for (int index = many_balls; index > 0; index--) + { + struct render_sprite_type_struct* curBall = *ballPtr; + rectangle_type* rect2 = &(*ballPtr)->DirtyRect; + int width = (*ballPtr)->DirtyRect.Width; + if (width > 0) + gdrv::copy_bitmap( + &vscreen, + width, + (*ballPtr)->DirtyRect.Height, + (*ballPtr)->DirtyRect.XPosition, + (*ballPtr)->DirtyRect.YPosition, + bitmapPtr, + 0, + 0); + + rectangle_type* rectCopy = &curBall->BmpRectCopy; + rectCopy->XPosition = rect2->XPosition; + rectCopy->YPosition = rect2->YPosition; + rectCopy->Width = rect2->Width; + rectCopy->Height = rect2->Height; + + --ballPtr; + --bitmapPtr; + } + } +} + +void render::shift(int offsetX, int offsetY, int xSrc, int ySrc, int DestWidth, int DestHeight) +{ + offset_x += offsetX; + offset_y += offsetY; + paint_balls(); + gdrv::blit( + &vscreen, + xSrc, + ySrc, + xSrc + offset_x + vscreen.XPosition, + ySrc + offset_y + vscreen.YPosition, + DestWidth, + DestHeight); + unpaint_balls(); } diff --git a/SpaceCadetPinball/render.h b/SpaceCadetPinball/render.h index f56fcc1..b6a4fd3 100644 --- a/SpaceCadetPinball/render.h +++ b/SpaceCadetPinball/render.h @@ -12,30 +12,22 @@ enum class VisualType : char struct __declspec(align(4)) render_sprite_type_struct { - int XPosition; - int YPosition; - int Bmp8Width; - int Bmp8Height; - gdrv_bitmap8* RootBmp8; + rectangle_type BmpRect; + gdrv_bitmap8* Bmp; zmap_header_type* ZMap; char Unknown6_0; VisualType VisualType; - short Depth; - int XPosition2; - int YPosition2; - int Bmp8Width2; - int Bmp8Height2; + __int16 Depth; + rectangle_type BmpRectCopy; int ZMapOffestY; int ZMapOffestX; - int Unknown13; - int Unknown14; - int Unknown15; - int Unknown16; - int Unknown17; - int Unknown18; - visual_rect Rect; + rectangle_type DirtyRect; + render_sprite_type_struct** SpriteArray; + int SpriteCount; + rectangle_type BoundingRect; }; + static_assert(sizeof(render_sprite_type_struct) == 0x5c, "Wrong size render_sprite_type_struct"); class render @@ -45,12 +37,29 @@ public: static int many_dirty, many_sprites, many_balls; static render_sprite_type_struct **dirty_list, **sprite_list, **ball_list; static zmap_header_type* background_zmap; - static int zmap_offset, zmap_offsetY; + static int zmap_offset, zmap_offsetY, offset_x, offset_y; + static float zscaler, zmin, zmax; + static rectangle_type vscreen_rect; + static gdrv_bitmap8 vscreen, *background_bitmap, ball_bitmap[20]; + static zmap_header_type zscreen; + static void init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height); + static void uninit(); static void update(); static void paint(); - static int sprite_modified(render_sprite_type_struct* sprite); - static render_sprite_type_struct* create_sprite(VisualType visualType, gdrv_bitmap8* rootBmp8, + static void sprite_modified(render_sprite_type_struct* sprite); + static render_sprite_type_struct* create_sprite(VisualType visualType, gdrv_bitmap8* bmp, zmap_header_type* zMap, - int xPosition, int yPosition, visual_rect* rect); + int xPosition, int yPosition, rectangle_type* rect); + static void remove_sprite(render_sprite_type_struct* sprite); + static void remove_ball(struct render_sprite_type_struct* ball); + static void sprite_set(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp, zmap_header_type* zMap, int xPos, + int yPos); + static void sprite_set_bitmap(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp); + static void set_background_zmap(struct zmap_header_type* zMap, int offsetX, int offsetY); + static void ball_set(render_sprite_type_struct* sprite, gdrv_bitmap8* bmp, float depth, int xPos, int yPos); + static void repaint(struct render_sprite_type_struct* sprite); + static void paint_balls(); + static void unpaint_balls(); + static void shift(int offsetX, int offsetY, int xSrc, int ySrc, int DestWidth, int DestHeight); }; diff --git a/SpaceCadetPinball/score.cpp b/SpaceCadetPinball/score.cpp index 101ad74..a987dc8 100644 --- a/SpaceCadetPinball/score.cpp +++ b/SpaceCadetPinball/score.cpp @@ -10,13 +10,13 @@ int score::init() return 1; } -scoreStruct* score::create(LPCSTR fieldName, int renderBgBmp) +scoreStruct* score::create(LPCSTR fieldName, gdrv_bitmap8* renderBgBmp) { scoreStruct* score = (scoreStruct*)memory::allocate(sizeof(scoreStruct)); if (!score) return nullptr; score->Unknown1 = -9999; - score->RenderBgBmp = renderBgBmp; + score->BackgroundBmp = renderBgBmp; __int16* shortArr = (__int16*)partman::field_labeled(loader::loader_table, fieldName, datFieldTypes::ShortArray); if (!shortArr) { diff --git a/SpaceCadetPinball/score.h b/SpaceCadetPinball/score.h index 0bbc71c..215e37b 100644 --- a/SpaceCadetPinball/score.h +++ b/SpaceCadetPinball/score.h @@ -1,10 +1,11 @@ #pragma once +#include "gdrv.h" struct scoreStruct { int Unknown1; int Unknown2; - int RenderBgBmp; + gdrv_bitmap8* BackgroundBmp; int Short1; int Short2; int Short3; @@ -25,6 +26,6 @@ class score { public: static int init(); - static scoreStruct* create(LPCSTR fieldName, int renderBgBmp); + static scoreStruct* create(LPCSTR fieldName, gdrv_bitmap8* renderBgBmp); static scoreStruct* dup(scoreStruct* score, int scoreIndex); }; diff --git a/SpaceCadetPinball/zdrv.cpp b/SpaceCadetPinball/zdrv.cpp index 8abcb7c..5463949 100644 --- a/SpaceCadetPinball/zdrv.cpp +++ b/SpaceCadetPinball/zdrv.cpp @@ -31,15 +31,11 @@ int zdrv::destroy_zmap(zmap_header_type* 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; + memset(zmap, 0, sizeof(zmap_header_type)); return 0; } -void zdrv::fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, __int16 fillChar) +void zdrv::fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, unsigned __int16 fillChar) { int fillCharInt = fillChar | (fillChar << 16); auto zmapPtr = &zmap->ZPtr1[2 * (xOff + zmap->Stride * (zmap->Height - height - yOff))]; @@ -50,7 +46,7 @@ void zdrv::fill(zmap_header_type* zmap, int width, int height, int xOff, int yOf unsigned int widthDiv2 = static_cast(width) >> 1; memset32(zmapPtr, fillCharInt, widthDiv2); - __int16* lastShort = (__int16*)&zmapPtr[2 * widthDiv2]; + auto lastShort = &zmapPtr[2 * widthDiv2]; for (int i = widthMod2; i; --i) *lastShort++ = fillChar; diff --git a/SpaceCadetPinball/zdrv.h b/SpaceCadetPinball/zdrv.h index 92d23ce..744b4eb 100644 --- a/SpaceCadetPinball/zdrv.h +++ b/SpaceCadetPinball/zdrv.h @@ -22,7 +22,7 @@ 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 fill(zmap_header_type* zmap, int width, int height, int xOff, int yOff, unsigned __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);