Initial commit of Command & Conquer Red Alert source code.

This commit is contained in:
LFeenanEA
2025-02-27 16:15:05 +00:00
parent b685cea758
commit 5e733d5dcc
2082 changed files with 797727 additions and 0 deletions

160
WIN32LIB/AUDIO/AUDIO.H Normal file
View File

@@ -0,0 +1,160 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : AUDIO.H *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : March 10, 1995 *
* *
* Last Update : March 10, 1995 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "wwstd.h"
/*=========================================================================*/
/* AUD file header type */
/*=========================================================================*/
#define AUD_FLAG_STEREO 1
#define AUD_FLAG_16BIT 2
// PWG 3-14-95: This structure used to have bit fields defined for Stereo
// and Bits. These were removed because watcom packs them into a 32 bit
// flag entry even though they could have fit in a 8 bit entry.
#pragma pack(1);
typedef struct {
unsigned short int Rate; // Playback rate (hertz).
long Size; // Size of data (bytes).
long UncompSize; // Size of data (bytes).
unsigned char Flags; // Holds flags for info
// 1: Is the sample stereo?
// 2: Is the sample 16 bits?
unsigned char Compression; // What kind of compression for this sample?
} AUDHeaderType;
/*=========================================================================*/
/* There can be a different sound driver for sound effects, digitized */
/* samples, and musical scores. Each one must be of these specified */
/* types. */
/*=========================================================================*/
typedef enum {
SAMPLE_NONE, // No digitized sounds will be played.
SAMPLE_SB, // Sound Blaster digitized driver.
SAMPLE_SBPRO, // Sound Blaster Pro digitized driver.
SAMPLE_PAS, // Pro-Audio Spectrum digitized driver.
SAMPLE_ADLIBG, // Adlib-Gold digitized driver.
SAMPLE_TANDY, // Tandy 'compatible' driver.
SAMPLE_PCSPKR, // PC speaker digitized driver (The Audio Solution driver).
SAMPLE_ADLIB, // Adlib digitized driver (The Audio Solution driver).
SAMPLE_TEMP=0x1000,
SAMPLE_LAST
} Sample_Type;
typedef enum {
SCORE_NONE, // No scores will be played.
SCORE_ALFX, // Westwood's ALFX adlib compatable driver.
SCORE_WWPCSPKR, // Westwood's PC-speaker driver (obsolete).
SCORE_WWTANDY, // Westwood's PC-speaker driver with Tandy mod (obsolete).
SCORE_PCSPKR, // PC speaker XMIDI driver.
SCORE_TANDY, // Tandy XMIDI driver.
SCORE_MT32, // MT-32 / LAPC-1 Roland XMIDI driver.
SCORE_CANVAS, // Sound Canvas SC-55.
SCORE_ADLIB, // Adlib XMIDI driver.
SCORE_ADLIBG, // Adlib Gold XMIDI driver.
SCORE_PASFM, // Pro Audio Spectrum XMIDI driver.
SCORE_SBFM, // Sound Blaster XMIDI driver.
SCORE_SBP1FM, // Sound Blaster Pro (YM3812) XMIDI driver.
SCORE_SBP2FM, // Sound Blaster Pro (OPL3) XMIDI driver (Can't use with SFX_ALFX).
SCORE_TEMP=0x1000,
SCORE_LAST
} Score_Type;
typedef enum {
SFX_NONE, // No sound effects will be played.
SFX_ALFX, // Westwood's ALFX adlib compatable driver.
SFX_WWPCSPKR, // Westwood's PC-speaker driver.
SFX_WWTANDY, // Westwood's PC-speaker driver with Tandy mod.
SFX_PCSPKR, // PC speaker XMIDI driver.
SFX_TANDY, // Tandy XMIDI driver.
SFX_MT32, // MT-32 / LAPC-1 Roland XMIDI driver.
SFX_CANVAS, // Sound Canvas SC-55.
SFX_ADLIB, // Adlib XMIDI driver.
SFX_ADLIBG, // Adlib Gold XMIDI driver.
SFX_PASFM, // Pro Audio Spectrum XMIDI driver.
SFX_SBFM, // Sound Blaster XMIDI driver.
SFX_SBP1FM, // Sound Blaster Pro (YM3812) XMIDI driver.
SFX_SBP2FM, // Sound Blaster Pro (OPL3) XMIDI driver.
SFX_TEMP=0x1000,
SFX_LAST
} SFX_Type;
/*=========================================================================*/
/* The following prototypes are for the file: SOUNDIO.CPP */
/*=========================================================================*/
int File_Stream_Sample(char const *filename, BOOL real_time_start = FALSE);
int File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start = FALSE);
void __cdecl Sound_Callback(void);
void __cdecl far maintenance_callback(void);
void *Load_Sample(char const *filename);
long Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);
long Sample_Read(int fh, void *buffer, long size);
void Free_Sample(void const *sample);
BOOL Audio_Init( HWND window , int bits_per_sample, BOOL stereo , int rate , int reverse_channels);
void Sound_End(void);
void Stop_Sample(int handle);
BOOL Sample_Status(int handle);
BOOL Is_Sample_Playing(void const * sample);
void Stop_Sample_Playing(void const * sample);
int Play_Sample(void const *sample, int priority=0xFF, int volume=0xFF, signed short panloc = 0x0);
int Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id);
int Set_Sound_Vol(int volume);
int Set_Score_Vol(int volume);
void Fade_Sample(int handle, int ticks);
int Get_Free_Sample_Handle(int priority);
int Get_Digi_Handle(void);
long Sample_Length(void const *sample);
void Restore_Sound_Buffers (void);
BOOL Set_Primary_Buffer_Format(void);
BOOL Start_Primary_Sound_Buffer (BOOL forced);
void Stop_Primary_Sound_Buffer (void);
/*
** Function to call if we detect focus loss
*/
extern void (*Audio_Focus_Loss_Function)(void);
extern int Misc;
extern SFX_Type SoundType;
extern Sample_Type SampleType;
extern CRITICAL_SECTION GlobalAudioCriticalSection;
extern int StreamLowImpact;

BIN
WIN32LIB/AUDIO/AUDIO.IDE Normal file

Binary file not shown.

374
WIN32LIB/AUDIO/AUDUNCMP.ASM Normal file
View File

@@ -0,0 +1,374 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Audio Library *
;* *
;* File Name : AUDUNCMP.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : March 14, 1995 *
;* *
;* Last Update : June 26, 1995 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Decompress_Frame_Lock -- locks the JLB audio decompression code *
;* Decompress_Frame_Unlock -- Unlocks the JLB audio compression code *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
CODESEG
DPMI_INTR equ 31h
LABEL LockedCodeStart BYTE
CODE_2BIT EQU 0
CODE_4BIT EQU 1
CODE_RAW EQU 2
CODE_SILENCE EQU 3
MAGICNUMBER EQU 00000DEAFh
MAGICNUMBER2 EQU 0BABEBABEh
_2bitdecode DB -2,-1,0,1
_4bitdecode DB -9,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8
;***************************************************************************
;* DECOMPRESS_FRAME -- Uncompresses a WW compressed audio frame *
;* *
;* INPUT: void * source - pointer to encoded audio data *
;* void * dest - pointer to decompression area *
;* long size - the maximum size of destination buffer *
;* *
;* OUTPUT: long - the number of bytes we uncompressed *
;* *
;* PROTO: long Decompress_Frame(void *, void *, long); *
;* *
;* HISTORY: *
;* 03/14/1995 PWG : Created. *
;*=========================================================================*
GLOBAL C Decompress_Frame:NEAR
PROC Decompress_Frame C NEAR USES ebx ecx edx esi edi
ARG source:DWORD
ARG dest:DWORD
ARG count:DWORD
LOCAL previous:BYTE
LOCAL incount:DWORD
pushfd
cld
mov [incount],0 ;Bytes read from source
; Source, Dest and count must be valid.
cmp [source],0
je ??fini
cmp [dest],0
je ??fini
cmp [count],0
je ??fini
mov esi,[source] ;Pointer to source data.
mov edi,[dest] ;Pointer to destination data.
mov ecx,[count] ;Number of bytes to fill dest buffer.
mov dl,080h ;Previous sample (starting value).
??mainloop:
cmp ecx,0 ;If dest full then exit
jle ??fini
xor eax,eax
mov al,[esi] ;Get code byte
inc [incount]
inc esi
shl eax,2 ;AH contains code.
shr al,2 ;AL contains sub-code data.
cmp ah,CODE_RAW ;Raw sequence?
jne short ??try4bit
; The code contains either a 5 bit delta or a count of
; raw samples to dump out.
test al,00100000b
je short ??justraw
; The lower 5 bits are actually a signed delta.
; Sign extend the delta and add it to the stream.
shl al,3
sar al,3
add dl,al
mov [edi],dl
dec ecx
inc edi
jmp ??mainloop
; The lower 5 bits hold a count of the number of raw
; samples that follow this code. Dump these samples to
; the output buffer.
??justraw:
mov ebx,ecx
xor ah,ah
inc al
mov ecx,eax
shr ecx,1
rep movsw
adc ecx,ecx
rep movsb
mov ecx,ebx
add [incount],eax
sub ecx,eax
dec edi
mov dl,[edi] ;Set "previous" value.
inc edi
jmp ??mainloop
; Check to see if this is a 4 bit delta code sequence.
??try4bit:
inc al ;Following codes use AL+1
cmp ah,CODE_4BIT
jne short ??try2bit
; A sequence of 4bit deltas follow. AL equals the
; number of nibble packed delta bytes to process.
??bit4loop:
mov ah,[esi] ;Fetch nibble packed delta codes
mov bl,ah
inc [incount]
inc esi
; Add first delta to 'previous' sample already in DL.
and ebx,00001111b
add dl,[_4bitdecode+ebx]
pushfd
cmp [_4bitdecode+ebx],0
jl short ??neg1
popfd
jnc short ??ok1
mov dl,0FFh
jmp short ??ok1
??neg1:
popfd
jc short ??ok1
xor dl,dl
??ok1:
mov dh,dl ;DH now holds new 'previous' sample.
mov bl,ah
shr bl,4
add dh,[_4bitdecode+ebx]
pushfd
cmp [_4bitdecode+ebx],0
jl short ??neg2
popfd
jnc short ??ok2
mov dh,0FFh
jmp short ??ok2
??neg2:
popfd
jc short ??ok2
xor dh,dh
??ok2:
mov [edi],dx ;Output the two sample bytes
sub ecx,2
add edi,2
; Put the correct 'previous' sample in DL where it belongs.
mov dl,dh
; If there are more deltas to process then loop back.
dec al
jnz short ??bit4loop
jmp ??mainloop
; Check to see if 2 bit deltas need to be processed.
??try2bit:
cmp ah,CODE_2BIT
jne ??zerodelta
; A sequence of 2bit deltas follow. AL equals the number of
; packed delta bytes to process.
??bit2loop:
mov ah,[esi] ;Fetch packed delat codes
inc [incount]
inc esi
; Add first delta to 'previous' sample already in DL.
mov bl,ah
and ebx,000011b
add dl,[_2bitdecode+ebx]
pushfd
cmp [_2bitdecode+ebx],0
jl short ??neg3
popfd
jnc short ??ok3
mov dl,0FFh
jmp short ??ok3
??neg3:
popfd
jc short ??ok3
xor dl,dl
??ok3:
mov dh,dl
ror edx,8
mov bl,ah
shr ebx,2
and bl,00000011b
add dl,[_2bitdecode+ebx]
pushfd
cmp [_2bitdecode+ebx],0
jl short ??neg4
popfd
jnc short ??ok4
mov dl,0FFh
jmp short ??ok4
??neg4:
popfd
jc short ??ok4
xor dl,dl
??ok4:
mov dh,dl
ror edx,8
mov bl,ah
shr ebx,4
and bl,00000011b
add dl,[_2bitdecode+ebx]
pushfd
cmp [_2bitdecode+ebx],0
jl short ??neg5
popfd
jnc short ??ok5
mov dl,0FFh
jmp short ??ok5
??neg5:
popfd
jc short ??ok5
xor dl,dl
??ok5:
mov dh,dl
ror edx,8
mov bl,ah
shr ebx,6
and bl,00000011b
add dl,[_2bitdecode+ebx]
pushfd
cmp [_2bitdecode+ebx],0
jl short ??neg6
popfd
jnc short ??ok6
mov dl,0FFh
jmp short ??ok6
??neg6:
popfd
jc short ??ok6
xor dl,dl
??ok6:
ror edx,8
mov [edi],edx ;Output two sample bytes
sub ecx,4
add edi,4
; Put the correct 'previous' sample in DL where it belongs.
rol edx,8
; If there are more deltas to process then loop back.
dec al
jnz ??bit2loop
jmp ??mainloop
; There is a run of zero deltas. Zero deltas merely duplicate
; the 'previous' sample the requested number of times.
??zerodelta:
xor ebx,ebx
mov bl,al
mov al,dl
sub ecx,ebx
xchg ecx,ebx
rep stosb
mov ecx,ebx
jmp ??mainloop
??fini:
popfd
mov eax,[incount]
ret
ENDP Decompress_Frame
LABEL LockedCodeEnd BYTE
END

1448
WIN32LIB/AUDIO/DIFFTB.INC Normal file

File diff suppressed because it is too large Load Diff

47
WIN32LIB/AUDIO/FUNCTION.H Normal file
View File

@@ -0,0 +1,47 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/*=========================================================================*/
/* The following prototypes are for the file: SOUNDIO.CPP */
/*=========================================================================*/
short Decompress_Frame(void * source, void * dest, short size);
int __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback);
int __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback);
int __cdecl File_Stream_Sample(char const *filename);
int __cdecl File_Stream_Sample_Vol(char const *filename, int volume);
void __cdecl _saveregs _loadds Sound_Callback(void);
void __cdecl far _saveregs _loadds maintenance_callback(void);
void __cdecl Load_Sample(char const *filename);
long __cdecl Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);
long __cdecl Sample_Read(int fh, void *buffer, long size);
void __cdecl Free_Sample(void const *sample);
BOOL __cdecl Sound_Init(int sfx, int score, int sample);
void far VQA_TimerCallback(void);
BOOL Audio_Init(int sample, int address, int inter, int dma);
void __cdecl Sound_End(void);
void __cdecl Stop_Sample(int handle);
BOOL __cdecl Sample_Status(int handle);
BOOL __cdecl Is_Sample_Playing(void const * sample);
void __cdecl Stop_Sample_Playing(void const * sample);
int __cdecl Play_Sample(void const *sample);
int __cdecl Play_Sample_Vol(void const *sample, int priority, int volume);
int __cdecl Set_Sound_Vol(int volume);
int __cdecl Set_Score_Vol(int volume);
void __cdecl Fade_Sample(int handle, int ticks);

1448
WIN32LIB/AUDIO/INDEXTB.INC Normal file

File diff suppressed because it is too large Load Diff

186
WIN32LIB/AUDIO/MAKEFILE Normal file
View File

@@ -0,0 +1,186 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WIN32LIB path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef %WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef %WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef %WATCOM
!error WATCOM Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = AUDIO
PROJ_DIR = $(%WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(%WIN32LIB)\lib
!include $(%WIN32LIB)\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = &
soundio.obj &
soundint.obj &
soundlck.obj &
soscodec.obj &
olsosdec.obj &
auduncmp.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.asm: $(PROJ_DIR)
.c: $(PROJ_DIR)
.cpp: $(PROJ_DIR)
.h: $(PROJ_DIR)
.obj: $(PROJ_DIR)
.lib: $(%WIN32LIB)\lib
.exe: $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = wcc386
CPP_CMD = wpp386
LIB_CMD = wlib
LINK_CMD = wlink
ASM_CMD = tasm
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(%WIN32LIB)\LIB;..\..\dxsdk\lib;$(%WATCOM)\LIB
INCLUDEPATH = $(%WIN32LIB)\INCLUDE;..\..\dxsdk\inc;$(%WATCOM)\H
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
*$(C_CMD) $(CC_CFG) $<
.cpp.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\$^*.cpp
.asm.obj: $(%WIN32LIB)\project.cfg
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib .SYMBOLIC
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc
copy *.lib $(%WIN32LIB)\lib
copy *.h $(%WIN32LIB)\include
copy *.inc $(%WIN32LIB)\include
copy *.cpp $(%WIN32LIB)\srcdebug
copy *.asm $(%WIN32LIB)\srcdebug
copy *.lib $(%WIN32LIB)\lib
$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc
#---------------------------------------------------------------------------
# Objects now have a link file which is NOT generated everytime. Instead
# it just has its own dependacy rule.
#---------------------------------------------------------------------------
objects.lbc : $(OBJECTS)
%create $^@
for %index in ($(OBJECTS)) do %append $^@ +%index
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(%WWVCS)\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..
copy *.386 test
#**************************** End of makefile ******************************

177
WIN32LIB/AUDIO/MAKEFILE.BOR Normal file
View File

@@ -0,0 +1,177 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WWFLAT path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
.AUTODEPEND
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef COMPILER
!error COMPILER Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = audio
PROJ_DIR = $(WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(WIN32LIB)\lib
!include $(WIN32LIB)\\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = \
soundio.obj \
soundint.obj \
soundlck.obj \
soscodec.obj \
auduncmp.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.path.asm = $(PROJ_DIR)
.path.c = $(PROJ_DIR)
.path.cpp = $(PROJ_DIR)
.path.h = $(PROJ_DIR)
.path.obj = $(PROJ_DIR)
.path.lib = $(WIN32LIB)\lib
.path.exe = $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = bcc32
CPP_CMD = bcc32
LIB_CMD = tlib
LINK_CMD = tlink32
ASM_CMD = tasm32
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(WIN32LIB)\LIB;$(COMPILER)\LIB
INCLUDEPATH = $(WIN32LIB)\INCLUDE;$(COMPILER)\INCLUDE
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj:
$(C_CMD) $(CC_CFG) $<
.cpp.obj:
$(CPP_CMD) $(CC_CFG) $<
.asm.obj:
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS)
copy *.h $(WIN32LIB)\\include
copy *.inc $(WIN32LIB)\\include
copy *.cpp $(WIN32LIB)\\srcdebug
copy *.asm $(WIN32LIB)\\srcdebug
$(LIB_CMD) $< $(LIB_CFG) @&&|
+-soundio.obj &
+-soundint.obj &
+-soundlck.obj &
+-soscodec.obj &
+-auduncmp.obj
|
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(WWVCS)\\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..

59
WIN32LIB/AUDIO/NYBBTB.INC Normal file
View File

@@ -0,0 +1,59 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
;
;****************************************************************************
;* bNybbleTablexxxx - ADPCM Lookup table for nybbles
;****************************************************************************
align 4
bNybbleTableLow DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
align 4
bNybbleTableHigh DB 00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2
DB 01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2
DB 02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2
DB 03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2
DB 04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2
DB 05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2
DB 06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2
DB 07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2
DB 08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2
DB 09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2
DB 0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2
DB 0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2
DB 0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2
DB 0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2
DB 0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2
DB 0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2

158
WIN32LIB/AUDIO/OLD/AUDIO.H Normal file
View File

@@ -0,0 +1,158 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : AUDIO.H *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : March 10, 1995 *
* *
* Last Update : March 10, 1995 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "wwstd.h"
/*=========================================================================*/
/* AUD file header type */
/*=========================================================================*/
#define AUD_FLAG_STEREO 1
#define AUD_FLAG_16BIT 2
// PWG 3-14-95: This structure used to have bit fields defined for Stereo
// and Bits. These were removed because watcom packs them into a 32 bit
// flag entry even though they could have fit in a 8 bit entry.
#pragma pack(1);
typedef struct {
unsigned short int Rate; // Playback rate (hertz).
long Size; // Size of data (bytes).
long UncompSize; // Size of data (bytes).
unsigned char Flags; // Holds flags for info
// 1: Is the sample stereo?
// 2: Is the sample 16 bits?
unsigned char Compression; // What kind of compression for this sample?
} AUDHeaderType;
/*=========================================================================*/
/* There can be a different sound driver for sound effects, digitized */
/* samples, and musical scores. Each one must be of these specified */
/* types. */
/*=========================================================================*/
typedef enum {
SAMPLE_NONE, // No digitized sounds will be played.
SAMPLE_SB, // Sound Blaster digitized driver.
SAMPLE_SBPRO, // Sound Blaster Pro digitized driver.
SAMPLE_PAS, // Pro-Audio Spectrum digitized driver.
SAMPLE_ADLIBG, // Adlib-Gold digitized driver.
SAMPLE_TANDY, // Tandy 'compatible' driver.
SAMPLE_PCSPKR, // PC speaker digitized driver (The Audio Solution driver).
SAMPLE_ADLIB, // Adlib digitized driver (The Audio Solution driver).
SAMPLE_TEMP=0x1000,
SAMPLE_LAST
} Sample_Type;
typedef enum {
SCORE_NONE, // No scores will be played.
SCORE_ALFX, // Westwood's ALFX adlib compatable driver.
SCORE_WWPCSPKR, // Westwood's PC-speaker driver (obsolete).
SCORE_WWTANDY, // Westwood's PC-speaker driver with Tandy mod (obsolete).
SCORE_PCSPKR, // PC speaker XMIDI driver.
SCORE_TANDY, // Tandy XMIDI driver.
SCORE_MT32, // MT-32 / LAPC-1 Roland XMIDI driver.
SCORE_CANVAS, // Sound Canvas SC-55.
SCORE_ADLIB, // Adlib XMIDI driver.
SCORE_ADLIBG, // Adlib Gold XMIDI driver.
SCORE_PASFM, // Pro Audio Spectrum XMIDI driver.
SCORE_SBFM, // Sound Blaster XMIDI driver.
SCORE_SBP1FM, // Sound Blaster Pro (YM3812) XMIDI driver.
SCORE_SBP2FM, // Sound Blaster Pro (OPL3) XMIDI driver (Can't use with SFX_ALFX).
SCORE_TEMP=0x1000,
SCORE_LAST
} Score_Type;
typedef enum {
SFX_NONE, // No sound effects will be played.
SFX_ALFX, // Westwood's ALFX adlib compatable driver.
SFX_WWPCSPKR, // Westwood's PC-speaker driver.
SFX_WWTANDY, // Westwood's PC-speaker driver with Tandy mod.
SFX_PCSPKR, // PC speaker XMIDI driver.
SFX_TANDY, // Tandy XMIDI driver.
SFX_MT32, // MT-32 / LAPC-1 Roland XMIDI driver.
SFX_CANVAS, // Sound Canvas SC-55.
SFX_ADLIB, // Adlib XMIDI driver.
SFX_ADLIBG, // Adlib Gold XMIDI driver.
SFX_PASFM, // Pro Audio Spectrum XMIDI driver.
SFX_SBFM, // Sound Blaster XMIDI driver.
SFX_SBP1FM, // Sound Blaster Pro (YM3812) XMIDI driver.
SFX_SBP2FM, // Sound Blaster Pro (OPL3) XMIDI driver.
SFX_TEMP=0x1000,
SFX_LAST
} SFX_Type;
/*=========================================================================*/
/* The following prototypes are for the file: SOUNDIO.CPP */
/*=========================================================================*/
int File_Stream_Sample(char const *filename, BOOL real_time_start = FALSE);
int File_Stream_Sample_Vol(char const *filename, int volume, BOOL real_time_start = FALSE);
void __cdecl Sound_Callback(void);
void __cdecl far maintenance_callback(void);
void *Load_Sample(char const *filename);
long Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);
long Sample_Read(int fh, void *buffer, long size);
void Free_Sample(void const *sample);
BOOL Audio_Init( HWND window , int bits_per_sample, BOOL stereo , int rate , int reverse_channels);
void Sound_End(void);
void Stop_Sample(int handle);
BOOL Sample_Status(int handle);
BOOL Is_Sample_Playing(void const * sample);
void Stop_Sample_Playing(void const * sample);
int Play_Sample(void const *sample, int priority=0xFF, int volume=0xFF, signed short panloc = 0x0);
int Play_Sample_Handle(void const *sample, int priority, int volume, signed short panloc, int id);
int Set_Sound_Vol(int volume);
int Set_Score_Vol(int volume);
void Fade_Sample(int handle, int ticks);
int Get_Free_Sample_Handle(int priority);
int Get_Digi_Handle(void);
long Sample_Length(void const *sample);
void Restore_Sound_Buffers (void);
BOOL Set_Primary_Buffer_Format(void);
BOOL Start_Primary_Sound_Buffer (BOOL forced);
void Stop_Primary_Sound_Buffer (void);
/*
** Function to call if we detect focus loss
*/
extern void (*Audio_Focus_Loss_Function)(void);
extern int Misc;
extern SFX_Type SoundType;
extern Sample_Type SampleType;
extern CRITICAL_SECTION GlobalAudioCriticalSection;

Binary file not shown.

View File

@@ -0,0 +1,374 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Audio Library *
;* *
;* File Name : AUDUNCMP.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : March 14, 1995 *
;* *
;* Last Update : June 26, 1995 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Decompress_Frame_Lock -- locks the JLB audio decompression code *
;* Decompress_Frame_Unlock -- Unlocks the JLB audio compression code *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
CODESEG
DPMI_INTR equ 31h
LABEL LockedCodeStart BYTE
CODE_2BIT EQU 0
CODE_4BIT EQU 1
CODE_RAW EQU 2
CODE_SILENCE EQU 3
MAGICNUMBER EQU 00000DEAFh
MAGICNUMBER2 EQU 0BABEBABEh
_2bitdecode DB -2,-1,0,1
_4bitdecode DB -9,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8
;***************************************************************************
;* DECOMPRESS_FRAME -- Uncompresses a WW compressed audio frame *
;* *
;* INPUT: void * source - pointer to encoded audio data *
;* void * dest - pointer to decompression area *
;* long size - the maximum size of destination buffer *
;* *
;* OUTPUT: long - the number of bytes we uncompressed *
;* *
;* PROTO: long Decompress_Frame(void *, void *, long); *
;* *
;* HISTORY: *
;* 03/14/1995 PWG : Created. *
;*=========================================================================*
GLOBAL C Decompress_Frame:NEAR
PROC Decompress_Frame C NEAR USES ebx ecx edx esi edi
ARG source:DWORD
ARG dest:DWORD
ARG count:DWORD
LOCAL previous:BYTE
LOCAL incount:DWORD
pushfd
cld
mov [incount],0 ;Bytes read from source
; Source, Dest and count must be valid.
cmp [source],0
je ??fini
cmp [dest],0
je ??fini
cmp [count],0
je ??fini
mov esi,[source] ;Pointer to source data.
mov edi,[dest] ;Pointer to destination data.
mov ecx,[count] ;Number of bytes to fill dest buffer.
mov dl,080h ;Previous sample (starting value).
??mainloop:
cmp ecx,0 ;If dest full then exit
jle ??fini
xor eax,eax
mov al,[esi] ;Get code byte
inc [incount]
inc esi
shl eax,2 ;AH contains code.
shr al,2 ;AL contains sub-code data.
cmp ah,CODE_RAW ;Raw sequence?
jne short ??try4bit
; The code contains either a 5 bit delta or a count of
; raw samples to dump out.
test al,00100000b
je short ??justraw
; The lower 5 bits are actually a signed delta.
; Sign extend the delta and add it to the stream.
shl al,3
sar al,3
add dl,al
mov [edi],dl
dec ecx
inc edi
jmp ??mainloop
; The lower 5 bits hold a count of the number of raw
; samples that follow this code. Dump these samples to
; the output buffer.
??justraw:
mov ebx,ecx
xor ah,ah
inc al
mov ecx,eax
shr ecx,1
rep movsw
adc ecx,ecx
rep movsb
mov ecx,ebx
add [incount],eax
sub ecx,eax
dec edi
mov dl,[edi] ;Set "previous" value.
inc edi
jmp ??mainloop
; Check to see if this is a 4 bit delta code sequence.
??try4bit:
inc al ;Following codes use AL+1
cmp ah,CODE_4BIT
jne short ??try2bit
; A sequence of 4bit deltas follow. AL equals the
; number of nibble packed delta bytes to process.
??bit4loop:
mov ah,[esi] ;Fetch nibble packed delta codes
mov bl,ah
inc [incount]
inc esi
; Add first delta to 'previous' sample already in DL.
and ebx,00001111b
add dl,[_4bitdecode+ebx]
pushfd
cmp [_4bitdecode+ebx],0
jl short ??neg1
popfd
jnc short ??ok1
mov dl,0FFh
jmp short ??ok1
??neg1:
popfd
jc short ??ok1
xor dl,dl
??ok1:
mov dh,dl ;DH now holds new 'previous' sample.
mov bl,ah
shr bl,4
add dh,[_4bitdecode+ebx]
pushfd
cmp [_4bitdecode+ebx],0
jl short ??neg2
popfd
jnc short ??ok2
mov dh,0FFh
jmp short ??ok2
??neg2:
popfd
jc short ??ok2
xor dh,dh
??ok2:
mov [edi],dx ;Output the two sample bytes
sub ecx,2
add edi,2
; Put the correct 'previous' sample in DL where it belongs.
mov dl,dh
; If there are more deltas to process then loop back.
dec al
jnz short ??bit4loop
jmp ??mainloop
; Check to see if 2 bit deltas need to be processed.
??try2bit:
cmp ah,CODE_2BIT
jne ??zerodelta
; A sequence of 2bit deltas follow. AL equals the number of
; packed delta bytes to process.
??bit2loop:
mov ah,[esi] ;Fetch packed delat codes
inc [incount]
inc esi
; Add first delta to 'previous' sample already in DL.
mov bl,ah
and ebx,000011b
add dl,[_2bitdecode+ebx]
pushfd
cmp [_2bitdecode+ebx],0
jl short ??neg3
popfd
jnc short ??ok3
mov dl,0FFh
jmp short ??ok3
??neg3:
popfd
jc short ??ok3
xor dl,dl
??ok3:
mov dh,dl
ror edx,8
mov bl,ah
shr ebx,2
and bl,00000011b
add dl,[_2bitdecode+ebx]
pushfd
cmp [_2bitdecode+ebx],0
jl short ??neg4
popfd
jnc short ??ok4
mov dl,0FFh
jmp short ??ok4
??neg4:
popfd
jc short ??ok4
xor dl,dl
??ok4:
mov dh,dl
ror edx,8
mov bl,ah
shr ebx,4
and bl,00000011b
add dl,[_2bitdecode+ebx]
pushfd
cmp [_2bitdecode+ebx],0
jl short ??neg5
popfd
jnc short ??ok5
mov dl,0FFh
jmp short ??ok5
??neg5:
popfd
jc short ??ok5
xor dl,dl
??ok5:
mov dh,dl
ror edx,8
mov bl,ah
shr ebx,6
and bl,00000011b
add dl,[_2bitdecode+ebx]
pushfd
cmp [_2bitdecode+ebx],0
jl short ??neg6
popfd
jnc short ??ok6
mov dl,0FFh
jmp short ??ok6
??neg6:
popfd
jc short ??ok6
xor dl,dl
??ok6:
ror edx,8
mov [edi],edx ;Output two sample bytes
sub ecx,4
add edi,4
; Put the correct 'previous' sample in DL where it belongs.
rol edx,8
; If there are more deltas to process then loop back.
dec al
jnz ??bit2loop
jmp ??mainloop
; There is a run of zero deltas. Zero deltas merely duplicate
; the 'previous' sample the requested number of times.
??zerodelta:
xor ebx,ebx
mov bl,al
mov al,dl
sub ecx,ebx
xchg ecx,ebx
rep stosb
mov ecx,ebx
jmp ??mainloop
??fini:
popfd
mov eax,[incount]
ret
ENDP Decompress_Frame
LABEL LockedCodeEnd BYTE
END

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/*=========================================================================*/
/* The following prototypes are for the file: SOUNDIO.CPP */
/*=========================================================================*/
short Decompress_Frame(void * source, void * dest, short size);
int __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback);
int __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback);
int __cdecl File_Stream_Sample(char const *filename);
int __cdecl File_Stream_Sample_Vol(char const *filename, int volume);
void __cdecl _saveregs _loadds Sound_Callback(void);
void __cdecl far _saveregs _loadds maintenance_callback(void);
void __cdecl Load_Sample(char const *filename);
long __cdecl Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);
long __cdecl Sample_Read(int fh, void *buffer, long size);
void __cdecl Free_Sample(void const *sample);
BOOL __cdecl Sound_Init(int sfx, int score, int sample);
void far VQA_TimerCallback(void);
BOOL Audio_Init(int sample, int address, int inter, int dma);
void __cdecl Sound_End(void);
void __cdecl Stop_Sample(int handle);
BOOL __cdecl Sample_Status(int handle);
BOOL __cdecl Is_Sample_Playing(void const * sample);
void __cdecl Stop_Sample_Playing(void const * sample);
int __cdecl Play_Sample(void const *sample);
int __cdecl Play_Sample_Vol(void const *sample, int priority, int volume);
int __cdecl Set_Sound_Vol(int volume);
int __cdecl Set_Score_Vol(int volume);
void __cdecl Fade_Sample(int handle, int ticks);

