summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>1999-04-12 13:39:11 +0000
committerdes <des@FreeBSD.org>1999-04-12 13:39:11 +0000
commit2dc3d69d77872e584e39a0a6fa82448ece1e5037 (patch)
tree7e1220b844a6908553472e0d548cf29e55b8e887 /sys/dev
parent791f19da95cba106f2842309ff0a3fabb4a7e757 (diff)
downloadFreeBSD-src-2dc3d69d77872e584e39a0a6fa82448ece1e5037.zip
FreeBSD-src-2dc3d69d77872e584e39a0a6fa82448ece1e5037.tar.gz
PCX loader for pseudo-device splash.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fb/splash_pcx.c262
1 files changed, 262 insertions, 0 deletions
diff --git a/sys/dev/fb/splash_pcx.c b/sys/dev/fb/splash_pcx.c
new file mode 100644
index 0000000..3066bb3
--- /dev/null
+++ b/sys/dev/fb/splash_pcx.c
@@ -0,0 +1,262 @@
+/*-
+ * Copyright (c) 1999 Michael Smith <msmith@freebsd.org>
+ * Copyright (c) 1999 Kazutaka YOKOTA <yokota@freebsd.org>
+ * Copyright (c) 1999 Dag-Erling Coïdan Smørgrav
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/linker.h>
+
+#include <machine/console.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+
+#define FADE_TIMEOUT 300 /* sec */
+
+static int splash_mode = -1;
+static int splash_on = FALSE;
+
+static int pcx_start(video_adapter_t *adp);
+static int pcx_end(video_adapter_t *adp);
+static int pcx_splash(video_adapter_t *adp, int on);
+static int pcx_init(const char *data, int sdepth);
+static int pcx_draw(video_adapter_t *adp);
+
+static splash_decoder_t pcx_decoder = {
+ "splash_pcx", pcx_start, pcx_end, pcx_splash, SPLASH_IMAGE,
+};
+
+SPLASH_DECODER(splash_pcx, pcx_decoder);
+
+static struct
+{
+ int width, height, bpsl;
+ int bpp, planes, zlen;
+ const u_char *zdata, *palette;
+} pcx_info;
+
+static int
+pcx_start(video_adapter_t *adp)
+{
+ static int modes[] = {
+ M_VGA_CG320,
+ M_VESA_CG640x480,
+ M_VESA_CG800x600,
+ M_VESA_CG1024x768,
+ -1,
+ };
+ video_info_t info;
+ int i;
+
+ if (pcx_decoder.data == NULL
+ || pcx_decoder.data_size <= 0
+ || pcx_init((u_char *)pcx_decoder.data, pcx_decoder.data_size))
+ return ENODEV;
+
+ if (bootverbose)
+ printf("splash_pcx: image good:\n"
+ " width = %d\n"
+ " height = %d\n"
+ " depth = %d\n"
+ " planes = %d\n",
+ pcx_info.width, pcx_info.height,
+ pcx_info.bpp, pcx_info.planes);
+
+ for (i = 0; modes[i] >= 0; ++i) {
+ if (get_mode_info(adp, modes[i], &info) != 0)
+ continue;
+ if (bootverbose)
+ printf("splash_pcx: considering mode %d:\n"
+ " vi_width = %d\n"
+ " vi_height = %d\n"
+ " vi_depth = %d\n"
+ " vi_planes = %d\n",
+ modes[i],
+ info.vi_width, info.vi_height,
+ info.vi_depth, info.vi_planes);
+ if (info.vi_width >= pcx_info.width
+ && info.vi_height >= pcx_info.height
+ && info.vi_depth == pcx_info.bpp
+ && info.vi_planes == pcx_info.planes)
+ break;
+ }
+
+ splash_mode = modes[i];
+ if (splash_mode == -1)
+ return ENODEV;
+ if (bootverbose)
+ printf("pcx_splash: selecting mode %d\n", splash_mode);
+ return 0;
+}
+
+static int
+pcx_end(video_adapter_t *adp)
+{
+ /* nothing to do */
+ return 0;
+}
+
+static int
+pcx_splash(video_adapter_t *adp, int on)
+{
+ if (on) {
+ if (!splash_on) {
+ if (set_video_mode(adp, splash_mode) || pcx_draw(adp))
+ return 1;
+ splash_on = TRUE;
+ }
+ return 0;
+ } else {
+ splash_on = FALSE;
+ return 0;
+ }
+}
+
+struct pcxheader {
+ u_char manufactor;
+ u_char version;
+ u_char encoding;
+ u_char bpp;
+ u_short xmin, ymin, xmax, ymax;
+ u_short hres, vres;
+ u_char colormap[48];
+ u_char rsvd;
+ u_char nplanes;
+ u_short bpsl;
+ u_short palinfo;
+ u_short hsize, vsize;
+};
+
+#define MAXSCANLINE 1024
+
+static int
+pcx_init(const char *data, int size)
+{
+ const struct pcxheader *hdr;
+
+ hdr = (const struct pcxheader *)data;
+
+ if (size < 128 + 1 + 1 + 768
+ || hdr->manufactor != 10
+ || hdr->version != 5
+ || hdr->encoding != 1
+ || hdr->nplanes != 1
+ || hdr->bpp != 8
+ || hdr->bpsl > MAXSCANLINE
+ || data[size-769] != 12) {
+ printf("splash_pcx: invalid PCX image\n");
+ return 1;
+ }
+ pcx_info.width = hdr->xmax - hdr->xmin + 1;
+ pcx_info.height = hdr->ymax - hdr->ymin + 1;
+ pcx_info.bpsl = hdr->bpsl;
+ pcx_info.bpp = hdr->bpp;
+ pcx_info.planes = hdr->nplanes;
+ pcx_info.zlen = size - (128 + 1 + 768);
+ pcx_info.zdata = data + 128;
+ pcx_info.palette = data + size - 768;
+ return 0;
+}
+
+static int
+pcx_draw(video_adapter_t *adp)
+{
+ u_char *vidmem;
+ int swidth, sheight, sbpsl, sdepth, splanes;
+ int banksize, origin;
+ int c, i, j, pos, scan, x, y;
+ u_char line[MAXSCANLINE];
+
+ if (pcx_info.zlen < 1)
+ return 1;
+
+ load_palette(adp, pcx_info.palette);
+
+ vidmem = (u_char *)adp->va_window;
+ swidth = adp->va_info.vi_width;
+ sheight = adp->va_info.vi_height;
+ sbpsl = adp->va_line_width;
+ sdepth = adp->va_info.vi_depth;
+ splanes = adp->va_info.vi_planes;
+ banksize = adp->va_info.vi_window_size;
+
+ for (origin = 0; origin < sheight*sbpsl; origin += banksize) {
+ set_origin(adp, origin);
+ bzero(vidmem, banksize);
+ }
+
+ x = (swidth - pcx_info.width) / 2;
+ y = (sheight - pcx_info.height) / 2;
+ origin = 0;
+ pos = y * sbpsl + x;
+ while (pos > banksize) {
+ pos -= banksize;
+ origin += banksize;
+ }
+ set_origin(adp, origin);
+
+ for (scan = i = 0; scan < pcx_info.height; ++scan, ++y, pos += sbpsl) {
+ for (j = 0; j < pcx_info.bpsl && i < pcx_info.zlen; ++i) {
+ if ((pcx_info.zdata[i] & 0xc0) == 0xc0) {
+ c = pcx_info.zdata[i++] & 0x3f;
+ if (i >= pcx_info.zlen)
+ return 1;
+ } else {
+ c = 1;
+ }
+ if (j + c > pcx_info.bpsl)
+ return 1;
+ while (c--)
+ line[j++] = pcx_info.zdata[i];
+ }
+
+ if (pos > banksize) {
+ origin += banksize;
+ pos -= banksize;
+ set_origin(adp, origin);
+ }
+
+ if (pos + pcx_info.width > banksize) {
+ /* scanline crosses bank boundary */
+ j = banksize - pos;
+ bcopy(line, vidmem + pos, j);
+ origin += banksize;
+ pos -= banksize;
+ set_origin(adp, origin);
+ bcopy(line + j, vidmem, pcx_info.width - j);
+ } else {
+ bcopy(line, vidmem + pos, pcx_info.width);
+ }
+ }
+
+ return 0;
+}
OpenPOWER on IntegriCloud