summaryrefslogtreecommitdiff
path: root/apps/plugins/xrick/system/sysvid_rockbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/xrick/system/sysvid_rockbox.c')
-rw-r--r--apps/plugins/xrick/system/sysvid_rockbox.c402
1 files changed, 402 insertions, 0 deletions
diff --git a/apps/plugins/xrick/system/sysvid_rockbox.c b/apps/plugins/xrick/system/sysvid_rockbox.c
new file mode 100644
index 0000000000..236bc87616
--- /dev/null
+++ b/apps/plugins/xrick/system/sysvid_rockbox.c
@@ -0,0 +1,402 @@
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Port of xrick, a Rick Dangerous clone, to Rockbox.
11 * See http://www.bigorno.net/xrick/
12 *
13 * Copyright (C) 2008-2014 Pierluigi Vicinanza
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#include "xrick/system/system.h"
26
27#include "xrick/config.h"
28#include "xrick/draw.h"
29#include "xrick/game.h"
30#include "xrick/data/img.h"
31#include "xrick/debug.h"
32
33#include "plugin.h"
34#include "lib/helper.h"
35
36/*
37 * Global variables
38 */
39U8 *sysvid_fb = NULL; /* xRick generic 320x200 8bpp frame buffer */
40
41/*
42 * Local variables
43 */
44static fb_data palette[256] IBSS_ATTR;
45static bool isVideoInitialised = false;
46#ifndef HAVE_LCD_COLOR
47# include "lib/grey.h"
48GREY_INFO_STRUCT_IRAM
49static unsigned char greybuffer[LCD_HEIGHT * LCD_WIDTH] IBSS_ATTR; /* off screen buffer */
50static unsigned char *gbuf;
51# if LCD_PIXELFORMAT == HORIZONTAL_PACKING
52enum { GREYBUFSIZE = (((LCD_WIDTH+7)/8)*LCD_HEIGHT*16+200) };
53# else
54enum { GREYBUFSIZE = (LCD_WIDTH*((LCD_HEIGHT+7)/8)*16+200) };
55# endif
56#endif /* ndef HAVE_LCD_COLOR */
57
58static fb_data *lcd_fb = NULL;
59
60#if (LCD_HEIGHT < SYSVID_HEIGHT)
61enum { ROW_RESIZE_STEP = (LCD_HEIGHT << 16) / SYSVID_HEIGHT };
62
63static bool rowsToSkip[SYSVID_HEIGHT];
64
65/*
66 *
67 */
68static void calculateRowsToSkip(void)
69{
70 U32 currentRow, prevResizedRow;
71
72 prevResizedRow = 0;
73 rowsToSkip[0] = false;
74
75 for (currentRow = 1; currentRow < SYSVID_HEIGHT; ++currentRow)
76 {
77 U32 resizedRow = (currentRow * ROW_RESIZE_STEP) >> 16;
78 if (resizedRow == prevResizedRow)
79 {
80 rowsToSkip[currentRow] = true;
81 }
82 prevResizedRow = resizedRow;
83 }
84}
85#endif /* (LCD_HEIGHT < SYSVID_HEIGHT) */
86
87#if (LCD_WIDTH < SYSVID_WIDTH)
88enum { COLUMN_RESIZE_STEP = (LCD_WIDTH << 16) / (SYSVID_WIDTH + (DRAW_XYMAP_SCRLEFT*2)) };
89
90static bool columnsToSkip[SYSVID_WIDTH + (DRAW_XYMAP_SCRLEFT*2)];
91
92/*
93 *
94 */
95static void calculateColumnsToSkip(void)
96{
97 U32 currentColumn, prevResizedColumn;
98
99 prevResizedColumn = 0;
100 columnsToSkip[0] = false;
101
102 for (currentColumn = 1; currentColumn < (SYSVID_WIDTH + (DRAW_XYMAP_SCRLEFT*2)); ++currentColumn)
103 {
104 U32 resizedColumn = (currentColumn * COLUMN_RESIZE_STEP) >> 16;
105 if (resizedColumn == prevResizedColumn)
106 {
107 columnsToSkip[currentColumn] = true;
108 }
109 prevResizedColumn = resizedColumn;
110 }
111}
112#endif /* (LCD_WIDTH < SYSVID_WIDTH) */
113
114/*
115 *
116 */
117void sysvid_setPalette(img_color_t *pal, U16 n)
118{
119 U16 i;
120
121 for (i = 0; i < n; i++)
122 {
123#ifdef HAVE_LCD_COLOR
124 palette[i] = LCD_RGBPACK(pal[i].r, pal[i].g, pal[i].b);
125#else
126 palette[i] = ((3 * pal[i].r) + (6 * pal[i].g) + pal[i].b) / 10;
127#endif
128 }
129}
130
131/*
132 *
133 */
134void sysvid_setGamePalette()
135{
136 sysvid_setPalette(game_colors, game_color_count);
137}
138
139/*
140 * Update screen
141 */
142void sysvid_update(const rect_t *rects)
143{
144 unsigned sourceRow, sourceLastRow;
145 unsigned sourceColumn, sourceLastColumn;
146 unsigned resizedRow, resizedColumn;
147 unsigned resizedWidth, resizedHeight;
148 unsigned x, y;
149 U8 *sourceBuf, *sourceTemp;
150 fb_data *destBuf, *destTemp;
151
152 if (!rects)
153 {
154 return;
155 }
156
157 while (rects)
158 {
159 sourceRow = rects->y;
160 sourceLastRow = sourceRow + rects->height;
161 sourceColumn = rects->x;
162 sourceLastColumn = sourceColumn + rects->width;
163
164#if (LCD_WIDTH < SYSVID_WIDTH)
165 /* skip black borders */
166 if (sourceColumn < -DRAW_XYMAP_SCRLEFT)
167 {
168 sourceColumn = -DRAW_XYMAP_SCRLEFT;
169 }
170 if (sourceLastColumn > (SYSVID_WIDTH + DRAW_XYMAP_SCRLEFT))
171 {
172 sourceLastColumn = SYSVID_WIDTH + DRAW_XYMAP_SCRLEFT;
173 }
174
175 /* skip unwanted columns */
176 while (columnsToSkip[sourceColumn + DRAW_XYMAP_SCRLEFT] /* && sourceColumn < (SYSVID_WIDTH + DRAW_XYMAP_SCRLEFT) */)
177 {
178 ++sourceColumn;
179 }
180
181 resizedColumn = ((sourceColumn + DRAW_XYMAP_SCRLEFT) * COLUMN_RESIZE_STEP) >> 16;
182 resizedWidth = 0;
183#else
184 resizedColumn = sourceColumn;
185 resizedWidth = rects->width;
186#endif /* (LCD_WIDTH < SYSVID_WIDTH) */
187
188#if (LCD_HEIGHT < SYSVID_HEIGHT)
189 /* skip unwanted rows */
190 while (rowsToSkip[sourceRow] /* && sourceRow < SYSVID_HEIGHT */)
191 {
192 ++sourceRow;
193 }
194
195 resizedRow = (sourceRow * ROW_RESIZE_STEP) >> 16;
196 resizedHeight = 0;
197#else
198 resizedRow = sourceRow;
199 resizedHeight = rects->height;
200#endif /* (LCD_HEIGHT < SYSVID_HEIGHT) */
201
202 sourceBuf = sysvid_fb;
203 sourceBuf += sourceColumn + sourceRow * SYSVID_WIDTH;
204
205#ifdef HAVE_LCD_COLOR
206 if(!lcd_fb)
207 {
208 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
209 lcd_fb = vp_main->buffer->fb_ptr;
210 }
211 destBuf = lcd_fb;
212#else
213 destBuf = greybuffer;
214#endif /* HAVE_LCD_COLOR */
215 destBuf += resizedColumn + resizedRow * LCD_WIDTH;
216
217#if (LCD_WIDTH < SYSVID_WIDTH)
218 sourceColumn += DRAW_XYMAP_SCRLEFT;
219 sourceLastColumn += DRAW_XYMAP_SCRLEFT;
220#endif /* (LCD_WIDTH < SYSVID_WIDTH) */
221
222 for (y = sourceRow; y < sourceLastRow; ++y)
223 {
224#if (LCD_HEIGHT < SYSVID_HEIGHT)
225 if (rowsToSkip[y])
226 {
227 sourceBuf += SYSVID_WIDTH;
228 continue;
229 }
230
231 ++resizedHeight;
232#endif /* (LCD_HEIGHT < SYSVID_HEIGHT) */
233
234 sourceTemp = sourceBuf;
235 destTemp = destBuf;
236 for (x = sourceColumn; x < sourceLastColumn; ++x)
237 {
238#if (LCD_WIDTH < SYSVID_WIDTH)
239 if (columnsToSkip[x])
240 {
241 ++sourceTemp;
242 continue;
243 }
244
245 if (y == sourceRow)
246 {
247 ++resizedWidth;
248 }
249#endif /* (LCD_WIDTH < SYSVID_WIDTH) */
250
251 *destTemp = palette[*sourceTemp];
252
253 ++sourceTemp;
254 ++destTemp;
255 }
256
257 sourceBuf += SYSVID_WIDTH;
258 destBuf += LCD_WIDTH;
259 }
260
261#ifdef HAVE_LCD_COLOR
262 IFDEBUG_VIDEO2(
263 for (y = resizedRow; y < resizedRow + resizedHeight; ++y)
264 {
265 destBuf = lcd_fb + resizedColumn + y * LCD_WIDTH;
266 *destBuf = palette[0x01];
267 *(destBuf + resizedWidth - 1) = palette[0x01];
268 }
269
270 for (x = resizedColumn; x < resizedColumn + resizedWidth; ++x)
271 {
272 destBuf = rb->lcd_fb + x + resizedRow * LCD_WIDTH;
273 *destBuf = palette[0x01];
274 *(destBuf + (resizedHeight - 1) * LCD_WIDTH) = palette[0x01];
275 }
276 );
277
278 rb->lcd_update_rect(resizedColumn, resizedRow, resizedWidth, resizedHeight);
279#else
280 grey_ub_gray_bitmap_part(greybuffer, resizedColumn, resizedRow, LCD_WIDTH, resizedColumn, resizedRow, resizedWidth, resizedHeight);
281#endif /* HAVE_LCD_COLOR */
282
283 rects = rects->next;
284 }
285}
286
287/*
288 * Clear screen
289 * (077C)
290 */
291void sysvid_clear(void)
292{
293 rb->memset(sysvid_fb, 0, sizeof(U8) * SYSVID_WIDTH * SYSVID_HEIGHT);
294}
295
296/*
297 * Initialise video
298 */
299bool sysvid_init()
300{
301 bool success;
302
303 if (isVideoInitialised)
304 {
305 return true;
306 }
307
308 IFDEBUG_VIDEO(sys_printf("xrick/video: start\n"););
309
310 success = false;
311 do
312 {
313 /* allocate xRick generic frame buffer into memory */
314 sysvid_fb = sysmem_push(sizeof(U8) * SYSVID_WIDTH * SYSVID_HEIGHT);
315 if (!sysvid_fb)
316 {
317 sys_error("(video) unable to allocate frame buffer");
318 break;
319 }
320
321#ifndef HAVE_LCD_COLOR
322 gbuf = sysmem_push(GREYBUFSIZE);
323 if (!gbuf)
324 {
325 sys_error("(video) unable to allocate buffer for greyscale functions");
326 break;
327 }
328
329 if (!grey_init(gbuf, GREYBUFSIZE, GREY_ON_COP, LCD_WIDTH, LCD_HEIGHT, NULL))
330 {
331 sys_error("(video) not enough memory to initialise greyscale functions");
332 break;
333 }
334#endif /* ndef HAVE_LCD_COLOR */
335
336 success = true;
337 } while (false);
338
339 if (!success)
340 {
341#ifndef HAVE_LCD_COLOR
342 sysmem_pop(gbuf);
343#endif
344 sysmem_pop(sysvid_fb);
345 return false;
346 }
347
348#if (LCD_HEIGHT < SYSVID_HEIGHT)
349 calculateRowsToSkip();
350#endif
351#if (LCD_WIDTH < SYSVID_WIDTH)
352 calculateColumnsToSkip();
353#endif
354
355#if LCD_DEPTH > 1
356 rb->lcd_set_backdrop(NULL);
357#endif
358 /* Turn off backlight timeout */
359 backlight_ignore_timeout();
360
361 rb->lcd_set_foreground(LCD_WHITE);
362 rb->lcd_set_background(LCD_BLACK);
363 rb->lcd_clear_display();
364
365#ifdef HAVE_LCD_COLOR
366 rb->lcd_update();
367#else
368 /* switch on greyscale overlay */
369 grey_show(true);
370#endif /* HAVE_LCD_COLOR */
371
372 isVideoInitialised = true;
373 IFDEBUG_VIDEO(sys_printf("xrick/video: ready\n"););
374 return true;
375}
376
377/*
378 * Shutdown video
379 */
380void sysvid_shutdown(void)
381{
382 if (!isVideoInitialised)
383 {
384 return;
385 }
386
387#ifndef HAVE_LCD_COLOR
388 grey_show(false);
389 grey_release();
390
391 sysmem_pop(gbuf);
392#endif /* ndef HAVE_LCD_COLOR */
393 sysmem_pop(sysvid_fb);
394
395 /* Turn on backlight timeout (revert to settings) */
396 backlight_use_settings();
397
398 isVideoInitialised = false;
399 IFDEBUG_VIDEO(sys_printf("xrick/video: stop\n"););
400}
401
402/* eof */