File diff suppressed because it is too large Load Diff

186
WIN32LIB/AUDIO/OLD/MAKEFILE Normal file
View File

@@ -0,0 +1,186 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WIN32LIB path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef %WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef %WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef %WATCOM
!error WATCOM Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = AUDIO
PROJ_DIR = $(%WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(%WIN32LIB)\lib
!include $(%WIN32LIB)\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = &
soundio.obj &
soundint.obj &
soundlck.obj &
soscodec.obj &
olsosdec.obj &
auduncmp.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.asm: $(PROJ_DIR)
.c: $(PROJ_DIR)
.cpp: $(PROJ_DIR)
.h: $(PROJ_DIR)
.obj: $(PROJ_DIR)
.lib: $(%WIN32LIB)\lib
.exe: $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = wcc386
CPP_CMD = wpp386
LIB_CMD = wlib
LINK_CMD = wlink
ASM_CMD = tasm
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(%WIN32LIB)\LIB;$(%WATCOM)\LIB
INCLUDEPATH = $(%WIN32LIB)\INCLUDE;$(%WATCOM)\H
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(C_CMD) $(CC_CFG) $<
.cpp.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\$^*.cpp
.asm.obj: $(%WIN32LIB)\project.cfg
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib .SYMBOLIC
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc
copy *.lib $(%WIN32LIB)\lib
copy *.h $(%WIN32LIB)\include
copy *.inc $(%WIN32LIB)\include
copy *.cpp $(%WIN32LIB)\srcdebug
copy *.asm $(%WIN32LIB)\srcdebug
copy *.lib $(%WIN32LIB)\lib
$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc
#---------------------------------------------------------------------------
# Objects now have a link file which is NOT generated everytime. Instead
# it just has its own dependacy rule.
#---------------------------------------------------------------------------
objects.lbc : $(OBJECTS)
%create $^@
for %index in ($(OBJECTS)) do %append $^@ +%index
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(%WWVCS)\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..
copy *.386 test
#**************************** End of makefile ******************************

View File

@@ -0,0 +1,177 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WWFLAT path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
.AUTODEPEND
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef COMPILER
!error COMPILER Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = audio
PROJ_DIR = $(WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(WIN32LIB)\lib
!include $(WIN32LIB)\\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = \
soundio.obj \
soundint.obj \
soundlck.obj \
soscodec.obj \
auduncmp.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.path.asm = $(PROJ_DIR)
.path.c = $(PROJ_DIR)
.path.cpp = $(PROJ_DIR)
.path.h = $(PROJ_DIR)
.path.obj = $(PROJ_DIR)
.path.lib = $(WIN32LIB)\lib
.path.exe = $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = bcc32
CPP_CMD = bcc32
LIB_CMD = tlib
LINK_CMD = tlink32
ASM_CMD = tasm32
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(WIN32LIB)\LIB;$(COMPILER)\LIB
INCLUDEPATH = $(WIN32LIB)\INCLUDE;$(COMPILER)\INCLUDE
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj:
$(C_CMD) $(CC_CFG) $<
.cpp.obj:
$(CPP_CMD) $(CC_CFG) $<
.asm.obj:
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS)
copy *.h $(WIN32LIB)\\include
copy *.inc $(WIN32LIB)\\include
copy *.cpp $(WIN32LIB)\\srcdebug
copy *.asm $(WIN32LIB)\\srcdebug
$(LIB_CMD) $< $(LIB_CFG) @&&|
+-soundio.obj &
+-soundint.obj &
+-soundlck.obj &
+-soscodec.obj &
+-auduncmp.obj
|
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(WWVCS)\\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..

View File

@@ -0,0 +1,177 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WWFLAT path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
.AUTODEPEND
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef COMPILER
!error COMPILER Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = audio
PROJ_DIR = $(WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(WIN32LIB)\lib
!include $(WIN32LIB)\\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = \
soundio.obj \
soundint.obj \
soundlck.obj \
soscodec.obj \
auduncmp.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.path.asm = $(PROJ_DIR)
.path.c = $(PROJ_DIR)
.path.cpp = $(PROJ_DIR)
.path.h = $(PROJ_DIR)
.path.obj = $(PROJ_DIR)
.path.lib = $(WIN32LIB)\lib
.path.exe = $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = bcc32
CPP_CMD = bcc32
LIB_CMD = tlib
LINK_CMD = tlink32
ASM_CMD = tasm32
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(WIN32LIB)\LIB;$(COMPILER)\LIB
INCLUDEPATH = $(WIN32LIB)\INCLUDE;$(COMPILER)\INCLUDE
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj:
$(C_CMD) $(CC_CFG) $<
.cpp.obj:
$(CPP_CMD) $(CC_CFG) $<
.asm.obj:
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS)
copy *.h $(WIN32LIB)\\include
copy *.inc $(WIN32LIB)\\include
copy *.cpp $(WIN32LIB)\\srcdebug
copy *.asm $(WIN32LIB)\\srcdebug
$(LIB_CMD) $< $(LIB_CFG) @&&|
+-soundio.obj &
+-soundint.obj &
+-soundlck.obj &
+-soscodec.obj &
+-auduncmp.obj
|
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(WWVCS)\\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..

View File

@@ -0,0 +1,59 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
;
;****************************************************************************
;* bNybbleTablexxxx - ADPCM Lookup table for nybbles
;****************************************************************************
align 4
bNybbleTableLow DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
align 4
bNybbleTableHigh DB 00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2
DB 01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2
DB 02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2
DB 03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2
DB 04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2
DB 05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2
DB 06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2
DB 07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2
DB 08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2
DB 09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2
DB 0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2
DB 0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2
DB 0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2
DB 0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2
DB 0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2
DB 0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2

View File

@@ -0,0 +1,755 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
;
;****************************************************************************
;*
;* Copyright (c) 1994, HMI, INC. All Rights Reserved
;*
;*---------------------------------------------------------------------------
;*
;* FILE
;* soscodec.asm
;*
;* DESCRIPTION
;* HMI SOS ADPCM compression/decompression.
;*
;* PROGRAMMER
;* Nick Skrepetos
;* Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)
;* Bill Petro (Added stereo support)
;* DATE
;* Febuary 15, 1995
;*
;*---------------------------------------------------------------------------
;*
;* PUBLIC
;*
;****************************************************************************
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
DPMI_INTR equ 31h
IF_LOCKED_PM_CODE equ 1h ; Locked PM code for DPMI.
IF_LOCKED_PM_DATA equ 2h ; Locked PM code for DPMI.
STRUC sCompInfo
lpSource DD ? ;Compressed data pointer
lpDest DD ? ;Uncompressed data pointer
dwCompSize DD ? ;Compressed size
dwUnCompSize DD ? ;Uncompressed size
dwSampleIndex DD ? ;Index into sample
dwPredicted DD ? ;Next predicted value
dwDifference DD ? ;Difference from last sample
wCodeBuf DW ? ;Holds 2 nibbles for decompression
wCode DW ? ;Current 4 bit code
wStep DW ? ;Step value in table
wIndex DW ? ;Index into step table
dwSampleIndex2 DD ? ;Index into sample
dwPredicted2 DD ? ;Next predicted value
dwDifference2 DD ? ;Difference from last sample
wCodeBuf2 DW ? ;Holds 2 nibbles for decompression
wCode2 DW ? ;Current 4 bit code
wStep2 DW ? ;Step value in table
wIndex2 DW ? ;Index into step table
wBitSize DW ? ;Bit size for decompression
wChannels DW ? ;number of channels
ENDS sCompInfo
DATASEG
InitFlags DD 0 ; Flags to indicate what has been initialized.
LABEL LockedDataStart BYTE
;* Index table for stepping into step table
wCODECIndexTab DW -1,-1,-1,-1,2,4,6,8
DW -1,-1,-1,-1,2,4,6,8
;Lookup table of replacement values
;The actual sound value is replaced with an index to lookup in this table
;The index only takes up a nibble(4bits) and represents an int(16bits)
;Essentially:
;Get a value
;compare it with the value before it
;find closest value in table and store the index into the table
;if i'm going down then negitize it
;go to next byte.
;Theory for stereo:
;1)handle stereo and mono in two seperate loops. cleaner...
;start at byte 0 and skip every other byte(or word) both write and read
;when we get done
; set start byte to 1 and do it again
;This table essentialy round off to closes values in 3 distinct bands
; precalculated and optimized(i guess) for human hearing.
wCODECStepTab DW 7, 8, 9, 10, 11, 12, 13,14
DW 16, 17, 19, 21, 23, 25, 28, 31
DW 34, 37, 41, 45, 50, 55, 60, 66
DW 73, 80, 88, 97, 107, 118, 130, 143
DW 157, 173, 190, 209, 230, 253, 279, 307
DW 337, 371, 408, 449, 494, 544, 598, 658
DW 724, 796, 876, 963, 1060, 1166, 1282, 1411
DW 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024
DW 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484
DW 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899
DW 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794
DW 32767
;dwCODECByteIndex DD 0 ; this is when to stop compressing
;dwCODECTempStep DD 0 ; tempory storage for step value
;wCODECMask DW 0 ; Current mask
LABEL LockedDataEnd BYTE
CODESEG
LABEL LockedCodeStart BYTE
;****************************************************************************
;*
;* NAME
;* sosCODECInitStream - Initialize compression stream.
;*
;* SYNOPSIS
;* sosCODECInitStream(CompInfo)
;*
;* void sosCODECInitStream(_SOS_COMPRESS_INFO *);
;*
;* FUNCTION
;* Initialize compression stream for compression and decompression.
;*
;* INPUTS
;* CompInfo - Compression information structure.
;*
;* RESULT
;* NONE
;*
;****************************************************************************
GLOBAL C sosCODECInitStream:NEAR
PROC sosCODECInitStream C NEAR
ARG sSOSInfo:NEAR PTR
mov eax,[sSOSInfo]
mov [(sCompInfo eax).wIndex],0 ; starting index 0
mov [(sCompInfo eax).wStep],7 ; start with a step of 7
mov [(sCompInfo eax).dwPredicted],0 ; no predicted value
mov [(sCompInfo eax).dwSampleIndex],0 ;start at head of index
mov [(sCompInfo eax).wIndex2],0 ; starting index 0
mov [(sCompInfo eax).wStep2],7 ; start with a step of 7
mov [(sCompInfo eax).dwPredicted2],0 ; no predicted value
mov [(sCompInfo eax).dwSampleIndex2],0 ;start at head of index
ret
ENDP sosCODECInitStream
;****************************************************************************
;*
;* NAME
;* sosCODECDecompressData - Decompress audio data.
;*
;* SYNOPSIS
;* Size = sosCODECDecompressData(CompInfo, NumBytes)
;*
;* long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);
;*
;* FUNCTION
;* Decompress data from a 4:1 ADPCM compressed stream. The number of
;* bytes decompressed is returned.
;*
;* INPUTS
;* CompInfo - Compress information structure.
;* NumBytes - Number of bytes to compress.
;*
;* RESULT
;* Size - Size of decompressed data.
;*
;****************************************************************************
GLOBAL C General_sosCODECDecompressData:NEAR
PROC General_sosCODECDecompressData C NEAR
ARG sSOSInfo:NEAR PTR
ARG wBytes:DWORD
local dwCODECBytesProcessed:dword ;bytes to decompress
local dwCODECByteIndex:dword ;this is when to stop compressing
; these need to be local if the function is to be reenterant
push esi
push edi
push ebx
push ecx
push edx
;*---------------------------------------------------------------------------
;* Initialize
;*---------------------------------------------------------------------------
mov ebx,[sSOSInfo]
mov eax,[wBytes]
mov [dwCODECBytesProcessed],eax
mov [(sCompInfo ebx).dwSampleIndex],0 ;start at head of index
mov [(sCompInfo ebx).dwSampleIndex2],0 ;start at head of index
;Check for 16 bit decompression
cmp [(sCompInfo ebx).wBitSize],16
jne short ??skipByteDivide
shr eax,1 ;Divide size by two
??skipByteDivide:
mov [dwCODECByteIndex],eax
mov esi,[(sCompInfo ebx).lpSource]
mov edi,[(sCompInfo ebx).lpDest]
cmp [(sCompInfo ebx).wChannels],2 ;stereo check
je ??mainloopl ;do left side first
; Determine if sample index is even or odd. This will determine
; if we need to get a new token or not.
;---------------------------------------------------------------------------
;Main Mono Loop
;---------------------------------------------------------------------------
??mainloop:
test [(sCompInfo ebx).dwSampleIndex],1 ;odd ??
je short ??fetchToken ; if so get new token
xor eax,eax ;else shift int codebuf
mov ax,[(sCompInfo ebx).wCodeBuf] ;ored with Code
shr eax,4
and eax,000Fh
mov [(sCompInfo ebx).wCode],ax
jmp short ??calcDifference
??fetchToken:
xor eax,eax ;get a new token
mov al,[esi] ;put in codebuf
mov [(sCompInfo ebx).wCodeBuf],ax
inc esi
and eax,000Fh
mov [(sCompInfo ebx).wCode],ax ;and then code
??calcDifference:
mov [(sCompInfo ebx).dwDifference],0 ;reset diff
xor ecx,ecx
mov cx,[(sCompInfo ebx).wStep] ;cx is step value
test eax,4 ;Check for wCode & 4
je short ??no4
add [(sCompInfo ebx).dwDifference],ecx ;Add wStep
??no4:
test eax,2 ;Check for wCode & 2
je short ??no2
mov edx,ecx ;Add wStep >> 1
shr edx,1
add [(sCompInfo ebx).dwDifference],edx
??no2:
test eax,1 ;Check for wCode & 1
je short ??no1
mov edx,ecx ;Add wStep >> 2
shr edx,2
add [(sCompInfo ebx).dwDifference],edx
??no1:
mov edx,ecx ;Add in wStep >> 3
shr edx,3
add [(sCompInfo ebx).dwDifference],edx
test eax,8 ;Check for wCode & 8
je short ??no8
neg [(sCompInfo ebx).dwDifference] ;Negate diff
??no8:
; add difference to predicted value.
mov eax,[(sCompInfo ebx).dwPredicted]
add eax,[(sCompInfo ebx).dwDifference]
; make sure there is no under or overflow.
cmp eax,7FFFh
jl short ??noOverflow
mov eax,7FFFh
??noOverflow:
cmp eax,0FFFF8000h
jg short ??noUnderflow
mov eax,0FFFF8000h
??noUnderflow:
mov [(sCompInfo ebx).dwPredicted],eax
cmp [(sCompInfo ebx).wBitSize],16
jne short ??output8Bit
mov [edi],ax ;Output 16bit sample
add edi,2
jmp short ??adjustIndex
??output8Bit:
; output 8 bit sample
xor ah,80h
mov [edi],ah
inc edi
??adjustIndex:
xor ecx,ecx
mov cx,[(sCompInfo ebx).wCode]
xor eax,eax
shl ecx,1
mov ax,[wCODECIndexTab + ecx]
add [(sCompInfo ebx).wIndex],ax ;check if wIndex < 0
cmp [(sCompInfo ebx).wIndex],8000h
jb short ??checkOverflow
mov [(sCompInfo ebx).wIndex],0 ;reset index to zero
jmp short ??adjustStep
??checkOverflow:
cmp [(sCompInfo ebx).wIndex],88 ;check if wIndex > 88
jbe short ??adjustStep
mov [(sCompInfo ebx).wIndex],88 ;reset index to 88
??adjustStep:
; fetch wIndex so we can fetch new step value
xor ecx,ecx
mov cx,[(sCompInfo ebx).wIndex]
xor eax,eax
shl ecx,1
mov ax,[wCODECStepTab + ecx]
; advance index and store step value
add [(sCompInfo ebx).dwSampleIndex],1
mov [(sCompInfo ebx).wStep],ax
; decrement bytes processed and loop back.
dec [dwCODECByteIndex]
jne ??mainloop
jmp ??exitout
;--------------------------------------------------------------------------
;Left Channel Start
;--------------------------------------------------------------------------
??mainloopl:
test [(sCompInfo ebx).dwSampleIndex],1
je short ??fetchTokenl
xor eax,eax
mov ax,[(sCompInfo ebx).wCodeBuf]
shr eax,4
and eax,000Fh
mov [(sCompInfo ebx).wCode],ax
jmp short ??calcDifferencel
??fetchTokenl:
xor eax,eax
mov al,[esi]
mov [(sCompInfo ebx).wCodeBuf],ax
add esi,2 ;2 for stereo
and eax,000Fh
mov [(sCompInfo ebx).wCode],ax
??calcDifferencel:
; reset difference
mov [(sCompInfo ebx).dwDifference],0
xor ecx,ecx
mov cx,[(sCompInfo ebx).wStep]
test eax,4 ;Check for wCode & 4
je short ??no4l
add [(sCompInfo ebx).dwDifference],ecx ;Add wStep
??no4l:
test eax,2 ;Check for wCode & 2
je short ??no2l
mov edx,ecx ;Add wStep >> 1
shr edx,1
add [(sCompInfo ebx).dwDifference],edx
??no2l:
test eax,1 ;Check for wCode & 1
je short ??no1l
mov edx,ecx ;Add wStep >> 2
shr edx,2
add [(sCompInfo ebx).dwDifference],edx
??no1l:
mov edx,ecx ;Add in wStep >> 3
shr edx,3
add [(sCompInfo ebx).dwDifference],edx
test eax,8 ;Check for wCode & 8
je short ??no8l
neg [(sCompInfo ebx).dwDifference] ;Negate diff
??no8l:
; add difference to predicted value.
mov eax,[(sCompInfo ebx).dwPredicted]
add eax,[(sCompInfo ebx).dwDifference]
; make sure there is no under or overflow.
cmp eax,7FFFh
jl short ??noOverflowl
mov eax,7FFFh
??noOverflowl:
cmp eax,0FFFF8000h
jg short ??noUnderflowl
mov eax,0FFFF8000h
??noUnderflowl:
mov [(sCompInfo ebx).dwPredicted],eax
cmp [(sCompInfo ebx).wBitSize],16
jne short ??output8Bitl
mov [edi],ax ;Output 16bit sample
add edi,4 ;4 for stereo
jmp short ??adjustIndexl
??output8Bitl:
; output 8 bit sample
xor ah,80h
mov [edi],ah
add edi,2 ;2 for stereo
??adjustIndexl:
xor ecx,ecx
mov cx,[(sCompInfo ebx).wCode]
xor eax,eax
shl ecx,1
mov ax,[wCODECIndexTab + ecx]
add [(sCompInfo ebx).wIndex],ax
; check if wIndex < 0
cmp [(sCompInfo ebx).wIndex],8000h
jb short ??checkOverflowl
mov [(sCompInfo ebx).wIndex],0
jmp short ??adjustStepl ;reset index to zero
??checkOverflowl:
cmp [(sCompInfo ebx).wIndex],88 ; check if wIndex > 88
jbe short ??adjustStepl
mov [(sCompInfo ebx).wIndex],88 ; reset index to 88
??adjustStepl:
; fetch wIndex so we can fetch new step value
xor ecx,ecx
mov cx,[(sCompInfo ebx).wIndex]
xor eax,eax
shl ecx,1
mov ax,[wCODECStepTab + ecx]
; advance index and store step value
add [(sCompInfo ebx).dwSampleIndex],1
mov [(sCompInfo ebx).wStep],ax
; decrement bytes processed and loop back.
sub [dwCODECByteIndex],2
jne ??mainloopl
;----------------------------------------------------------------------------
; Right Side Setup
;----------------------------------------------------------------------------
mov eax,[wBytes]
mov [dwCODECBytesProcessed],eax
mov esi,[(sCompInfo ebx).lpSource]
mov edi,[(sCompInfo ebx).lpDest]
inc esi ; skip left channel
inc edi ; skip left channel
cmp [(sCompInfo ebx).wBitSize],16 ;16 bit ??
je short ??doByteDivide
mov [dwCODECByteIndex],eax
jmp short ??mainloopr
??doByteDivide:
shr eax,1 ;Divide size by two
inc edi ; 16 bit so skip 1 more
mov [dwCODECByteIndex],eax
;--------------------------------------------------------------------------
;Right Channel Start
;--------------------------------------------------------------------------
??mainloopr:
test [(sCompInfo ebx).dwSampleIndex2],1
je short ??fetchTokenr
xor eax,eax
mov ax,[(sCompInfo ebx).wCodeBuf2]
shr eax,4
and eax,000Fh
mov [(sCompInfo ebx).wCode2],ax
jmp short ??calcDifferencer
??fetchTokenr:
xor eax,eax
mov al,[esi]
mov [(sCompInfo ebx).wCodeBuf2],ax
add esi,2 ;2 for stereo
and eax,000Fh
mov [(sCompInfo ebx).wCode2],ax
??calcDifferencer:
; reset difference
mov [(sCompInfo ebx).dwDifference2],0
xor ecx,ecx
mov cx,[(sCompInfo ebx).wStep2]
test eax,4 ;Check for wCode & 4
je short ??no4r
add [(sCompInfo ebx).dwDifference2],ecx ;Add wStep
??no4r:
test eax,2 ;Check for wCode & 2
je short ??no2r
mov edx,ecx ;Add wStep >> 1
shr edx,1
add [(sCompInfo ebx).dwDifference2],edx
??no2r:
test eax,1 ;Check for wCode & 1
je short ??no1r
mov edx,ecx ;Add wStep >> 2
shr edx,2
add [(sCompInfo ebx).dwDifference2],edx
??no1r:
mov edx,ecx ;Add in wStep >> 3
shr edx,3
add [(sCompInfo ebx).dwDifference2],edx
test eax,8 ;Check for wCode & 8
je short ??no8r
neg [(sCompInfo ebx).dwDifference2] ;Negate diff
??no8r:
; add difference to predicted value.
mov eax,[(sCompInfo ebx).dwPredicted2]
add eax,[(sCompInfo ebx).dwDifference2]
cmp eax,7FFFh
jl short ??noOverflowr
mov eax,7FFFh
??noOverflowr:
cmp eax,0FFFF8000h
jg short ??noUnderflowr
mov eax,0FFFF8000h
??noUnderflowr:
mov [(sCompInfo ebx).dwPredicted2],eax
cmp [(sCompInfo ebx).wBitSize],16
jne short ??output8Bitr
mov [edi],ax ;Output 16bit sample
add edi,4 ;4 for stereo ***
jmp short ??adjustIndexr
??output8Bitr:
; output 8 bit sample
xor ah,80h
mov [edi],ah
add edi,2 ;2 for stereo
??adjustIndexr:
xor ecx,ecx
mov cx,[(sCompInfo ebx).wCode2]
xor eax,eax
shl ecx,1
mov ax,[wCODECIndexTab + ecx]
add [(sCompInfo ebx).wIndex2],ax
; check if wIndex < 0
cmp [(sCompInfo ebx).wIndex2],8000h
jb short ??checkOverflowr
; reset index to zero
mov [(sCompInfo ebx).wIndex2],0
jmp short ??adjustStepr
??checkOverflowr:
; check if wIndex > 88
cmp [(sCompInfo ebx).wIndex2],88
jbe short ??adjustStepr
mov [(sCompInfo ebx).wIndex2],88 ; reset index to 88
??adjustStepr:
; fetch wIndex so we can fetch new step value
xor ecx,ecx
mov cx,[(sCompInfo ebx).wIndex2]
xor eax,eax
shl ecx,1
mov ax,[wCODECStepTab + ecx]
; advance index and store step value
add [(sCompInfo ebx).dwSampleIndex2],1
mov [(sCompInfo ebx).wStep2],ax
; decrement bytes processed and loop back.
sub [dwCODECByteIndex],2
jne ??mainloopr
??exitout:
; don't think we need this but just in case i'll leave it here!!
; mov [(sCompInfo ebx).lpSource],esi
; mov [(sCompInfo ebx).lpDest],edi
; set up return value for number of bytes processed.
mov eax,[dwCODECBytesProcessed]
pop edx
pop ecx
pop ebx
pop edi
pop esi
ret
ENDP General_sosCODECDecompressData
LABEL LockedCodeEnd BYTE
;***************************************************************************
;* sosCODEC_LOCK -- locks the JLB audio decompression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is lock sucessful, false otherwise *
;* *
;* PROTO: BOOL sosCODEC_Lock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL C sosCODEC_Lock:NEAR
PROC sosCODEC_Lock C NEAR USES ebx ecx edx esi edi
;
; Lock the code that is used by the sos decompression method.
;
mov eax,0600h ; function number.
mov ecx,OFFSET LockedCodeStart ; ecx must have start of memory.
mov edi,OFFSET LockedCodeEnd ; edi will have size of region in bytes.
shld ebx,ecx,16
sub edi, ecx
shld esi,edi,16
int DPMI_INTR ; do call.
jc ??error
or [InitFlags], IF_LOCKED_PM_CODE
;
; Lock the data used by the sos decompression method.
;
mov eax,0600h ; function number.
mov ecx,OFFSET LockedDataStart ; ecx must have start of memory.
mov edi,OFFSET LockedDataEnd ; edi will have size of region in bytes.
shld ebx,ecx,16
sub edi, ecx
shld esi,edi,16
int DPMI_INTR ; do call.
jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region.
or [InitFlags], IF_LOCKED_PM_DATA
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP sosCODEC_Lock
;***************************************************************************
;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is unlock sucessful, false otherwise *
;* *
;* PROTO: BOOL sosCODEC_Unlock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL C sosCODEC_Unlock:NEAR
PROC sosCODEC_Unlock C NEAR USES ebx ecx edx esi edi
test [InitFlags],IF_LOCKED_PM_CODE
jz ??code_not_locked
mov eax , 0601h
mov ecx,OFFSET LockedCodeStart ; ecx must have start of memory.
mov edi,OFFSET LockedCodeEnd ; edx will have size of region in bytes.
sub edi,ecx ; - figure size.
shld ebx , ecx , 16
shld esi , edi , 16
int DPMI_INTR ; do call.
jc ??error
??code_not_locked:
test [InitFlags],IF_LOCKED_PM_DATA
jz ??data_not_locked
mov ax,0601h ; set es to descriptor of data.
mov ecx,OFFSET LockedDataStart ; ecx must have start of memory.
mov edi,OFFSET LockedDataEnd ; edx will have size of region in bytes.
sub edi,ecx ; - figure size.
shld ebx , ecx , 16
shld esi , edi , 16
int DPMI_INTR ; do call.
jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region.
??data_not_locked:
mov [InitFlags],0
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP sosCODEC_Unlock
END

