Commit | Line | Data |
---|---|---|
984263bc | 1 | /*- |
22ff886e AH |
2 | * (MPSAFE) |
3 | * | |
984263bc MD |
4 | * Copyright (c) 1999 Michael Smith <msmith@freebsd.org> |
5 | * Copyright (c) 1999 Kazutaka YOKOTA <yokota@freebsd.org> | |
6 | * All rights reserved. | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
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 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE | |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | |
28 | * | |
29 | * $FreeBSD: src/sys/modules/splash/bmp/splash_bmp.c,v 1.10.2.3 2000/10/31 08:00:06 nyan Exp $ | |
30 | */ | |
31 | ||
32 | #include <sys/param.h> | |
33 | #include <sys/systm.h> | |
34 | #include <sys/kernel.h> | |
35 | #include <sys/linker.h> | |
36 | #include <sys/fbio.h> | |
22ff886e | 37 | #include <sys/thread.h> |
984263bc | 38 | |
ac2e3f5e MD |
39 | #include <dev/video/fb/fbreg.h> |
40 | #include <dev/video/fb/splashreg.h> | |
ac2e3f5e | 41 | #include <dev/video/fb/vgareg.h> |
984263bc | 42 | |
1f2de5d4 | 43 | #include <bus/isa/isareg.h> |
984263bc MD |
44 | |
45 | #define FADE_TIMEOUT 15 /* sec */ | |
46 | #define FADE_LEVELS 10 | |
47 | ||
48 | static int splash_mode = -1; | |
49 | static int splash_on = FALSE; | |
50 | ||
1692d8ef SW |
51 | static int bmp_start(video_adapter_t *); |
52 | static int bmp_end(video_adapter_t *); | |
53 | static int bmp_splash(video_adapter_t *, int); | |
54 | static int bmp_Init(const char *, int, int, int); | |
55 | static int bmp_Draw(video_adapter_t *); | |
984263bc MD |
56 | |
57 | static splash_decoder_t bmp_decoder = { | |
58 | "splash_bmp", bmp_start, bmp_end, bmp_splash, SPLASH_IMAGE, | |
59 | }; | |
60 | ||
61 | SPLASH_DECODER(splash_bmp, bmp_decoder); | |
62 | ||
63 | static int | |
64 | bmp_start(video_adapter_t *adp) | |
65 | { | |
66 | /* currently only 256-color modes are supported XXX */ | |
67 | static int modes[] = { | |
984263bc MD |
68 | M_CG640x480, |
69 | /* | |
70 | * As 320x200 doesn't generally look great, | |
71 | * it's least preferred here. | |
72 | */ | |
73 | M_VGA_CG320, | |
984263bc MD |
74 | -1, |
75 | }; | |
76 | video_info_t info; | |
77 | int i; | |
78 | ||
2efb75f3 | 79 | lwkt_gettoken(&vga_token); |
984263bc | 80 | if ((bmp_decoder.data == NULL) || (bmp_decoder.data_size <= 0)) { |
e3869ec7 | 81 | kprintf("splash_bmp: No bitmap file found\n"); |
2efb75f3 | 82 | lwkt_reltoken(&vga_token); |
984263bc MD |
83 | return ENODEV; |
84 | } | |
85 | for (i = 0; modes[i] >= 0; ++i) { | |
86 | if (((*vidsw[adp->va_index]->get_info)(adp, modes[i], &info) == 0) | |
87 | && (bmp_Init((u_char *)bmp_decoder.data, | |
88 | info.vi_width, info.vi_height, info.vi_depth) == 0)) | |
89 | break; | |
90 | } | |
91 | splash_mode = modes[i]; | |
92 | if (splash_mode < 0) | |
e3869ec7 | 93 | kprintf("splash_bmp: No appropriate video mode found\n"); |
984263bc | 94 | if (bootverbose) |
e3869ec7 | 95 | kprintf("bmp_start(): splash_mode:%d\n", splash_mode); |
2efb75f3 | 96 | lwkt_reltoken(&vga_token); |
984263bc MD |
97 | return ((splash_mode < 0) ? ENODEV : 0); |
98 | } | |
99 | ||
100 | static int | |
101 | bmp_end(video_adapter_t *adp) | |
102 | { | |
103 | /* nothing to do */ | |
104 | return 0; | |
105 | } | |
106 | ||
107 | static int | |
108 | bmp_splash(video_adapter_t *adp, int on) | |
109 | { | |
110 | static u_char pal[256*3]; | |
111 | static long time_stamp; | |
112 | u_char tpal[256*3]; | |
113 | static int fading = TRUE, brightness = FADE_LEVELS; | |
114 | struct timeval tv; | |
115 | int i; | |
116 | ||
2efb75f3 | 117 | lwkt_gettoken(&vga_token); |
984263bc MD |
118 | if (on) { |
119 | if (!splash_on) { | |
120 | /* set up the video mode and draw something */ | |
22ff886e | 121 | if ((*vidsw[adp->va_index]->set_mode)(adp, splash_mode)) { |
2efb75f3 | 122 | lwkt_reltoken(&vga_token); |
984263bc | 123 | return 1; |
22ff886e AH |
124 | } |
125 | if (bmp_Draw(adp)) { | |
2efb75f3 | 126 | lwkt_reltoken(&vga_token); |
984263bc | 127 | return 1; |
22ff886e | 128 | } |
984263bc MD |
129 | (*vidsw[adp->va_index]->save_palette)(adp, pal); |
130 | time_stamp = 0; | |
131 | splash_on = TRUE; | |
132 | } | |
133 | /* | |
134 | * This is a kludge to fade the image away. This section of the | |
135 | * code takes effect only after the system is completely up. | |
136 | * FADE_TIMEOUT should be configurable. | |
137 | */ | |
138 | if (!cold) { | |
139 | getmicrotime(&tv); | |
140 | if (time_stamp == 0) | |
141 | time_stamp = tv.tv_sec; | |
142 | if (tv.tv_sec > time_stamp + FADE_TIMEOUT) { | |
143 | if (fading) | |
144 | if (brightness == 0) { | |
145 | fading = FALSE; | |
146 | brightness++; | |
147 | } | |
148 | else brightness--; | |
149 | else | |
150 | if (brightness == FADE_LEVELS) { | |
151 | fading = TRUE; | |
152 | brightness--; | |
153 | } | |
154 | else brightness++; | |
155 | for (i = 0; i < sizeof(pal); ++i) { | |
156 | tpal[i] = pal[i] * brightness / FADE_LEVELS; | |
157 | } | |
158 | (*vidsw[adp->va_index]->load_palette)(adp, tpal); | |
159 | time_stamp = tv.tv_sec; | |
160 | } | |
161 | } | |
2efb75f3 | 162 | lwkt_reltoken(&vga_token); |
984263bc MD |
163 | return 0; |
164 | } else { | |
165 | /* the video mode will be restored by the caller */ | |
166 | splash_on = FALSE; | |
2efb75f3 | 167 | lwkt_reltoken(&vga_token); |
984263bc MD |
168 | return 0; |
169 | } | |
170 | } | |
171 | ||
172 | /* | |
173 | ** Code to handle Microsoft DIB (".BMP") format images. | |
174 | ** | |
175 | ** Blame me (msmith@freebsd.org) if this is broken, not Soren. | |
176 | */ | |
177 | ||
178 | typedef struct tagBITMAPFILEHEADER { /* bmfh */ | |
993c9e7a SW |
179 | u_short bfType; |
180 | int bfSize; | |
181 | u_short bfReserved1; | |
182 | u_short bfReserved2; | |
183 | int bfOffBits; | |
184 | } __packed BITMAPFILEHEADER; | |
984263bc MD |
185 | |
186 | typedef struct tagBITMAPINFOHEADER { /* bmih */ | |
993c9e7a SW |
187 | int biSize; |
188 | int biWidth; | |
189 | int biHeight; | |
190 | short biPlanes; | |
191 | short biBitCount; | |
192 | int biCompression; | |
193 | int biSizeImage; | |
194 | int biXPelsPerMeter; | |
195 | int biYPelsPerMeter; | |
196 | int biClrUsed; | |
197 | int biClrImportant; | |
198 | } __packed BITMAPINFOHEADER; | |
984263bc MD |
199 | |
200 | typedef struct tagRGBQUAD { /* rgbq */ | |
993c9e7a SW |
201 | u_char rgbBlue; |
202 | u_char rgbGreen; | |
203 | u_char rgbRed; | |
204 | u_char rgbReserved; | |
205 | } __packed RGBQUAD; | |
984263bc MD |
206 | |
207 | typedef struct tagBITMAPINFO { /* bmi */ | |
993c9e7a SW |
208 | BITMAPINFOHEADER bmiHeader; |
209 | RGBQUAD bmiColors[256]; | |
210 | } __packed BITMAPINFO; | |
984263bc MD |
211 | |
212 | typedef struct tagBITMAPF | |
213 | { | |
993c9e7a SW |
214 | BITMAPFILEHEADER bmfh; |
215 | BITMAPINFO bmfi; | |
216 | } __packed BITMAPF; | |
984263bc MD |
217 | |
218 | #define BI_RGB 0 | |
219 | #define BI_RLE8 1 | |
220 | #define BI_RLE4 2 | |
221 | ||
222 | /* | |
223 | ** all we actually care about the image | |
224 | */ | |
225 | typedef struct | |
226 | { | |
227 | int width,height; /* image dimensions */ | |
228 | int swidth,sheight; /* screen dimensions for the current mode */ | |
229 | u_char depth; /* image depth (1, 4, 8, 24 bits) */ | |
230 | u_char sdepth; /* screen depth (1, 4, 8 bpp) */ | |
231 | int ncols; /* number of colours */ | |
232 | u_char palette[256][3]; /* raw palette data */ | |
233 | u_char format; /* one of the BI_* constants above */ | |
e7cb9e6a JS |
234 | const u_char *data; /* pointer to the raw data */ |
235 | const u_char *index; /* running pointer to the data while drawing */ | |
984263bc MD |
236 | u_char *vidmem; /* video memory allocated for drawing */ |
237 | video_adapter_t *adp; | |
238 | int bank; | |
984263bc MD |
239 | } BMP_INFO; |
240 | ||
241 | static BMP_INFO bmp_info; | |
242 | ||
243 | /* | |
244 | ** bmp_SetPix | |
245 | ** | |
246 | ** Given (info), set the pixel at (x),(y) to (val) | |
247 | ** | |
248 | */ | |
249 | static void | |
250 | bmp_SetPix(BMP_INFO *info, int x, int y, u_char val) | |
251 | { | |
252 | int sofs, bofs; | |
253 | int newbank; | |
254 | ||
255 | /* | |
256 | * range check to avoid explosions | |
257 | */ | |
258 | if ((x < 0) || (x >= info->swidth) || (y < 0) || (y >= info->sheight)) | |
259 | return; | |
260 | ||
2efb75f3 | 261 | lwkt_gettoken(&vga_token); |
984263bc MD |
262 | /* |
263 | * calculate offset into video memory; | |
264 | * because 0,0 is bottom-left for DIB, we have to convert. | |
265 | */ | |
266 | sofs = ((info->height - (y+1) + (info->sheight - info->height) / 2) | |
267 | * info->adp->va_line_width); | |
268 | x += (info->swidth - info->width) / 2; | |
269 | ||
270 | switch(info->sdepth) { | |
984263bc MD |
271 | case 4: |
272 | case 1: | |
273 | /* EGA/VGA planar modes */ | |
274 | sofs += (x >> 3); | |
275 | newbank = sofs/info->adp->va_window_size; | |
276 | if (info->bank != newbank) { | |
277 | (*vidsw[info->adp->va_index]->set_win_org)(info->adp, newbank*info->adp->va_window_size); | |
278 | info->bank = newbank; | |
279 | } | |
280 | sofs %= info->adp->va_window_size; | |
281 | bofs = x & 0x7; /* offset within byte */ | |
282 | outw(GDCIDX, (0x8000 >> bofs) | 0x08); /* bit mask */ | |
283 | outw(GDCIDX, (val << 8) | 0x00); /* set/reset */ | |
284 | *(info->vidmem + sofs) ^= 0xff; /* read-modify-write */ | |
285 | break; | |
984263bc MD |
286 | |
287 | case 8: | |
288 | sofs += x; | |
289 | newbank = sofs/info->adp->va_window_size; | |
290 | if (info->bank != newbank) { | |
291 | (*vidsw[info->adp->va_index]->set_win_org)(info->adp, newbank*info->adp->va_window_size); | |
292 | info->bank = newbank; | |
293 | } | |
294 | sofs %= info->adp->va_window_size; | |
295 | *(info->vidmem+sofs) = val; | |
296 | break; | |
297 | } | |
2efb75f3 | 298 | lwkt_reltoken(&vga_token); |
984263bc MD |
299 | } |
300 | ||
301 | /* | |
302 | ** bmp_DecodeRLE4 | |
303 | ** | |
304 | ** Given (data) pointing to a line of RLE4-format data and (line) being the starting | |
305 | ** line onscreen, decode the line. | |
306 | */ | |
307 | static void | |
308 | bmp_DecodeRLE4(BMP_INFO *info, int line) | |
309 | { | |
310 | int count; /* run count */ | |
311 | u_char val; | |
312 | int x,y; /* screen position */ | |
313 | ||
314 | x = 0; /* starting position */ | |
315 | y = line; | |
316 | ||
317 | /* loop reading data */ | |
318 | for (;;) { | |
319 | /* | |
320 | * encoded mode starts with a run length, and then a byte with | |
321 | * two colour indexes to alternate between for the run | |
322 | */ | |
323 | if (*info->index) { | |
324 | for (count = 0; count < *info->index; count++, x++) { | |
325 | if (count & 1) { /* odd count, low nybble */ | |
326 | bmp_SetPix(info, x, y, *(info->index+1) & 0x0f); | |
327 | } else { /* even count, high nybble */ | |
328 | bmp_SetPix(info, x, y, (*(info->index+1) >>4) & 0x0f); | |
329 | } | |
330 | } | |
331 | info->index += 2; | |
332 | /* | |
333 | * A leading zero is an escape; it may signal the end of the | |
334 | * bitmap, a cursor move, or some absolute data. | |
335 | */ | |
336 | } else { /* zero tag may be absolute mode or an escape */ | |
337 | switch (*(info->index+1)) { | |
338 | case 0: /* end of line */ | |
339 | info->index += 2; | |
340 | return; | |
341 | case 1: /* end of bitmap */ | |
342 | info->index = NULL; | |
343 | return; | |
344 | case 2: /* move */ | |
345 | x += *(info->index + 2); /* new coords */ | |
346 | y += *(info->index + 3); | |
347 | info->index += 4; | |
348 | break; | |
349 | default: /* literal bitmap data */ | |
350 | for (count = 0; count < *(info->index + 1); count++, x++) { | |
351 | val = *(info->index + 2 + (count / 2)); /* byte with nybbles */ | |
352 | if (count & 1) { | |
353 | val &= 0xf; /* get low nybble */ | |
354 | } else { | |
355 | val = (val >> 4); /* get high nybble */ | |
356 | } | |
357 | bmp_SetPix(info, x, y, val); | |
358 | } | |
359 | /* warning, this depends on integer truncation, do not hand-optimise! */ | |
360 | info->index += 2 + ((count + 3) / 4) * 2; | |
361 | break; | |
362 | } | |
363 | } | |
364 | } | |
365 | } | |
366 | ||
367 | /* | |
368 | ** bmp_DecodeRLE8 | |
369 | ** Given (data) pointing to a line of RLE8-format data and (line) being the starting | |
370 | ** line onscreen, decode the line. | |
371 | */ | |
372 | static void | |
373 | bmp_DecodeRLE8(BMP_INFO *info, int line) | |
374 | { | |
375 | int count; /* run count */ | |
376 | int x,y; /* screen position */ | |
377 | ||
378 | x = 0; /* starting position */ | |
379 | y = line; | |
380 | ||
381 | /* loop reading data */ | |
382 | for(;;) { | |
383 | /* | |
384 | * encoded mode starts with a run length, and then a byte with | |
385 | * two colour indexes to alternate between for the run | |
386 | */ | |
387 | if (*info->index) { | |
388 | for (count = 0; count < *info->index; count++, x++) | |
389 | bmp_SetPix(info, x, y, *(info->index+1)); | |
390 | info->index += 2; | |
391 | /* | |
392 | * A leading zero is an escape; it may signal the end of the | |
393 | * bitmap, a cursor move, or some absolute data. | |
394 | */ | |
395 | } else { /* zero tag may be absolute mode or an escape */ | |
396 | switch(*(info->index+1)) { | |
397 | case 0: /* end of line */ | |
398 | info->index += 2; | |
399 | return; | |
400 | case 1: /* end of bitmap */ | |
401 | info->index = NULL; | |
402 | return; | |
403 | case 2: /* move */ | |
404 | x += *(info->index + 2); /* new coords */ | |
405 | y += *(info->index + 3); | |
406 | info->index += 4; | |
407 | break; | |
408 | default: /* literal bitmap data */ | |
409 | for (count = 0; count < *(info->index + 1); count++, x++) | |
410 | bmp_SetPix(info, x, y, *(info->index + 2 + count)); | |
411 | /* must be an even count */ | |
412 | info->index += 2 + count + (count & 1); | |
413 | break; | |
414 | } | |
415 | } | |
416 | } | |
417 | } | |
418 | ||
419 | /* | |
420 | ** bmp_DecodeLine | |
421 | ** | |
422 | ** Given (info) pointing to an image being decoded, (line) being the line currently | |
423 | ** being displayed, decode a line of data. | |
424 | */ | |
425 | static void | |
426 | bmp_DecodeLine(BMP_INFO *info, int line) | |
427 | { | |
428 | int x; | |
e7cb9e6a JS |
429 | u_char val, mask; |
430 | const u_char *p; | |
984263bc MD |
431 | |
432 | switch(info->format) { | |
433 | case BI_RGB: | |
434 | switch(info->depth) { | |
435 | case 8: | |
436 | for (x = 0; x < info->width; x++, info->index++) | |
437 | bmp_SetPix(info, x, line, *info->index); | |
438 | info->index += 3 - (--x % 4); | |
439 | break; | |
440 | case 4: | |
441 | p = info->index; | |
442 | for (x = 0; x < info->width; x++) { | |
443 | if (x & 1) { | |
444 | val = *p & 0xf; /* get low nybble */ | |
445 | p++; | |
446 | } else { | |
447 | val = *p >> 4; /* get high nybble */ | |
448 | } | |
449 | bmp_SetPix(info, x, line, val); | |
450 | } | |
451 | /* warning, this depends on integer truncation, do not hand-optimise! */ | |
452 | info->index += ((x + 7) / 8) * 4; | |
453 | break; | |
454 | case 1: | |
455 | p = info->index; | |
456 | mask = 0x80; | |
457 | for (x = 0; x < info->width; x++) { | |
458 | val = (*p & mask) ? 1 : 0; | |
459 | mask >>= 1; | |
460 | if (mask == 0) { | |
461 | mask = 0x80; | |
462 | p++; | |
463 | } | |
464 | bmp_SetPix(info, x, line, val); | |
465 | } | |
466 | /* warning, this depends on integer truncation, do not hand-optimise! */ | |
467 | info->index += ((x + 31) / 32) * 4; | |
468 | break; | |
469 | } | |
470 | break; | |
471 | case BI_RLE4: | |
472 | bmp_DecodeRLE4(info, line); | |
473 | break; | |
474 | case BI_RLE8: | |
475 | bmp_DecodeRLE8(info, line); | |
476 | break; | |
477 | } | |
478 | } | |
479 | ||
480 | /* | |
481 | ** bmp_Init | |
482 | ** | |
483 | ** Given a pointer (data) to the image of a BMP file, fill in bmp_info with what | |
484 | ** can be learnt from it. Return nonzero if the file isn't usable. | |
485 | ** | |
486 | ** Take screen dimensions (swidth), (sheight) and (sdepth) and make sure we | |
487 | ** can work with these. | |
488 | */ | |
489 | static int | |
490 | bmp_Init(const char *data, int swidth, int sheight, int sdepth) | |
491 | { | |
e7cb9e6a | 492 | const BITMAPF *bmf = (const BITMAPF *)data; |
984263bc MD |
493 | int pind; |
494 | ||
495 | bmp_info.data = NULL; /* assume setup failed */ | |
496 | ||
497 | /* check file ID */ | |
498 | if (bmf->bmfh.bfType != 0x4d42) { | |
e3869ec7 | 499 | kprintf("splash_bmp: not a BMP file\n"); |
984263bc MD |
500 | return(1); /* XXX check word ordering for big-endian ports? */ |
501 | } | |
502 | ||
503 | /* do we understand this bitmap format? */ | |
504 | if (bmf->bmfi.bmiHeader.biSize > sizeof(bmf->bmfi.bmiHeader)) { | |
e3869ec7 | 505 | kprintf("splash_bmp: unsupported BMP format (size=%d)\n", |
984263bc MD |
506 | bmf->bmfi.bmiHeader.biSize); |
507 | return(1); | |
508 | } | |
509 | ||
510 | /* save what we know about the screen */ | |
511 | bmp_info.swidth = swidth; | |
512 | bmp_info.sheight = sheight; | |
513 | bmp_info.sdepth = sdepth; | |
514 | ||
515 | /* where's the data? */ | |
e7cb9e6a | 516 | bmp_info.data = (const u_char *)data + bmf->bmfh.bfOffBits; |
984263bc MD |
517 | |
518 | /* image parameters */ | |
519 | bmp_info.width = bmf->bmfi.bmiHeader.biWidth; | |
520 | bmp_info.height = bmf->bmfi.bmiHeader.biHeight; | |
521 | bmp_info.depth = bmf->bmfi.bmiHeader.biBitCount; | |
522 | bmp_info.format = bmf->bmfi.bmiHeader.biCompression; | |
523 | ||
524 | switch(bmp_info.format) { /* check compression format */ | |
525 | case BI_RGB: | |
526 | case BI_RLE4: | |
527 | case BI_RLE8: | |
528 | break; | |
529 | default: | |
e3869ec7 | 530 | kprintf("splash_bmp: unsupported compression format\n"); |
984263bc MD |
531 | return(1); /* unsupported compression format */ |
532 | } | |
533 | ||
534 | /* palette details */ | |
535 | bmp_info.ncols = (bmf->bmfi.bmiHeader.biClrUsed); | |
536 | bzero(bmp_info.palette,sizeof(bmp_info.palette)); | |
537 | if (bmp_info.ncols == 0) { /* uses all of them */ | |
538 | bmp_info.ncols = 1 << bmf->bmfi.bmiHeader.biBitCount; | |
539 | } | |
540 | if ((bmp_info.height > bmp_info.sheight) || | |
541 | (bmp_info.width > bmp_info.swidth) || | |
542 | (bmp_info.ncols > (1 << sdepth))) { | |
543 | if (bootverbose) | |
e3869ec7 | 544 | kprintf("splash_bmp: beyond screen capacity (%dx%d, %d colors)\n", |
984263bc MD |
545 | bmp_info.width, bmp_info.height, bmp_info.ncols); |
546 | return(1); | |
547 | } | |
548 | ||
549 | /* read palette */ | |
550 | for (pind = 0; pind < bmp_info.ncols; pind++) { | |
551 | bmp_info.palette[pind][0] = bmf->bmfi.bmiColors[pind].rgbRed; | |
552 | bmp_info.palette[pind][1] = bmf->bmfi.bmiColors[pind].rgbGreen; | |
553 | bmp_info.palette[pind][2] = bmf->bmfi.bmiColors[pind].rgbBlue; | |
554 | } | |
555 | return(0); | |
556 | } | |
557 | ||
558 | /* | |
559 | ** bmp_Draw | |
560 | ** | |
561 | ** Render the image. Return nonzero if that's not possible. | |
562 | ** | |
563 | */ | |
564 | static int | |
565 | bmp_Draw(video_adapter_t *adp) | |
566 | { | |
567 | int line; | |
6b08710e | 568 | #if 0 |
984263bc | 569 | int i; |
6b08710e | 570 | #endif |
984263bc MD |
571 | |
572 | if (bmp_info.data == NULL) { /* init failed, do nothing */ | |
573 | return(1); | |
574 | } | |
22ff886e | 575 | |
2efb75f3 | 576 | lwkt_gettoken(&vga_token); |
984263bc MD |
577 | /* clear the screen */ |
578 | bmp_info.vidmem = (u_char *)adp->va_window; | |
579 | bmp_info.adp = adp; | |
580 | (*vidsw[adp->va_index]->clear)(adp); | |
581 | (*vidsw[adp->va_index]->set_win_org)(adp, 0); | |
582 | bmp_info.bank = 0; | |
583 | ||
584 | /* initialise the info structure for drawing */ | |
585 | bmp_info.index = bmp_info.data; | |
984263bc MD |
586 | |
587 | /* set the palette for our image */ | |
588 | (*vidsw[adp->va_index]->load_palette)(adp, (u_char *)&bmp_info.palette); | |
589 | ||
590 | #if 0 | |
984263bc MD |
591 | /* XXX: this is ugly, but necessary for EGA/VGA 1bpp/4bpp modes */ |
592 | if ((adp->va_type == KD_EGA) || (adp->va_type == KD_VGA)) { | |
593 | inb(adp->va_crtc_addr + 6); /* reset flip-flop */ | |
594 | outb(ATC, 0x14); | |
595 | outb(ATC, 0); | |
596 | for (i = 0; i < 16; ++i) { | |
597 | outb(ATC, i); | |
598 | outb(ATC, i); | |
599 | } | |
600 | inb(adp->va_crtc_addr + 6); /* reset flip-flop */ | |
601 | outb(ATC, 0x20); /* enable palette */ | |
602 | ||
603 | outw(GDCIDX, 0x0f01); /* set/reset enable */ | |
604 | ||
605 | if (bmp_info.sdepth == 1) | |
606 | outw(TSIDX, 0x0102); /* unmask plane #0 */ | |
607 | } | |
984263bc MD |
608 | #endif |
609 | ||
610 | for (line = 0; (line < bmp_info.height) && bmp_info.index; line++) { | |
611 | bmp_DecodeLine(&bmp_info, line); | |
612 | } | |
2efb75f3 | 613 | lwkt_reltoken(&vga_token); |
984263bc MD |
614 | return(0); |
615 | } |