# HG changeset patch # User Paul Boddie # Date 1541800230 -3600 # Node ID 9e84b8d477a3cf4af12ebf3d1a8c76bc3dbf26fb # Parent bfe765ff97e0520cbffc0aab8b458ede9834cd02 Introduced a viewport abstraction to simplify the example program. diff -r bfe765ff97e0 -r 9e84b8d477a3 examples/vga/main.c --- a/examples/vga/main.c Fri Nov 09 21:05:06 2018 +0100 +++ b/examples/vga/main.c Fri Nov 09 22:50:30 2018 +0100 @@ -25,6 +25,7 @@ #include "pic32_c.h" #include "utils.h" #include "vga_display.h" +#include "viewport.h" /* Specific functionality. */ @@ -93,6 +94,10 @@ uint8_t *screen_starts[FRAME_COUNT]; +/* Origin details for the viewport. */ + +int xorigins[FRAME_COUNT], yorigins[FRAME_COUNT]; + /* Bundled image and font data. */ @@ -133,7 +138,8 @@ /* Plot the revealed region at the edge of the screen after scrolling. */ -static void plot_screen_edge(int xorigin, int yorigin, int xstep) +static void plot_screen_edge(viewport_t *v, int xorigin, int yorigin, + int xstep, int ystep) { /* Determine positions within the image. */ @@ -169,7 +175,7 @@ screendata_width, screendata_height, xsource, ypos, width, screendata_height - ypos, - SOURCE_YSTEP, + v->yscale, xdisplay, 0, -1, 1); @@ -183,8 +189,8 @@ screendata_width, screendata_height, xsource, 0, width, ypos, - SOURCE_YSTEP, - xdisplay, (screendata_height - ypos) / SOURCE_YSTEP, + v->yscale, + xdisplay, (screendata_height - ypos) / v->yscale, -1, 1); /* Get the next slice of the column. */ @@ -223,30 +229,25 @@ int dir[] = {1, 0, -1, 0, 1}; int dirindex = 0; - /* Scrolling position. */ + /* Scroll increments. */ - int xorigin = 0, yorigin = 0; - - /* Scrolling positions for each frame. */ + int xdir, ydir; - int xorigins[FRAME_COUNT], yorigins[FRAME_COUNT]; - - /* Scroll increments and replotted column details. */ + /* Scrolling viewport. */ - int xdir, ydir, xstep, ystep; + viewport_t v; - /* Current frame being accessed. */ + /* Initialise the backing stores. */ int frame; for (frame = 0; frame < display_config.frames; frame++) - { background_stored[frame] = 0; - xorigins[frame] = xorigin; - yorigins[frame] = yorigin; - } + + /* Initialise the viewport. */ - frame = display_config.frame; + init_viewport(&v, &display_config, xorigins, yorigins, + SCROLL_XSTEP, SOURCE_YSTEP, plot_screen_edge); /* Animation loop. */ @@ -256,13 +257,13 @@ { for (x = 0; x < display_config.line_length - sprite_width; x++) { - plot_sprite(background[frame], x, y); + plot_sprite(background[display_config.frame], x, y); /* Record the stored background. */ - background_x[frame] = x; - background_y[frame] = y; - background_stored[frame] = 1; + background_x[display_config.frame] = x; + background_y[display_config.frame] = y; + background_stored[display_config.frame] = 1; /* Update the display with the frame details. */ @@ -271,13 +272,14 @@ /* Select the next frame to plot to. */ - frame = wrap_value(frame + 1, display_config.frames); - display_select_frame(&display_config, frame); + display_select_next_frame(&display_config); /* Prepare the frame for updates. */ - if (background_stored[frame]) - unplot_sprite(background[frame], background_x[frame], background_y[frame]); + if (background_stored[display_config.frame]) + unplot_sprite(background[display_config.frame], + background_x[display_config.frame], + background_y[display_config.frame]); /* Scroll in the indicated direction. */ @@ -291,36 +293,11 @@ pixel increments and thus requires a two-pixel column to be 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; - - /* Determine the magnitude of the scrolling required from this - frame to the current origin. */ - - xstep = xorigin - xorigins[frame]; - ystep = yorigin - yorigins[frame]; - - /* Scroll the frame. */ - - display_scroll(&display_config, xstep / SCROLL_XSTEP, - ystep / SOURCE_YSTEP); - - /* For horizontal scrolling, plot the exposed column at the left - (if scrolling left) or at the right (if scrolling right). */ - - if (xstep) - plot_screen_edge(xorigin, yorigin, xstep); - - /* Record the origin for this frame. */ - - xorigins[frame] = xorigin; - yorigins[frame] = yorigin; + viewport_update_origin(&v, xdir * SCROLL_XSTEP, + ydir * SOURCE_YSTEP); } /* Switch direction periodically. */ diff -r bfe765ff97e0 -r 9e84b8d477a3 include/display.h --- a/include/display.h Fri Nov 09 21:05:06 2018 +0100 +++ b/include/display.h Fri Nov 09 22:50:30 2018 +0100 @@ -106,6 +106,8 @@ void display_select_frame(display_config_t *cfg, int frame); +void display_select_next_frame(display_config_t *cfg); + void display_set_frames(display_config_t *cfg, int frames); uint8_t *display_get_frame_start(display_config_t *cfg, int frame); diff -r bfe765ff97e0 -r 9e84b8d477a3 include/viewport.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/viewport.h Fri Nov 09 22:50:30 2018 +0100 @@ -0,0 +1,65 @@ +/* + * Common viewport-related functions. + * + * Copyright (C) 2018 Paul Boddie + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __VIEWPORT_H__ +#define __VIEWPORT_H__ + +#include "display.h" + + + +/* An abstraction providing a scrolling viewport. */ + +typedef struct +{ + /* Display configuration. */ + + display_config_t *cfg; + + /* Scrolling positions for each frame. */ + + int *xorigins, *yorigins; + + /* Scrolling position. */ + + int xorigin, yorigin; + + /* Scaling factors, translating the origin coordinates to display columns + and rows. */ + + int xscale, yscale; + + /* Update function after scrolling. */ + + void (*update)(); + +} viewport_t; + + + +/* Viewport operations. */ + +void init_viewport(viewport_t *v, display_config_t *cfg, + int xorigins[], int yorigins[], + int xscale, int yscale, + void (*update)()); + +void viewport_update_origin(viewport_t *v, int dx, int dy); + +#endif /* __VIEWPORT_H__ */ diff -r bfe765ff97e0 -r 9e84b8d477a3 lib/display.c --- a/lib/display.c Fri Nov 09 21:05:06 2018 +0100 +++ b/lib/display.c Fri Nov 09 22:50:30 2018 +0100 @@ -117,6 +117,13 @@ init_display_properties(cfg); } +/* Select the next available frame in the framebuffer. */ + +void display_select_next_frame(display_config_t *cfg) +{ + display_select_frame(cfg, wrap_value(cfg->frame + 1, cfg->frames)); +} + /* Set the number of frames in the framebuffer memory. */ void display_set_frames(display_config_t *cfg, int frames) diff -r bfe765ff97e0 -r 9e84b8d477a3 lib/viewport.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/viewport.c Fri Nov 09 22:50:30 2018 +0100 @@ -0,0 +1,95 @@ +/* + * Common viewport-related functions. + * + * Copyright (C) 2018 Paul Boddie + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "viewport.h" + + + +/* Initialise a viewport with display, origin, scaling and update function + details. */ + +void init_viewport(viewport_t *v, display_config_t *cfg, + int xorigins[], int yorigins[], + int xscale, int yscale, + void (*update)()) +{ + int frame; + + v->cfg = cfg; + + /* Set the storage for the frame origin details. */ + + v->xorigins = xorigins; + v->yorigins = yorigins; + + /* Set the relationship between origin coordinates and display columns and + rows. */ + + v->xscale = xscale; + v->yscale = yscale; + + /* Set the post-scroll update function. */ + + v->update = update; + + /* Set the origin to (0, 0) for every frame. */ + + v->xorigin = 0; + v->yorigin = 0; + + for (frame = 0; frame < cfg->frames; frame++) + { + v->xorigins[frame] = 0; + v->yorigins[frame] = 0; + } +} + +/* Update the origin by the given changes in origin coordinates. */ + +void viewport_update_origin(viewport_t *v, int dx, int dy) +{ + int xstep, ystep; + int frame = v->cfg->frame; + + /* Change the origin coordinates. */ + + v->xorigin += dx; + v->yorigin += dy; + + /* Determine the magnitude of the scrolling required from this frame to the + current origin. */ + + xstep = v->xorigin - v->xorigins[frame]; + ystep = v->yorigin - v->yorigins[frame]; + + /* Scroll the frame, converting to columns and rows. */ + + display_scroll(v->cfg, xstep / v->xscale, ystep / v->yscale); + + /* For horizontal scrolling, plot the exposed column at the left (if + scrolling left) or at the right (if scrolling right). */ + + if (v->update) + v->update(v, v->xorigin, v->yorigin, xstep, ystep); + + /* Record the origin for this frame. */ + + v->xorigins[frame] = v->xorigin; + v->yorigins[frame] = v->yorigin; +} diff -r bfe765ff97e0 -r 9e84b8d477a3 mk/common.mk --- a/mk/common.mk Fri Nov 09 21:05:06 2018 +0100 +++ b/mk/common.mk Fri Nov 09 22:50:30 2018 +0100 @@ -52,8 +52,8 @@ COMMON_SRC = $(LIBDIR)/payload.c $(LIBDIR)/init.c $(LIBDIR)/debug.c $(LIBDIR)/utils.c $(LIBDIR)/cpu.S COMMON_OBJ = $(LIBDIR)/payload.o $(LIBDIR)/init.o $(LIBDIR)/debug.o $(LIBDIR)/utils.o $(LIBDIR)/cpu.o -DISPLAY_COMMON_SRC = $(LIBDIR)/display.c $(LIBDIR)/font.c -DISPLAY_COMMON_OBJ = $(LIBDIR)/display.o $(LIBDIR)/font.o +DISPLAY_COMMON_SRC = $(LIBDIR)/display.c $(LIBDIR)/font.c $(LIBDIR)/viewport.c +DISPLAY_COMMON_OBJ = $(LIBDIR)/display.o $(LIBDIR)/font.o $(LIBDIR)/viewport.o DISPLAY_SRC = $(DISPLAY_COMMON_SRC) $(LIBDIR)/vga_display.c DISPLAY_OBJ = $(DISPLAY_COMMON_OBJ) $(LIBDIR)/vga_display.o