Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PC Speaker sound effects #5

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 222 additions & 0 deletions a_pcfx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
/*
Copyright (C) 1994-1995 Apogee Software, Ltd.
Copyright (C) 2023-2024 Frenkel Smeijers

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.

*/
/**********************************************************************
module: PCFX.C

author: James R. Dose
date: April 1, 1994

Low level routines to support PC sound effects created by Muse.

(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/

#include <stdint.h>
#include <stdlib.h>

#include "compiler.h"
#include "doomtype.h"
#include "doomdef.h"
#include "a_pcfx.h"
#include "i_system.h"


static uint32_t __far* pjiffies;
static uint32_t previoustick;


static int16_t PCFX_LengthLeft;
static uint16_t *PCFX_Sound = NULL;
static uint16_t PCFX_LastSample;

static boolean PCFX_Installed = false;


/*---------------------------------------------------------------------
Function: PCFX_Stop

Halts playback of the currently playing sound effect.
---------------------------------------------------------------------*/

static void PCFX_Stop(void)
{
if (PCFX_Sound == NULL)
return;

// Turn off speaker
outp(0x61, inp(0x61) & 0xfc);

PCFX_Sound = NULL;
PCFX_LengthLeft = 0;
PCFX_LastSample = 0;
}


/*---------------------------------------------------------------------
Function: PCFX_Service

Routine to perform the playback of a sound effect.
---------------------------------------------------------------------*/

void PCFX_Service(void)
{
if (PCFX_Sound)
{
uint32_t currenttick = *pjiffies;
int16_t newticks = currenttick - previoustick;
previoustick = currenttick;
while (newticks--)
{
uint16_t sample = *PCFX_Sound++;

if (sample != PCFX_LastSample)
{
PCFX_LastSample = sample;
if (sample)
{
outp(0x43, 0xb6);
outp(0x42, LOBYTE(sample));
outp(0x42, HIBYTE(sample));
outp(0x61, inp(0x61) | 0x3);
} else
outp(0x61, inp(0x61) & 0xfc);
}

PCFX_LengthLeft--;
if (PCFX_LengthLeft == 0)
{
PCFX_Stop();
break;
}
}
}
}


/*---------------------------------------------------------------------
Function: PCFX_Play

Starts playback of a Muse sound effect.
---------------------------------------------------------------------*/

typedef struct
{
uint16_t length;
uint8_t data[];
} PCSound;

#define PCFX_MinVoiceHandle 1
static int16_t PCFX_VoiceHandle = PCFX_MinVoiceHandle;

static int16_t ASS_PCFX_Play(PCSound *sound)
{
PCFX_Stop();

PCFX_VoiceHandle++;
if (PCFX_VoiceHandle < PCFX_MinVoiceHandle)
PCFX_VoiceHandle = PCFX_MinVoiceHandle;

PCFX_LengthLeft = sound->length;
PCFX_Sound = (uint16_t*)&sound->data[0];

previoustick = *pjiffies;

return PCFX_VoiceHandle;
}

static const uint16_t divisors[] = {
0,
6818, 6628, 6449, 6279, 6087, 5906, 5736, 5575,
5423, 5279, 5120, 4971, 4830, 4697, 4554, 4435,
4307, 4186, 4058, 3950, 3836, 3728, 3615, 3519,
3418, 3323, 3224, 3131, 3043, 2960, 2875, 2794,
2711, 2633, 2560, 2485, 2415, 2348, 2281, 2213,
2153, 2089, 2032, 1975, 1918, 1864, 1810, 1757,
1709, 1659, 1612, 1565, 1521, 1478, 1435, 1395,
1355, 1316, 1280, 1242, 1207, 1173, 1140, 1107,
1075, 1045, 1015, 986, 959, 931, 905, 879,
854, 829, 806, 783, 760, 739, 718, 697,
677, 658, 640, 621, 604, 586, 570, 553,
538, 522, 507, 493, 479, 465, 452, 439,
427, 415, 403, 391, 380, 369, 359, 348,
339, 329, 319, 310, 302, 293, 285, 276,
269, 261, 253, 246, 239, 232, 226, 219,
213, 207, 201, 195, 190, 184, 179,
};

