From 4197ad064f87e8262ea281736d7e3bb6d4797e0a Mon Sep 17 00:00:00 2001 From: Mikko Juola Date: Mon, 16 Aug 2010 16:35:58 +0300 Subject: [PATCH] Add a dirty hack to stop flickering on non-synchronizing DF processes. --- library/modules/Position.cpp | 48 ++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/library/modules/Position.cpp b/library/modules/Position.cpp index 694db6838..4499b6089 100644 --- a/library/modules/Position.cpp +++ b/library/modules/Position.cpp @@ -43,6 +43,11 @@ struct Position::Private uint32_t hotkey_size; uint32_t screen_tiles_ptr_offset; + uint32_t last_screen_offset; + + uint8_t* tiles; + uint32_t tiles_size; + bool first_read; // used in getScreenTiles DFContextShared *d; Process * owner; @@ -57,6 +62,11 @@ Position::Position(DFContextShared * d_) d = new Private; d->d = d_; d->owner = d_->p; + d->last_screen_offset = (uint32_t) 0; + d->tiles = (uint8_t*) 0; + d->first_read = true; + d->tiles_size = 0; + d->Inited = true; d->StartedHotkeys = d->Started = d->StartedScreen = false; memory_info * mem; @@ -90,6 +100,7 @@ Position::Position(DFContextShared * d_) Position::~Position() { + if (d->tiles) delete[] d->tiles; delete d; } @@ -176,13 +187,42 @@ bool Position::getScreenTiles (int32_t width, int32_t height, t_screen screen[]) if(!d->Inited) return false; if(!d->StartedScreen) return false; + /* + To work around flickering without synchronization, + we take advantage of double buffering in DF. + + We don't return the buffer currently in use, + but the buffer that was last used. This has much less + chance of being empty or flicker. + */ + uint32_t screen_addr; + d->owner->read (d->screen_tiles_ptr_offset, sizeof(uint32_t), (uint8_t *) &screen_addr); + if (d->first_read) + d->last_screen_offset = screen_addr; + + if (d->tiles && width * height * 4 != d->tiles_size) + { + delete[] d->tiles; + d->tiles = (uint8_t*) 0; + } - uint8_t* tiles = new uint8_t[width*height*4/* + 80 + width*height*4*/]; - - d->owner->read (screen_addr, (width*height*4/* + 80 + width*height*4*/), (uint8_t *) tiles); + if (!d->tiles) + { + d->tiles = new uint8_t[width * height * 4]; + d->tiles_size = width * height * 4; + } + + if (d->last_screen_offset != screen_addr || d->first_read) + { + d->owner->read (d->last_screen_offset, width*height*4, (uint8_t*) d->tiles); + d->last_screen_offset = screen_addr; + } + d->first_read = false; + const uint8_t* tiles = d->tiles; + for(int32_t iy=0; iy