add hardware display

This commit is contained in:
IntelOrca 2015-05-22 03:17:46 +01:00
parent 25c5c8cbaa
commit 0013310f0d
6 changed files with 138 additions and 55 deletions

View File

@ -3487,3 +3487,4 @@ STR_5150 :Enable debugging tools
STR_5151 :,
STR_5152 :.
STR_5153 :RCT1 colour scheme
STR_5154 :Hardware display

View File

@ -161,6 +161,7 @@ config_property_definition _generalDefinitions[] = {
{ offsetof(general_configuration, window_height), "window_height", CONFIG_VALUE_TYPE_SINT32, -1, NULL },
{ offsetof(general_configuration, window_snap_proximity), "window_snap_proximity", CONFIG_VALUE_TYPE_UINT8, 5, NULL },
{ offsetof(general_configuration, window_width), "window_width", CONFIG_VALUE_TYPE_SINT32, -1, NULL },
{ offsetof(general_configuration, hardware_display), "hardware_display", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL },
};
config_property_definition _interfaceDefinitions[] = {

View File

@ -130,6 +130,7 @@ typedef struct {
uint16 language;
uint8 window_snap_proximity;
uint8 autosave_frequency;
uint8 hardware_display;
} general_configuration;
typedef struct {

View File

@ -77,6 +77,7 @@ void platform_free();
void platform_update_palette(char* colours, int start_index, int num_colours);
void platform_set_fullscreen_mode(int mode);
void platform_set_cursor(char cursor);
void platform_refresh_video();
void platform_process_messages();
int platform_scancode_to_rct_keycode(int sdl_key);
void platform_start_text_input(char* buffer, int max_length);

View File

@ -45,12 +45,16 @@ int gNumResolutions = 0;
resolution *gResolutions = NULL;
int gResolutionsAllowAnyAspectRatio = 0;
SDL_Window *gWindow;
SDL_Window *gWindow = NULL;
SDL_Renderer *gRenderer = NULL;
SDL_Texture *gBufferTexture = NULL;
SDL_Color gPalette[256];
static SDL_Surface *_surface;
static SDL_Palette *_palette;
static int _screenBufferSize;
static void *_screenBuffer;
static int _screenBufferPitch;
static SDL_Cursor* _cursors[CURSOR_COUNT];
static const int _fullscreen_modes[] = { 0, SDL_WINDOW_FULLSCREEN, SDL_WINDOW_FULLSCREEN_DESKTOP };
static unsigned int _lastGestureTimestamp;
@ -162,28 +166,63 @@ void platform_get_closest_resolution(int inWidth, int inHeight, int *outWidth, i
void platform_draw()
{
// Lock the surface before setting its pixels
if (SDL_MUSTLOCK(_surface))
if (SDL_LockSurface(_surface) < 0) {
RCT2_ERROR("locking failed %s", SDL_GetError());
return;
int width = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16);
int height = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16);
if (gConfigGeneral.hardware_display) {
void *pixels;
int pitch;
if (SDL_LockTexture(gBufferTexture, NULL, &pixels, &pitch) == 0) {
uint8 *dst = pixels;
uint8 *src = (uint8*)_screenBuffer;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
uint8 paletteIndex = *src;
SDL_Color colour = gPalette[paletteIndex];
dst[0] = 255;
dst[1] = colour.b;
dst[2] = colour.g;
dst[3] = colour.r;
src += 1;
dst += 4;
}
src += _screenBufferPitch - width;
dst += pitch - (width * 4);
}
SDL_UnlockTexture(gBufferTexture);
}
// Copy pixels from the virtual screen buffer to the surface
memcpy(_surface->pixels, _screenBuffer, _surface->pitch * _surface->h);
SDL_RenderCopy(gRenderer, gBufferTexture, NULL, NULL);
SDL_RenderPresent(gRenderer);
} else {
// Lock the surface before setting its pixels
if (SDL_MUSTLOCK(_surface)) {
if (SDL_LockSurface(_surface) < 0) {
log_error("locking failed %s", SDL_GetError());
return;
}
}
// Unlock the surface
if (SDL_MUSTLOCK(_surface))
SDL_UnlockSurface(_surface);
// Copy pixels from the virtual screen buffer to the surface
memcpy(_surface->pixels, _screenBuffer, _surface->pitch * _surface->h);
// Copy the surface to the window
if (SDL_BlitSurface(_surface, NULL, SDL_GetWindowSurface(gWindow), NULL)) {
RCT2_ERROR("SDL_BlitSurface %s", SDL_GetError());
exit(1);
}
if (SDL_UpdateWindowSurface(gWindow)) {
RCT2_ERROR("SDL_UpdateWindowSurface %s", SDL_GetError());
exit(1);
// Unlock the surface
if (SDL_MUSTLOCK(_surface))
SDL_UnlockSurface(_surface);
// Copy the surface to the window
if (SDL_BlitSurface(_surface, NULL, SDL_GetWindowSurface(gWindow), NULL)) {
log_fatal("SDL_BlitSurface %s", SDL_GetError());
exit(1);
}
if (SDL_UpdateWindowSurface(gWindow)) {
log_fatal("SDL_UpdateWindowSurface %s", SDL_GetError());
exit(1);
}
}
}
@ -194,25 +233,12 @@ static void platform_resize(int width, int height)
void *newScreenBuffer;
uint32 flags;
if (_surface != NULL)
SDL_FreeSurface(_surface);
if (_palette != NULL)
SDL_FreePalette(_palette);
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) = width;
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) = height;
_surface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0);
_palette = SDL_AllocPalette(256);
platform_refresh_video();
if (!_surface || !_palette) {
RCT2_ERROR("%p || %p == NULL %s", _surface, _palette, SDL_GetError());
exit(-1);
}
if (SDL_SetSurfacePalette(_surface, _palette)) {
RCT2_ERROR("SDL_SetSurfacePalette failed %s", SDL_GetError());
exit(-1);
}
newScreenBufferSize = _surface->pitch * _surface->h;
newScreenBufferSize = _screenBufferPitch * height;
newScreenBuffer = malloc(newScreenBufferSize);
if (_screenBuffer == NULL) {
memset(newScreenBuffer, 0, newScreenBufferSize);
@ -226,16 +252,13 @@ static void platform_resize(int width, int height)
_screenBuffer = newScreenBuffer;
_screenBufferSize = newScreenBufferSize;
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) = width;
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) = height;
screenDPI = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo);
screenDPI->bits = _screenBuffer;
screenDPI->x = 0;
screenDPI->y = 0;
screenDPI->width = width;
screenDPI->height = height;
screenDPI->pitch = _surface->pitch - _surface->w;
screenDPI->pitch = _screenBufferPitch - width;
RCT2_GLOBAL(0x009ABDF0, uint8) = 6;
RCT2_GLOBAL(0x009ABDF1, uint8) = 3;
@ -268,27 +291,28 @@ static void platform_resize(int width, int height)
void platform_update_palette(char* colours, int start_index, int num_colours)
{
SDL_Color base[256];
SDL_Surface *surface;
int i;
surface = SDL_GetWindowSurface(gWindow);
if (!surface) {
RCT2_ERROR("SDL_GetWindowSurface failed %s", SDL_GetError());
exit(1);
}
for (i = 0; i < 256; i++) {
base[i].r = colours[2];
base[i].g = colours[1];
base[i].b = colours[0];
base[i].a = 0;
gPalette[i].r = colours[2];
gPalette[i].g = colours[1];
gPalette[i].b = colours[0];
gPalette[i].a = 0;
colours += 4;
}
if (SDL_SetPaletteColors(_palette, base, 0, 256)) {
RCT2_ERROR("SDL_SetPaletteColors failed %s", SDL_GetError());
exit(1);
if (!gConfigGeneral.hardware_display) {
surface = SDL_GetWindowSurface(gWindow);
if (!surface) {
log_fatal("SDL_GetWindowSurface failed %s", SDL_GetError());
exit(1);
}
if (_palette != NULL && SDL_SetPaletteColors(_palette, gPalette, 0, 256)) {
log_fatal("SDL_SetPaletteColors failed %s", SDL_GetError());
exit(1);
}
}
}
@ -521,10 +545,12 @@ static void platform_create_window()
int width, height;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
RCT2_ERROR("SDL_Init %s", SDL_GetError());
log_fatal("SDL_Init %s", SDL_GetError());
exit(-1);
}
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, 0);
platform_load_cursors();
RCT2_CALLPROC_EBPSAFE(0x0068371D);
@ -711,4 +737,41 @@ int platform_get_cursor_pos(int* x, int* y)
GetCursorPos(&point);
*x = point.x;
*y = point.y;
}
void platform_refresh_video()
{
int width = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16);
int height = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16);
if (gConfigGeneral.hardware_display) {
if (gRenderer == NULL)
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
if (gBufferTexture != NULL)
SDL_DestroyTexture(gBufferTexture);
gBufferTexture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBX8888, SDL_TEXTUREACCESS_STREAMING, width, height);
_screenBufferPitch = width;
} else {
if (_surface != NULL)
SDL_FreeSurface(_surface);
if (_palette != NULL)
SDL_FreePalette(_palette);
_surface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0);
_palette = SDL_AllocPalette(256);
if (!_surface || !_palette) {
log_fatal("%p || %p == NULL %s", _surface, _palette, SDL_GetError());
exit(-1);
}
if (SDL_SetSurfacePalette(_surface, _palette)) {
log_fatal("SDL_SetSurfacePalette failed %s", SDL_GetError());
exit(-1);
}
_screenBufferPitch = _surface->pitch;
}
}