565
WIN32LIB/AUDIO/OLD/SOS.H Normal file
View File

@@ -0,0 +1,565 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sos.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOS_DEFINED
#define _SOS_DEFINED
#include "sosdefs.h"
#pragma pack(4)
// error definition for sound operating system
#define _SOS_ERR -1
// number of drivers allowed to be open at one time
#define _SOS_MAX_DRIVERS 5
// structure definition for the capabilities
typedef struct _tagCAPABILITIES
{
BYTE szDeviceName[ 32 ]; // device name
WORD wDeviceVersion; // device version
WORD wBitsPerSample; // bits per sound sample
WORD wChannels; // stereo/mono sound card
WORD wMinRate; // minimum rate
WORD wMaxRate; // maximum rate
WORD wMixerOnBoard; // board contains mixer
WORD wMixerFlags; // mixer capabilities
WORD wFlags; // miscellaneous flags
short far * lpPortList; // list of usable ports
short far * lpDMAList; // list of usable dma channels
short far * lpIRQList; // list of usable irq channels
short far * lpRateList; // list of usable rates, -1 if any in min to max
WORD fBackground; // foreground or background driver
WORD wDeviceID; // ID for the device
WORD wTimerID; // ID for the timer
} _SOS_CAPABILITIES;
// far pointer to the device capabilities structure
typedef _SOS_CAPABILITIES far * LPSOSDEVICECAPS;
// flag types for driver
#define _FLAGS_SIGNED 0x8000
// devices that can be loaded
#define _SOUND_BLASTER_8_MONO 0xe000
#define _SOUND_BLASTER_8_ST 0xe001
#define _SBPRO_8_ST _SOUND_BLASTER_8_ST
#define _SBPRO_8_MONO 0xe00f
#define _SOUND_MASTER_II_8_MONO 0xe002
#define _MV_PAS_8_MONO 0xe003
#define _MV_PAS_16_MONO 0xe004
#define _MV_PAS_8_ST 0xe005
#define _MV_PAS_16_ST 0xe006
#define _ADLIB_GOLD_8_ST 0xe007
#define _ADLIB_GOLD_16_ST 0xe008
#define _ADLIB_GOLD_8_MONO 0xe009
#define _ADLIB_GOLD_16_MONO 0xe00a
#define _MICROSOFT_8_MONO 0xe00b
#define _MICROSOFT_8_ST 0xe00c
#define _MICROSOFT_16_MONO 0xe00d
#define _MICROSOFT_16_ST 0xe00e
#define _SOUND_SOURCE_8_MONO_PC 0xe010
#define _SOUND_SOURCE_8_MONO_TANDY 0xe011
#define _GENERAL_PORT_8_MONO 0xe012
#define _GENERAL_PORT_8_MONO_R 0xe013
#define _SIERRA_8_MONO 0xe014
#define _SB16_8_MONO 0xe015
#define _SB16_8_ST 0xe016
#define _SB16_16_MONO 0xe017
#define _SB16_16_ST 0xe018
#define _ESS_AUDIODRIVE_8_MONO 0xe019
#define _ESS_AUDIODRIVE_8_ST 0xe01a
#define _ESS_AUDIODRIVE_16_MONO 0xe01b
#define _ESS_AUDIODRIVE_16_ST 0xe01c
#define _SOUNDSCAPE_8_MONO 0xe01d
#define _SOUNDSCAPE_8_ST 0xe01e
#define _SOUNDSCAPE_16_MONO 0xe01f
#define _SOUNDSCAPE_16_ST 0xe020
#define _RAP10_8_MONO 0xe021
#define _RAP10_16_MONO 0xe022
#define _GUS_8_MONO 0xe023
#define _GUS_8_ST 0xe024
#define _GUS_16_MONO 0xe025
#define _GUS_16_ST 0xe026
#define _GUS_MAX_8_MONO 0xe027
#define _GUS_MAX_8_ST 0xe028
#define _GUS_MAX_16_MONO 0xe029
#define _GUS_MAX_16_ST 0xe02a
#define _WAVEJAMMER_8_MONO 0xe02b
#define _WAVEJAMMER_8_ST 0xe02c
#define _WAVEJAMMER_16_MONO 0xe02d
#define _WAVEJAMMER_16_ST 0xe02e
#define _TEMPOCS_8_MONO 0xe02f
#define _TEMPOCS_8_ST 0xe030
#define _TEMPOCS_16_MONO 0xe031
#define _TEMPOCS_16_ST 0xe032
#define _WAVEJAMMERCD_8_MONO 0xe033
#define _WAVEJAMMERCD_8_ST 0xe034
#define _WAVEJAMMERCD_16_MONO 0xe035
#define _WAVEJAMMERCD_16_ST 0xe036
#define _SOUND_BLASTER_8_MONO_R 0xe050
#define _MICROSOFT_8_MONO_R 0xe051
#define _SOUND_MASTER_II_8_MONO_R 0xe052
#define _ADLIB_GOLD_8_MONO_R 0xe053
#define _MV_PAS_8_MONO_R 0xe054
#define _RAP10_8_MONO_R 0xe058
#define _RAP10_16_MONO_R 0xe059
#define _SB16_8_MONO_R 0xe05a
#define _SB16_8_ST_R 0xe05b
#define _SB16_16_MONO_R 0xe05c
#define _SB16_16_ST_R 0xe05d
#define _MV_PAS_16_MONO_R 0xe060
#define _SOUNDSCAPE_8_MONO_R 0xe061
#define _SOUNDSCAPE_8_ST_R 0xe062
#define _SOUNDSCAPE_16_MONO_R 0xe063
#define _SOUNDSCAPE_16_ST_R 0xe064
#define _ESS_AUDIODRIVE_8_MONO_R 0xe065
#define _ESS_AUDIODRIVE_8_ST_R 0xe066
#define _ESS_AUDIODRIVE_16_MONO_R 0xe067
#define _ESS_AUDIODRIVE_16_ST_R 0xe068
#define _SPEECH_THING_8_MONO 0xe090
#define _YAMAHA_8_MONO 0xe106
#define _INT_SPEAKER_8_MONO 0xe107
// call indexes for the loadable drivers
enum
{
_DRV_INIT,
_DRV_UNINIT,
_DRV_SETRATE,
_DRV_SETACTION,
_DRV_START,
_DRV_STOP,
_DRV_PAUSE,
_DRV_RESUME,
_DRV_CAPABILITIES,
_DRV_PLAY_FOREGROUND,
_DRV_GET_FILL_INFO,
_DRV_GET_CALL_FUNCTIONS,
_DRV_SET_CALL_FUNCTIONS
};
// fill info
typedef struct _tagFillInfo
{
LPSTR lpFillHandler; // pointer to fill handler
LPWORD lpDMAFillCount; // pointer to dma count
LPSTR lpSampleList; // pointer to sample list
LPWORD lpDMAMasterVolume; // pointer to dma count
} _SOS_FILL_INFO;
// caps info structure
typedef struct _tagCapsInfo
{
LPSTR lpPortList; // pointer to port list
LPSTR lpDMAList; // pointer to DMA list
LPSTR lpIRQList; // pointer to IRQ list
LPSTR lpRateList; // pointer to rate list
} _SOS_CAPS_INFO;
// maximum number of available voice
#define _MAX_VOICES 32
// structure definition
typedef struct _tagSAMPLE
{
LPSTR samplePtr; // pointer to data buffer
LPSTR sampleData; // pointer to active data
LPSTR sampleLoopPtr; // pointer for loop back
WORD sampleLength; // length of sample
WORD sampleIndex; // index into sample
WORD sampleLoopLength; // length of loop
WORD sampleBytesLeft; // bytes left to play in sample
WORD sampleLoopPoint; // byte count for loop point
WORD sampleLoopEndLength; // length of remaining chunk
short sampleFlags; // control sample
short sampleVolume; // volume control
short sampleID; // sample ID
short sampleChannel; // channel to play sample on
short sampleLoopCount; // loop count
short sampleLastFill; // last fill position
VOID ( far __cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample
WORD samplePitchAdd;
short samplePitchFraction;
short samplePort; // port to use for non-dma digitized
WORD sampleTotalBytes;
WORD sampleByteLength;
short samplePanLocation;
short samplePanSpeed;
short samplePanDirection;
short samplePanStart;
short samplePanEnd;
short sampleDelayBytes;
short sampleDelayRepeat;
WORD sampleADPCMPredicted;
short sampleADPCMIndex;
short sampleRootNoteMIDI;
WORD sampleTemp1;
} _SOS_SAMPLE;
// enumeration for left or right channel
enum
{
_LEFT_CHANNEL,
_RIGHT_CHANNEL,
_CENTER_CHANNEL,
_INTERLEAVED
};
// enumeration for foreground and background
enum
{
_FOREGROUND,
_BACKGROUND
};
// defines for the sample flags
#define _ACTIVE 0x8000
#define _LOOPING 0x4000
#define _FIRST_TIME 0x2000
#define _PENDING_RELEASE 0x1000
#define _CONTINUE_BLOCK 0x0800
#define _PITCH_SHIFT 0x0400
#define _PANNING 0x0200
#define _VOLUME 0x0100
#define _TRANSLATE16TO8 0x0080
#define _STAGE_LOOP 0x0040
#define _TRANSLATE8TO16 0x0020
#define _STEREOTOMONO 0x0010
// defines for the wParam flags
#define _SINGLE_SAMPLE 0x01
#define _SOS_DCAPS_AUTO_REINIT 0x01
#define _SOS_DCAPS_MPU_401 0x02
#define _SOS_DCAPS_OPL2 0x04
#define _SOS_DCAPS_OPL3 0x08
#define _SOS_DCAPS_OPL4 0x10
#define _SOS_DCAPS_WAVETABLE 0x20
#define _SOS_DCAPS_DL_SAMPLES 0x40
#define _SOS_DCAPS_FIFO_DEVICE 0x80
#define _SOS_DCAPS_ENV_NEEDED 0x100
#define _SOS_DCAPS_PSEUDO_DMA1 0x200
#define _SOS_DCAPS_SIGNED_DATA 0x8000
// file header structure
typedef struct
{
// name ID
BYTE szName[ 32 ];
// number of drivers in the file
WORD wDrivers;
// offset of first driver
WORD lOffset;
// size of the file
WORD lFileSize;
} _FILEHEADER;
// driver header structure
typedef struct
{
// name ID
BYTE szName[ 32 ];
// offset of next driver
WORD lNextDriver;
// size of current driver
WORD wSize;
// id for the current device
WORD wDeviceID;
// id for the type of DOS extender
WORD wExtenderType;
} _DRIVERHEADER;
// device hardware information
typedef struct
{
// port to be used
WORD wPort;
// irq to use
WORD wIRQ;
// dma channel to se
WORD wDMA;
// extra parameter
WORD wParam;
} _SOS_HARDWARE;
// structure definition for start sample
typedef struct
{
// pointer to sample
LPSTR lpSamplePtr;
// size of the sample
WORD dwSampleSize;
// number of times to loop the sample -1 is infinite
WORD wLoopCount;
// channel to play sample on
WORD wChannel;
// volume to play sample at
WORD wVolume;
// id for the sample
WORD wSampleID;
// far pointer to the callback function
VOID ( far __cdecl *lpCallback )( WORD, WORD, WORD );
// port to use if driver is a non-dma background driver
WORD wSamplePort;
// flags field
WORD wSampleFlags;
// total length of sample including loops, etc..
WORD dwSampleByteLength;
// loop point for the sample
WORD dwSampleLoopPoint;
WORD dwSampleLoopLength;
// pitch shifting components
WORD dwSamplePitchAdd;
WORD wSamplePitchFraction;
// pan components
WORD wSamplePanLocation;
WORD wSamplePanSpeed;
WORD wSamplePanDirection;
WORD wSamplePanStart;
WORD wSamplePanEnd;
// delay parts
WORD wSampleDelayBytes;
WORD wSampleDelayRepeat;
// compression components
WORD dwSampleADPCMPredicted;
WORD wSampleADPCMIndex;
// root note for pitch shifting
WORD wSampleRootNoteMIDI;
// filler for future upgrades
WORD dwSampleTemp1;
WORD dwSampleTemp2;
WORD dwSampleTemp3;
} _SOS_START_SAMPLE;
// structure for initializing a driver
typedef struct
{
WORD wBufferSize;
LPSTR lpBuffer;
BOOL wAllocateBuffer;
WORD wSampleRate;
WORD wParam;
LONG dwParam;
VOID ( far *lpFillHandler )( VOID );
LPSTR lpDriverMemory;
LPSTR lpDriverMemoryCS;
LPSTR lpTimerMemory;
LPSTR lpTimerMemoryCS;
WORD wTimerID;
WORD wPhysical;
} _SOS_INIT_DRIVER;
// define for the timer types to use
#define _SOS_NORMAL_TIMER 0x00
// enumeration for the timer types
enum
{
_TIMER_8_MONO = 0x1000,
_TIMER_8_ST,
_TIMER_16_MONO,
_TIMER_16_ST,
_TIMER_8_MONO_ULAW,
_TIMER_8_ST_ULAW,
_TIMER_16_MONO_ULAW,
_TIMER_16_ST_ULAW,
_TIMER_8_MONO_REC,
_TIMER_8_MONO_ULAW_REC,
_TIMER_UNDEFINED_1,
_TIMER_UNDEFINED_2,
_TIMER_UNDEFINED_3,
_TIMER_UNDEFINED_4,
_TIMER_UNDEFINED_5,
_TIMER_UNDEFINED_6,
_TIMER_UNDEFINED_7,
_TIMER_UNDEFINED_8,
_TIMER_UNDEFINED_9,
_TIMER_UNDEFINED_A,
_TIMER_UNDEFINED_B,
_TIMER_UNDEFINED_C,
_TIMER_UNDEFINED_D,
_TIMER_UNDEFINED_E,
_TIMER_UNDEFINED_F,
_TIMER_UNDEFINED_10,
_TIMER_UNDEFINED_11,
_TIMER_UNDEFINED_12,
_TIMER_UNDEFINED_13,
_TIMER_UNDEFINED_14,
_TIMER_UNDEFINED_15,
_TIMER_UNDEFINED_16,
_TIMER_8_SOUND_SOURCE,
_TIMER_8_SOUND_SOURCE_TANDY,
_TIMER_8_GENERAL_PORT,
_TIMER_8_GENERAL_PORT_REC
};
// define for no slots available
#define _ERR_NO_SLOTS ( WORD )-1
// error codes for the system
enum
{
_ERR_NO_ERROR,
_ERR_DRIVER_NOT_LOADED,
_ERR_INVALID_POINTER,
_ERR_DETECT_INITIALIZED,
_ERR_FAIL_ON_FILE_OPEN,
_ERR_MEMORY_FAIL,
_ERR_INVALID_DRIVER_ID,
_ERR_NO_DRIVER_FOUND,
_ERR_DETECTION_FAILURE,
_ERR_DRIVER_LOADED,
_ERR_INVALID_HANDLE,
_ERR_NO_HANDLES,
_ERR_PAUSED,
_ERR_NOT_PAUSED,
_ERR_INVALID_DATA,
_ERR_DRV_FILE_FAIL,
_ERR_INVALID_PORT,
_ERR_INVALID_IRQ,
_ERR_INVALID_DMA,
_ERR_INVALID_DMA_IRQ
};
// maximum number of timer events that can be registered
#define _TIMER_MAX_EVENTS 0x10
// flags for the debugging system
#define _SOS_DEBUG_NORMAL 0x0000
#define _SOS_DEBUG_NO_TIMER 0x0001
#define _SOS_TIMER_DPMI 0x0002
// define for types of DOS extenders
#define _SOS_RATIONAL 0x8000
#define _SOS_FLASHTECK 0x4000
// defines for the types of timers for different
// dos extenders
#define _SOS_TIMER_NEAR 0x8000
#define _SOS_TIMER_FAR 0x4000
// values for callback information
enum
{
_SAMPLE_PROCESSED,
_SAMPLE_LOOPING,
_SAMPLE_DONE
};
// define for special 18.2 callback rate to dos
#define _TIMER_DOS_RATE 0xff00
#pragma pack()
#pragma aux int_3 = "int 3"
#pragma pack( 1 )
typedef struct
{
unsigned region_size;
unsigned offset;
unsigned segment;
unsigned short number_available;
unsigned short number_used;
unsigned page0;
} EVDS_STRUCT;
typedef struct
{
unsigned region_size;
unsigned offset;
unsigned short segment;
unsigned short ID;
unsigned physical;
} VDS_STRUCT;
#pragma pack()
#include "sosdata.h"
#include "sosfnct.h"
#endif

View File

@@ -0,0 +1,724 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
;
;****************************************************************************
;*
;* Copyright (c) 1994, HMI, INC. All Rights Reserved
;*
;*---------------------------------------------------------------------------
;*
;* FILE
;* soscodec.asm
;*
;* DESCRIPTION
;* HMI SOS ADPCM compression/decompression.
;*
;* PROGRAMMER
;* Nick Skrepetos
;* Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)
;* Bill Petro (Added stereo support)
;* Jonathan Lanier
;*
;* DATE
;* Febuary 15, 1995
;*
;* LAST MODIFIED
;* 08/07/95 [jdl] - Rewrote/optimized sosCODECDecompressData
;*
;*---------------------------------------------------------------------------
;*
;* PUBLIC
;*
;****************************************************************************
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
DPMI_INTR equ 31h
IF_LOCKED_PM_CODE equ 1h ; Locked PM code for DPMI.
IF_LOCKED_PM_DATA equ 2h ; Locked PM code for DPMI.
STRUC sCompInfo
lpSource DD ? ;Compressed data pointer
lpDest DD ? ;Uncompressed data pointer
dwCompSize DD ? ;Compressed size
dwUnCompSize DD ? ;Uncompressed size
dwSampleIndex DD ? ;Index into sample
dwPredicted DD ? ;Next predicted value
dwDifference DD ? ;Difference from last sample
wCodeBuf DW ? ;Holds 2 nibbles for decompression
wCode DW ? ;Current 4 bit code
wStep DW ? ;Step value in table
wIndex DW ? ;Index into step table
dwSampleIndex2 DD ? ;Index into sample
dwPredicted2 DD ? ;Next predicted value
dwDifference2 DD ? ;Difference from last sample
wCodeBuf2 DW ? ;Holds 2 nibbles for decompression
wCode2 DW ? ;Current 4 bit code
wStep2 DW ? ;Step value in table
wIndex2 DW ? ;Index into step table
wBitSize DW ? ;Bit size for decompression
wChannels DW ? ;number of channels
ENDS sCompInfo
DATASEG
InitFlags DD 0 ; Flags to indicate what has been initialized.
LABEL LockedDataStart BYTE
;* Index table for stepping into step table
INCLUDE "difftb.inc"
INCLUDE "indextb.inc"
INCLUDE "nybbtb.inc"
LABEL LockedDataEnd BYTE
CODESEG
LABEL LockedCodeStart BYTE
;****************************************************************************
;*
;* NAME
;* sosCODECInitStream - Initialize compression stream.
;*
;* SYNOPSIS
;* sosCODECInitStream(CompInfo)
;*
;* void sosCODECInitStream(_SOS_COMPRESS_INFO *);
;*
;* FUNCTION
;* Initialize compression stream for compression and decompression.
;*
;* INPUTS
;* CompInfo - Compression information structure.
;*
;* RESULT
;* NONE
;*
;****************************************************************************
GLOBAL sosCODECInitStream:NEAR
PROC sosCODECInitStream C NEAR
ARG sSOSInfo:NEAR PTR
mov eax,[sSOSInfo]
mov [(sCompInfo eax).wIndex],0 ; starting index 0
mov [(sCompInfo eax).dwPredicted],0 ; no predicted value
mov [(sCompInfo eax).wIndex2],0 ; starting index 0
mov [(sCompInfo eax).dwPredicted2],0 ; no predicted value
ret
ENDP sosCODECInitStream
;****************************************************************************
;*
;* NAME
;* sosCODECDecompressData - Decompress audio data.
;*
;* SYNOPSIS
;* Size = sosCODECDecompressData(CompInfo, NumBytes)
;*
;* long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);
;*
;* FUNCTION
;* Decompress data from a 4:1 ADPCM compressed stream. The number of
;* bytes decompressed is returned.
;*
;* INPUTS
;* CompInfo - Compress information structure.
;* NumBytes - Number of bytes to decompress.
;*
;* RESULT
;* Size - Size of decompressed data.
;*
;*
;* NOTES
;* This routine has been optimized for pipelining on both
;* 486 and Pentium processors. Changing, inserting, or moving any
;* instructions will most likely slow down the code, in some cases by
;* as much as 20%. It can burst-decompress 16384 samples in about
;* 1940<34>s on a Pentium 90Mhz, and about 3960<36>s on a 486 66Mhz.
;* Instruction reordering could bring this down to below 1870<37>s on
;* the Pentium, but this would cause a great degradation in 486
;* performance. Since slow 486's are the reason this code was
;* written to be fast, it has been optimized for the Pentium only where
;* it would not degrade 486 performance. So, be careful when changing
;* ANY of this code, because it is very carefully balanced...
;****************************************************************************
GLOBAL C sosCODECDecompressData:NEAR
PROC sosCODECDecompressData C NEAR
ARG sSOSInfo:NEAR PTR
ARG wBytes:DWORD
push esi
push edi
push ebx
push ecx
push edx ;save all the regs
mov ebx,[sSOSInfo] ;get base of sCompInfo struct
mov cx,[(sCompInfo ebx).wBitSize] ;check the bit size
mov dx,[(sCompInfo ebx).wChannels] ;check the number of channels
;
;
; Determine the correct routine to use for decoding
; (for now only ADPCM 4:1 Mono 16-bit is implemented)
cmp cx,8
jne ??do16Bits
??do8Bits:
cmp dx,2
jne ??not8Stereo
; jmp ??decomp8Stereo
jmp ??byeBye
??not8Stereo:
cmp dx,1
jne ??byeBye
; jmp decomp8Mono
jmp ??byeBye
??do16Bits:
cmp cx,16
jne ??byeBye
cmp dx,2
jne ??not16Stereo
; jmp ??decomp16Stereo
jmp ??byeBye
??not16Stereo:
cmp dx,1
jne ??byeBye
push ebp
;
;
; 16 bit ADPCM 4:1 Mono pre-loop initialization
??decomp16Mono:
push ebx ;save struct base
xor edx,edx ;clear index
mov eax,[(sCompInfo ebx).dwPredicted] ;get last sample
mov dx,[(sCompInfo ebx).wIndex] ;get last index value
mov esi,[(sCompInfo ebx).lpSource] ;get source address
mov edi,[(sCompInfo ebx).lpDest] ;get dest address
mov ebp,[wBytes] ;get the number of dest. bytes
cmp ebp,16 ;less than 16? (less than 8 samples)
jl ??fixAlign16Mono0 ;if so, don't bother with alignment
;
;
; Check to see if we need to fix an alignment problem on the source buffer
; (non-aligned buffers are MUCH slower; if we're given a non-DWORD aligned
; source address, we do as many samples as needed to get to the nearest
; DWORD boundary, then finish the bulk as a DWORD-aligned decompress).
mov ebx,esi ;get source address
and ebx,03h ;check LSB
jnz ??fixalign16Mono ;if non-zero, need to align for
;warp speed
??fixAlign16Mono0:
push ebp ;save for later
shr ebp,4 ;divide by 16 for 16-bit,
;because we do 8 nybbles per loop,
;and there are two samples per
;byte, so there are n/16 iterations
;required
xor ebx,ebx ;clear our nybble index
or ebp,ebp ;set flags for EBP
jmp ??start16Mono ;start with test... don't go if
;we have zero bytes to do
??fixalign16Mono:
jmp [DWORD PTR dwMono16AlignJmpTable+ebx*4] ;do non-aligned first
align 4
??fixAlign16Mono1:
sub ebp,12 ;adjust # of dest. bytes
push ebp ;save it
shr ebp,4 ;divide by 16 to get samples/8
xor ebx,ebx ;clear our nybble index
inc ebp ;adjust ebp for loop
jmp ??finish16Mono6 ;borrow exit code to go through a
;piece of a loop
align 4
??fixAlign16Mono2:
sub ebp,8 ;adjust # of dest. bytes
push ebp ;save it
shr ebp,4 ;divide by 16 to get samples/8
xor ebx,ebx ;clear our nybble index
inc ebp ;adjust ebp for loop
jmp ??finish16Mono4 ;borrow exit code to go through a
;piece of a loop
align 4
??fixAlign16Mono3:
sub ebp,4 ;adjust # of dest. bytes
push ebp ;save it
shr ebp,4 ;divide by 16 to get samples/8
xor ebx,ebx ;clear our nybble index
inc ebp ;adjust ebp for loop
jmp ??finish16Mono2 ;borrow exit code to go through a
;piece of a loop
; "The Loop"
;
; Process 1st nybble
align 4
??loop16Mono:
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix1Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix1Smp16MonoU
??fixed1Smp16Mono:
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
mov [edi],ax ;save the sample
;
;
; Process 2nd nybble
??finish7Smp16Mono:
mov bl,ch ;get next 2 nybbles in ebx
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix2Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix2Smp16MonoU
??fixed2Smp16Mono:
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
mov [edi+02h],ax ;save the sample
shr ecx,16 ;move top four nybbles into bottom
;
;
; Process 3rd nybble
??finish6Smp16Mono:
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix3Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix3Smp16MonoU
??fixed3Smp16Mono:
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
mov [edi+04h],ax ;save the sample
;
;
; Process 4th nybble
??finish5Smp16Mono:
mov bl,cl
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix4Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix4Smp16MonoU
??fixed4Smp16Mono:
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
mov [edi+06h],ax ;save the sample
;
;
; Process 5th nybble
??finish4Smp16Mono:
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix5Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix5Smp16MonoU
??fixed5Smp16Mono:
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
mov [edi+08h],ax ;save the sample
;
;
; Process 6th nybble
??finish3Smp16Mono:
mov bl,ch
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix6Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix6Smp16MonoU
??fixed6Smp16Mono:
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
mov [edi+0Ah],ax ;save the sample
;
;
; Process 7th nybble
??finish2Smp16Mono:
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix7Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix7Smp16MonoU
??fixed7Smp16Mono:
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
mov [edi+0Ch],ax ;save the sample
;
;
; Process 8th nybble
??finish1Smp16Mono:
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix8Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix8Smp16MonoU
;
;
; Loop cleanup for next pass
??fixed8Smp16Mono:
mov [edi+0Eh],ax ;save the sample
add esi,04h ;bump esi to point to next longword
add edi,10h ;incr. the destination buffer ptr
dec ebp ;count down the number of samples/8
??start16Mono:
jng ??cleanup16Mono ;if done, clean up
mov ecx,[esi] ;get 4 nybbles in one whack (whee!)
mov bl,cl ;get next 2 nybbles in ebx
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
jmp ??loop16Mono ;loop until done
??cleanup16Mono:
jnz ??done16Mono ;if ebp is non-zero, we're DONE
;if exactly zero, finish the tail-end
;of the conversion (may be a non-
;multiple of 8 nybbles)
;
;
; Loop cleanup for last (incomplete) pass
pop ecx ;restore # of words
shr ecx,1 ;divide by two to get samples
and ecx,07h ;get # of samples we missed
jmp [DWORD PTR dwMono16JmpTable+ecx*4] ;go finish the job...
;
;
; Structure cleanup
??done16Mono:
pop ebx ;restore struct base
pop ebp ;restore stack frame pointer
mov [(sCompInfo ebx).dwPredicted],eax ;save last sample
mov [(sCompInfo ebx).wIndex],dx ;save last index value
mov eax,[wBytes] ;get # of bytes we did
??byeBye:
pop edx ;restore all the regs
pop ecx
pop ebx
pop edi
pop esi
ret
;
;
; Jumps for -32768/+32767 bounds check go to these vvvv
align 4
??fix1Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed1Smp16Mono ;go back
align 4
??fix1Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed1Smp16Mono ;go back
align 4
??fix2Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed2Smp16Mono ;go back
align 4
??fix2Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed2Smp16Mono ;go back
align 4
??fix3Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed3Smp16Mono ;go back
align 4
??fix3Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed3Smp16Mono ;go back
align 4
??fix4Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed4Smp16Mono ;go back
align 4
??fix4Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed4Smp16Mono ;go back
align 4
??fix5Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed5Smp16Mono ;go back
align 4
??fix5Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed5Smp16Mono ;go back
align 4
??fix6Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed6Smp16Mono ;go back
align 4
??fix6Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed6Smp16Mono ;go back
align 4
??fix7Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed7Smp16Mono ;go back
align 4
??fix7Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed7Smp16Mono ;go back
align 4
??fix8Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed8Smp16Mono ;go back
align 4
??fix8Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed8Smp16Mono ;go back
;
;
; Jump tables for cleanup after loop unroll point to these vvvv
align 4
??finish16Mono1:
xor ecx,ecx ;clear nybble bucket
mov ch,[esi] ;get 1 nybble (1 byte)
shl ch,4 ;move it over
mov bl,ch ;get nybble in ebx
sub edi,0Eh ;back edi up
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
jmp ??finish1Smp16Mono ;go finish it
align 4
??finish16Mono2:
xor ecx,ecx ;clear nybble bucket
mov ch,[esi] ;get 2 nybbles (1 byte)
mov bl,ch ;get nybbles in ebx
sub edi,0Ch ;back edi up
sub esi,3 ;adjust esi (used for dword aligning)
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
jmp ??finish2Smp16Mono ;go finish it
align 4
??finish16Mono3:
xor ecx,ecx ;clear nybble bucket
mov cx,[esi] ;get 3 nybbles (2 bytes)
shl cx,4 ;move it over
mov bl,cl ;get nybbles in ebx
sub edi,0Ah ;back edi up
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
jmp ??finish3Smp16Mono ;go finish it
align 4
??finish16Mono4:
xor ecx,ecx ;clear nybble bucket
mov cx,[esi] ;get 4 nybbles (2 bytes)
mov bl,cl ;get nybbles in ebx
sub edi,08h ;back edi up
sub esi,2 ;adjust esi (used for dword aligning)
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
jmp ??finish4Smp16Mono ;go finish it
align 4
??finish16Mono5:
xor ecx,ecx ;clear nybble bucket
mov cl,[esi+2] ;get 1 nybble (1 byte)
shl ecx,16 ;shift it over
mov cx,[esi] ;get 4 nybbles (2 bytes)
mov bl,cl ;get nybbles in ebx
shr ecx,4 ;move it over
shl bl,4 ;move it over
sub edi,06h ;back edi up
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
jmp ??finish5Smp16Mono ;go finish it
align 4
??finish16Mono6:
xor ecx,ecx ;clear nybble bucket
mov cl,[esi+2] ;get 2 nybbles (1 byte)
shl ecx,16 ;move it over
mov cx,[esi] ;get 4 nybbles (2 bytes)
mov bl,cl ;get nybbles in ebx
shr ecx,8 ;move it over
sub esi,1 ;adjust esi (used for dword aligning)
sub edi,04h ;back edi up
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
jmp ??finish6Smp16Mono ;go finish it
align 4
??finish16Mono7:
xor ecx,ecx ;clear nybble bucket
mov ecx,[esi] ;get 7 nybbles (4 bytes)
shl ecx,4 ;move it over
mov bl,cl ;get nybbles in ebx
sub edi,02h ;back edi up
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
jmp ??finish7Smp16Mono ;go finish it
;
;
; Jump Tables
align 4
dwMono16JmpTable DD ??done16Mono
DD ??finish16Mono1
DD ??finish16Mono2
DD ??finish16Mono3
DD ??finish16Mono4
DD ??finish16Mono5
DD ??finish16Mono6
DD ??finish16Mono7
align 4
dwMono16AlignJmpTable DD ??fixAlign16Mono0
DD ??fixAlign16Mono1
DD ??fixAlign16Mono2
DD ??fixAlign16Mono3
ENDP sosCODECDecompressData
LABEL LockedCodeEnd BYTE
;***************************************************************************
;* sosCODEC_LOCK -- locks the JLB audio decompression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is lock sucessful, false otherwise *
;* *
;* PROTO: BOOL sosCODEC_Lock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL sosCODEC_Lock:NEAR
PROC sosCODEC_Lock C NEAR USES ebx ecx edx esi edi
;
; Lock the code that is used by the sos decompression method.
;
mov eax,0600h ; function number.
mov ecx,OFFSET LockedCodeStart ; ecx must have start of memory.
mov edi,OFFSET LockedCodeEnd ; edi will have size of region in bytes.
shld ebx,ecx,16
sub edi, ecx
shld esi,edi,16
int DPMI_INTR ; do call.
jc ??error
or [InitFlags], IF_LOCKED_PM_CODE
;
; Lock the data used by the sos decompression method.
;
mov eax,0600h ; function number.
mov ecx,OFFSET LockedDataStart ; ecx must have start of memory.
mov edi,OFFSET LockedDataEnd ; edi will have size of region in bytes.
shld ebx,ecx,16
sub edi, ecx
shld esi,edi,16
int DPMI_INTR ; do call.
jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region.
or [InitFlags], IF_LOCKED_PM_DATA
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP sosCODEC_Lock
;***************************************************************************
;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is unlock sucessful, false otherwise *
;* *
;* PROTO: BOOL sosCODEC_Unlock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL sosCODEC_Unlock:NEAR
PROC sosCODEC_Unlock C NEAR USES ebx ecx edx esi edi
test [InitFlags],IF_LOCKED_PM_CODE
jz ??code_not_locked
mov eax , 0601h
mov ecx,OFFSET LockedCodeStart ; ecx must have start of memory.
mov edi,OFFSET LockedCodeEnd ; edx will have size of region in bytes.
sub edi,ecx ; - figure size.
shld ebx , ecx , 16
shld esi , edi , 16
int DPMI_INTR ; do call.
jc ??error
??code_not_locked:
test [InitFlags],IF_LOCKED_PM_DATA
jz ??data_not_locked
mov ax,0601h ; set es to descriptor of data.
mov ecx,OFFSET LockedDataStart ; ecx must have start of memory.
mov edi,OFFSET LockedDataEnd ; edx will have size of region in bytes.
sub edi,ecx ; - figure size.
shld ebx , ecx , 16
shld esi , edi , 16
int DPMI_INTR ; do call.
jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region.
??data_not_locked:
mov [InitFlags],0
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP sosCODEC_Unlock
END

