# HG changeset patch # User Paul Boddie # Date 1541367857 -3600 # Node ID b09769a6eaa574b11850268091e6daa6fb23dfd1 # Parent ec41bb0393497a2458966b322345e581f2bbc969 Fixed screen edge updates where update columns span the background image edge. Maintain the scroll origin as signed integers to allow general subtraction, with more general value wrapping employed to keep the origin point in the background image within limits. diff -r ec41bb039349 -r b09769a6eaa5 examples/vga/main.c --- a/examples/vga/main.c Sun Nov 04 20:45:02 2018 +0100 +++ b/examples/vga/main.c Sun Nov 04 22:44:17 2018 +0100 @@ -161,62 +161,86 @@ x, y, -1, 1); } +/* Wrap a value within the bounds [0, limit). */ + +static int wrap_value(int value, int limit) +{ + if (value < 0) + return limit - (-value % limit); + else if (value >= limit) + return (value - limit) % limit; + else + return value; +} + /* Plot the revealed region at the edge of the screen after scrolling. */ static void plot_screen_edge(int xorigin, int yorigin, int xstep) { + /* Determine positions within the image. */ + + int xpos = wrap_value(xorigin, screendata_width); + int ypos = wrap_value(yorigin, screendata_height); + /* The display region is either the left or right edge. */ int xdisplay = xstep < 0 ? 0 : screendata_width - xstep; /* The source region depends on the origin within the background image. */ - int xsource = (xdisplay + xorigin) % screendata_width; + int xsource = wrap_value(xdisplay + xpos, screendata_width); /* The column width is the absolute increment. */ int width = xstep < 0 ? -xstep : xstep; - /* Plot a column in two pieces if the vertical origin is - non-zero. The first piece is at (xdisplay, 0) and - provides the lower part of the background image displaced - upwards (or downwards having wrapped around) on the - screen. */ + /* Not all of the column may be available if close to the edge of the + image, requiring multiple slices. */ + + int available = screendata_width - xsource; - copy_display_section(&display_config, screendata, - screendata_width, screendata_height, - xsource, yorigin, - width, screendata_height - yorigin, - SOURCE_YSTEP, - xdisplay, 0, - -1, 1); + while (width) + { + /* Plot a column in two pieces if the vertical origin is + non-zero. The first piece is at (xdisplay, 0) and + provides the lower part of the background image displaced + upwards (or downwards having wrapped around) on the + screen. */ - /* The second column is at (xdisplay, h - yorigin) and - provides the upper part of the background image displaced - downwards (or upwards having wrapped around) on the - screen. */ - - if (yorigin) copy_display_section(&display_config, screendata, screendata_width, screendata_height, - xsource, 0, - width, yorigin, + xsource, ypos, + width, screendata_height - ypos, SOURCE_YSTEP, - xdisplay, (screendata_height - yorigin) / SOURCE_YSTEP, + xdisplay, 0, -1, 1); -} + + /* The second column is at (xdisplay, h - ypos) and + provides the upper part of the background image displaced + downwards (or upwards having wrapped around) on the + screen. */ -/* Wrap a value within the bounds [0, limit) provided value is already within - the bounds [-limit, limit * 2). */ + if (ypos) + copy_display_section(&display_config, screendata, + screendata_width, screendata_height, + xsource, 0, + width, ypos, + SOURCE_YSTEP, + xdisplay, (screendata_height - ypos) / SOURCE_YSTEP, + -1, 1); + + /* Get the next slice of the column. */ -static int wrap_value(int value, int limit) -{ - if (value < 0) - return value + limit; - else if (value >= limit) - return value - limit; - else - return value; + if (available < width) + { + width -= available; + xsource = 0; + xdisplay = wrap_value(xdisplay + available, screendata_width); + available = screendata_width; + } + else + width = 0; + } } /* Move a sprite around on the framebuffer. */ @@ -312,11 +336,14 @@ /* Due to the effect of a simple screen start increment in the dual channel configuration, horizontal scrolling involves two pixel increments and thus requires a two-pixel column to be - plotted. */ + plotted per scrolling increment. */ if (xdir) xorigin += xdir * SCROLL_XSTEP; + /* For vertically-scaled backgrounds, the full resolution image + is traversed by multiples of the scrolling increment. */ + if (ydir) yorigin += ydir * SOURCE_YSTEP; @@ -335,11 +362,6 @@ frame_offset[frame] = get_start_offset(&display_config); - /* Update the current origin. */ - - xorigin = wrap_value(xorigin, screendata_width); - yorigin = wrap_value(yorigin, screendata_height); - /* For horizontal scrolling, plot the exposed column at the left (if scrolling left) or at the right (if scrolling right). */