source: mainline/uspace/app/tetris/screen.c@ e540bc87

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e540bc87 was 582a0b8, checked in by Jakub Jermar <jakub@…>, 8 years ago

Remove unistd.h

  • Rename usleep() and sleep() to thread_usleep() and thread_sleep() and move to thread.[hc].
  • Include stddef.h in order to provide NULL.
  • Move getpagesize() to libposix.
  • Sync uspace/dist/src/c/demos with originals.
  • 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>
[0c25c10]60#include <vfs/vfs.h>
[f1b4e74]61#include <async.h>
[3e6a98c5]62#include <stdbool.h>
[9f1362d4]63#include <io/console.h>
64#include <io/style.h>
[e9a3c52]65#include "screen.h"
66#include "tetris.h"
67
[ebe70f1]68#define STOP (B_COLS - 3)
69
70static cell curscreen[B_SIZE]; /* non-zero => standout (or otherwise marked) */
[e9a3c52]71static int curscore;
[ebe70f1]72static int isset; /* true => terminal is in game mode */
73
[9f1362d4]74static bool use_color; /* true => use colors */
[50cfa6c]75
[ebe70f1]76static const struct shape *lastshape;
[f1b4e74]77
[79ae36dd]78static suseconds_t timeleft = 0;
79
80console_ctrl_t *console;
81
[f1b4e74]82
[e9a3c52]83/*
[f1b4e74]84 * putstr() is for unpadded strings (either as in termcap(5) or
[0c25c10]85 * simply literal strings);
[e9a3c52]86 */
[a000878c]87static inline void putstr(const char *s)
[59ed572]88{
89 while (*s)
90 putchar(*(s++));
91}
[e9a3c52]92
[ebe70f1]93static void start_standout(uint32_t color)
[e9a3c52]94{
[79ae36dd]95 console_flush(console);
[7c014d1]96 console_set_rgb_color(console, use_color ? color : 0x000000,
97 0xffffff);
[f1b4e74]98}
[e9a3c52]99
[f1b4e74]100static void resume_normal(void)
101{
[79ae36dd]102 console_flush(console);
103 console_set_style(console, STYLE_NORMAL);
[e9a3c52]104}
105
[9996ed5]106void clear_screen(void)
107{
[79ae36dd]108 console_clear(console);
[0cc4313]109 moveto(0, 0);
[9996ed5]110}
111
[e9a3c52]112/*
[f1b4e74]113 * Clear the screen, forgetting the current contents in the process.
[e9a3c52]114 */
[ebe70f1]115void scr_clear(void)
[f1b4e74]116{
[d6cc453]117 resume_normal();
[79ae36dd]118 console_clear(console);
[f1b4e74]119 curscore = -1;
[ebe70f1]120 memset(curscreen, 0, sizeof(curscreen));
[f1b4e74]121}
[b917098]122
[e9a3c52]123/*
[f1b4e74]124 * Set up screen
[e9a3c52]125 */
[ebe70f1]126void scr_init(void)
[e9a3c52]127{
[79ae36dd]128 console_cursor_visibility(console, 0);
[f1b4e74]129 resume_normal();
130 scr_clear();
[e9a3c52]131}
132
[96b02eb9]133void moveto(sysarg_t r, sysarg_t c)
[f1b4e74]134{
[79ae36dd]135 console_flush(console);
136 console_set_pos(console, c, r);
[f1b4e74]137}
138
[9996ed5]139winsize_t winsize;
[f1b4e74]140
[9996ed5]141static int get_display_size(winsize_t *ws)
[f1b4e74]142{
[79ae36dd]143 return console_get_size(console, &ws->ws_col, &ws->ws_row);
[f1b4e74]144}
[e9a3c52]145
[9f1362d4]146static bool get_display_color_sup(void)
[50cfa6c]147{
[96b02eb9]148 sysarg_t ccap;
[79ae36dd]149 int rc = console_get_color_cap(console, &ccap);
[9f1362d4]150
[50cfa6c]151 if (rc != 0)
[9f1362d4]152 return false;
153
[7c014d1]154 return ((ccap & CONSOLE_CAP_RGB) == CONSOLE_CAP_RGB);
[50cfa6c]155}
156
[e9a3c52]157/*
158 * Set up screen mode.
159 */
[ebe70f1]160void scr_set(void)
[e9a3c52]161{
[9996ed5]162 winsize_t ws;
[ebe70f1]163
164 Rows = 0;
165 Cols = 0;
166
[f1b4e74]167 if (get_display_size(&ws) == 0) {
[e9a3c52]168 Rows = ws.ws_row;
169 Cols = ws.ws_col;
170 }
[50cfa6c]171
172 use_color = get_display_color_sup();
[ebe70f1]173
174 if ((Rows < MINROWS) || (Cols < MINCOLS)) {
[e9a3c52]175 char smallscr[55];
[ebe70f1]176
[86029498]177 snprintf(smallscr, sizeof(smallscr),
[e9a3c52]178 "the screen is too small (must be at least %dx%d)",
179 MINROWS, MINCOLS);
180 stop(smallscr);
181 }
182 isset = 1;
[ebe70f1]183
[e9a3c52]184 scr_clear();
185}
186
187/*
188 * End screen mode.
189 */
[ebe70f1]190void scr_end(void)
[e9a3c52]191{
[79ae36dd]192 console_cursor_visibility(console, 1);
[e9a3c52]193}
194
[a000878c]195void stop(const char *why)
[e9a3c52]196{
197 if (isset)
198 scr_end();
[ebe70f1]199
[e9a3c52]200 errx(1, "aborting: %s", why);
201}
202
203/*
204 * Update the screen.
205 */
[ebe70f1]206void scr_update(void)
[e9a3c52]207{
[ebe70f1]208 cell *bp;
209 cell *sp;
210 cell so;
211 cell cur_so = 0;
212 int i;
213 int j;
214 int ccol;
215
216 /* Always leave cursor after last displayed point */
[e9a3c52]217 curscreen[D_LAST * B_COLS - 1] = -1;
[ebe70f1]218
[e9a3c52]219 if (score != curscore) {
[f1b4e74]220 moveto(0, 0);
[86029498]221 printf("Score: %d", score);
[e9a3c52]222 curscore = score;
223 }
[ebe70f1]224
225 /* Draw preview of next pattern */
226 if ((showpreview) && (nextshape != lastshape)) {
[e9a3c52]227 int i;
[ebe70f1]228 static int r = 5, c = 2;
[e9a3c52]229 int tr, tc, t;
[ebe70f1]230
[e9a3c52]231 lastshape = nextshape;
[ebe70f1]232
233 /* Clean */
[f1b4e74]234 resume_normal();
[ebe70f1]235 moveto(r - 1, c - 1);
236 putstr(" ");
237 moveto(r, c - 1);
238 putstr(" ");
239 moveto(r + 1, c - 1);
240 putstr(" ");
241 moveto(r + 2, c - 1);
242 putstr(" ");
243
244 moveto(r - 3, c - 2);
[e9a3c52]245 putstr("Next shape:");
[ebe70f1]246
247 /* Draw */
248 start_standout(nextshape->color);
[e9a3c52]249 moveto(r, 2 * c);
[f1b4e74]250 putstr(" ");
[e9a3c52]251 for (i = 0; i < 3; i++) {
252 t = c + r * B_COLS;
253 t += nextshape->off[i];
[ebe70f1]254
[e9a3c52]255 tr = t / B_COLS;
256 tc = t % B_COLS;
[ebe70f1]257
[e9a3c52]258 moveto(tr, 2*tc);
[f1b4e74]259 putstr(" ");
[e9a3c52]260 }
[f1b4e74]261 resume_normal();
[e9a3c52]262 }
[ebe70f1]263
[e9a3c52]264 bp = &board[D_FIRST * B_COLS];
265 sp = &curscreen[D_FIRST * B_COLS];
266 for (j = D_FIRST; j < D_LAST; j++) {
267 ccol = -1;
268 for (i = 0; i < B_COLS; bp++, sp++, i++) {
269 if (*sp == (so = *bp))
270 continue;
[ebe70f1]271
[e9a3c52]272 *sp = so;
273 if (i != ccol) {
[86029498]274 if (cur_so) {
275 resume_normal();
276 cur_so = 0;
277 }
[e9a3c52]278 moveto(RTOD(j), CTOD(i));
279 }
[ebe70f1]280
[f1b4e74]281 if (so != cur_so) {
282 if (so)
[ebe70f1]283 start_standout(so);
[f1b4e74]284 else
285 resume_normal();
286 cur_so = so;
287 }
288 putstr(" ");
[ebe70f1]289
[e9a3c52]290 ccol = i + 1;
291 /*
292 * Look ahead a bit, to avoid extra motion if
293 * we will be redrawing the cell after the next.
294 * Motion probably takes four or more characters,
295 * so we save even if we rewrite two cells
296 * `unnecessarily'. Skip it all, though, if
297 * the next cell is a different color.
298 */
[ebe70f1]299
300 if ((i > STOP) || (sp[1] != bp[1]) || (so != bp[1]))
[e9a3c52]301 continue;
[ebe70f1]302
[e9a3c52]303 if (sp[2] != bp[2])
304 sp[1] = -1;
[ebe70f1]305 else if ((i < STOP) && (so == bp[2]) && (sp[3] != bp[3])) {
[e9a3c52]306 sp[2] = -1;
307 sp[1] = -1;
308 }
309 }
310 }
[ebe70f1]311
[86029498]312 if (cur_so)
313 resume_normal();
[ebe70f1]314
[79ae36dd]315 console_flush(console);
[e9a3c52]316}
317
318/*
[ebe70f1]319 * Write a message (set != 0), or clear the same message (set == 0).
[e9a3c52]320 * (We need its length in case we have to overwrite with blanks.)
321 */
[9f1362d4]322void scr_msg(char *s, bool set)
[e9a3c52]323{
[92fd52d7]324 int l = str_size(s);
[d6cc453]325
326 moveto(Rows - 2, ((Cols - l) >> 1) - 1);
[ebe70f1]327
[d6cc453]328 if (set)
329 putstr(s);
330 else
331 while (--l >= 0)
332 (void) putchar(' ');
[e9a3c52]333}
[b2951e2]334
[79ae36dd]335/** Sleep for the current turn time
336 *
337 * Eat any input that might be available.
338 *
339 */
340void tsleep(void)
341{
342 suseconds_t timeout = fallrate;
343
344 while (timeout > 0) {
[07b7c48]345 cons_event_t event;
[79ae36dd]346
[07b7c48]347 if (!console_get_event_timeout(console, &event, &timeout))
[79ae36dd]348 break;
349 }
350}
351
352/** Get char with timeout
353 *
354 */
355int tgetchar(void)
356{
357 /*
358 * Reset timeleft to fallrate whenever it is not positive
359 * and increase speed.
360 */
361
362 if (timeleft <= 0) {
363 faster();
364 timeleft = fallrate;
365 }
366
367 /*
368 * Wait to see if there is any input. If so, take it and
369 * update timeleft so that the next call to tgetchar()
370 * will not wait as long. If there is no input,
371 * make timeleft zero and return -1.
372 */
373
374 wchar_t c = 0;
375
376 while (c == 0) {
[07b7c48]377 cons_event_t event;
[79ae36dd]378
[07b7c48]379 if (!console_get_event_timeout(console, &event, &timeleft)) {
[79ae36dd]380 timeleft = 0;
381 return -1;
382 }
383
[07b7c48]384 if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS)
385 c = event.ev.key.c;
[79ae36dd]386 }
387
388 return (int) c;
389}
390
391/** Get char without timeout
392 *
393 */
394int twait(void)
395{
396 wchar_t c = 0;
397
398 while (c == 0) {
[07b7c48]399 cons_event_t event;
[79ae36dd]400
[07b7c48]401 if (!console_get_event(console, &event))
[79ae36dd]402 return -1;
403
[07b7c48]404 if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS)
405 c = event.ev.key.c;
[79ae36dd]406 }
407
408 return (int) c;
409}
410
[b2951e2]411/** @}
412 */
Note: See TracBrowser for help on using the repository browser.