View File

@@ -0,0 +1,83 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
*
* File : soscomp.h
* Date Created : 6/1/94
* Description :
*
* Programmer(s) : Nick Skrepetos
* Last Modification : 10/1/94 - 11:37:9 AM
* Additional Notes : Modified by Denzil E. Long, Jr.
*
*****************************************************************************
* Copyright (c) 1994, HMI, Inc. All Rights Reserved *
****************************************************************************/
#ifndef _SOS_COMPRESS
#define _SOS_COMPRESS
/* compression types */
enum {
_ADPCM_TYPE_1,
};
/* define compression structure */
typedef struct _tagCOMPRESS_INFO {
char *lpSource;
char *lpDest;
unsigned long dwCompSize;
unsigned long dwUnCompSize;
unsigned long dwSampleIndex;
long dwPredicted;
long dwDifference;
short wCodeBuf;
short wCode;
short wStep;
short wIndex;
unsigned long dwSampleIndex2; //added BP for channel 2
long dwPredicted2; //added BP for channel 2
long dwDifference2; //added BP for channel 2
short wCodeBuf2; //added BP for channel 2
short wCode2; //added BP for channel 2
short wStep2; //added BP for channel 2
short wIndex2; //added BP for channel 2
short wBitSize;
short wChannels; //added BP for # of channels
} _SOS_COMPRESS_INFO;
/* compressed file type header */
typedef struct _tagCOMPRESS_HEADER {
unsigned long dwType; // type of compression
unsigned long dwCompressedSize; // compressed file size
unsigned long dwUnCompressedSize; // uncompressed file size
unsigned long dwSourceBitSize; // original bit size
char szName[16]; // file type, for error checking
} _SOS_COMPRESS_HEADER;
/* Prototypes */
extern "C" {
void __cdecl sosCODECInitStream(_SOS_COMPRESS_INFO *);
unsigned long __cdecl sosCODECCompressData(_SOS_COMPRESS_INFO *, unsigned long);
unsigned long __cdecl sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);
unsigned long __cdecl General_sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);
}
#endif

View File

@@ -0,0 +1,128 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosdata.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOS_DATA
#define _SOS_DATA
#include <stddef.h>
#pragma pack(4)
extern WORD _sosDIGIData_Start;
extern WORD _sosDIGIData_End;
extern WORD _wSOSDriverLinear[];
extern WORD _wSOSTimerLinear[];
extern LPSTR _lpSOSDriver[];
extern LPSTR _lpSOSTimer[];
extern LPSTR _lpSOSDriverCS[];
extern LPSTR _lpSOSTimerCS[];
extern BOOL _wSOSDriverLoaded[];
extern BOOL _wSOSTimerLoaded[];
extern BOOL _wSOSDriverInitialized[];
extern WORD _wSOSOutputRate[];
extern WORD _wSOSDMABuffersize[];
extern LONG _dwSOSDMABufferPhysical[];
extern LPSTR _lpSOSDMABuffer[];
extern BOOL _wTimerUsed;
extern VOID ( far *_lpSOSFillHandler[] )( VOID );
extern WORD _wSOSTimerType[];
extern WORD _wSOSDriverType[];
extern _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];
extern LPWORD _lpSOSDMAIrqCount[];
extern LPWORD _lpSOSDMAFillCount[];
extern WORD _wSOSTmrNextCount;
extern VOID ( interrupt far *_lpSOSOldTimer )( VOID );
extern WORD _wSOSDriverID[];
extern _SOS_CAPABILITIES _sSOSDriverCaps[];
extern WORD _wSOSDMAPortList[];
extern BYTE _bSOSDMAChannel[];
extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[];
extern BYTE _pSOSDriverPath[];
extern BYTE _pSOSTempDriverPath[];
extern BOOL _wTIMERUsed;
extern WORD _wTIMERValue;
extern VOID ( far * _lpTIMEREvents[] )( VOID );
extern WORD _wTIMEREventRate[];
extern WORD _dwTIMEREventFraction[];
extern WORD _dwTIMEREventFractionCurrent[];
extern BYTE _bSOSMIDITimerSongHandler[];
extern BYTE _bSOSMIDISongHandle;
extern WORD _wSOSTimerMemHandle[];
extern WORD _wSOSDriverMemHandle[];
extern WORD _wSOSRealSeg[];
extern _FILEHEADER _sDETFileHeader;
extern _DRIVERHEADER _sDETDriverHeader;
extern _FILEHEADER sLOADFileHeader;
extern _DRIVERHEADER sLOADDriverHeader;
extern BOOL _wDETInitialized;
extern WORD _wDETLinear;
extern LPSTR _lpDETDriverBuffer;
extern LPSTR _lpDETDriverBufferCS;
extern WORD _hDETFile;
extern DWORD _dwDETDriverIndex;
extern WORD _wDETDriverIndexCur;
extern WORD _wDETMemHandle;
extern LPSOSDEVICECAPS _lpDETDeviceCaps;
extern _SOS_CAPABILITIES _sDETCaps;
extern PSTR _pSOSErrorStrings[];
extern BOOL _wSOSBufferAllocated[];
extern BOOL _wSOSSystemInitialized;
extern VDS_STRUCT _sSOSVDSInfo;
extern _SOS_FILL_INFO _sSOSFillInfo;
extern WORD _wSOSTimerEventIndex;
extern WORD _wSOSTimerEntered;
extern WORD _wSOSDriverSize[];
extern WORD _wSOSTimerSize[];
#ifdef __cplusplus
extern "C" {
#endif
extern WORD _sosDIGIData1_Start;
extern WORD _sosDIGIData1_End;
extern WORD _sosDIGIData2_Start;
extern WORD _sosDIGIData2_End;
extern BYTE _bTIMERInstalled;
extern BYTE _bTIMERDPMI;
extern WORD wDetectPort;
extern WORD wDetectIRQ;
extern WORD wDetectDMA;
extern WORD wDetectParam;
#ifdef __cplusplus
}
#endif
#pragma pack()
#endif

View File

@@ -0,0 +1,83 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosdefs.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOSDEFS_DEFINED
#define _SOSDEFS_DEFINED
#undef _TRUE
#undef _FALSE
#undef _NULL
enum
{
_FALSE,
_TRUE
};
#define _NULL 0
#ifndef VOID
#define VOID void
#endif
typedef int BOOL;
typedef unsigned int UINT;
typedef unsigned char BYTE;
typedef unsigned WORD;
#ifndef LONG
typedef signed long LONG;
#endif
typedef unsigned long DWORD;
typedef BYTE * PBYTE;
typedef char near * PSTR;
typedef WORD * PWORD;
typedef LONG * PLONG;
typedef VOID * PVOID;
typedef BYTE far * LPBYTE;
typedef BYTE far * LPSTR;
typedef WORD far * LPWORD;
typedef LONG far * LPLONG;
typedef VOID far * LPVOID;
typedef BYTE huge * HPBYTE;
typedef BYTE huge * HPSTR;
typedef WORD huge * HPWORD;
typedef LONG huge * HPLONG;
typedef VOID huge * HPVOID;
typedef unsigned HANDLE;
#endif

View File

@@ -0,0 +1,219 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosfnct.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOS_FUNCTIONS
#define _SOS_FUNCTIONS
#pragma pack(4)
WORD sosDIGILockMemory ( VOID );
WORD sosDIGIUnLockMemory ( VOID );
WORD sosDIGIInitSystem ( LPSTR, WORD );
WORD sosDIGIUnInitSystem ( VOID );
WORD sosDIGIInitDriver ( WORD, _SOS_HARDWARE far *,
_SOS_INIT_DRIVER far *, WORD far * );
WORD sosDIGIUnInitDriver ( WORD, BOOL, BOOL );
WORD sosDIGILoadDriver ( WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );
WORD sosDIGIUnLoadDriver ( WORD );
WORD sosDIGIGetDeviceCaps ( WORD, LPSOSDEVICECAPS );
#ifdef PHARLAP
LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * );
#else
LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * );
#endif
WORD sosDIGIStopSample ( WORD, WORD );
WORD sosDIGISamplesPlaying ( WORD );
BOOL sosDIGISampleDone ( WORD, WORD );
BOOL sosDIGISampleFilling ( WORD, WORD );
WORD sosDIGIStartSample ( WORD, _SOS_START_SAMPLE far * );
WORD sosDIGIContinueSample ( WORD, WORD, _SOS_START_SAMPLE far * );
WORD sosDIGIDetectInit ( LPSTR );
WORD sosDIGIDetectUnInit ( VOID );
WORD sosDIGIDetectFindHardware ( WORD, _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectFindFirst ( _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectFindNext ( _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectGetSettings ( _SOS_HARDWARE far * );
WORD sosDIGIDetectGetCaps ( WORD, _SOS_CAPABILITIES far * );
WORD sosDIGIDetectVerifySettings( _SOS_HARDWARE far * );
PSTR sosGetErrorString ( WORD );
WORD sosDIGILoadTimer ( WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );
WORD sosDIGIUnLoadTimer ( WORD );
WORD sosTIMERRegisterEvent ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );
WORD sosTIMERInitSystem ( WORD, WORD );
WORD sosTIMERUnInitSystem ( WORD );
WORD sosTIMERSetRate ( WORD );
WORD sosTIMERRemoveEvent ( WORD );
WORD sosTIMERAlterEventRate ( WORD, WORD );
WORD sosTIMERGetEventRate ( WORD );
VOID far sosTIMEROldHandler ( VOID );
VOID far sosTIMERHandler ( VOID );
// functions in soscntl.c
WORD sosDIGISetSampleVolume ( WORD, WORD, WORD );
WORD sosDIGIGetSampleVolume ( WORD, WORD );
WORD sosDIGISetChannel ( WORD, WORD, WORD );
WORD sosDIGIGetChannel ( WORD, WORD );
WORD sosDIGIGetBytesProcessed ( WORD, WORD );
WORD sosDIGIGetLoopCount ( WORD, WORD );
WORD sosDIGISetPanLocation ( WORD, WORD, WORD );
WORD sosDIGIGetPanLocation ( WORD, WORD );
DWORD sosDIGISetPitch ( WORD, WORD, DWORD );
DWORD sosDIGIGetPitch ( WORD, WORD );
WORD sosDIGIGetDMAPosition ( WORD );
WORD sosDIGISetPanSpeed ( WORD, WORD, WORD );
WORD sosDIGIGetPanSpeed ( WORD, WORD );
WORD sosDIGIGetSampleID ( WORD, WORD );
WORD sosDIGIGetSampleHandle ( WORD, WORD );
WORD sosDIGISetMasterVolume ( WORD, WORD );
#ifdef PHARLAP
VOID sosFreeVDSPage ( unsigned short, unsigned short, DWORD );
WORD sosAllocVDSPage ( unsigned short *, unsigned short *, DWORD * );
#else
WORD sosAllocVDSPage ( LPSTR *, WORD *, WORD * );
VOID sosFreeVDSPage ( WORD, WORD, LONG );
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef PHARLAP
extern int __cdecl sosRealFree ( int );
extern BOOL __cdecl _sos_read( WORD, LPSTR, WORD, WORD * );
extern int __cdecl sosRealAlloc( int, int *, int * );
extern void __cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );
extern int __cdecl sosGetCS( VOID );
extern int __cdecl sosGetES( VOID );
#else
extern int __cdecl sosRealAlloc ( int, int *, int * );
extern int __cdecl sosRealFree ( int );
#endif
// sos driver functions
extern WORD __cdecl sosDRVLockMemory ( DWORD, DWORD );
extern WORD __cdecl sosDRVUnLockMemory ( DWORD, DWORD );
extern void __cdecl sosDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDRVGetCapsPtr ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDRVInit ( LPSTR, LPSTR, int, int, int, int, int, int );
extern void __cdecl sosDRVStart ( LPSTR, LPSTR, int, int );
extern void __cdecl sosDRVSetRate ( LPSTR, LPSTR, int );
extern void __cdecl sosDRVSetAction ( LPSTR, LPSTR );
extern void __cdecl sosDRVStop ( LPSTR, LPSTR );
extern void __cdecl sosDRVUnInit ( LPSTR, LPSTR );
extern void __cdecl sosDRVGetFillInfo ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );
extern void __cdecl sosFillSampleStructs ( PSTR, LPSTR );
extern WORD __cdecl sosDetDRVExist ( LPSTR, LPSTR );
extern WORD __cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );
extern WORD __cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );
extern WORD __cdecl sosDIGIInitForWindows( WORD );
extern WORD __cdecl sosDIGIUnInitForWindows( WORD );
extern LPSTR __cdecl sosAllocateFarMem ( WORD, PSTR, WORD * );
extern LPSTR __cdecl sosCreateAliasCS ( LPSTR );
extern VOID __cdecl sosFreeSelector ( LPSTR, DWORD );
extern LPSTR __cdecl sosMAKEDOSPtr ( PSTR );
extern VOID __cdecl sosDetDRVSetEnvString ( DWORD, PSTR );
extern PSTR __cdecl sosDetDRVGetEnvString ( DWORD );
extern VOID __cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );
extern VOID __cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );
extern WORD __cdecl sosDRVGetFreeMemory ( VOID );
extern WORD __cdecl sosDRVAllocVDSStruct ( WORD, WORD *, WORD * );
extern WORD __cdecl sosDRVFreeVDSStruct ( WORD, WORD );
extern WORD __cdecl sosDRVIsWindowsActive ( VOID );
extern WORD __cdecl sosDRVVDSGetBuffer ( WORD );
extern WORD __cdecl sosDRVVDSFreeBuffer ( WORD );
extern WORD __cdecl getDS( VOID );
extern WORD __cdecl sosDRVMakeDMASelector ( WORD );
extern WORD __cdecl sosDRVFreeDMASelector ( WORD );
extern void __cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );
extern void __cdecl sosTIMERDRVUnInit( void );
extern void __cdecl sosTIMERDRVHandler( void );
extern void __cdecl sosTIMERDRVFHandler( void );
extern void __cdecl sosTIMERDRVEnable( void );
extern void __cdecl sosTIMERDRVDisable( void );
extern void __cdecl sosTIMERDRVCallOld( void );
extern void __cdecl sosTIMERDRVSetRate( WORD );
extern void __cdecl sosDIGITimer_Start( void );
extern void __cdecl sosDIGITimer_End( void );
extern void __cdecl sosDIGIDrv_Start( void );
extern void __cdecl sosDIGIDrv_End( void );
#ifdef __cplusplus
}
#endif
// external functions for handling system initialization and
// uninitialization
WORD sosEXDIGInitDriver ( WORD, WORD, WORD, LPSTR,
_SOS_HARDWARE far *, WORD * );
WORD sosEXDIGIUnInitDriver ( VOID );
WORD sosEXDETFindDriver ( WORD, LPSTR, _SOS_HARDWARE far *,
_SOS_CAPABILITIES far * );
// memory locking prototypes
VOID sosDIGICaps_Start( VOID );
VOID sosDIGICaps_End( VOID );
VOID sosDIGIErr_Start( VOID );
VOID sosDIGIErr_End( VOID );
VOID sosDIGITmr_Start( VOID );
VOID sosDIGITmr_End( VOID );
VOID sosDIGIStart_Start( VOID );
VOID sosDIGIStart_End( VOID );
VOID sosDIGIPlyng_Start( VOID );
VOID sosDIGIPlyng_End( VOID );
VOID sosDIGIRate_Start( VOID );
VOID sosDIGIRate_End( VOID );
VOID sosDIGIDone_Start( VOID );
VOID sosDIGIDone_End( VOID );
VOID sosDIGIDetec_Start( VOID );
VOID sosDIGIDetec_End( VOID );
VOID sosDIGIInit_Start( VOID );
VOID sosDIGIInit_End( VOID );
VOID sosDIGILoad_Start( VOID );
VOID sosDIGILoad_End( VOID );
VOID sosDIGICntl_Start( VOID );
VOID sosDIGICntl_End( VOID );
#pragma pack()
#endif

129
WIN32LIB/AUDIO/OLD/SOSRES.H Normal file
View File

@@ -0,0 +1,129 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosres.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#define _SOS_RESOURCE
#ifndef _SOS_RESOURCE
#define _SOS_RESOURCE
// structure for resource file header
typedef struct
{
// file version
WORD wVersion;
// file size
LONG dwFileSize;
// number of resources in file
WORD wResCount;
// offset of resource data from top of file
LONG dwResOffset;
// offset of sync track from top of file
LONG dwSyncTrackOffset;
} _RES_FILE_HEADER;
// structure for resource block header
typedef struct
{
// resource id
WORD wID;
// resource type
WORD wResType;
// offset of next block
LONG dwNextBlock;
// size of the current resource information
LONG dwResSize;
// rate to play block at
WORD wBlockRate;
// id for the sync track to use
WORD wSyncTrackID;
} _RES_BLOCK_HEADER;
// structure for sync mark tag
typedef struct _tagSYNCMARK
{
// ID of the type of mark being used
WORD wID;
// location in data of sync mark
LONG dwSyncOffset;
// length of sync block
LONG dwSyncSize;
// start sample data
_SOS_START_SAMPLE sampleData;
} _RES_SYNCMARK;
typedef union
{
// structure for sync mark tag
_RES_SYNCMARK syncMark;
} _RES_TAG;
// union for filter information for prepareWave
typedef union
{
// filter type
WORD wFilterID;
// structure for volume
struct volume
{
WORD wVolume;
};
// structure for delay
struct delay
{
WORD wDelaySamples;
};
} _SOS_FILTER;
#endif


View File

@@ -0,0 +1,54 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood Library *
* *
* File Name : SOUND.H *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : September 1, 1993 *
* *
* Last Update : September 1, 1993 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SOUND_H
#define SOUND_H
//#define HMI_DRIVER TRUE
//#include "sos.h"
#include "soscomp.h"
/*
** Maximum number of sound effects that may run at once.
*/
#define MAX_SFX 5
/*
** Size of temp HMI low memory staging buffer.
*/
#define SECONDARY_BUFFER_SIZE (1024*32)
#endif

View File

