aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2018-09-03 21:49:12 -0700
committerH. Peter Anvin <hpa@zytor.com>2018-09-03 21:49:12 -0700
commit3bbec528eb74d0ed0f5b3d3c5803cbf81de2aaba (patch)
tree2a8ce2f772114ca7aea73752bd4424eaf7266a47
parent09ab098f1647b48f97d6cb948c4685a1cefa7aa1 (diff)
downloadgrv-3bbec528eb74d0ed0f5b3d3c5803cbf81de2aaba.tar.gz
grv-3bbec528eb74d0ed0f5b3d3c5803cbf81de2aaba.tar.xz
grv-3bbec528eb74d0ed0f5b3d3c5803cbf81de2aaba.zip
Render the screen at native resolution
Use the current desktop resolution for the screen canvas instead of switching display modes. Many modern monitors don't handle it well, and this way we get a colored border instead of strange aspect ratios. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--graphics.c143
-rw-r--r--grv.c13
-rw-r--r--grv.h1
-rw-r--r--highscore.c6
-rw-r--r--intro.c3
-rw-r--r--scoretbl.c4
-rw-r--r--utils.c2
7 files changed, 131 insertions, 41 deletions
diff --git a/graphics.c b/graphics.c
index 123effb..d0728c9 100644
--- a/graphics.c
+++ b/graphics.c
@@ -66,6 +66,13 @@ static struct current_screen {
uint8_t dwidth; /* Double width characters, must be 0 or 1 */
} current = {0, 0, 7, 1}; /* Current screen parameters */
+static struct video_mode {
+ int scale; /* Scaling factor */
+ int xoffs; /* width of left border */
+ int yoffs; /* height of top border */
+ char *bufstart; /* upper left corner of non-border */
+} vm;
+
static SDL_Surface *rscreen;
static volatile uint8_t blink_mask = 0;
@@ -76,6 +83,10 @@ static volatile uint8_t blink_mask = 0;
void color(int fg, int bg)
{
current.attr = (fg & 15) | ((bg & 7) << 4) | ((fg & 16) << 3);
+ if (opt.debug) {
+ fprintf(stderr, "color(%d,%d) -> current.attr = %02x\n",
+ fg, bg, current.attr);
+ }
}
/*
@@ -135,6 +146,9 @@ void update_screen(void)
int x, x0, y, y0;
int n = 0;
+ if (opt.debug)
+ fprintf(stderr, "update_screen():\n");
+
for (y = 0; y < TS_HEIGHT; y++) {
for (x = 0; x < TS_WIDTH; x++) {
if (screendirty[y][x]) {
@@ -145,26 +159,29 @@ void update_screen(void)
screendirty[y][x] = 0;
x++;
}
-
+
/* See if we can expand this rectangle vertically */
while (++y < TS_HEIGHT) {
int x1;
for (x1 = x0; x1 < x; x1++)
if (!screendirty[y][x1])
goto done;
-
+
/* It worked... */
for (x1 = x0; x1 < x; x1++)
screendirty[y][x1] = 0;
}
done:
- r->x = x0 * FONT_XSIZE;
- r->y = y0 * FONT_YSIZE;
- r->w = (x - x0) * FONT_XSIZE;
- r->h = (y - y0) * FONT_YSIZE;
+ r->x = vm.xoffs + x0 * vm.scale * FONT_XSIZE;
+ r->y = vm.yoffs + y0 * vm.scale * FONT_YSIZE;
+ r->w = (x - x0) * vm.scale * FONT_XSIZE;
+ r->h = (y - y0) * vm.scale * FONT_YSIZE;
+ if (opt.debug) {
+ fprintf(stderr, " (%d:%d,%d:%d) -> rect(%d,%d) size (%d,%d)\n",
+ x0, x, y0, y, r->x, r->y, r->w, r->h);
+ }
r++;
n++;
-
y = y0;
x--;
}
@@ -187,9 +204,10 @@ static void put_screen(int tx, int ty)
font_t *fontp;
font_t v;
uint32_t *pixelp, *pixelr, fgp, bgp;
- int x, y, z;
+ int x, y, xp, yp;
int attr;
- int pxwid = current.dwidth + 1;
+ int pxw = vm.scale << current.dwidth;
+ int pxh = vm.scale;
int bmask = blink_mask;
attr = screendata[ty][tx].attr;
@@ -202,23 +220,26 @@ static void put_screen(int tx, int ty)
* This assumes that either unaligned references are okay, or
* pitch will be a multiple of 4.
*/
- pixelr = ((uint32_t *) ((char *)rscreen->pixels +
- ty*FONT_YSIZE*rscreen->pitch)) +
- tx*FONT_XSIZE;
+ pixelr = ((uint32_t *) (vm.bufstart
+ + ty*vm.scale*FONT_YSIZE*rscreen->pitch)) +
+ tx*vm.scale*FONT_XSIZE;
for ( y = 0 ; y < FONT_YSIZE ; y++ ) {
- pixelp = pixelr;
- v = fontp[y];
- for ( x = 0 ; x < FONT_XSIZE ; x++ ) {
- for ( z = 0 ; z < pxwid ; z++ )
- *pixelp++ = v & ((font_t)1 << (FONT_XSIZE-1)) ? fgp : bgp;
- v <<= 1;
+ for ( yp = 0 ; yp < pxh ; yp++ ) {
+ pixelp = pixelr;
+ v = fontp[y];
+ for ( x = 0 ; x < FONT_XSIZE ; x++ ) {
+ Uint32 pixel = v & ((font_t)1 << (FONT_XSIZE-1)) ? fgp : bgp;
+ v <<= 1;
+ for ( xp = 0 ; xp < pxw ; xp++ )
+ *pixelp++ = pixel;
+ }
+ pixelr = (uint32_t *)((char *)pixelr + rscreen->pitch);
}
- pixelr = (uint32_t *)((char *)pixelr + rscreen->pitch);
}
screendirty[ty][tx] = 1;
- screendirty[ty][tx+pxwid-1] = 1;
+ screendirty[ty][tx+current.dwidth] = 1;
}
/*
@@ -345,7 +366,8 @@ void width(int wid)
/*
* Clear the screen, set all characters to ' ' and set all pixels to the
- * current background, then refresh the screen content.
+ * current background, then refresh the screen content including the
+ * border.
*/
void cls(void)
{
@@ -357,6 +379,9 @@ void cls(void)
lock_screen();
+ if (opt.debug)
+ fprintf(stderr, "cls with attr %02x\n", current.attr);
+
empty.sym = ' ';
empty.attr = current.attr;
@@ -366,13 +391,18 @@ void cls(void)
*scp++ = empty;
rect.x = rect.y = 0;
- rect.w = PX_WIDTH;
- rect.h = PX_HEIGHT;
+ rect.w = rscreen->w;
+ rect.h = rscreen->h;
SDL_FillRect(rscreen, &rect, pixelval);
unlock_screen();
+ if (opt.debug) {
+ fprintf(stderr, "x = %d, y = %d, w = %d, h = %d\n",
+ rect.x, rect.y, rect.w, rect.h);
+ }
+
SDL_UpdateRects(rscreen, 1, &rect);
memset(screendirty, 0, sizeof screendirty);
@@ -424,11 +454,48 @@ void restore_screen(struct saved_screen *save)
}
/*
+ * Compute scaling factors and frame
+ */
+static int configure_screen(void)
+{
+ int i;
+
+ /* Convert colors to preferred machine representation */
+ for ( i = 0 ; i < NCOLORS ; i++ ) {
+ colors[i] = SDL_MapRGB(rscreen->format,
+ rgbcolors[i].r, rgbcolors[i].g, rgbcolors[i].b);
+ }
+
+ /* Set up scaling factor etc. */
+
+ vm.scale = min(rscreen->w/PX_WIDTH, rscreen->h/PX_HEIGHT);
+ vm.xoffs = (rscreen->w - vm.scale*PX_WIDTH) >> 1;
+ vm.yoffs = (rscreen->h - vm.scale*PX_HEIGHT) >> 1;
+
+ vm.bufstart = (char *)rscreen->pixels
+ + vm.yoffs*rscreen->pitch
+ + vm.xoffs*sizeof(Uint32);
+
+ if (opt.debug) {
+ fprintf(stderr,
+ "rscreen->w = %d\n"
+ "rscreen->h = %d\n"
+ "vm.scale = %d\n"
+ "vm.xoffs = %d\n"
+ "vm.yoffs = %d\n",
+ rscreen->w, rscreen->h, vm.scale, vm.xoffs, vm.yoffs);
+ }
+
+ return vm.scale;
+}
+
+/*
* Initialize SDL and the data structures
*/
int screen_init(int window)
{
- int i;
+ int xpix, ypix;
+ Uint32 flags;
if ( SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO
| (opt.debug ? SDL_INIT_NOPARACHUTE : 0)) )
@@ -436,20 +503,32 @@ int screen_init(int window)
atexit(SDL_Quit);
- if ( !(rscreen = SDL_SetVideoMode(PX_WIDTH, PX_HEIGHT, 32,
- SDL_SWSURFACE | (window ? 0 : SDL_FULLSCREEN))) ) {
- return -1;
+ if ( window ) {
+ xpix = (PX_WIDTH + 4*FONT_XSIZE) * window;
+ ypix = (PX_HEIGHT + 2*FONT_YSIZE) * window;
+ flags = SDL_SWSURFACE;
+ } else {
+ /* full screen */
+ const SDL_VideoInfo *vi = SDL_GetVideoInfo();
+
+ if ( !vi )
+ return -1;
+
+ xpix = vi->current_w;
+ ypix = vi->current_h;
+ flags = SDL_FULLSCREEN | SDL_SWSURFACE;
}
+ rscreen = SDL_SetVideoMode(xpix, ypix, 32, flags);
+ if ( !rscreen )
+ return -1;
+
/* No mouse cursor, please */
if ( !window )
SDL_ShowCursor(SDL_DISABLE);
- /* Convert colors to preferred machine representation */
- for ( i = 0 ; i < NCOLORS ; i++ ) {
- colors[i] = SDL_MapRGB(rscreen->format,
- rgbcolors[i].r, rgbcolors[i].g, rgbcolors[i].b);
- }
+ if ( configure_screen() < 1 )
+ return -1;
cls();
diff --git a/grv.c b/grv.c
index 1a1476e..b4fd7ee 100644
--- a/grv.c
+++ b/grv.c
@@ -36,6 +36,10 @@ void init_gameparams(void)
void initscreen(int w)
{
+ if (opt.debug) {
+ fprintf(stderr, "initscreen(%d), gp.c = %d\n", w, gp.c);
+ }
+
width(w);
color(0,gp.c);
cls();
@@ -119,9 +123,12 @@ int main(int argc, char *argv[])
if ( !strcmp(argv[i], "-nonet") ||
!strcmp(argv[i], "-no-net") )
opt.nonet = 1;
- else if ( !strcmp(argv[i], "-window") )
- opt.window = 1;
- else if ( !strcmp(argv[i], "-debug") )
+ else if ( !strncmp(argv[i], "-window", 7) ) {
+ const char *p = argv[i] + 7;
+ opt.window++;
+ while ( *p++ == '+' )
+ opt.window++;
+ } else if ( !strcmp(argv[i], "-debug") )
opt.debug = 1;
}
diff --git a/grv.h b/grv.h
index e8391f0..9db797c 100644
--- a/grv.h
+++ b/grv.h
@@ -3,6 +3,7 @@
#include <inttypes.h>
#include <stddef.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
diff --git a/highscore.c b/highscore.c
index 9c52374..f47eeaf 100644
--- a/highscore.c
+++ b/highscore.c
@@ -51,7 +51,7 @@ void highscore_download(void)
void highscore_save(void)
{
FILE *f;
-
+
f = fopen(score_file, "w");
if ( !f )
return;
@@ -67,11 +67,11 @@ void highscore_upload(void)
if ( opt.nonet )
return;
-
+
if ( !have_upload_scores() )
return;
-
+
n = fopen_network(score_server, score_ul_port, 1);
if ( !n )
return;
diff --git a/intro.c b/intro.c
index d3ff31a..c0eea7e 100644
--- a/intro.c
+++ b/intro.c
@@ -9,6 +9,9 @@
void intro(void)
{
+ if (opt.debug)
+ fprintf(stderr, "intro()\n");
+
gp.c = 1;
gp.c2 = 6;
diff --git a/scoretbl.c b/scoretbl.c
index 2d62160..f04d40e 100644
--- a/scoretbl.c
+++ b/scoretbl.c
@@ -208,7 +208,7 @@ void highscore_parse(FILE *f, uint8_t upload)
*/
int highscore_write(FILE *f, uint8_t leave)
{
- char buffer[MAXLINE];
+ char buffer[MAXLINE*2];
int i, j;
fputs("VC 1.0\n", f); /* Version C 1.0 */
@@ -263,6 +263,6 @@ int have_upload_scores(void)
if ( bests.level[i].score[j].upload ||
bests.level[i].time_ms[j].upload )
return 1;
-
+
return 0;
}
diff --git a/utils.c b/utils.c
index 4b3b94b..5e98cc5 100644
--- a/utils.c
+++ b/utils.c
@@ -28,7 +28,7 @@ int busy(int r, int c)
/* Format time elapsed in MM:SS.s format */
char *format_time(double t)
{
- static char ts[10];
+ static char ts[32];
int ds = (int)(t*10.0); /* Deciseconds */
sprintf(ts, "%02d:%02d.%01d", ds/600, (ds%600)/10, ds%10);