diff -ruN lxdoom-1.4.1.orig/Makefile.in lxdoom-1.4.1/Makefile.in --- lxdoom-1.4.1.orig/Makefile.in Tue Oct 19 13:55:30 1999 +++ lxdoom-1.4.1/Makefile.in Sun Dec 26 02:37:44 1999 @@ -71,12 +71,18 @@ target_triplet = @target@ BUILD_LSDOOM = @BUILD_LSDOOM@ BUILD_LXDOOM = @BUILD_LXDOOM@ +BUILD_SDLDOOM = @BUILD_SDLDOOM@ BUILD_SNDSERV = @BUILD_SNDSERV@ CC = @CC@ LIB_XDGA = @LIB_XDGA@ LIB_XEXT = @LIB_XEXT@ MAKEINFO = @MAKEINFO@ +MIXER_CFLAGS = @MIXER_CFLAGS@ +MIXER_LIBS = @MIXER_LIBS@ PACKAGE = @PACKAGE@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ VERSION = @VERSION@ SUBDIRS = doc data src diff -ruN lxdoom-1.4.1.orig/acinclude.m4 lxdoom-1.4.1/acinclude.m4 --- lxdoom-1.4.1.orig/acinclude.m4 Wed Dec 31 16:00:00 1969 +++ lxdoom-1.4.1/acinclude.m4 Sat Dec 25 13:52:39 1999 @@ -0,0 +1,168 @@ +# Configure paths for SDL +# Sam Lantinga 9/21/99 +# stolen from Manish Singh +# stolen back from Frank Belew +# stolen from Manish Singh +# Shamelessly stolen from Owen Taylor + +dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS +dnl +AC_DEFUN(AM_PATH_SDL, +[dnl +dnl Get the cflags and libraries from the sdl-config script +dnl +AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], + sdl_prefix="$withval", sdl_prefix="") +AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], + sdl_exec_prefix="$withval", sdl_exec_prefix="") +AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], + , enable_sdltest=yes) + + if test x$sdl_exec_prefix != x ; then + sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config + fi + fi + if test x$sdl_prefix != x ; then + sdl_args="$sdl_args --prefix=$sdl_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_prefix/bin/sdl-config + fi + fi + + AC_PATH_PROG(SDL_CONFIG, sdl-config, no) + min_sdl_version=ifelse([$1], ,0.11.0,$1) + AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) + no_sdl="" + if test "$SDL_CONFIG" = "no" ; then + no_sdl=yes + else + SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` + SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` + + sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_sdltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" +dnl +dnl Now check if the installed SDL is sufficiently new. (Also sanity +dnl checks the results of sdl-config to some extent +dnl + rm -f conf.sdltest + AC_TRY_RUN([ +#include +#include +#include +#include "SDL.h" + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major, minor, micro; + char *tmp_version; + + /* This hangs on some systems (?) + system ("touch conf.sdltest"); + */ + { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_sdl_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_sdl_version"); + exit(1); + } + + if (($sdl_major_version > major) || + (($sdl_major_version == major) && ($sdl_minor_version > minor)) || + (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); + printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); + printf("*** to point to the correct copy of sdl-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_sdl" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$SDL_CONFIG" = "no" ; then + echo "*** The sdl-config script installed by SDL could not be found" + echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the SDL_CONFIG environment variable to the" + echo "*** full path to sdl-config." + else + if test -f conf.sdltest ; then + : + else + echo "*** Could not run SDL test program, checking why..." + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + AC_TRY_LINK([ +#include +#include "SDL.h" +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding SDL or finding the wrong" + echo "*** version of SDL. If it is not finding SDL, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means SDL was incorrectly installed" + echo "*** or that you have moved SDL since it was installed. In the latter case, you" + echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + SDL_CFLAGS="" + SDL_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(SDL_CFLAGS) + AC_SUBST(SDL_LIBS) + rm -f conf.sdltest +]) diff -ruN lxdoom-1.4.1.orig/configure.in lxdoom-1.4.1/configure.in --- lxdoom-1.4.1.orig/configure.in Mon Oct 18 12:16:42 1999 +++ lxdoom-1.4.1/configure.in Sun Dec 26 02:34:28 1999 @@ -45,6 +45,11 @@ dnl --- CPhipps - disable XFree86 DGA support for release dnl AC_CHECK_LIB(Xxf86dga,XF86DGADirectVideo,AC_DEFINE(HAVE_LIBXXF86DGA) LIB_XDGA=-lXxf86dga,LIB_XDGA=,-lXxf86dga -lXext -lX11) AC_CHECK_LIB(vga,vga_setpalvec,BUILD_LSDOOM=lsdoom,BUILD_LSDOOM=) +AM_PATH_SDL(1.0.1, BUILD_SDLDOOM=lsdldoom, BUILD_SDLDOOM=) +AC_CHECK_LIB(mixer,open_music,[ + MIXER_CFLAGS=-DHAVE_MIXER + MIXER_LIBS=-lmixer +],) dnl --- Library functions AC_CHECK_FUNC(stricmp,,AC_DEFINE(stricmp,strcasecmp)) @@ -84,6 +89,10 @@ AC_SUBST(BUILD_SNDSERV) AC_SUBST(BUILD_LXDOOM) AC_SUBST(BUILD_LSDOOM) +AC_SUBST(BUILD_SDLDOOM) +AC_SUBST(SDL_CFLAGS) +AC_SUBST(MIXER_CFLAGS) +AC_SUBST(MIXER_LIBS) AC_SUBST(LIB_XEXT) AC_SUBST(LIB_XDGA) diff -ruN lxdoom-1.4.1.orig/src/Makefile.am lxdoom-1.4.1/src/Makefile.am --- lxdoom-1.4.1.orig/src/Makefile.am Sat Oct 2 08:00:48 1999 +++ lxdoom-1.4.1/src/Makefile.am Sun Dec 26 02:31:10 1999 @@ -7,8 +7,8 @@ # # gamesdir=$(prefix)/games -EXTRA_PROGRAMS = lsdoom lxdoom sndserv -games_PROGRAMS = @BUILD_LSDOOM@ @BUILD_LXDOOM@ @BUILD_SNDSERV@ lxdoom-game-server +EXTRA_PROGRAMS = lsdldoom lsdoom lxdoom sndserv +games_PROGRAMS = @BUILD_SDLDOOM@ @BUILD_LSDOOM@ @BUILD_LXDOOM@ @BUILD_SNDSERV@ lxdoom-game-server EXTRA_DIST = makefile.pre-ac if I386_ASM @@ -20,7 +20,7 @@ SYS_CFLAGS = endif -CFLAGS = @X_CFLAGS@ -O2 -ffast-math $(SYS_CFLAGS) -Wall -Winline -Wcast-align -Wwrite-strings +CFLAGS = @X_CFLAGS@ @SDL_CFLAGS@ @MIXER_CFLAGS@ -g -O2 -ffast-math $(SYS_CFLAGS) -Wall -Winline -Wcast-align -Wwrite-strings sndserv_SOURCES = version.c l_soundsrv.c sounds.c l_soundgen.c l_soundsrv.h l_soundgen.h sndserv_LDADD = @@ -47,7 +47,7 @@ m_random.c p_tick.c st_stuff.h l_main.c \ d_think.h m_random.h p_tick.h tables.c \ d_ticcmd.h m_swap.h p_user.c tables.h l_system.c \ - doomdata.h l_sound.c p_ceilng.c p_user.h v_video.c \ + doomdata.h p_ceilng.c p_user.h v_video.c \ doomdef.c p_doors.c protocol.h v_video.h \ doomdef.h p_enemy.c r_bsp.c version.c \ doomstat.c p_enemy.h r_bsp.h version.h \ @@ -60,11 +60,13 @@ f_wipe.c p_map.h r_main.h z_zone.c \ f_wipe.h p_maputl.c r_plane.c z_zone.h $(ASMS) -lxdoom_SOURCES = l_video_trans.h l_video_trans.c l_video_x.c $(COMMON_SRC) -lsdoom_SOURCES = l_video_svgalib.c $(COMMON_SRC) +lxdoom_SOURCES = l_video_trans.h l_video_trans.c l_video_x.c l_sound.c $(COMMON_SRC) +lsdoom_SOURCES = l_video_svgalib.c l_sound.c $(COMMON_SRC) +lsdldoom_SOURCES = l_video_trans.h l_video_trans.c l_video_sdl.c l_sound_sdl.c qmus2mid.c qmus2mid.h $(COMMON_SRC) lxdoom_LDADD = @X_LIBS@ @X_PRE_LIBS@ -lX11 @X_EXTRA_LIBS@ @LIB_XEXT@ @LIB_XDGA@ lsdoom_LDADD = -lvga +lsdldoom_LDADD = -lSDL -lpthread @MIXER_LIBS@ EXTRA_lxdoom_SOURCES = $(ASMS) diff -ruN lxdoom-1.4.1.orig/src/d_main.c lxdoom-1.4.1/src/d_main.c --- lxdoom-1.4.1.orig/src/d_main.c Sun Oct 17 02:35:15 1999 +++ lxdoom-1.4.1/src/d_main.c Sat Dec 25 12:47:22 1999 @@ -1572,7 +1572,7 @@ { int i; - for (i=0; i<3; i++) { + for (i=0; i<4; i++) { const char* folder; char* path_buf; @@ -1582,6 +1582,9 @@ folder = DOOMWADDIR; break; case 2: + folder = D_DoomExeDir(); + break; + case 3: folder = getenv("HOME"); break; default: diff -ruN lxdoom-1.4.1.orig/src/l_sound_sdl.c lxdoom-1.4.1/src/l_sound_sdl.c --- lxdoom-1.4.1.orig/src/l_sound_sdl.c Wed Dec 31 16:00:00 1969 +++ lxdoom-1.4.1/src/l_sound_sdl.c Sun Dec 26 02:30:41 1999 @@ -0,0 +1,774 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// $Id:$ +// +// Copyright (C) 1993-1996 by id Software, Inc. +// +// This source is available for distribution and/or modification +// only under the terms of the DOOM Source Code License as +// published by id Software. All rights reserved. +// +// The source is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License +// for more details. +// +// $Log:$ +// +// DESCRIPTION: +// System interface for sound. +// +//----------------------------------------------------------------------------- + +static const char +rcsid[] = "$Id: i_unix.c,v 1.5 1997/02/03 22:45:10 b1 Exp $"; + +#include +#include + +#include "SDL_audio.h" +#include "SDL_mutex.h" +#include "SDL_byteorder.h" +#include "SDL_version.h" + +#include "z_zone.h" + +#include "m_swap.h" +#include "i_system.h" +#include "i_sound.h" +#include "m_argv.h" +#include "m_misc.h" +#include "w_wad.h" +#include "lprintf.h" + +#include "doomdef.h" +#include "doomstat.h" +#include "doomtype.h" + +#include "d_main.h" + +/* Define this if you want to use the MIDI music support */ +//#define HAVE_MIXER + +// The number of internal mixing channels, +// the samples calculated for each mixing step, +// the size of the 16bit, 2 hardware channel (stereo) +// mixing buffer, and the samplerate of the raw data. + +#define PIPE_CHECK(fh) if (broken_pipe) { fclose(fh); fh = NULL; broken_pipe = 0; } + +// Variables used by Boom from Allegro +// created here to avoid changes to core Boom files +int snd_card = 1; +int mus_card = 1; +int detect_voices = 0; // God knows + +// Needed for calling the actual sound output. +static int SAMPLECOUNT= 512; +#define NUM_CHANNELS 8 + +#define SAMPLERATE 11025 // Hz + +// The actual lengths of all sound effects. +int lengths[NUMSFX]; + +// The actual output device. +int audio_fd; + + +// The channel step amount... +unsigned int channelstep[NUM_CHANNELS]; +// ... and a 0.16 bit remainder of last step. +unsigned int channelstepremainder[NUM_CHANNELS]; + + +// The channel data pointers, start and end. +unsigned char* channels[NUM_CHANNELS]; +unsigned char* channelsend[NUM_CHANNELS]; + + +// Time/gametic that the channel started playing, +// used to determine oldest, which automatically +// has lowest priority. +// In case number of active sounds exceeds +// available channels. +int channelstart[NUM_CHANNELS]; + +// The sound in channel handles, +// determined on registration, +// might be used to unregister/stop/modify, +// currently unused. +int channelhandles[NUM_CHANNELS]; + +// SFX id of the playing sound effect. +// Used to catch duplicates (like chainsaw). +int channelids[NUM_CHANNELS]; + +// Pitch to stepping lookup, unused. +int steptable[256]; + +// Volume lookups. +int vol_lookup[128*256]; + +// Hardware left and right channel volume lookup. +int* channelleftvol_lookup[NUM_CHANNELS]; +int* channelrightvol_lookup[NUM_CHANNELS]; + + + +// +// This function loads the sound data from the WAD lump, +// for single sound. +// +void* +getsfx +( const char* sfxname, + int* len ) +{ + unsigned char* sfx; + unsigned char* paddedsfx; + int i; + int size; + int paddedsize; + char name[20]; + int sfxlump; + + + // Get the sound data from the WAD, allocate lump + // in zone memory. + sprintf(name, "ds%s", sfxname); + + // Now, there is a severe problem with the + // sound handling, in it is not (yet/anymore) + // gamemode aware. That means, sounds from + // DOOM II will be requested even with DOOM + // shareware. + // The sound list is wired into sounds.c, + // which sets the external variable. + // I do not do runtime patches to that + // variable. Instead, we will use a + // default sound for replacement. + if ( W_CheckNumForName(name) == -1 ) + sfxlump = W_GetNumForName("dspistol"); + else + sfxlump = W_GetNumForName(name); + + size = W_LumpLength( sfxlump ); + + // Debug. + // fprintf( stderr, "." ); + //fprintf( stderr, " -loading %s (lump %d, %d bytes)\n", + // sfxname, sfxlump, size ); + //fflush( stderr ); + + sfx = (unsigned char*)W_CacheLumpNum(sfxlump); + + // Pads the sound effect out to the mixing buffer size. + // The original realloc would interfere with zone memory. + paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT; + + // Allocate from zone memory. + paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 ); + // ddt: (unsigned char *) realloc(sfx, paddedsize+8); + // This should interfere with zone memory handling, + // which does not kick in in the soundserver. + + // Now copy and pad. + memcpy( paddedsfx, sfx, size ); + for (i=size ; i> 16); ///(256*256); + seperation = seperation - 257; + rightvol = + volume - ((volume*seperation*seperation) >> 16); + + // Sanity check, clamp volume. + if (rightvol < 0 || rightvol > 127) + I_Error("rightvol out of bounds"); + + if (leftvol < 0 || leftvol > 127) + I_Error("leftvol out of bounds"); + + // Get the proper lookup table piece + // for this volume level??? + channelleftvol_lookup[slot] = &vol_lookup[leftvol*256]; + channelrightvol_lookup[slot] = &vol_lookup[rightvol*256]; + + // Preserve sound SFX id, + // e.g. for avoiding duplicates of chainsaw. + channelids[slot] = sfxid; + + // You tell me. + return rc; +} + + + + + +// +// SFX API +// Note: this was called by S_Init. +// However, whatever they did in the +// old DPMS based DOS version, this +// were simply dummies in the Linux +// version. +// See soundserver initdata(). +// +void I_SetChannels() +{ + // Init internal lookups (raw data, mixing buffer, channels). + // This function sets up internal lookups used during + // the mixing process. + int i; + int j; + + int* steptablemid = steptable + 128; + + // Okay, reset internal mixing channels to zero. + /*for (i=0; iname); + return W_GetNumForName(namebuf); +} + +// +// Starting a sound means adding it +// to the current list of active sounds +// in the internal channels. +// As the SFX info struct contains +// e.g. a pointer to the raw data, +// it is ignored. +// As our sound handling does not handle +// priority, it is ignored. +// Pitching (that is, increased speed of playback) +// is set, but currently not used by mixing. +// +int +I_StartSound +( int id, + int vol, + int sep, + int pitch, + int priority ) +{ + + // UNUSED + priority = 0; + + // Debug. + //fprintf( stderr, "starting sound %d", id ); + + // Returns a handle (not used). + SDL_LockAudio(); + id = addsfx( id, vol, steptable[pitch], sep ); + SDL_UnlockAudio(); + + // fprintf( stderr, "/handle is %d\n", id ); + + return id; +} + + + +void I_StopSound (int handle) +{ + // You need the handle returned by StartSound. + // Would be looping all channels, + // tracking down the handle, + // an setting the channel to zero. + + // UNUSED. + handle = 0; +} + + +boolean I_SoundIsPlaying(int handle) +{ + // Ouch. + return gametic < handle; +} + + +// +// This function loops all active (internal) sound +// channels, retrieves a given number of samples +// from the raw sound data, modifies it according +// to the current (internal) channel parameters, +// mixes the per channel samples into the given +// mixing buffer, and clamping it to the allowed +// range. +// +// This function currently supports only 16bit. +// +void I_UpdateSound(void *unused, Uint8 *stream, int len) +{ + // Mix current sound data. + // Data, from raw sound, for right and left. + register unsigned int sample; + register int dl; + register int dr; + + // Pointers in audio stream, left, right, end. + signed short* leftout; + signed short* rightout; + signed short* leftend; + // Step in stream, left and right, thus two. + int step; + + // Mixing channel index. + int chan; + +#ifdef HAVE_MIXER +extern void music_mixer(void *udata, Uint8 *stream, int len); + // Mix in the music + music_mixer(NULL, stream, len); +#endif + + // Left and right channel + // are in audio stream, alternating. + leftout = (signed short *)stream; + rightout = ((signed short *)stream)+1; + step = 2; + + // Determine end, for left channel only + // (right channel is implicit). + leftend = leftout + SAMPLECOUNT*step; + + // Mix sounds into the mixing buffer. + // Loop over step*SAMPLECOUNT, + // that is 512 values for two channels. + while (leftout != leftend) + { + // Reset left/right value. + //dl = 0; + //dr = 0; + dl = *leftout; + dr = *rightout; + + // Love thy L2 chache - made this a loop. + // Now more channels could be set at compile time + // as well. Thus loop those channels. + for ( chan = 0; chan < NUM_CHANNELS; chan++ ) + { + // Check channel, if active. + if (channels[ chan ]) + { + // Get the raw data from the channel. + sample = *channels[ chan ]; + // Add left and right part + // for this channel (sound) + // to the current data. + // Adjust volume accordingly. + dl += channelleftvol_lookup[ chan ][sample]; + dr += channelrightvol_lookup[ chan ][sample]; + // Increment index ??? + channelstepremainder[ chan ] += channelstep[ chan ]; + // MSB is next sample??? + channels[ chan ] += channelstepremainder[ chan ] >> 16; + // Limit to LSB??? + channelstepremainder[ chan ] &= 65536-1; + + // Check whether we are done. + if (channels[ chan ] >= channelsend[ chan ]) + channels[ chan ] = 0; + } + } + + // Clamp to range. Left hardware channel. + // Has been char instead of short. + // if (dl > 127) *leftout = 127; + // else if (dl < -128) *leftout = -128; + // else *leftout = dl; + + if (dl > 0x7fff) + *leftout = 0x7fff; + else if (dl < -0x8000) + *leftout = -0x8000; + else + *leftout = dl; + + // Same for right hardware channel. + if (dr > 0x7fff) + *rightout = 0x7fff; + else if (dr < -0x8000) + *rightout = -0x8000; + else + *rightout = dr; + + // Increment current pointers in stream + leftout += step; + rightout += step; + } +} + +void +I_UpdateSoundParams +( int handle, + int vol, + int sep, + int pitch) +{ + // I fail too see that this is used. + // Would be using the handle to identify + // on which channel the sound might be active, + // and resetting the channel parameters. + + // UNUSED. + handle = vol = sep = pitch = 0; +} + + +void I_ShutdownSound(void) +{ + I_ShutdownMusic(); + SDL_CloseAudio(); +} + +static SDL_AudioSpec audio; + +void +I_InitSound() +{ + int i; + + // Secure and configure sound device first. + fprintf( stderr, "I_InitSound: "); + + // Open the audio device + audio.freq = SAMPLERATE; + if ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) { + audio.format = AUDIO_S16MSB; + } else { + audio.format = AUDIO_S16LSB; + } + audio.channels = 2; + audio.samples = SAMPLECOUNT; + audio.callback = I_UpdateSound; + if ( SDL_OpenAudio(&audio, NULL) < 0 ) { + fprintf(stderr, "couldn't open audio with desired format\n"); + return; + } + SAMPLECOUNT = audio.samples; + fprintf(stderr, " configured audio device with %d samples/slice\n", SAMPLECOUNT); + + + // Initialize external data (all sounds) at start, keep static. + fprintf( stderr, "I_InitSound: "); + + for (i=1 ; idata; + lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)]; + } + } + + fprintf( stderr, " pre-cached all sound data\n"); + + if (!nomusicparm) + I_InitMusic(); + + // Finished initialization. + fprintf(stderr, "I_InitSound: sound module ready\n"); + SDL_PauseAudio(0); +} + + + + +// +// MUSIC API. +// + +#ifdef HAVE_MIXER +#include "mixer.h" +#endif +#include "qmus2mid.h" + +/* FIXME: Make this file instance-specific */ +#define MIDI_TMPFILE "/tmp/.lsdlmidi" + +#ifdef HAVE_MIXER +static Mix_Music *music[2] = { NULL, NULL }; +#endif + +void I_ShutdownMusic(void) +{ +#ifdef HAVE_MIXER + /* Should this be exposed in mixer.h? */ + extern void close_music(void); + + close_music(); +#endif +} + +void I_InitMusic(void) +{ +#ifdef HAVE_MIXER + /* Should this be exposed in mixer.h? */ + extern int open_music(SDL_AudioSpec *); + + if ( open_music(&audio) < 0 ) { + fprintf(stderr, "Unable to open music: %s\n", Mix_GetError()); + return; + } +#endif +} + +void I_PlaySong(int handle, int looping) +{ +//printf("Playing song %d (%d loops)\n", handle, looping); +#ifdef HAVE_MIXER + if ( music[handle] ) { + Mix_FadeInMusic(music[handle], looping ? -1 : 0, 500); + } +#endif +} + +extern int mus_pause_opt; // From m_misc.c + +void I_PauseSong (int handle) +{ +#ifdef HAVE_MIXER + switch(mus_pause_opt) { + case 0: +//printf("Stopping song %d (pause)\n", handle); + I_StopSong(handle); + break; + case 1: +//printf("Pausing song %d (pause)\n", handle); + Mix_PauseMusic(); + break; + } +#endif + // Default - let music continue +} + +void I_ResumeSong (int handle) +{ +//printf("Resuming song %d\n", handle); +#ifdef HAVE_MIXER + Mix_ResumeMusic(); +#endif +} + +void I_StopSong(int handle) +{ +//printf("Stopping song %d\n", handle); +#ifdef HAVE_MIXER + Mix_FadeOutMusic(500); +#endif +} + +void I_UnRegisterSong(int handle) +{ +//printf("Unregistering song %d\n", handle); +#ifdef HAVE_MIXER + if ( music[handle] ) { + Mix_FreeMusic(music[handle]); + music[handle] = NULL; + } + unlink(MIDI_TMPFILE); +#endif +} + +int I_RegisterSong(void* data, size_t len) +{ + FILE *midfile; + +//printf("Registering song {%c%c%c}\n", ((unsigned char *)data)[0], +// ((unsigned char *)data)[1], +// ((unsigned char *)data)[2]); + midfile = fopen(MIDI_TMPFILE, "wb"); + if ( midfile == NULL ) { + printf("Couldn't write MIDI to %s\n", MIDI_TMPFILE); + return 0; + } + /* Convert MUS chunk to MIDI? */ + if ( memcmp(data, "MUS", 3) == 0 ) { + qmus2mid(data, len, midfile, 1, 0, 0, 0); + } else { + fwrite(data, len, 1, midfile); + } + fclose(midfile); + +#ifdef HAVE_MIXER + music[0] = Mix_LoadMUS(MIDI_TMPFILE); + if ( music[0] == NULL ) { + printf("Couldn't load MIDI from %s: %s\n", MIDI_TMPFILE, Mix_GetError()); + } +#endif + return (0); +} + +void I_SetMusicVolume(int volume) +{ +//printf("Setting music volume to %d\n", volume); +#ifdef HAVE_MIXER + Mix_VolumeMusic(volume*8); +#endif +} diff -ruN lxdoom-1.4.1.orig/src/l_video_sdl.c lxdoom-1.4.1/src/l_video_sdl.c --- lxdoom-1.4.1.orig/src/l_video_sdl.c Wed Dec 31 16:00:00 1969 +++ lxdoom-1.4.1/src/l_video_sdl.c Sat Dec 25 15:02:02 1999 @@ -0,0 +1,515 @@ +/* Emacs style mode select -*- C++ -*- + *----------------------------------------------------------------------------- + * + * $Id: l_video_x.c,v 1.27 1999/10/12 13:01:11 cphipps Exp $ + * + * SDL display code for LxDoom. Based on the original linuxdoom i_video.c + * Copyright (C) 1993-1996 by id Software + * Copyright (C) 1999 by Colin Phipps + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * DESCRIPTION: + * DOOM graphics stuff for SDL + * + *----------------------------------------------------------------------------- + */ + +static const char +rcsid[] = "$Id: l_video_x.c,v 1.27 1999/10/12 13:01:11 cphipps Exp $"; + +#include +#include + +#include "SDL.h" + +#include "i_system.h" +#include "m_argv.h" +#include "doomstat.h" +#include "doomdef.h" +#include "doomtype.h" +#include "v_video.h" +#include "r_draw.h" +#include "d_main.h" +#include "d_event.h" +#include "l_video_trans.h" +#include "i_joy.h" +#include "i_video.h" +#include "z_zone.h" +#include "s_sound.h" +#include "sounds.h" +#include "w_wad.h" +#include "lprintf.h" + +#ifdef I386 +void (*R_DrawColumn)(void); +void (*R_DrawTLColumn)(void); +#endif + +extern void M_QuitDOOM(int choice); + +int use_vsync = 0; // Included not to break m_misc, but not relevant to SDL +static SDL_Surface *screen; + +// This is the pointer to the buffer to blit +pval * out_buffer = NULL; + +// Common const strings +static const char lcase_lxdoom[] = { "lxdoom" }; +static const char ucase_lxdoom[] = { "LXDOOM" }; + +//////////////////////////////////////////////////////////////////////////// +// Input code +int leds_always_off = 0; // Expected by m_misc, not relevant + +// Mouse handling +extern int usemouse; // config file var +static boolean grabMouse; // internal var + +///////////////////////////////////////////////////////////////////////////////// +// Keyboard handling + +// +// Translates the key currently in key +// + +static int I_TranslateKey(SDL_keysym* key) +{ + int rc = 0; + + switch (key->sym) { + case SDLK_LEFT: rc = KEYD_LEFTARROW; break; + case SDLK_RIGHT: rc = KEYD_RIGHTARROW; break; + case SDLK_DOWN: rc = KEYD_DOWNARROW; break; + case SDLK_UP: rc = KEYD_UPARROW; break; + case SDLK_ESCAPE: rc = KEYD_ESCAPE; break; + case SDLK_RETURN: rc = KEYD_ENTER; break; + case SDLK_TAB: rc = KEYD_TAB; break; + case SDLK_F1: rc = KEYD_F1; break; + case SDLK_F2: rc = KEYD_F2; break; + case SDLK_F3: rc = KEYD_F3; break; + case SDLK_F4: rc = KEYD_F4; break; + case SDLK_F5: rc = KEYD_F5; break; + case SDLK_F6: rc = KEYD_F6; break; + case SDLK_F7: rc = KEYD_F7; break; + case SDLK_F8: rc = KEYD_F8; break; + case SDLK_F9: rc = KEYD_F9; break; + case SDLK_F10: rc = KEYD_F10; break; + case SDLK_F11: rc = KEYD_F11; break; + case SDLK_F12: rc = KEYD_F12; break; + case SDLK_BACKSPACE: + case SDLK_DELETE: rc = KEYD_BACKSPACE; break; + case SDLK_PAUSE: rc = KEYD_PAUSE; break; + case SDLK_EQUALS: rc = KEYD_EQUALS; break; + case SDLK_MINUS: rc = KEYD_MINUS; break; + case SDLK_KP0: rc = KEYD_KEYPAD0; break; + case SDLK_KP1: rc = KEYD_KEYPAD1; break; + case SDLK_KP2: rc = KEYD_KEYPAD2; break; + case SDLK_KP3: rc = KEYD_KEYPAD3; break; + case SDLK_KP4: rc = KEYD_KEYPAD4; break; + case SDLK_KP5: rc = KEYD_KEYPAD0; break; + case SDLK_KP6: rc = KEYD_KEYPAD6; break; + case SDLK_KP7: rc = KEYD_KEYPAD7; break; + case SDLK_KP8: rc = KEYD_KEYPAD8; break; + case SDLK_KP9: rc = KEYD_KEYPAD9; break; + case SDLK_KP_PLUS: rc = KEYD_KEYPADPLUS; break; + case SDLK_KP_MINUS: rc = KEYD_KEYPADMINUS; break; + case SDLK_KP_DIVIDE: rc = KEYD_KEYPADDIVIDE; break; + case SDLK_KP_MULTIPLY: rc = KEYD_KEYPADMULTIPLY; break; + case SDLK_KP_ENTER: rc = KEYD_KEYPADENTER; break; + case SDLK_LSHIFT: + case SDLK_RSHIFT: rc = KEYD_RSHIFT; break; + case SDLK_LCTRL: + case SDLK_RCTRL: rc = KEYD_RCTRL; break; + case SDLK_LALT: + case SDLK_LMETA: + case SDLK_RALT: + case SDLK_RMETA: rc = KEYD_RALT; break; + default: rc = key->sym; break; + } + + return rc; + +} + +// Null keyboard translation to satisfy m_misc.c +int I_DoomCode2ScanCode(int c) +{ + return c; +} + +int I_ScanCode2DoomCode(int c) +{ + return c; +} + +///////////////////////////////////////////////////////////////////////////////// +// Main input code + +static void I_GetEvent(SDL_Event *Event) +{ + event_t event; + + switch (Event->type) { + case SDL_KEYDOWN: + event.type = ev_keydown; + event.data1 = I_TranslateKey(&Event->key.keysym); + D_PostEvent(&event); + break; + + case SDL_KEYUP: + { + event.type = ev_keyup; + event.data1 = I_TranslateKey(&Event->key.keysym); + D_PostEvent(&event); + } + break; + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + if (usemouse) + { Uint8 buttonstate; + buttonstate = SDL_GetMouseState(NULL, NULL); + event.type = ev_mouse; + event.data1 = 0 + | (buttonstate & SDL_BUTTON(1) ? 1 : 0) + | (buttonstate & SDL_BUTTON(2) ? 2 : 0) + | (buttonstate & SDL_BUTTON(3) ? 4 : 0); + event.data2 = event.data3 = 0; + D_PostEvent(&event); + } + break; + + case SDL_MOUSEMOTION: + /* Ignore mouse warp events */ + if (usemouse && + ((Event->motion.x != screen->w/2)||(Event->motion.y != screen->h/2))) + { + /* Warp the mouse back to the center */ + if (grabMouse) { + if ( (Event->motion.x < ((screen->w/2)-(screen->w/4))) || + (Event->motion.x > ((screen->w/2)+(screen->w/4))) || + (Event->motion.y < ((screen->h/2)-(screen->h/4))) || + (Event->motion.y > ((screen->h/2)+(screen->h/4))) ) + SDL_WarpMouse(screen->w/2, screen->h/2); + } + event.type = ev_mouse; + event.data1 = 0 + | (Event->motion.state & SDL_BUTTON(1) ? 1 : 0) + | (Event->motion.state & SDL_BUTTON(2) ? 2 : 0) + | (Event->motion.state & SDL_BUTTON(3) ? 4 : 0); + event.data2 = Event->motion.xrel << 2; + event.data3 = -Event->motion.yrel << 2; + D_PostEvent(&event); + } + break; + + case SDL_QUIT: + S_StartSound(NULL, sfx_swtchn); + M_QuitDOOM(0); + + default: + break; + } +} + + +// +// I_StartTic +// +void I_StartTic (void) +{ + SDL_Event Event; + + while ( SDL_PollEvent(&Event) ) + I_GetEvent(&Event); + + I_PollJoystick(); +} + +// +// I_StartFrame +// +void I_StartFrame (void) +{ +} + +// +// I_InitInputs +// + +static void I_InitInputs(void) +{ + // check if the user wants to grab the mouse (quite unnice) + grabMouse = M_CheckParm("-nomouse") ? false : + usemouse ? true : false; + + I_InitJoystick(); +} +///////////////////////////////////////////////////////////////////////////// + +// I_SkipFrame +// +// Returns true if it thinks we can afford to skip this frame + +static inline boolean I_SkipFrame(void) +{ + static int frameno; + + frameno++; + switch (gamestate) { + case GS_LEVEL: + if (!paused) + return false; + default: + // Skip odd frames + return (frameno & 1) ? true : false; + } +} + +/////////////////////////////////////////////////////////// +// Palette stuff. +// +static void I_UploadNewPalette(int pal) +{ + // This is used to replace the current 256 colour cmap with a new one + // Used by 256 colour PseudoColor modes + + // Array of SDL_Color structs used for setting the 256-colour palette + static SDL_Color* colours; + static int cachedgamma; + static size_t num_pals; + + if ((colours == NULL) || (cachedgamma != usegamma)) { + int lump = W_GetNumForName("PLAYPAL"); + const byte *palette = W_CacheLumpNum(lump); + register const byte *const gtable = gammatable[cachedgamma = usegamma]; + register int i; + + num_pals = W_LumpLength(lump) / (3*256); + num_pals *= 256; + + if (!colours) { + // First call - allocate and prepare colour array + colours = malloc(sizeof(*colours)*num_pals); + } + + // set the colormap entries + for (i=0 ; i= num_pals) + I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)", + pal, num_pals); +#endif + + // store the colors to the current display + SDL_SetColors(SDL_GetVideoSurface(), colours+256*pal, 0, 256); +} + +////////////////////////////////////////////////////////////////////////////// +// Graphics API + +void I_ShutdownGraphics(void) +{ + fprintf(stderr, "I_ShutdownGraphics : "); + + // Free internal structures + if (pixelvals != NULL) free(pixelvals); + I_EndImageTranslation(); + + SDL_Quit(); +} + +// +// I_UpdateNoBlit +// +void I_UpdateNoBlit (void) +{ +} + +// +// I_FinishUpdate +// +void I_FinishUpdate (void) +{ + if (I_SkipFrame()) return; + +#ifdef MONITOR_VISIBILITY + if (!(SDL_GetAppState()&SDL_APPACTIVE)) { + return; + } +#endif + + // scales the screen size before blitting it + if (expand_buffer) + (*I_ExpandImage)(out_buffer, screens[0]); + + // Update the display buffer (flipping video pages if supported) + SDL_Flip(screen); +} + +// +// I_ReadScreen +// +void I_ReadScreen (byte* scr) +{ + memcpy(scr, screens[0], SCREENWIDTH*SCREENHEIGHT); +} + +// +// I_SetPalette +// +void I_SetPalette (int pal) +{ + if (true_color) { + int lump = W_GetNumForName("PLAYPAL"); + const byte *palette = W_CacheLumpNum(lump); + I_SetPaletteTranslation(palette + (3*256)*pal); + W_UnlockLumpNum(lump); + } else + I_UploadNewPalette(pal); +} + +// I_PreInitGraphics + +void I_PreInitGraphics(void) +{ +} + +// CPhipps - +// I_SetRes +// Sets the screen resolution, possibly using the supplied guide + +void I_SetRes(unsigned int width, unsigned int height) +{ +#ifdef HIGHRES + SCREENWIDTH = +#endif + (width+3) & ~3; + +#ifdef HIGHRES + SCREENHEIGHT = +#endif + (height+3) & ~3; + +#ifdef I386 + if (SCREENWIDTH == 320) { + R_DrawColumn = R_DrawColumn_Normal; + R_DrawTLColumn = R_DrawTLColumn_Normal; + } else { + R_DrawColumn = R_DrawColumn_HighRes; + R_DrawTLColumn = R_DrawTLColumn_HighRes; + } +#endif + printf("I_SetRes: Using resolution %dx%d\n", SCREENWIDTH, SCREENHEIGHT); +} + +void I_InitGraphics(void) +{ + const int depth_list[] = { 0, 8 }; + int w, h; + int n; + Uint32 init_flags; + + { + static int firsttime=1; + + if (!firsttime) { + return; + } + firsttime = 0; + } + + { // Check for screen enlargement + char str[3] = { '-', 0, 0 }; + + for (n=1; n<4; n++) { + str[1] = n + '0'; + if (M_CheckParm(str)) multiply = n; + } + } + + w = SCREENWIDTH * multiply; + h = SCREENHEIGHT * multiply; + + // Initialize SDL with this graphics mode + if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { + I_Error("Could not initialize SDL [%s]", SDL_GetError()); + } + + init_flags = SDL_SWSURFACE|SDL_HWPALETTE; + if ( M_CheckParm("-fullscreen") ) { + init_flags |= SDL_FULLSCREEN; + } + for ( n=0; n<(sizeof(depth_list)/sizeof(depth_list[0])); ++n ) { + screen = SDL_SetVideoMode(w, h, depth_list[n], init_flags); + if ( screen ) { + dest_bpp = screen->format->BitsPerPixel; + if (I_QueryImageTranslation()) + break; + else + screen = NULL; + } + } + if ( screen == NULL ) { + I_Error("Couldn't set %dx%d video mode [%s]", w, h, SDL_GetError()); + } + SDL_WM_SetCaption(lcase_lxdoom, ucase_lxdoom); + + I_InitImageTranslation(); + if (true_color) { + // Set up colour shifts + I_SetColourShift(screen->format->Rmask, &redshift); + I_SetColourShift(screen->format->Gmask, &greenshift); + I_SetColourShift(screen->format->Bmask, &blueshift); + } + + lprintf(LO_INFO,"I_InitGraphics:"); + lprintf(LO_INFO, " SDL %d bpp %s, scale x%d\n", dest_bpp, + screen->format->palette ? "PseudoColor" : "TrueColor", multiply); + + // Get the info needed to render to the display + out_buffer = (pval *)screen->pixels; + if (!expand_buffer) { + // Render directly into SDL display memory + Z_Free(screens[0]); + screens[0] = (unsigned char *) (screen->pixels); + } + + atexit(I_ShutdownGraphics); + + // Initialize the input system + I_InitInputs(); + + // Hide pointer while over this window + SDL_ShowCursor(0); +} + +// +// $Log: l_video_x.c,v $ +// Revision 1.1 1998/10/27 07:50:11 cphipps +// Initial revision +// diff -ruN lxdoom-1.4.1.orig/src/qmus2mid.c lxdoom-1.4.1/src/qmus2mid.c --- lxdoom-1.4.1.orig/src/qmus2mid.c Wed Dec 31 16:00:00 1969 +++ lxdoom-1.4.1/src/qmus2mid.c Sun Dec 26 02:01:18 1999 @@ -0,0 +1,522 @@ +/* + Quick MUS to Midi converter. + (C) 1995,96 Sebastien Bacquet ( bacquet@iie.cnam.fr ) + + Ported to unix by Hans Peter Verne ( hpv@kjemi.uio.no ) + + This is free software, distributed under the terms of the + GNU General Public License. For details see the file COPYING. + + Use gcc to compile, if possible. Please look in "qmus2mid.h" + for system dependencies, in particular the int2 and int4 typedef's. + + To compile for MS-DOS, #define MSDOG or use -DMSDOG parameter + + Otherwise, vanilla unix is assumed, but it still compiles under dos. + + For the time being, this only works for little-endian machines, + such as i86, dec-mips, alpha; but not rs6000, sparc.... + + Ripped for the lsdldoom port by Sam Lantinga - Thanks! :) +*/ + +#include +#include +#include +#include +#include +#include +#include "qmus2mid.h" + +int4 TRACKBUFFERSIZE = 65536L ; /* 64 Ko */ + +typedef struct { + unsigned char *buf; + int len; +} buflen_t; + +/* Read a 16-bit little-endian value */ +int read1(buflen_t *buflen) +{ + int value; + + if ( buflen->len < 1 ) { + return(-1); + } + value = buflen->buf[0]; + buflen->buf++; + buflen->len--; + return(value); +} +int read2(int2 *intp, buflen_t *buflen) +{ + int i; + + if ( buflen->len < 2 ) { + return(0); + } + for ( i=0; i<2; ++i ) { + *intp <<= 8; + *intp |= buflen->buf[1-i]; + } + buflen->buf += 2; + buflen->len -= 2; + return(1); +} +/* Read a 32-bit little-endian value */ +int read4(int4 *intp, buflen_t *buflen) +{ + int i; + + if ( buflen->len < 4 ) { + return(0); + } + for ( i=0; i<4; ++i ) { + *intp <<= 8; + *intp |= buflen->buf[3-i]; + } + buflen->buf += 4; + buflen->len -= 4; + return(1); +} + +size_t fwrite2(const int2 *ptr, size_t size, FILE *file) +{ + int4 rev = 0; + int i; + + for( i = 0 ; i < size ; i++ ) + rev = (rev << 8) + (((*ptr) >> (i*8)) & 0xFF) ; + + return fwrite( &rev, size, 1, file ) ; +} + + +void FreeTracks( struct Track track[] ) +{ + int i ; + + for( i = 0 ; i < 16 ; i++ ) + if( track[i].data ) + free( track[i].data ) ; +} + + +void TWriteByte( unsigned char MIDItrack, char byte, struct Track track[] ) +{ + int4 pos ; + + pos = track[MIDItrack].current ; + if( pos < TRACKBUFFERSIZE ) + track[MIDItrack].data[pos] = byte ; + else + { + printf("ERROR : Track buffer full.\n" + "Increase the track buffer size (option -size).\n" ) ; + FreeTracks( track ) ; + exit( EXIT_FAILURE ) ; + } + track[MIDItrack].current++ ; +} + + +void TWriteVarLen( int tracknum, register int4 value, + struct Track track[] ) +{ + register int4 buffer ; + + buffer = value & 0x7f ; + while( (value >>= 7) ) + { + buffer <<= 8 ; + buffer |= 0x80 ; + buffer += (value & 0x7f) ; + } + while( 1 ) + { + TWriteByte( tracknum, buffer, track ) ; + if( buffer & 0x80 ) + buffer >>= 8 ; + else + break; + } +} + + +int ReadMUSheader( MUSheader *MUSh, buflen_t *buflen ) +{ + if ( buflen->len < 4 ) { + return NOTMUSFILE ; + } + memcpy(MUSh->ID, buflen->buf, 4); + buflen->buf += 4; + buflen->len -= 4; + if( strncmp( MUSh->ID, MUSMAGIC, 4 ) ) + return NOTMUSFILE ; + if( read2( &(MUSh->ScoreLength), buflen ) != 1 ) return COMUSFILE ; + if( read2( &(MUSh->ScoreStart), buflen ) != 1 ) return COMUSFILE ; + if( read2( &(MUSh->channels), buflen ) != 1 ) return COMUSFILE ; + if( read2( &(MUSh->SecChannels), buflen ) != 1 ) return COMUSFILE ; + if( read2( &(MUSh->InstrCnt), buflen ) != 1 ) return COMUSFILE ; + if( read2( &(MUSh->dummy), buflen ) != 1 ) return COMUSFILE ; +#if 0 + MUSh->instruments = (int2 *) calloc(MUSh->InstrCnt, sizeof(int2)) ; + if( fread( MUSh->instruments, 2, MUSh->InstrCnt, file ) != MUSh->InstrCnt ) + { + free( MUSh->instruments ) ; + return COMUSFILE ; + } + free( MUSh->instruments ) ; /* suppress this line if you want to display + instruments later */ +#else + buflen->buf += 2*MUSh->InstrCnt; + buflen->len += 2*MUSh->InstrCnt; +#endif + return 0 ; +} + + +int WriteMIDheader( int2 ntrks, int2 division, FILE *file ) +{ + fwrite( MIDIMAGIC , 10, 1, file ) ; + fwrite2( &ntrks, 2, file) ; + fwrite2( &division, 2, file ) ; + return 0 ; +} + + /* maybe for ms-dog too ? */ /* Yes, why not ?... */ +#define last(e) ((unsigned char)(e & 0x80)) +#define event_type(e) ((unsigned char)((e & 0x7F) >> 4)) +#define channel(e) ((unsigned char)(e & 0x0F)) + +void TWriteString( char tracknum, const char *string, int length, + struct Track track[] ) +{ + register int i ; + + for( i = 0 ; i < length ; i++ ) + TWriteByte( tracknum, string[i], track ) ; +} + + +void WriteTrack( int tracknum, FILE *file, struct Track track[] ) +{ + int2 size ; + size_t quot, rem ; + + /* Do we risk overflow here ? */ + size = track[tracknum].current+4 ; + fwrite( "MTrk", 4, 1, file ) ; + if( !tracknum ) size += 33 ; + + fwrite2( &size, 4, file ) ; + if( !tracknum) + fwrite( TRACKMAGIC1 "Quick MUS->MID ! by S.Bacquet", 33, 1, file ) ; + quot = (size_t) (track[tracknum].current / 4096) ; + rem = (size_t) (track[tracknum].current - quot*4096) ; + fwrite( track[tracknum].data, 4096, quot, file ) ; + fwrite( ((const unsigned char *) track[tracknum].data)+4096*quot, rem, + 1, file ) ; + fwrite( TRACKMAGIC2, 4, 1, file ) ; +} + + +void WriteFirstTrack( FILE *file ) +{ + int2 size ; + + size = 43 ; + fwrite( "MTrk", 4, 1, file ) ; + fwrite2( &size, 4, file ) ; + fwrite( TRACKMAGIC3 , 4, 1, file ) ; + fwrite( "QMUS2MID (C) S.Bacquet", 22, 1, file ) ; + fwrite( TRACKMAGIC4, 6, 1, file ) ; + fwrite( TRACKMAGIC5, 7, 1, file ) ; + fwrite( TRACKMAGIC6, 4, 1, file ) ; +} + +int4 ReadTime( buflen_t *buflen ) +{ + register int4 time = 0 ; + int byte ; + + do + { + byte = read1( buflen ) ; + if( byte != EOF ) time = (time << 7) + (byte & 0x7F) ; + } while( (byte != EOF) && (byte & 0x80) ) ; + + return time ; +} + +char FirstChannelAvailable( signed char MUS2MIDchannel[] ) +{ + int i ; + signed char old15 = MUS2MIDchannel[15], max = -1 ; + + MUS2MIDchannel[15] = -1 ; + for( i = 0 ; i < 16 ; i++ ) + if( MUS2MIDchannel[i] > max ) max = MUS2MIDchannel[i] ; + MUS2MIDchannel[15] = old15 ; + + return (max == 8 ? 10 : max+1) ; +} + + +int qmus2mid( void *mus, size_t len, FILE *file_mid, + int nodisplay, int2 division, int BufferSize, int nocomp ) +{ + struct Track track[16] ; + int2 TrackCnt = 0 ; + unsigned char et, MUSchannel, MIDIchannel, MIDItrack, NewEvent ; + int i, event, data, r ; + buflen_t buflen; + static MUSheader MUSh ; + int4 DeltaTime, TotalTime = 0, time, min, n = 0 ; + unsigned char MUS2MIDcontrol[15] = { + 0, /* Program change - not a MIDI control change */ + 0x00, /* Bank select */ + 0x01, /* Modulation pot */ + 0x07, /* Volume */ + 0x0A, /* Pan pot */ + 0x0B, /* Expression pot */ + 0x5B, /* Reverb depth */ + 0x5D, /* Chorus depth */ + 0x40, /* Sustain pedal */ + 0x43, /* Soft pedal */ + 0x78, /* All sounds off */ + 0x7B, /* All notes off */ + 0x7E, /* Mono */ + 0x7F, /* Poly */ + 0x79 /* Reset all controllers */ + }, MIDIchan2track[16] ; + signed char MUS2MIDchannel[16] ; +#ifdef MSDOG + char drive[MAXDRIVE], dir[MAXDIR], name[MAXFILE], ext[MAXEXT] ; +#endif + char ouch = 0, sec ; + + /* Set up the MUS data source */ + buflen.buf = (unsigned char *)mus; + buflen.len = len; + + r = ReadMUSheader( &MUSh, &buflen ) ; + if( r ) + { + return r ; + } + buflen.buf = (unsigned char *)mus + MUSh.ScoreStart; + buflen.len = len - MUSh.ScoreStart; + if ( buflen.len <= 0 ) + { + return MUSFILECOR ; + } + if( !nodisplay ) + printf( "MUS chunk (%lu bytes) contains %d melodic channel%s.\n", + (unsigned long) len, MUSh.channels, + MUSh.channels >= 2 ? "s" : "" ); + if( MUSh.channels > 15 ) /* <=> MUSchannels+drums > 16 */ + { + return TOOMCHAN ; + } + + for( i = 0 ; i < 16 ; i++ ) + { + MUS2MIDchannel[i] = -1 ; + track[i].current = 0 ; + track[i].vel = 64 ; + track[i].DeltaTime = 0 ; + track[i].LastEvent = 0 ; + track[i].data = NULL ; + } + if( BufferSize ) + { + TRACKBUFFERSIZE = ((int4) BufferSize) << 10 ; + if( !nodisplay ) + printf( "Track buffer size set to %d KB.\n", BufferSize ) ; + } + + if( !nodisplay ) + { + printf( "Converting..." ) ; + fflush( stdout ) ; + } + event = read1( &buflen ) ; + et = event_type( event ) ; + MUSchannel = channel( event ) ; + while( (et != 6) && (buflen.len > 0) ) + { + if( MUS2MIDchannel[MUSchannel] == -1 ) + { + MIDIchannel = MUS2MIDchannel[MUSchannel ] = + (MUSchannel == 15 ? 9 : FirstChannelAvailable( MUS2MIDchannel)) ; + MIDItrack = MIDIchan2track[MIDIchannel] = TrackCnt++ ; + if( !(track[MIDItrack].data = (char *) malloc( TRACKBUFFERSIZE )) ) + { + FreeTracks( track ) ; + return MEMALLOC ; + } + } + else + { + MIDIchannel = MUS2MIDchannel[MUSchannel] ; + MIDItrack = MIDIchan2track [MIDIchannel] ; + } + TWriteVarLen( MIDItrack, track[MIDItrack].DeltaTime, track ) ; + track[MIDItrack].DeltaTime = 0 ; + switch( et ) + { + case 0 : /* release note */ + NewEvent = 0x90 | MIDIchannel ; + if( (NewEvent != track[MIDItrack].LastEvent) || nocomp ) + { + TWriteByte( MIDItrack, NewEvent, track ) ; + track[MIDItrack].LastEvent = NewEvent ; + } + else + n++ ; + data = read1( &buflen ) ; + TWriteByte( MIDItrack, data, track ) ; + TWriteByte( MIDItrack, 0, track ) ; + break ; + case 1 : + NewEvent = 0x90 | MIDIchannel ; + if( (NewEvent != track[MIDItrack].LastEvent) || nocomp ) + { + TWriteByte( MIDItrack, NewEvent, track ) ; + track[MIDItrack].LastEvent = NewEvent ; + } + else + n++ ; + data = read1( &buflen ) ; + TWriteByte( MIDItrack, data & 0x7F, track ) ; + if( data & 0x80 ) + track[MIDItrack].vel = read1( &buflen ) ; + TWriteByte( MIDItrack, track[MIDItrack].vel, track ) ; + break ; + case 2 : + NewEvent = 0xE0 | MIDIchannel ; + if( (NewEvent != track[MIDItrack].LastEvent) || nocomp ) + { + TWriteByte( MIDItrack, NewEvent, track ) ; + track[MIDItrack].LastEvent = NewEvent ; + } + else + n++ ; + data = read1( &buflen ) ; + TWriteByte( MIDItrack, (data & 1) << 6, track ) ; + TWriteByte( MIDItrack, data >> 1, track ) ; + break ; + case 3 : + NewEvent = 0xB0 | MIDIchannel ; + if( (NewEvent != track[MIDItrack].LastEvent) || nocomp ) + { + TWriteByte( MIDItrack, NewEvent, track ) ; + track[MIDItrack].LastEvent = NewEvent ; + } + else + n++ ; + data = read1( &buflen ) ; + TWriteByte( MIDItrack, MUS2MIDcontrol[data], track ) ; + if( data == 12 ) + TWriteByte( MIDItrack, MUSh.channels+1, track ) ; + else + TWriteByte( MIDItrack, 0, track ) ; + break ; + case 4 : + data = read1( &buflen ) ; + if( data ) + { + NewEvent = 0xB0 | MIDIchannel ; + if( (NewEvent != track[MIDItrack].LastEvent) || nocomp ) + { + TWriteByte( MIDItrack, NewEvent, track ) ; + track[MIDItrack].LastEvent = NewEvent ; + } + else + n++ ; + TWriteByte( MIDItrack, MUS2MIDcontrol[data], track ) ; + } + else + { + NewEvent = 0xC0 | MIDIchannel ; + if( (NewEvent != track[MIDItrack].LastEvent) || nocomp ) + { + TWriteByte( MIDItrack, NewEvent, track ) ; + track[MIDItrack].LastEvent = NewEvent ; + } + else + n++ ; + } + data = read1( &buflen ) ; + TWriteByte( MIDItrack, data, track ) ; + break ; + case 5 : + case 7 : + FreeTracks( track ) ; + return MUSFILECOR ; + default : break ; + } + if( last( event ) ) + { + DeltaTime = ReadTime( &buflen ) ; + TotalTime += DeltaTime ; + for( i = 0 ; i < (int) TrackCnt ; i++ ) + track[i].DeltaTime += DeltaTime ; + } + event = read1( &buflen ) ; + if( event != EOF ) + { + et = event_type( event ) ; + MUSchannel = channel( event ) ; + } + else + ouch = 1 ; + } + if( !nodisplay ) printf( "done !\n" ) ; + if( ouch ) + printf( "WARNING : There are bytes missing at the end of MUS.\n " + "The end of the MIDI file might not fit the original one.\n") ; + if( !division ) + division = 89 ; + else + if( !nodisplay ) printf( "Ticks per quarter note set to %d.\n", division ) ; + if( !nodisplay ) + { + if( division != 89 ) + { + time = TotalTime / 140 ; + min = time / 60 ; + sec = (char) (time - min*60) ; + printf( "Playing time of the MUS file : %u'%.2u''.\n", min, sec ) ; + } + time = (TotalTime * 89) / (140 * division) ; + min = time / 60 ; + sec = (char) (time - min*60) ; + if( division != 89 ) + printf( " MID file" ) ; + else + printf( "Playing time" ) ; + printf( " : %u'%.2u''.\n", min, sec ) ; + } + if( !nodisplay ) + { + printf( "Writing..." ) ; + fflush( stdout ) ; + } + WriteMIDheader( TrackCnt+1, division, file_mid ) ; + WriteFirstTrack( file_mid ) ; + for( i = 0 ; i < (int) TrackCnt ; i++ ) + WriteTrack( i, file_mid, track ) ; + if( !nodisplay ) + printf( "done !\n" ) ; + if( !nodisplay && !nocomp ) + printf( "Compression : %u%%.\n", + (100 * n) / (n+ (int4) ftell( file_mid )) ) ; + + FreeTracks( track ) ; + + return 0 ; +} + + diff -ruN lxdoom-1.4.1.orig/src/qmus2mid.h lxdoom-1.4.1/src/qmus2mid.h --- lxdoom-1.4.1.orig/src/qmus2mid.h Wed Dec 31 16:00:00 1969 +++ lxdoom-1.4.1/src/qmus2mid.h Sun Dec 26 01:56:21 1999 @@ -0,0 +1,58 @@ +#if !defined( QMUS2MID_H ) +#define QMUS2MID_H + +typedef unsigned short int2; /* a two-byte int, use short.*/ +typedef unsigned int int4; /* a four-byte int, use int unless int is + 16 bits, then use long. Don't use long + on an alpha. */ + +#define NOTMUSFILE 1 /* Not a MUS file */ +#define COMUSFILE 2 /* Can't open MUS file */ +#define COTMPFILE 3 /* Can't open TMP file */ +#define CWMIDFILE 4 /* Can't write MID file */ +#define MUSFILECOR 5 /* MUS file corrupted */ +#define TOOMCHAN 6 /* Too many channels */ +#define MEMALLOC 7 /* Memory allocation error */ + +/* some (old) compilers mistake the "MUS\x1A" construct (interpreting + it as "MUSx1A") */ + +#define MUSMAGIC "MUS\032" /* this seems to work */ +#define MIDIMAGIC "MThd\000\000\000\006\000\001" +#define TRACKMAGIC1 "\000\377\003\035" +#define TRACKMAGIC2 "\000\377\057\000" +#define TRACKMAGIC3 "\000\377\002\026" +#define TRACKMAGIC4 "\000\377\131\002\000\000" +#define TRACKMAGIC5 "\000\377\121\003\011\243\032" +#define TRACKMAGIC6 "\000\377\057\000" + + +typedef struct +{ + char ID[4]; /* identifier "MUS" 0x1A */ + int2 ScoreLength; + int2 ScoreStart; + int2 channels; /* count of primary channels */ + int2 SecChannels; /* count of secondary channels (?) */ + int2 InstrCnt; + int2 dummy; + /* variable-length part starts here */ + int2 *instruments; +} MUSheader; + +struct Track +{ + unsigned long current; + char vel; + long DeltaTime; + unsigned char LastEvent; + char *data; /* Primary data */ +}; + + +int qmus2mid( void *mus, size_t len, FILE *file_mid, + int nodisplay, int2 division, int BufferSize, int nocomp ); + +#endif + +