@@ -0,0 +1,538 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : SOUNDINT.CPP *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : June 23, 1995 *
* *
* Last Update : June 28, 1995 [PWG] *
* *
* This module contains all of the functions that are used within our *
* sound interrupt. They are stored in a seperate module because memory *
* around these functions must be locked or they will cause a read to *
* be generated while in an interrupt. *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Simple_Copy -- Copyies 1 or 2 source chuncks to a dest *
* Sample_Copy -- Copies sound data from source format to raw format. *
* DigiCallback -- Low level double buffering handler. *
* save_my_regs -- Inline function which will save assembly regs *
* restore_my_regs -- Inline function which will restore saved registes *
* Audio_Add_Long_To_Pointer -- Adds an offset to a ptr casted void *
* Init_Locked_Data -- Initializes sound driver locked data *
* Audio_Mem_Set -- Quick see routine to set memory to a value *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
#pragma pack(4)
#define WIN32
#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check
#define _WIN32
#endif // _WIN32
#include <windows.h>
#include <windowsx.h>
#include "dsound.h"
#include <wwstd.h>
#include "soundint.h"
#include "memflag.h"
#include "audio.h"
extern DebugBuffer[];
/***************************************************************************
** All routines past this point must be locked for the sound driver to **
** function under a VCPI memory manager. These locks are unnecessary if **
** the driver does not have to run under windows or does not use virtual **
** memory. **
***************************************************************************/
/***************************************************************************
* SIMPLE_COPY -- Copyies 1 or 2 source chuncks to a dest *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
long Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size)
{
long out = 0; // Number of bytes copied to the destination.
/*
** It could happen that entering this routine, the source buffer
** has been exhausted, but the alternate buffer is still valid.
** Move the alternate into the primary position before proceeding.
*/
if (!(*ssize)) {
*source = *alternate;
*ssize = *altsize;
*alternate = NULL;
*altsize = 0;
}
if (*source && *ssize) {
long s; // Scratch length var.
/*
** Copy as much as possible from the primary source, but no
** more than the primary source has to offer.
*/
s = size;
if (*ssize < s) s = *ssize;
Mem_Copy(*source, *dest, s);
*source = Audio_Add_Long_To_Pointer(*source, s);
*ssize -= s;
*dest = Audio_Add_Long_To_Pointer(*dest, s);
size -= s;
out += s;
/*
** If the primary source was insufficient to fill the request, then
** move the alternate into the primary position and try again.
*/
if (size) {
*source = *alternate;
*ssize = *altsize;
*alternate = 0;
*altsize = 0;
out += Simple_Copy(source, ssize, alternate, altsize, dest, size);
}
}
return(out);
}
/***********************************************************************************************
* Sample_Copy -- Copies sound data from source format to raw format. *
* *
* This routine is used to copy the sound data (possibly compressed) to the destination *
* buffer in raw format. *
* *
* INPUT: source -- Pointer to the source data (possibly compressed). *
* *
* dest -- Pointer to the destination buffer. *
* *
* size -- The size of the destination buffer. *
* *
* OUTPUT: Returns with the number of bytes placed into the output buffer. This is usually *
* the number of bytes requested except in the case when the source is exhausted. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 09/03/1994 JLB : Created. *
* 09/04/1994 JLB : Revamped entirely. *
*=============================================================================================*/
#pragma argsused
long Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * , short int *)
{
long s;
long datasize = 0; // Output bytes.
switch (scomp) {
default:
case SCOMP_NONE:
datasize = Simple_Copy(source, ssize, alternate, altsize, &dest, size);
break;
case SCOMP_WESTWOOD:
case SCOMP_SOS:
while (size > 0) {
/*
** The block spans two buffers. It must be copied down to
** a staging area before it can be decompressed.
*/
{
long magic;
unsigned short fsize;
unsigned short dsize;
void *fptr;
void *dptr;
void *mptr;
fptr = &fsize;
dptr = &dsize;
mptr = &magic;
s = Simple_Copy(source, ssize, alternate, altsize, &fptr, sizeof(fsize));
if (s < sizeof(fsize)) {
return datasize;
}
s = Simple_Copy(source, ssize, alternate, altsize, &dptr, sizeof(dsize));
if (s < sizeof(dsize) || size < dsize) {
return datasize;
}
s = Simple_Copy(source, ssize, alternate, altsize, &mptr, sizeof(magic));
if (s < sizeof(magic) || magic != LockedData.MagicNumber) {
return datasize;
}
/*
** If the frame and uncompressed data size are identical, then this
** indicates that the frame is not compressed. Just copy it directly
** to the destination buffer in this case.
*/
if (fsize == dsize) {
s = Simple_Copy(source, ssize, alternate, altsize, &dest, fsize);
if (s < dsize) {
return (datasize);
}
} else {
/*
** The frame was compressed, so copy it to the staging buffer, and then
** uncompress it into the final destination buffer.
*/
fptr = LockedData.UncompBuffer;
s = Simple_Copy(source, ssize, alternate, altsize, &fptr, fsize);
if (s < fsize) {
return (datasize);
}
if (scomp == SCOMP_WESTWOOD) {
Decompress_Frame(LockedData.UncompBuffer, dest, dsize);
} else {
st->sosinfo.lpSource = (char *)LockedData.UncompBuffer;
st->sosinfo.lpDest = (char *)dest;
if (st->sosinfo.wBitSize==16 && st->sosinfo.wChannels==1){
sosCODECDecompressData(&st->sosinfo, dsize);
} else {
General_sosCODECDecompressData(&st->sosinfo, dsize);
}
}
dest = Audio_Add_Long_To_Pointer(dest, dsize);
}
datasize += dsize;
size -= dsize;
}
}
break;
}
return(datasize);
}
/***********************************************************************************************
* maintenance_callback -- routine to service the direct play secondary buffers *
* and other stuff..? *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* ....Unknown *
* 10/17/95 10:15PM ST : tidied up a tad for direct sound *
*=============================================================================================*/
VOID far __cdecl maintenance_callback(VOID)
{
int index; //index used in for loop
SampleTrackerType *st; //ptr to SampleTracker structure
DWORD play_cursor; //Position that direct sound is reading from
DWORD write_cursor; //Position in buffer that we can write to
int bytes_copied; //Number of bytes copied into the buffer
BOOL write_more; //Flag to set if we need to write more into the buffer
LPVOID play_buffer_ptr; //Beginning of locked area of buffer
LPVOID dummy_buffer_ptr; //Length of locked area in buffer
DWORD lock_length1; //Beginning of second locked area in buffer
DWORD lock_length2; //Length of second locked area in buffer
HRESULT return_code;
//EnterCriticalSection(&GlobalAudioCriticalSection);
st = &LockedData.SampleTracker[0];
for (index = 0; index < MAX_SFX; index++) {
if (st->Active) {
/*
** General service routine to handle moving small blocks from the
** source into the direct sound buffers. If the source is
** compressed, then this will also uncompress it as the copy
** is performed.
*/
if (st->Service && !st->DontTouch ) {
//EnterCriticalSection (&st->AudioCriticalSection);
st->DontTouch = TRUE;
/*
** Get the current position of the direct sound play cursor within the buffer
*/
return_code = st->PlayBuffer->GetCurrentPosition ( &play_cursor , &write_cursor );
/*
** Check for unusual situations like a focus loss
*/
if (return_code != DS_OK){
if (return_code == DSERR_BUFFERLOST){
if (Audio_Focus_Loss_Function){
Audio_Focus_Loss_Function();
}
}
//LeaveCriticalSection(&GlobalAudioCriticalSection);
//LeaveCriticalSection (&st->AudioCriticalSection);
return; //Our app has lost focus or something else nasty has happened
} //so dont update the sound buffers
if (st->MoreSource){
/*
** If the direct sound read pointer is less than a quarter
** of a buffer away from the end of the data then copy some
** more.
*/
write_more = FALSE;
if ( play_cursor < (unsigned)st->DestPtr ){
if ( (unsigned)st->DestPtr - (unsigned)play_cursor <= SECONDARY_BUFFER_SIZE/4 ){
write_more=TRUE;
}
} else {
/* The only time that play_cursor can be greater than DestPtr is
** if we wrote right to the end of the buffer last time and DestPtr
** looped back to the beginning of the buffer.
** That being the case, all we have to do is see if play_cursor is
** within the last 25% of the buffer
*/
if ( ( (int)play_cursor > SECONDARY_BUFFER_SIZE*3/4) &&st->DestPtr==0 ){
write_more=TRUE;
}
}
if (write_more){
/*
** Lock a 1/2 of the direct sound buffer so we can write to it
*/
if ( DS_OK== st->PlayBuffer->Lock ( (DWORD)st->DestPtr ,
(DWORD)SECONDARY_BUFFER_SIZE/2,
&play_buffer_ptr,
&lock_length1,
&dummy_buffer_ptr,
&lock_length2,
0 )){
bytes_copied = Sample_Copy( st,
&st->Source,
&st->Remainder,
&st->QueueBuffer,
&st->QueueSize,
play_buffer_ptr,
SECONDARY_BUFFER_SIZE/4,
st->Compression,
&st->Trailer[0],
&st->TrailerLen);
if ( bytes_copied != (SECONDARY_BUFFER_SIZE/4) ){
/*
** We must have reached the end of the sample
*/
st->MoreSource=FALSE;
memset (((char*)play_buffer_ptr)+bytes_copied ,
0 ,
(SECONDARY_BUFFER_SIZE/4)-bytes_copied);
/*
** Clear out an extra area in the buffer ahead of the play cursor
** to give us a quiet period of grace in which to stop the buffer playing
*/
if ( (unsigned)st->DestPtr == SECONDARY_BUFFER_SIZE*3/4 ){
if ( dummy_buffer_ptr && lock_length2 ){
memset (dummy_buffer_ptr , 0 , lock_length2);
}
} else {
memset ((char*)play_buffer_ptr+SECONDARY_BUFFER_SIZE/4 , 0 , SECONDARY_BUFFER_SIZE/4);
}
}
/*
** Update our pointer into the direct sound buffer
**
*/
st->DestPtr = Audio_Add_Long_To_Pointer (st->DestPtr,bytes_copied);
if ( (unsigned)st->DestPtr >= (unsigned)SECONDARY_BUFFER_SIZE ){
st->DestPtr = Audio_Add_Long_To_Pointer (st->DestPtr,(long)-SECONDARY_BUFFER_SIZE);
}
/*
** Unlock the direct sound buffer
*/
st->PlayBuffer->Unlock( play_buffer_ptr,
lock_length1,
dummy_buffer_ptr,
lock_length2);
}
} //write_more
} else { //!more_source
/*
** no more source to write - check if the buffer play
** has overrun the end of the sample and stop it if it has
*/
if ( ( (play_cursor >= (unsigned)st->DestPtr) && ( ((unsigned)play_cursor - (unsigned)st->DestPtr) <SECONDARY_BUFFER_SIZE/4) ) ||
(!st->OneShot &&( (play_cursor < (unsigned)st->DestPtr) && ( ((unsigned)st->DestPtr - (unsigned)play_cursor) >(SECONDARY_BUFFER_SIZE*3/4) ) )) ){
st->PlayBuffer->Stop();
st->Service = FALSE;
Stop_Sample( index );
}
} //more_source
st->DontTouch = FALSE;
//LeaveCriticalSection (&st->AudioCriticalSection);
}
/*
** For file streamed samples, fill the queue pointer if needed.
** This allows for delays in calling the Sound_Callback function.
*/
if (!st->DontTouch && !st->QueueBuffer && st->FilePending) {
st->QueueBuffer = Audio_Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);
st->FilePending--;
st->Odd++;
if (!st->FilePending) {
st->QueueSize = st->FilePendingSize;
} else {
st->QueueSize = LockedData.StreamBufferSize;
}
}
}
/*
** Advance to the next sample control structure.
*/
st++;
}
if (!LockedData._int) {
LockedData._int++;
st = &LockedData.SampleTracker[0];
for (index = 0; index < MAX_SFX; index++) {
/*
** If there are any samples that require fading, then do so at this
** time.
*/
if (st->Active && st->Reducer && st->Volume) {
//EnterCriticalSection (&st->AudioCriticalSection);
if (st->Reducer >= st->Volume) {
st->Volume = 0;
} else {
st->Volume -= st->Reducer;
}
#ifdef NO_VOLUME_CONTROL
st->PlayBuffer->SetVolume (-( ( (32768-st->Volume)*1000) >>15 ) );
#endif //ifdef NO_VOLUME_CONTROL
//LeaveCriticalSection (&st->AudioCriticalSection);
}
st++;
}
LockedData._int--;
}
//LeaveCriticalSection(&GlobalAudioCriticalSection);
}
/***************************************************************************
* ADD_LONG_TO_POINTER -- Adds an offset to a ptr casted void *
* *
* INPUT: void * ptr - the pointer to add to *
* long size - the size to add to it *
* *
* OUTPUT: void * ptr - the new location it will point to *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
void *Audio_Add_Long_To_Pointer(void const *ptr, long size)
{
return ((void *) ( (char const *) ptr + size));
}
/***************************************************************************
* AUDIO_MEM_SET -- Quick see routine to set memory to a value *
* *
* INPUT: void const * - the memory that needs to be set *
* unsigned char - the value to set the memory to *
* long size - how big an area to set *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 06/28/1995 PWG : Created. *
*=========================================================================*/
void Audio_Mem_Set(void const *ptr, unsigned char value, long size)
{
unsigned char *temp = (unsigned char *)ptr;
for (int lp = 0; lp < size; lp ++) {
*temp++ = value;
}
}

View File

@@ -0,0 +1,292 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : SOUNDINT.H *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : June 23, 1995 *
* *
* Last Update : June 23, 1995 [PWG] *
* *
* This file is the include file for the Westwood Sound Sytem defines and *
* routines that are handled in an interrupt.
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "sound.h"
/*
** Defines for true and false. These are included because we do not allow
** the sound int to include any of the westwood standard headers. If we
** did, there might be too much temptation to call another library function.
** this would be bad, because then that function would not be locked.
*/
#define FALSE 0
#define TRUE 1
/*
** Define the different type of sound compression avaliable to the westwood
** library.
*/
typedef enum {
SCOMP_NONE=0, // No compression -- raw data.
SCOMP_WESTWOOD=1, // Special sliding window delta compression.
SCOMP_SONARC=33, // Sonarc frame compression.
SCOMP_SOS=99 // SOS frame compression.
} SCompressType;
/*
** This is the safety overrun margin for the sonarc compressed
** data frames. This value should be equal the maximum 'order' times
** the maximum number of bytes per sample. It should be evenly divisible
** by 16 to aid paragraph alignment.
*/
#define SONARC_MARGIN 32
/*
** Define the sample control structure which helps us to handle feeding
** data to the sound interrupt.
*/
#pragma pack(1);
typedef struct {
/*
** This flags whether this sample structure is active or not.
*/
unsigned Active;
//unsigned Active:1;
/*
** This flags whether the sample is loading or has been started.
*/
//unsigned Loading:1;
unsigned Loading;
/*
** This semaphore ensures that simultaneous update of this structure won't
** occur. This is necessary since both interrupt and regular code can modify
** this structure.
*/
//unsigned DontTouch:1;
unsigned DontTouch;
/*
** If this sample is really to be considered a score rather than
** a sound effect, then special rules apply. These largely fall into
** the area of volume control.
*/
//unsigned IsScore:1;
unsigned IsScore;
/*
** This is the original sample pointer. It is used to control the sample based on
** pointer rather than handle. The handle method is necessary when more than one
** sample could be playing simultaneously. The pointer method is necessary when
** the dealing with a sample that may have stopped behind the programmer's back and
** this occurance is not otherwise determinable. It is also used in
** conjunction with original size to unlock a sample which has been DPMI
** locked.
*/
void const *Original;
long OriginalSize;
/*
** These are pointers to the double buffers.
*/
LPDIRECTSOUNDBUFFER PlayBuffer;
/*
** Variable to keep track of the playback rate of this buffer
*/
int PlaybackRate;
/*
** Variable to keep track of the sample type ( 8 or 16 bit ) of this buffer
*/
int BitSize;
/*
** Variable to keep track of the stereo ability of this buffer
*/
int Stereo;
/*
** The number of bytes in the buffer that has been filled but is not
** yet playing. This value is normally the size of the buffer,
** except for the case of the last bit of the sample.
*/
LONG DataLength;
/*
** This is the buffer index for the low buffer that
** has been filled with data but not yet being
** played.
*/
// short int Index;
/*
** Pointer into the play buffer for writing the next
** chunk of sample to
**
*/
VOID *DestPtr;
/*
** This flag indicates that there is more source data
** to copy to the play buffer
**
*/
BOOL MoreSource;
/*
** This flag indicates that the entire sample fitted inside the
** direct sound secondary buffer
**
*/
BOOL OneShot;
/*
** Pointer to the sound data that has not yet been copied
** to the playback buffers.
*/
VOID *Source;
/*
** This is the number of bytes remaining in the source data as
** pointed to by the "Source" element.
*/
LONG Remainder;
/*
** Object to use with Enter/LeaveCriticalSection
**
*/
CRITICAL_SECTION AudioCriticalSection;
/*
** Samples maintain a priority which is used to determine
** which sounds live or die when the maximum number of
** sounds are being played.
*/
int Priority;
/*
** This is the handle as returned by sosDIGIStartSample function.
*/
short int Handle;
/*
** This is the current volume of the sample as it is being played.
*/
int Volume;
int Reducer; // Amount to reduce volume per tick.
/*
** This is the compression that the sound data is using.
*/
SCompressType Compression;
short int TrailerLen; // Number of trailer bytes in buffer.
BYTE Trailer[SONARC_MARGIN]; // Maximum number of 'order' samples needed.
DWORD Pitch;
WORD Flags;
/*
** This flag indicates whether this sample needs servicing.
** Servicing entails filling one of the empty low buffers.
*/
short int Service;
/*
** This flag is TRUE when the sample has stopped playing,
** BUT there is more data available. The sample must be
** restarted upon filling the low buffer.
*/
BOOL Restart;
/*
** Streaming control handlers.
*/
BOOL (*Callback)(short int id, short int *odd, VOID **buffer, LONG *size);
VOID *QueueBuffer; // Pointer to continued sample data.
LONG QueueSize; // Size of queue buffer attached.
short int Odd; // Block number tracker (0..StreamBufferCount-1).
int FilePending; // Number of buffers already filled ahead.
long FilePendingSize; // Number of bytes in last filled buffer.
/*
** The file variables are used when streaming directly off of the
** hard drive.
*/
int FileHandle; // Streaming file handle (ERROR = not in use).
VOID *FileBuffer; // Temporary streaming buffer (allowed to be freed).
/*
** The following structure is used if the sample if compressed using
** the sos 16 bit compression Codec.
*/
_SOS_COMPRESS_INFO sosinfo;
} SampleTrackerType;
typedef struct LockedData {
unsigned int DigiHandle; // = -1;
BOOL ServiceSomething; // = FALSE;
long MagicNumber; // = 0xDEAF;
VOID *UncompBuffer; // = NULL;
long StreamBufferSize; // = (2*SECONDARY_BUFFER_SIZE)+128;
short StreamBufferCount; // = 32;
SampleTrackerType SampleTracker[MAX_SFX];
unsigned int SoundVolume;
unsigned int ScoreVolume;
BOOL _int;
} LockedDataType;
extern LockedDataType LockedData;
#pragma pack(4);
void Init_Locked_Data(void);
long Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size);
long Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, short int *trailersize);
VOID far __cdecl maintenance_callback(VOID);
VOID __cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid);
void far HMI_TimerCallback(void);
void *Audio_Add_Long_To_Pointer(void const *ptr, long size);
void DPMI_Unlock(VOID const *ptr, long const size);
extern "C" {
void __cdecl Audio_Mem_Set(void const *ptr, unsigned char value, long size);
// void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);
long __cdecl Decompress_Frame(void * source, void * dest, long size);
int __cdecl Decompress_Frame_Lock(void);
int __cdecl Decompress_Frame_Unlock(void);
int __cdecl sosCODEC_Lock(void);
int __cdecl sosCODEC_Unlock(void);
void __GETDS(void);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,120 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : SOUNDLCK.CPP *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : June 23, 1995 *
* *
* Last Update : June 23, 1995 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check
#define _WIN32
#endif // _WIN32
#define WIN32
#include <windows.h>
#include <windowsx.h>
#include <objbase.h>
#include "dsound.h"
#include <mem.h>
#include "wwmem.h"
#include "wwstd.h"
#include "soundint.h"
LockedDataType LockedData;
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* INIT_LOCKED_DATA -- Initializes sound driver locked data *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
void Init_Locked_Data(void)
{
/*
** Initialize all of the data elements that need to be locked.
*/
LockedData.DigiHandle = -1;
LockedData.ServiceSomething = FALSE;
LockedData.MagicNumber = 0xDEAF;
LockedData.UncompBuffer = NULL;
// LockedData.StreamBufferSize = (2*SECONDARY_BUFFER_SIZE)+128;
LockedData.StreamBufferSize = (SECONDARY_BUFFER_SIZE/4)+128;
LockedData.StreamBufferCount = 16;
LockedData.SoundVolume = 255;
LockedData.ScoreVolume = 255;
LockedData._int = FALSE;
#ifdef cuts
/*
** Lock the sound specific c functions that will cause us problems if
** they are swapped out during an interrupt.
*/
DPMI_Lock(&LockedData, 4096L);
DPMI_Lock(Simple_Copy, 4096L);
DPMI_Lock(Sample_Copy, 4096L);
DPMI_Lock((void *)maintenance_callback, 4096L);
DPMI_Lock((void *)DigiCallback, 4096L);
DPMI_Lock((void *)HMI_TimerCallback, 4096L);
DPMI_Lock(Audio_Add_Long_To_Pointer, 4096L);
DPMI_Lock(DPMI_Unlock, 4096L);
/*
** Lock the library functions that will cause us problems if they are
** swapped out during an interrupt.
*/
DPMI_Lock(Mem_Copy, 4096L);
DPMI_Lock(Audio_Mem_Set, 4096L);
DPMI_Lock(__GETDS, 4096L);
/*
** Finally lock the two assembly modules that need locking. This can
** be handled by calling the lock function that is local to thier module
** swapped out during an interrupt.
*/
Decompress_Frame_Lock();
sosCODEC_Lock();
#endif //cuts
}

View File

@@ -0,0 +1,39 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include "audio.h"
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
File_Stream_Sample_Vol("file", 0, 0);
return (0);
}

View File

@@ -0,0 +1,32 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#undef _WINDOWS_16_
#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check
#define _WIN32
#endif // _WIN32
#define WIN32
#define __WIN32
#include <windows.h>
#include <windowsx.h>
#include <ole2.h>
main
{}

755
WIN32LIB/AUDIO/OLSOSDEC.ASM Normal file
View File

@@ -0,0 +1,755 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
;
;****************************************************************************
;*
;* Copyright (c) 1994, HMI, INC. All Rights Reserved
;*
;*---------------------------------------------------------------------------
;*
;* FILE
;* soscodec.asm
;*
;* DESCRIPTION
;* HMI SOS ADPCM compression/decompression.
;*
;* PROGRAMMER
;* Nick Skrepetos
;* Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)
;* Bill Petro (Added stereo support)
;* DATE
;* Febuary 15, 1995
;*
;*---------------------------------------------------------------------------
;*
;* PUBLIC
;*
;****************************************************************************
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
DPMI_INTR equ 31h
IF_LOCKED_PM_CODE equ 1h ; Locked PM code for DPMI.
IF_LOCKED_PM_DATA equ 2h ; Locked PM code for DPMI.
STRUC sCompInfo
lpSource DD ? ;Compressed data pointer
lpDest DD ? ;Uncompressed data pointer
dwCompSize DD ? ;Compressed size
dwUnCompSize DD ? ;Uncompressed size
dwSampleIndex DD ? ;Index into sample
dwPredicted DD ? ;Next predicted value
dwDifference DD ? ;Difference from last sample
wCodeBuf DW ? ;Holds 2 nibbles for decompression
wCode DW ? ;Current 4 bit code
wStep DW ? ;Step value in table
wIndex DW ? ;Index into step table
dwSampleIndex2 DD ? ;Index into sample
dwPredicted2 DD ? ;Next predicted value
dwDifference2 DD ? ;Difference from last sample
wCodeBuf2 DW ? ;Holds 2 nibbles for decompression
wCode2 DW ? ;Current 4 bit code
wStep2 DW ? ;Step value in table
wIndex2 DW ? ;Index into step table
wBitSize DW ? ;Bit size for decompression
wChannels DW ? ;number of channels
ENDS sCompInfo
DATASEG
InitFlags DD 0 ; Flags to indicate what has been initialized.
LABEL LockedDataStart BYTE
;* Index table for stepping into step table
wCODECIndexTab DW -1,-1,-1,-1,2,4,6,8
DW -1,-1,-1,-1,2,4,6,8
;Lookup table of replacement values
;The actual sound value is replaced with an index to lookup in this table
;The index only takes up a nibble(4bits) and represents an int(16bits)
;Essentially:
;Get a value
;compare it with the value before it
;find closest value in table and store the index into the table
;if i'm going down then negitize it
;go to next byte.
;Theory for stereo:
;1)handle stereo and mono in two seperate loops. cleaner...
;start at byte 0 and skip every other byte(or word) both write and read
;when we get done
; set start byte to 1 and do it again
;This table essentialy round off to closes values in 3 distinct bands
; precalculated and optimized(i guess) for human hearing.
wCODECStepTab DW 7, 8, 9, 10, 11, 12, 13,14
DW 16, 17, 19, 21, 23, 25, 28, 31
DW 34, 37, 41, 45, 50, 55, 60, 66
DW 73, 80, 88, 97, 107, 118, 130, 143
DW 157, 173, 190, 209, 230, 253, 279, 307
DW 337, 371, 408, 449, 494, 544, 598, 658
DW 724, 796, 876, 963, 1060, 1166, 1282, 1411
DW 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024
DW 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484
DW 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899
DW 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794
DW 32767
;dwCODECByteIndex DD 0 ; this is when to stop compressing
;dwCODECTempStep DD 0 ; tempory storage for step value
;wCODECMask DW 0 ; Current mask
LABEL LockedDataEnd BYTE
CODESEG
LABEL LockedCodeStart BYTE
;****************************************************************************
;*
;* NAME
;* sosCODECInitStream - Initialize compression stream.
;*
;* SYNOPSIS
;* sosCODECInitStream(CompInfo)
;*
;* void sosCODECInitStream(_SOS_COMPRESS_INFO *);
;*
;* FUNCTION
;* Initialize compression stream for compression and decompression.
;*
;* INPUTS
;* CompInfo - Compression information structure.
;*
;* RESULT
;* NONE
;*
;****************************************************************************
GLOBAL C sosCODECInitStream:NEAR
PROC sosCODECInitStream C NEAR
ARG sSOSInfo:NEAR PTR
mov eax,[sSOSInfo]
mov [(sCompInfo eax).wIndex],0 ; starting index 0
mov [(sCompInfo eax).wStep],7 ; start with a step of 7
mov [(sCompInfo eax).dwPredicted],0 ; no predicted value
mov [(sCompInfo eax).dwSampleIndex],0 ;start at head of index
mov [(sCompInfo eax).wIndex2],0 ; starting index 0
mov [(sCompInfo eax).wStep2],7 ; start with a step of 7
mov [(sCompInfo eax).dwPredicted2],0 ; no predicted value
mov [(sCompInfo eax).dwSampleIndex2],0 ;start at head of index
ret
ENDP sosCODECInitStream
;****************************************************************************
;*
;* NAME
;* sosCODECDecompressData - Decompress audio data.
;*
;* SYNOPSIS
;* Size = sosCODECDecompressData(CompInfo, NumBytes)
;*
;* long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);
;*
;* FUNCTION
;* Decompress data from a 4:1 ADPCM compressed stream. The number of
;* bytes decompressed is returned.
;*
;* INPUTS
;* CompInfo - Compress information structure.
;* NumBytes - Number of bytes to compress.
;*
;* RESULT
;* Size - Size of decompressed data.
;*
;****************************************************************************
GLOBAL C General_sosCODECDecompressData:NEAR
PROC General_sosCODECDecompressData C NEAR
ARG sSOSInfo:NEAR PTR
ARG wBytes:DWORD
local dwCODECBytesProcessed:dword ;bytes to decompress
local dwCODECByteIndex:dword ;this is when to stop compressing
; these need to be local if the function is to be reenterant
push esi
push edi
push ebx
push ecx
push edx
;*---------------------------------------------------------------------------
;* Initialize
;*---------------------------------------------------------------------------
mov ebx,[sSOSInfo]
mov eax,[wBytes]
mov [dwCODECBytesProcessed],eax
mov [(sCompInfo ebx).dwSampleIndex],0 ;start at head of index
mov [(sCompInfo ebx).dwSampleIndex2],0 ;start at head of index
;Check for 16 bit decompression
cmp [(sCompInfo ebx).wBitSize],16
jne short ??skipByteDivide
shr eax,1 ;Divide size by two
??skipByteDivide:
mov [dwCODECByteIndex],eax
mov esi,[(sCompInfo ebx).lpSource]
mov edi,[(sCompInfo ebx).lpDest]
cmp [(sCompInfo ebx).wChannels],2 ;stereo check
je ??mainloopl ;do left side first
; Determine if sample index is even or odd. This will determine
; if we need to get a new token or not.
;---------------------------------------------------------------------------
;Main Mono Loop
;---------------------------------------------------------------------------
??mainloop:
test [(sCompInfo ebx).dwSampleIndex],1 ;odd ??
je short ??fetchToken ; if so get new token
xor eax,eax ;else shift int codebuf
mov ax,[(sCompInfo ebx).wCodeBuf] ;ored with Code
shr eax,4
and eax,000Fh
mov [(sCompInfo ebx).wCode],ax
jmp short ??calcDifference
??fetchToken:
xor eax,eax ;get a new token
mov al,[esi] ;put in codebuf
mov [(sCompInfo ebx).wCodeBuf],ax
inc esi
and eax,000Fh
mov [(sCompInfo ebx).wCode],ax ;and then code
??calcDifference:
mov [(sCompInfo ebx).dwDifference],0 ;reset diff
xor ecx,ecx
mov cx,[(sCompInfo ebx).wStep] ;cx is step value
test eax,4 ;Check for wCode & 4
je short ??no4
add [(sCompInfo ebx).dwDifference],ecx ;Add wStep
??no4:
test eax,2 ;Check for wCode & 2
je short ??no2
mov edx,ecx ;Add wStep >> 1
shr edx,1
add [(sCompInfo ebx).dwDifference],edx
??no2:
test eax,1 ;Check for wCode & 1
je short ??no1
mov edx,ecx ;Add wStep >> 2
shr edx,2
add [(sCompInfo ebx).dwDifference],edx
??no1:
mov edx,ecx ;Add in wStep >> 3
shr edx,3
add [(sCompInfo ebx).dwDifference],edx
test eax,8 ;Check for wCode & 8
je short ??no8
neg [(sCompInfo ebx).dwDifference] ;Negate diff
??no8:
; add difference to predicted value.
mov eax,[(sCompInfo ebx).dwPredicted]
add eax,[(sCompInfo ebx).dwDifference]
; make sure there is no under or overflow.
cmp eax,7FFFh
jl short ??noOverflow
mov eax,7FFFh
??noOverflow:
cmp eax,0FFFF8000h
jg short ??noUnderflow
mov eax,0FFFF8000h
??noUnderflow:
mov [(sCompInfo ebx).dwPredicted],eax
cmp [(sCompInfo ebx).wBitSize],16
jne short ??output8Bit
mov [edi],ax ;Output 16bit sample
add edi,2
jmp short ??adjustIndex
??output8Bit:
; output 8 bit sample
xor ah,80h
mov [edi],ah
inc edi
??adjustIndex:
xor ecx,ecx
mov cx,[(sCompInfo ebx).wCode]
xor eax,eax
shl ecx,1
mov ax,[wCODECIndexTab + ecx]
add [(sCompInfo ebx).wIndex],ax ;check if wIndex < 0
cmp [(sCompInfo ebx).wIndex],8000h
jb short ??checkOverflow
mov [(sCompInfo ebx).wIndex],0 ;reset index to zero
jmp short ??adjustStep
??checkOverflow:
cmp [(sCompInfo ebx).wIndex],88 ;check if wIndex > 88
jbe short ??adjustStep
mov [(sCompInfo ebx).wIndex],88 ;reset index to 88
??adjustStep:
; fetch wIndex so we can fetch new step value
xor ecx,ecx
mov cx,[(sCompInfo ebx).wIndex]
xor eax,eax
shl ecx,1
mov ax,[wCODECStepTab + ecx]
; advance index and store step value
add [(sCompInfo ebx).dwSampleIndex],1
mov [(sCompInfo ebx).wStep],ax
; decrement bytes processed and loop back.
dec [dwCODECByteIndex]
jne ??mainloop
jmp ??exitout
;--------------------------------------------------------------------------
;Left Channel Start
;--------------------------------------------------------------------------
??mainloopl:
test [(sCompInfo ebx).dwSampleIndex],1
je short ??fetchTokenl
xor eax,eax
mov ax,[(sCompInfo ebx).wCodeBuf]
shr eax,4
and eax,000Fh
mov [(sCompInfo ebx).wCode],ax
jmp short ??calcDifferencel
??fetchTokenl:
xor eax,eax
mov al,[esi]
mov [(sCompInfo ebx).wCodeBuf],ax
add esi,2 ;2 for stereo
and eax,000Fh
mov [(sCompInfo ebx).wCode],ax
??calcDifferencel:
; reset difference
mov [(sCompInfo ebx).dwDifference],0
xor ecx,ecx
mov cx,[(sCompInfo ebx).wStep]
test eax,4 ;Check for wCode & 4
je short ??no4l
add [(sCompInfo ebx).dwDifference],ecx ;Add wStep
??no4l:
test eax,2 ;Check for wCode & 2
je short ??no2l
mov edx,ecx ;Add wStep >> 1
shr edx,1
add [(sCompInfo ebx).dwDifference],edx
??no2l:
test eax,1 ;Check for wCode & 1
je short ??no1l
mov edx,ecx ;Add wStep >> 2
shr edx,2
add [(sCompInfo ebx).dwDifference],edx
??no1l:
mov edx,ecx ;Add in wStep >> 3
shr edx,3
add [(sCompInfo ebx).dwDifference],edx
test eax,8 ;Check for wCode & 8
je short ??no8l
neg [(sCompInfo ebx).dwDifference] ;Negate diff
??no8l:
; add difference to predicted value.
mov eax,[(sCompInfo ebx).dwPredicted]
add eax,[(sCompInfo ebx).dwDifference]
; make sure there is no under or overflow.
cmp eax,7FFFh
jl short ??noOverflowl
mov eax,7FFFh
??noOverflowl:
cmp eax,0FFFF8000h
jg short ??noUnderflowl
mov eax,0FFFF8000h
??noUnderflowl:
mov [(sCompInfo ebx).dwPredicted],eax
cmp [(sCompInfo ebx).wBitSize],16
jne short ??output8Bitl
mov [edi],ax ;Output 16bit sample
add edi,4 ;4 for stereo
jmp short ??adjustIndexl
??output8Bitl:
; output 8 bit sample
xor ah,80h
mov [edi],ah
add edi,2 ;2 for stereo
??adjustIndexl:
xor ecx,ecx
mov cx,[(sCompInfo ebx).wCode]
xor eax,eax
shl ecx,1
mov ax,[wCODECIndexTab + ecx]
add [(sCompInfo ebx).wIndex],ax
; check if wIndex < 0
cmp [(sCompInfo ebx).wIndex],8000h
jb short ??checkOverflowl
mov [(sCompInfo ebx).wIndex],0
jmp short ??adjustStepl ;reset index to zero
??checkOverflowl:
cmp [(sCompInfo ebx).wIndex],88 ; check if wIndex > 88
jbe short ??adjustStepl
mov [(sCompInfo ebx).wIndex],88 ; reset index to 88
??adjustStepl:
; fetch wIndex so we can fetch new step value
xor ecx,ecx
mov cx,[(sCompInfo ebx).wIndex]
xor eax,eax
shl ecx,1
mov ax,[wCODECStepTab + ecx]
; advance index and store step value
add [(sCompInfo ebx).dwSampleIndex],1
mov [(sCompInfo ebx).wStep],ax
; decrement bytes processed and loop back.
sub [dwCODECByteIndex],2
jne ??mainloopl
;----------------------------------------------------------------------------
; Right Side Setup
;----------------------------------------------------------------------------
mov eax,[wBytes]
mov [dwCODECBytesProcessed],eax
mov esi,[(sCompInfo ebx).lpSource]
mov edi,[(sCompInfo ebx).lpDest]
inc esi ; skip left channel
inc edi ; skip left channel
cmp [(sCompInfo ebx).wBitSize],16 ;16 bit ??
je short ??doByteDivide
mov [dwCODECByteIndex],eax
jmp short ??mainloopr
??doByteDivide:
shr eax,1 ;Divide size by two
inc edi ; 16 bit so skip 1 more
mov [dwCODECByteIndex],eax
;--------------------------------------------------------------------------
;Right Channel Start
;--------------------------------------------------------------------------
??mainloopr:
test [(sCompInfo ebx).dwSampleIndex2],1
je short ??fetchTokenr
xor eax,eax
mov ax,[(sCompInfo ebx).wCodeBuf2]
shr eax,4
and eax,000Fh
mov [(sCompInfo ebx).wCode2],ax
jmp short ??calcDifferencer
??fetchTokenr:
xor eax,eax
mov al,[esi]
mov [(sCompInfo ebx).wCodeBuf2],ax
add esi,2 ;2 for stereo
and eax,000Fh
mov [(sCompInfo ebx).wCode2],ax
??calcDifferencer:
; reset difference
mov [(sCompInfo ebx).dwDifference2],0
xor ecx,ecx
mov cx,[(sCompInfo ebx).wStep2]
test eax,4 ;Check for wCode & 4
je short ??no4r
add [(sCompInfo ebx).dwDifference2],ecx ;Add wStep
??no4r:
test eax,2 ;Check for wCode & 2
je short ??no2r
mov edx,ecx ;Add wStep >> 1
shr edx,1
add [(sCompInfo ebx).dwDifference2],edx
??no2r:
test eax,1 ;Check for wCode & 1
je short ??no1r
mov edx,ecx ;Add wStep >> 2
shr edx,2
add [(sCompInfo ebx).dwDifference2],edx
??no1r:
mov edx,ecx ;Add in wStep >> 3
shr edx,3
add [(sCompInfo ebx).dwDifference2],edx
test eax,8 ;Check for wCode & 8
je short ??no8r
neg [(sCompInfo ebx).dwDifference2] ;Negate diff
??no8r:
; add difference to predicted value.
mov eax,[(sCompInfo ebx).dwPredicted2]
add eax,[(sCompInfo ebx).dwDifference2]
cmp eax,7FFFh
jl short ??noOverflowr
mov eax,7FFFh
??noOverflowr:
cmp eax,0FFFF8000h
jg short ??noUnderflowr
mov eax,0FFFF8000h
??noUnderflowr:
mov [(sCompInfo ebx).dwPredicted2],eax
cmp [(sCompInfo ebx).wBitSize],16
jne short ??output8Bitr
mov [edi],ax ;Output 16bit sample
add edi,4 ;4 for stereo ***
jmp short ??adjustIndexr
??output8Bitr:
; output 8 bit sample
xor ah,80h
mov [edi],ah
add edi,2 ;2 for stereo
??adjustIndexr:
xor ecx,ecx
mov cx,[(sCompInfo ebx).wCode2]
xor eax,eax
shl ecx,1
mov ax,[wCODECIndexTab + ecx]
add [(sCompInfo ebx).wIndex2],ax
; check if wIndex < 0
cmp [(sCompInfo ebx).wIndex2],8000h
jb short ??checkOverflowr
; reset index to zero
mov [(sCompInfo ebx).wIndex2],0
jmp short ??adjustStepr
??checkOverflowr:
; check if wIndex > 88
cmp [(sCompInfo ebx).wIndex2],88
jbe short ??adjustStepr
mov [(sCompInfo ebx).wIndex2],88 ; reset index to 88
??adjustStepr:
; fetch wIndex so we can fetch new step value
xor ecx,ecx
mov cx,[(sCompInfo ebx).wIndex2]
xor eax,eax
shl ecx,1
mov ax,[wCODECStepTab + ecx]
; advance index and store step value
add [(sCompInfo ebx).dwSampleIndex2],1
mov [(sCompInfo ebx).wStep2],ax
; decrement bytes processed and loop back.
sub [dwCODECByteIndex],2
jne ??mainloopr
??exitout:
; don't think we need this but just in case i'll leave it here!!
; mov [(sCompInfo ebx).lpSource],esi
; mov [(sCompInfo ebx).lpDest],edi
; set up return value for number of bytes processed.
mov eax,[dwCODECBytesProcessed]
pop edx
pop ecx
pop ebx
pop edi
pop esi
ret
ENDP General_sosCODECDecompressData
LABEL LockedCodeEnd BYTE
;***************************************************************************
;* sosCODEC_LOCK -- locks the JLB audio decompression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is lock sucessful, false otherwise *
;* *
;* PROTO: BOOL sosCODEC_Lock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL C sosCODEC_Lock:NEAR
PROC sosCODEC_Lock C NEAR USES ebx ecx edx esi edi
;
; Lock the code that is used by the sos decompression method.
;
mov eax,0600h ; function number.
mov ecx,OFFSET LockedCodeStart ; ecx must have start of memory.
mov edi,OFFSET LockedCodeEnd ; edi will have size of region in bytes.
shld ebx,ecx,16
sub edi, ecx
shld esi,edi,16
int DPMI_INTR ; do call.
jc ??error
or [InitFlags], IF_LOCKED_PM_CODE
;
; Lock the data used by the sos decompression method.
;
mov eax,0600h ; function number.
mov ecx,OFFSET LockedDataStart ; ecx must have start of memory.
mov edi,OFFSET LockedDataEnd ; edi will have size of region in bytes.
shld ebx,ecx,16
sub edi, ecx
shld esi,edi,16
int DPMI_INTR ; do call.
jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region.
or [InitFlags], IF_LOCKED_PM_DATA
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP sosCODEC_Lock
;***************************************************************************
;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is unlock sucessful, false otherwise *
;* *
;* PROTO: BOOL sosCODEC_Unlock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL C sosCODEC_Unlock:NEAR
PROC sosCODEC_Unlock C NEAR USES ebx ecx edx esi edi
test [InitFlags],IF_LOCKED_PM_CODE
jz ??code_not_locked
mov eax , 0601h
mov ecx,OFFSET LockedCodeStart ; ecx must have start of memory.
mov edi,OFFSET LockedCodeEnd ; edx will have size of region in bytes.
sub edi,ecx ; - figure size.
shld ebx , ecx , 16
shld esi , edi , 16
int DPMI_INTR ; do call.
jc ??error
??code_not_locked:
test [InitFlags],IF_LOCKED_PM_DATA
jz ??data_not_locked
mov ax,0601h ; set es to descriptor of data.
mov ecx,OFFSET LockedDataStart ; ecx must have start of memory.
mov edi,OFFSET LockedDataEnd ; edx will have size of region in bytes.
sub edi,ecx ; - figure size.
shld ebx , ecx , 16
shld esi , edi , 16
int DPMI_INTR ; do call.
jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region.
??data_not_locked:
mov [InitFlags],0
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP sosCODEC_Unlock
END

