aboutsummaryrefslogtreecommitdiffstats
path: root/fbmngplay
diff options
context:
space:
mode:
Diffstat (limited to 'fbmngplay')
-rw-r--r--fbmngplay/ChangeLog33
-rw-r--r--fbmngplay/Makefile69
-rw-r--r--fbmngplay/README30
-rw-r--r--fbmngplay/console.c45
-rw-r--r--fbmngplay/console.h21
-rw-r--r--fbmngplay/fbmngplay.c250
-rw-r--r--fbmngplay/fbmngplay.h45
-rw-r--r--fbmngplay/messages.c43
-rw-r--r--fbmngplay/messages.h19
-rw-r--r--fbmngplay/mng.c421
-rw-r--r--fbmngplay/mng.h38
11 files changed, 1014 insertions, 0 deletions
diff --git a/fbmngplay/ChangeLog b/fbmngplay/ChangeLog
new file mode 100644
index 0000000..91956f8
--- /dev/null
+++ b/fbmngplay/ChangeLog
@@ -0,0 +1,33 @@
+******************* Sun Nov 17 02:19:34 CET 2002 *********************
+
+* fix fbmngplay to cope with 15bit displays that state they are 16bit
+ (aty128fb on ppc)
+
+******************* Tue Sep 3 15:28:20 CEST 2002 ********************
+
+* get rid of dynamic positioning code (moved to theme config files
+ for flexibility.
+
+******************* Mon Mar 18 14:56:29 CET 2002 *********************
+
+* rewrite console detection code.
+* fix console chosing code to show pictures on the right console
+ only, when booting or shutting down the system.
+* get rid of obsolete code fragments.
+
+******************* Wed Sep 19 17:25:19 CEST 2001 ********************
+
+* gnore multiple USR1 signals to prevent halt animation to
+ stop early
+* if console is one, and you are not on it, exit.
+
+******************* Thu Sep 13 15:28:01 CEST 2001 ********************
+
+* new option -S to play on start console only.
+* new option -c to play animationon any fb console
+* split fbmngplay to several files.
+
+******************* Wed Sep 12 14:51:44 CEST 2001 ********************
+
+* new option -p for dynamic positioning of the mng animation in the
+ upper right corner.
diff --git a/fbmngplay/Makefile b/fbmngplay/Makefile
new file mode 100644
index 0000000..ccde3dd
--- /dev/null
+++ b/fbmngplay/Makefile
@@ -0,0 +1,69 @@
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
+SHELL = /bin/sh
+CC = gcc
+STRIP = strip
+
+# Triggering lib64 path from spec file.
+ifeq ($(PREFIX)x,x)
+PREFIX = $(prefix)/usr
+endif
+ifeq ($(LIB)x,x)
+LIB = lib
+endif
+LIBDIR = /usr/$(LIB)
+bindir = $(PREFIX)/bin
+
+PROGRAMS = fbmngplay fbmngplay.static
+OBJECTS = fbmngplay.o messages.o mng.o console.o
+
+LDFLAGS = -L$(LIBDIR)
+LIBSS = $(LIBDIR)/libmng.a $(LIBDIR)/libz.a $(LIBDIR)/libjpeg.a -lm
+LIBSD = -lmng -lz -lm
+
+CFLAGS = -O2 -Wall
+COMPILE = $(CC) $(CFLAGS)
+LINKS = $(CC) $(CFLAGS) $(LDFLAGS) -static -o $@
+LINKD = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+
+all: $(PROGRAMS) strip
+
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean:
+ -rm -f *.o core
+clean: mostlyclean
+ -rm -f fbmngplay fbmngplay.static
+
+install:
+ install -m 755 -d $(bindir)
+ install -m755 fbmngplay.static $(prefix)/bin
+ install -m755 fbmngplay $(bindir)
+
+fbmngplay: $(OBJECTS)
+ @rm -f fbmngplay
+ $(LINKD) $(LDFLAGS) $(OBJECTS) $(LIBSD)
+fbmngplay.static: $(OBJECTS)
+ @rm -f fbmngplay.static
+ $(LINKS) $(LDFLAGS) $(OBJECTS) $(LIBSS)
+
+strip: $(PROGRAMS)
+ $(STRIP) -s $(PROGRAMS)
+
+.PHONY: mostlyclean clean fbmngplay fbmngplay.static all strip
diff --git a/fbmngplay/README b/fbmngplay/README
new file mode 100644
index 0000000..1ffec8f
--- /dev/null
+++ b/fbmngplay/README
@@ -0,0 +1,30 @@
+* fbmngplay *
+
+a simple fbcon based mng player
+
+This is a simple example program, using the kernel framebuffer device
+to display mng animation decoded by the new libmng implementation.
+
+This player is based on the SDL version included in the libmng package
+from Ralph Giles <giles@ashlu.bc.ca>. The code's fairly rough at this
+point, but there was no example player for *nix in the distribution.
+Patches welcome, of course.
+
+On a unix-like system, the build instructions are simple:
+
+(install and/or build the mng library from libmng.com)
+make
+make install
+
+To use the player:
+
+fbmngplay <filename>.mng <filename>.mng ...
+
+To stop looping animations, press CTRL C or send a TERM or INT signal.
+
+See the options with
+fbmngplay -h
+
+---
+Stefan Reinauer, <stepan@suse.de>
+$Date$
diff --git a/fbmngplay/console.c b/fbmngplay/console.c
new file mode 100644
index 0000000..8bc7991
--- /dev/null
+++ b/fbmngplay/console.c
@@ -0,0 +1,45 @@
+/*
+ * fbmngplay - framebuffer console MNG player.
+ * (c) 2001-2002 by Stefan Reinauer, <stepan@suse.de>
+ *
+ * This program is based on mngplay, part of libmng, written and (C) by
+ * Ralph Giles <giles@ashlu.bc.ca>
+ *
+ * This program my be redistributed under the terms of the
+ * GNU General Public Licence, version 2, or at your preference,
+ * any later version.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+#include <sys/ioctl.h>
+
+#include "console.h"
+
+int start_console = 0;
+int fd;
+
+int current_console(void)
+{
+ int result=0;
+ char twelve=12;
+
+ result = ioctl(fd, TIOCLINUX, &twelve);
+
+ return result;
+}
+
+void init_consoles(void)
+{
+ fd=open("/dev/tty0", O_RDWR|O_NDELAY);
+ if (fd<0) {
+ fprintf(stderr, "Could not open virtual terminal.\n");
+ exit (1);
+ }
+}
+
diff --git a/fbmngplay/console.h b/fbmngplay/console.h
new file mode 100644
index 0000000..e9832f2
--- /dev/null
+++ b/fbmngplay/console.h
@@ -0,0 +1,21 @@
+/*
+ * fbmngplay - fb console MNG player.
+ * (c) 2001-2002 by Stefan Reinauer, <stepan@suse.de>
+ *
+ * This program is based on mngplay, part of libmng, written and (C) by
+ *
+ * Ralph Giles <giles@ashlu.bc.ca>
+ *
+ * This program my be redistributed under the terms of the
+ * GNU General Public Licence, version 2, or at your preference,
+ * any later version.
+ */
+
+#ifndef __CONSOLES_H
+#define __CONSOLES_H
+
+extern void init_consoles(void);
+extern int current_console(void);
+extern int start_console;
+
+#endif
diff --git a/fbmngplay/fbmngplay.c b/fbmngplay/fbmngplay.c
new file mode 100644
index 0000000..d0dbac2
--- /dev/null
+++ b/fbmngplay/fbmngplay.c
@@ -0,0 +1,250 @@
+/*
+ * fbmngplay - fb console MNG player.
+ * (c) 2001-2002 by Stefan Reinauer, <stepan@suse.de>
+ *
+ * This program is based on mngplay, written and (C) by
+ * Ralph Giles <giles@ashlu.bc.ca>
+ *
+ * This program my be redistributed under the terms of the
+ * GNU General Public Licence, version 2, or at your preference,
+ * any later version.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <signal.h>
+
+#include "fbmngplay.h"
+#include "messages.h"
+#include "console.h"
+#include "mng.h"
+
+volatile int run = 1;
+int verbose = 0;
+int buffered = 0;
+int waitsignal = 0;
+int delta = 16;
+int sconly=0;
+
+/*
+ * Signal handlers
+ */
+
+void sigint_handler(int sig)
+{
+ if (waitsignal)
+ return;
+ run = 2;
+}
+
+void sigterm_handler(int sig)
+{
+ if (waitsignal)
+ return;
+ restore_area();
+ run = 0;
+}
+
+void sigusr1_handler(int sig)
+{
+ signal(SIGUSR1, SIG_IGN);
+ run = 0;
+}
+
+/*
+ * Main loop
+ */
+
+int main(int argc, char *argv[])
+{
+ int fbdev,c,option_index;
+ unsigned int alpha;
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+
+ /* Check which console we're running on */
+ init_consoles();
+
+ /* allocate our stream data structure */
+ mng = (mngstuff *) calloc(1, sizeof(*mng));
+ if (mng == NULL) {
+ fprintf(stderr, "could not allocate stream structure.\n");
+ exit(0);
+ }
+
+ alpha = 100;
+ mng->alpha = 100;
+ mng->fbx = 15;
+ mng->fby = 15;
+ mng->background = NULL;
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", 0, 0, 'h'},
+ {"verbose", 0, 0, 'v'},
+ {"alpha", 1, 0, 'a'},
+ {"buffered", 0, 0, 'b'},
+ {"signal", 0, 0, 's'},
+ {"delta", 0, 0, 'd'},
+ {"version", 0, 0, 'V'},
+ {"start-console",0,0,'S'},
+ {"console",1,0,'c'},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv, "a:x:y:bh?vsd:VSc:",
+ long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'a':
+ alpha = atoi(optarg);
+ if (alpha > 100)
+ alpha = 100;
+ mng->alpha = alpha;
+ break;
+ case 'x':
+ mng->fbx = atoi(optarg);
+ break;
+ case 'y':
+ mng->fby = atoi(optarg);
+ break;
+ case 'd':
+ delta = atoi(optarg);
+ break;
+ case '?':
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ case 'v':
+ verbose = 1;
+ break;
+ case 's':
+ waitsignal = 1;
+ break;
+ case 'b':
+ buffered = 1;
+ break;
+ case 'V':
+ version();
+ exit(0);
+ case 'c':
+ start_console=atoi(optarg)-1;
+ case 'S':
+ sconly=1;
+ break;
+ default:
+ break;
+ }
+ }
+#if 0
+ if (!output && optind >= argc) {
+#else
+ if (optind >= argc) {
+#endif
+ printf("Which files do you want to play?\n");
+ exit(0);
+ }
+
+ /* Initialize framebuffer */
+ fbdev = open("/dev/fb0", O_RDWR);
+ if (fbdev < 0) {
+ fprintf(stderr, "error while opening framebuffer.\n");
+ exit(fbdev);
+ }
+
+ ioctl(fbdev, FBIOGET_VSCREENINFO, &var);
+ mng->fbwidth = var.xres;
+ mng->fbheight = var.yres;
+ mng->fbbpp = var.bits_per_pixel;
+
+ mng->fbredo = var.red.offset;
+ mng->fbgreeno = var.green.offset;
+ mng->fbblueo = var.blue.offset;
+ mng->fbredl = var.red.length;
+ mng->fbgreenl = var.green.length;
+ mng->fbbluel = var.blue.length;
+
+ /* Display might have a line length unequal
+ * the visible line.
+ */
+ ioctl(fbdev, FBIOGET_FSCREENINFO, &fix);
+ mng->fbrow = fix.line_length;
+
+ mng->display =
+ mmap(NULL, mng->fbrow * mng->fbheight ,
+ PROT_WRITE | PROT_READ, MAP_SHARED, fbdev, 0);
+#if 0
+ if (output)
+ prepare_output();
+#endif
+ /* arrange to call the shutdown routine before we exit */
+ atexit(&cleanup);
+
+ while (optind < argc) {
+ /* leftover arguements are filenames. */
+ mng->filename = argv[optind++];
+
+ /* set up the mng decoder for our stream */
+ mng->mng = mng_initialize(mng, mngalloc, mngfree, MNG_NULL);
+ if (mng->mng == MNG_NULL) {
+ fprintf(stderr, "could not initialize libmng.\n");
+ exit(1);
+ }
+
+ /* set the callbacks */
+ mng_setcb_errorproc(mng->mng, mngerror);
+ mng_setcb_openstream(mng->mng, mngopenstream);
+ mng_setcb_closestream(mng->mng, mngclosestream);
+ mng_setcb_readdata(mng->mng, mngreadstream);
+ mng_setcb_gettickcount(mng->mng, mnggetticks);
+ mng_setcb_settimer(mng->mng, mngsettimer);
+ mng_setcb_processheader(mng->mng, mngprocessheader);
+ mng_setcb_getcanvasline(mng->mng, mnggetcanvasline);
+ mng_setcb_refresh(mng->mng, mngrefresh);
+
+ signal(SIGINT, sigint_handler);
+ signal(SIGTERM, sigterm_handler);
+
+ mng_readdisplay(mng->mng);
+
+ /* loop though the frames */
+ while (mng->delay && run) {
+ usleep(mng->delay * 1000);
+ mng->delay = 0;
+ mng_display_resume(mng->mng);
+ if (run == 2) {
+ if (mng->alpha == 0)
+ run = 0;
+ mng->alpha -= delta;
+ if (mng->alpha < 0)
+ mng->alpha = 0;
+ }
+ }
+
+ if (waitsignal && optind < argc) {
+ signal(SIGUSR1, sigusr1_handler);
+ run = 1;
+ while (run) {
+ sleep(2);
+ }
+ }
+
+ memset(mng->copybuffer, 0,
+ 4 * mng->width * mng->height);
+ run = 1;
+ mng->alpha = alpha;
+ if (optind == argc) { /* last file */
+ restore_area();
+ }
+ }
+
+ /* cleanup and quit */
+ return mngquit(mng->mng);
+}
diff --git a/fbmngplay/fbmngplay.h b/fbmngplay/fbmngplay.h
new file mode 100644
index 0000000..34d3259
--- /dev/null
+++ b/fbmngplay/fbmngplay.h
@@ -0,0 +1,45 @@
+/*
+ * fbmngplay - fb console MNG player.
+ * (c) 2001-2002 by Stefan Reinauer, <stepan@suse.de>
+ *
+ * This program is based on mngplay, part of libmng, written and (C) by
+ *
+ * Ralph Giles <giles@ashlu.bc.ca>
+ *
+ * This program my be redistributed under the terms of the
+ * GNU General Public Licence, version 2, or at your preference,
+ * any later version.
+ */
+
+#ifndef __FBMNGPLAY_H
+#define __FBMNGPLAY_H
+
+#include <libmng.h>
+
+#define FBMNGPLAY_VERSION "0.5.1"
+
+/* structure for keeping track of our mng stream inside the callbacks */
+typedef struct {
+ FILE *file; /* pointer to the file we're decoding */
+ char *filename; /* pointer to the file's path/name */
+ mng_uint32 delay; /* ticks to wait before resuming decode */
+ unsigned char *display; /* pointer to display */
+ unsigned char *copybuffer;
+ unsigned char *background;
+ mng_handle mng; /* mng handle */
+ int width, height;
+ int fbwidth, fbheight, fbbpp, fbrow;
+ int fbx, fby;
+ int fbredo, fbredl, fbgreeno, fbgreenl, fbblueo, fbbluel;
+ int alpha;
+} mngstuff;
+
+extern volatile int run;
+extern int verbose;
+extern int buffered;
+extern int dynpos;
+extern int waitsignal;
+extern int delta;
+extern int sconly;
+
+#endif
diff --git a/fbmngplay/messages.c b/fbmngplay/messages.c
new file mode 100644
index 0000000..6bc2aa4
--- /dev/null
+++ b/fbmngplay/messages.c
@@ -0,0 +1,43 @@
+/*
+ * fbmngplay - fb console MNG player.
+ * (c) 2001-2002 by Stefan Reinauer, <stepan@suse.de>
+ *
+ * This program is based on mngplay, part of libmng, written and (C) by
+ *
+ * Ralph Giles <giles@ashlu.bc.ca>
+ *
+ * This program my be redistributed under the terms of the
+ * GNU General Public Licence, version 2, or at your preference,
+ * any later version.
+ */
+
+#include <stdio.h>
+#include "fbmngplay.h"
+#include "messages.h"
+
+void usage(char *name)
+{
+ fprintf(stderr, "\nusage: %s [ -x <val> ] [ -y <val> ] [ -a <val> ] [-b] [-v]"
+ " [-s] [file.mng [file.mng [...]]]\n", name);
+ fprintf(stderr,
+ "\n -x: x coordinate\n"
+ " -y: y coordinate\n"
+ " -a, --alpha: default alpha channel 1..100\n"
+ " -v, --verbose: verbose mode\n"
+ " -b, --buffered: buffered mode\n"
+ " -s, --signal: wait for SIGUSR1 between animations\n"
+ " -p, --position: dynamically select position\n"
+ " -V, --version: show version and exit\n"
+ " -?, -h, --help: print this help.\n"
+ " -S --start-console: only output animation on console it was started on.\n"
+ " -c: start output animation on specified console.\n\n");
+}
+
+void version(void)
+{
+ fprintf(stderr,
+ "fbmngplay v%s, Copyright (C) 2001-2002 Stefan Reinauer <stepan@suse.de>\n\n"
+ "fbmngplay comes with ABSOLUTELY NO WARRANTY;\n"
+ "This is free software, and you are welcome to redistribute it\n"
+ "under certain conditions; Check the GPL for details.\n", FBMNGPLAY_VERSION);
+}
diff --git a/fbmngplay/messages.h b/fbmngplay/messages.h
new file mode 100644
index 0000000..bc8c95b
--- /dev/null
+++ b/fbmngplay/messages.h
@@ -0,0 +1,19 @@
+/*
+ * fbmngplay - fb console MNG player.
+ * (c) 2001-2002 by Stefan Reinauer, <stepan@suse.de>
+ *
+ * This program is based on mngplay, part of libmng, written and (C) by
+ * Ralph Giles <giles@ashlu.bc.ca>
+ *
+ * This program my be redistributed under the terms of the
+ * GNU General Public Licence, version 2, or at your preference,
+ * any later version.
+ */
+
+#ifndef __MESSAGES_H
+#define __MESSAGES_H
+
+extern void usage(char *name);
+extern void version(void);
+
+#endif
diff --git a/fbmngplay/mng.c b/fbmngplay/mng.c
new file mode 100644
index 0000000..9728975
--- /dev/null
+++ b/fbmngplay/mng.c
@@ -0,0 +1,421 @@
+/*
+ * fbmngplay - fb console MNG player.
+ * (c) 2001-2002 by Stefan Reinauer, <stepan@suse.de>
+ *
+ * This program is based on mngplay, part of libmng, written and (C) by
+ * Ralph Giles <giles@ashlu.bc.ca>
+ *
+ * This program my be redistributed under the terms of the
+ * GNU General Public Licence, version 2, or at your preference,
+ * any later version.
+ */
+
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "fbmngplay.h"
+#include "console.h"
+#include "mng.h"
+
+mngstuff *mng;
+unsigned char *bufferstream;
+unsigned long bufferpos = 0, buffersize = 0;
+
+/*
+ * callbacks for the mng decoder
+ */
+
+/* memory allocation; data must be zeroed */
+mng_ptr mngalloc(mng_uint32 size)
+{
+ return (mng_ptr) calloc(1, size);
+}
+
+/* memory deallocation */
+void mngfree(mng_ptr p, mng_uint32 size)
+{
+ free(p);
+ return;
+}
+
+mng_bool mngopenstream(mng_handle mng)
+{
+ mngstuff *mymng;
+
+ /* look up our stream struct */
+ mymng = (mngstuff *) mng_get_userdata(mng);
+
+ /* open the file */
+ mymng->file = fopen(mymng->filename, "rb");
+ if (mymng->file == NULL) {
+ fprintf(stderr, "unable to open '%s'\n", mymng->filename);
+ run = 0;
+ return MNG_FALSE;
+ }
+
+ if (buffered) {
+ unsigned long len;
+ fseek(mymng->file, 0, SEEK_END);
+ len = ftell(mymng->file);
+ rewind(mymng->file);
+ bufferstream = malloc(len);
+ if (!bufferstream) {
+ /* Not enough memory for buffers
+ * -> we go back to unbuffered mode
+ */
+ printf("Reverted to non buffered mode.\n");
+ buffered = 0;
+ return MNG_TRUE;
+ }
+ buffersize = len;
+ fread(bufferstream, 1, len, mymng->file);
+ bufferpos = 0;
+ fclose(mymng->file);
+ mymng->file = NULL;
+ }
+
+ return MNG_TRUE;
+}
+
+mng_bool mngclosestream(mng_handle mng)
+{
+ mngstuff *mymng;
+
+ /* look up our stream struct */
+ mymng = (mngstuff *) mng_get_userdata(mng);
+
+ /* close the file */
+ if (mymng->file)
+ fclose(mymng->file);
+ mymng->file = NULL; /* for safety */
+
+ if (bufferstream) {
+ free(bufferstream);
+ bufferstream = 0;
+ buffersize = 0;
+ bufferpos = 0;
+ }
+ return MNG_TRUE;
+}
+
+/* feed data to the decoder */
+mng_bool mngreadstream(mng_handle mng, mng_ptr buffer,
+ mng_uint32 size, mng_uint32 * bytesread)
+{
+ mngstuff *mymng;
+
+ /* look up our stream struct */
+ mymng = (mngstuff *) mng_get_userdata(mng);
+ if (!buffered) {
+ /* read the requested amount of data from the file */
+ *bytesread = fread(buffer, 1, size, mymng->file);
+ } else {
+ *bytesread = (buffersize - bufferpos) <
+ size ? (buffersize - bufferpos) : size;
+ memcpy(buffer, bufferstream + bufferpos, *bytesread);
+ bufferpos += (*bytesread);
+ }
+ return MNG_TRUE;
+}
+
+mng_bool mnggetbackgroundbuffer(mng_handle mng)
+{
+ unsigned char *background, *src;
+ mngstuff *mymng=mng_get_userdata(mng);
+ mng_uint32 width=mymng->width, height=mymng->height;
+ int bytes=(mymng->fbbpp >> 3);
+
+ if (mymng->background)
+ return MNG_TRUE;
+
+ /* If we're not on the right terminal, don't
+ * initialize background yet.
+ */
+ if (sconly && current_console()!=start_console)
+ return MNG_FALSE;
+
+ background = (unsigned char *) malloc(width * height * bytes);
+ if (background == NULL) {
+ fprintf(stderr, "could not allocate background buffer.\n");
+ exit(0);
+ }
+
+ mymng->background = background;
+ src = mymng->display + (mymng->fbwidth * mymng->fby + mymng->fbx) * bytes;
+
+ while (height--) {
+ memcpy(background, src, width * bytes);
+ background += width * bytes;
+ src += mymng->fbrow;
+ }
+
+ return MNG_TRUE;
+}
+
+/* the header's been read. set up the display stuff */
+mng_bool mngprocessheader(mng_handle mng,
+ mng_uint32 width, mng_uint32 height)
+{
+ mngstuff *mymng;
+ unsigned char *copybuffer;
+
+ mymng = (mngstuff *) mng_get_userdata(mng);
+ mymng->width = width;
+ mymng->height = height;
+
+ copybuffer = (unsigned char *) malloc(width * height * 4);
+ if (copybuffer == NULL) {
+ fprintf(stderr, "could not allocate copy buffer.\n");
+ exit(0);
+ }
+ mymng->copybuffer = copybuffer;
+
+ /* Try to get background buffer */
+ mnggetbackgroundbuffer(mng);
+
+ /* tell the mng decoder about our bit-depth choice */
+ /* FIXME: this works on intel. is it correct in general? */
+ mng_set_canvasstyle(mng, MNG_CANVAS_BGRA8);
+
+ return MNG_TRUE;
+}
+
+/* return a row pointer for the decoder to fill */
+mng_ptr mnggetcanvasline(mng_handle mng, mng_uint32 line)
+{
+ mngstuff *mymng;
+ mng_ptr row;
+
+ /* dereference our structure */
+ mymng = (mngstuff *) mng_get_userdata(mng);
+
+ /* we assume any necessary locking has happened
+ outside, in the frame level code */
+ row = mymng->copybuffer + mymng->width * 4 * line;
+
+ return (row);
+}
+
+/* timer */
+mng_uint32 mnggetticks(mng_handle mng)
+{
+ mng_uint32 ticks;
+ struct timeval tv;
+ struct timezone tz;
+
+ gettimeofday(&tv, &tz);
+ ticks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+
+ return (ticks);
+}
+
+static inline void copyline(unsigned char *dest, unsigned char *src,
+ unsigned char *background, mngstuff * mymng)
+{
+ // BGRA8
+ unsigned int i = mymng->width;
+ unsigned int fr, fg, fb, br, bg, bb, r, g, b, a;
+ unsigned short output, input;
+
+ while (i--) {
+ fb = *src++;
+ fg = *src++;
+ fr = *src++;
+
+ a = *src++;
+ a = a * mymng->alpha / 100;
+ switch (mymng->fbbpp) {
+ case 16:
+ input = *((unsigned short *) background)++;
+
+ br = (input >> mng->fbredo) << (8-mng->fbredl);
+ bg = (input >> mng->fbgreeno) << (8-mng->fbgreenl);
+ bb = (input >> mng->fbblueo) << (8-mng->fbbluel);
+ br &= 0xf8;
+ bg &= 0xfc;
+ bb &= 0xff;
+#if 0
+ br = (input >> 8) & 0xf8;
+ bg = (input >> 3) & 0xfc;
+ bb = input << 3 & 0xff;
+#endif
+ break;
+ case 24:
+ bb = *background++;
+ bg = *background++;
+ br = *background++;
+ break;
+ case 32:
+ bb = *background++;
+ bg = *background++;
+ br = *background++;
+ background++;
+ break;
+ default:
+ br = 0;
+ bg = 0;
+ bb = 0;
+ printf("depth not supported.\n");
+ run = 0;
+ break;
+ }
+
+ r = ((fr * a) + (br * (0x100 - a))) >> 8;
+ g = ((fg * a) + (bg * (0x100 - a))) >> 8;
+ b = ((fb * a) + (bb * (0x100 - a))) >> 8;
+
+ switch (mymng->fbbpp) {
+ case 16:
+ // dumb 24->16 bit conversion.
+ r >>= (8-mng->fbredl);
+ g >>= (8-mng->fbgreenl);
+ b >>= (8-mng->fbbluel);
+
+ output = (r << mng->fbredo) | (g << mng->fbgreeno) | (b << mng->fbblueo);
+
+ *((unsigned short *) dest)++ = output;
+ break;
+ case 24:
+ *dest++ = b;
+ *dest++ = g;
+ *dest++ = r;
+ break;
+ case 32:
+ *dest++ = b;
+ *dest++ = g;
+ *dest++ = r;
+ dest++;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+mng_bool mngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y,
+ mng_uint32 w, mng_uint32 h)
+{
+ mngstuff *mymng=mng_get_userdata(mng);
+ unsigned char *background;
+ unsigned char *dest, *src;
+ int bytes=(mymng->fbbpp >> 3);
+
+ if (sconly && current_console()!=start_console)
+ return MNG_TRUE;
+
+ /* When we read the header, we might still
+ * have been on a different console
+ */
+
+ if (!(mymng->background))
+ mnggetbackgroundbuffer(mng);
+
+ background = mymng->background;
+
+ dest = mymng->display+(mymng->fby*mymng->fbwidth + mymng->fbx)*bytes;
+ src = mymng->copybuffer;
+
+ /* refresh the screen with the new frame */
+ while (h-- > 0) {
+ copyline(dest, src, background, mymng);
+
+ dest += mymng->fbrow;
+ background += mymng->width * bytes;
+ /* 4 bytes per pixel due to RGBA */
+ src += 4 * mymng->width;
+ }
+
+ /* remove traces in alpha transparent pictures. */
+ memset(mymng->copybuffer, 0, 4 * mymng->width * mymng->height);
+
+ return MNG_TRUE;
+}
+
+/* interframe delay callback */
+mng_bool mngsettimer(mng_handle mng, mng_uint32 msecs)
+{
+ mngstuff *mymng;
+
+ /* look up our stream struct */
+ mymng = (mngstuff *) mng_get_userdata(mng);
+
+ /* set the timer for when the decoder wants to be woken */
+ mymng->delay = msecs;
+
+ return MNG_TRUE;
+}
+
+mng_bool mngerror(mng_handle mng, mng_int32 code, mng_int8 severity,
+ mng_chunkid chunktype, mng_uint32 chunkseq,
+ mng_int32 extra1, mng_int32 extra2, mng_pchar text)
+{
+ mngstuff *mymng;
+ char chunk[5];
+
+ /* dereference our data so we can get the filename */
+ mymng = (mngstuff *) mng_get_userdata(mng);
+ /* pull out the chuck type as a string */
+ // FIXME: does this assume unsigned char?
+ chunk[0] = (char) ((chunktype >> 24) & 0xFF);
+ chunk[1] = (char) ((chunktype >> 16) & 0xFF);
+ chunk[2] = (char) ((chunktype >> 8) & 0xFF);
+ chunk[3] = (char) ((chunktype) & 0xFF);
+ chunk[4] = '\0';
+
+ /* output the error */
+ fprintf(stderr, "error playing '%s' chunk %s (%d):\n",
+ mymng->filename, chunk, chunkseq);
+ fprintf(stderr, "%s\n", text);
+
+ return 0;
+}
+
+int mngquit(mng_handle mng)
+{
+ mngstuff *mymng;
+
+ /* dereference our data so we can free it */
+ mymng = (mngstuff *) mng_get_userdata(mng);
+
+ /* cleanup. this will call mymngclosestream */
+ mng_cleanup(&mng);
+
+ /* free our data */
+ free(mymng);
+
+ exit(0);
+}
+
+void cleanup(void)
+{
+ mngquit(mng->mng);
+ exit(0);
+}
+
+void restore_area(void)
+{
+ int height, width;
+ unsigned char *dest, *background;
+
+ if (sconly && current_console()!=start_console)
+ return;
+
+ /* when we didn't manage to get a background until
+ * now, we don't have anything to restore anyways.
+ */
+
+ if (!(mng->background))
+ return;
+
+ background = mng->background;
+ height = mng->height;
+ width = mng->width;
+ dest = mng->display + (( mng->fbwidth*mng->fby + mng->fbx) *
+ (mng->fbbpp>>3));
+
+ while (height--) {
+ memcpy(dest, background, width * (mng->fbbpp >> 3));
+ background += width * (mng->fbbpp >> 3);
+ dest += mng->fbrow;
+ }
+}
diff --git a/fbmngplay/mng.h b/fbmngplay/mng.h
new file mode 100644
index 0000000..bbe8af2
--- /dev/null
+++ b/fbmngplay/mng.h
@@ -0,0 +1,38 @@
+/*
+ * fbmngplay - fb console MNG player.
+ * (c) 2001-2002 by Stefan Reinauer, <stepan@suse.de>
+ *
+ * This program is based on mngplay, part of libmng, written and (C) by
+ * Ralph Giles <giles@ashlu.bc.ca>
+ *
+ * This program my be redistributed under the terms of the
+ * GNU General Public Licence, version 2, or at your preference,
+ * any later version.
+ */
+
+#ifndef __HOOKS_H
+#define __HOOKS_H
+
+#include "fbmngplay.h"
+
+extern mngstuff *mng;
+
+mng_ptr mngalloc(mng_uint32 size);
+void mngfree(mng_ptr p, mng_uint32 size);
+mng_bool mngopenstream(mng_handle mng);
+mng_bool mngclosestream(mng_handle mng);
+mng_bool mngreadstream( mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 * bytesread);
+mng_bool mngprocessheader( mng_handle mng, mng_uint32 width, mng_uint32 height);
+mng_ptr mnggetcanvasline(mng_handle mng, mng_uint32 line);
+mng_uint32 mnggetticks(mng_handle mng);
+mng_bool mngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h);
+mng_bool mngsettimer(mng_handle mng, mng_uint32 msecs);
+mng_bool mngerror(mng_handle mng, mng_int32 code, mng_int8 severity,
+ mng_chunkid chunktype, mng_uint32 chunkseq,
+ mng_int32 extra1, mng_int32 extra2, mng_pchar text);
+int mngquit(mng_handle mng);
+void cleanup(void);
+void restore_area(void);
+
+#endif
+