View File

@ -68,6 +68,7 @@ enum WINDOW_OPTIONS_WIDGET_IDX {
WIDX_GRIDLINES_CHECKBOX,
WIDX_CONSTRUCTION_MARKER,
WIDX_CONSTRUCTION_MARKER_DROPDOWN,
WIDX_HARDWARE_DISPLAY_CHECKBOX,
WIDX_LANGUAGE,
WIDX_LANGUAGE_DROPDOWN,
@ -126,6 +127,7 @@ static rct_widget window_options_widgets[] = {
{ WWT_CHECKBOX, 0, 10, 299, 99, 110, STR_GRIDLINES, STR_GRIDLINES_TIP },
{ WWT_DROPDOWN, 0, 155, 299, 113, 124, STR_NONE, STR_NONE }, // construction marker
{ WWT_DROPDOWN_BUTTON, 0, 288, 298, 114, 123, 876, STR_NONE },
{ WWT_CHECKBOX, 0, 10, 290, 129, 140, 5154, STR_NONE },
// Culture / units tab
{ WWT_DROPDOWN, 0, 155, 299, 53, 64, STR_NONE, STR_NONE }, // language
@ -266,6 +268,7 @@ void window_options_open()
(1ULL << WIDX_HEIGHT_LABELS_DROPDOWN) |
(1ULL << WIDX_TILE_SMOOTHING_CHECKBOX) |
(1ULL << WIDX_GRIDLINES_CHECKBOX) |
(1ULL << WIDX_HARDWARE_DISPLAY_CHECKBOX) |
(1ULL << WIDX_SAVE_PLUGIN_DATA_CHECKBOX) |
(1ULL << WIDX_AUTOSAVE) |
(1ULL << WIDX_AUTOSAVE_DROPDOWN) |
@ -364,6 +367,12 @@ static void window_options_mouseup()
w->viewport->flags &= ~VIEWPORT_FLAG_GRIDLINES;
}
break;
case WIDX_HARDWARE_DISPLAY_CHECKBOX:
gConfigGeneral.hardware_display ^= 1;
platform_refresh_video();
config_save_default();
window_invalidate(w);
break;
case WIDX_SAVE_PLUGIN_DATA_CHECKBOX:
gConfigGeneral.save_plugin_data ^= 1;
config_save_default();
@ -708,6 +717,12 @@ static void window_options_invalidate()
else
w->pressed_widgets &= ~(1ULL << WIDX_GRIDLINES_CHECKBOX);
// show hardware display
if (gConfigGeneral.hardware_display)
w->pressed_widgets |= (1ULL << WIDX_HARDWARE_DISPLAY_CHECKBOX);
else
w->pressed_widgets &= ~(1ULL << WIDX_HARDWARE_DISPLAY_CHECKBOX);
// construction marker: celsius/fahrenheit
window_options_widgets[WIDX_CONSTRUCTION_MARKER].image = STR_WHITE + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CONSTRUCTION_MARKER, uint8);
@ -719,6 +734,7 @@ static void window_options_invalidate()
window_options_widgets[WIDX_GRIDLINES_CHECKBOX].type = WWT_CHECKBOX;
window_options_widgets[WIDX_CONSTRUCTION_MARKER].type = WWT_DROPDOWN;
window_options_widgets[WIDX_CONSTRUCTION_MARKER_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
window_options_widgets[WIDX_HARDWARE_DISPLAY_CHECKBOX].type = WWT_CHECKBOX;
break;
case WINDOW_OPTIONS_PAGE_CULTURE:
// currency: pounds, dollars, etc. (10 total)