Deleted Added
full compact
splash_pcx.c (45617) splash_pcx.c (48104)
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 *
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 * $Id$
30 * $Id: splash_pcx.c,v 1.1 1999/04/12 13:39:11 des Exp $
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/linker.h>
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/fbio.h>
37
38
38#include <machine/console.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(const 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, *palette;
65} pcx_info;
66
67static int
68pcx_start(video_adapter_t *adp)
69{
70 static int modes[] = {
71 M_VGA_CG320,
72 M_VESA_CG640x480,
73 M_VESA_CG800x600,
74 M_VESA_CG1024x768,
75 -1,
76 };
77 video_info_t info;
78 int i;
79
80 if (pcx_decoder.data == NULL
81 || pcx_decoder.data_size <= 0
82 || pcx_init((u_char *)pcx_decoder.data, pcx_decoder.data_size))
83 return ENODEV;
84
85 if (bootverbose)
86 printf("splash_pcx: image good:\n"
87 " width = %d\n"
88 " height = %d\n"
89 " depth = %d\n"
90 " planes = %d\n",
91 pcx_info.width, pcx_info.height,
92 pcx_info.bpp, pcx_info.planes);
93
94 for (i = 0; modes[i] >= 0; ++i) {
95 if (get_mode_info(adp, modes[i], &info) != 0)
96 continue;
97 if (bootverbose)
98 printf("splash_pcx: considering mode %d:\n"
99 " vi_width = %d\n"
100 " vi_height = %d\n"
101 " vi_depth = %d\n"
102 " vi_planes = %d\n",
103 modes[i],
104 info.vi_width, info.vi_height,
105 info.vi_depth, info.vi_planes);
106 if (info.vi_width >= pcx_info.width
107 && info.vi_height >= pcx_info.height
108 && info.vi_depth == pcx_info.bpp
109 && info.vi_planes == pcx_info.planes)
110 break;
111 }
112
113 splash_mode = modes[i];
114 if (splash_mode == -1)
115 return ENODEV;
116 if (bootverbose)
117 printf("pcx_splash: selecting mode %d\n", splash_mode);
118 return 0;
119}
120
121static int
122pcx_end(video_adapter_t *adp)
123{
124 /* nothing to do */
125 return 0;
126}
127
128static int
129pcx_splash(video_adapter_t *adp, int on)
130{
131 if (on) {
132 if (!splash_on) {
133 if (set_video_mode(adp, splash_mode) || pcx_draw(adp))
134 return 1;
135 splash_on = TRUE;
136 }
137 return 0;
138 } else {
139 splash_on = FALSE;
140 return 0;
141 }
142}
143
144struct pcxheader {
145 u_char manufactor;
146 u_char version;
147 u_char encoding;
148 u_char bpp;
149 u_short xmin, ymin, xmax, ymax;
150 u_short hres, vres;
151 u_char colormap[48];
152 u_char rsvd;
153 u_char nplanes;
154 u_short bpsl;
155 u_short palinfo;
156 u_short hsize, vsize;
157};
158
159#define MAXSCANLINE 1024
160
161static int
162pcx_init(const char *data, int size)
163{
164 const struct pcxheader *hdr;
165
166 hdr = (const struct pcxheader *)data;
167
168 if (size < 128 + 1 + 1 + 768
169 || hdr->manufactor != 10
170 || hdr->version != 5
171 || hdr->encoding != 1
172 || hdr->nplanes != 1
173 || hdr->bpp != 8
174 || hdr->bpsl > MAXSCANLINE
175 || data[size-769] != 12) {
176 printf("splash_pcx: invalid PCX image\n");
177 return 1;
178 }
179 pcx_info.width = hdr->xmax - hdr->xmin + 1;
180 pcx_info.height = hdr->ymax - hdr->ymin + 1;
181 pcx_info.bpsl = hdr->bpsl;
182 pcx_info.bpp = hdr->bpp;
183 pcx_info.planes = hdr->nplanes;
184 pcx_info.zlen = size - (128 + 1 + 768);
185 pcx_info.zdata = data + 128;
186 pcx_info.palette = data + size - 768;
187 return 0;
188}
189
190static int
191pcx_draw(video_adapter_t *adp)
192{
193 u_char *vidmem;
194 int swidth, sheight, sbpsl, sdepth, splanes;
195 int banksize, origin;
196 int c, i, j, pos, scan, x, y;
197 u_char line[MAXSCANLINE];
198
199 if (pcx_info.zlen < 1)
200 return 1;
201
202 load_palette(adp, pcx_info.palette);
203
204 vidmem = (u_char *)adp->va_window;
205 swidth = adp->va_info.vi_width;
206 sheight = adp->va_info.vi_height;
207 sbpsl = adp->va_line_width;
208 sdepth = adp->va_info.vi_depth;
209 splanes = adp->va_info.vi_planes;
210 banksize = adp->va_info.vi_window_size;
211
212 for (origin = 0; origin < sheight*sbpsl; origin += banksize) {
213 set_origin(adp, origin);
214 bzero(vidmem, banksize);
215 }
216
217 x = (swidth - pcx_info.width) / 2;
218 y = (sheight - pcx_info.height) / 2;
219 origin = 0;
220 pos = y * sbpsl + x;
221 while (pos > banksize) {
222 pos -= banksize;
223 origin += banksize;
224 }
225 set_origin(adp, origin);
226
227 for (scan = i = 0; scan < pcx_info.height; ++scan, ++y, pos += sbpsl) {
228 for (j = 0; j < pcx_info.bpsl && i < pcx_info.zlen; ++i) {
229 if ((pcx_info.zdata[i] & 0xc0) == 0xc0) {
230 c = pcx_info.zdata[i++] & 0x3f;
231 if (i >= pcx_info.zlen)
232 return 1;
233 } else {
234 c = 1;
235 }
236 if (j + c > pcx_info.bpsl)
237 return 1;
238 while (c--)
239 line[j++] = pcx_info.zdata[i];
240 }
241
242 if (pos > banksize) {
243 origin += banksize;
244 pos -= banksize;
245 set_origin(adp, origin);
246 }
247
248 if (pos + pcx_info.width > banksize) {
249 /* scanline crosses bank boundary */
250 j = banksize - pos;
251 bcopy(line, vidmem + pos, j);
252 origin += banksize;
253 pos -= banksize;
254 set_origin(adp, origin);
255 bcopy(line + j, vidmem, pcx_info.width - j);
256 } else {
257 bcopy(line, vidmem + pos, pcx_info.width);
258 }
259 }
260
261 return 0;
262}
39#include <dev/fb/fbreg.h>
40#include <dev/fb/splashreg.h>
41
42#define FADE_TIMEOUT 300 /* sec */
43
44static int splash_mode = -1;
45static int splash_on = FALSE;
46
47static int pcx_start(video_adapter_t *adp);
48static int pcx_end(video_adapter_t *adp);
49static int pcx_splash(video_adapter_t *adp, int on);
50static int pcx_init(const char *data, int sdepth);
51static int pcx_draw(video_adapter_t *adp);
52
53static splash_decoder_t pcx_decoder = {
54 "splash_pcx", pcx_start, pcx_end, pcx_splash, SPLASH_IMAGE,
55};
56
57SPLASH_DECODER(splash_pcx, pcx_decoder);
58
59static struct
60{
61 int width, height, bpsl;
62 int bpp, planes, zlen;
63 const u_char *zdata, *palette;
64} pcx_info;
65
66static int
67pcx_start(video_adapter_t *adp)
68{
69 static int modes[] = {
70 M_VGA_CG320,
71 M_VESA_CG640x480,
72 M_VESA_CG800x600,
73 M_VESA_CG1024x768,
74 -1,
75 };
76 video_info_t info;
77 int i;
78
79 if (pcx_decoder.data == NULL
80 || pcx_decoder.data_size <= 0
81 || pcx_init((u_char *)pcx_decoder.data, pcx_decoder.data_size))
82 return ENODEV;
83
84 if (bootverbose)
85 printf("splash_pcx: image good:\n"
86 " width = %d\n"
87 " height = %d\n"
88 " depth = %d\n"
89 " planes = %d\n",
90 pcx_info.width, pcx_info.height,
91 pcx_info.bpp, pcx_info.planes);
92
93 for (i = 0; modes[i] >= 0; ++i) {
94 if (get_mode_info(adp, modes[i], &info) != 0)
95 continue;
96 if (bootverbose)
97 printf("splash_pcx: considering mode %d:\n"
98 " vi_width = %d\n"
99 " vi_height = %d\n"
100 " vi_depth = %d\n"
101 " vi_planes = %d\n",
102 modes[i],
103 info.vi_width, info.vi_height,
104 info.vi_depth, info.vi_planes);
105 if (info.vi_width >= pcx_info.width
106 && info.vi_height >= pcx_info.height
107 && info.vi_depth == pcx_info.bpp
108 && info.vi_planes == pcx_info.planes)
109 break;
110 }
111
112 splash_mode = modes[i];
113 if (splash_mode == -1)
114 return ENODEV;
115 if (bootverbose)
116 printf("pcx_splash: selecting mode %d\n", splash_mode);
117 return 0;
118}
119
120static int
121pcx_end(video_adapter_t *adp)
122{
123 /* nothing to do */
124 return 0;
125}
126
127static int
128pcx_splash(video_adapter_t *adp, int on)
129{
130 if (on) {
131 if (!splash_on) {
132 if (set_video_mode(adp, splash_mode) || pcx_draw(adp))
133 return 1;
134 splash_on = TRUE;
135 }
136 return 0;
137 } else {
138 splash_on = FALSE;
139 return 0;
140 }
141}
142
143struct pcxheader {
144 u_char manufactor;
145 u_char version;
146 u_char encoding;
147 u_char bpp;
148 u_short xmin, ymin, xmax, ymax;
149 u_short hres, vres;
150 u_char colormap[48];
151 u_char rsvd;
152 u_char nplanes;
153 u_short bpsl;
154 u_short palinfo;
155 u_short hsize, vsize;
156};
157
158#define MAXSCANLINE 1024
159
160static int
161pcx_init(const char *data, int size)
162{
163 const struct pcxheader *hdr;
164
165 hdr = (const struct pcxheader *)data;
166
167 if (size < 128 + 1 + 1 + 768
168 || hdr->manufactor != 10
169 || hdr->version != 5
170 || hdr->encoding != 1
171 || hdr->nplanes != 1
172 || hdr->bpp != 8
173 || hdr->bpsl > MAXSCANLINE
174 || data[size-769] != 12) {
175 printf("splash_pcx: invalid PCX image\n");
176 return 1;
177 }
178 pcx_info.width = hdr->xmax - hdr->xmin + 1;
179 pcx_info.height = hdr->ymax - hdr->ymin + 1;
180 pcx_info.bpsl = hdr->bpsl;
181 pcx_info.bpp = hdr->bpp;
182 pcx_info.planes = hdr->nplanes;
183 pcx_info.zlen = size - (128 + 1 + 768);
184 pcx_info.zdata = data + 128;
185 pcx_info.palette = data + size - 768;
186 return 0;
187}
188
189static int
190pcx_draw(video_adapter_t *adp)
191{
192 u_char *vidmem;
193 int swidth, sheight, sbpsl, sdepth, splanes;
194 int banksize, origin;
195 int c, i, j, pos, scan, x, y;
196 u_char line[MAXSCANLINE];
197
198 if (pcx_info.zlen < 1)
199 return 1;
200
201 load_palette(adp, pcx_info.palette);
202
203 vidmem = (u_char *)adp->va_window;
204 swidth = adp->va_info.vi_width;
205 sheight = adp->va_info.vi_height;
206 sbpsl = adp->va_line_width;
207 sdepth = adp->va_info.vi_depth;
208 splanes = adp->va_info.vi_planes;
209 banksize = adp->va_info.vi_window_size;
210
211 for (origin = 0; origin < sheight*sbpsl; origin += banksize) {
212 set_origin(adp, origin);
213 bzero(vidmem, banksize);
214 }
215
216 x = (swidth - pcx_info.width) / 2;
217 y = (sheight - pcx_info.height) / 2;
218 origin = 0;
219 pos = y * sbpsl + x;
220 while (pos > banksize) {
221 pos -= banksize;
222 origin += banksize;
223 }
224 set_origin(adp, origin);
225
226 for (scan = i = 0; scan < pcx_info.height; ++scan, ++y, pos += sbpsl) {
227 for (j = 0; j < pcx_info.bpsl && i < pcx_info.zlen; ++i) {
228 if ((pcx_info.zdata[i] & 0xc0) == 0xc0) {
229 c = pcx_info.zdata[i++] & 0x3f;
230 if (i >= pcx_info.zlen)
231 return 1;
232 } else {
233 c = 1;
234 }
235 if (j + c > pcx_info.bpsl)
236 return 1;
237 while (c--)
238 line[j++] = pcx_info.zdata[i];
239 }
240
241 if (pos > banksize) {
242 origin += banksize;
243 pos -= banksize;
244 set_origin(adp, origin);
245 }
246
247 if (pos + pcx_info.width > banksize) {
248 /* scanline crosses bank boundary */
249 j = banksize - pos;
250 bcopy(line, vidmem + pos, j);
251 origin += banksize;
252 pos -= banksize;
253 set_origin(adp, origin);
254 bcopy(line + j, vidmem, pcx_info.width - j);
255 } else {
256 bcopy(line, vidmem + pos, pcx_info.width);
257 }
258 }
259
260 return 0;
261}