Deleted Added
sdiff udiff text old ( 106766 ) new ( 129880 )
full compact
1/*-
2 * Copyright (c) 1999 Michael Smith <msmith@freebsd.org>
3 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@freebsd.org>
4 * Copyright (c) 1999 Dag-Erling Co�dan Sm�rgrav
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in this position and unchanged.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $FreeBSD: head/sys/dev/fb/splash_pcx.c 129880 2004-05-30 20:27:19Z phk $
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/linker.h>
37#include <sys/module.h>
38#include <sys/fbio.h>
39
40#include <dev/fb/fbreg.h>
41#include <dev/fb/splashreg.h>
42
43#define FADE_TIMEOUT 300 /* sec */
44
45static int splash_mode = -1;
46static int splash_on = FALSE;
47
48static int pcx_start(video_adapter_t *adp);
49static int pcx_end(video_adapter_t *adp);
50static int pcx_splash(video_adapter_t *adp, int on);
51static int pcx_init(char *data, int sdepth);
52static int pcx_draw(video_adapter_t *adp);
53
54static splash_decoder_t pcx_decoder = {
55 "splash_pcx", pcx_start, pcx_end, pcx_splash, SPLASH_IMAGE,
56};
57
58SPLASH_DECODER(splash_pcx, pcx_decoder);
59
60static struct
61{
62 int width, height, bpsl;
63 int bpp, planes, zlen;
64 const u_char *zdata;
65 u_char *palette;
66} pcx_info;
67
68static int
69pcx_start(video_adapter_t *adp)
70{
71 static int modes[] = {
72 M_VGA_CG320,
73 M_VESA_CG640x480,
74 M_VESA_CG800x600,
75 M_VESA_CG1024x768,
76 -1,
77 };
78 video_info_t info;
79 int i;
80
81 if (pcx_decoder.data == NULL
82 || pcx_decoder.data_size <= 0
83 || pcx_init((u_char *)pcx_decoder.data, pcx_decoder.data_size))
84 return ENODEV;
85
86 if (bootverbose)
87 printf("splash_pcx: image good:\n"
88 " width = %d\n"
89 " height = %d\n"
90 " depth = %d\n"
91 " planes = %d\n",
92 pcx_info.width, pcx_info.height,
93 pcx_info.bpp, pcx_info.planes);
94
95 for (i = 0; modes[i] >= 0; ++i) {
96 if (get_mode_info(adp, modes[i], &info) != 0)
97 continue;
98 if (bootverbose)
99 printf("splash_pcx: considering mode %d:\n"
100 " vi_width = %d\n"
101 " vi_height = %d\n"
102 " vi_depth = %d\n"
103 " vi_planes = %d\n",
104 modes[i],
105 info.vi_width, info.vi_height,
106 info.vi_depth, info.vi_planes);
107 if (info.vi_width >= pcx_info.width
108 && info.vi_height >= pcx_info.height
109 && info.vi_depth == pcx_info.bpp
110 && info.vi_planes == pcx_info.planes)
111 break;
112 }
113
114 splash_mode = modes[i];
115 if (splash_mode == -1)
116 return ENODEV;
117 if (bootverbose)
118 printf("pcx_splash: selecting mode %d\n", splash_mode);
119 return 0;
120}
121
122static int
123pcx_end(video_adapter_t *adp)
124{
125 /* nothing to do */
126 return 0;
127}
128
129static int
130pcx_splash(video_adapter_t *adp, int on)
131{
132 if (on) {
133 if (!splash_on) {
134 if (set_video_mode(adp, splash_mode) || pcx_draw(adp))
135 return 1;
136 splash_on = TRUE;
137 }
138 return 0;
139 } else {
140 splash_on = FALSE;
141 return 0;
142 }
143}
144
145struct pcxheader {
146 u_char manufactor;
147 u_char version;
148 u_char encoding;
149 u_char bpp;
150 u_short xmin, ymin, xmax, ymax;
151 u_short hres, vres;
152 u_char colormap[48];
153 u_char rsvd;
154 u_char nplanes;
155 u_short bpsl;
156 u_short palinfo;
157 u_short hsize, vsize;
158};
159
160#define MAXSCANLINE 1024
161
162static int
163pcx_init(char *data, int size)
164{
165 const struct pcxheader *hdr;
166
167 hdr = (const struct pcxheader *)data;
168
169 if (size < 128 + 1 + 1 + 768
170 || hdr->manufactor != 10
171 || hdr->version != 5
172 || hdr->encoding != 1
173 || hdr->nplanes != 1
174 || hdr->bpp != 8
175 || hdr->bpsl > MAXSCANLINE
176 || data[size-769] != 12) {
177 printf("splash_pcx: invalid PCX image\n");
178 return 1;
179 }
180 pcx_info.width = hdr->xmax - hdr->xmin + 1;
181 pcx_info.height = hdr->ymax - hdr->ymin + 1;
182 pcx_info.bpsl = hdr->bpsl;
183 pcx_info.bpp = hdr->bpp;
184 pcx_info.planes = hdr->nplanes;
185 pcx_info.zlen = size - (128 + 1 + 768);
186 pcx_info.zdata = data + 128;
187 pcx_info.palette = data + size - 768;
188 return 0;
189}
190
191static int
192pcx_draw(video_adapter_t *adp)
193{
194 u_char *vidmem;
195 int swidth, sheight, sbpsl, sdepth, splanes;
196 int banksize, origin;
197 int c, i, j, pos, scan, x, y;
198 u_char line[MAXSCANLINE];
199
200 if (pcx_info.zlen < 1)
201 return 1;
202
203 load_palette(adp, pcx_info.palette);
204
205 vidmem = (u_char *)adp->va_window;
206 swidth = adp->va_info.vi_width;
207 sheight = adp->va_info.vi_height;
208 sbpsl = adp->va_line_width;
209 sdepth = adp->va_info.vi_depth;
210 splanes = adp->va_info.vi_planes;
211 banksize = adp->va_window_size;
212
213 for (origin = 0; origin < sheight*sbpsl; origin += banksize) {
214 set_origin(adp, origin);
215 bzero(vidmem, banksize);
216 }
217
218 x = (swidth - pcx_info.width) / 2;
219 y = (sheight - pcx_info.height) / 2;
220 origin = 0;
221 pos = y * sbpsl + x;
222 while (pos > banksize) {
223 pos -= banksize;
224 origin += banksize;
225 }
226 set_origin(adp, origin);
227
228 for (scan = i = 0; scan < pcx_info.height; ++scan, ++y, pos += sbpsl) {
229 for (j = 0; j < pcx_info.bpsl && i < pcx_info.zlen; ++i) {
230 if ((pcx_info.zdata[i] & 0xc0) == 0xc0) {
231 c = pcx_info.zdata[i++] & 0x3f;
232 if (i >= pcx_info.zlen)
233 return 1;
234 } else {
235 c = 1;
236 }
237 if (j + c > pcx_info.bpsl)
238 return 1;
239 while (c--)
240 line[j++] = pcx_info.zdata[i];
241 }
242
243 if (pos > banksize) {
244 origin += banksize;
245 pos -= banksize;
246 set_origin(adp, origin);
247 }
248
249 if (pos + pcx_info.width > banksize) {
250 /* scanline crosses bank boundary */
251 j = banksize - pos;
252 bcopy(line, vidmem + pos, j);
253 origin += banksize;
254 pos -= banksize;
255 set_origin(adp, origin);
256 bcopy(line + j, vidmem, pcx_info.width - j);
257 } else {
258 bcopy(line, vidmem + pos, pcx_info.width);
259 }
260 }
261
262 return 0;
263}