shithub: dumb

Download patch

ref: 54a1797e76b72fdc2d8aa780b920179c9c18cb24
parent: 242103a85280e574a5b881e277e43159d1aaeffb
parent: b1fd89712225fed501970ab417706453f7640fc6
author: Christopher Snowhill <kode54@gmail.com>
date: Thu May 5 19:11:48 EDT 2016

Merge pull request #29 from winterheart/allegro4

Allegro4 support

diff: cannot open b/src/allegro//null: file does not exist: 'b/src/allegro//null'
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,6 +4,7 @@
 set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake-scripts)
 
 option(BUILD_EXAMPLES "Build example binaries" ON)
+option(BUILD_ALLEGRO4 "Build Allegro4 support" ON)
 
 set(CMAKE_C_FLAGS "-Wall -DDUMB_DECLARE_DEPRECATED -D_USE_SSE -msse -Wno-unused-variable -Wno-unused-but-set-variable")
 set(CMAKE_C_FLAGS_DEBUG "-ggdb -DDEBUGMODE=1 -D_DEBUG")
@@ -21,6 +22,12 @@
     message(STATUS "Not building examples")
 endif()
 
+if(BUILD_ALLEGRO4)
+    find_package(Allegro4)
+else()
+    message(STATUS "Not building Allegro 4 support")
+endif()
+
 SET(SOURCES
     src/core/unload.c
     src/core/rendsig.c
@@ -113,9 +120,33 @@
     ../include/dumb.h
 )
 
+set(ALLEGRO_SOURCES
+    src/allegro/alplay.c
+    src/allegro/datitq.c
+    src/allegro/dats3m.c
+    src/allegro/datxm.c
+    src/allegro/datduh.c
+    src/allegro/datmod.c
+    src/allegro/dats3mq.c
+    src/allegro/datxmq.c
+    src/allegro/datit.c
+    src/allegro/datmodq.c
+    src/allegro/datunld.c
+    src/allegro/packfile.c
+)
+
+
 add_library(dumb ${SOURCES})
 set_target_properties(dumb PROPERTIES DEBUG_POSTFIX d)
 
+set(ALLEGRO4_TARGETS "")
+if(BUILD_ALLEGRO4)
+    add_library(aldmb ${ALLEGRO_SOURCES})
+    set(ALLEGRO4_TARGETS ${ALLEGRO_TARGETS} aldmb)
+    set(ALLEGRO4_HEADERS indclude/aldumb.h)
+    target_link_libraries(aldmb ${ALLEGRO_LIBRARIES})
+endif()
+
 set(EXAMPLE_TARGETS "")
 
 if(BUILD_EXAMPLES)
@@ -141,7 +172,7 @@
 
 target_link_libraries(dumb m)
 
