# HG changeset patch # User Paul Boddie # Date 1541279425 -3600 # Node ID 87260bbe53995d6d33d72d0fa16a1b256381f689 # Parent 9ef06df79194663a7f73c8095e79199986c54f39 Introduced separate functions to simplify the animate function. diff -r 9ef06df79194 -r 87260bbe5399 examples/vga/main.c --- a/examples/vga/main.c Sat Nov 03 21:47:40 2018 +0100 +++ b/examples/vga/main.c Sat Nov 03 22:10:25 2018 +0100 @@ -130,6 +130,83 @@ } } +/* Copy to the store from the display, then blit the image. */ + +static void plot_sprite(uint8_t *background, int x, int y) +{ + copy_display(&display_config, background, + sprite_width, sprite_height, + x, y, -1, 0); + copy_display(&display_config, sprite, + sprite_width, sprite_height, + x, y, 0x8c, 1); +} + +/* Copy to the display from the store, restoring the original background. */ + +static void unplot_sprite(uint8_t *background, int x, int y) +{ + copy_display(&display_config, background, + sprite_width, sprite_height, + x, y, -1, 1); +} + +/* Plot the revealed region at the edge of the screen after scrolling. */ + +static void plot_screen_edge(int xorigin, int yorigin, int xstep) +{ + /* 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; + + /* 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. */ + + copy_display_section(&display_config, screendata, + screendata_width, screendata_height, + xsource, yorigin, + width, screendata_height - yorigin, + xdisplay, 0, + -1, 1); + + /* 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, + xdisplay, screendata_height - yorigin, + -1, 1); +} + +/* Wrap a value within the bounds [0, limit) provided value is already within + the bounds [-limit, limit * 2). */ + +static int wrap_value(int value, int limit) +{ + if (value < 0) + return value + limit; + else if (value >= limit) + return value - limit; + else + return value; +} + /* Move a sprite around on the framebuffer. */ static void animate(uint32_t delay) @@ -144,15 +221,16 @@ /* Scrolling directions. */ - int dir[] = {1, 0, -1, 0, 1}, i = 0; + int dir[] = {1, 0, -1, 0, 1}; + int dirindex = 0; /* Scrolling position. */ int xorigin = 0, yorigin = 0; - /* Replotted column details. */ + /* Scroll increments and replotted column details. */ - int width, column_width, xsource, xdisplay; + int xdir, ydir, xstep; while (1) { @@ -160,104 +238,52 @@ { for (x = 0; x < screendata_width - sprite_width; x++) { - /* Copy to the store from the display, then blit the image. */ - - copy_display(&display_config, background, - sprite_width, sprite_height, - x, y, -1, 0); - copy_display(&display_config, sprite, - sprite_width, sprite_height, - x, y, 0x8c, 1); + plot_sprite(background, x, y); /* Update the display with the frame details. */ vga_set_frame(&display_config); wait(delay); - /* Copy to the display from the store, restoring the original - background. */ - - copy_display(&display_config, background, - sprite_width, sprite_height, - x, y, -1, 1); + unplot_sprite(background, x, y); /* Scroll in the indicated direction. */ - scroll_display(&display_config, dir[i], dir[i + 1]); + xdir = dir[dirindex]; + ydir = dir[dirindex + 1]; + + scroll_display(&display_config, xdir, ydir); /* Update the vertical origin if appropriate. */ - if (dir[i + 1]) - { - yorigin += dir[i + 1]; - - if (yorigin < 0) - yorigin += screendata_height; - else if (yorigin >= screendata_height) - yorigin -= screendata_height; - } + if (ydir) + yorigin = wrap_value(yorigin + ydir, screendata_height); /* For horizontal scrolling, plot the exposed column at the left (if scrolling left) or at the right (if scrolling right). */ - if (dir[i]) + if (xdir) { /* 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. */ - width = dir[i] * SCROLL_XSTEP; - column_width = width < 0 ? -width : width; - - /* Plot either at the left or right edge. */ - - xdisplay = width < 0 ? 0 : screendata_width - width; + xstep = xdir * SCROLL_XSTEP; /* Determine the location of the column to be plotted. */ - xorigin += width; - - if (xorigin < 0) - xorigin += screendata_width; - else if (xorigin >= screendata_width) - xorigin -= screendata_width; - - xsource = (xdisplay + xorigin) % screendata_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. */ + xorigin = wrap_value(xorigin + xstep, screendata_width); - copy_display_section(&display_config, screendata, - screendata_width, screendata_height, - xsource, yorigin, - column_width, screendata_height - yorigin, - xdisplay, 0, - -1, 1); + /* Plot either at the left or right edge. */ - /* 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, - column_width, yorigin, - xdisplay, screendata_height - yorigin, - -1, 1); + plot_screen_edge(xorigin, yorigin, xstep); } } /* Switch direction periodically. */ - i++; - if (i == 4) - i = 0; + dirindex = wrap_value(dirindex + 1, 4); } } }