summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2004-06-14 12:50:05 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2004-06-14 12:50:05 +0000
commitf5491a519dfe6a9156967eb0c514e978008f2c00 (patch)
tree255a8f48f1bd658c0a673b12a469c7a7ff326d39 /apps
parent034165ce6977242b8d505c59f14b113025bee0b1 (diff)
downloadrockbox-f5491a519dfe6a9156967eb0c514e978008f2c00.tar.gz
rockbox-f5491a519dfe6a9156967eb0c514e978008f2c00.zip
Tetris is now Rockblox, to avoid trademark problems
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4742 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/rockblox.c418
1 files changed, 418 insertions, 0 deletions
diff --git a/apps/plugins/rockblox.c b/apps/plugins/rockblox.c
new file mode 100644
index 0000000000..f90ced2450
--- /dev/null
+++ b/apps/plugins/rockblox.c
@@ -0,0 +1,418 @@
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#include "plugin.h"
22
23#ifdef HAVE_LCD_BITMAP
24
25static const int start_x = 5;
26static const int start_y = 5;
27static const int max_x = 4 * 17;
28static const int max_y = 3 * 10;
29static const short level_speeds[10] = {
30 1000, 900, 800, 700, 600, 500, 400, 300, 250, 200
31};
32static const int blocks = 7;
33static const int block_frames[7] = {1,2,2,2,4,4,4};
34
35static int current_x, current_y, current_f, current_b;
36static int level, score;
37static int next_b, next_f;
38static short lines;
39static char virtual[LCD_WIDTH * LCD_HEIGHT];
40static struct plugin_api* rb;
41
42/*
43 block_data is built up the following way
44
45 first array index specifies the block number
46 second array index specifies the rotation of the block
47 third array index specifies:
48 0: x-coordinates of pixels
49 1: y-coordinates of pixels
50 fourth array index specifies the coordinate of a pixel
51
52 each block consists of four pixels whose relative coordinates are given
53 with block_data
54*/
55
56static const char block_data[7][4][2][4] =
57{
58 {
59 {{0,1,0,1},{0,0,1,1}}
60 },
61 {
62 {{0,1,1,2},{1,1,0,0}},
63 {{0,0,1,1},{0,1,1,2}}
64 },
65 {
66 {{0,1,1,2},{0,0,1,1}},
67 {{1,1,0,0},{0,1,1,2}}
68 },
69 {
70 {{1,1,1,1},{0,1,2,3}},
71 {{0,1,2,3},{2,2,2,2}}
72 },
73 {
74 {{1,1,1,2},{2,1,0,0}},
75 {{0,1,2,2},{1,1,1,2}},
76 {{0,1,1,1},{2,2,1,0}},
77 {{0,0,1,2},{0,1,1,1}}
78 },
79 {
80 {{0,1,1,1},{0,0,1,2}},
81 {{0,1,2,2},{1,1,1,0}},
82 {{1,1,1,2},{0,1,2,2}},
83 {{0,0,1,2},{2,1,1,1}}
84 },
85 {
86 {{1,0,1,2},{0,1,1,1}},
87 {{2,1,1,1},{1,0,1,2}},
88 {{1,0,1,2},{2,1,1,1}},
89 {{0,1,1,1},{1,0,1,2}}
90 }
91};
92
93static int t_rand(int range)
94{
95 return *rb->current_tick % range;
96}
97
98static void draw_frame(int fstart_x,int fstop_x,int fstart_y,int fstop_y)
99{
100 rb->lcd_drawline(fstart_x, fstart_y, fstop_x, fstart_y);
101 rb->lcd_drawline(fstart_x, fstop_y, fstop_x, fstop_y);
102
103 rb->lcd_drawline(fstart_x, fstart_y, fstart_x, fstop_y);
104 rb->lcd_drawline(fstop_x, fstart_y, fstop_x, fstop_y);
105
106 rb->lcd_drawline(fstart_x - 1, fstart_y + 1, fstart_x - 1, fstop_y + 1);
107 rb->lcd_drawline(fstart_x - 1, fstop_y + 1, fstop_x - 1, fstop_y + 1);
108}
109
110static void draw_block(int x, int y, int block, int frame, bool clear)
111{
112 int i, a, b;
113 for(i=0;i < 4;i++) {
114 if (clear)
115 {
116 for (a = 0; a < 3; a++)
117 for (b = 0; b < 4; b++)
118 rb->lcd_clearpixel(start_x + x + block_data[block][frame][1][i] * 4 - b,
119 start_y + y + block_data[block][frame][0][i] * 3 + a);
120 }
121 else
122 {
123 for (a = 0; a < 3; a++)
124 for (b = 0; b < 4; b++)
125 rb->lcd_drawpixel(start_x+x+block_data[block][frame][1][i] * 4 - b,
126 start_y+y+block_data[block][frame][0][i] * 3 + a);
127 }
128 }
129}
130
131static void to_virtual(void)
132{
133 int i, a, b;
134
135 for(i = 0; i < 4; i++)
136 for (a = 0; a < 3; a++)
137 for (b = 0; b < 4; b++)
138 *(virtual +
139 (current_y + block_data[current_b][current_f][0][i] * 3 + a) *
140 max_x + current_x + block_data[current_b][current_f][1][i] *
141 4 - b) = current_b + 1;
142}
143
144static bool block_touch (int x, int y)
145{
146 int a,b;
147 for (a = 0; a < 4; a++)
148 for (b = 0; b < 3; b++)
149 if (*(virtual + (y + b) * max_x + (x - a)) != 0)
150 return true;
151 return false;
152}
153
154static bool gameover(void)
155{
156 int i;
157 int frame, block, y, x;
158
159 x = current_x;
160 y = current_y;
161 block = current_b;
162 frame = current_f;
163
164 for(i = 0; i < 4; i++){
165 /* Do we have blocks touching? */
166 if(block_touch(x + block_data[block][frame][1][i] * 4,
167 y + block_data[block][frame][0][i] * 3))
168 {
169 /* Are we at the top of the frame? */
170 if(x + block_data[block][frame][1][i] * 4 >= max_x - 16)
171 {
172 /* Game over ;) */
173 return true;
174 }
175 }
176 }
177 return false;
178}
179
180static bool valid_position(int x, int y, int block, int frame)
181{
182 int i;
183 for(i=0;i < 4;i++)
184 if ((y + block_data[block][frame][0][i] * 3 > max_y - 3) ||
185 (x + block_data[block][frame][1][i] * 4 > max_x - 4) ||
186 (y + block_data[block][frame][0][i] * 3 < 0) ||
187 (x + block_data[block][frame][1][i] * 4 < 4) ||
188 block_touch (x + block_data[block][frame][1][i] * 4,
189 y + block_data[block][frame][0][i] * 3))
190 {
191 return false;
192 }
193 return true;
194}
195
196static void from_virtual(void)
197{
198 int x,y;
199 for(y = 0; y < max_y; y++)
200 for(x = 1; x < max_x - 1; x++)
201 if(*(virtual + (y * max_x) + x) != 0)
202 rb->lcd_drawpixel(start_x + x, start_y + y);
203 else
204 rb->lcd_clearpixel(start_x + x, start_y + y);
205}
206
207static void move_block(int x,int y,int f)
208{
209 int last_frame = current_f;
210 if(f != 0)
211 {
212 current_f += f;
213 if(current_f > block_frames[current_b]-1)
214 current_f = 0;
215 if(current_f < 0)
216 current_f = block_frames[current_b]-1;
217 }
218
219 if(valid_position(current_x + x, current_y + y, current_b, current_f))
220 {
221 draw_block(current_x,current_y,current_b,last_frame,true);
222 current_x += x;
223 current_y += y;
224 draw_block(current_x,current_y,current_b,current_f,false);
225 rb->lcd_update();
226 }
227 else
228 current_f = last_frame;
229}
230
231static void new_block(void)
232{
233 current_b = next_b;
234 current_f = next_f;
235 current_x = max_x - 16;
236 current_y = (int)12;
237 next_b = t_rand(blocks);
238 next_f = t_rand(block_frames[next_b]);
239
240 rb->lcd_drawline (max_x + 7, start_y - 1, max_x + 29, start_y - 1);
241 rb->lcd_drawline (max_x + 29, start_y, max_x + 29, start_y + 14);
242 rb->lcd_drawline (max_x + 29, start_y + 14, max_x + 7, start_y + 14);
243 rb->lcd_drawline (max_x + 7, start_y + 14, max_x + 7, start_y - 1);
244 rb->lcd_drawline (max_x + 6, start_y + 15, max_x + 6, start_y);
245 rb->lcd_drawline (max_x + 6, start_y + 15, max_x + 28, start_y + 15);
246
247 draw_block(max_x + 9, start_y - 4, current_b, current_f, true);
248 draw_block(max_x + 9, start_y - 4, next_b, next_f, false);
249 if(!valid_position(current_x, current_y, current_b, current_f))
250 {
251 draw_block(current_x, current_y, current_b, current_f, false);
252 rb->lcd_update();
253 }
254 else
255 draw_block(current_x, current_y, current_b, current_f, false);
256}
257
258static int check_lines(void)
259{
260 int x,y,i,j;
261 bool line;
262 int lines = 0;
263 for(x = 0; x < max_x; x++)
264 {
265 line = true;
266 for(y = 0; y < max_y; y++)
267 {
268 if(*(virtual + y * max_x + x) == 0)
269 {
270 line = false;
271 break;
272 }
273 }
274
275 if(line)
276 {
277 lines++;
278 /* move rows down */
279 for(i = x; i < max_x - 1; i++)
280 for (j = 0; j < max_y; j++)
281 *(virtual + j * max_x + i)=*(virtual + j * max_x + (i + 1));
282
283 x--; /* re-check this line */
284 }
285 }
286
287 return lines / 4;
288}
289
290static void move_down(void)
291{
292 int l;
293 char s[25];
294
295 if(!valid_position(current_x - 4, current_y, current_b, current_f))
296 {
297 to_virtual();
298 l = check_lines();
299 if(l)
300 {
301 lines += l;
302 level = (int)lines/10;
303 if(level > 9)
304 level = 9;
305 from_virtual();
306 score += l*l;
307 }
308
309 rb->snprintf(s, sizeof(s), "%d Rows - Level %d", lines, level);
310 rb->lcd_putsxy(2, 42, s);
311
312 new_block();
313 move_block(0,0,0);
314 }
315 else
316 move_block(-4,0,0);
317}
318
319static int game_loop(void)
320{
321 while(1)
322 {
323 int count = 0;
324 while(count * 300 < level_speeds[level])
325 {
326 switch(rb->button_get_w_tmo(HZ/10))
327 {
328 case BUTTON_OFF:
329 return PLUGIN_OK;
330
331 case BUTTON_UP:
332 case BUTTON_UP | BUTTON_REPEAT:
333 move_block(0,-3,0);
334 break;
335
336 case BUTTON_DOWN:
337 case BUTTON_DOWN | BUTTON_REPEAT:
338 move_block(0,3,0);
339 break;
340
341 case BUTTON_RIGHT:
342 case BUTTON_RIGHT | BUTTON_REPEAT:
343 move_block(0,0,1);
344 break;
345
346 case BUTTON_LEFT:
347 case BUTTON_LEFT | BUTTON_REPEAT:
348 move_down();
349 break;
350
351 case SYS_USB_CONNECTED:
352 rb->usb_screen();
353 return PLUGIN_USB_CONNECTED;
354 }
355
356 count++;
357 }
358
359 if(gameover())
360 {
361 rb->lcd_clearrect(0, 52, LCD_WIDTH, LCD_HEIGHT - 52);
362 rb->lcd_putsxy(2, 52, "You lose!");
363 rb->lcd_update();
364 rb->sleep(HZ * 3);
365 return false;
366 }
367
368 move_down();
369 }
370
371 return false;
372}
373
374static void init_rockblox(void)
375{
376 rb->memset(&virtual, 0, sizeof(virtual));
377
378 current_x = 0;
379 current_y = 0;
380 current_f = 0;
381 current_b = 0;
382 level = 0;
383 lines = 0;
384 score = 0;
385 next_b = 0;
386 next_f = 0;
387}
388
389enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
390{
391 int ret;
392
393 TEST_PLUGIN_API(api);
394
395 (void)parameter;
396 rb = api;
397
398 /* Lets use the default font */
399 rb->lcd_setfont(FONT_SYSFIXED);
400
401 init_rockblox();
402
403 draw_frame(start_x, start_x + max_x - 1, start_y - 1, start_y + max_y);
404 rb->lcd_putsxy(2, 42, "0 Rows - Level 0");
405 rb->lcd_update();
406
407 next_b = t_rand(blocks);
408 next_f = t_rand(block_frames[next_b]);
409 new_block();
410 ret = game_loop();
411
412 rb->lcd_setfont(FONT_UI);
413
414 return ret;
415}
416
417#endif
418