565
WIN32LIB/AUDIO/SOS.H Normal file
View File

@@ -0,0 +1,565 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sos.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOS_DEFINED
#define _SOS_DEFINED
#include "sosdefs.h"
#pragma pack(4)
// error definition for sound operating system
#define _SOS_ERR -1
// number of drivers allowed to be open at one time
#define _SOS_MAX_DRIVERS 5
// structure definition for the capabilities
typedef struct _tagCAPABILITIES
{
BYTE szDeviceName[ 32 ]; // device name
WORD wDeviceVersion; // device version
WORD wBitsPerSample; // bits per sound sample
WORD wChannels; // stereo/mono sound card
WORD wMinRate; // minimum rate
WORD wMaxRate; // maximum rate
WORD wMixerOnBoard; // board contains mixer
WORD wMixerFlags; // mixer capabilities
WORD wFlags; // miscellaneous flags
short far * lpPortList; // list of usable ports
short far * lpDMAList; // list of usable dma channels
short far * lpIRQList; // list of usable irq channels
short far * lpRateList; // list of usable rates, -1 if any in min to max
WORD fBackground; // foreground or background driver
WORD wDeviceID; // ID for the device
WORD wTimerID; // ID for the timer
} _SOS_CAPABILITIES;
// far pointer to the device capabilities structure
typedef _SOS_CAPABILITIES far * LPSOSDEVICECAPS;
// flag types for driver
#define _FLAGS_SIGNED 0x8000
// devices that can be loaded
#define _SOUND_BLASTER_8_MONO 0xe000
#define _SOUND_BLASTER_8_ST 0xe001
#define _SBPRO_8_ST _SOUND_BLASTER_8_ST
#define _SBPRO_8_MONO 0xe00f
#define _SOUND_MASTER_II_8_MONO 0xe002
#define _MV_PAS_8_MONO 0xe003
#define _MV_PAS_16_MONO 0xe004
#define _MV_PAS_8_ST 0xe005
#define _MV_PAS_16_ST 0xe006
#define _ADLIB_GOLD_8_ST 0xe007
#define _ADLIB_GOLD_16_ST 0xe008
#define _ADLIB_GOLD_8_MONO 0xe009
#define _ADLIB_GOLD_16_MONO 0xe00a
#define _MICROSOFT_8_MONO 0xe00b
#define _MICROSOFT_8_ST 0xe00c
#define _MICROSOFT_16_MONO 0xe00d
#define _MICROSOFT_16_ST 0xe00e
#define _SOUND_SOURCE_8_MONO_PC 0xe010
#define _SOUND_SOURCE_8_MONO_TANDY 0xe011
#define _GENERAL_PORT_8_MONO 0xe012
#define _GENERAL_PORT_8_MONO_R 0xe013
#define _SIERRA_8_MONO 0xe014
#define _SB16_8_MONO 0xe015
#define _SB16_8_ST 0xe016
#define _SB16_16_MONO 0xe017
#define _SB16_16_ST 0xe018
#define _ESS_AUDIODRIVE_8_MONO 0xe019
#define _ESS_AUDIODRIVE_8_ST 0xe01a
#define _ESS_AUDIODRIVE_16_MONO 0xe01b
#define _ESS_AUDIODRIVE_16_ST 0xe01c
#define _SOUNDSCAPE_8_MONO 0xe01d
#define _SOUNDSCAPE_8_ST 0xe01e
#define _SOUNDSCAPE_16_MONO 0xe01f
#define _SOUNDSCAPE_16_ST 0xe020
#define _RAP10_8_MONO 0xe021
#define _RAP10_16_MONO 0xe022
#define _GUS_8_MONO 0xe023
#define _GUS_8_ST 0xe024
#define _GUS_16_MONO 0xe025
#define _GUS_16_ST 0xe026
#define _GUS_MAX_8_MONO 0xe027
#define _GUS_MAX_8_ST 0xe028
#define _GUS_MAX_16_MONO 0xe029
#define _GUS_MAX_16_ST 0xe02a
#define _WAVEJAMMER_8_MONO 0xe02b
#define _WAVEJAMMER_8_ST 0xe02c
#define _WAVEJAMMER_16_MONO 0xe02d
#define _WAVEJAMMER_16_ST 0xe02e
#define _TEMPOCS_8_MONO 0xe02f
#define _TEMPOCS_8_ST 0xe030
#define _TEMPOCS_16_MONO 0xe031
#define _TEMPOCS_16_ST 0xe032
#define _WAVEJAMMERCD_8_MONO 0xe033
#define _WAVEJAMMERCD_8_ST 0xe034
#define _WAVEJAMMERCD_16_MONO 0xe035
#define _WAVEJAMMERCD_16_ST 0xe036
#define _SOUND_BLASTER_8_MONO_R 0xe050
#define _MICROSOFT_8_MONO_R 0xe051
#define _SOUND_MASTER_II_8_MONO_R 0xe052
#define _ADLIB_GOLD_8_MONO_R 0xe053
#define _MV_PAS_8_MONO_R 0xe054
#define _RAP10_8_MONO_R 0xe058
#define _RAP10_16_MONO_R 0xe059
#define _SB16_8_MONO_R 0xe05a
#define _SB16_8_ST_R 0xe05b
#define _SB16_16_MONO_R 0xe05c
#define _SB16_16_ST_R 0xe05d
#define _MV_PAS_16_MONO_R 0xe060
#define _SOUNDSCAPE_8_MONO_R 0xe061
#define _SOUNDSCAPE_8_ST_R 0xe062
#define _SOUNDSCAPE_16_MONO_R 0xe063
#define _SOUNDSCAPE_16_ST_R 0xe064
#define _ESS_AUDIODRIVE_8_MONO_R 0xe065
#define _ESS_AUDIODRIVE_8_ST_R 0xe066
#define _ESS_AUDIODRIVE_16_MONO_R 0xe067
#define _ESS_AUDIODRIVE_16_ST_R 0xe068
#define _SPEECH_THING_8_MONO 0xe090
#define _YAMAHA_8_MONO 0xe106
#define _INT_SPEAKER_8_MONO 0xe107
// call indexes for the loadable drivers
enum
{
_DRV_INIT,
_DRV_UNINIT,
_DRV_SETRATE,
_DRV_SETACTION,
_DRV_START,
_DRV_STOP,
_DRV_PAUSE,
_DRV_RESUME,
_DRV_CAPABILITIES,
_DRV_PLAY_FOREGROUND,
_DRV_GET_FILL_INFO,
_DRV_GET_CALL_FUNCTIONS,
_DRV_SET_CALL_FUNCTIONS
};
// fill info
typedef struct _tagFillInfo
{
LPSTR lpFillHandler; // pointer to fill handler
LPWORD lpDMAFillCount; // pointer to dma count
LPSTR lpSampleList; // pointer to sample list
LPWORD lpDMAMasterVolume; // pointer to dma count
} _SOS_FILL_INFO;
// caps info structure
typedef struct _tagCapsInfo
{
LPSTR lpPortList; // pointer to port list
LPSTR lpDMAList; // pointer to DMA list
LPSTR lpIRQList; // pointer to IRQ list
LPSTR lpRateList; // pointer to rate list
} _SOS_CAPS_INFO;
// maximum number of available voice
#define _MAX_VOICES 32
// structure definition
typedef struct _tagSAMPLE
{
LPSTR samplePtr; // pointer to data buffer
LPSTR sampleData; // pointer to active data
LPSTR sampleLoopPtr; // pointer for loop back
WORD sampleLength; // length of sample
WORD sampleIndex; // index into sample
WORD sampleLoopLength; // length of loop
WORD sampleBytesLeft; // bytes left to play in sample
WORD sampleLoopPoint; // byte count for loop point
WORD sampleLoopEndLength; // length of remaining chunk
short sampleFlags; // control sample
short sampleVolume; // volume control
short sampleID; // sample ID
short sampleChannel; // channel to play sample on
short sampleLoopCount; // loop count
short sampleLastFill; // last fill position
VOID ( far __cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample
WORD samplePitchAdd;
short samplePitchFraction;
short samplePort; // port to use for non-dma digitized
WORD sampleTotalBytes;
WORD sampleByteLength;
short samplePanLocation;
short samplePanSpeed;
short samplePanDirection;
short samplePanStart;
short samplePanEnd;
short sampleDelayBytes;
short sampleDelayRepeat;
WORD sampleADPCMPredicted;
short sampleADPCMIndex;
short sampleRootNoteMIDI;
WORD sampleTemp1;
} _SOS_SAMPLE;
// enumeration for left or right channel
enum
{
_LEFT_CHANNEL,
_RIGHT_CHANNEL,
_CENTER_CHANNEL,
_INTERLEAVED
};
// enumeration for foreground and background
enum
{
_FOREGROUND,
_BACKGROUND
};
// defines for the sample flags
#define _ACTIVE 0x8000
#define _LOOPING 0x4000
#define _FIRST_TIME 0x2000
#define _PENDING_RELEASE 0x1000
#define _CONTINUE_BLOCK 0x0800
#define _PITCH_SHIFT 0x0400
#define _PANNING 0x0200
#define _VOLUME 0x0100
#define _TRANSLATE16TO8 0x0080
#define _STAGE_LOOP 0x0040
#define _TRANSLATE8TO16 0x0020
#define _STEREOTOMONO 0x0010
// defines for the wParam flags
#define _SINGLE_SAMPLE 0x01
#define _SOS_DCAPS_AUTO_REINIT 0x01
#define _SOS_DCAPS_MPU_401 0x02
#define _SOS_DCAPS_OPL2 0x04
#define _SOS_DCAPS_OPL3 0x08
#define _SOS_DCAPS_OPL4 0x10
#define _SOS_DCAPS_WAVETABLE 0x20
#define _SOS_DCAPS_DL_SAMPLES 0x40
#define _SOS_DCAPS_FIFO_DEVICE 0x80
#define _SOS_DCAPS_ENV_NEEDED 0x100
#define _SOS_DCAPS_PSEUDO_DMA1 0x200
#define _SOS_DCAPS_SIGNED_DATA 0x8000
// file header structure
typedef struct
{
// name ID
BYTE szName[ 32 ];
// number of drivers in the file
WORD wDrivers;
// offset of first driver
WORD lOffset;
// size of the file
WORD lFileSize;
} _FILEHEADER;
// driver header structure
typedef struct
{
// name ID
BYTE szName[ 32 ];
// offset of next driver
WORD lNextDriver;
// size of current driver
WORD wSize;
// id for the current device
WORD wDeviceID;
// id for the type of DOS extender
WORD wExtenderType;
} _DRIVERHEADER;
// device hardware information
typedef struct
{
// port to be used
WORD wPort;
// irq to use
WORD wIRQ;
// dma channel to se
WORD wDMA;
// extra parameter
WORD wParam;
} _SOS_HARDWARE;
// structure definition for start sample
typedef struct
{
// pointer to sample
LPSTR lpSamplePtr;
// size of the sample
WORD dwSampleSize;
// number of times to loop the sample -1 is infinite
WORD wLoopCount;
// channel to play sample on
WORD wChannel;
// volume to play sample at
WORD wVolume;
// id for the sample
WORD wSampleID;
// far pointer to the callback function
VOID ( far __cdecl *lpCallback )( WORD, WORD, WORD );
// port to use if driver is a non-dma background driver
WORD wSamplePort;
// flags field
WORD wSampleFlags;
// total length of sample including loops, etc..
WORD dwSampleByteLength;
// loop point for the sample
WORD dwSampleLoopPoint;
WORD dwSampleLoopLength;
// pitch shifting components
WORD dwSamplePitchAdd;
WORD wSamplePitchFraction;
// pan components
WORD wSamplePanLocation;
WORD wSamplePanSpeed;
WORD wSamplePanDirection;
WORD wSamplePanStart;
WORD wSamplePanEnd;
// delay parts
WORD wSampleDelayBytes;
WORD wSampleDelayRepeat;
// compression components
WORD dwSampleADPCMPredicted;
WORD wSampleADPCMIndex;
// root note for pitch shifting
WORD wSampleRootNoteMIDI;
// filler for future upgrades
WORD dwSampleTemp1;
WORD dwSampleTemp2;
WORD dwSampleTemp3;
} _SOS_START_SAMPLE;
// structure for initializing a driver
typedef struct
{
WORD wBufferSize;
LPSTR lpBuffer;
BOOL wAllocateBuffer;
WORD wSampleRate;
WORD wParam;
LONG dwParam;
VOID ( far *lpFillHandler )( VOID );
LPSTR lpDriverMemory;
LPSTR lpDriverMemoryCS;
LPSTR lpTimerMemory;
LPSTR lpTimerMemoryCS;
WORD wTimerID;
WORD wPhysical;
} _SOS_INIT_DRIVER;
// define for the timer types to use
#define _SOS_NORMAL_TIMER 0x00
// enumeration for the timer types
enum
{
_TIMER_8_MONO = 0x1000,
_TIMER_8_ST,
_TIMER_16_MONO,
_TIMER_16_ST,
_TIMER_8_MONO_ULAW,
_TIMER_8_ST_ULAW,
_TIMER_16_MONO_ULAW,
_TIMER_16_ST_ULAW,
_TIMER_8_MONO_REC,
_TIMER_8_MONO_ULAW_REC,
_TIMER_UNDEFINED_1,
_TIMER_UNDEFINED_2,
_TIMER_UNDEFINED_3,
_TIMER_UNDEFINED_4,
_TIMER_UNDEFINED_5,
_TIMER_UNDEFINED_6,
_TIMER_UNDEFINED_7,
_TIMER_UNDEFINED_8,
_TIMER_UNDEFINED_9,
_TIMER_UNDEFINED_A,
_TIMER_UNDEFINED_B,
_TIMER_UNDEFINED_C,
_TIMER_UNDEFINED_D,
_TIMER_UNDEFINED_E,
_TIMER_UNDEFINED_F,
_TIMER_UNDEFINED_10,
_TIMER_UNDEFINED_11,
_TIMER_UNDEFINED_12,
_TIMER_UNDEFINED_13,
_TIMER_UNDEFINED_14,
_TIMER_UNDEFINED_15,
_TIMER_UNDEFINED_16,
_TIMER_8_SOUND_SOURCE,
_TIMER_8_SOUND_SOURCE_TANDY,
_TIMER_8_GENERAL_PORT,
_TIMER_8_GENERAL_PORT_REC
};
// define for no slots available
#define _ERR_NO_SLOTS ( WORD )-1
// error codes for the system
enum
{
_ERR_NO_ERROR,
_ERR_DRIVER_NOT_LOADED,
_ERR_INVALID_POINTER,
_ERR_DETECT_INITIALIZED,
_ERR_FAIL_ON_FILE_OPEN,
_ERR_MEMORY_FAIL,
_ERR_INVALID_DRIVER_ID,
_ERR_NO_DRIVER_FOUND,
_ERR_DETECTION_FAILURE,
_ERR_DRIVER_LOADED,
_ERR_INVALID_HANDLE,
_ERR_NO_HANDLES,
_ERR_PAUSED,
_ERR_NOT_PAUSED,
_ERR_INVALID_DATA,
_ERR_DRV_FILE_FAIL,
_ERR_INVALID_PORT,
_ERR_INVALID_IRQ,
_ERR_INVALID_DMA,
_ERR_INVALID_DMA_IRQ
};
// maximum number of timer events that can be registered
#define _TIMER_MAX_EVENTS 0x10
// flags for the debugging system
#define _SOS_DEBUG_NORMAL 0x0000
#define _SOS_DEBUG_NO_TIMER 0x0001
#define _SOS_TIMER_DPMI 0x0002
// define for types of DOS extenders
#define _SOS_RATIONAL 0x8000
#define _SOS_FLASHTECK 0x4000
// defines for the types of timers for different
// dos extenders
#define _SOS_TIMER_NEAR 0x8000
#define _SOS_TIMER_FAR 0x4000
// values for callback information
enum
{
_SAMPLE_PROCESSED,
_SAMPLE_LOOPING,
_SAMPLE_DONE
};
// define for special 18.2 callback rate to dos
#define _TIMER_DOS_RATE 0xff00
#pragma pack()
#pragma aux int_3 = "int 3"
#pragma pack( 1 )
typedef struct
{
unsigned region_size;
unsigned offset;
unsigned segment;
unsigned short number_available;
unsigned short number_used;
unsigned page0;
} EVDS_STRUCT;
typedef struct
{
unsigned region_size;
unsigned offset;
unsigned short segment;
unsigned short ID;
unsigned physical;
} VDS_STRUCT;
#pragma pack()
#include "sosdata.h"
#include "sosfnct.h"
#endif

724
WIN32LIB/AUDIO/SOSCODEC.ASM Normal file
View File

@@ -0,0 +1,724 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
;
;****************************************************************************
;*
;* Copyright (c) 1994, HMI, INC. All Rights Reserved
;*
;*---------------------------------------------------------------------------
;*
;* FILE
;* soscodec.asm
;*
;* DESCRIPTION
;* HMI SOS ADPCM compression/decompression.
;*
;* PROGRAMMER
;* Nick Skrepetos
;* Denzil E. Long, Jr. (Fixed bugs, rewrote for watcom)
;* Bill Petro (Added stereo support)
;* Jonathan Lanier
;*
;* DATE
;* Febuary 15, 1995
;*
;* LAST MODIFIED
;* 08/07/95 [jdl] - Rewrote/optimized sosCODECDecompressData
;*
;*---------------------------------------------------------------------------
;*
;* PUBLIC
;*
;****************************************************************************
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
DPMI_INTR equ 31h
IF_LOCKED_PM_CODE equ 1h ; Locked PM code for DPMI.
IF_LOCKED_PM_DATA equ 2h ; Locked PM code for DPMI.
STRUC sCompInfo
lpSource DD ? ;Compressed data pointer
lpDest DD ? ;Uncompressed data pointer
dwCompSize DD ? ;Compressed size
dwUnCompSize DD ? ;Uncompressed size
dwSampleIndex DD ? ;Index into sample
dwPredicted DD ? ;Next predicted value
dwDifference DD ? ;Difference from last sample
wCodeBuf DW ? ;Holds 2 nibbles for decompression
wCode DW ? ;Current 4 bit code
wStep DW ? ;Step value in table
wIndex DW ? ;Index into step table
dwSampleIndex2 DD ? ;Index into sample
dwPredicted2 DD ? ;Next predicted value
dwDifference2 DD ? ;Difference from last sample
wCodeBuf2 DW ? ;Holds 2 nibbles for decompression
wCode2 DW ? ;Current 4 bit code
wStep2 DW ? ;Step value in table
wIndex2 DW ? ;Index into step table
wBitSize DW ? ;Bit size for decompression
wChannels DW ? ;number of channels
ENDS sCompInfo
DATASEG
InitFlags DD 0 ; Flags to indicate what has been initialized.
LABEL LockedDataStart BYTE
;* Index table for stepping into step table
INCLUDE "difftb.inc"
INCLUDE "indextb.inc"
INCLUDE "nybbtb.inc"
LABEL LockedDataEnd BYTE
CODESEG
LABEL LockedCodeStart BYTE
;****************************************************************************
;*
;* NAME
;* sosCODECInitStream - Initialize compression stream.
;*
;* SYNOPSIS
;* sosCODECInitStream(CompInfo)
;*
;* void sosCODECInitStream(_SOS_COMPRESS_INFO *);
;*
;* FUNCTION
;* Initialize compression stream for compression and decompression.
;*
;* INPUTS
;* CompInfo - Compression information structure.
;*
;* RESULT
;* NONE
;*
;****************************************************************************
GLOBAL sosCODECInitStream:NEAR
PROC sosCODECInitStream C NEAR
ARG sSOSInfo:NEAR PTR
mov eax,[sSOSInfo]
mov [(sCompInfo eax).wIndex],0 ; starting index 0
mov [(sCompInfo eax).dwPredicted],0 ; no predicted value
mov [(sCompInfo eax).wIndex2],0 ; starting index 0
mov [(sCompInfo eax).dwPredicted2],0 ; no predicted value
ret
ENDP sosCODECInitStream
;****************************************************************************
;*
;* NAME
;* sosCODECDecompressData - Decompress audio data.
;*
;* SYNOPSIS
;* Size = sosCODECDecompressData(CompInfo, NumBytes)
;*
;* long sosCODECDecompressData(_SOS_COMPRESS_INFO *, long);
;*
;* FUNCTION
;* Decompress data from a 4:1 ADPCM compressed stream. The number of
;* bytes decompressed is returned.
;*
;* INPUTS
;* CompInfo - Compress information structure.
;* NumBytes - Number of bytes to decompress.
;*
;* RESULT
;* Size - Size of decompressed data.
;*
;*
;* NOTES
;* This routine has been optimized for pipelining on both
;* 486 and Pentium processors. Changing, inserting, or moving any
;* instructions will most likely slow down the code, in some cases by
;* as much as 20%. It can burst-decompress 16384 samples in about
;* 1940<34>s on a Pentium 90Mhz, and about 3960<36>s on a 486 66Mhz.
;* Instruction reordering could bring this down to below 1870<37>s on
;* the Pentium, but this would cause a great degradation in 486
;* performance. Since slow 486's are the reason this code was
;* written to be fast, it has been optimized for the Pentium only where
;* it would not degrade 486 performance. So, be careful when changing
;* ANY of this code, because it is very carefully balanced...
;****************************************************************************
GLOBAL C sosCODECDecompressData:NEAR
PROC sosCODECDecompressData C NEAR
ARG sSOSInfo:NEAR PTR
ARG wBytes:DWORD
push esi
push edi
push ebx
push ecx
push edx ;save all the regs
mov ebx,[sSOSInfo] ;get base of sCompInfo struct
mov cx,[(sCompInfo ebx).wBitSize] ;check the bit size
mov dx,[(sCompInfo ebx).wChannels] ;check the number of channels
;
;
; Determine the correct routine to use for decoding
; (for now only ADPCM 4:1 Mono 16-bit is implemented)
cmp cx,8
jne ??do16Bits
??do8Bits:
cmp dx,2
jne ??not8Stereo
; jmp ??decomp8Stereo
jmp ??byeBye
??not8Stereo:
cmp dx,1
jne ??byeBye
; jmp decomp8Mono
jmp ??byeBye
??do16Bits:
cmp cx,16
jne ??byeBye
cmp dx,2
jne ??not16Stereo
; jmp ??decomp16Stereo
jmp ??byeBye
??not16Stereo:
cmp dx,1
jne ??byeBye
push ebp
;
;
; 16 bit ADPCM 4:1 Mono pre-loop initialization
??decomp16Mono:
push ebx ;save struct base
xor edx,edx ;clear index
mov eax,[(sCompInfo ebx).dwPredicted] ;get last sample
mov dx,[(sCompInfo ebx).wIndex] ;get last index value
mov esi,[(sCompInfo ebx).lpSource] ;get source address
mov edi,[(sCompInfo ebx).lpDest] ;get dest address
mov ebp,[wBytes] ;get the number of dest. bytes
cmp ebp,16 ;less than 16? (less than 8 samples)
jl ??fixAlign16Mono0 ;if so, don't bother with alignment
;
;
; Check to see if we need to fix an alignment problem on the source buffer
; (non-aligned buffers are MUCH slower; if we're given a non-DWORD aligned
; source address, we do as many samples as needed to get to the nearest
; DWORD boundary, then finish the bulk as a DWORD-aligned decompress).
mov ebx,esi ;get source address
and ebx,03h ;check LSB
jnz ??fixalign16Mono ;if non-zero, need to align for
;warp speed
??fixAlign16Mono0:
push ebp ;save for later
shr ebp,4 ;divide by 16 for 16-bit,
;because we do 8 nybbles per loop,
;and there are two samples per
;byte, so there are n/16 iterations
;required
xor ebx,ebx ;clear our nybble index
or ebp,ebp ;set flags for EBP
jmp ??start16Mono ;start with test... don't go if
;we have zero bytes to do
??fixalign16Mono:
jmp [DWORD PTR dwMono16AlignJmpTable+ebx*4] ;do non-aligned first
align 4
??fixAlign16Mono1:
sub ebp,12 ;adjust # of dest. bytes
push ebp ;save it
shr ebp,4 ;divide by 16 to get samples/8
xor ebx,ebx ;clear our nybble index
inc ebp ;adjust ebp for loop
jmp ??finish16Mono6 ;borrow exit code to go through a
;piece of a loop
align 4
??fixAlign16Mono2:
sub ebp,8 ;adjust # of dest. bytes
push ebp ;save it
shr ebp,4 ;divide by 16 to get samples/8
xor ebx,ebx ;clear our nybble index
inc ebp ;adjust ebp for loop
jmp ??finish16Mono4 ;borrow exit code to go through a
;piece of a loop
align 4
??fixAlign16Mono3:
sub ebp,4 ;adjust # of dest. bytes
push ebp ;save it
shr ebp,4 ;divide by 16 to get samples/8
xor ebx,ebx ;clear our nybble index
inc ebp ;adjust ebp for loop
jmp ??finish16Mono2 ;borrow exit code to go through a
;piece of a loop
; "The Loop"
;
; Process 1st nybble
align 4
??loop16Mono:
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix1Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix1Smp16MonoU
??fixed1Smp16Mono:
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
mov [edi],ax ;save the sample
;
;
; Process 2nd nybble
??finish7Smp16Mono:
mov bl,ch ;get next 2 nybbles in ebx
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix2Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix2Smp16MonoU
??fixed2Smp16Mono:
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
mov [edi+02h],ax ;save the sample
shr ecx,16 ;move top four nybbles into bottom
;
;
; Process 3rd nybble
??finish6Smp16Mono:
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix3Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix3Smp16MonoU
??fixed3Smp16Mono:
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
mov [edi+04h],ax ;save the sample
;
;
; Process 4th nybble
??finish5Smp16Mono:
mov bl,cl
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix4Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix4Smp16MonoU
??fixed4Smp16Mono:
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
mov [edi+06h],ax ;save the sample
;
;
; Process 5th nybble
??finish4Smp16Mono:
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix5Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix5Smp16MonoU
??fixed5Smp16Mono:
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
mov [edi+08h],ax ;save the sample
;
;
; Process 6th nybble
??finish3Smp16Mono:
mov bl,ch
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix6Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix6Smp16MonoU
??fixed6Smp16Mono:
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
mov [edi+0Ah],ax ;save the sample
;
;
; Process 7th nybble
??finish2Smp16Mono:
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix7Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix7Smp16MonoU
??fixed7Smp16Mono:
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
mov [edi+0Ch],ax ;save the sample
;
;
; Process 8th nybble
??finish1Smp16Mono:
add eax,[dwDiffTable+edx*2] ;add difference to prev. sample
mov dx,[wIndexTable+edx] ;adjust dx to next index base
cmp eax,00007FFFh ;check for overflow
jg ??fix8Smp16MonoO
cmp eax,0FFFF8000h ;check for underflow
jl ??fix8Smp16MonoU
;
;
; Loop cleanup for next pass
??fixed8Smp16Mono:
mov [edi+0Eh],ax ;save the sample
add esi,04h ;bump esi to point to next longword
add edi,10h ;incr. the destination buffer ptr
dec ebp ;count down the number of samples/8
??start16Mono:
jng ??cleanup16Mono ;if done, clean up
mov ecx,[esi] ;get 4 nybbles in one whack (whee!)
mov bl,cl ;get next 2 nybbles in ebx
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
jmp ??loop16Mono ;loop until done
??cleanup16Mono:
jnz ??done16Mono ;if ebp is non-zero, we're DONE
;if exactly zero, finish the tail-end
;of the conversion (may be a non-
;multiple of 8 nybbles)
;
;
; Loop cleanup for last (incomplete) pass
pop ecx ;restore # of words
shr ecx,1 ;divide by two to get samples
and ecx,07h ;get # of samples we missed
jmp [DWORD PTR dwMono16JmpTable+ecx*4] ;go finish the job...
;
;
; Structure cleanup
??done16Mono:
pop ebx ;restore struct base
pop ebp ;restore stack frame pointer
mov [(sCompInfo ebx).dwPredicted],eax ;save last sample
mov [(sCompInfo ebx).wIndex],dx ;save last index value
mov eax,[wBytes] ;get # of bytes we did
??byeBye:
pop edx ;restore all the regs
pop ecx
pop ebx
pop edi
pop esi
ret
;
;
; Jumps for -32768/+32767 bounds check go to these vvvv
align 4
??fix1Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed1Smp16Mono ;go back
align 4
??fix1Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed1Smp16Mono ;go back
align 4
??fix2Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed2Smp16Mono ;go back
align 4
??fix2Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed2Smp16Mono ;go back
align 4
??fix3Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed3Smp16Mono ;go back
align 4
??fix3Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed3Smp16Mono ;go back
align 4
??fix4Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed4Smp16Mono ;go back
align 4
??fix4Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed4Smp16Mono ;go back
align 4
??fix5Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed5Smp16Mono ;go back
align 4
??fix5Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed5Smp16Mono ;go back
align 4
??fix6Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed6Smp16Mono ;go back
align 4
??fix6Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed6Smp16Mono ;go back
align 4
??fix7Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed7Smp16Mono ;go back
align 4
??fix7Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed7Smp16Mono ;go back
align 4
??fix8Smp16MonoO:
mov eax,00007FFFh ;Overflow - truncate to +32767
jmp ??fixed8Smp16Mono ;go back
align 4
??fix8Smp16MonoU:
mov eax,0FFFF8000h ;Underflow - truncate to -32768
jmp ??fixed8Smp16Mono ;go back
;
;
; Jump tables for cleanup after loop unroll point to these vvvv
align 4
??finish16Mono1:
xor ecx,ecx ;clear nybble bucket
mov ch,[esi] ;get 1 nybble (1 byte)
shl ch,4 ;move it over
mov bl,ch ;get nybble in ebx
sub edi,0Eh ;back edi up
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
jmp ??finish1Smp16Mono ;go finish it
align 4
??finish16Mono2:
xor ecx,ecx ;clear nybble bucket
mov ch,[esi] ;get 2 nybbles (1 byte)
mov bl,ch ;get nybbles in ebx
sub edi,0Ch ;back edi up
sub esi,3 ;adjust esi (used for dword aligning)
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
jmp ??finish2Smp16Mono ;go finish it
align 4
??finish16Mono3:
xor ecx,ecx ;clear nybble bucket
mov cx,[esi] ;get 3 nybbles (2 bytes)
shl cx,4 ;move it over
mov bl,cl ;get nybbles in ebx
sub edi,0Ah ;back edi up
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
jmp ??finish3Smp16Mono ;go finish it
align 4
??finish16Mono4:
xor ecx,ecx ;clear nybble bucket
mov cx,[esi] ;get 4 nybbles (2 bytes)
mov bl,cl ;get nybbles in ebx
sub edi,08h ;back edi up
sub esi,2 ;adjust esi (used for dword aligning)
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
jmp ??finish4Smp16Mono ;go finish it
align 4
??finish16Mono5:
xor ecx,ecx ;clear nybble bucket
mov cl,[esi+2] ;get 1 nybble (1 byte)
shl ecx,16 ;shift it over
mov cx,[esi] ;get 4 nybbles (2 bytes)
mov bl,cl ;get nybbles in ebx
shr ecx,4 ;move it over
shl bl,4 ;move it over
sub edi,06h ;back edi up
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
jmp ??finish5Smp16Mono ;go finish it
align 4
??finish16Mono6:
xor ecx,ecx ;clear nybble bucket
mov cl,[esi+2] ;get 2 nybbles (1 byte)
shl ecx,16 ;move it over
mov cx,[esi] ;get 4 nybbles (2 bytes)
mov bl,cl ;get nybbles in ebx
shr ecx,8 ;move it over
sub esi,1 ;adjust esi (used for dword aligning)
sub edi,04h ;back edi up
or dl,[BYTE PTR bNybbleTableLow+ebx] ;adjust index for nybble
jmp ??finish6Smp16Mono ;go finish it
align 4
??finish16Mono7:
xor ecx,ecx ;clear nybble bucket
mov ecx,[esi] ;get 7 nybbles (4 bytes)
shl ecx,4 ;move it over
mov bl,cl ;get nybbles in ebx
sub edi,02h ;back edi up
or dl,[BYTE PTR bNybbleTableHigh+ebx] ;adjust index for nybble
jmp ??finish7Smp16Mono ;go finish it
;
;
; Jump Tables
align 4
dwMono16JmpTable DD ??done16Mono
DD ??finish16Mono1
DD ??finish16Mono2
DD ??finish16Mono3
DD ??finish16Mono4
DD ??finish16Mono5
DD ??finish16Mono6
DD ??finish16Mono7
align 4
dwMono16AlignJmpTable DD ??fixAlign16Mono0
DD ??fixAlign16Mono1
DD ??fixAlign16Mono2
DD ??fixAlign16Mono3
ENDP sosCODECDecompressData
LABEL LockedCodeEnd BYTE
;***************************************************************************
;* sosCODEC_LOCK -- locks the JLB audio decompression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is lock sucessful, false otherwise *
;* *
;* PROTO: BOOL sosCODEC_Lock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL sosCODEC_Lock:NEAR
PROC sosCODEC_Lock C NEAR USES ebx ecx edx esi edi
;
; Lock the code that is used by the sos decompression method.
;
mov eax,0600h ; function number.
mov ecx,OFFSET LockedCodeStart ; ecx must have start of memory.
mov edi,OFFSET LockedCodeEnd ; edi will have size of region in bytes.
shld ebx,ecx,16
sub edi, ecx
shld esi,edi,16
int DPMI_INTR ; do call.
jc ??error
or [InitFlags], IF_LOCKED_PM_CODE
;
; Lock the data used by the sos decompression method.
;
mov eax,0600h ; function number.
mov ecx,OFFSET LockedDataStart ; ecx must have start of memory.
mov edi,OFFSET LockedDataEnd ; edi will have size of region in bytes.
shld ebx,ecx,16
sub edi, ecx
shld esi,edi,16
int DPMI_INTR ; do call.
jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region.
or [InitFlags], IF_LOCKED_PM_DATA
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP sosCODEC_Lock
;***************************************************************************
;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is unlock sucessful, false otherwise *
;* *
;* PROTO: BOOL sosCODEC_Unlock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL sosCODEC_Unlock:NEAR
PROC sosCODEC_Unlock C NEAR USES ebx ecx edx esi edi
test [InitFlags],IF_LOCKED_PM_CODE
jz ??code_not_locked
mov eax , 0601h
mov ecx,OFFSET LockedCodeStart ; ecx must have start of memory.
mov edi,OFFSET LockedCodeEnd ; edx will have size of region in bytes.
sub edi,ecx ; - figure size.
shld ebx , ecx , 16
shld esi , edi , 16
int DPMI_INTR ; do call.
jc ??error
??code_not_locked:
test [InitFlags],IF_LOCKED_PM_DATA
jz ??data_not_locked
mov ax,0601h ; set es to descriptor of data.
mov ecx,OFFSET LockedDataStart ; ecx must have start of memory.
mov edi,OFFSET LockedDataEnd ; edx will have size of region in bytes.
sub edi,ecx ; - figure size.
shld ebx , ecx , 16
shld esi , edi , 16
int DPMI_INTR ; do call.
jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region.
??data_not_locked:
mov [InitFlags],0
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP sosCODEC_Unlock
END

83
WIN32LIB/AUDIO/SOSCOMP.H Normal file
View File

@@ -0,0 +1,83 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
*
* File : soscomp.h
* Date Created : 6/1/94
* Description :
*
* Programmer(s) : Nick Skrepetos
* Last Modification : 10/1/94 - 11:37:9 AM
* Additional Notes : Modified by Denzil E. Long, Jr.
*
*****************************************************************************
* Copyright (c) 1994, HMI, Inc. All Rights Reserved *
****************************************************************************/
#ifndef _SOS_COMPRESS
#define _SOS_COMPRESS
/* compression types */
enum {
_ADPCM_TYPE_1,
};
/* define compression structure */
typedef struct _tagCOMPRESS_INFO {
char *lpSource;
char *lpDest;
unsigned long dwCompSize;
unsigned long dwUnCompSize;
unsigned long dwSampleIndex;
long dwPredicted;
long dwDifference;
short wCodeBuf;
short wCode;
short wStep;
short wIndex;
unsigned long dwSampleIndex2; //added BP for channel 2
long dwPredicted2; //added BP for channel 2
long dwDifference2; //added BP for channel 2
short wCodeBuf2; //added BP for channel 2
short wCode2; //added BP for channel 2
short wStep2; //added BP for channel 2
short wIndex2; //added BP for channel 2
short wBitSize;
short wChannels; //added BP for # of channels
} _SOS_COMPRESS_INFO;
/* compressed file type header */
typedef struct _tagCOMPRESS_HEADER {
unsigned long dwType; // type of compression
unsigned long dwCompressedSize; // compressed file size
unsigned long dwUnCompressedSize; // uncompressed file size
unsigned long dwSourceBitSize; // original bit size
char szName[16]; // file type, for error checking
} _SOS_COMPRESS_HEADER;
/* Prototypes */
extern "C" {
void __cdecl sosCODECInitStream(_SOS_COMPRESS_INFO *);
unsigned long __cdecl sosCODECCompressData(_SOS_COMPRESS_INFO *, unsigned long);
unsigned long __cdecl sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);
unsigned long __cdecl General_sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);
}
#endif