typedef struct {
uint16_t length;
uint16_t data[150 - 2 - 2];
} pcspkmuse_t;

static pcspkmuse_t pcspkmuse;

typedef struct {
uint16_t type; // 0 = PC Speaker
uint16_t length;
uint8_t data[];
} dmxpcs_t;

int16_t PCFX_Play(const void __far* vdata)
{
dmxpcs_t __far* dmxpcs = (dmxpcs_t __far* )vdata;

pcspkmuse.length = dmxpcs->length;
for (uint_fast16_t i = 0; i < dmxpcs->length; i++)
pcspkmuse.data[i] = divisors[dmxpcs->data[i]];

return ASS_PCFX_Play((PCSound *)&pcspkmuse);
}


/*---------------------------------------------------------------------
Function: PCFX_Init

Initializes the sound effect engine.
---------------------------------------------------------------------*/

void PCFX_Init(void)
{
if (PCFX_Installed)
return;

PCFX_Stop();

pjiffies = I_GetPjiffies();

PCFX_Installed = true;
}


/*---------------------------------------------------------------------
Function: PCFX_Shutdown

Ends the use of the sound effect engine.
---------------------------------------------------------------------*/

void PCFX_Shutdown(void)
{
if (PCFX_Installed)
{
PCFX_Stop();
PCFX_Installed = false;
}
}
40 changes: 40 additions & 0 deletions a_pcfx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
Copyright (C) 1994-1995 Apogee Software, Ltd.
Copyright (C) 2023-2024 Frenkel Smeijers

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.

*/
/**********************************************************************
module: PCFX.H

author: James R. Dose
date: April 1, 1994

Public header for PCFX.C

(c) Copyright 1994 James R. Dose. All Rights Reserved.
**********************************************************************/

#ifndef __PCFX_H
#define __PCFX_H

void PCFX_Service(void);
int16_t PCFX_Play(const void __far* vdata);
void PCFX_Init(void);
void PCFX_Shutdown(void);

#endif
3 changes: 2 additions & 1 deletion compelks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ CCOPTST="-oaxet -oh -ol+ -bt=none -0 -zq -s -mm -wx -zastd=c99 -zls"

nasm i_vmodya.asm -f obj -DCPU=i8088

wcc $CCOPTSS a_pcfx.c -fo=a_pcfx.obj
wcc $CCOPTSS am_map.c -fo=am_map.obj
wcc $CCOPTSS d_items.c -fo=d_items.obj
wcc $CCOPTSS d_main.c -fo=d_main.obj
Expand Down Expand Up @@ -52,7 +53,7 @@ wcc $CCOPTSS z_zone.c -fo=z_zone.obj
wcc $CCOPTST i_vmodey.c -fo=i_vmodey.obj
wcc $CCOPTST r_draw.c -fo=r_draw.obj

