2 * Copyright (c) 2011 Martin Decky
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
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
35 * Based upon BSD Tetris
37 * Copyright (c) 1992, 1993
38 * The Regents of the University of California.
39 * Distributed under BSD license.
41 * This code is derived from software contributed to Berkeley by
42 * Chris Torek and Darren F. Provine.
46 /** @addtogroup tetris
53 * Tetris screen control.
62 #include <io/console.h>
67 #define STOP (B_COLS - 3)
69 static cell curscreen
[B_SIZE
]; /* non-zero => standout (or otherwise marked) */
71 static int isset
; /* true => terminal is in game mode */
73 static bool use_color
; /* true => use colors */
75 static const struct shape
*lastshape
;
77 static usec_t timeleft
= 0;
79 console_ctrl_t
*console
;
83 * putstr() is for unpadded strings (either as in termcap(5) or
84 * simply literal strings);
86 static inline void putstr(const char *s
)
92 static void start_standout(uint32_t color
)
94 console_flush(console
);
95 console_set_rgb_color(console
, use_color
? color
: 0x000000,
99 static void resume_normal(void)
101 console_flush(console
);
102 console_set_style(console
, STYLE_NORMAL
);
105 void clear_screen(void)
107 console_clear(console
);
112 * Clear the screen, forgetting the current contents in the process.
117 console_clear(console
);
119 memset(curscreen
, 0, sizeof(curscreen
));
127 console_cursor_visibility(console
, 0);
132 void moveto(sysarg_t r
, sysarg_t c
)
134 console_flush(console
);
135 console_set_pos(console
, c
, r
);
140 static errno_t
get_display_size(winsize_t
*ws
)
142 return console_get_size(console
, &ws
->ws_col
, &ws
->ws_row
);
145 static bool get_display_color_sup(void)
148 errno_t rc
= console_get_color_cap(console
, &ccap
);
153 return ((ccap
& CONSOLE_CAP_RGB
) == CONSOLE_CAP_RGB
);
157 * Set up screen mode.
166 if (get_display_size(&ws
) == 0) {
171 use_color
= get_display_color_sup();
173 if ((Rows
< MINROWS
) || (Cols
< MINCOLS
)) {
176 snprintf(smallscr
, sizeof(smallscr
),
177 "the screen is too small (must be at least %dx%d)",
191 console_cursor_visibility(console
, 1);
194 void stop(const char *why
)
199 fprintf(stderr
, "aborting: %s", why
);
206 void scr_update(void)
216 /* Always leave cursor after last displayed point */
217 curscreen
[D_LAST
* B_COLS
- 1] = -1;
219 if (score
!= curscore
) {
221 printf("Score: %d", score
);
225 /* Draw preview of next pattern */
226 if ((showpreview
) && (nextshape
!= lastshape
)) {
228 static int r
= 5, c
= 2;
231 lastshape
= nextshape
;
235 moveto(r
- 1, c
- 1);
239 moveto(r
+ 1, c
- 1);
241 moveto(r
+ 2, c
- 1);
244 moveto(r
- 3, c
- 2);
245 putstr("Next shape:");
248 start_standout(nextshape
->color
);
251 for (i
= 0; i
< 3; i
++) {
253 t
+= nextshape
->off
[i
];
264 bp
= &board
[D_FIRST
* B_COLS
];
265 sp
= &curscreen
[D_FIRST
* B_COLS
];
266 for (j
= D_FIRST
; j
< D_LAST
; j
++) {
268 for (i
= 0; i
< B_COLS
; bp
++, sp
++, i
++) {
269 if (*sp
== (so
= *bp
))
278 moveto(RTOD(j
), CTOD(i
));
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.
300 if ((i
> STOP
) || (sp
[1] != bp
[1]) || (so
!= bp
[1]))
305 else if ((i
< STOP
) && (so
== bp
[2]) && (sp
[3] != bp
[3])) {
315 console_flush(console
);
319 * Write a message (set != 0), or clear the same message (set == 0).
320 * (We need its length in case we have to overwrite with blanks.)
322 void scr_msg(char *s
, bool set
)
326 moveto(Rows
- 2, ((Cols
- l
) >> 1) - 1);
335 /** Sleep for the current turn time
337 * Eat any input that might be available.
342 usec_t timeout
= fallrate
;
344 while (timeout
> 0) {
347 if (!console_get_event_timeout(console
, &event
, &timeout
))
352 /** Get char with timeout
358 * Reset timeleft to fallrate whenever it is not positive
359 * and increase speed.
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.
379 if (!console_get_event_timeout(console
, &event
, &timeleft
)) {
384 if (event
.type
== CEV_KEY
&& event
.ev
.key
.type
== KEY_PRESS
)
391 /** Get char without timeout
401 if (!console_get_event(console
, &event
))
404 if (event
.type
== CEV_KEY
&& event
.ev
.key
.type
== KEY_PRESS
)