-INSTALL(FILES ${INSTALL_HEADERS} DESTINATION include/)
+INSTALL(FILES ${INSTALL_HEADERS} ${ALLEGRO_HEADERS} DESTINATION include/)
 INSTALL(TARGETS dumb ${EXAMPLE_TARGETS}
     RUNTIME DESTINATION bin
     LIBRARY DESTINATION lib${LIB_SUFFIX}
--- /dev/null
+++ b/cmake-scripts/FindAllegro4.cmake
@@ -1,0 +1,51 @@
+# - Find allegro
+# Find the native ALLEGRO includes and library
+#
+# ALLEGRO_INCLUDE_DIR - where to find allegro.h, etc.
+# ALLEGRO_LIBRARIES - List of libraries when using allegro.
+# ALLEGRO_FOUND - True if allegro found.
+
+
+IF (ALLEGRO_INCLUDE_DIR)
+    # Already in cache, be silent
+    SET(ALLEGRO_FIND_QUIETLY TRUE)
+ENDIF (ALLEGRO_INCLUDE_DIR)
+
+FIND_PATH(ALLEGRO_INCLUDE_DIR allegro.h
+/usr/local/include
+/usr/include
+$ENV{MINGDIR}/include
+)
+
+if(UNIX AND NOT CYGWIN)
+    exec_program(allegro-config ARGS --libs OUTPUT_VARIABLE ALLEGRO_LIBRARY)
+else(UNIX AND NOT CYGWIN)
+    SET(ALLEGRO_NAMES alleg alleglib alleg41 alleg42 allegdll)
+    FIND_LIBRARY(ALLEGRO_LIBRARY
+        NAMES ${ALLEGRO_NAMES}
+        PATHS /usr/lib /usr/local/lib $ENV{MINGDIR}/lib)
+endif(UNIX AND NOT CYGWIN)
+
+IF (ALLEGRO_INCLUDE_DIR AND ALLEGRO_LIBRARY)
+    SET(ALLEGRO_FOUND TRUE)
+    SET( ALLEGRO_LIBRARIES ${ALLEGRO_LIBRARY} )
+ELSE (ALLEGRO_INCLUDE_DIR AND ALLEGRO_LIBRARY)
+    SET(ALLEGRO_FOUND FALSE)
+    SET( ALLEGRO_LIBRARIES )
+ENDIF (ALLEGRO_INCLUDE_DIR AND ALLEGRO_LIBRARY)
+
+IF (ALLEGRO_FOUND)
+    IF (NOT ALLEGRO_FIND_QUIETLY)
+        MESSAGE(STATUS "Found Allegro: ${ALLEGRO_LIBRARY}")
+    ENDIF (NOT ALLEGRO_FIND_QUIETLY)
+ELSE (ALLEGRO_FOUND)
+    IF (ALLEGRO_FIND_REQUIRED)
+        MESSAGE(STATUS "Looked for Allegro libraries named ${ALLEGRO_NAMES}.")
+        MESSAGE(FATAL_ERROR "Could NOT find Allegro library")
+    ENDIF (ALLEGRO_FIND_REQUIRED)
+ENDIF (ALLEGRO_FOUND)
+
+MARK_AS_ADVANCED(
+ALLEGRO_LIBRARY
+ALLEGRO_INCLUDE_DIR
+)
\ No newline at end of file
--- /dev/null
+++ b/include/aldumb.h
@@ -1,0 +1,98 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * aldumb.h - The user header file for DUMB with      / / \  \
+ *            Allegro.                               | <  /   \_
+ *                                                   |  \/ /\   /
+ * Include this file if you wish to use DUMB          \_  /  > /
+ * with Allegro. It will include dumb.h for you,        | \ / /
+ * and provide extra functionality such as audio        |  ' /
+ * stream and datafile integration.                      \__/
+ */
+
+#ifndef ALDUMB_H
+#define ALDUMB_H
+
+
+#include <allegro.h>
+
+#include "dumb.h"
+
+
+#ifdef __cplusplus
+	extern "C" {
+#endif
+
+
+/* Packfile Support */
+
+void dumb_register_packfiles(void);
+
+DUMBFILE *dumbfile_open_packfile(PACKFILE *p);
+DUMBFILE *dumbfile_from_packfile(PACKFILE *p);
+
+
+/* Datafile Registration Functions */
+
+#define DUMB_DAT_DUH DAT_ID('D','U','H',' ')
+#define DUMB_DAT_IT  DAT_ID('I','T',' ',' ')
+#define DUMB_DAT_XM  DAT_ID('X','M',' ',' ')
+#define DUMB_DAT_S3M DAT_ID('S','3','M',' ')
+#define DUMB_DAT_MOD DAT_ID('M','O','D',' ')
+
+void dumb_register_dat_duh(long type);
+void dumb_register_dat_it(long type);
+void dumb_register_dat_xm(long type);
+void dumb_register_dat_s3m(long type);
+void dumb_register_dat_mod(long type);
+void dumb_register_dat_it_quick(long type);
+void dumb_register_dat_xm_quick(long type);
+void dumb_register_dat_s3m_quick(long type);
+void dumb_register_dat_mod_quick(long type);
+
+
+/* DUH Playing Functions */
+
+typedef struct AL_DUH_PLAYER AL_DUH_PLAYER;
+
+AL_DUH_PLAYER *al_start_duh(DUH *duh, int n_channels, long pos, float volume, long bufsize, int freq);
+void al_stop_duh(AL_DUH_PLAYER *dp);
+void al_pause_duh(AL_DUH_PLAYER *dp);
+void al_resume_duh(AL_DUH_PLAYER *dp);
+void al_duh_set_priority(AL_DUH_PLAYER *dp, int priority);
+void al_duh_set_volume(AL_DUH_PLAYER *dp, float volume);
+float al_duh_get_volume(AL_DUH_PLAYER *dp);
+int al_poll_duh(AL_DUH_PLAYER *dp);
+long al_duh_get_position(AL_DUH_PLAYER *dp);
+
+AL_DUH_PLAYER *al_duh_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer, float volume, long bufsize, int freq);
+DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp);
+
+/* IMPORTANT: This function will return NULL if the music has ended. */
+DUH_SIGRENDERER *al_duh_decompose_to_sigrenderer(AL_DUH_PLAYER *dp);
+
+#ifdef DUMB_DECLARE_DEPRECATED
+
+AL_DUH_PLAYER *al_duh_encapsulate_renderer(DUH_SIGRENDERER *dr, float volume, long bufsize, int freq) DUMB_DEPRECATED;
+DUH_SIGRENDERER *al_duh_get_renderer(AL_DUH_PLAYER *dp) DUMB_DEPRECATED;
+DUH_SIGRENDERER *al_duh_decompose_to_renderer(AL_DUH_PLAYER *dp) DUMB_DEPRECATED;
+/* Replace 'renderer' with 'sigrenderer' in each case where you called one of
+ * these functions.
+ */
+
+#endif
+
+
+#ifdef __cplusplus
+	}
+#endif
+
+
+#endif /* ALDUMB_H */
--- /dev/null
+++ b/src/allegro/alplay.c
@@ -1,0 +1,277 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * alplay.c - Functions to play a DUH through         / / \  \
+ *            an Allegro audio stream.               | <  /   \_
+ *                                                   |  \/ /\   /
+ * By entheh.                                         \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <stdlib.h>
+
+#include <allegro.h>
+
+#include "aldumb.h"
+
+
+
+#define ADP_PLAYING 1
+
+struct AL_DUH_PLAYER
+{
+	int flags;
+	long bufsize;
+	int freq;
+	AUDIOSTREAM *stream;
+	DUH_SIGRENDERER *sigrenderer; /* If this is NULL, stream is invalid. */
+	float volume;
+	int silentcount;
+};
+
+
+
+AL_DUH_PLAYER *al_start_duh(DUH *duh, int n_channels, long pos, float volume, long bufsize, int freq)
+{
+	AL_DUH_PLAYER *dp;
+
+	/* This restriction is imposed by Allegro. */
+	ASSERT(n_channels > 0);
+	ASSERT(n_channels <= 2);
+
+	if (!duh)
+		return NULL;
+
+	dp = malloc(sizeof(*dp));
+	if (!dp)
+		return NULL;
+
+	dp->flags = ADP_PLAYING;
+	dp->bufsize = bufsize;
+	dp->freq = freq;
+
+	dp->stream = play_audio_stream(bufsize, 16, n_channels - 1, freq, 255, 128);
+
+	if (!dp->stream) {
+		free(dp);
+		return NULL;
+	}
+
+	voice_set_priority(dp->stream->voice, 255);
+
+	dp->sigrenderer = duh_start_sigrenderer(duh, 0, n_channels, pos);
+
+	if (!dp->sigrenderer) {
+		stop_audio_stream(dp->stream);
+		free(dp);
+		return NULL;
+	}
+
+	dp->volume = volume;
+	dp->silentcount = 0;
+
+	return dp;
+}
+
+
+
+void al_stop_duh(AL_DUH_PLAYER *dp)
+{
+	if (dp) {
+		if (dp->sigrenderer) {
+			duh_end_sigrenderer(dp->sigrenderer);
+			stop_audio_stream(dp->stream);
+		}
+		free(dp);
+	}
+}
+
+
+
+void al_pause_duh(AL_DUH_PLAYER *dp)
+{
+	if (dp && dp->sigrenderer && (dp->flags & ADP_PLAYING)) {
+		voice_stop(dp->stream->voice);
+		dp->flags &= ~ADP_PLAYING;
+	}
+}
+
+
+
+void al_resume_duh(AL_DUH_PLAYER *dp)
+{
+	if (dp && dp->sigrenderer && !(dp->flags & ADP_PLAYING)) {
+		voice_start(dp->stream->voice);
+		dp->flags |= ADP_PLAYING;
+	}
+}
+
+
+
+void al_duh_set_priority(AL_DUH_PLAYER *dp, int priority)
+{
+	if (dp && dp->sigrenderer)
+		voice_set_priority(dp->stream->voice, priority);
+}
+
+
+
+void al_duh_set_volume(AL_DUH_PLAYER *dp, float volume)
+{
+	if (dp)
+		dp->volume = volume;
+}
+
+
+
+float al_duh_get_volume(AL_DUH_PLAYER *dp)
+{
+	return dp ? dp->volume : 0;
+}
+
+
+
+int al_poll_duh(AL_DUH_PLAYER *dp)
+{
+	unsigned short *sptr;
+	long n;
+	long size;
+	int n_channels;
+
+	if (!dp || !dp->sigrenderer)
+		return 1;
+
+	if (!(dp->flags & ADP_PLAYING))
+		return 0;
+
+	sptr = get_audio_stream_buffer(dp->stream);
+
+	if (!sptr)
+		return 0;
+
+	n = duh_render(dp->sigrenderer, 16, 1, dp->volume, 65536.0 / dp->freq, dp->bufsize, sptr);
+
+	if (n == 0) {
+		if (++dp->silentcount >= 2) {
+			duh_end_sigrenderer(dp->sigrenderer);
+			free_audio_stream_buffer(dp->stream);
+			stop_audio_stream(dp->stream);
+			dp->sigrenderer = NULL;
+			return 1;
+		}
+	}
+
+	n_channels = duh_sigrenderer_get_n_channels(dp->sigrenderer);
+	n *= n_channels;
+	size = dp->bufsize * n_channels;
+	for (; n < size; n++)
+		sptr[n] = 0x8000;
+
+	free_audio_stream_buffer(dp->stream);
+
+	return 0;
+}
+
+
+
+long al_duh_get_position(AL_DUH_PLAYER *dp)
+{
+	return dp ? duh_sigrenderer_get_position(dp->sigrenderer) : -1;
+}
+
+
+
+AL_DUH_PLAYER *al_duh_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer, float volume, long bufsize, int freq)
+{
+	AL_DUH_PLAYER *dp;
+	int n_channels;
+
+	if (!sigrenderer)
+		return NULL;
+
+	dp = malloc(sizeof(*dp));
+	if (!dp)
+		return NULL;
+
+	n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
+
+	/* This restriction is imposed by Allegro. */
+	ASSERT(n_channels > 0);
+	ASSERT(n_channels <= 2);
+
+	dp->flags = ADP_PLAYING;
+	dp->bufsize = bufsize;
+	dp->freq = freq;
+
+	dp->stream = play_audio_stream(bufsize, 16, n_channels - 1, freq, 255, 128);
+
+	if (!dp->stream) {
+		free(dp);
+		return NULL;
+	}
+
+	voice_set_priority(dp->stream->voice, 255);
+
+	dp->sigrenderer = sigrenderer;
+
+	dp->volume = volume;
+	dp->silentcount = 0;
+
+	return dp;
+}
+
+
+
+DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp)
+{
+	return dp ? dp->sigrenderer : NULL;
+}
+
+
+
+/* IMPORTANT: This function will return NULL if the music has ended. */
+// Should this be changed? User might want to hack the underlying SIGRENDERER
+// and resurrect it (e.g. change pattern number), before it gets destroyed...
+DUH_SIGRENDERER *al_duh_decompose_to_sigrenderer(AL_DUH_PLAYER *dp)
+{
+	if (dp) {
+		DUH_SIGRENDERER *sigrenderer = dp->sigrenderer;
+		if (sigrenderer) stop_audio_stream(dp->stream);
+		free(dp);
+		return sigrenderer;
+	}
+	return NULL;
+}
+
+
+
+/* DEPRECATED */
+AL_DUH_PLAYER *al_duh_encapsulate_renderer(DUH_SIGRENDERER *dr, float volume, long bufsize, int freq)
+{
+	return al_duh_encapsulate_sigrenderer(dr, volume, bufsize, freq);
+}
+
+
+
+/* DEPRECATED */
+DUH_SIGRENDERER *al_duh_get_renderer(AL_DUH_PLAYER *dp)
+{
+	return al_duh_get_sigrenderer(dp);
+}
+
+
+
+/* DEPRECATED */
+DUH_SIGRENDERER *al_duh_decompose_to_renderer(AL_DUH_PLAYER *dp)
+{
+	return al_duh_decompose_to_sigrenderer(dp);
+}
--- /dev/null
+++ b/src/allegro/datduh.c
@@ -1,0 +1,60 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * datduh.c - Integration with Allegro's              / / \  \
+ *            datafiles.                             | <  /   \_
+ *                                                   |  \/ /\   /
+ * By entheh.                                         \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <allegro.h>
+
+#include "aldumb.h"
+#include "internal/aldumb.h"
+
+
+
+static void *dat_read_duh(PACKFILE *f, long size)
+{
+	DUMBFILE *df;
+	DUH *duh;
+
+	(void)size;
+
+	df = dumbfile_open_packfile(f);
+
+	if (!df)
+		return NULL;
+
+	duh = read_duh(df);
+
+	dumbfile_close(df);
+
+	return duh;
+}
+
+
+
+/* dumb_register_dat_duh(): tells Allegro about the DUH datafile object. If
+ * you intend to load a datafile containing a DUH object, you must call this
+ * function first. It is recommended you pass DAT_DUH, but you may have a
+ * reason to use a different type (apart from pride, that doesn't count).
+ */
+void dumb_register_dat_duh(long type)
+{
+	register_datafile_object(
+		type,
+		&dat_read_duh,
+		&_dat_unload_duh
+	);
+}
--- /dev/null
+++ b/src/allegro/datit.c
@@ -1,0 +1,62 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * datit.c - Integration of IT files with             / / \  \
+ *           Allegro's datafiles.                    | <  /   \_
+ *                                                   |  \/ /\   /
+ * By entheh.                                         \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <allegro.h>
+
+#include "aldumb.h"
+#include "internal/aldumb.h"
+
+
+
+static void *dat_read_it(PACKFILE *f, long size)
+{
+	DUMBFILE *df;
+	DUH *duh;
+
+	(void)size;
+
+	df = dumbfile_open_packfile(f);
+
+	if (!df)
+		return NULL;
+
+	duh = dumb_read_it(df);
+
+	dumbfile_close(df);
+
+	return duh;
+}
+
+
+
+/* dumb_register_dat_it(): tells Allegro about the IT datafile object. If you
+ * intend to load a datafile containing an IT object, you must call this
+ * function first. It is recommended you pass DUMB_DAT_IT, but you may have a
+ * reason to use a different type (perhaps you already have a datafile with
+ * IT files in and they use a different type).
+ */
+void dumb_register_dat_it(long type)
+{
+	register_datafile_object(
+		type,
+		&dat_read_it,
+		&_dat_unload_duh
+	);
+}
+
--- /dev/null
+++ b/src/allegro/datitq.c
@@ -1,0 +1,64 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * datitq.c - Integration of IT files with            / / \  \
+ *            Allegro's datafiles.                   | <  /   \_
+ *                                                   |  \/ /\   /
+ * By entheh.                                         \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <allegro.h>
+
+#include "aldumb.h"
+#include "internal/aldumb.h"
+
+
+
+static void *dat_read_it_quick(PACKFILE *f, long size)
+{
+	DUMBFILE *df;
+	DUH *duh;
+
+	(void)size;
+
+	df = dumbfile_open_packfile(f);
+
+	if (!df)
+		return NULL;
+
+	duh = dumb_read_it_quick(df);
+
+	dumbfile_close(df);
+
+	return duh;
+}
+
+
+
+/* dumb_register_dat_it_quick(): tells Allegro about the IT datafile object.
+ * If you intend to load a datafile containing an IT object, you must call
+ * this function first. It is recommended you pass DUMB_DAT_IT, but you may
+ * have a reason to use a different type (perhaps you already have a datafile
+ * with IT files in and they use a different type).
+ *
+ * This installs the quick loader: the song length and fast seek points are
+ * not calculated.
+ */
+void dumb_register_dat_it_quick(long type)
+{
+	register_datafile_object(
+		type,
+		&dat_read_it_quick,
+		&_dat_unload_duh
+	);
+}
--- /dev/null
+++ b/src/allegro/datmod.c
@@ -1,0 +1,61 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * datmod.c - Integration of MOD files with           / / \  \
+ *            Allegro's datafiles.                   | <  /   \_
+ *                                                   |  \/ /\   /
+ * By entheh.                                         \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <allegro.h>
+
+#include "aldumb.h"
+#include "internal/aldumb.h"
+
+
+
+static void *dat_read_mod(PACKFILE *f, long size)
+{
+	DUMBFILE *df;
+	DUH *duh;
+
+	(void)size;
+
+	df = dumbfile_open_packfile(f);
+
+	if (!df)
+		return NULL;
+
+	duh = dumb_read_mod(df, 2);
+
+	dumbfile_close(df);
+
+	return duh;
+}
+
+
+
+/* dumb_register_dat_mod(): tells Allegro about the MOD datafile object. If
+ * you intend to load a datafile containing a MOD object, you must call this
+ * function first. It is recommended you pass DUMB_DAT_MOD, but you may have
+ * a reason to use a different type (perhaps you already have a datafile with
+ * MOD files in and they use a different type).
+ */
+void dumb_register_dat_mod(long type)
+{
+	register_datafile_object(
+		type,
+		&dat_read_mod,
+		&_dat_unload_duh
+	);
+}
--- /dev/null
+++ b/src/allegro/datmodq.c
@@ -1,0 +1,64 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * datmodq.c - Integration of MOD files with          / / \  \
+ *             Allegro's datafiles.                  | <  /   \_
+ *                                                   |  \/ /\   /
+ * By entheh.                                         \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <allegro.h>
+
+#include "aldumb.h"
+#include "internal/aldumb.h"
+
+
+
+static void *dat_read_mod_quick(PACKFILE *f, long size)
+{
+	DUMBFILE *df;
+	DUH *duh;
+
+	(void)size;
+
+	df = dumbfile_open_packfile(f);
+
+	if (!df)
+		return NULL;
+
+	duh = dumb_read_mod_quick(df, 2);
+
+	dumbfile_close(df);
+
+	return duh;
+}
+
+
+
+/* dumb_register_dat_mod_quick(): tells Allegro about the MOD datafile object.
+ * If you intend to load a datafile containing a MOD object, you must call this
+ * function first. It is recommended you pass DUMB_DAT_MOD, but you may have
+ * a reason to use a different type (perhaps you already have a datafile with
+ * MOD files in and they use a different type).
+ *
+ * This installs the quick loader: the song length and fast seek points are
+ * not calculated.
+ */
+void dumb_register_dat_mod_quick(long type)
+{
+	register_datafile_object(
+		type,
+		&dat_read_mod_quick,
+		&_dat_unload_duh
+	);
+}
--- /dev/null
+++ b/src/allegro/dats3m.c
@@ -1,0 +1,61 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * dats3m.c - Integration of S3M files with           / / \  \
+ *            Allegro's datafiles.                   | <  /   \_
+ *                                                   |  \/ /\   /
+ * By entheh.                                         \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <allegro.h>
+
+#include "aldumb.h"
+#include "internal/aldumb.h"
+
+
+
+static void *dat_read_s3m(PACKFILE *f, long size)
+{
+	DUMBFILE *df;
+	DUH *duh;
+
+	(void)size;
+
+	df = dumbfile_open_packfile(f);
+
+	if (!df)
+		return NULL;
+
+	duh = dumb_read_s3m(df);
+
+	dumbfile_close(df);
+
+	return duh;
+}
+
+
+
+/* dumb_register_dat_s3m(): tells Allegro about the S3M datafile object. If
+ * you intend to load a datafile containing an S3M object, you must call this
+ * function first. It is recommended you pass DUMB_DAT_S3M, but you may have
+ * a reason to use a different type (perhaps you already have a datafile with
+ * S3M files in and they use a different type).
+ */
+void dumb_register_dat_s3m(long type)
+{
+	register_datafile_object(
+		type,
+		&dat_read_s3m,
+		&_dat_unload_duh
+	);
+}
--- /dev/null
+++ b/src/allegro/dats3mq.c
@@ -1,0 +1,64 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * dats3mq.c - Integration of S3M files with          / / \  \
+ *             Allegro's datafiles.                  | <  /   \_
+ *                                                   |  \/ /\   /
+ * By entheh.                                         \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <allegro.h>
+
+#include "aldumb.h"
+#include "internal/aldumb.h"
+
+
+
+static void *dat_read_s3m_quick(PACKFILE *f, long size)
+{
+	DUMBFILE *df;
+	DUH *duh;
+
+	(void)size;
+
+	df = dumbfile_open_packfile(f);
+
+	if (!df)
+		return NULL;
+
+	duh = dumb_read_s3m_quick(df);
+
+	dumbfile_close(df);
+
+	return duh;
+}
+
+
+
+/* dumb_register_dat_s3m_quick(): tells Allegro about the S3M datafile object.
+ * If you intend to load a datafile containing an S3M object, you must call this
+ * function first. It is recommended you pass DUMB_DAT_S3M, but you may have
+ * a reason to use a different type (perhaps you already have a datafile with
+ * S3M files in and they use a different type).
+ *
+ * This installs the quick loader: the song length and fast seek points are
+ * not calculated.
+ */
+void dumb_register_dat_s3m_quick(long type)
+{
+	register_datafile_object(
+		type,
+		&dat_read_s3m_quick,
+		&_dat_unload_duh
+	);
+}
--- /dev/null
+++ b/src/allegro/datunld.c
@@ -1,0 +1,31 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * datunld.c - Unload function for integration        / / \  \
+ *             with Allegro's datafiles.             | <  /   \_
+ *                                                   |  \/ /\   /
+ * By entheh.                                         \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <allegro.h>
+
+#include "aldumb.h"
+#include "internal/aldumb.h"
+
+
+
+void _dat_unload_duh(void *duh)
+{
+	unload_duh(duh);
+}
+
--- /dev/null
+++ b/src/allegro/datxm.c
@@ -1,0 +1,62 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * datxm.c - Integration of XM files with             / / \  \
+ *           Allegro's datafiles.                    | <  /   \_
+ *                                                   |  \/ /\   /
+ * By entheh.                                         \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <allegro.h>
+
+#include "aldumb.h"
+#include "internal/aldumb.h"
+
+
+
+static void *dat_read_xm(PACKFILE *f, long size)
+{
+	DUMBFILE *df;
+	DUH *duh;
+
+	(void)size;
+
+	df = dumbfile_open_packfile(f);
+
+	if (!df)
+		return NULL;
+
+	duh = dumb_read_xm(df);
+
+	dumbfile_close(df);
+
+	return duh;
+}
+
+
+
+/* dumb_register_dat_xm(): tells Allegro about the XM datafile object. If you
+ * intend to load a datafile containing an XM object, you must call this
+ * function first. It is recommended you pass DUMB_DAT_XM, but you may have a
+ * reason to use a different type (perhaps you already have a datafile with
+ * XM files in and they use a different type).
+ */
+void dumb_register_dat_xm(long type)
+{
+	register_datafile_object(
+		type,
+		&dat_read_xm,
+		&_dat_unload_duh
+	);
+}
+
--- /dev/null
+++ b/src/allegro/datxmq.c
@@ -1,0 +1,64 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * datxmq.c - Integration of XM files with            / / \  \
+ *            Allegro's datafiles.                   | <  /   \_
+ *                                                   |  \/ /\   /
+ * By entheh.                                         \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <allegro.h>
+
+#include "aldumb.h"
+#include "internal/aldumb.h"
+
+
+
+static void *dat_read_xm_quick(PACKFILE *f, long size)
+{
+	DUMBFILE *df;
+	DUH *duh;
+
+	(void)size;
+
+	df = dumbfile_open_packfile(f);
+
+	if (!df)
+		return NULL;
+
+	duh = dumb_read_xm_quick(df);
+
+	dumbfile_close(df);
+
+	return duh;
+}
+
+
+
+/* dumb_register_dat_xm_quick(): tells Allegro about the XM datafile object.
+ * If you intend to load a datafile containing an XM object, you must call this
+ * function first. It is recommended you pass DUMB_DAT_XM, but you may have a
+ * reason to use a different type (perhaps you already have a datafile with
+ * XM files in and they use a different type).
+ *
+ * This installs the quick loader: the song length and fast seek points are
+ * not calculated.
+ */
+void dumb_register_dat_xm_quick(long type)
+{
+	register_datafile_object(
+		type,
+		&dat_read_xm_quick,
+		&_dat_unload_duh
+	);
+}
--- /dev/null
+++ b/src/allegro/packfile.c
@@ -1,0 +1,134 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * packfile.c - Packfile input module.                / / \  \
+ *                                                   | <  /   \_
+ * By entheh.                                        |  \/ /\   /
+ *                                                    \_  /  > /
+ * Note that this does not use file compression;        | \ / /
+ * for that you must open the file yourself and         |  ' /
+ * then use dumbfile_open_packfile().                    \__/
+ */
+
+#include <allegro.h>
+
+#include "aldumb.h"
+
+
+typedef struct dumb_packfile
+{
+	FILE * file;
+	long size;
+} dumb_packfile;
+
+
+static void *dumb_packfile_open(const char *filename)
+{
+	dumb_packfile * file = ( dumb_packfile * ) malloc( sizeof(dumb_packfile) );
+	if ( !file ) return 0;
+	file->file = fopen(filename, "rb");
+	fseek(file->file, 0, SEEK_END);
+	file->size = ftell(file->file);
+	fseek(file->file, 0, SEEK_SET);
+	return file;
+}
+
+
+
+static int dumb_packfile_skip(void *f, long n)
+{
+	dumb_packfile * file = ( dumb_packfile * ) f;
+	return fseek(file->file, n, SEEK_CUR);
+}
+
+
+
+static int dumb_packfile_getc(void *f)
+{
+	dumb_packfile * file = ( dumb_packfile * ) f;
+	return fgetc(file->file);
+}
+
+
+
+static long dumb_packfile_getnc(char *ptr, long n, void *f)
+{
+	dumb_packfile * file = ( dumb_packfile * ) f;
+	return fread(ptr, 1, n, file->file);
+}
+
+
+
+static void dumb_packfile_close(void *f)
+{
+	dumb_packfile * file = ( dumb_packfile * ) f;
+	fclose(file->file);
+	free(f);
+}
+
+static void dumb_packfile_noclose(void *f)
+{
+	free(f);
+}
+
+static int dumb_packfile_seek(void *f, long n)
+{
+	dumb_packfile * file = (dumb_packfile *) f;
+	return fseek(file->file, n, SEEK_SET);
+}
+
+static long dumb_packfile_get_size(void *f)
+{
+	dumb_packfile * file = (dumb_packfile *) f;
+	return file->size;
+}
+
+static DUMBFILE_SYSTEM packfile_dfs = {
+	&dumb_packfile_open,
+	&dumb_packfile_skip,
+	&dumb_packfile_getc,
+	&dumb_packfile_getnc,
+	&dumb_packfile_close,
+	&dumb_packfile_seek,
+	&dumb_packfile_get_size
+};
+
+
+
+void dumb_register_packfiles(void)
+{
+	register_dumbfile_system(&packfile_dfs);
+}
+
+
+
+static DUMBFILE_SYSTEM packfile_dfs_leave_open = {
+	NULL,
+	&dumb_packfile_skip,
+	&dumb_packfile_getc,
+	&dumb_packfile_getnc,
+	&dumb_packfile_noclose,
+	&dumb_packfile_seek,
+	&dumb_packfile_get_size
+};
+
+
+
+DUMBFILE *dumbfile_open_packfile(PACKFILE *p)
+{
+	return dumbfile_open_ex(p, &packfile_dfs_leave_open);
+}
+
+
+
+DUMBFILE *dumbfile_from_packfile(PACKFILE *p)
+{
+	return p ? dumbfile_open_ex(p, &packfile_dfs) : NULL;
+}