128
WIN32LIB/AUDIO/SOSDATA.H Normal file
View File

@@ -0,0 +1,128 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosdata.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOS_DATA
#define _SOS_DATA
#include <stddef.h>
#pragma pack(4)
extern WORD _sosDIGIData_Start;
extern WORD _sosDIGIData_End;
extern WORD _wSOSDriverLinear[];
extern WORD _wSOSTimerLinear[];
extern LPSTR _lpSOSDriver[];
extern LPSTR _lpSOSTimer[];
extern LPSTR _lpSOSDriverCS[];
extern LPSTR _lpSOSTimerCS[];
extern BOOL _wSOSDriverLoaded[];
extern BOOL _wSOSTimerLoaded[];
extern BOOL _wSOSDriverInitialized[];
extern WORD _wSOSOutputRate[];
extern WORD _wSOSDMABuffersize[];
extern LONG _dwSOSDMABufferPhysical[];
extern LPSTR _lpSOSDMABuffer[];
extern BOOL _wTimerUsed;
extern VOID ( far *_lpSOSFillHandler[] )( VOID );
extern WORD _wSOSTimerType[];
extern WORD _wSOSDriverType[];
extern _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];
extern LPWORD _lpSOSDMAIrqCount[];
extern LPWORD _lpSOSDMAFillCount[];
extern WORD _wSOSTmrNextCount;
extern VOID ( interrupt far *_lpSOSOldTimer )( VOID );
extern WORD _wSOSDriverID[];
extern _SOS_CAPABILITIES _sSOSDriverCaps[];
extern WORD _wSOSDMAPortList[];
extern BYTE _bSOSDMAChannel[];
extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[];
extern BYTE _pSOSDriverPath[];
extern BYTE _pSOSTempDriverPath[];
extern BOOL _wTIMERUsed;
extern WORD _wTIMERValue;
extern VOID ( far * _lpTIMEREvents[] )( VOID );
extern WORD _wTIMEREventRate[];
extern WORD _dwTIMEREventFraction[];
extern WORD _dwTIMEREventFractionCurrent[];
extern BYTE _bSOSMIDITimerSongHandler[];
extern BYTE _bSOSMIDISongHandle;
extern WORD _wSOSTimerMemHandle[];
extern WORD _wSOSDriverMemHandle[];
extern WORD _wSOSRealSeg[];
extern _FILEHEADER _sDETFileHeader;
extern _DRIVERHEADER _sDETDriverHeader;
extern _FILEHEADER sLOADFileHeader;
extern _DRIVERHEADER sLOADDriverHeader;
extern BOOL _wDETInitialized;
extern WORD _wDETLinear;
extern LPSTR _lpDETDriverBuffer;
extern LPSTR _lpDETDriverBufferCS;
extern WORD _hDETFile;
extern DWORD _dwDETDriverIndex;
extern WORD _wDETDriverIndexCur;
extern WORD _wDETMemHandle;
extern LPSOSDEVICECAPS _lpDETDeviceCaps;
extern _SOS_CAPABILITIES _sDETCaps;
extern PSTR _pSOSErrorStrings[];
extern BOOL _wSOSBufferAllocated[];
extern BOOL _wSOSSystemInitialized;
extern VDS_STRUCT _sSOSVDSInfo;
extern _SOS_FILL_INFO _sSOSFillInfo;
extern WORD _wSOSTimerEventIndex;
extern WORD _wSOSTimerEntered;
extern WORD _wSOSDriverSize[];
extern WORD _wSOSTimerSize[];
#ifdef __cplusplus
extern "C" {
#endif
extern WORD _sosDIGIData1_Start;
extern WORD _sosDIGIData1_End;
extern WORD _sosDIGIData2_Start;
extern WORD _sosDIGIData2_End;
extern BYTE _bTIMERInstalled;
extern BYTE _bTIMERDPMI;
extern WORD wDetectPort;
extern WORD wDetectIRQ;
extern WORD wDetectDMA;
extern WORD wDetectParam;
#ifdef __cplusplus
}
#endif
#pragma pack()
#endif

83
WIN32LIB/AUDIO/SOSDEFS.H Normal file
View File

@@ -0,0 +1,83 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosdefs.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOSDEFS_DEFINED
#define _SOSDEFS_DEFINED
#undef _TRUE
#undef _FALSE
#undef _NULL
enum
{
_FALSE,
_TRUE
};
#define _NULL 0
#ifndef VOID
#define VOID void
#endif
typedef int BOOL;
typedef unsigned int UINT;
typedef unsigned char BYTE;
typedef unsigned WORD;
#ifndef LONG
typedef signed long LONG;
#endif
typedef unsigned long DWORD;
typedef BYTE * PBYTE;
typedef char near * PSTR;
typedef WORD * PWORD;
typedef LONG * PLONG;
typedef VOID * PVOID;
typedef BYTE far * LPBYTE;
typedef BYTE far * LPSTR;
typedef WORD far * LPWORD;
typedef LONG far * LPLONG;
typedef VOID far * LPVOID;
typedef BYTE huge * HPBYTE;
typedef BYTE huge * HPSTR;
typedef WORD huge * HPWORD;
typedef LONG huge * HPLONG;
typedef VOID huge * HPVOID;
typedef unsigned HANDLE;
#endif

219
WIN32LIB/AUDIO/SOSFNCT.H Normal file
View File

@@ -0,0 +1,219 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosfnct.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOS_FUNCTIONS
#define _SOS_FUNCTIONS
#pragma pack(4)
WORD sosDIGILockMemory ( VOID );
WORD sosDIGIUnLockMemory ( VOID );
WORD sosDIGIInitSystem ( LPSTR, WORD );
WORD sosDIGIUnInitSystem ( VOID );
WORD sosDIGIInitDriver ( WORD, _SOS_HARDWARE far *,
_SOS_INIT_DRIVER far *, WORD far * );
WORD sosDIGIUnInitDriver ( WORD, BOOL, BOOL );
WORD sosDIGILoadDriver ( WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );
WORD sosDIGIUnLoadDriver ( WORD );
WORD sosDIGIGetDeviceCaps ( WORD, LPSOSDEVICECAPS );
#ifdef PHARLAP
LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * );
#else
LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * );
#endif
WORD sosDIGIStopSample ( WORD, WORD );
WORD sosDIGISamplesPlaying ( WORD );
BOOL sosDIGISampleDone ( WORD, WORD );
BOOL sosDIGISampleFilling ( WORD, WORD );
WORD sosDIGIStartSample ( WORD, _SOS_START_SAMPLE far * );
WORD sosDIGIContinueSample ( WORD, WORD, _SOS_START_SAMPLE far * );
WORD sosDIGIDetectInit ( LPSTR );
WORD sosDIGIDetectUnInit ( VOID );
WORD sosDIGIDetectFindHardware ( WORD, _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectFindFirst ( _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectFindNext ( _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectGetSettings ( _SOS_HARDWARE far * );
WORD sosDIGIDetectGetCaps ( WORD, _SOS_CAPABILITIES far * );
WORD sosDIGIDetectVerifySettings( _SOS_HARDWARE far * );
PSTR sosGetErrorString ( WORD );
WORD sosDIGILoadTimer ( WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );
WORD sosDIGIUnLoadTimer ( WORD );
WORD sosTIMERRegisterEvent ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );
WORD sosTIMERInitSystem ( WORD, WORD );
WORD sosTIMERUnInitSystem ( WORD );
WORD sosTIMERSetRate ( WORD );
WORD sosTIMERRemoveEvent ( WORD );
WORD sosTIMERAlterEventRate ( WORD, WORD );
WORD sosTIMERGetEventRate ( WORD );
VOID far sosTIMEROldHandler ( VOID );
VOID far sosTIMERHandler ( VOID );
// functions in soscntl.c
WORD sosDIGISetSampleVolume ( WORD, WORD, WORD );
WORD sosDIGIGetSampleVolume ( WORD, WORD );
WORD sosDIGISetChannel ( WORD, WORD, WORD );
WORD sosDIGIGetChannel ( WORD, WORD );
WORD sosDIGIGetBytesProcessed ( WORD, WORD );
WORD sosDIGIGetLoopCount ( WORD, WORD );
WORD sosDIGISetPanLocation ( WORD, WORD, WORD );
WORD sosDIGIGetPanLocation ( WORD, WORD );
DWORD sosDIGISetPitch ( WORD, WORD, DWORD );
DWORD sosDIGIGetPitch ( WORD, WORD );
WORD sosDIGIGetDMAPosition ( WORD );
WORD sosDIGISetPanSpeed ( WORD, WORD, WORD );
WORD sosDIGIGetPanSpeed ( WORD, WORD );
WORD sosDIGIGetSampleID ( WORD, WORD );
WORD sosDIGIGetSampleHandle ( WORD, WORD );
WORD sosDIGISetMasterVolume ( WORD, WORD );
#ifdef PHARLAP
VOID sosFreeVDSPage ( unsigned short, unsigned short, DWORD );
WORD sosAllocVDSPage ( unsigned short *, unsigned short *, DWORD * );
#else
WORD sosAllocVDSPage ( LPSTR *, WORD *, WORD * );
VOID sosFreeVDSPage ( WORD, WORD, LONG );
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef PHARLAP
extern int __cdecl sosRealFree ( int );
extern BOOL __cdecl _sos_read( WORD, LPSTR, WORD, WORD * );
extern int __cdecl sosRealAlloc( int, int *, int * );
extern void __cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );
extern int __cdecl sosGetCS( VOID );
extern int __cdecl sosGetES( VOID );
#else
extern int __cdecl sosRealAlloc ( int, int *, int * );
extern int __cdecl sosRealFree ( int );
#endif
// sos driver functions
extern WORD __cdecl sosDRVLockMemory ( DWORD, DWORD );
extern WORD __cdecl sosDRVUnLockMemory ( DWORD, DWORD );
extern void __cdecl sosDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDRVGetCapsPtr ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDRVInit ( LPSTR, LPSTR, int, int, int, int, int, int );
extern void __cdecl sosDRVStart ( LPSTR, LPSTR, int, int );
extern void __cdecl sosDRVSetRate ( LPSTR, LPSTR, int );
extern void __cdecl sosDRVSetAction ( LPSTR, LPSTR );
extern void __cdecl sosDRVStop ( LPSTR, LPSTR );
extern void __cdecl sosDRVUnInit ( LPSTR, LPSTR );
extern void __cdecl sosDRVGetFillInfo ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );
extern void __cdecl sosFillSampleStructs ( PSTR, LPSTR );
extern WORD __cdecl sosDetDRVExist ( LPSTR, LPSTR );
extern WORD __cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );
extern WORD __cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );
extern WORD __cdecl sosDIGIInitForWindows( WORD );
extern WORD __cdecl sosDIGIUnInitForWindows( WORD );
extern LPSTR __cdecl sosAllocateFarMem ( WORD, PSTR, WORD * );
extern LPSTR __cdecl sosCreateAliasCS ( LPSTR );
extern VOID __cdecl sosFreeSelector ( LPSTR, DWORD );
extern LPSTR __cdecl sosMAKEDOSPtr ( PSTR );
extern VOID __cdecl sosDetDRVSetEnvString ( DWORD, PSTR );
extern PSTR __cdecl sosDetDRVGetEnvString ( DWORD );
extern VOID __cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );
extern VOID __cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );
extern WORD __cdecl sosDRVGetFreeMemory ( VOID );
extern WORD __cdecl sosDRVAllocVDSStruct ( WORD, WORD *, WORD * );
extern WORD __cdecl sosDRVFreeVDSStruct ( WORD, WORD );
extern WORD __cdecl sosDRVIsWindowsActive ( VOID );
extern WORD __cdecl sosDRVVDSGetBuffer ( WORD );
extern WORD __cdecl sosDRVVDSFreeBuffer ( WORD );
extern WORD __cdecl getDS( VOID );
extern WORD __cdecl sosDRVMakeDMASelector ( WORD );
extern WORD __cdecl sosDRVFreeDMASelector ( WORD );
extern void __cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );
extern void __cdecl sosTIMERDRVUnInit( void );
extern void __cdecl sosTIMERDRVHandler( void );
extern void __cdecl sosTIMERDRVFHandler( void );
extern void __cdecl sosTIMERDRVEnable( void );
extern void __cdecl sosTIMERDRVDisable( void );
extern void __cdecl sosTIMERDRVCallOld( void );
extern void __cdecl sosTIMERDRVSetRate( WORD );
extern void __cdecl sosDIGITimer_Start( void );
extern void __cdecl sosDIGITimer_End( void );
extern void __cdecl sosDIGIDrv_Start( void );
extern void __cdecl sosDIGIDrv_End( void );
#ifdef __cplusplus
}
#endif
// external functions for handling system initialization and
// uninitialization
WORD sosEXDIGInitDriver ( WORD, WORD, WORD, LPSTR,
_SOS_HARDWARE far *, WORD * );
WORD sosEXDIGIUnInitDriver ( VOID );
WORD sosEXDETFindDriver ( WORD, LPSTR, _SOS_HARDWARE far *,
_SOS_CAPABILITIES far * );
// memory locking prototypes
VOID sosDIGICaps_Start( VOID );
VOID sosDIGICaps_End( VOID );
VOID sosDIGIErr_Start( VOID );
VOID sosDIGIErr_End( VOID );
VOID sosDIGITmr_Start( VOID );
VOID sosDIGITmr_End( VOID );
VOID sosDIGIStart_Start( VOID );
VOID sosDIGIStart_End( VOID );
VOID sosDIGIPlyng_Start( VOID );
VOID sosDIGIPlyng_End( VOID );
VOID sosDIGIRate_Start( VOID );
VOID sosDIGIRate_End( VOID );
VOID sosDIGIDone_Start( VOID );
VOID sosDIGIDone_End( VOID );
VOID sosDIGIDetec_Start( VOID );
VOID sosDIGIDetec_End( VOID );
VOID sosDIGIInit_Start( VOID );
VOID sosDIGIInit_End( VOID );
VOID sosDIGILoad_Start( VOID );
VOID sosDIGILoad_End( VOID );
VOID sosDIGICntl_Start( VOID );
VOID sosDIGICntl_End( VOID );
#pragma pack()
#endif

