summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2009-02-10 23:47:24 +0000
committerJens Arnold <amiconn@rockbox.org>2009-02-10 23:47:24 +0000
commit7ddcce11063bc42179fc112f1ab40bd327ca79bc (patch)
tree46fd3e50687a1244a430f0a7c782fff256049900
parent11ad7b4bc8bcb049040c02fae04074faf5dfaf27 (diff)
downloadrockbox-7ddcce11063bc42179fc112f1ab40bd327ca79bc.tar.gz
rockbox-7ddcce11063bc42179fc112f1ab40bd327ca79bc.zip
Forgot to add the new screendump source files.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19968 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/screendump.h62
-rw-r--r--firmware/screendump.c371
2 files changed, 433 insertions, 0 deletions
diff --git a/firmware/export/screendump.h b/firmware/export/screendump.h
new file mode 100644
index 0000000000..515db08a70
--- /dev/null
+++ b/firmware/export/screendump.h
@@ -0,0 +1,62 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
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#ifndef __SCREENDUMP_H__
23#define __SCREENDUMP_H__
24
25#include "config.h"
26
27/* Make BMP colour map entries from R, G, B triples, without and with blending.
28 * Not within HAVE_LCD_BITMAP because it is also used for the Player sim */
29#define RED_CMP(c) (((c) >> 16) & 0xff)
30#define GREEN_CMP(c) (((c) >> 8) & 0xff)
31#define BLUE_CMP(c) ((c) & 0xff)
32
33#define BMP_COLOR(c) BLUE_CMP(c), GREEN_CMP(c), RED_CMP(c), 0
34#define BMP_COLOR_MIX(c1, c2, num, den) \
35 (BLUE_CMP(c2) - BLUE_CMP(c1)) * (num) / (den) + BLUE_CMP(c1), \
36 (GREEN_CMP(c2) - GREEN_CMP(c1)) * (num) / (den) + GREEN_CMP(c1), \
37 (RED_CMP(c2) - RED_CMP(c1)) * (num) / (den) + RED_CMP(c1), 0
38
39#define LE16_CONST(x) (x)&0xff, ((x)>>8)&0xff
40#define LE32_CONST(x) (x)&0xff, ((x)>>8)&0xff, ((x)>>16)&0xff, ((x)>>24)&0xff
41
42
43#ifdef BOOTLOADER
44
45#define screen_dump()
46#define remote_screen_dump()
47
48#else /* !BOOTLOADER */
49
50#ifdef HAVE_LCD_BITMAP
51/* Save a .BMP file containing the current screen contents. */
52void screen_dump(void);
53void screen_dump_set_hook(void (*hook)(int fd));
54#endif
55#ifdef HAVE_REMOTE_LCD
56/* Save a .BMP file containing the current remote screen contents. */
57void remote_screen_dump(void);
58#endif
59
60#endif /* !BOOTLOADER */
61
62#endif /* __SCREENDUMP_H__ */
diff --git a/firmware/screendump.c b/firmware/screendump.c
new file mode 100644
index 0000000000..3a3985505e
--- /dev/null
+++ b/firmware/screendump.c
@@ -0,0 +1,371 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
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 "screendump.h"
24
25#include "file.h"
26#include "general.h"
27#include "lcd.h"
28#include "stdlib.h"
29#include "string.h"
30#include "system.h"
31
32#ifdef HAVE_REMOTE_LCD
33#include "lcd-remote.h"
34#endif
35
36#if LCD_DEPTH == 16
37#define BMP_COMPRESSION 3 /* BI_BITFIELDS */
38#define BMP_NUMCOLORS 3
39#else /* LCD_DEPTH != 16 */
40#define BMP_COMPRESSION 0 /* BI_RGB */
41#if LCD_DEPTH <= 8
42#ifdef HAVE_LCD_SPLIT
43#define BMP_NUMCOLORS (2 << LCD_DEPTH)
44#else
45#define BMP_NUMCOLORS (1 << LCD_DEPTH)
46#endif
47#else /* LCD_DEPTH > 8 */
48#define BMP_NUMCOLORS 0
49#endif /* LCD_DEPTH > 8 */
50#endif /* LCD_DEPTH != 16 */
51
52#if LCD_DEPTH <= 4
53#define BMP_BPP 4
54#define BMP_LINESIZE ((LCD_WIDTH/2 + 3) & ~3)
55#elif LCD_DEPTH <= 8
56#define BMP_BPP 8
57#define BMP_LINESIZE ((LCD_WIDTH + 3) & ~3)
58#elif LCD_DEPTH <= 16
59#define BMP_BPP 16
60#define BMP_LINESIZE ((LCD_WIDTH*2 + 3) & ~3)
61#else
62#define BMP_BPP 24
63#define BMP_LINESIZE ((LCD_WIDTH*3 + 3) & ~3)
64#endif
65
66#define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS)
67#define BMP_DATASIZE (BMP_LINESIZE * (LCD_HEIGHT+LCD_SPLIT_LINES))
68#define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE)
69
70static const unsigned char bmpheader[] =
71{
72 0x42, 0x4d, /* 'BM' */
73 LE32_CONST(BMP_TOTALSIZE), /* Total file size */
74 0x00, 0x00, 0x00, 0x00, /* Reserved */
75 LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */
76
77 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
78 LE32_CONST(LCD_WIDTH), /* Width in pixels */
79 LE32_CONST(LCD_HEIGHT+LCD_SPLIT_LINES), /* Height in pixels */
80 0x01, 0x00, /* Number of planes (always 1) */
81 LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */
82 LE32_CONST(BMP_COMPRESSION),/* Compression mode */
83 LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */
84 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
85 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
86 LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */
87 LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */
88
89#if LCD_DEPTH == 1
90#ifdef HAVE_NEGATIVE_LCD
91 BMP_COLOR(LCD_BL_DARKCOLOR),
92 BMP_COLOR(LCD_BL_BRIGHTCOLOR),
93#ifdef HAVE_LCD_SPLIT
94 BMP_COLOR(LCD_BL_DARKCOLOR_2),
95 BMP_COLOR(LCD_BL_BRIGHTCOLOR_2),
96#endif
97#else /* positive display */
98 BMP_COLOR(LCD_BL_BRIGHTCOLOR),
99 BMP_COLOR(LCD_BL_DARKCOLOR),
100#endif /* positive display */
101#elif LCD_DEPTH == 2
102 BMP_COLOR(LCD_BL_BRIGHTCOLOR),
103 BMP_COLOR_MIX(LCD_BL_BRIGHTCOLOR, LCD_BL_DARKCOLOR, 1, 3),
104 BMP_COLOR_MIX(LCD_BL_BRIGHTCOLOR, LCD_BL_DARKCOLOR, 2, 3),
105 BMP_COLOR(LCD_BL_DARKCOLOR),
106#elif LCD_DEPTH == 16
107 0x00, 0xf8, 0x00, 0x00, /* red bitfield mask */
108 0xe0, 0x07, 0x00, 0x00, /* green bitfield mask */
109 0x1f, 0x00, 0x00, 0x00, /* blue bitfield mask */
110#endif
111};
112
113static void (*screen_dump_hook)(int fh) = NULL;
114
115void screen_dump(void)
116{
117 int fd, y;
118 char filename[MAX_PATH];
119
120 fb_data *src;
121#if LCD_DEPTH == 1
122 unsigned mask;
123 unsigned val;
124#elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT != HORIZONTAL_PACKING)
125 int shift;
126 unsigned val;
127#endif
128#if LCD_DEPTH <= 8
129 unsigned char *dst, *dst_end;
130 unsigned char linebuf[BMP_LINESIZE];
131#elif LCD_DEPTH <= 16
132 unsigned short *dst, *dst_end;
133 unsigned short linebuf[BMP_LINESIZE/2];
134#endif
135
136#if CONFIG_RTC
137 create_datetime_filename(filename, "", "dump ", ".bmp", false);
138#else
139 create_numbered_filename(filename, "", "dump_", ".bmp", 4
140 IF_CNFN_NUM_(, NULL));
141#endif
142
143 fd = creat(filename);
144 if (fd < 0)
145 return;
146
147 if (screen_dump_hook)
148 {
149 screen_dump_hook(fd);
150 }
151 else
152 {
153 write(fd, bmpheader, sizeof(bmpheader));
154
155 /* BMP image goes bottom up */
156 for (y = LCD_HEIGHT - 1; y >= 0; y--)
157 {
158 memset(linebuf, 0, BMP_LINESIZE);
159
160#if defined(HAVE_LCD_SPLIT) && (LCD_SPLIT_LINES == 2)
161 if (y == LCD_SPLIT_POS - 1)
162 {
163 write(fd, linebuf, BMP_LINESIZE);
164 write(fd, linebuf, BMP_LINESIZE);
165 }
166#endif
167 dst = linebuf;
168
169#if LCD_DEPTH == 1
170 dst_end = dst + LCD_WIDTH/2;
171 src = lcd_framebuffer[y >> 3];
172 mask = 1 << (y & 7);
173
174 do
175 {
176 val = (*src++ & mask) ? 0x10 : 0;
177 val |= (*src++ & mask) ? 0x01 : 0;
178#ifdef HAVE_LCD_SPLIT
179 if (y < LCD_SPLIT_POS)
180 val |= 0x22;
181#endif
182 *dst++ = val;
183 }
184 while (dst < dst_end);
185
186#elif LCD_DEPTH == 2
187 dst_end = dst + LCD_WIDTH/2;
188
189#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
190 src = lcd_framebuffer[y];
191
192 do
193 {
194 unsigned data = *src++;
195
196 *dst++ = ((data >> 2) & 0x30) | ((data >> 4) & 0x03);
197 *dst++ = ((data << 2) & 0x30) | (data & 0x03);
198 }
199 while (dst < dst_end);
200
201#elif LCD_PIXELFORMAT == VERTICAL_PACKING
202 src = lcd_framebuffer[y >> 2];
203 shift = 2 * (y & 3);
204
205 do
206 {
207 val = ((*src++ >> shift) & 3) << 4;
208 val |= ((*src++ >> shift) & 3);
209 *dst++ = val;
210 }
211 while (dst < dst_end);
212
213#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
214 src = lcd_framebuffer[y >> 3];
215 shift = y & 7;
216
217 do
218 {
219 unsigned data = (*src++ >> shift) & 0x0101;
220
221 val = (((data >> 7) | data) & 3) << 4;
222 data = (*src++ >> shift) & 0x0101;
223 val |= ((data >> 7) | data) & 3;
224 *dst++ = val;
225 }
226 while (dst < dst_end);
227
228#endif
229#elif LCD_DEPTH == 16
230 dst_end = dst + LCD_WIDTH;
231 src = lcd_framebuffer[y];
232
233 do
234 {
235#if (LCD_PIXELFORMAT == RGB565SWAPPED)
236 /* iPod LCD data is big endian although the CPU is not */
237 *dst++ = htobe16(*src++);
238#else
239 *dst++ = htole16(*src++);
240#endif
241 }
242 while (dst < dst_end);
243
244#endif /* LCD_DEPTH */
245 write(fd, linebuf, BMP_LINESIZE);
246 }
247 }
248 close(fd);
249}
250
251void screen_dump_set_hook(void (*hook)(int fh))
252{
253 screen_dump_hook = hook;
254}
255
256#ifdef HAVE_REMOTE_LCD
257
258#define RBMP_COMPRESSION 0 /* BI_RGB */
259#define RBMP_NUMCOLORS (1 << LCD_REMOTE_DEPTH)
260#define RBMP_BPP 4
261#define RBMP_LINESIZE ((LCD_REMOTE_WIDTH/2 + 3) & ~3)
262
263#define RBMP_HEADERSIZE (54 + 4 * RBMP_NUMCOLORS)
264#define RBMP_DATASIZE (RBMP_LINESIZE * LCD_REMOTE_HEIGHT)
265#define RBMP_TOTALSIZE (RBMP_HEADERSIZE + RBMP_DATASIZE)
266
267static const unsigned char rbmpheader[] =
268{
269 0x42, 0x4d, /* 'BM' */
270 LE32_CONST(RBMP_TOTALSIZE), /* Total file size */
271 0x00, 0x00, 0x00, 0x00, /* Reserved */
272 LE32_CONST(RBMP_HEADERSIZE), /* Offset to start of pixel data */
273
274 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
275 LE32_CONST(LCD_REMOTE_WIDTH), /* Width in pixels */
276 LE32_CONST(LCD_REMOTE_HEIGHT), /* Height in pixels */
277 0x01, 0x00, /* Number of planes (always 1) */
278 LE16_CONST(RBMP_BPP), /* Bits per pixel 1/4/8/16/24 */
279 LE32_CONST(RBMP_COMPRESSION), /* Compression mode */
280 LE32_CONST(RBMP_DATASIZE), /* Size of bitmap data */
281 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
282 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
283 LE32_CONST(RBMP_NUMCOLORS), /* Number of used colours */
284 LE32_CONST(RBMP_NUMCOLORS), /* Number of important colours */
285
286#if LCD_REMOTE_DEPTH == 1
287 BMP_COLOR(LCD_REMOTE_BL_BRIGHTCOLOR),
288 BMP_COLOR(LCD_REMOTE_BL_DARKCOLOR),
289#elif LCD_REMOTE_DEPTH == 2
290 BMP_COLOR(LCD_REMOTE_BL_BRIGHTCOLOR),
291 BMP_COLOR_MIX(LCD_REMOTE_BL_BRIGHTCOLOR, LCD_REMOTE_BL_DARKCOLOR, 1, 3),
292 BMP_COLOR_MIX(LCD_REMOTE_BL_BRIGHTCOLOR, LCD_REMOTE_BL_DARKCOLOR, 2, 3),
293 BMP_COLOR(LCD_REMOTE_BL_DARKCOLOR),
294#endif
295};
296
297void remote_screen_dump(void)
298{
299 int fd, y;
300 char filename[MAX_PATH];
301
302 fb_remote_data *src;
303#if LCD_REMOTE_DEPTH == 1
304 unsigned mask;
305 unsigned val;
306#elif LCD_REMOTE_DEPTH == 2
307 int shift;
308 unsigned val;
309#endif
310 unsigned char *dst, *dst_end;
311 unsigned char linebuf[RBMP_LINESIZE];
312
313#if CONFIG_RTC
314 create_datetime_filename(filename, "", "rdump ", ".bmp", false);
315#else
316 create_numbered_filename(filename, "", "rdump_", ".bmp", 4
317 IF_CNFN_NUM_(, NULL));
318#endif
319
320 fd = creat(filename);
321 if (fd < 0)
322 return;
323
324 write(fd, rbmpheader, sizeof(rbmpheader));
325
326 /* BMP image goes bottom up */
327 for (y = LCD_REMOTE_HEIGHT - 1; y >= 0; y--)
328 {
329 memset(linebuf, 0, RBMP_LINESIZE);
330
331 dst = linebuf;
332
333#if LCD_REMOTE_DEPTH == 1
334 dst_end = dst + LCD_REMOTE_WIDTH/2;
335 src = lcd_remote_framebuffer[y >> 3];
336 mask = 1 << (y & 7);
337
338 do
339 {
340 val = (*src++ & mask) ? 0x10 : 0;
341 val |= (*src++ & mask) ? 0x01 : 0;
342 *dst++ = val;
343 }
344 while (dst < dst_end);
345
346#elif LCD_REMOTE_DEPTH == 2
347 dst_end = dst + LCD_REMOTE_WIDTH/2;
348
349#if LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED
350 src = lcd_remote_framebuffer[y >> 3];
351 shift = y & 7;
352
353 do
354 {
355 unsigned data = (*src++ >> shift) & 0x0101;
356
357 val = (((data >> 7) | data) & 3) << 4;
358 data = (*src++ >> shift) & 0x0101;
359 val |= ((data >> 7) | data) & 3;
360 *dst++ = val;
361 }
362 while (dst < dst_end);
363
364#endif
365#endif /* LCD_REMOTE_DEPTH */
366 write(fd, linebuf, RBMP_LINESIZE);
367 }
368 close(fd);
369}
370
371#endif /* HAVE_REMOTE_LCD */