diff --git a/WinQuake/Makefile b/WinQuake/Makefile index 33ea49c..ac0ac70 100644 --- a/WinQuake/Makefile +++ b/WinQuake/Makefile @@ -39,7 +39,7 @@ CC=gcc -m32 BASE_CFLAGS=-Dstricmp=strcasecmp RELEASE_CFLAGS=$(BASE_CFLAGS) DEBUG_CFLAGS=$(BASE_CFLAGS) -g -LDFLAGS=-lm -ldl +LDFLAGS=-lm -ldl /usr/local/lib/libdumb.a XLDFLAGS=-L/usr/X11R6/lib -lX11 -lXext -lXxf86dga XCFLAGS=-DX11 @@ -143,7 +143,8 @@ X11_OBJS = \ $(BUILDDIR)/obj/view.o \ $(BUILDDIR)/obj/wad.o \ $(BUILDDIR)/obj/world.o \ - $(BUILDDIR)/obj/cd_linux.o \ + $(BUILDDIR)/obj/tracker_linux.o \ + $(BUILDDIR)/obj/cd_null.o \ $(BUILDDIR)/obj/sys_linux.o \ $(BUILDDIR)/obj/vid_x.o \ $(BUILDDIR)/obj/snd_dma.o \ @@ -376,7 +377,10 @@ $(BUILDDIR)/obj/wad.o : $(MOUNT_DIR)/wad.c $(BUILDDIR)/obj/world.o : $(MOUNT_DIR)/world.c $(DO_X11_CC) -$(BUILDDIR)/obj/cd_linux.o : $(MOUNT_DIR)/cd_linux.c +$(BUILDDIR)/obj/tracker_linux.o : $(MOUNT_DIR)/tracker_linux.c + $(DO_X11_CC) + +$(BUILDDIR)/obj/cd_null.o : $(MOUNT_DIR)/cd_null.c $(DO_X11_CC) $(BUILDDIR)/obj/sys_linux.o :$(MOUNT_DIR)/sys_linux.c diff --git a/WinQuake/amidi.c b/WinQuake/amidi.c deleted file mode 100644 index d64108c..0000000 --- a/WinQuake/amidi.c +++ /dev/null @@ -1,5 +0,0 @@ -// stupid workaround file for playing back midis. - - - -// BO diff --git a/WinQuake/block8.h b/WinQuake/block8.h index 10df9d3..bb88a68 100644 --- a/WinQuake/block8.h +++ b/WinQuake/block8.h @@ -140,4 +140,3 @@ LBPatch14: LBPatch15: movb %cl,1(%edi) addl $0x2,%edi - diff --git a/WinQuake/bspfile.h b/WinQuake/bspfile.h index b4852a4..dd0edc1 100644 --- a/WinQuake/bspfile.h +++ b/WinQuake/bspfile.h @@ -32,7 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_MAP_PLANES 32767 #define MAX_MAP_NODES 32767 // because negative shorts are contents -#define MAX_MAP_CLIPNODES 65535 // +#define MAX_MAP_CLIPNODES 65535 #define MAX_MAP_LEAFS 32768 #define MAX_MAP_VERTS 65535 #define MAX_MAP_FACES 65535 @@ -58,7 +58,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_MAP_PLANES 32767 #define MAX_MAP_NODES 32767 // because negative shorts are contents -#define MAX_MAP_CLIPNODES 32767 // +#define MAX_MAP_CLIPNODES 32767 #define MAX_MAP_LEAFS 8192 #define MAX_MAP_VERTS 65535 #define MAX_MAP_FACES 32767 @@ -165,8 +165,6 @@ typedef struct int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate } dplane_t; - - #define CONTENTS_EMPTY -1 #define CONTENTS_SOLID -2 #define CONTENTS_WATER -3 @@ -176,20 +174,19 @@ typedef struct #define CONTENTS_ORIGIN -7 // removed at csg time #define CONTENTS_CLIP -8 // changed to contents_solid -#define CONTENTS_CURRENT_0 -9 -#define CONTENTS_CURRENT_90 -10 +#define CONTENTS_CURRENT_0 -9 +#define CONTENTS_CURRENT_90 -10 #define CONTENTS_CURRENT_180 -11 #define CONTENTS_CURRENT_270 -12 -#define CONTENTS_CURRENT_UP -13 +#define CONTENTS_CURRENT_UP -13 #define CONTENTS_CURRENT_DOWN -14 - // !!! if this is changed, it must be changed in asm_i386.h too !!! typedef struct { - int planenum; + int planenum; short children[2]; // negative numbers are -(leafs+1), not nodes - short mins[3]; // for sphere culling + short mins[3]; // for sphere culling short maxs[3]; unsigned short firstface; unsigned short numfaces; // counting both sides @@ -197,18 +194,18 @@ typedef struct typedef struct { - int planenum; + int planenum; short children[2]; // negative numbers are contents } dclipnode_t; typedef struct texinfo_s { - float vecs[2][4]; // [s/t][xyz offset] - int miptex; - int flags; + float vecs[2][4]; // [s/t][xyz offset] + int miptex; + int flags; } texinfo_t; -#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision +#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision // note that edge 0 is never used, because negative edge nums are used for // counterclockwise use of the edge in a face @@ -232,21 +229,19 @@ typedef struct int lightofs; // start of [numstyles*surfsize] samples } dface_t; - - #define AMBIENT_WATER 0 -#define AMBIENT_SKY 1 +#define AMBIENT_SKY 1 #define AMBIENT_SLIME 2 #define AMBIENT_LAVA 3 -#define NUM_AMBIENTS 4 // automatic ambient sounds +#define NUM_AMBIENTS 4 // automatic ambient sounds // leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas // all other leafs need visibility info typedef struct { int contents; - int visofs; // -1 = no visibility info + int visofs; // -1 = no visibility info short mins[3]; // for frustum culling short maxs[3]; @@ -265,7 +260,6 @@ typedef struct #define ANGLE_UP -1 #define ANGLE_DOWN -2 - // the utilities get to be lazy and just use large static arrays extern int nummodels; diff --git a/WinQuake/cd_linux.c b/WinQuake/cd_linux.c deleted file mode 100644 index 72b2594..0000000 --- a/WinQuake/cd_linux.c +++ /dev/null @@ -1,416 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -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. - -*/ -// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All -// rights reserved. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "quakedef.h" - -static qboolean cdValid = false; -static qboolean playing = false; -static qboolean wasPlaying = false; -static qboolean initialized = false; -static qboolean enabled = true; -static qboolean playLooping = false; -static float cdvolume; -static byte remap[100]; -static byte playTrack; -static byte maxTrack; - -static int cdfile = -1; -static char cd_dev[64] = "/dev/cdrom"; - -static void CDAudio_Eject(void) -{ - if (cdfile == -1 || !enabled) - return; // no cd init'd - - if ( ioctl(cdfile, CDROMEJECT) == -1 ) - Con_DPrintf("ioctl cdromeject failed\n"); -} - - -static void CDAudio_CloseDoor(void) -{ - if (cdfile == -1 || !enabled) - return; // no cd init'd - - if ( ioctl(cdfile, CDROMCLOSETRAY) == -1 ) - Con_DPrintf("ioctl cdromclosetray failed\n"); -} - -static int CDAudio_GetAudioDiskInfo(void) -{ - struct cdrom_tochdr tochdr; - - cdValid = false; - - if ( ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1 ) - { - Con_DPrintf("ioctl cdromreadtochdr failed\n"); - return -1; - } - - if (tochdr.cdth_trk0 < 1) - { - Con_DPrintf("CDAudio: no music tracks\n"); - return -1; - } - - cdValid = true; - maxTrack = tochdr.cdth_trk1; - - return 0; -} - - -void CDAudio_Play(byte track, qboolean looping) -{ - struct cdrom_tocentry entry; - struct cdrom_ti ti; - - if (cdfile == -1 || !enabled) - return; - - if (!cdValid) - { - CDAudio_GetAudioDiskInfo(); - if (!cdValid) - return; - } - - track = remap[track]; - - if (track < 1 || track > maxTrack) - { - Con_DPrintf("CDAudio: Bad track number %u.\n", track); - return; - } - - // don't try to play a non-audio track - entry.cdte_track = track; - entry.cdte_format = CDROM_MSF; - if ( ioctl(cdfile, CDROMREADTOCENTRY, &entry) == -1 ) - { - Con_DPrintf("ioctl cdromreadtocentry failed\n"); - return; - } - if (entry.cdte_ctrl == CDROM_DATA_TRACK) - { - Con_Printf("CDAudio: track %i is not audio\n", track); - return; - } - - if (playing) - { - if (playTrack == track) - return; - CDAudio_Stop(); - } - - ti.cdti_trk0 = track; - ti.cdti_trk1 = track; - ti.cdti_ind0 = 1; - ti.cdti_ind1 = 99; - - if ( ioctl(cdfile, CDROMPLAYTRKIND, &ti) == -1 ) - { - Con_DPrintf("ioctl cdromplaytrkind failed\n"); - return; - } - - if ( ioctl(cdfile, CDROMRESUME) == -1 ) - Con_DPrintf("ioctl cdromresume failed\n"); - - playLooping = looping; - playTrack = track; - playing = true; - - if (cdvolume == 0.0) - CDAudio_Pause (); -} - - -void CDAudio_Stop(void) -{ - if (cdfile == -1 || !enabled) - return; - - if (!playing) - return; - - if ( ioctl(cdfile, CDROMSTOP) == -1 ) - Con_DPrintf("ioctl cdromstop failed (%d)\n", errno); - - wasPlaying = false; - playing = false; -} - -void CDAudio_Pause(void) -{ - if (cdfile == -1 || !enabled) - return; - - if (!playing) - return; - - if ( ioctl(cdfile, CDROMPAUSE) == -1 ) - Con_DPrintf("ioctl cdrompause failed\n"); - - wasPlaying = playing; - playing = false; -} - - -void CDAudio_Resume(void) -{ - if (cdfile == -1 || !enabled) - return; - - if (!cdValid) - return; - - if (!wasPlaying) - return; - - if ( ioctl(cdfile, CDROMRESUME) == -1 ) - Con_DPrintf("ioctl cdromresume failed\n"); - playing = true; -} - -static void CD_f (void) -{ - char *command; - int ret; - int n; - - if (Cmd_Argc() < 2) - return; - - command = Cmd_Argv (1); - - if (Q_strcasecmp(command, "on") == 0) - { - enabled = true; - return; - } - - if (Q_strcasecmp(command, "off") == 0) - { - if (playing) - CDAudio_Stop(); - enabled = false; - return; - } - - if (Q_strcasecmp(command, "reset") == 0) - { - enabled = true; - if (playing) - CDAudio_Stop(); - for (n = 0; n < 100; n++) - remap[n] = n; - CDAudio_GetAudioDiskInfo(); - return; - } - - if (Q_strcasecmp(command, "remap") == 0) - { - ret = Cmd_Argc() - 2; - if (ret <= 0) - { - for (n = 1; n < 100; n++) - if (remap[n] != n) - Con_Printf(" %u -> %u\n", n, remap[n]); - return; - } - for (n = 1; n <= ret; n++) - remap[n] = Q_atoi(Cmd_Argv (n+1)); - return; - } - - if (Q_strcasecmp(command, "close") == 0) - { - CDAudio_CloseDoor(); - return; - } - - if (!cdValid) - { - CDAudio_GetAudioDiskInfo(); - if (!cdValid) - { - Con_Printf("No CD in player.\n"); - return; - } - } - - if (Q_strcasecmp(command, "play") == 0) - { - CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false); - return; - } - - if (Q_strcasecmp(command, "loop") == 0) - { - CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true); - return; - } - - if (Q_strcasecmp(command, "stop") == 0) - { - CDAudio_Stop(); - return; - } - - if (Q_strcasecmp(command, "pause") == 0) - { - CDAudio_Pause(); - return; - } - - if (Q_strcasecmp(command, "resume") == 0) - { - CDAudio_Resume(); - return; - } - - if (Q_strcasecmp(command, "eject") == 0) - { - if (playing) - CDAudio_Stop(); - CDAudio_Eject(); - cdValid = false; - return; - } - - if (Q_strcasecmp(command, "info") == 0) - { - Con_Printf("%u tracks\n", maxTrack); - if (playing) - Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); - else if (wasPlaying) - Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); - Con_Printf("Volume is %f\n", cdvolume); - return; - } -} - -void CDAudio_Update(void) -{ - struct cdrom_subchnl subchnl; - static time_t lastchk; - - if (!enabled) - return; - - if (bgmvolume->value != cdvolume) - { - if (cdvolume) - { - Cvar_Set (bgmvolume, "0"); - cdvolume = bgmvolume->value; - CDAudio_Pause (); - } - else - { - Cvar_Set (bgmvolume, "1"); - cdvolume = bgmvolume->value; - CDAudio_Resume (); - } - } - - if (playing && lastchk < time(NULL)) { - lastchk = time(NULL) + 2; //two seconds between chks - subchnl.cdsc_format = CDROM_MSF; - if (ioctl(cdfile, CDROMSUBCHNL, &subchnl) == -1 ) { - Con_DPrintf("ioctl cdromsubchnl failed\n"); - playing = false; - return; - } - if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY && - subchnl.cdsc_audiostatus != CDROM_AUDIO_PAUSED) { - playing = false; - if (playLooping) - CDAudio_Play(playTrack, true); - } - } -} - -int CDAudio_Init(void) -{ - int i; - - if (cls.state == ca_dedicated) - return -1; - - if (COM_CheckParm("-nocdaudio")) - return -1; - - if ((i = COM_CheckParm("-cddev")) != 0 && i < com_argc - 1) { - strncpy(cd_dev, com_argv[i + 1], sizeof(cd_dev)); - cd_dev[sizeof(cd_dev) - 1] = 0; - } - - if ((cdfile = open(cd_dev, O_RDONLY)) == -1) { - Con_Printf("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev, errno); - cdfile = -1; - return -1; - } - - for (i = 0; i < 100; i++) - remap[i] = i; - initialized = true; - enabled = true; - - if (CDAudio_GetAudioDiskInfo()) - { - Con_Printf("CDAudio_Init: No CD in player.\n"); - cdValid = false; - } - - Cmd_AddCommand ("cd", CD_f); - - Con_Printf("CD Audio Initialized\n"); - - return 0; -} - - -void CDAudio_Shutdown(void) -{ - if (!initialized) - return; - CDAudio_Stop(); - close(cdfile); - cdfile = -1; -} diff --git a/WinQuake/cdaudio.h b/WinQuake/cdaudio.h index 70f2a9d..1911e33 100644 --- a/WinQuake/cdaudio.h +++ b/WinQuake/cdaudio.h @@ -17,12 +17,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifdef DUMB -//typedef struct DUMBFILE DUMBERFILE; -struct DUMBFILE_SYSTEM *duhfile; -struct DUH *duhsong; -//struct DUH *duhgame; // experimental ingame sounding -#endif int CDAudio_Init(void); void CDAudio_Play(byte track, qboolean looping); void CDAudio_Stop(void); diff --git a/WinQuake/cl_parse.c b/WinQuake/cl_parse.c index b70a4b7..1af8a28 100644 --- a/WinQuake/cl_parse.c +++ b/WinQuake/cl_parse.c @@ -1459,14 +1459,14 @@ void CL_ParseServerMessage (void) if (cl.paused) { - CDAudio_Pause (); + Tracker_Pause (); #ifdef _WIN32 VID_HandlePause (true); #endif } else { - CDAudio_Resume (); + Tracker_Resume (); #ifdef _WIN32 VID_HandlePause (false); #endif @@ -1527,9 +1527,9 @@ void CL_ParseServerMessage (void) cl.cdtrack = MSG_ReadByte (); cl.looptrack = MSG_ReadByte (); if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) ) - CDAudio_Play ((byte)cls.forcetrack, true); + Tracker_Play ((byte)cls.forcetrack, true); else - CDAudio_Play ((byte)cl.cdtrack, true); + Tracker_Play ((byte)cl.cdtrack, true); break; #endif diff --git a/WinQuake/host.c b/WinQuake/host.c index b343867..7586cde 100644 --- a/WinQuake/host.c +++ b/WinQuake/host.c @@ -954,6 +954,7 @@ void _Host_Frame (float time) MIDI_Update(); // leilei - update our midi #endif CDAudio_Update(); + Tracker_Update(); if (host_speeds->value) { @@ -1439,7 +1440,7 @@ void Host_Init (quakeparms_t *parms) //TW CDAudio_Init_Cvars(); // 2001-09-18 New cvar system by Maddes (Init) #ifndef BENCH CDAudio_Init (); - + Tracker_Init (); Sbar_Init (); #endif CL_Init (); @@ -1498,6 +1499,7 @@ void Host_Shutdown(void) Host_WriteConfiguration (); #endif CDAudio_Shutdown (); + Tracker_Shutdown (); NET_Shutdown (); S_Shutdown(); IN_Shutdown (); diff --git a/WinQuake/quakedef.h b/WinQuake/quakedef.h index 895c6d9..cf3bb5e 100644 --- a/WinQuake/quakedef.h +++ b/WinQuake/quakedef.h @@ -463,6 +463,7 @@ typedef struct #include "menu.h" #include "crc.h" #include "cdaudio.h" +#include "tracker.h" #ifdef GLQUAKE #include "glquake.h" diff --git a/WinQuake/tracker.h b/WinQuake/tracker.h new file mode 100644 index 0000000..b5b6e50 --- /dev/null +++ b/WinQuake/tracker.h @@ -0,0 +1,26 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2015 Marco "eukara" Hladik +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. + +*/ +int Tracker_Init(void); +void Tracker_Play(byte track, qboolean looping); +void Tracker_Stop(void); +void Tracker_Pause(void); +void Tracker_Resume(void); +void Tracker_Shutdown(void); +void Tracker_Update(void); diff --git a/WinQuake/tracker_linux.c b/WinQuake/tracker_linux.c new file mode 100644 index 0000000..0c97bf5 --- /dev/null +++ b/WinQuake/tracker_linux.c @@ -0,0 +1,199 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2015 Marco "eukara" Hladik + +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. + +*/ + +#include "quakedef.h" +#include + +// eukara - added in tracker playback using DUMB - UNIX ONLY! +char name[256]; +DUH *trackmod; // The music file ~eukara +DUH_SIGRENDERER *sr; // The DUMB renderer +FILE *oss_device; // output device (by default /dev/dsp for OSS) + +// Set up the renderer options +static int depth = 16; // by default 16bit, only affects output not internal 32bit processing +static int unsign = 0; +static int freq = 22050;// 22050 is enough for most music +static int n_channels = 2; // stereo action +static float cdvolume = 0.8f; // default cdvolume...? +static float delay = 0.0f; // You shouldn't need to touch this. +static float delta; // For the speed, combination of frequency +static int bufsize; +static qboolean playing = false;// Is the music playing or not? + +union { + short s16[2048]; // was 8192 + char s8[4096]; // was twice as the thing above +} buffer; + +void Tracker_Play(byte track, qboolean looping) +{ + dumb_register_stdfiles(); // Initialize loading files + + // Attempt to load every format imaginable, TODO: better method? + sprintf (name, "%s/music/track%d.it", com_gamedir, track); + trackmod = dumb_load_it(name); + if (!trackmod) { + sprintf (name, "%s/music/track%d.xm", com_gamedir, track); + trackmod = dumb_load_xm(name); + if (!trackmod) { + sprintf (name, "%s/music/track%d.s3m", com_gamedir, track); + trackmod = dumb_load_s3m(name); + if (!trackmod) { + sprintf (name, "%s/music/track%d.mod", com_gamedir, track); + trackmod = dumb_load_mod(name); + if (!trackmod) { + fprintf(stderr, "Unable to open %s!\n", name); + return; + } + } + } + } + + // Let us know which track you are playing + Con_Printf("Playing %s\n", name); + sr = duh_start_sigrenderer(trackmod, 0, n_channels, 0); // start rendering, action happens in Tracker_Update + if (!sr) { // If it doesn't want to render, stop it before it's too late + unload_duh(trackmod); // Unload the track safely + fprintf(stderr, "Unable to play file!\n"); + return; + } + + delta = 61536.0f / freq; // This affects the speed + bufsize = depth == 16 ? 2048 : 4096; // Buffer size, small buffer = laggy music; big buff = laggy game + bufsize /= n_channels; // Tell him we are hopefully stereo + playing = true; // Announce that we have a track playing +} + +void Tracker_Stop(void) +{ + playing = false; // Not playing the song anymore to prevent Tracker_Update + Con_Printf("Stopping %s\n", name); // Just print that we are stopping whatever track + duh_end_sigrenderer(sr); // Stop the renderer safely + unload_duh(trackmod); // Unload the song! +} + +void Tracker_Pause(void) +{ + playing = false; // Prevent from Tracker_Update from happening + Con_Printf("Paused %s\n", name); +} + +void Tracker_Resume(void) +{ + // Just making sure we aren't calling Tracker_Update with no song... + if(!trackmod || !sr) + return; + + playing = true; // Tracker_Update should now be triggered again + Con_Printf("Resuming %s\n", name); +} + + +static void Tracker_f (void) +{ + char *command; + int ret; + int n; + + if (Cmd_Argc() < 2) + return; + + command = Cmd_Argv (1); + + if (Q_strcasecmp(command, "play") == 0) + { + Tracker_Play((byte)Q_atoi(Cmd_Argv (2)), false); + return; + } + + if (Q_strcasecmp(command, "stop") == 0) + { + Tracker_Stop(); + return; + } + + if (Q_strcasecmp(command, "volume") == 0) + { + cdvolume = (float)Q_atoi(Cmd_Argv (2)); + return; + } + + if (Q_strcasecmp(command, "frequency") == 0) + { + freq = (int)Q_atoi(Cmd_Argv (2)); + return; + } + + if (Q_strcasecmp(command, "pause") == 0) + { + Tracker_Pause(); + return; + } + + if (Q_strcasecmp(command, "resume") == 0) + { + Tracker_Resume(); + return; + } +} + +void Tracker_Update(void) +{ + int i; + + // Only update when a song is playing and the renderer works... + if (!sr) + return; + if(playing == false) + return; + + // Render the song + int l = duh_render(sr, depth, unsign, cdvolume, delta, bufsize, &buffer); + if (depth == 16) { // On 16 bit, fill the buffer accordingly + for (i = 0; i < l * n_channels; i++) { + short val = buffer.s16[i]; + buffer.s8[i*2] = (char)val; + buffer.s8[i*2+1] = (char)(val >> 8); + } + } + + // TODO: Write this into the engine's soundbuffer instead for speed! + fwrite(buffer.s8, 1, l * n_channels * (depth >> 3), oss_device); // write it into OSS' device +} + +int Tracker_Init(void) +{ + oss_device = fopen("/dev/dsp", "wb"); // /dev/dsp is the standard OSS output + if(oss_device == NULL) // just get out if there's none + return 0; + + Cmd_AddCommand ("dumb", Tracker_f); // link DUMB + Con_Printf("DUMB Initialized\n"); // Tell them we are ready + return 1; // return that we have successfully initialised +} + +void Tracker_Shutdown(void) +{ + Tracker_Stop(); // First stop the track + fclose(oss_device); // Close the device + dumb_exit(); // Kill DUMB +}