owcc -bos2 -s -Wl,option -Wl,start=_start -Wl,alias -Wl,source=_source -Wl,alias -Wl,nearcolormap=_nearcolormap -Wl,alias -Wl,dest=_dest -Wl,alias -Wl,R_DrawColumn2_=R_DrawColumn2 -Wl,option -Wl,dosseg -Wl,option -Wl,nodefaultlibs -Wl,option -Wl,stack=0x1000 -Wl,option -Wl,heapsize=0x1000 -Wl,library -Wl,$LIBC -o elksdoom.os2 am_map.obj d_items.obj d_main.obj f_finale.obj g_game.obj hu_stuff.obj i_audio.obj i_main.obj i_elks.obj i_vmodey.obj i_vmodya.obj info.obj m_cheat.obj m_menu.obj m_random.obj p_doors.obj p_enemy.obj p_floor.obj p_inter.obj p_lights.obj p_map.obj p_maputl.obj p_mobj.obj p_plats.obj p_pspr.obj p_setup.obj p_sight.obj p_spec.obj p_switch.obj p_telept.obj p_tick.obj p_user.obj r_data.obj r_draw.obj r_plane.obj r_sky.obj r_things.obj s_sound.obj sounds.obj st_stuff.obj tables.obj v_video.obj w_wad.obj wi_stuff.obj z_bmallo.obj z_zone.obj
owcc -bos2 -s -Wl,option -Wl,start=_start -Wl,alias -Wl,source=_source -Wl,alias -Wl,nearcolormap=_nearcolormap -Wl,alias -Wl,dest=_dest -Wl,alias -Wl,R_DrawColumn2_=R_DrawColumn2 -Wl,option -Wl,dosseg -Wl,option -Wl,nodefaultlibs -Wl,option -Wl,stack=0x1000 -Wl,option -Wl,heapsize=0x1000 -Wl,library -Wl,$LIBC -o elksdoom.os2 a_pcfx.obj am_map.obj d_items.obj d_main.obj f_finale.obj g_game.obj hu_stuff.obj i_audio.obj i_main.obj i_elks.obj i_vmodey.obj i_vmodya.obj info.obj m_cheat.obj m_menu.obj m_random.obj p_doors.obj p_enemy.obj p_floor.obj p_inter.obj p_lights.obj p_map.obj p_maputl.obj p_mobj.obj p_plats.obj p_pspr.obj p_setup.obj p_sight.obj p_spec.obj p_switch.obj p_telept.obj p_tick.obj p_user.obj r_data.obj r_draw.obj r_plane.obj r_sky.obj r_things.obj s_sound.obj sounds.obj st_stuff.obj tables.obj v_video.obj w_wad.obj wi_stuff.obj z_bmallo.obj z_zone.obj

rm *.obj
rm *.err
47 changes: 43 additions & 4 deletions i_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,29 +60,68 @@

#include "m_fixed.h"

#include "a_pcfx.h"

#include "globdata.h"


#define MAX_CHANNELS 1


int16_t I_StartSound(sfxenum_t id, int16_t channel, int16_t vol, int16_t sep)
{
UNUSED(id);
UNUSED(channel);
UNUSED(vol);
UNUSED(sep);

return -1;
if (!(0 <= channel && channel < MAX_CHANNELS))
return -1;

// // hacks out certain PC sounds
// if (id == sfx_posact
// || id == sfx_bgact
// || id == sfx_dmact
// || id == sfx_dmpain
// || id == sfx_popain
// || id == sfx_sawidl)
// return -1;

int16_t lumpnum = 96 - 1; // TODO should be W_GetNumForName("DPPISTOL") - 1;
if (id < sfx_chgun)
lumpnum += id;
else if (id == sfx_chgun)
lumpnum += sfx_pistol;
else
lumpnum += id - 1;

const void __far* soundpatch = W_GetLumpByNum(lumpnum);
PCFX_Play(soundpatch);
Z_ChangeTagToCache(soundpatch);

return channel;
}


void I_UpdateSound(void)
{
PCFX_Service();
}


void I_InitSound(void)
{
if (nomusicparm && nosfxparm)
return;

PCFX_Init();

// Finished initialization.
printf("I_InitSound: sound ready\n");
}


void I_ShutdownSound(void)
{

PCFX_Shutdown();
}


Expand Down
9 changes: 9 additions & 0 deletions i_elks.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "doomtype.h"
#include "compiler.h"
#include "d_main.h"
#include "i_sound.h"
#include "i_system.h"
#include "globdata.h"

Expand Down Expand Up @@ -191,6 +192,8 @@ static void I_ShutdownKeyboard(void)

void I_StartTic(void)
{
I_UpdateSound();

//
// process keyboard events
//
Expand Down Expand Up @@ -342,6 +345,12 @@ int32_t I_GetTime(void)
}


uint32_t __far* I_GetPjiffies(void)
{
return pjiffies;
}


void I_InitTimer(void)
{
int16_t fd = open("/dev/kmem", O_RDONLY);
Expand Down
Loading