129
WIN32LIB/AUDIO/SOSRES.H Normal file
View File

@@ -0,0 +1,129 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosres.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#define _SOS_RESOURCE
#ifndef _SOS_RESOURCE
#define _SOS_RESOURCE
// structure for resource file header
typedef struct
{
// file version
WORD wVersion;
// file size
LONG dwFileSize;
// number of resources in file
WORD wResCount;
// offset of resource data from top of file
LONG dwResOffset;
// offset of sync track from top of file
LONG dwSyncTrackOffset;
} _RES_FILE_HEADER;
// structure for resource block header
typedef struct
{
// resource id
WORD wID;
// resource type
WORD wResType;
// offset of next block
LONG dwNextBlock;
// size of the current resource information
LONG dwResSize;
// rate to play block at
WORD wBlockRate;
// id for the sync track to use
WORD wSyncTrackID;
} _RES_BLOCK_HEADER;
// structure for sync mark tag
typedef struct _tagSYNCMARK
{
// ID of the type of mark being used
WORD wID;
// location in data of sync mark
LONG dwSyncOffset;
// length of sync block
LONG dwSyncSize;
// start sample data
_SOS_START_SAMPLE sampleData;
} _RES_SYNCMARK;
typedef union
{
// structure for sync mark tag
_RES_SYNCMARK syncMark;
} _RES_TAG;
// union for filter information for prepareWave
typedef union
{
// filter type
WORD wFilterID;
// structure for volume
struct volume
{
WORD wVolume;
};
// structure for delay
struct delay
{
WORD wDelaySamples;
};
} _SOS_FILTER;
#endif


54
WIN32LIB/AUDIO/SOUND.H Normal file
View File

@@ -0,0 +1,54 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood Library *
* *
* File Name : SOUND.H *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : September 1, 1993 *
* *
* Last Update : September 1, 1993 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SOUND_H
#define SOUND_H
//#define HMI_DRIVER TRUE
//#include "sos.h"
#include "soscomp.h"
/*
** Maximum number of sound effects that may run at once.
*/
#define MAX_SFX 5
/*
** Size of temp HMI low memory staging buffer.
*/
#define SECONDARY_BUFFER_SIZE (1024*32)
#endif

544
WIN32LIB/AUDIO/SOUNDINT.CPP Normal file
View File

@@ -0,0 +1,544 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : SOUNDINT.CPP *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : June 23, 1995 *
* *
* Last Update : June 28, 1995 [PWG] *
* *
* This module contains all of the functions that are used within our *
* sound interrupt. They are stored in a seperate module because memory *
* around these functions must be locked or they will cause a read to *
* be generated while in an interrupt. *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Simple_Copy -- Copyies 1 or 2 source chuncks to a dest *
* Sample_Copy -- Copies sound data from source format to raw format. *
* DigiCallback -- Low level double buffering handler. *
* save_my_regs -- Inline function which will save assembly regs *
* restore_my_regs -- Inline function which will restore saved registes *
* Audio_Add_Long_To_Pointer -- Adds an offset to a ptr casted void *
* Init_Locked_Data -- Initializes sound driver locked data *
* Audio_Mem_Set -- Quick see routine to set memory to a value *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
#pragma pack(4)
#define WIN32
#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check
#define _WIN32
#endif // _WIN32
#include <windows.h>
#include <windowsx.h>
#include "dsound.h"
#include <wwstd.h>
#include "soundint.h"
#include "memflag.h"
#include "audio.h"
extern DebugBuffer[];
/***************************************************************************
** All routines past this point must be locked for the sound driver to **
** function under a VCPI memory manager. These locks are unnecessary if **
** the driver does not have to run under windows or does not use virtual **
** memory. **
***************************************************************************/
/***************************************************************************
* SIMPLE_COPY -- Copyies 1 or 2 source chuncks to a dest *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
long Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size)
{
long out = 0; // Number of bytes copied to the destination.
/*
** It could happen that entering this routine, the source buffer
** has been exhausted, but the alternate buffer is still valid.
** Move the alternate into the primary position before proceeding.
*/
if (!(*ssize)) {
*source = *alternate;
*ssize = *altsize;
*alternate = NULL;
*altsize = 0;
}
if (*source && *ssize) {
long s; // Scratch length var.
/*
** Copy as much as possible from the primary source, but no
** more than the primary source has to offer.
*/
s = size;
if (*ssize < s) s = *ssize;
Mem_Copy(*source, *dest, s);
*source = Audio_Add_Long_To_Pointer(*source, s);
*ssize -= s;
*dest = Audio_Add_Long_To_Pointer(*dest, s);
size -= s;
out += s;
/*
** If the primary source was insufficient to fill the request, then
** move the alternate into the primary position and try again.
*/
if (size) {
*source = *alternate;
*ssize = *altsize;
*alternate = 0;
*altsize = 0;
out += Simple_Copy(source, ssize, alternate, altsize, dest, size);
}
}
return(out);
}
/***********************************************************************************************
* Sample_Copy -- Copies sound data from source format to raw format. *
* *
* This routine is used to copy the sound data (possibly compressed) to the destination *
* buffer in raw format. *
* *
* INPUT: source -- Pointer to the source data (possibly compressed). *
* *
* dest -- Pointer to the destination buffer. *
* *
* size -- The size of the destination buffer. *
* *
* OUTPUT: Returns with the number of bytes placed into the output buffer. This is usually *
* the number of bytes requested except in the case when the source is exhausted. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 09/03/1994 JLB : Created. *
* 09/04/1994 JLB : Revamped entirely. *
*=============================================================================================*/
#pragma argsused
long Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * , short int *)
{
long s;
long datasize = 0; // Output bytes.
switch (scomp) {
default:
case SCOMP_NONE:
datasize = Simple_Copy(source, ssize, alternate, altsize, &dest, size);
break;
case SCOMP_WESTWOOD:
case SCOMP_SOS:
while (size > 0) {
/*
** The block spans two buffers. It must be copied down to
** a staging area before it can be decompressed.
*/
{
long magic;
unsigned short fsize;
unsigned short dsize;
void *fptr;
void *dptr;
void *mptr;
fptr = &fsize;
dptr = &dsize;
mptr = &magic;
s = Simple_Copy(source, ssize, alternate, altsize, &fptr, sizeof(fsize));
if (s < sizeof(fsize)) {
return datasize;
}
s = Simple_Copy(source, ssize, alternate, altsize, &dptr, sizeof(dsize));
if (s < sizeof(dsize) || size < dsize) {
return datasize;
}
s = Simple_Copy(source, ssize, alternate, altsize, &mptr, sizeof(magic));
if (s < sizeof(magic) || magic != LockedData.MagicNumber) {
return datasize;
}
/*
** If the frame and uncompressed data size are identical, then this
** indicates that the frame is not compressed. Just copy it directly
** to the destination buffer in this case.
*/
if (fsize == dsize) {
s = Simple_Copy(source, ssize, alternate, altsize, &dest, fsize);
if (s < dsize) {
return (datasize);
}
} else {
/*
** The frame was compressed, so copy it to the staging buffer, and then
** uncompress it into the final destination buffer.
*/
fptr = LockedData.UncompBuffer;
s = Simple_Copy(source, ssize, alternate, altsize, &fptr, fsize);
if (s < fsize) {
return (datasize);
}
if (scomp == SCOMP_WESTWOOD) {
Decompress_Frame(LockedData.UncompBuffer, dest, dsize);
} else {
st->sosinfo.lpSource = (char *)LockedData.UncompBuffer;
st->sosinfo.lpDest = (char *)dest;
if (st->sosinfo.wBitSize==16 && st->sosinfo.wChannels==1){
sosCODECDecompressData(&st->sosinfo, dsize);
} else {
General_sosCODECDecompressData(&st->sosinfo, dsize);
}
}
dest = Audio_Add_Long_To_Pointer(dest, dsize);
}
datasize += dsize;
size -= dsize;
}
}
break;
}
return(datasize);
}
extern int Convert_HMI_To_Direct_Sound_Volume(int volume);
/***********************************************************************************************
* maintenance_callback -- routine to service the direct play secondary buffers *
* and other stuff..? *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* ....Unknown *
* 10/17/95 10:15PM ST : tidied up a tad for direct sound *
*=============================================================================================*/
VOID far __cdecl maintenance_callback(VOID)
{
int index; //index used in for loop
SampleTrackerType *st; //ptr to SampleTracker structure
DWORD play_cursor; //Position that direct sound is reading from
DWORD write_cursor; //Position in buffer that we can write to
int bytes_copied; //Number of bytes copied into the buffer
BOOL write_more; //Flag to set if we need to write more into the buffer
LPVOID play_buffer_ptr; //Beginning of locked area of buffer
LPVOID dummy_buffer_ptr; //Length of locked area in buffer
DWORD lock_length1; //Beginning of second locked area in buffer
DWORD lock_length2; //Length of second locked area in buffer
HRESULT return_code;
//EnterCriticalSection(&GlobalAudioCriticalSection);
st = &LockedData.SampleTracker[0];
for (index = 0; index < MAX_SFX; index++) {
if (st->Active) {
/*
** General service routine to handle moving small blocks from the
** source into the direct sound buffers. If the source is
** compressed, then this will also uncompress it as the copy
** is performed.
*/
if (st->Service && !st->DontTouch ) {
//EnterCriticalSection (&st->AudioCriticalSection);
st->DontTouch = TRUE;
/*
** Get the current position of the direct sound play cursor within the buffer
*/
return_code = st->PlayBuffer->GetCurrentPosition ( &play_cursor , &write_cursor );
/*
** Check for unusual situations like a focus loss
*/
if (return_code != DS_OK){
if (return_code == DSERR_BUFFERLOST){
if (Audio_Focus_Loss_Function){
Audio_Focus_Loss_Function();
}
}
//LeaveCriticalSection(&GlobalAudioCriticalSection);
//LeaveCriticalSection (&st->AudioCriticalSection);
return; //Our app has lost focus or something else nasty has happened
} //so dont update the sound buffers
if (st->MoreSource){
/*
** If the direct sound read pointer is less than a quarter
** of a buffer away from the end of the data then copy some
** more.
*/
write_more = FALSE;
if ( play_cursor < (unsigned)st->DestPtr ){
if ( (unsigned)st->DestPtr - (unsigned)play_cursor <= SECONDARY_BUFFER_SIZE/4 ){
write_more=TRUE;
}
} else {
/* The only time that play_cursor can be greater than DestPtr is
** if we wrote right to the end of the buffer last time and DestPtr
** looped back to the beginning of the buffer.
** That being the case, all we have to do is see if play_cursor is
** within the last 25% of the buffer
*/
if ( ( (int)play_cursor > SECONDARY_BUFFER_SIZE*3/4) &&st->DestPtr==0 ){
write_more=TRUE;
}
}
if (write_more){
/*
** Lock a 1/2 of the direct sound buffer so we can write to it
*/
if ( DS_OK== st->PlayBuffer->Lock ( (DWORD)st->DestPtr ,
(DWORD)SECONDARY_BUFFER_SIZE/2,
&play_buffer_ptr,
&lock_length1,
&dummy_buffer_ptr,
&lock_length2,
0 )){
bytes_copied = Sample_Copy( st,
&st->Source,
&st->Remainder,
&st->QueueBuffer,
&st->QueueSize,
play_buffer_ptr,
SECONDARY_BUFFER_SIZE/4,
st->Compression,
&st->Trailer[0],
&st->TrailerLen);
if ( bytes_copied != (SECONDARY_BUFFER_SIZE/4) ){
/*
** We must have reached the end of the sample
*/
st->MoreSource=FALSE;
memset (((char*)play_buffer_ptr)+bytes_copied ,
0 ,
(SECONDARY_BUFFER_SIZE/4)-bytes_copied);
/*
** Clear out an extra area in the buffer ahead of the play cursor
** to give us a quiet period of grace in which to stop the buffer playing
*/
if ( (unsigned)st->DestPtr == SECONDARY_BUFFER_SIZE*3/4 ){
if ( dummy_buffer_ptr && lock_length2 ){
memset (dummy_buffer_ptr , 0 , lock_length2);
}
} else {
memset ((char*)play_buffer_ptr+SECONDARY_BUFFER_SIZE/4 , 0 , SECONDARY_BUFFER_SIZE/4);
}
}
/*
** Update our pointer into the direct sound buffer
**
*/
st->DestPtr = Audio_Add_Long_To_Pointer (st->DestPtr,bytes_copied);
if ( (unsigned)st->DestPtr >= (unsigned)SECONDARY_BUFFER_SIZE ){
st->DestPtr = Audio_Add_Long_To_Pointer (st->DestPtr,(long)-SECONDARY_BUFFER_SIZE);
}
/*
** Unlock the direct sound buffer
*/
st->PlayBuffer->Unlock( play_buffer_ptr,
lock_length1,
dummy_buffer_ptr,
lock_length2);
}
} //write_more
} else { //!more_source
/*
** no more source to write - check if the buffer play
** has overrun the end of the sample and stop it if it has
*/
if ( ( (play_cursor >= (unsigned)st->DestPtr) && ( ((unsigned)play_cursor - (unsigned)st->DestPtr) <SECONDARY_BUFFER_SIZE/4) ) ||
(!st->OneShot &&( (play_cursor < (unsigned)st->DestPtr) && ( ((unsigned)st->DestPtr - (unsigned)play_cursor) >(SECONDARY_BUFFER_SIZE*3/4) ) )) ){
st->PlayBuffer->Stop();
st->Service = FALSE;
Stop_Sample( index );
}
} //more_source
st->DontTouch = FALSE;
//LeaveCriticalSection (&st->AudioCriticalSection);
}
/*
** For file streamed samples, fill the queue pointer if needed.
** This allows for delays in calling the Sound_Callback function.
*/
if (!st->DontTouch && !st->QueueBuffer && st->FilePending) {
st->QueueBuffer = Audio_Add_Long_To_Pointer(st->FileBuffer, (long)(st->Odd%LockedData.StreamBufferCount)*(long)LockedData.StreamBufferSize);
st->FilePending--;
st->Odd++;
if (!st->FilePending) {
st->QueueSize = st->FilePendingSize;
} else {
st->QueueSize = LockedData.StreamBufferSize;
}
}
}
/*
** Advance to the next sample control structure.
*/
st++;
}
if (!LockedData._int) {
LockedData._int++;
st = &LockedData.SampleTracker[0];
for (index = 0; index < MAX_SFX; index++) {
/*
** If there are any samples that require fading, then do so at this
** time.
*/
if (st->Active && st->Reducer && st->Volume) {
//EnterCriticalSection (&st->AudioCriticalSection);
if (st->Reducer >= st->Volume) {
st->Volume = 0;
} else {
st->Volume -= st->Reducer;
}
//st->PlayBuffer->SetVolume (-( ( (32768-st->Volume)*1000) >>15 ) );
if (st->IsScore){
st->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume( ( LockedData.ScoreVolume*(st->Volume >>7))/256) );
}else{
st->PlayBuffer->SetVolume ( Convert_HMI_To_Direct_Sound_Volume( ( LockedData.SoundVolume*(st->Volume >>7))/256) );
}
//LeaveCriticalSection (&st->AudioCriticalSection);
}
st++;
}
LockedData._int--;
}
//LeaveCriticalSection(&GlobalAudioCriticalSection);
}
/***************************************************************************
* ADD_LONG_TO_POINTER -- Adds an offset to a ptr casted void *
* *
* INPUT: void * ptr - the pointer to add to *
* long size - the size to add to it *
* *
* OUTPUT: void * ptr - the new location it will point to *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
void *Audio_Add_Long_To_Pointer(void const *ptr, long size)
{
return ((void *) ( (char const *) ptr + size));
}
/***************************************************************************
* AUDIO_MEM_SET -- Quick see routine to set memory to a value *
* *
* INPUT: void const * - the memory that needs to be set *
* unsigned char - the value to set the memory to *
* long size - how big an area to set *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 06/28/1995 PWG : Created. *
*=========================================================================*/
void Audio_Mem_Set(void const *ptr, unsigned char value, long size)
{
unsigned char *temp = (unsigned char *)ptr;
for (int lp = 0; lp < size; lp ++) {
*temp++ = value;
}
}

292
WIN32LIB/AUDIO/SOUNDINT.H Normal file
View File

@@ -0,0 +1,292 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : SOUNDINT.H *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : June 23, 1995 *
* *
* Last Update : June 23, 1995 [PWG] *
* *
* This file is the include file for the Westwood Sound Sytem defines and *
* routines that are handled in an interrupt.
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "sound.h"
/*
** Defines for true and false. These are included because we do not allow
** the sound int to include any of the westwood standard headers. If we
** did, there might be too much temptation to call another library function.
** this would be bad, because then that function would not be locked.
*/
#define FALSE 0
#define TRUE 1
/*
** Define the different type of sound compression avaliable to the westwood
** library.
*/
typedef enum {
SCOMP_NONE=0, // No compression -- raw data.
SCOMP_WESTWOOD=1, // Special sliding window delta compression.
SCOMP_SONARC=33, // Sonarc frame compression.
SCOMP_SOS=99 // SOS frame compression.
} SCompressType;
/*
** This is the safety overrun margin for the sonarc compressed
** data frames. This value should be equal the maximum 'order' times
** the maximum number of bytes per sample. It should be evenly divisible
** by 16 to aid paragraph alignment.
*/
#define SONARC_MARGIN 32
/*
** Define the sample control structure which helps us to handle feeding
** data to the sound interrupt.
*/
#pragma pack(1);
typedef struct {
/*
** This flags whether this sample structure is active or not.
*/
unsigned Active;
//unsigned Active:1;
/*
** This flags whether the sample is loading or has been started.
*/
//unsigned Loading:1;
unsigned Loading;
/*
** This semaphore ensures that simultaneous update of this structure won't
** occur. This is necessary since both interrupt and regular code can modify
** this structure.
*/
//unsigned DontTouch:1;
unsigned DontTouch;
/*
** If this sample is really to be considered a score rather than
** a sound effect, then special rules apply. These largely fall into
** the area of volume control.
*/
//unsigned IsScore:1;
unsigned IsScore;
/*
** This is the original sample pointer. It is used to control the sample based on
** pointer rather than handle. The handle method is necessary when more than one
** sample could be playing simultaneously. The pointer method is necessary when
** the dealing with a sample that may have stopped behind the programmer's back and
** this occurance is not otherwise determinable. It is also used in
** conjunction with original size to unlock a sample which has been DPMI
** locked.
*/
void const *Original;
long OriginalSize;
/*
** These are pointers to the double buffers.
*/
LPDIRECTSOUNDBUFFER PlayBuffer;
/*
** Variable to keep track of the playback rate of this buffer
*/
int PlaybackRate;
/*
** Variable to keep track of the sample type ( 8 or 16 bit ) of this buffer
*/
int BitSize;
/*
** Variable to keep track of the stereo ability of this buffer
*/
int Stereo;
/*
** The number of bytes in the buffer that has been filled but is not
** yet playing. This value is normally the size of the buffer,
** except for the case of the last bit of the sample.
*/
LONG DataLength;
/*
** This is the buffer index for the low buffer that
** has been filled with data but not yet being
** played.
*/
// short int Index;
/*
** Pointer into the play buffer for writing the next
** chunk of sample to
**
*/
VOID *DestPtr;
/*
** This flag indicates that there is more source data
** to copy to the play buffer
**
*/
BOOL MoreSource;
/*
** This flag indicates that the entire sample fitted inside the
** direct sound secondary buffer
**
*/
BOOL OneShot;
/*
** Pointer to the sound data that has not yet been copied
** to the playback buffers.
*/
VOID *Source;
/*
** This is the number of bytes remaining in the source data as
** pointed to by the "Source" element.
*/
LONG Remainder;
/*
** Object to use with Enter/LeaveCriticalSection
**
*/
CRITICAL_SECTION AudioCriticalSection;
/*
** Samples maintain a priority which is used to determine
** which sounds live or die when the maximum number of
** sounds are being played.
*/
int Priority;
/*
** This is the handle as returned by sosDIGIStartSample function.
*/
short int Handle;
/*
** This is the current volume of the sample as it is being played.
*/
int Volume;
int Reducer; // Amount to reduce volume per tick.
/*
** This is the compression that the sound data is using.
*/
SCompressType Compression;
short int TrailerLen; // Number of trailer bytes in buffer.
BYTE Trailer[SONARC_MARGIN]; // Maximum number of 'order' samples needed.
DWORD Pitch;
WORD Flags;
/*
** This flag indicates whether this sample needs servicing.
** Servicing entails filling one of the empty low buffers.
*/
short int Service;
/*
** This flag is TRUE when the sample has stopped playing,
** BUT there is more data available. The sample must be
** restarted upon filling the low buffer.
*/
BOOL Restart;
/*
** Streaming control handlers.
*/
BOOL (*Callback)(short int id, short int *odd, VOID **buffer, LONG *size);
VOID *QueueBuffer; // Pointer to continued sample data.
LONG QueueSize; // Size of queue buffer attached.
short int Odd; // Block number tracker (0..StreamBufferCount-1).
int FilePending; // Number of buffers already filled ahead.
long FilePendingSize; // Number of bytes in last filled buffer.
/*
** The file variables are used when streaming directly off of the
** hard drive.
*/
int FileHandle; // Streaming file handle (ERROR = not in use).
VOID *FileBuffer; // Temporary streaming buffer (allowed to be freed).
/*
** The following structure is used if the sample if compressed using
** the sos 16 bit compression Codec.
*/
_SOS_COMPRESS_INFO sosinfo;
} SampleTrackerType;
typedef struct LockedData {
unsigned int DigiHandle; // = -1;
BOOL ServiceSomething; // = FALSE;
long MagicNumber; // = 0xDEAF;
VOID *UncompBuffer; // = NULL;
long StreamBufferSize; // = (2*SECONDARY_BUFFER_SIZE)+128;
short StreamBufferCount; // = 32;
SampleTrackerType SampleTracker[MAX_SFX];
unsigned int SoundVolume;
unsigned int ScoreVolume;
BOOL _int;
} LockedDataType;
extern LockedDataType LockedData;
#pragma pack(4);
void Init_Locked_Data(void);
long Simple_Copy(void ** source, long * ssize, void ** alternate, long * altsize, void **dest, long size);
long Sample_Copy(SampleTrackerType *st, void ** source, long * ssize, void ** alternate, long * altsize, void * dest, long size, SCompressType scomp, void * trailer, short int *trailersize);
VOID far __cdecl maintenance_callback(VOID);
VOID __cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid);
void far HMI_TimerCallback(void);
void *Audio_Add_Long_To_Pointer(void const *ptr, long size);
void DPMI_Unlock(VOID const *ptr, long const size);
extern "C" {
void __cdecl Audio_Mem_Set(void const *ptr, unsigned char value, long size);
// void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);
long __cdecl Decompress_Frame(void * source, void * dest, long size);
int __cdecl Decompress_Frame_Lock(void);
int __cdecl Decompress_Frame_Unlock(void);
int __cdecl sosCODEC_Lock(void);
int __cdecl sosCODEC_Unlock(void);
void __GETDS(void);
}

2207
WIN32LIB/AUDIO/SOUNDIO.CPP Normal file

File diff suppressed because it is too large Load Diff

120
WIN32LIB/AUDIO/SOUNDLCK.CPP Normal file
View File

@@ -0,0 +1,120 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : SOUNDLCK.CPP *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : June 23, 1995 *
* *
* Last Update : June 23, 1995 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check
#define _WIN32
#endif // _WIN32
#define WIN32
#include <windows.h>
#include <windowsx.h>
#include <objbase.h>
#include "dsound.h"
#include <mem.h>
#include "wwmem.h"
#include "wwstd.h"
#include "soundint.h"
LockedDataType LockedData;
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* INIT_LOCKED_DATA -- Initializes sound driver locked data *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
void Init_Locked_Data(void)
{
/*
** Initialize all of the data elements that need to be locked.
*/
LockedData.DigiHandle = -1;
LockedData.ServiceSomething = FALSE;
LockedData.MagicNumber = 0xDEAF;
LockedData.UncompBuffer = NULL;
// LockedData.StreamBufferSize = (2*SECONDARY_BUFFER_SIZE)+128;
LockedData.StreamBufferSize = (SECONDARY_BUFFER_SIZE/4)+128;
LockedData.StreamBufferCount = 16;
LockedData.SoundVolume = 255;
LockedData.ScoreVolume = 255;
LockedData._int = FALSE;
#ifdef cuts
/*
** Lock the sound specific c functions that will cause us problems if
** they are swapped out during an interrupt.
*/
DPMI_Lock(&LockedData, 4096L);
DPMI_Lock(Simple_Copy, 4096L);
DPMI_Lock(Sample_Copy, 4096L);
DPMI_Lock((void *)maintenance_callback, 4096L);
DPMI_Lock((void *)DigiCallback, 4096L);
DPMI_Lock((void *)HMI_TimerCallback, 4096L);
DPMI_Lock(Audio_Add_Long_To_Pointer, 4096L);
DPMI_Lock(DPMI_Unlock, 4096L);
/*
** Lock the library functions that will cause us problems if they are
** swapped out during an interrupt.
*/
DPMI_Lock(Mem_Copy, 4096L);
DPMI_Lock(Audio_Mem_Set, 4096L);
DPMI_Lock(__GETDS, 4096L);
/*
** Finally lock the two assembly modules that need locking. This can
** be handled by calling the lock function that is local to thier module
** swapped out during an interrupt.
*/
Decompress_Frame_Lock();
sosCODEC_Lock();
#endif //cuts
}

39
WIN32LIB/AUDIO/TEST.CPP Normal file
View File

@@ -0,0 +1,39 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include "audio.h"
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
File_Stream_Sample_Vol("file", 0, 0);
return (0);
}

32
WIN32LIB/AUDIO/TST.CPP Normal file
View File

@@ -0,0 +1,32 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#undef _WINDOWS_16_
#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check
#define _WIN32
#endif // _WIN32
#define WIN32
#define __WIN32
#include <windows.h>
#include <windowsx.h>
#include <ole2.h>
main
{}