2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1999 Michael Smith <msmith@freebsd.org>
5 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@freebsd.org>
6 * Copyright (c) 1999 Dag-Erling Coïdan Smørgrav
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer
14 * in this position and unchanged.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/linker.h>
39 #include <sys/module.h>
42 #include <dev/fb/fbreg.h>
43 #include <dev/fb/splashreg.h>
45 static int splash_mode = -1;
46 static int splash_on = FALSE;
48 static int pcx_start(video_adapter_t *adp);
49 static int pcx_end(video_adapter_t *adp);
50 static int pcx_splash(video_adapter_t *adp, int on);
51 static int pcx_init(void *data, int sdepth);
52 static int pcx_draw(video_adapter_t *adp);
54 static splash_decoder_t pcx_decoder = {
59 .data_type = SPLASH_IMAGE,
62 SPLASH_DECODER(splash_pcx, pcx_decoder);
76 pcx_start(video_adapter_t *adp)
78 static int modes[] = {
88 if (pcx_decoder.data == NULL ||
89 pcx_decoder.data_size <= 0 ||
90 pcx_init(pcx_decoder.data, pcx_decoder.data_size))
94 printf("splash_pcx: image good:\n"
99 pcx_info.width, pcx_info.height,
100 pcx_info.bpp, pcx_info.planes);
102 for (i = 0; modes[i] >= 0; ++i) {
103 if (vidd_get_info(adp, modes[i], &info) != 0)
106 printf("splash_pcx: considering mode %d:\n"
112 info.vi_width, info.vi_height,
113 info.vi_depth, info.vi_planes);
114 if (info.vi_width >= pcx_info.width
115 && info.vi_height >= pcx_info.height
116 && info.vi_depth == pcx_info.bpp
117 && info.vi_planes == pcx_info.planes)
121 splash_mode = modes[i];
122 if (splash_mode == -1)
125 printf("splash_pcx: selecting mode %d\n", splash_mode);
130 pcx_end(video_adapter_t *adp)
137 pcx_splash(video_adapter_t *adp, int on)
141 if (vidd_set_mode(adp, splash_mode) || pcx_draw(adp))
163 uint8_t colormap[48];
172 #define MAXSCANLINE 1024
175 pcx_init(void *data, int size)
177 const struct pcx_header *hdr = data;
179 if (size < 128 + 1 + 1 + 768 ||
180 hdr->manufactor != 10 ||
182 hdr->encoding != 1 ||
185 hdr->bpsl > MAXSCANLINE ||
186 ((uint8_t *)data)[size - 769] != 12) {
187 printf("splash_pcx: invalid PCX image\n");
190 pcx_info.width = hdr->xmax - hdr->xmin + 1;
191 pcx_info.height = hdr->ymax - hdr->ymin + 1;
192 pcx_info.bpsl = hdr->bpsl;
193 pcx_info.bpp = hdr->bpp;
194 pcx_info.planes = hdr->nplanes;
195 pcx_info.zlen = size - (128 + 1 + 768);
196 pcx_info.zdata = (uint8_t *)data + 128;
197 pcx_info.palette = (uint8_t *)data + size - 768;
202 pcx_draw(video_adapter_t *adp)
205 int swidth, sheight, sbpsl;
206 int banksize, origin;
207 int c, i, j, pos, scan, x, y;
208 uint8_t line[MAXSCANLINE];
210 if (pcx_info.zlen < 1)
213 vidd_load_palette(adp, pcx_info.palette);
215 vidmem = (uint8_t *)adp->va_window;
216 swidth = adp->va_info.vi_width;
217 sheight = adp->va_info.vi_height;
218 sbpsl = adp->va_line_width;
219 banksize = adp->va_window_size;
221 for (origin = 0; origin < sheight*sbpsl; origin += banksize) {
222 vidd_set_win_org(adp, origin);
223 bzero(vidmem, banksize);
226 x = (swidth - pcx_info.width) / 2;
227 y = (sheight - pcx_info.height) / 2;
230 while (pos > banksize) {
234 vidd_set_win_org(adp, origin);
236 for (scan = i = 0; scan < pcx_info.height; ++scan, ++y, pos += sbpsl) {
237 for (j = 0; j < pcx_info.bpsl && i < pcx_info.zlen; ++i) {
238 if ((pcx_info.zdata[i] & 0xc0) == 0xc0) {
239 c = pcx_info.zdata[i++] & 0x3f;
240 if (i >= pcx_info.zlen)
245 if (j + c > pcx_info.bpsl)
248 line[j++] = pcx_info.zdata[i];
251 if (pos > banksize) {
254 vidd_set_win_org(adp, origin);
257 if (pos + pcx_info.width > banksize) {
258 /* scanline crosses bank boundary */
260 bcopy(line, vidmem + pos, j);
263 vidd_set_win_org(adp, origin);
264 bcopy(line + j, vidmem, pcx_info.width - j);
266 bcopy(line, vidmem + pos, pcx_info.width);