1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-25 15:54:31 +01:00

port gfx_fill_rect to IDrawingContext

This commit is contained in:
Ted John
2016-06-04 11:07:52 +01:00
parent 6e8cc5469a
commit 90704ac1fe
4 changed files with 214 additions and 201 deletions

View File

@@ -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;
};

View File

@@ -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);
}
}
}

View File

@@ -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)

View File

@@ -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
*