# HG changeset patch # User Paul Boddie # Date 1542200115 -3600 # Node ID f6e7f5065d264a1c9d27f2f167989ae270c84a6f # Parent 4edaab76cca865e52b23caf634811ac4ccf1f7a4 Introduced the copying of line data needed when the start pointer wraps around. This was largely overlooked due to the test background image being padded at the top and bottom: this will have masked artefacts that might have been visible otherwise. diff -r 4edaab76cca8 -r f6e7f5065d26 lib/display.c --- a/lib/display.c Tue Nov 13 22:33:09 2018 +0100 +++ b/lib/display.c Wed Nov 14 13:55:15 2018 +0100 @@ -215,6 +215,14 @@ } } +/* Convenience function for copying. */ + +static void copy_data(uint8_t *dest, const uint8_t *src, int count) +{ + while (count--) + *dest = *src; +} + /* Scroll the display. */ void display_scroll(display_config_t *cfg, int x, int y) @@ -222,8 +230,50 @@ /* Move the screen start by the given number of bytes and lines, wrapping around the start and end of the framebuffer. */ - cfg->screen_start = display_wrap_pointer(cfg, cfg->screen_start + x + - y * cfg->line_length); + uint8_t *screen_start = cfg->screen_start + x + y * cfg->line_length; + uint32_t offset; + + /* Test for the start pointer needing to be wrapped. Where wrapping around + the screen limits occurs, the data for the line referenced by the start + pointer needs copying to its new location. This is because a spare line + is used (due to line data needing to be contiguous), and upon wrapping + around, the newly-referenced line will not contain relevant data. + + Such copying may be unnecessary if an entire pixel line is scrolled onto + the display. */ + + if (screen_start < cfg->frame_start) + { + /* Get the extent to which the screen start (and the start of the first + display line) is off the start of the frame. */ + + offset = cfg->frame_start - screen_start; + screen_start = display_wrap_pointer(cfg, screen_start); + + /* The end of the first display line needs copying, with any data from + the frame start being transferred to the relocated line. */ + + if (offset < cfg->line_length) + copy_data(screen_start + offset, cfg->frame_start, + cfg->line_length - offset); + } + else if (screen_start >= cfg->screen_limit) + { + /* Get the extent to which the screen start (and the start of the first + display line) is off the end of the frame. */ + + offset = screen_start - cfg->screen_limit; + screen_start = display_wrap_pointer(cfg, screen_start); + + /* The start of the first display line needs copying, with any data + before the frame end being transferred to the relocated line. */ + + if (offset < cfg->line_length) + copy_data(screen_start, cfg->screen_limit + offset, + cfg->line_length - offset); + } + + cfg->screen_start = screen_start; } /* Provide a pattern to test the line data. */