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