source: mainline/uspace/app/tetris/screen.c@ 902f0906

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 902f0906 was 07b7c48, checked in by Jiri Svoboda <jiri@…>, 12 years ago

Extend console library API to support different event types.

  • Property mode set to 100644
File size: 8.0 KB
RevLine 
[79ae36dd]1/*
2 * Copyright (c) 2011 Martin Decky
3 * All rights reserved.
[e9a3c52]4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
[79ae36dd]9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** Attributations
30 *
31 * screen.c 8.1 (Berkeley) 5/31/93
32 * NetBSD: screen.c,v 1.4 1995/04/29 01:11:36 mycroft
33 * OpenBSD: screen.c,v 1.13 2006/04/20 03:25:36 ray
34 *
35 * Based upon BSD Tetris
36 *
37 * Copyright (c) 1992, 1993
38 * The Regents of the University of California.
39 * Distributed under BSD license.
40 *
41 * This code is derived from software contributed to Berkeley by
42 * Chris Torek and Darren F. Provine.
[e9a3c52]43 *
44 */
45
[b2951e2]46/** @addtogroup tetris
[ebe70f1]47 * @{
[b2951e2]48 */
49/** @file
50 */
51
[e9a3c52]52/*
53 * Tetris screen control.
54 */
55
56#include <err.h>
57#include <stdio.h>
58#include <stdlib.h>
[19f857a]59#include <str.h>
[e9a3c52]60#include <unistd.h>
[0c25c10]61#include <vfs/vfs.h>
[f1b4e74]62#include <async.h>
[3e6a98c5]63#include <stdbool.h>
[9f1362d4]64#include <io/console.h>
65#include <io/style.h>
[e9a3c52]66#include "screen.h"
67#include "tetris.h"
68
[ebe70f1]69#define STOP (B_COLS - 3)
70
71static cell curscreen[B_SIZE]; /* non-zero => standout (or otherwise marked) */
[e9a3c52]72static int curscore;
[ebe70f1]73static int isset; /* true => terminal is in game mode */
74
[9f1362d4]75static bool use_color; /* true => use colors */
[50cfa6c]76
[ebe70f1]77static const struct shape *lastshape;
[f1b4e74]78
[79ae36dd]79static suseconds_t timeleft = 0;
80
81console_ctrl_t *console;
82
[f1b4e74]83
[e9a3c52]84/*
[f1b4e74]85 * putstr() is for unpadded strings (either as in termcap(5) or
[0c25c10]86 * simply literal strings);
[e9a3c52]87 */
[a000878c]88static inline void putstr(const char *s)
[59ed572]89{
90 while (*s)
91 putchar(*(s++));
92}
[e9a3c52]93
[ebe70f1]94static void start_standout(uint32_t color)
[e9a3c52]95{
[79ae36dd]96 console_flush(console);
[7c014d1]97 console_set_rgb_color(console, use_color ? color : 0x000000,
98 0xffffff);
[f1b4e74]99}
[e9a3c52]100
[f1b4e74]101static void resume_normal(void)
102{
[79ae36dd]103 console_flush(console);
104 console_set_style(console, STYLE_NORMAL);
[e9a3c52]105}
106
[9996ed5]107void clear_screen(void)
108{
[79ae36dd]109 console_clear(console);
[0cc4313]110 moveto(0, 0);
[9996ed5]111}
112
[e9a3c52]113/*
[f1b4e74]114 * Clear the screen, forgetting the current contents in the process.
[e9a3c52]115 */
[ebe70f1]116void scr_clear(void)
[f1b4e74]117{
[d6cc453]118 resume_normal();
[79ae36dd]119 console_clear(console);
[f1b4e74]120 curscore = -1;
[ebe70f1]121 memset(curscreen, 0, sizeof(curscreen));
[f1b4e74]122}
[b917098]123
[e9a3c52]124/*
[f1b4e74]125 * Set up screen
[e9a3c52]126 */
[ebe70f1]127void scr_init(void)
[e9a3c52]128{
[79ae36dd]129 console_cursor_visibility(console, 0);
[f1b4e74]130 resume_normal();
131 scr_clear();
[e9a3c52]132}
133
[96b02eb9]134void moveto(sysarg_t r, sysarg_t c)
[f1b4e74]135{
[79ae36dd]136 console_flush(console);
137 console_set_pos(console, c, r);
[f1b4e74]138}
139
[9996ed5]140winsize_t winsize;
[f1b4e74]141
[9996ed5]142static int get_display_size(winsize_t *ws)
[f1b4e74]143{
[79ae36dd]144 return console_get_size(console, &ws->ws_col, &ws->ws_row);
[f1b4e74]145}
[e9a3c52]146
[9f1362d4]147static bool get_display_color_sup(void)
[50cfa6c]148{
[96b02eb9]149 sysarg_t ccap;
[79ae36dd]150 int rc = console_get_color_cap(console, &ccap);
[9f1362d4]151
[50cfa6c]152 if (rc != 0)
[9f1362d4]153 return false;
154
[7c014d1]155 return ((ccap & CONSOLE_CAP_RGB) == CONSOLE_CAP_RGB);
[50cfa6c]156}
157
[e9a3c52]158/*
159 * Set up screen mode.
160 */
[ebe70f1]161void scr_set(void)
[e9a3c52]162{
[9996ed5]163 winsize_t ws;
[ebe70f1]164
165 Rows = 0;
166 Cols = 0;
167
[f1b4e74]168 if (get_display_size(&ws) == 0) {
[e9a3c52]169 Rows = ws.ws_row;
170 Cols = ws.ws_col;
171 }
[50cfa6c]172
173 use_color = get_display_color_sup();
[ebe70f1]174
175 if ((Rows < MINROWS) || (Cols < MINCOLS)) {
[e9a3c52]176 char smallscr[55];
[ebe70f1]177
[86029498]178 snprintf(smallscr, sizeof(smallscr),
[e9a3c52]179 "the screen is too small (must be at least %dx%d)",
180 MINROWS, MINCOLS);
181 stop(smallscr);
182 }
183 isset = 1;
[ebe70f1]184
[e9a3c52]185 scr_clear();
186}
187
188/*
189 * End screen mode.
190 */
[ebe70f1]191void scr_end(void)
[e9a3c52]192{
[79ae36dd]193 console_cursor_visibility(console, 1);
[e9a3c52]194}
195
[a000878c]196void stop(const char *why)
[e9a3c52]197{
198 if (isset)
199 scr_end();
[ebe70f1]200
[e9a3c52]201 errx(1, "aborting: %s", why);
202}
203
204/*
205 * Update the screen.
206 */
[ebe70f1]207void scr_update(void)
[e9a3c52]208{
[ebe70f1]209 cell *bp;
210 cell *sp;
211 cell so;
212 cell cur_so = 0;
213 int i;
214 int j;
215 int ccol;
216
217 /* Always leave cursor after last displayed point */
[e9a3c52]218 curscreen[D_LAST * B_COLS - 1] = -1;
[ebe70f1]219
[e9a3c52]220 if (score != curscore) {
[f1b4e74]221 moveto(0, 0);
[86029498]222 printf("Score: %d", score);
[e9a3c52]223 curscore = score;
224 }
[ebe70f1]225
226 /* Draw preview of next pattern */
227 if ((showpreview) && (nextshape != lastshape)) {
[e9a3c52]228 int i;
[ebe70f1]229 static int r = 5, c = 2;
[e9a3c52]230 int tr, tc, t;
[ebe70f1]231
[e9a3c52]232 lastshape = nextshape;
[ebe70f1]233
234 /* Clean */
[f1b4e74]235 resume_normal();
[ebe70f1]236 moveto(r - 1, c - 1);
237 putstr(" ");
238 moveto(r, c - 1);
239 putstr(" ");
240 moveto(r + 1, c - 1);
241 putstr(" ");
242 moveto(r + 2, c - 1);
243 putstr(" ");
244
245 moveto(r - 3, c - 2);
[e9a3c52]246 putstr("Next shape:");
[ebe70f1]247
248 /* Draw */
249 start_standout(nextshape->color);
[e9a3c52]250 moveto(r, 2 * c);
[f1b4e74]251 putstr(" ");
[e9a3c52]252 for (i = 0; i < 3; i++) {
253 t = c + r * B_COLS;
254 t += nextshape->off[i];
[ebe70f1]255
[e9a3c52]256 tr = t / B_COLS;
257 tc = t % B_COLS;
[ebe70f1]258
[e9a3c52]259 moveto(tr, 2*tc);
[f1b4e74]260 putstr(" ");
[e9a3c52]261 }
[f1b4e74]262 resume_normal();
[e9a3c52]263 }
[ebe70f1]264
[e9a3c52]265 bp = &board[D_FIRST * B_COLS];
266 sp = &curscreen[D_FIRST * B_COLS];
267 for (j = D_FIRST; j < D_LAST; j++) {
268 ccol = -1;
269 for (i = 0; i < B_COLS; bp++, sp++, i++) {
270 if (*sp == (so = *bp))
271 continue;
[ebe70f1]272
[e9a3c52]273 *sp = so;
274 if (i != ccol) {
[86029498]275 if (cur_so) {
276 resume_normal();
277 cur_so = 0;
278 }
[e9a3c52]279 moveto(RTOD(j), CTOD(i));
280 }
[ebe70f1]281
[f1b4e74]282 if (so != cur_so) {
283 if (so)
[ebe70f1]284 start_standout(so);
[f1b4e74]285 else
286 resume_normal();
287 cur_so = so;
288 }
289 putstr(" ");
[ebe70f1]290
[e9a3c52]291 ccol = i + 1;
292 /*
293 * Look ahead a bit, to avoid extra motion if
294 * we will be redrawing the cell after the next.
295 * Motion probably takes four or more characters,
296 * so we save even if we rewrite two cells
297 * `unnecessarily'. Skip it all, though, if
298 * the next cell is a different color.
299 */
[ebe70f1]300
301 if ((i > STOP) || (sp[1] != bp[1]) || (so != bp[1]))
[e9a3c52]302 continue;
[ebe70f1]303
[e9a3c52]304 if (sp[2] != bp[2])
305 sp[1] = -1;
[ebe70f1]306 else if ((i < STOP) && (so == bp[2]) && (sp[3] != bp[3])) {
[e9a3c52]307 sp[2] = -1;
308 sp[1] = -1;
309 }
310 }
311 }
[ebe70f1]312
[86029498]313 if (cur_so)
314 resume_normal();
[ebe70f1]315
[79ae36dd]316 console_flush(console);
[e9a3c52]317}
318
319/*
[ebe70f1]320 * Write a message (set != 0), or clear the same message (set == 0).
[e9a3c52]321 * (We need its length in case we have to overwrite with blanks.)
322 */
[9f1362d4]323void scr_msg(char *s, bool set)
[e9a3c52]324{
[92fd52d7]325 int l = str_size(s);
[d6cc453]326
327 moveto(Rows - 2, ((Cols - l) >> 1) - 1);
[ebe70f1]328
[d6cc453]329 if (set)
330 putstr(s);
331 else
332 while (--l >= 0)
333 (void) putchar(' ');
[e9a3c52]334}
[b2951e2]335
[79ae36dd]336/** Sleep for the current turn time
337 *
338 * Eat any input that might be available.
339 *
340 */
341void tsleep(void)
342{
343 suseconds_t timeout = fallrate;
344
345 while (timeout > 0) {
[07b7c48]346 cons_event_t event;
[79ae36dd]347
[07b7c48]348 if (!console_get_event_timeout(console, &event, &timeout))
[79ae36dd]349 break;
350 }
351}
352
353/** Get char with timeout
354 *
355 */
356int tgetchar(void)
357{
358 /*
359 * Reset timeleft to fallrate whenever it is not positive
360 * and increase speed.
361 */
362
363 if (timeleft <= 0) {
364 faster();
365 timeleft = fallrate;
366 }
367
368 /*
369 * Wait to see if there is any input. If so, take it and
370 * update timeleft so that the next call to tgetchar()
371 * will not wait as long. If there is no input,
372 * make timeleft zero and return -1.
373 */
374
375 wchar_t c = 0;
376
377 while (c == 0) {
[07b7c48]378 cons_event_t event;
[79ae36dd]379
[07b7c48]380 if (!console_get_event_timeout(console, &event, &timeleft)) {
[79ae36dd]381 timeleft = 0;
382 return -1;
383 }
384
[07b7c48]385 if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS)
386 c = event.ev.key.c;
[79ae36dd]387 }
388
389 return (int) c;
390}
391
392/** Get char without timeout
393 *
394 */
395int twait(void)
396{
397 wchar_t c = 0;
398
399 while (c == 0) {
[07b7c48]400 cons_event_t event;
[79ae36dd]401
[07b7c48]402 if (!console_get_event(console, &event))
[79ae36dd]403 return -1;
404
[07b7c48]405 if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS)
406 c = event.ev.key.c;
[79ae36dd]407 }
408
409 return (int) c;
410}
411
[b2951e2]412/** @}
413 */
Note: See TracBrowser for help on using the repository browser.