summaryrefslogtreecommitdiff
path: root/apps/recorder/tetris.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/recorder/tetris.c')
-rw-r--r--apps/recorder/tetris.c438
1 files changed, 0 insertions, 438 deletions
diff --git a/apps/recorder/tetris.c b/apps/recorder/tetris.c
deleted file mode 100644
index 6302e40109..0000000000
--- a/apps/recorder/tetris.c
+++ /dev/null
@@ -1,438 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 1999 Mattis Wadman (nappe@sudac.org)
11 *
12 * Heavily modified for embedded use by Björn Stenberg (bjorn@haxx.se)
13 *
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "options.h"
24
25#ifdef USE_GAMES
26
27#include <stdbool.h>
28#include <string.h>
29#include "lcd.h"
30#include "button.h"
31#include "kernel.h"
32#include "menu.h"
33#include "screens.h"
34#include "font.h"
35
36#ifdef SIMULATOR
37#include <stdio.h>
38#endif
39#include "sprintf.h"
40#include "lang.h"
41#define TETRIS_TITLE "Tetris!"
42#define TETRIS_TITLE_FONT 1
43#define TETRIS_TITLE_XLOC 43
44#define TETRIS_TITLE_YLOC 15
45
46static const int start_x = 5;
47static const int start_y = 5;
48static const int max_x = 4 * 17;
49static const int max_y = 3 * 10;
50static const short level_speeds[10] = {
51 1000, 900, 800, 700, 600, 500, 400, 300, 250, 200
52};
53static const int blocks = 7;
54static const int block_frames[7] = {1,2,2,2,4,4,4};
55
56static int current_x, current_y, current_f, current_b;
57static int level, score;
58static int next_b, next_f;
59static short lines;
60static char virtual[LCD_WIDTH * LCD_HEIGHT];
61
62/*
63 block_data is built up the following way
64
65 first array index specifies the block number
66 second array index specifies the rotation of the block
67 third array index specifies:
68 0: x-coordinates of pixels
69 1: y-coordinates of pixels
70 fourth array index specifies the coordinate of a pixel
71
72 each block consists of four pixels whose relative coordinates are given
73 with block_data
74*/
75
76static const char block_data[7][4][2][4] =
77{
78 {
79 {{0,1,0,1},{0,0,1,1}}
80 },
81 {
82 {{0,1,1,2},{1,1,0,0}},
83 {{0,0,1,1},{0,1,1,2}}
84 },
85 {
86 {{0,1,1,2},{0,0,1,1}},
87 {{1,1,0,0},{0,1,1,2}}
88 },
89 {
90 {{1,1,1,1},{0,1,2,3}},
91 {{0,1,2,3},{2,2,2,2}}
92 },
93 {
94 {{1,1,1,2},{2,1,0,0}},
95 {{0,1,2,2},{1,1,1,2}},
96 {{0,1,1,1},{2,2,1,0}},
97 {{0,0,1,2},{0,1,1,1}}
98 },
99 {
100 {{0,1,1,1},{0,0,1,2}},
101 {{0,1,2,2},{1,1,1,0}},
102 {{1,1,1,2},{0,1,2,2}},
103 {{0,0,1,2},{2,1,1,1}}
104 },
105 {
106 {{1,0,1,2},{0,1,1,1}},
107 {{2,1,1,1},{1,0,1,2}},
108 {{1,0,1,2},{2,1,1,1}},
109 {{0,1,1,1},{1,0,1,2}}
110 }
111};
112
113static int t_rand(int range)
114{
115 return current_tick % range;
116}
117
118static void draw_frame(int fstart_x,int fstop_x,int fstart_y,int fstop_y)
119{
120 lcd_drawline(fstart_x, fstart_y, fstop_x, fstart_y);
121 lcd_drawline(fstart_x, fstop_y, fstop_x, fstop_y);
122
123 lcd_drawline(fstart_x, fstart_y, fstart_x, fstop_y);
124 lcd_drawline(fstop_x, fstart_y, fstop_x, fstop_y);
125
126 lcd_drawline(fstart_x - 1, fstart_y + 1, fstart_x - 1, fstop_y + 1);
127 lcd_drawline(fstart_x - 1, fstop_y + 1, fstop_x - 1, fstop_y + 1);
128}
129
130static void draw_block(int x, int y, int block, int frame, bool clear)
131{
132 int i, a, b;
133 for(i=0;i < 4;i++) {
134 if (clear)
135 {
136 for (a = 0; a < 3; a++)
137 for (b = 0; b < 4; b++)
138 lcd_clearpixel(start_x + x + block_data[block][frame][1][i] * 4 - b,
139 start_y + y + block_data[block][frame][0][i] * 3 + a);
140 }
141 else
142 {
143 for (a = 0; a < 3; a++)
144 for (b = 0; b < 4; b++)
145 lcd_drawpixel(start_x+x+block_data[block][frame][1][i] * 4 - b,
146 start_y+y+block_data[block][frame][0][i] * 3 + a);
147 }
148 }
149}
150
151static void to_virtual(void)
152{
153 int i, a, b;
154
155 for(i = 0; i < 4; i++)
156 for (a = 0; a < 3; a++)
157 for (b = 0; b < 4; b++)
158 *(virtual +
159 (current_y + block_data[current_b][current_f][0][i] * 3 + a) *
160 max_x + current_x + block_data[current_b][current_f][1][i] *
161 4 - b) = current_b + 1;
162}
163
164static bool block_touch (int x, int y)
165{
166 int a,b;
167 for (a = 0; a < 4; a++)
168 for (b = 0; b < 3; b++)
169 if (*(virtual + (y + b) * max_x + (x - a)) != 0)
170 return true;
171 return false;
172}
173
174static bool gameover(void)
175{
176 int i;
177 int frame, block, y, x;
178
179 x = current_x;
180 y = current_y;
181 block = current_b;
182 frame = current_f;
183
184 for(i = 0; i < 4; i++){
185 /* Do we have blocks touching? */
186 if(block_touch(x + block_data[block][frame][1][i] * 4,
187 y + block_data[block][frame][0][i] * 3))
188 {
189 /* Are we at the top of the frame? */
190 if(x + block_data[block][frame][1][i] * 4 >= max_x - 16)
191 {
192 /* Game over ;) */
193 return true;
194 }
195 }
196 }
197 return false;
198}
199
200static bool valid_position(int x, int y, int block, int frame)
201{
202 int i;
203 for(i=0;i < 4;i++)
204 if ((y + block_data[block][frame][0][i] * 3 > max_y - 3) ||
205 (x + block_data[block][frame][1][i] * 4 > max_x - 4) ||
206 (y + block_data[block][frame][0][i] * 3 < 0) ||
207 (x + block_data[block][frame][1][i] * 4 < 4) ||
208 block_touch (x + block_data[block][frame][1][i] * 4,
209 y + block_data[block][frame][0][i] * 3))
210 {
211 return false;
212 }
213 return true;
214}
215
216static void from_virtual(void)
217{
218 int x,y;
219 for(y = 0; y < max_y; y++)
220 for(x = 1; x < max_x - 1; x++)
221 if(*(virtual + (y * max_x) + x) != 0)
222 lcd_drawpixel(start_x + x, start_y + y);
223 else
224 lcd_clearpixel(start_x + x, start_y + y);
225}
226
227static void move_block(int x,int y,int f)
228{
229 int last_frame = current_f;
230 if(f != 0)
231 {
232 current_f += f;
233 if(current_f > block_frames[current_b]-1)
234 current_f = 0;
235 if(current_f < 0)
236 current_f = block_frames[current_b]-1;
237 }
238
239 if(valid_position(current_x + x, current_y + y, current_b, current_f))
240 {
241 draw_block(current_x,current_y,current_b,last_frame,true);
242 current_x += x;
243 current_y += y;
244 draw_block(current_x,current_y,current_b,current_f,false);
245 lcd_update();
246 }
247 else
248 current_f = last_frame;
249}
250
251static void new_block(void)
252{
253 current_b = next_b;
254 current_f = next_f;
255 current_x = max_x - 16;
256 current_y = (int)12;
257 next_b = t_rand(blocks);
258 next_f = t_rand(block_frames[next_b]);
259
260 lcd_drawline (max_x + 7, start_y - 1, max_x + 29, start_y - 1);
261 lcd_drawline (max_x + 29, start_y, max_x + 29, start_y + 14);
262 lcd_drawline (max_x + 29, start_y + 14, max_x + 7, start_y + 14);
263 lcd_drawline (max_x + 7, start_y + 14, max_x + 7, start_y - 1);
264 lcd_drawline (max_x + 6, start_y + 15, max_x + 6, start_y);
265 lcd_drawline (max_x + 6, start_y + 15, max_x + 28, start_y + 15);
266
267 draw_block(max_x + 9, start_y - 4, current_b, current_f, true);
268 draw_block(max_x + 9, start_y - 4, next_b, next_f, false);
269 if(!valid_position(current_x, current_y, current_b, current_f))
270 {
271 draw_block(current_x, current_y, current_b, current_f, false);
272 lcd_update();
273 }
274 else
275 draw_block(current_x, current_y, current_b, current_f, false);
276}
277
278static int check_lines(void)
279{
280 int x,y,i,j;
281 bool line;
282 int lines = 0;
283 for(x = 0; x < max_x; x++)
284 {
285 line = true;
286 for(y = 0; y < max_y; y++)
287 {
288 if(*(virtual + y * max_x + x) == 0)
289 {
290 line = false;
291 break;
292 }
293 }
294
295 if(line)
296 {
297 lines++;
298 /* move rows down */
299 for(i = x; i < max_x - 1; i++)
300 for (j = 0; j < max_y; j++)
301 *(virtual + j * max_x + i)=*(virtual + j * max_x + (i + 1));
302
303 x--; /* re-check this line */
304 }
305 }
306
307 return lines / 4;
308}
309
310static void move_down(void)
311{
312 int l;
313 char s[25];
314
315 if(!valid_position(current_x - 4, current_y, current_b, current_f))
316 {
317 to_virtual();
318 l = check_lines();
319 if(l)
320 {
321 lines += l;
322 level = (int)lines/10;
323 if(level > 9)
324 level = 9;
325 from_virtual();
326 score += l*l;
327 }
328
329 snprintf (s, sizeof(s), "%d %s %d", lines,
330 str(LANG_TETRIS_LEVEL), level);
331 lcd_putsxy (2, 42, s);
332
333 new_block();
334 move_block(0,0,0);
335 }
336 else
337 move_block(-4,0,0);
338}
339
340static bool game_loop(void)
341{
342 while(1)
343 {
344 int count = 0;
345 while(count * 300 < level_speeds[level])
346 {
347 switch(button_get_w_tmo(HZ/10))
348 {
349 case BUTTON_OFF:
350 return false;
351
352 case BUTTON_UP:
353 case BUTTON_UP | BUTTON_REPEAT:
354 move_block(0,-3,0);
355 break;
356
357 case BUTTON_DOWN:
358 case BUTTON_DOWN | BUTTON_REPEAT:
359 move_block(0,3,0);
360 break;
361
362 case BUTTON_RIGHT:
363 case BUTTON_RIGHT | BUTTON_REPEAT:
364 move_block(0,0,1);
365 break;
366
367 case BUTTON_LEFT:
368 case BUTTON_LEFT | BUTTON_REPEAT:
369 move_down();
370 break;
371
372 case SYS_USB_CONNECTED:
373 usb_screen();
374 return true;
375 }
376
377 count++;
378 }
379
380 if(gameover())
381 {
382 lcd_clearrect(0, 52, LCD_WIDTH, LCD_HEIGHT - 52);
383 lcd_putsxy (2, 52, str(LANG_TETRIS_LOSE));
384 lcd_update();
385 sleep(HZ * 3);
386 return false;
387 }
388
389 move_down();
390 }
391
392 return false;
393}
394
395static void init_tetris(void)
396{
397 memset(&virtual, 0, sizeof(virtual));
398
399 current_x = 0;
400 current_y = 0;
401 current_f = 0;
402 current_b = 0;
403 level = 0;
404 lines = 0;
405 score = 0;
406 next_b = 0;
407 next_f = 0;
408}
409
410bool tetris(void)
411{
412 char buf[20];
413 bool val;
414
415 /* Lets use the default font */
416 lcd_setfont(FONT_SYSFIXED);
417
418 init_tetris();
419
420 draw_frame(start_x, start_x + max_x - 1, start_y - 1, start_y + max_y);
421 snprintf(buf, sizeof(buf), "0 %s 0", str(LANG_TETRIS_LEVEL));
422 lcd_putsxy (2, 42, buf);
423 lcd_update();
424
425 next_b = t_rand(blocks);
426 next_f = t_rand(block_frames[next_b]);
427 new_block();
428 val = game_loop();
429
430 lcd_setfont(FONT_UI);
431
432 return val;
433}
434
435#endif
436
437
438