diff --git a/src/drawing/IDrawingContext.h b/src/drawing/IDrawingContext.h index d670458c66..ad5b1edf02 100644 --- a/src/drawing/IDrawingContext.h +++ b/src/drawing/IDrawingContext.h @@ -26,7 +26,7 @@ interface IDrawingContext virtual IDrawingEngine * GetEngine() abstract; - virtual void Clear(uint32 colour) abstract; - virtual void FillRect(uint32 colour, sint32 x, sint32 y, sint32 w, sint32 h) abstract; - virtual void DrawSprite(uint32 image, sint32 x, sint32 y) abstract; + virtual void Clear(uint32 colour) abstract; + virtual void FillRect(uint32 colour, sint32 left, sint32 top, sint32 right, sint32 bottom) abstract; + virtual void DrawSprite(uint32 image, sint32 x, sint32 y) abstract; }; diff --git a/src/drawing/NewDrawing.cpp b/src/drawing/NewDrawing.cpp index 46e9cfe26c..35381321ec 100644 --- a/src/drawing/NewDrawing.cpp +++ b/src/drawing/NewDrawing.cpp @@ -82,4 +82,23 @@ extern "C" dc->Clear(colour); } } + + /** + * + * rct2: 0x00678AD4 + * dpi (edi) + * left (ax) + * top (cx) + * right (bx) + * bottom (dx) + * colour (ebp) + */ + void gfx_fill_rect(rct_drawpixelinfo *dpi, int left, int top, int right, int bottom, int colour) + { + if (_drawingEngine != nullptr) + { + IDrawingContext * dc = _drawingEngine->GetDrawingContext(dpi); + dc->FillRect(colour, left, top, right, bottom); + } + } } diff --git a/src/drawing/engines/SoftwareDrawingEngine.cpp b/src/drawing/engines/SoftwareDrawingEngine.cpp index b0b019b8f8..18f9eabbcc 100644 --- a/src/drawing/engines/SoftwareDrawingEngine.cpp +++ b/src/drawing/engines/SoftwareDrawingEngine.cpp @@ -553,9 +553,200 @@ void SoftwareDrawingContext::Clear(uint32 colour) } } -void SoftwareDrawingContext::FillRect(uint32 colour, sint32 x, sint32 y, sint32 w, sint32 h) +void SoftwareDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint32 right, sint32 bottom) { + rct_drawpixelinfo * dpi = _dpi; + if (left > right) return; + if (top > bottom) return; + if (dpi->x > right) return; + if (left >= dpi->x + dpi->width) return; + if (bottom < dpi->y) return; + if (top >= dpi->y + dpi->height) return; + + colour |= RCT2_GLOBAL(0x009ABD9C, uint32); + + uint16 crossPattern = 0; + + int startX = left - dpi->x; + if (startX < 0) + { + crossPattern ^= startX; + startX = 0; + } + + int endX = right - dpi->x + 1; + if (endX > dpi->width) + { + endX = dpi->width; + } + + int startY = top - dpi->y; + if (startY < 0) + { + crossPattern ^= startY; + startY = 0; + } + + int endY = bottom - dpi->y + 1; + if (endY > dpi->height) + { + endY = dpi->height; + } + + int width = endX - startX; + int height = endY - startY; + + if (colour & 0x1000000) + { + // Cross hatching + uint8 * dst = (startY * (dpi->width + dpi->pitch)) + startX + dpi->bits; + for (int i = 0; i < height; i++) + { + uint8 * nextdst = dst + dpi->width + dpi->pitch; + uint32 p = ror32(crossPattern, 1); + p = (p & 0xFFFF0000) | width; + + // Fill every other pixel with the colour + for (; (p & 0xFFFF) != 0; p--) + { + p = p ^ 0x80000000; + if (p & 0x80000000) + { + *dst = colour & 0xFF; + } + dst++; + } + crossPattern ^= 1; + dst = nextdst; + } + } + else if (colour & 0x2000000) + { + //0x2000000 + // 00678B7E 00678C83 + // Location in screen buffer? + uint8 * dst = dpi->bits + (uint32)((startY >> (dpi->zoom_level)) * ((dpi->width >> dpi->zoom_level) + dpi->pitch) + (startX >> dpi->zoom_level)); + + // Find colour in colour table? + uint16 g1Index = palette_to_g1_offset[colour & 0xFF]; + rct_g1_element * g1Element = &g1Elements[g1Index]; + uint8 * g1Bits = g1Element->offset; + + // Fill the rectangle with the colours from the colour table + for (int i = 0; i < height >> dpi->zoom_level; i++) + { + uint8 * nextdst = dst + (dpi->width >> dpi->zoom_level) + dpi->pitch; + for (int j = 0; j < (width >> dpi->zoom_level); j++) + { + *dst = g1Bits[*dst]; + dst++; + } + dst = nextdst; + } + } + else if (colour & 0x4000000) + { + uint8 * dst = startY * (dpi->width + dpi->pitch) + startX + dpi->bits; + + // The pattern loops every 15 lines this is which + // part the pattern is on. + int patternY = (startY + dpi->y) % 16; + + // The pattern loops every 15 pixels this is which + // part the pattern is on. + int startPatternX = (startX + dpi->x) % 16; + int patternX = startPatternX; + + uint16 * patternsrc = RCT2_ADDRESS(0x0097FEFC, uint16*)[colour >> 28]; // or possibly uint8)[esi*4] ? + + for (int numLines = height; numLines > 0; numLines--) + { + uint8 * nextdst = dst + dpi->width + dpi->pitch; + uint16 pattern = patternsrc[patternY]; + + for (int numPixels = width; numPixels > 0; numPixels--) + { + if (pattern & (1 << patternX)) + { + *dst = colour & 0xFF; + } + patternX = (patternX + 1) % 16; + dst++; + } + patternX = startPatternX; + patternY = (patternY + 1) % 16; + dst = nextdst; + } + } + else if (colour & 0x8000000) + { + int esi = left - RCT2_GLOBAL(0x1420070, sint16); + RCT2_GLOBAL(0xEDF824, uint32) = esi; + esi = top - RCT2_GLOBAL(0x1420072, sint16); + RCT2_GLOBAL(0xEDF828, uint32) = esi; + left -= dpi->x; + if (left < 0) + { + RCT2_GLOBAL(0xEDF824, sint32) -= left; + left = 0; + } + right -= dpi->x; + right++; + if (right > dpi->width) + { + right = dpi->width; + } + right -= left; + top -= dpi->y; + if (top < 0) + { + RCT2_GLOBAL(0xEDF828, sint32) -= top; + top = 0; + } + bottom -= dpi->y; + bottom++; + if (bottom > dpi->height) + { + bottom = dpi->height; + } + bottom -= top; + RCT2_GLOBAL(0xEDF824, sint32) &= 0x3F; + RCT2_GLOBAL(0xEDF828, sint32) &= 0x3F; + esi = dpi->width; + esi += dpi->pitch; + esi *= top; + esi += left; + esi += (uint32)dpi->bits; + RCT2_GLOBAL(0xEDF82C, sint32) = right; + RCT2_GLOBAL(0xEDF830, sint32) = bottom; + left = dpi->width; + left += dpi->pitch; + left -= right; + RCT2_GLOBAL(0xEDF834, sint32) = left; + colour &= 0xFF; + colour--; + right = colour; + colour <<= 8; + right |= colour; + RCT2_GLOBAL(0xEDF838, sint32) = right; + //right <<= 4; + esi = RCT2_GLOBAL(0xEDF828, sint32); + esi *= 0x40; + left = 0; + esi += (uint32)g1Elements[right].offset;//??? + //Not finished + //Start of loop + } + else + { + uint8 * dst = startY * (dpi->width + dpi->pitch) + startX + dpi->bits; + for (int i = 0; i < height; i++) + { + Memory::Set(dst, colour & 0xFF, width); + dst += dpi->width + dpi->pitch; + } + } } void SoftwareDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y) diff --git a/src/drawing/rect.c b/src/drawing/rect.c index a2e08cbf40..4e9ffb6c67 100644 --- a/src/drawing/rect.c +++ b/src/drawing/rect.c @@ -20,203 +20,6 @@ #include "../platform/platform.h" #include "drawing.h" -/** - * - * rct2: 0x00678AD4 - * dpi (edi) - * left (ax) - * top (cx) - * right (bx) - * bottom (dx) - * colour (ebp) - */ -void gfx_fill_rect(rct_drawpixelinfo *dpi, int left, int top, int right, int bottom, int colour) -{ - int left_ = left; - int right_ = right; - int top_ = top; - int bottom_ = bottom; - rct_drawpixelinfo *dpi_ = dpi; - - if ((left > right) || (top > bottom) || (dpi->x > right) || (left >= (dpi->x + dpi->width)) || - (bottom < dpi->y) || (top >= (dpi->y + dpi->height))) - return; - - colour |= RCT2_GLOBAL(0x009ABD9C, uint32); - - uint16 cross_pattern = 0; - - int start_x = left - dpi->x; - if (start_x < 0){ - cross_pattern ^= start_x; - start_x = 0; - } - - int end_x = right - dpi->x; - end_x++; - if (end_x > dpi->width) - end_x = dpi->width; - - int width = end_x - start_x; - - int start_y = top - dpi->y; - if (start_y < 0){ - cross_pattern ^= start_y; - start_y = 0; - } - int end_y = bottom - dpi->y; - end_y++; - - if (end_y > dpi->height) - end_y = dpi->height; - - int height = end_y - start_y; - if (colour&0x1000000){ - // 00678B2E 00678BE5 - //Cross hatching - uint8* dest_pointer = (start_y * (dpi->width + dpi->pitch)) + start_x + dpi->bits; - - uint32 ecx; - for (int i = 0; i < height; ++i) { - uint8* next_dest_pointer = dest_pointer + dpi->width + dpi->pitch; - ecx = cross_pattern; - // Rotate right - ecx = (ecx >> 1) | (ecx << (sizeof(ecx) * CHAR_BIT - 1)); - ecx = (ecx & 0xFFFF0000) | width; - // Fill every other pixel with the colour - for (; (ecx & 0xFFFF) > 0; ecx--) { - ecx = ecx ^ 0x80000000; - if ((int)ecx < 0) { - *dest_pointer = colour & 0xFF; - } - dest_pointer++; - } - cross_pattern ^= 1; - dest_pointer = next_dest_pointer; - - } - return; - } - if (colour & 0x2000000){ - //0x2000000 - // 00678B7E 00678C83 - // Location in screen buffer? - uint8* dest_pointer = dpi->bits + (uint32)((start_y >> (dpi->zoom_level)) * ((dpi->width >> dpi->zoom_level) + dpi->pitch) + (start_x >> dpi->zoom_level)); - - // Find colour in colour table? - uint16 eax = palette_to_g1_offset[(colour & 0xFF)]; - rct_g1_element g1_element = g1Elements[eax]; - - // Fill the rectangle with the colours from the colour table - for (int i = 0; i < height>>dpi->zoom_level; ++i) { - uint8* next_dest_pointer = dest_pointer + (dpi->width >> dpi->zoom_level) + dpi->pitch; - for (int j = 0; j < width>>dpi->zoom_level; ++j) { - *dest_pointer = g1_element.offset[*dest_pointer]; - dest_pointer++; - } - dest_pointer = next_dest_pointer; - } - return; - } - if (colour & 0x4000000){ - //0x4000000 - // 00678B8A 00678E38 - uint8* dest_pointer = start_y * (dpi->width + dpi->pitch) + start_x + dpi->bits; - - //The pattern loops every 15 lines this is which - //part the pattern is on. - int pattern_y = (start_y + dpi->y) % 16; - - //The pattern loops every 15 pixels this is which - //part the pattern is on. - int start_pattern_x = (start_x + dpi_->x) % 16; - int pattern_x = start_pattern_x; - - uint16* pattern_pointer = RCT2_ADDRESS(0x0097FEFC,uint16*)[colour >> 28]; // or possibly uint8)[esi*4] ? - - for (int no_lines = height; no_lines > 0; no_lines--) { - uint8* next_dest_pointer = dest_pointer + dpi->width + dpi->pitch; - uint16 pattern = pattern_pointer[pattern_y]; - - for (int no_pixels = width; no_pixels > 0; --no_pixels) { - if (pattern & (1 << pattern_x)) - *dest_pointer = colour & 0xFF; - - pattern_x = (pattern_x + 1) % 16; - dest_pointer++; - } - pattern_x = start_pattern_x; - pattern_y = (pattern_y + 1) % 16; - dest_pointer = next_dest_pointer; - } - return; - } - if (colour & 0x8000000){ - //0x8000000 - // 00678B3A 00678EC9 still to be implemented - int esi = left - RCT2_GLOBAL(0x1420070,sint16); - RCT2_GLOBAL(0xEDF824,uint32) = esi; - esi = top - RCT2_GLOBAL(0x1420072,sint16); - RCT2_GLOBAL(0xEDF828,uint32) = esi; - left -= dpi->x;//0x4 - if ( left < 0 ){ - RCT2_GLOBAL(0xEDF824,sint32) -= left; - left = 0; - } - right -= dpi->x; - right++; - if ( right > dpi->width ){ - right = dpi->width; - } - right -= left; - top -= dpi->y; - if ( top < 0 ){ - RCT2_GLOBAL(0xEDF828,sint32) -= top; - top = 0; - } - bottom -= dpi->y; - bottom++; - if (bottom > dpi->height){ - bottom = dpi->height; - } - bottom -= top; - RCT2_GLOBAL(0xEDF824,sint32) &= 0x3F; - RCT2_GLOBAL(0xEDF828,sint32) &= 0x3F; - esi = dpi->width; - esi += dpi->pitch; - esi *= top; - esi += left; - esi += (uint32)dpi->bits; - RCT2_GLOBAL(0xEDF82C,sint32) = right; - RCT2_GLOBAL(0xEDF830,sint32) = bottom; - left = dpi->width; - left+= dpi->pitch; - left-= right; - RCT2_GLOBAL(0xEDF834,sint32) = left; - colour &= 0xFF; - colour--; - right = colour; - colour <<= 8; - right |= colour; - RCT2_GLOBAL(0xEDF838,sint32) = right; - //right <<= 4; - esi = RCT2_GLOBAL(0xEDF828,sint32); - esi *= 0x40; - left = 0; - esi += (uint32)g1Elements[right].offset;//??? - //Not finished - //Start of loop - return; - } - //0x0000000 - uint8* dest_pointer = start_y * (dpi->width + dpi->pitch) + start_x + dpi->bits; - - for (int i = 0; i < height; ++i) { - memset(dest_pointer, (colour & 0xFF), width); - dest_pointer += dpi->width + dpi->pitch; - } -} - /** * Draw a rectangle, with optional border or fill *