1.1 --- a/examples/vga/main.c Sat Nov 03 21:47:40 2018 +0100
1.2 +++ b/examples/vga/main.c Sat Nov 03 22:10:25 2018 +0100
1.3 @@ -130,6 +130,83 @@
1.4 }
1.5 }
1.6
1.7 +/* Copy to the store from the display, then blit the image. */
1.8 +
1.9 +static void plot_sprite(uint8_t *background, int x, int y)
1.10 +{
1.11 + copy_display(&display_config, background,
1.12 + sprite_width, sprite_height,
1.13 + x, y, -1, 0);
1.14 + copy_display(&display_config, sprite,
1.15 + sprite_width, sprite_height,
1.16 + x, y, 0x8c, 1);
1.17 +}
1.18 +
1.19 +/* Copy to the display from the store, restoring the original background. */
1.20 +
1.21 +static void unplot_sprite(uint8_t *background, int x, int y)
1.22 +{
1.23 + copy_display(&display_config, background,
1.24 + sprite_width, sprite_height,
1.25 + x, y, -1, 1);
1.26 +}
1.27 +
1.28 +/* Plot the revealed region at the edge of the screen after scrolling. */
1.29 +
1.30 +static void plot_screen_edge(int xorigin, int yorigin, int xstep)
1.31 +{
1.32 + /* The display region is either the left or right edge. */
1.33 +
1.34 + int xdisplay = xstep < 0 ? 0 : screendata_width - xstep;
1.35 +
1.36 + /* The source region depends on the origin within the background image. */
1.37 +
1.38 + int xsource = (xdisplay + xorigin) % screendata_width;
1.39 +
1.40 + /* The column width is the absolute increment. */
1.41 +
1.42 + int width = xstep < 0 ? -xstep : xstep;
1.43 +
1.44 + /* Plot a column in two pieces if the vertical origin is
1.45 + non-zero. The first piece is at (xdisplay, 0) and
1.46 + provides the lower part of the background image displaced
1.47 + upwards (or downwards having wrapped around) on the
1.48 + screen. */
1.49 +
1.50 + copy_display_section(&display_config, screendata,
1.51 + screendata_width, screendata_height,
1.52 + xsource, yorigin,
1.53 + width, screendata_height - yorigin,
1.54 + xdisplay, 0,
1.55 + -1, 1);
1.56 +
1.57 + /* The second column is at (xdisplay, h - yorigin) and
1.58 + provides the upper part of the background image displaced
1.59 + downwards (or upwards having wrapped around) on the
1.60 + screen. */
1.61 +
1.62 + if (yorigin)
1.63 + copy_display_section(&display_config, screendata,
1.64 + screendata_width, screendata_height,
1.65 + xsource, 0,
1.66 + width, yorigin,
1.67 + xdisplay, screendata_height - yorigin,
1.68 + -1, 1);
1.69 +}
1.70 +
1.71 +/* Wrap a value within the bounds [0, limit) provided value is already within
1.72 + the bounds [-limit, limit * 2). */
1.73 +
1.74 +static int wrap_value(int value, int limit)
1.75 +{
1.76 + if (value < 0)
1.77 + return value + limit;
1.78 + else if (value >= limit)
1.79 + return value - limit;
1.80 + else
1.81 + return value;
1.82 +}
1.83 +
1.84 /* Move a sprite around on the framebuffer. */
1.85
1.86 static void animate(uint32_t delay)
1.87 @@ -144,15 +221,16 @@
1.88
1.89 /* Scrolling directions. */
1.90
1.91 - int dir[] = {1, 0, -1, 0, 1}, i = 0;
1.92 + int dir[] = {1, 0, -1, 0, 1};
1.93 + int dirindex = 0;
1.94
1.95 /* Scrolling position. */
1.96
1.97 int xorigin = 0, yorigin = 0;
1.98
1.99 - /* Replotted column details. */
1.100 + /* Scroll increments and replotted column details. */
1.101
1.102 - int width, column_width, xsource, xdisplay;
1.103 + int xdir, ydir, xstep;
1.104
1.105 while (1)
1.106 {
1.107 @@ -160,104 +238,52 @@
1.108 {
1.109 for (x = 0; x < screendata_width - sprite_width; x++)
1.110 {
1.111 - /* Copy to the store from the display, then blit the image. */
1.112 -
1.113 - copy_display(&display_config, background,
1.114 - sprite_width, sprite_height,
1.115 - x, y, -1, 0);
1.116 - copy_display(&display_config, sprite,
1.117 - sprite_width, sprite_height,
1.118 - x, y, 0x8c, 1);
1.119 + plot_sprite(background, x, y);
1.120
1.121 /* Update the display with the frame details. */
1.122
1.123 vga_set_frame(&display_config);
1.124 wait(delay);
1.125
1.126 - /* Copy to the display from the store, restoring the original
1.127 - background. */
1.128 -
1.129 - copy_display(&display_config, background,
1.130 - sprite_width, sprite_height,
1.131 - x, y, -1, 1);
1.132 + unplot_sprite(background, x, y);
1.133
1.134 /* Scroll in the indicated direction. */
1.135
1.136 - scroll_display(&display_config, dir[i], dir[i + 1]);
1.137 + xdir = dir[dirindex];
1.138 + ydir = dir[dirindex + 1];
1.139 +
1.140 + scroll_display(&display_config, xdir, ydir);
1.141
1.142 /* Update the vertical origin if appropriate. */
1.143
1.144 - if (dir[i + 1])
1.145 - {
1.146 - yorigin += dir[i + 1];
1.147 -
1.148 - if (yorigin < 0)
1.149 - yorigin += screendata_height;
1.150 - else if (yorigin >= screendata_height)
1.151 - yorigin -= screendata_height;
1.152 - }
1.153 + if (ydir)
1.154 + yorigin = wrap_value(yorigin + ydir, screendata_height);
1.155
1.156 /* For horizontal scrolling, plot the exposed column at the left
1.157 (if scrolling left) or at the right (if scrolling right). */
1.158
1.159 - if (dir[i])
1.160 + if (xdir)
1.161 {
1.162 /* Due to the effect of a simple screen start increment in
1.163 the dual channel configuration, horizontal scrolling
1.164 involves two pixel increments and thus requires a two-
1.165 pixel column to be plotted. */
1.166
1.167 - width = dir[i] * SCROLL_XSTEP;
1.168 - column_width = width < 0 ? -width : width;
1.169 -
1.170 - /* Plot either at the left or right edge. */
1.171 -
1.172 - xdisplay = width < 0 ? 0 : screendata_width - width;
1.173 + xstep = xdir * SCROLL_XSTEP;
1.174
1.175 /* Determine the location of the column to be plotted. */
1.176
1.177 - xorigin += width;
1.178 -
1.179 - if (xorigin < 0)
1.180 - xorigin += screendata_width;
1.181 - else if (xorigin >= screendata_width)
1.182 - xorigin -= screendata_width;
1.183 -
1.184 - xsource = (xdisplay + xorigin) % screendata_width;
1.185 -
1.186 - /* Plot a column in two pieces if the vertical origin is
1.187 - non-zero. The first piece is at (xdisplay, 0) and
1.188 - provides the lower part of the background image displaced
1.189 - upwards (or downwards having wrapped around) on the
1.190 - screen. */
1.191 + xorigin = wrap_value(xorigin + xstep, screendata_width);
1.192
1.193 - copy_display_section(&display_config, screendata,
1.194 - screendata_width, screendata_height,
1.195 - xsource, yorigin,
1.196 - column_width, screendata_height - yorigin,
1.197 - xdisplay, 0,
1.198 - -1, 1);
1.199 + /* Plot either at the left or right edge. */
1.200
1.201 - /* The second column is at (xdisplay, h - yorigin) and
1.202 - provides the upper part of the background image displaced
1.203 - downwards (or upwards having wrapped around) on the
1.204 - screen. */
1.205 -
1.206 - if (yorigin)
1.207 - copy_display_section(&display_config, screendata,
1.208 - screendata_width, screendata_height,
1.209 - xsource, 0,
1.210 - column_width, yorigin,
1.211 - xdisplay, screendata_height - yorigin,
1.212 - -1, 1);
1.213 + plot_screen_edge(xorigin, yorigin, xstep);
1.214 }
1.215 }
1.216
1.217 /* Switch direction periodically. */
1.218
1.219 - i++;
1.220 - if (i == 4)
1.221 - i = 0;
1.222 + dirindex = wrap_value(dirindex + 1, 4);
1.223 }
1.224 }
1.225 }