mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-15 19:13:07 +01:00
Step 1 on road towards Linux. Remove windows-specific code, stub it out where needed and make sure we can still compile it the way it is. Take care of Travis' build matrix to include new build configuration. Install new packages.
329 lines
9.0 KiB
C
329 lines
9.0 KiB
C
/*****************************************************************************
|
|
* Copyright (c) 2014 Ted John, Peter Hill, Duncan Frost
|
|
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
|
*
|
|
* This file is part of OpenRCT2.
|
|
*
|
|
* OpenRCT2 is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*****************************************************************************/
|
|
|
|
#include "../addresses.h"
|
|
#include "../common.h"
|
|
#include "drawing.h"
|
|
#include "../platform/platform.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_, right_, top_, bottom_;
|
|
rct_drawpixelinfo* dpi_;
|
|
left_ = left;
|
|
right_ = right;
|
|
top_ = top;
|
|
bottom_ = bottom;
|
|
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
|
|
char* dest_pointer;
|
|
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;
|
|
pattern_pointer = RCT2_ADDRESS(0x0097FEFC,uint16*)[colour >> 28]; // or possibly uint8)[esi*4] ?
|
|
|
|
for (int no_lines = height; no_lines > 0; no_lines--) {
|
|
char* 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;
|
|
int edi = esi;
|
|
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
|
|
*
|
|
* rct2: 0x006E6F81
|
|
* dpi (edi)
|
|
* left (ax)
|
|
* top (cx)
|
|
* right (bx)
|
|
* bottom (dx)
|
|
* colour (ebp)
|
|
* flags (si)
|
|
*/
|
|
void gfx_fill_rect_inset(rct_drawpixelinfo* dpi, short left, short top, short right, short bottom, int colour, short flags)
|
|
{
|
|
uint8 shadow, fill, hilight;
|
|
|
|
// Flags
|
|
int no_border, no_fill, pressed;
|
|
|
|
no_border = 8;
|
|
no_fill = 0x10;
|
|
pressed = 0x20;
|
|
|
|
if (colour & 0x180) {
|
|
if (colour & 0x100) {
|
|
colour = colour & 0x7F;
|
|
} else {
|
|
colour = RCT2_ADDRESS(0x009DEDF4,uint8)[colour];
|
|
}
|
|
|
|
colour = colour | 0x2000000; //Transparent
|
|
|
|
if (flags & no_border) {
|
|
gfx_fill_rect(dpi, left, top, bottom, right, colour);
|
|
} else if (flags & pressed) {
|
|
// Draw outline of box
|
|
gfx_fill_rect(dpi, left, top, left, bottom, colour + 1);
|
|
gfx_fill_rect(dpi, left, top, right, top, colour + 1);
|
|
gfx_fill_rect(dpi, right, top, right, bottom, colour + 2);
|
|
gfx_fill_rect(dpi, left, bottom, right, bottom, colour + 2);
|
|
|
|
if (!(flags & no_fill)) {
|
|
gfx_fill_rect(dpi, left+1, top+1, right-1, bottom-1, colour);
|
|
}
|
|
} else {
|
|
// Draw outline of box
|
|
gfx_fill_rect(dpi, left, top, left, bottom, colour + 2);
|
|
gfx_fill_rect(dpi, left, top, right, top, colour + 2);
|
|
gfx_fill_rect(dpi, right, top, right, bottom, colour + 1);
|
|
gfx_fill_rect(dpi, left, bottom, right, bottom, colour + 1);
|
|
|
|
if (!(flags & no_fill)) {
|
|
gfx_fill_rect(dpi, left+1, top+1, right-1, bottom-1, colour);
|
|
}
|
|
}
|
|
} else {
|
|
if (flags & 0x80) {
|
|
shadow = RCT2_ADDRESS(0x0141FC46, uint8)[colour * 8];
|
|
fill = RCT2_ADDRESS(0x0141FC48, uint8)[colour * 8];
|
|
hilight = RCT2_ADDRESS(0x0141FC4A, uint8)[colour * 8];
|
|
} else {
|
|
shadow = RCT2_ADDRESS(0x0141FC47, uint8)[colour * 8];
|
|
fill = RCT2_ADDRESS(0x0141FC49, uint8)[colour * 8];
|
|
hilight = RCT2_ADDRESS(0x0141FC4B, uint8)[colour * 8];
|
|
}
|
|
|
|
if (flags & no_border) {
|
|
gfx_fill_rect(dpi, left, top, right, bottom, fill);
|
|
} else if (flags & pressed) {
|
|
// Draw outline of box
|
|
gfx_fill_rect(dpi, left, top, left, bottom, shadow);
|
|
gfx_fill_rect(dpi, left + 1, top, right, top, shadow);
|
|
gfx_fill_rect(dpi, right, top + 1, right, bottom - 1, hilight);
|
|
gfx_fill_rect(dpi, left + 1, bottom, right, bottom, hilight);
|
|
|
|
if (!(flags & no_fill)) {
|
|
if (!(flags & 0x40)) {
|
|
if (flags & 0x04) {
|
|
fill = RCT2_ADDRESS(0x0141FC49, uint8)[0];
|
|
} else {
|
|
fill = RCT2_ADDRESS(0x0141FC4A, uint8)[colour * 8];
|
|
}
|
|
}
|
|
gfx_fill_rect(dpi, left+1, top+1, right-1, bottom-1, fill);
|
|
}
|
|
} else {
|
|
// Draw outline of box
|
|
gfx_fill_rect(dpi, left, top, left, bottom - 1, hilight);
|
|
gfx_fill_rect(dpi, left + 1, top, right - 1, top, hilight);
|
|
gfx_fill_rect(dpi, right, top, right, bottom - 1, shadow);
|
|
gfx_fill_rect(dpi, left, bottom, right, bottom, shadow);
|
|
|
|
if (!(flags & no_fill)) {
|
|
if (flags & 0x04) {
|
|
fill = RCT2_ADDRESS(0x0141FC49, uint8)[0];
|
|
}
|
|
gfx_fill_rect(dpi, left+1, top+1, right-1, bottom-1, fill);
|
|
}
|
|
}
|
|
}
|
|
}
|