1.1 --- a/examples/vga/main.c Fri Nov 09 21:05:06 2018 +0100
1.2 +++ b/examples/vga/main.c Fri Nov 09 22:50:30 2018 +0100
1.3 @@ -25,6 +25,7 @@
1.4 #include "pic32_c.h"
1.5 #include "utils.h"
1.6 #include "vga_display.h"
1.7 +#include "viewport.h"
1.8
1.9 /* Specific functionality. */
1.10
1.11 @@ -93,6 +94,10 @@
1.12
1.13 uint8_t *screen_starts[FRAME_COUNT];
1.14
1.15 +/* Origin details for the viewport. */
1.16 +
1.17 +int xorigins[FRAME_COUNT], yorigins[FRAME_COUNT];
1.18 +
1.19
1.20
1.21 /* Bundled image and font data. */
1.22 @@ -133,7 +138,8 @@
1.23
1.24 /* Plot the revealed region at the edge of the screen after scrolling. */
1.25
1.26 -static void plot_screen_edge(int xorigin, int yorigin, int xstep)
1.27 +static void plot_screen_edge(viewport_t *v, int xorigin, int yorigin,
1.28 + int xstep, int ystep)
1.29 {
1.30 /* Determine positions within the image. */
1.31
1.32 @@ -169,7 +175,7 @@
1.33 screendata_width, screendata_height,
1.34 xsource, ypos,
1.35 width, screendata_height - ypos,
1.36 - SOURCE_YSTEP,
1.37 + v->yscale,
1.38 xdisplay, 0,
1.39 -1, 1);
1.40
1.41 @@ -183,8 +189,8 @@
1.42 screendata_width, screendata_height,
1.43 xsource, 0,
1.44 width, ypos,
1.45 - SOURCE_YSTEP,
1.46 - xdisplay, (screendata_height - ypos) / SOURCE_YSTEP,
1.47 + v->yscale,
1.48 + xdisplay, (screendata_height - ypos) / v->yscale,
1.49 -1, 1);
1.50
1.51 /* Get the next slice of the column. */
1.52 @@ -223,30 +229,25 @@
1.53 int dir[] = {1, 0, -1, 0, 1};
1.54 int dirindex = 0;
1.55
1.56 - /* Scrolling position. */
1.57 + /* Scroll increments. */
1.58
1.59 - int xorigin = 0, yorigin = 0;
1.60 -
1.61 - /* Scrolling positions for each frame. */
1.62 + int xdir, ydir;
1.63
1.64 - int xorigins[FRAME_COUNT], yorigins[FRAME_COUNT];
1.65 -
1.66 - /* Scroll increments and replotted column details. */
1.67 + /* Scrolling viewport. */
1.68
1.69 - int xdir, ydir, xstep, ystep;
1.70 + viewport_t v;
1.71
1.72 - /* Current frame being accessed. */
1.73 + /* Initialise the backing stores. */
1.74
1.75 int frame;
1.76
1.77 for (frame = 0; frame < display_config.frames; frame++)
1.78 - {
1.79 background_stored[frame] = 0;
1.80 - xorigins[frame] = xorigin;
1.81 - yorigins[frame] = yorigin;
1.82 - }
1.83 +
1.84 + /* Initialise the viewport. */
1.85
1.86 - frame = display_config.frame;
1.87 + init_viewport(&v, &display_config, xorigins, yorigins,
1.88 + SCROLL_XSTEP, SOURCE_YSTEP, plot_screen_edge);
1.89
1.90 /* Animation loop. */
1.91
1.92 @@ -256,13 +257,13 @@
1.93 {
1.94 for (x = 0; x < display_config.line_length - sprite_width; x++)
1.95 {
1.96 - plot_sprite(background[frame], x, y);
1.97 + plot_sprite(background[display_config.frame], x, y);
1.98
1.99 /* Record the stored background. */
1.100
1.101 - background_x[frame] = x;
1.102 - background_y[frame] = y;
1.103 - background_stored[frame] = 1;
1.104 + background_x[display_config.frame] = x;
1.105 + background_y[display_config.frame] = y;
1.106 + background_stored[display_config.frame] = 1;
1.107
1.108 /* Update the display with the frame details. */
1.109
1.110 @@ -271,13 +272,14 @@
1.111
1.112 /* Select the next frame to plot to. */
1.113
1.114 - frame = wrap_value(frame + 1, display_config.frames);
1.115 - display_select_frame(&display_config, frame);
1.116 + display_select_next_frame(&display_config);
1.117
1.118 /* Prepare the frame for updates. */
1.119
1.120 - if (background_stored[frame])
1.121 - unplot_sprite(background[frame], background_x[frame], background_y[frame]);
1.122 + if (background_stored[display_config.frame])
1.123 + unplot_sprite(background[display_config.frame],
1.124 + background_x[display_config.frame],
1.125 + background_y[display_config.frame]);
1.126
1.127 /* Scroll in the indicated direction. */
1.128
1.129 @@ -291,36 +293,11 @@
1.130 pixel increments and thus requires a two-pixel column to be
1.131 plotted per scrolling increment. */
1.132
1.133 - if (xdir)
1.134 - xorigin += xdir * SCROLL_XSTEP;
1.135 -
1.136 /* For vertically-scaled backgrounds, the full resolution image
1.137 is traversed by multiples of the scrolling increment. */
1.138
1.139 - if (ydir)
1.140 - yorigin += ydir * SOURCE_YSTEP;
1.141 -
1.142 - /* Determine the magnitude of the scrolling required from this
1.143 - frame to the current origin. */
1.144 -
1.145 - xstep = xorigin - xorigins[frame];
1.146 - ystep = yorigin - yorigins[frame];
1.147 -
1.148 - /* Scroll the frame. */
1.149 -
1.150 - display_scroll(&display_config, xstep / SCROLL_XSTEP,
1.151 - ystep / SOURCE_YSTEP);
1.152 -
1.153 - /* For horizontal scrolling, plot the exposed column at the left
1.154 - (if scrolling left) or at the right (if scrolling right). */
1.155 -
1.156 - if (xstep)
1.157 - plot_screen_edge(xorigin, yorigin, xstep);
1.158 -
1.159 - /* Record the origin for this frame. */
1.160 -
1.161 - xorigins[frame] = xorigin;
1.162 - yorigins[frame] = yorigin;
1.163 + viewport_update_origin(&v, xdir * SCROLL_XSTEP,
1.164 + ydir * SOURCE_YSTEP);
1.165 }
1.166
1.167 /* Switch direction periodically. */
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/include/viewport.h Fri Nov 09 22:50:30 2018 +0100
3.3 @@ -0,0 +1,65 @@
3.4 +/*
3.5 + * Common viewport-related functions.
3.6 + *
3.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
3.8 + *
3.9 + * This program is free software: you can redistribute it and/or modify
3.10 + * it under the terms of the GNU General Public License as published by
3.11 + * the Free Software Foundation, either version 3 of the License, or
3.12 + * (at your option) any later version.
3.13 + *
3.14 + * This program is distributed in the hope that it will be useful,
3.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.17 + * GNU General Public License for more details.
3.18 + *
3.19 + * You should have received a copy of the GNU General Public License
3.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
3.21 + */
3.22 +
3.23 +#ifndef __VIEWPORT_H__
3.24 +#define __VIEWPORT_H__
3.25 +
3.26 +#include "display.h"
3.27 +
3.28 +
3.29 +
3.30 +/* An abstraction providing a scrolling viewport. */
3.31 +
3.32 +typedef struct
3.33 +{
3.34 + /* Display configuration. */
3.35 +
3.36 + display_config_t *cfg;
3.37 +
3.38 + /* Scrolling positions for each frame. */
3.39 +
3.40 + int *xorigins, *yorigins;
3.41 +
3.42 + /* Scrolling position. */
3.43 +
3.44 + int xorigin, yorigin;
3.45 +
3.46 + /* Scaling factors, translating the origin coordinates to display columns
3.47 + and rows. */
3.48 +
3.49 + int xscale, yscale;
3.50 +
3.51 + /* Update function after scrolling. */
3.52 +
3.53 + void (*update)();
3.54 +
3.55 +} viewport_t;
3.56 +
3.57 +
3.58 +
3.59 +/* Viewport operations. */
3.60 +
3.61 +void init_viewport(viewport_t *v, display_config_t *cfg,
3.62 + int xorigins[], int yorigins[],
3.63 + int xscale, int yscale,
3.64 + void (*update)());
3.65 +
3.66 +void viewport_update_origin(viewport_t *v, int dx, int dy);
3.67 +
3.68 +#endif /* __VIEWPORT_H__ */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/lib/viewport.c Fri Nov 09 22:50:30 2018 +0100
5.3 @@ -0,0 +1,95 @@
5.4 +/*
5.5 + * Common viewport-related functions.
5.6 + *
5.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
5.8 + *
5.9 + * This program is free software: you can redistribute it and/or modify
5.10 + * it under the terms of the GNU General Public License as published by
5.11 + * the Free Software Foundation, either version 3 of the License, or
5.12 + * (at your option) any later version.
5.13 + *
5.14 + * This program is distributed in the hope that it will be useful,
5.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.17 + * GNU General Public License for more details.
5.18 + *
5.19 + * You should have received a copy of the GNU General Public License
5.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
5.21 + */
5.22 +
5.23 +#include "viewport.h"
5.24 +
5.25 +
5.26 +
5.27 +/* Initialise a viewport with display, origin, scaling and update function
5.28 + details. */
5.29 +
5.30 +void init_viewport(viewport_t *v, display_config_t *cfg,
5.31 + int xorigins[], int yorigins[],
5.32 + int xscale, int yscale,
5.33 + void (*update)())
5.34 +{
5.35 + int frame;
5.36 +
5.37 + v->cfg = cfg;
5.38 +
5.39 + /* Set the storage for the frame origin details. */
5.40 +
5.41 + v->xorigins = xorigins;
5.42 + v->yorigins = yorigins;
5.43 +
5.44 + /* Set the relationship between origin coordinates and display columns and
5.45 + rows. */
5.46 +
5.47 + v->xscale = xscale;
5.48 + v->yscale = yscale;
5.49 +
5.50 + /* Set the post-scroll update function. */
5.51 +
5.52 + v->update = update;
5.53 +
5.54 + /* Set the origin to (0, 0) for every frame. */
5.55 +
5.56 + v->xorigin = 0;
5.57 + v->yorigin = 0;
5.58 +
5.59 + for (frame = 0; frame < cfg->frames; frame++)
5.60 + {
5.61 + v->xorigins[frame] = 0;
5.62 + v->yorigins[frame] = 0;
5.63 + }
5.64 +}
5.65 +
5.66 +/* Update the origin by the given changes in origin coordinates. */
5.67 +
5.68 +void viewport_update_origin(viewport_t *v, int dx, int dy)
5.69 +{
5.70 + int xstep, ystep;
5.71 + int frame = v->cfg->frame;
5.72 +
5.73 + /* Change the origin coordinates. */
5.74 +
5.75 + v->xorigin += dx;
5.76 + v->yorigin += dy;
5.77 +
5.78 + /* Determine the magnitude of the scrolling required from this frame to the
5.79 + current origin. */
5.80 +
5.81 + xstep = v->xorigin - v->xorigins[frame];
5.82 + ystep = v->yorigin - v->yorigins[frame];
5.83 +
5.84 + /* Scroll the frame, converting to columns and rows. */
5.85 +
5.86 + display_scroll(v->cfg, xstep / v->xscale, ystep / v->yscale);
5.87 +
5.88 + /* For horizontal scrolling, plot the exposed column at the left (if
5.89 + scrolling left) or at the right (if scrolling right). */
5.90 +
5.91 + if (v->update)
5.92 + v->update(v, v->xorigin, v->yorigin, xstep, ystep);
5.93 +
5.94 + /* Record the origin for this frame. */
5.95 +
5.96 + v->xorigins[frame] = v->xorigin;
5.97 + v->yorigins[frame] = v->yorigin;
5.98 +}