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

152
WWFLAT32/AUDIO/AUDIO.BAK Normal file
View File

@@ -0,0 +1,152 @@
/*
** 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 {
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;
typedef enum RateEnum {
PLAYBACK_RATE_SLOW =11025,
PLAYBACK_RATE_NORMAL =(11025 * 2),
PLAYBACK_RATE_FAST =(11025 * 4),
} RateType;
/*=========================================================================*/
/* 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 _saveregs Sound_Callback(void);
void cdecl far __saveregs __loadds 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 Sound_Init(int sfx, int score, int sample, RateType rate, int bits_per_sample, int max_samples, int reverse_channels);
BOOL Audio_Init(int sample, int address, int inter, int dma, RateType rate, int bits_per_sample, int max_samples, int reverse_channels = FALSE);
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);
extern int Misc;
extern SFX_Type SoundType;
extern Sample_Type SampleType;

153
WWFLAT32/AUDIO/AUDIO.H Normal file
View File

@@ -0,0 +1,153 @@
/*
** 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 {
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;
typedef enum RateEnum {
PLAYBACK_RATE_SLOW =11025,
PLAYBACK_RATE_NORMAL =(11025 * 2),
PLAYBACK_RATE_FAST =(11025 * 4),
} RateType;
/*=========================================================================*/
/* 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 _saveregs Sound_Callback(void);
void cdecl far __saveregs __loadds 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 Sound_Init(int sfx, int score, int sample, RateType rate, int bits_per_sample, int max_samples, int reverse_channels);
BOOL Audio_Init(int sample, int address, int inter, int dma, RateType rate, int bits_per_sample, int max_samples, int reverse_channels = FALSE);
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);
extern int Misc;
extern SFX_Type SoundType;
extern Sample_Type SampleType;
extern short StreamLowImpact;

437
WWFLAT32/AUDIO/AUDUNCMP.ASM Normal file
View File

@@ -0,0 +1,437 @@
;
; 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 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
pushf
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]
pushf
cmp [_4bitdecode+ebx],0
jl short ??neg1
popf
jnc short ??ok1
mov dl,0FFh
jmp short ??ok1
??neg1:
popf
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]
pushf
cmp [_4bitdecode+ebx],0
jl short ??neg2
popf
jnc short ??ok2
mov dh,0FFh
jmp short ??ok2
??neg2:
popf
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]
pushf
cmp [_2bitdecode+ebx],0
jl short ??neg3
popf
jnc short ??ok3
mov dl,0FFh
jmp short ??ok3
??neg3:
popf
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]
pushf
cmp [_2bitdecode+ebx],0
jl short ??neg4
popf
jnc short ??ok4
mov dl,0FFh
jmp short ??ok4
??neg4:
popf
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]
pushf
cmp [_2bitdecode+ebx],0
jl short ??neg5
popf
jnc short ??ok5
mov dl,0FFh
jmp short ??ok5
??neg5:
popf
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]
pushf
cmp [_2bitdecode+ebx],0
jl short ??neg6
popf
jnc short ??ok6
mov dl,0FFh
jmp short ??ok6
??neg6:
popf
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:
popf
mov eax,[incount]
ret
ENDP Decompress_Frame
LABEL LockedCodeEnd BYTE
;***************************************************************************
;* DECOMPRESS_FRAME_LOCK -- locks the JLB audio decompression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is lock sucessful, false otherwise *
;* *
;* PROTO: BOOL Decompress_Frame_Lock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL Decompress_Frame_Lock:NEAR
PROC Decompress_Frame_Lock C NEAR USES ebx ecx edx esi edi
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
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP Decompress_Frame_Lock
;***************************************************************************
;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is unlock sucessful, false otherwise *
;* *
;* PROTO: BOOL Decompress_Frame_Unlock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL Decompress_Frame_Unlock:NEAR
PROC Decompress_Frame_Unlock C NEAR USES ebx ecx edx esi edi
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
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP Decompress_Frame_Unlock
END

1448
WWFLAT32/AUDIO/DIFFTB.INC Normal file

File diff suppressed because it is too large Load Diff

47
WWFLAT32/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
WWFLAT32/AUDIO/INDEXTB.INC Normal file

File diff suppressed because it is too large Load Diff

191
WWFLAT32/AUDIO/MAKEFILE Normal file
View File

@@ -0,0 +1,191 @@
#
# 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: *
#* WWFLAT = your root WWFLAT path *
#* WWVCS = root directory for wwlib version control archive *
#* WATCOM = 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 %WWFLAT
!error WWFLAT Environment var not configured.
!endif
!ifndef %WWVCS
!error WWVCS 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 = $(%WWFLAT)\$(PROJ_NAME)
LIB_DIR = $(%WWFLAT)\lib
!include $(%WWFLAT)\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.
#---------------------------------------------------------------------------
.asm: $(PROJ_DIR)
.c: $(PROJ_DIR)
.cpp: $(PROJ_DIR)
.h: $(PROJ_DIR)
.obj: $(PROJ_DIR)
.lib: $(%WWFLAT)\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 = 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 = $(%WWFLAT)\LIB;$(%WATCOM)\LIB
INCLUDEPATH = $(%WWFLAT)\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: $(%WWFLAT)\project.cfg .AUTODEPEND
$(C_CMD) $(CC_CFG) $<
.cpp.obj: $(%WWFLAT)\project.cfg .AUTODEPEND
$(CPP_CMD) $(CC_CFG) $<
.asm.obj: $(%WWFLAT)\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 WWFLAT\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc
copy *.lib $(%WWFLAT)\lib
copy *.h $(%WWFLAT)\include
copy *.inc $(%WWFLAT)\include
copy *.cpp $(%WWFLAT)\srcdebug
copy *.asm $(%WWFLAT)\srcdebug
copy *.lib $(%WWFLAT)\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
soundio.obj: .AUTODEPEND
$(CPP_CMD) -zp4 -5s -mf -s -d2 /i=$(%WWFLAT)\include soundio.cpp
#---------------------------------------------------------------------------
# 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 ******************************


152
WWFLAT32/AUDIO/NEW/AUDIO.H Normal file
View File

@@ -0,0 +1,152 @@
/*
** 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 {
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;
typedef enum RateEnum {
PLAYBACK_RATE_SLOW =11025,
PLAYBACK_RATE_NORMAL =(11025 * 2),
PLAYBACK_RATE_FAST =(11025 * 4),
} RateType;
/*=========================================================================*/
/* 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 _saveregs Sound_Callback(void);
void cdecl far __saveregs __loadds 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 Sound_Init(int sfx, int score, int sample, RateType rate, int bits_per_sample, int max_samples, int reverse_channels);
BOOL Audio_Init(int sample, int address, int inter, int dma, RateType rate, int bits_per_sample, int max_samples, int reverse_channels = FALSE);
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);
extern int Misc;
extern SFX_Type SoundType;
extern Sample_Type SampleType;

View File

@@ -0,0 +1,437 @@
;
; 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 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
pushf
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]
pushf
cmp [_4bitdecode+ebx],0
jl short ??neg1
popf
jnc short ??ok1
mov dl,0FFh
jmp short ??ok1
??neg1:
popf
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]
pushf
cmp [_4bitdecode+ebx],0
jl short ??neg2
popf
jnc short ??ok2
mov dh,0FFh
jmp short ??ok2
??neg2:
popf
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]
pushf
cmp [_2bitdecode+ebx],0
jl short ??neg3
popf
jnc short ??ok3
mov dl,0FFh
jmp short ??ok3
??neg3:
popf
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]
pushf
cmp [_2bitdecode+ebx],0
jl short ??neg4
popf
jnc short ??ok4
mov dl,0FFh
jmp short ??ok4
??neg4:
popf
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]
pushf
cmp [_2bitdecode+ebx],0
jl short ??neg5
popf
jnc short ??ok5
mov dl,0FFh
jmp short ??ok5
??neg5:
popf
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]
pushf
cmp [_2bitdecode+ebx],0
jl short ??neg6
popf
jnc short ??ok6
mov dl,0FFh
jmp short ??ok6
??neg6:
popf
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:
popf
mov eax,[incount]
ret
ENDP Decompress_Frame
LABEL LockedCodeEnd BYTE
;***************************************************************************
;* DECOMPRESS_FRAME_LOCK -- locks the JLB audio decompression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is lock sucessful, false otherwise *
;* *
;* PROTO: BOOL Decompress_Frame_Lock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL Decompress_Frame_Lock:NEAR
PROC Decompress_Frame_Lock C NEAR USES ebx ecx edx esi edi
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
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP Decompress_Frame_Lock
;***************************************************************************
;* DECOMPRESS_FRAME_UNLOCK -- Unlocks the JLB audio compression code *
;* *
;* INPUT: none *
;* *
;* OUTPUT: BOOL true is unlock sucessful, false otherwise *
;* *
;* PROTO: BOOL Decompress_Frame_Unlock(void); *
;* *
;* HISTORY: *
;* 06/26/1995 PWG : Created. *
;*=========================================================================*
GLOBAL Decompress_Frame_Unlock:NEAR
PROC Decompress_Frame_Unlock C NEAR USES ebx ecx edx esi edi
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
mov eax,1
jmp ??exit
??error:
xor eax,eax
??exit:
ret
ENDP Decompress_Frame_Unlock
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

191
WWFLAT32/AUDIO/NEW/MAKEFILE Normal file
View File

@@ -0,0 +1,191 @@
#
# 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: *
#* WWFLAT = your root WWFLAT path *
#* WWVCS = root directory for wwlib version control archive *
#* WATCOM = 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 %WWFLAT
!error WWFLAT Environment var not configured.
!endif
!ifndef %WWVCS
!error WWVCS 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 = $(%WWFLAT)\$(PROJ_NAME)
LIB_DIR = $(%WWFLAT)\lib
!include $(%WWFLAT)\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.
#---------------------------------------------------------------------------
.asm: $(PROJ_DIR)
.c: $(PROJ_DIR)
.cpp: $(PROJ_DIR)
.h: $(PROJ_DIR)
.obj: $(PROJ_DIR)
.lib: $(%WWFLAT)\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 = 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 = $(%WWFLAT)\LIB;$(%WATCOM)\LIB
INCLUDEPATH = $(%WWFLAT)\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: $(%WWFLAT)\project.cfg .AUTODEPEND
$(C_CMD) $(CC_CFG) $<
.cpp.obj: $(%WWFLAT)\project.cfg .AUTODEPEND
$(CPP_CMD) $(CC_CFG) $<
.asm.obj: $(%WWFLAT)\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 WWFLAT\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc
copy *.lib $(%WWFLAT)\lib
copy *.h $(%WWFLAT)\include
copy *.inc $(%WWFLAT)\include
copy *.cpp $(%WWFLAT)\srcdebug
copy *.asm $(%WWFLAT)\srcdebug
copy *.lib $(%WWFLAT)\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
soundio.obj: .AUTODEPEND
$(CPP_CMD) -zp4 -5s -mf -s -d2 /i=$(%WWFLAT)\include soundio.cpp
#---------------------------------------------------------------------------
# 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,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

565
WWFLAT32/AUDIO/NEW/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,871 @@
;
; 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 DD -1,-1,-1,-1,2,4,6,8
DD -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 DD 7, 8, 9, 10, 11, 12, 13,14
DD 16, 17, 19, 21, 23, 25, 28, 31
DD 34, 37, 41, 45, 50, 55, 60, 66
DD 73, 80, 88, 97, 107, 118, 130, 143
DD 157, 173, 190, 209, 230, 253, 279, 307
DD 337, 371, 408, 449, 494, 544, 598, 658
DD 724, 796, 876, 963, 1060, 1166, 1282, 1411
DD 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024
DD 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484
DD 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899
DD 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794
DD 32767
wCode DD 0 ; this is to hold index into wCodeStep
dwCODECByteIndex DD 0 ; this is when to stop compressing
dwCODECBytesProcessed DD 0 ; this is how many so far compressed
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 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 sosCODECDecompressData:NEAR
PROC sosCODECDecompressData C NEAR
ARG sSOSInfo:NEAR PTR
ARG wBytes:DWORD
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
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
;---------------------------------------------------------------------------
push ebp
movzx edx,[(sCompInfo ebx).wIndex] ;preload index
mov ebp, [dwCODECByteIndex]
mov ecx,[(sCompInfo ebx).dwSampleIndex] ;preload SampleIndex
??mainloop:
xor eax,eax ;get a new token
test ecx,1 ;odd Sample??
je short ??fetchToken ; if so get new token
mov ax,[(sCompInfo ebx).wCodeBuf] ;ored with Code
shr eax,4
jmp short ??calcDifference
align 4
??fetchToken:
mov al,[esi] ;put in codebuf
inc esi
mov [(sCompInfo ebx).wCodeBuf],ax
??calcDifference:
xor ecx,ecx
and eax,000Fh
mov cx,[(sCompInfo ebx).wStep] ;cx is step value
mov [wCode],eax
jmp [DWORD PTR JumpTable + eax*4]
align 4
; note: it is important for speed reasons to keep the order the
; following jumps entries as well as the "align 4" after some of
; the jmp statements
??7:
; eax = x + x/2 + x/4 + x/8 = (8*x + 4*x +2*x + x)>>3 =
; = ( x * ( 8 + 4 + 2 + 1 )) >> 3 = ( x * 15 ) >> 3
lea ecx,[ecx+ecx*2]
lea eax,[ecx+ecx*4]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??6:
; eax = x + x / 2 + x / 8 = (8*x + 4*x + x) >> 3 =
; = ( x * 8 + x * 5 ) >> 8
lea eax,[ecx+ecx*4]
lea eax,[eax+ecx*8]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??5:
; eax = x + x / 4 + x / 8 = (8*x + 2*x + x) >> 3 =
; = ( 8 * x + 3 * x) >> 3
lea eax,[ecx+ecx*2]
lea eax,[eax+ecx*8]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??4:
; eax = x + x / 8 = (8*x + x) >> 3 = (x * 9)>> 3
lea eax,[ecx+ecx*8]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??3:
; eax = x/2 + x/4 + x/8 = (4*x + 2*x + x) >> 3
; = ( 4x + 3x ) >> 3
lea eax,[ecx+ecx*2]
lea eax,[eax+ecx*4]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??2:
; eax = x/2 + x/8 = (4*x + x) >> 3
lea eax,[ecx+ecx*4]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??1:
; eax = x/4 + x/8 = (2x + x )>>8
lea eax,[ecx+ecx*2]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??0:
; eax = x/8 = x >> 3
mov eax,ecx
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??15:
; eax = x + x/2 + x/4 + x/8 = (8*x + 4*x +2*x + x)>>3 =
; = ( x * ( 8 + 4 + 2 + 1 )) >> 3 = ( x * 15 ) >> 3
lea ecx,[ecx+ecx*2]
lea eax,[ecx+ecx*4]
jmp ??neg_save_dif
align 4
??14:
; eax = x + x / 2 + x / 8 = (8*x + 4*x + x) >> 3 =
; = ( x * 8 + x * 5 ) >> 8
lea eax,[ecx+ecx*4]
lea eax,[eax+ecx*8]
jmp ??neg_save_dif
align 4
??13:
; eax = x + x / 4 + x / 8 = (8*x + 2*x + x) >> 3 =
; = ( 8 * x + 3 * x) >> 3
lea eax,[ecx+ecx*2]
lea eax,[eax+ecx*8]
jmp ??neg_save_dif
align 4
??12:
; eax = x + x / 8 = (8*x + x) >> 3 = (x * 9)>> 3
lea eax,[ecx+ecx*8]
jmp ??neg_save_dif
align 4
??11:
; eax = x/2 + x/4 + x/8 = (4*x + 2*x + x) >> 3
; = ( 4*x - 3*x ) >> 3
lea eax,[ecx+ecx*2]
lea eax,[eax+ecx*4]
jmp ??neg_save_dif
align 4
??10:
; eax = x/2 + x/8 = (4*x + x) >> 3
lea eax,[ecx+ecx*4]
jmp ??neg_save_dif
align 4
??9:
; eax = x/4 + x/8 = (2x + x )>>8
lea eax,[ecx+ecx*2]
jmp ??neg_save_dif
align 4
??8:
; eax = x/8 = x >> 3
mov eax,ecx ; !!important!! no need for align here
??neg_save_dif:
sar eax,3 ; now we divide x>>3
neg eax
??save_dif:
mov ecx,[wCode] ; load offset into CODETab table
mov [(sCompInfo ebx).dwDifference],eax ;Store wStep
; add difference to predicted value.
add eax,[(sCompInfo ebx).dwPredicted]
; 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:
add edx,[wCODECIndexTab + ecx*4] ; won't hurt 486
cmp [(sCompInfo ebx).wBitSize],16
mov [(sCompInfo ebx).dwPredicted],eax
mov ecx,[(sCompInfo ebx).dwSampleIndex] ;load dwSampleindex
je short ??output16Bit
; output 8 bit sample
xor ah,80h
mov [edi],ah
inc edi
jmp short ??adjustIndex
align 4
??output16Bit:
mov [edi],ax ;Output 16bit sample
add edi,2
??adjustIndex:
cmp edx,8000h
jb short ??checkOverflow
mov edx,0 ;reset index to zero
??checkOverflow:
inc ecx ; advance index and store step value
cmp edx,88 ;check if wIndex > 88
jbe short ??adjustStep
mov edx,88 ;reset index to 88
??adjustStep:
; advance index and store step value
mov [(sCompInfo ebx).dwSampleIndex],ecx
; fetch wIndex so we can fetch new step value
mov eax,[wCODECStepTab + edx*4]
; decrement bytes processed and loop back.
dec ebp
mov [(sCompInfo ebx).wStep],ax
jne ??mainloop
pop ebp
mov eax,[wCode] ; these three lines do not
mov [(sCompInfo ebx).wCode],ax ; seem to have any relevance
mov [(sCompInfo ebx).wIndex],dx ; save index
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,2
mov eax,[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,2
mov eax,[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,2
mov eax,[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,2
mov eax,[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
JumpTable DD ??0
DD ??1
DD ??2
DD ??3
DD ??4
DD ??5
DD ??6
DD ??7
DD ??8
DD ??9
DD ??10
DD ??11
DD ??12
DD ??13
DD ??14
DD ??15
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 sosCODECInitStream(_SOS_COMPRESS_INFO *);
unsigned long sosCODECCompressData(_SOS_COMPRESS_INFO *, unsigned long);
unsigned long 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


Binary file not shown.

View File

@@ -0,0 +1,218 @@
/*
** 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
WWFLAT32/AUDIO/NEW/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 4
/*
** Size of temp HMI low memory staging buffer.
*/
#define SFX_MINI_STAGE_BUFFER_SIZE (1024*4)
#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 SFX_MINI_STAGE_BUFFER_SIZE (1024*4)
#endif

View File

@@ -0,0 +1,253 @@
/*
** 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:1;
/*
** This flags whether the sample is loading or has been started.
*/
unsigned Loading:1;
/*
** 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;
/*
** 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;
/*
** 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 in low ram.
*/
VOID *Buffer[2];
/*
** 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.
*/
WORD Index;
/*
** 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;
/*
** Samples maintain a priority which is used to determine
** which sounds live or die when the maximum number of
** sounds are being played.
*/
WORD Priority;
/*
** This is the handle as returned by sosDIGIStartSample function.
*/
WORD Handle;
/*
** This is the current volume of the sample as it is being played.
*/
WORD Volume;
WORD Reducer; // Amount to reduce volume per tick.
/*
** This flags whether the sample is in stereo.
*/
WORD Stereo;
/*
** This is the compression that the sound data is using.
*/
SCompressType Compression;
WORD 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.
*/
WORD 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)(WORD id, WORD *odd, VOID **buffer, LONG *size);
VOID *QueueBuffer; // Pointer to continued sample data.
LONG QueueSize; // Size of queue buffer attached.
WORD 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.
*/
WORD 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*SFX_MINI_STAGE_BUFFER_SIZE)+128;
short StreamBufferCount; // = 32;
SampleTrackerType SampleTracker[MAX_SFX];
unsigned int SoundVolume;
unsigned int ScoreVolume;
BOOL _int;
int MaxSamples;
int Rate;
} LockedDataType;
extern LockedDataType LockedData;
#pragma pack(4);
void Init_Locked_Data(void);
void Unlock_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, WORD *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 Audio_Mem_Set(void const *ptr, unsigned char value, long size);
void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);
long Decompress_Frame(void * source, void * dest, long size);
int Decompress_Frame_Lock(void);
int Decompress_Frame_Unlock(void);
int sosCODEC_Lock(void);
int sosCODEC_Unlock(void);
void __GETDS(void);
}

View File

@@ -0,0 +1,549 @@
/*
** 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)
#include "soundint.h"
//#include "mem.h"
/***************************************************************************
** 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. **
***************************************************************************/
/***************************************************************************
* SAVE_MY_REGS -- Inline function which will save assembly regs *
* *
* *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
#pragma aux save_my_regs = \
"pushfd" \
"pushad" \
"push ds" \
"push es" \
"push fs" \
"push gs" \
"push ds" \
"pop es";
#pragma aux enable = \
"sti";
#pragma aux disable = \
"cli";
/***************************************************************************
* RESTORE_MY_REGS -- Inline function which will restore saved registers *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
#pragma aux restore_my_regs = \
"pop gs" \
"pop fs" \
"pop es" \
"pop ds" \
"popad" \
"popfd";
/***************************************************************************
* 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 * trailer, WORD *trailersize)
{
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;
sosCODECDecompressData(&st->sosinfo, dsize);
}
dest = Audio_Add_Long_To_Pointer(dest, dsize);
}
datasize += dsize;
size -= dsize;
}
}
break;
}
return(datasize);
}
VOID far cdecl maintenance_callback(VOID)
{
save_my_regs();
int index;
SampleTrackerType *st;
if (!LockedData._int && LockedData.DigiHandle != -1 && LockedData.ServiceSomething) {
LockedData._int++;
enable();
LockedData.ServiceSomething = FALSE;
st = &LockedData.SampleTracker[0];
for (index = 0; index < LockedData.MaxSamples; index++) {
if (st->Active) {
/*
** General service routine to handle moving small blocks from the
** source into the low RAM staging buffers. If the source is
** compressed, then this will also uncompress it as the copy
** is performed.
*/
if (st->Service) {
if (st->DontTouch) {
LockedData.ServiceSomething = TRUE;
} else {
st->Service = FALSE;
#if(FALSE)
st->DataLength = SFX_MINI_STAGE_BUFFER_SIZE;
#else
st->DataLength = Sample_Copy( st,
&st->Source,
&st->Remainder,
&st->QueueBuffer,
&st->QueueSize,
st->Buffer[st->Index],
SFX_MINI_STAGE_BUFFER_SIZE,
st->Compression,
&st->Trailer[0],
&st->TrailerLen);
#endif
}
}
/*
** 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++;
}
LockedData._int--;
}
if (!LockedData._int) {
LockedData._int++;
st = &LockedData.SampleTracker[0];
for (index = 0; index < LockedData.MaxSamples; index++) {
/*
** If there are any samples that require fading, then do so at this
** time.
*/
if (st->Active && st->Reducer && st->Volume) {
if (st->Reducer >= st->Volume) {
st->Volume = 0;
} else {
st->Volume -= st->Reducer;
}
if (st->IsScore) {
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.ScoreVolume);
} else {
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.SoundVolume);
}
}
st++;
}
LockedData._int--;
}
restore_my_regs();
}
/***********************************************************************************************
* DigiCallback -- Low level double buffering handler. *
* *
* This routine is called in an interrupt to handle the double *
* buffering of digital audio. This routine is the interface between *
* the buffers maintained by Sound_Callback() and the HMI driver *
* itself. *
* *
* INPUT: driverhandle -- The handle to the HMI driver. *
* *
* callsource -- Code indicating the reason for the callback. *
* *
* sampleid -- The ID number of the sample itself. *
* *
* OUTPUT: none *
* *
* WARNINGS: This is called in an interrupt so it return as quickly as *
* possible. *
* *
* HISTORY: *
* 01/06/1994 JLB : Created. *
*=============================================================================================*/
VOID cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid)
{
SampleTrackerType *st;
int index;
/*
** Find the correct control structure for the handle specified.
*/
for (index = 0; index < LockedData.MaxSamples; index++) {
st = &LockedData.SampleTracker[index];
if (st->Active && st->Handle == sampleid) {
break;
}
}
if (index == LockedData.MaxSamples) {
return;
}
if (driverhandle == LockedData.DigiHandle) {
switch (callsource) {
/*
** The sample is now no longer audible. Don't stop the sample
** tracking if a servicing is needed. If it is needed then
** obviously the sample isn't quite done.
*/
case _SAMPLE_DONE:
st->Active = FALSE;
if (!st->IsScore) {
// DPMI_Unlock(st->Original, st->OriginalSize);
}
break;
/*
** The sample is finished processing, but not necessarily finished playing.
*/
case _SAMPLE_PROCESSED:
if (st->DataLength && st->Active) {
_SOS_START_SAMPLE start;
long dlength;
dlength = st->DataLength;
st->DataLength = 0;
Audio_Mem_Set(&start, 0, sizeof(start));
start.lpSamplePtr = (LPSTR)st->Buffer[st->Index];
start.dwSampleSize = dlength-1;
start.wSampleFlags = st->Flags;
start.lpCallback = (void cdecl (far *)(unsigned int, unsigned int, unsigned int))&DigiCallback;
start.wLoopCount = 0;
if (st->IsScore) {
start.wVolume = (st->Volume>>8) * LockedData.ScoreVolume;
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);
} else {
start.wVolume = (st->Volume>>8) * LockedData.SoundVolume;
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);
}
start.wChannel = st->Stereo;
start.wSampleID = index+1;
start.dwSamplePitchAdd = st->Pitch;
st->Index ^= 1;
if (st->Remainder || st->QueueBuffer || st->Callback || st->FilePending) {
st->Service = TRUE;
LockedData.ServiceSomething = TRUE;
}
sosDIGIContinueSample(LockedData.DigiHandle, st->Handle, &start);
} else {
/*
** This is necessary because Stop_Sample may screw things
** up, otherwise. Can't rely on the _SAMPLE_DONE call.
*/
st->Active = FALSE;
if (!st->IsScore) {
// DPMI_Unlock(st->Original, st->OriginalSize);
}
}
break;
/*
** Sample is now looping (not used).
*/
case _SAMPLE_LOOPING:
break;
}
}
}
void far HMI_TimerCallback(void)
{
}
/***************************************************************************
* 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,253 @@
/*
** 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:1;
/*
** This flags whether the sample is loading or has been started.
*/
unsigned Loading:1;
/*
** 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;
/*
** 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;
/*
** 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 in low ram.
*/
VOID *Buffer[2];
/*
** 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.
*/
WORD Index;
/*
** 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;
/*
** Samples maintain a priority which is used to determine
** which sounds live or die when the maximum number of
** sounds are being played.
*/
WORD Priority;
/*
** This is the handle as returned by sosDIGIStartSample function.
*/
WORD Handle;
/*
** This is the current volume of the sample as it is being played.
*/
WORD Volume;
WORD Reducer; // Amount to reduce volume per tick.
/*
** This flags whether the sample is in stereo.
*/
WORD Stereo;
/*
** This is the compression that the sound data is using.
*/
SCompressType Compression;
WORD 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.
*/
WORD 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)(WORD id, WORD *odd, VOID **buffer, LONG *size);
VOID *QueueBuffer; // Pointer to continued sample data.
LONG QueueSize; // Size of queue buffer attached.
WORD 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.
*/
WORD 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*SFX_MINI_STAGE_BUFFER_SIZE)+128;
short StreamBufferCount; // = 32;
SampleTrackerType SampleTracker[MAX_SFX];
unsigned int SoundVolume;
unsigned int ScoreVolume;
BOOL _int;
int MaxSamples;
int Rate;
} LockedDataType;
extern LockedDataType LockedData;
#pragma pack(4);
void Init_Locked_Data(void);
void Unlock_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, WORD *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 Audio_Mem_Set(void const *ptr, unsigned char value, long size);
void Mem_Copy(void const *source, void *dest, unsigned long bytes_to_copy);
long Decompress_Frame(void * source, void * dest, long size);
int Decompress_Frame_Lock(void);
int Decompress_Frame_Unlock(void);
int sosCODEC_Lock(void);
int sosCODEC_Unlock(void);
void __GETDS(void);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,147 @@
/*
** 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: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <dos.h>
#include <mem.h>
#include "soundint.h"
#include "wwmem.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*SFX_MINI_STAGE_BUFFER_SIZE)+128;
LockedData.StreamBufferCount = 32;
LockedData.SoundVolume = 255;
LockedData.ScoreVolume = 255;
LockedData._int = FALSE;
LockedData.MaxSamples = MAX_SFX;
/*
** 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();
}
void Unlock_Locked_Data(void)
{
/*
** Lock the sound specific c functions that will cause us problems if
** they are swapped out during an interrupt.
*/
DPMI_Unlock(&LockedData, 4096L);
DPMI_Unlock(Simple_Copy, 4096L);
DPMI_Unlock(Sample_Copy, 4096L);
DPMI_Unlock((void *)maintenance_callback, 4096L);
DPMI_Unlock((void *)DigiCallback, 4096L);
DPMI_Unlock((void *)HMI_TimerCallback, 4096L);
DPMI_Unlock(Audio_Add_Long_To_Pointer, 4096L);
/*
** Lock the library functions that will cause us problems if they are
** swapped out during an interrupt.
*/
DPMI_Unlock(Mem_Copy, 4096L);
DPMI_Unlock(Audio_Mem_Set, 4096L);
DPMI_Unlock(__GETDS, 4096L);
/*
** Finally unlock 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_Unlock();
sosCODEC_Unlock();
/*
** As a last step go though all of the sample tracker structures and make
** sure all the samples have been properly unlocked.
*/
for (int id = 0; id < LockedData.MaxSamples; id++) {
if (LockedData.SampleTracker[id].Original && !LockedData.SampleTracker[id].IsScore) {
DPMI_Unlock(LockedData.SampleTracker[id].Original, LockedData.SampleTracker[id].OriginalSize);
LockedData.SampleTracker[id].Original = NULL;
}
}
}

59
WWFLAT32/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

565
WWFLAT32/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

871
WWFLAT32/AUDIO/SOSCODEC.ASM Normal file
View File

@@ -0,0 +1,871 @@
;
; 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 DD -1,-1,-1,-1,2,4,6,8
DD -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 DD 7, 8, 9, 10, 11, 12, 13,14
DD 16, 17, 19, 21, 23, 25, 28, 31
DD 34, 37, 41, 45, 50, 55, 60, 66
DD 73, 80, 88, 97, 107, 118, 130, 143
DD 157, 173, 190, 209, 230, 253, 279, 307
DD 337, 371, 408, 449, 494, 544, 598, 658
DD 724, 796, 876, 963, 1060, 1166, 1282, 1411
DD 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024
DD 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484
DD 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899
DD 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794
DD 32767
wCode DD 0 ; this is to hold index into wCodeStep
dwCODECByteIndex DD 0 ; this is when to stop compressing
dwCODECBytesProcessed DD 0 ; this is how many so far compressed
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 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 sosCODECDecompressData:NEAR
PROC sosCODECDecompressData C NEAR
ARG sSOSInfo:NEAR PTR
ARG wBytes:DWORD
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
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
;---------------------------------------------------------------------------
push ebp
movzx edx,[(sCompInfo ebx).wIndex] ;preload index
mov ebp, [dwCODECByteIndex]
mov ecx,[(sCompInfo ebx).dwSampleIndex] ;preload SampleIndex
??mainloop:
xor eax,eax ;get a new token
test ecx,1 ;odd Sample??
je short ??fetchToken ; if so get new token
mov ax,[(sCompInfo ebx).wCodeBuf] ;ored with Code
shr eax,4
jmp short ??calcDifference
align 4
??fetchToken:
mov al,[esi] ;put in codebuf
inc esi
mov [(sCompInfo ebx).wCodeBuf],ax
??calcDifference:
xor ecx,ecx
and eax,000Fh
mov cx,[(sCompInfo ebx).wStep] ;cx is step value
mov [wCode],eax
jmp [DWORD PTR JumpTable + eax*4]
align 4
; note: it is important for speed reasons to keep the order the
; following jumps entries as well as the "align 4" after some of
; the jmp statements
??7:
; eax = x + x/2 + x/4 + x/8 = (8*x + 4*x +2*x + x)>>3 =
; = ( x * ( 8 + 4 + 2 + 1 )) >> 3 = ( x * 15 ) >> 3
lea ecx,[ecx+ecx*2]
lea eax,[ecx+ecx*4]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??6:
; eax = x + x / 2 + x / 8 = (8*x + 4*x + x) >> 3 =
; = ( x * 8 + x * 5 ) >> 8
lea eax,[ecx+ecx*4]
lea eax,[eax+ecx*8]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??5:
; eax = x + x / 4 + x / 8 = (8*x + 2*x + x) >> 3 =
; = ( 8 * x + 3 * x) >> 3
lea eax,[ecx+ecx*2]
lea eax,[eax+ecx*8]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??4:
; eax = x + x / 8 = (8*x + x) >> 3 = (x * 9)>> 3
lea eax,[ecx+ecx*8]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??3:
; eax = x/2 + x/4 + x/8 = (4*x + 2*x + x) >> 3
; = ( 4x + 3x ) >> 3
lea eax,[ecx+ecx*2]
lea eax,[eax+ecx*4]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??2:
; eax = x/2 + x/8 = (4*x + x) >> 3
lea eax,[ecx+ecx*4]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??1:
; eax = x/4 + x/8 = (2x + x )>>8
lea eax,[ecx+ecx*2]
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??0:
; eax = x/8 = x >> 3
mov eax,ecx
sar eax,3 ; now we divide x>>3
jmp ??save_dif
align 4
??15:
; eax = x + x/2 + x/4 + x/8 = (8*x + 4*x +2*x + x)>>3 =
; = ( x * ( 8 + 4 + 2 + 1 )) >> 3 = ( x * 15 ) >> 3
lea ecx,[ecx+ecx*2]
lea eax,[ecx+ecx*4]
jmp ??neg_save_dif
align 4
??14:
; eax = x + x / 2 + x / 8 = (8*x + 4*x + x) >> 3 =
; = ( x * 8 + x * 5 ) >> 8
lea eax,[ecx+ecx*4]
lea eax,[eax+ecx*8]
jmp ??neg_save_dif
align 4
??13:
; eax = x + x / 4 + x / 8 = (8*x + 2*x + x) >> 3 =
; = ( 8 * x + 3 * x) >> 3
lea eax,[ecx+ecx*2]
lea eax,[eax+ecx*8]
jmp ??neg_save_dif
align 4
??12:
; eax = x + x / 8 = (8*x + x) >> 3 = (x * 9)>> 3
lea eax,[ecx+ecx*8]
jmp ??neg_save_dif
align 4
??11:
; eax = x/2 + x/4 + x/8 = (4*x + 2*x + x) >> 3
; = ( 4*x - 3*x ) >> 3
lea eax,[ecx+ecx*2]
lea eax,[eax+ecx*4]
jmp ??neg_save_dif
align 4
??10:
; eax = x/2 + x/8 = (4*x + x) >> 3
lea eax,[ecx+ecx*4]
jmp ??neg_save_dif
align 4
??9:
; eax = x/4 + x/8 = (2x + x )>>8
lea eax,[ecx+ecx*2]
jmp ??neg_save_dif
align 4
??8:
; eax = x/8 = x >> 3
mov eax,ecx ; !!important!! no need for align here
??neg_save_dif:
sar eax,3 ; now we divide x>>3
neg eax
??save_dif:
mov ecx,[wCode] ; load offset into CODETab table
mov [(sCompInfo ebx).dwDifference],eax ;Store wStep
; add difference to predicted value.
add eax,[(sCompInfo ebx).dwPredicted]
; 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:
add edx,[wCODECIndexTab + ecx*4] ; won't hurt 486
cmp [(sCompInfo ebx).wBitSize],16
mov [(sCompInfo ebx).dwPredicted],eax
mov ecx,[(sCompInfo ebx).dwSampleIndex] ;load dwSampleindex
je short ??output16Bit
; output 8 bit sample
xor ah,80h
mov [edi],ah
inc edi
jmp short ??adjustIndex
align 4
??output16Bit:
mov [edi],ax ;Output 16bit sample
add edi,2
??adjustIndex:
cmp edx,8000h
jb short ??checkOverflow
mov edx,0 ;reset index to zero
??checkOverflow:
inc ecx ; advance index and store step value
cmp edx,88 ;check if wIndex > 88
jbe short ??adjustStep
mov edx,88 ;reset index to 88
??adjustStep:
; advance index and store step value
mov [(sCompInfo ebx).dwSampleIndex],ecx
; fetch wIndex so we can fetch new step value
mov eax,[wCODECStepTab + edx*4]
; decrement bytes processed and loop back.
dec ebp
mov [(sCompInfo ebx).wStep],ax
jne ??mainloop
pop ebp
mov eax,[wCode] ; these three lines do not
mov [(sCompInfo ebx).wCode],ax ; seem to have any relevance
mov [(sCompInfo ebx).wIndex],dx ; save index
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,2
mov eax,[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,2
mov eax,[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,2
mov eax,[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,2
mov eax,[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
JumpTable DD ??0
DD ??1
DD ??2
DD ??3
DD ??4
DD ??5
DD ??6
DD ??7
DD ??8
DD ??9
DD ??10
DD ??11
DD ??12
DD ??13
DD ??14
DD ??15
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
WWFLAT32/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 sosCODECInitStream(_SOS_COMPRESS_INFO *);
unsigned long sosCODECCompressData(_SOS_COMPRESS_INFO *, unsigned long);
unsigned long sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);
}
#endif


128
WWFLAT32/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
WWFLAT32/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


BIN
WWFLAT32/AUDIO/SOSDW1PS.LIB Normal file

Binary file not shown.

218
WWFLAT32/AUDIO/SOSFNCT.H Normal file
View File

@@ -0,0 +1,218 @@
/*
** 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
WWFLAT32/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
WWFLAT32/AUDIO/SOUND.BAK 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 4
/*
** Size of temp HMI low memory staging buffer.
*/
#define SFX_MINI_STAGE_BUFFER_SIZE (1024*4)
#endif

54
WWFLAT32/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 SFX_MINI_STAGE_BUFFER_SIZE (1024*4)
#endif

549
WWFLAT32/AUDIO/SOUNDINT.BAK Normal file
View File

@@ -0,0 +1,549 @@
/*
** 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)
#include "soundint.h"
//#include "mem.h"
/***************************************************************************
** 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. **
***************************************************************************/
/***************************************************************************
* SAVE_MY_REGS -- Inline function which will save assembly regs *
* *
* *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
#pragma aux save_my_regs = \
"pushfd" \
"pushad" \
"push ds" \
"push es" \
"push fs" \
"push gs" \
"push ds" \
"pop es";
#pragma aux enable = \
"sti";
#pragma aux disable = \
"cli";
/***************************************************************************
* RESTORE_MY_REGS -- Inline function which will restore saved registers *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
#pragma aux restore_my_regs = \
"pop gs" \
"pop fs" \
"pop es" \
"pop ds" \
"popad" \
"popfd";
/***************************************************************************
* 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 * trailer, WORD *trailersize)
{
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;
sosCODECDecompressData(&st->sosinfo, dsize);
}
dest = Audio_Add_Long_To_Pointer(dest, dsize);
}
datasize += dsize;
size -= dsize;
}
}
break;
}
return(datasize);
}
VOID far cdecl maintenance_callback(VOID)
{
save_my_regs();
int index;
SampleTrackerType *st;
if (!LockedData._int && LockedData.DigiHandle != -1 && LockedData.ServiceSomething) {
LockedData._int++;
enable();
LockedData.ServiceSomething = FALSE;
st = &LockedData.SampleTracker[0];
for (index = 0; index < LockedData.MaxSamples; index++) {
if (st->Active) {
/*
** General service routine to handle moving small blocks from the
** source into the low RAM staging buffers. If the source is
** compressed, then this will also uncompress it as the copy
** is performed.
*/
if (st->Service) {
if (st->DontTouch) {
LockedData.ServiceSomething = TRUE;
} else {
st->Service = FALSE;
#if(FALSE)
st->DataLength = SFX_MINI_STAGE_BUFFER_SIZE;
#else
st->DataLength = Sample_Copy( st,
&st->Source,
&st->Remainder,
&st->QueueBuffer,
&st->QueueSize,
st->Buffer[st->Index],
SFX_MINI_STAGE_BUFFER_SIZE,
st->Compression,
&st->Trailer[0],
&st->TrailerLen);
#endif
}
}
/*
** 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++;
}
LockedData._int--;
}
if (!LockedData._int) {
LockedData._int++;
st = &LockedData.SampleTracker[0];
for (index = 0; index < LockedData.MaxSamples; index++) {
/*
** If there are any samples that require fading, then do so at this
** time.
*/
if (st->Active && st->Reducer && st->Volume) {
if (st->Reducer >= st->Volume) {
st->Volume = 0;
} else {
st->Volume -= st->Reducer;
}
if (st->IsScore) {
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.ScoreVolume);
} else {
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.SoundVolume);
}
}
st++;
}
LockedData._int--;
}
restore_my_regs();
}
/***********************************************************************************************
* DigiCallback -- Low level double buffering handler. *
* *
* This routine is called in an interrupt to handle the double *
* buffering of digital audio. This routine is the interface between *
* the buffers maintained by Sound_Callback() and the HMI driver *
* itself. *
* *
* INPUT: driverhandle -- The handle to the HMI driver. *
* *
* callsource -- Code indicating the reason for the callback. *
* *
* sampleid -- The ID number of the sample itself. *
* *
* OUTPUT: none *
* *
* WARNINGS: This is called in an interrupt so it return as quickly as *
* possible. *
* *
* HISTORY: *
* 01/06/1994 JLB : Created. *
*=============================================================================================*/
VOID cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid)
{
SampleTrackerType *st;
int index;
/*
** Find the correct control structure for the handle specified.
*/
for (index = 0; index < LockedData.MaxSamples; index++) {
st = &LockedData.SampleTracker[index];
if (st->Active && st->Handle == sampleid) {
break;
}
}
if (index == LockedData.MaxSamples) {
return;
}
if (driverhandle == LockedData.DigiHandle) {
switch (callsource) {
/*
** The sample is now no longer audible. Don't stop the sample
** tracking if a servicing is needed. If it is needed then
** obviously the sample isn't quite done.
*/
case _SAMPLE_DONE:
st->Active = FALSE;
if (!st->IsScore) {
// DPMI_Unlock(st->Original, st->OriginalSize);
}
break;
/*
** The sample is finished processing, but not necessarily finished playing.
*/
case _SAMPLE_PROCESSED:
if (st->DataLength && st->Active) {
_SOS_START_SAMPLE start;
long dlength;
dlength = st->DataLength;
st->DataLength = 0;
Audio_Mem_Set(&start, 0, sizeof(start));
start.lpSamplePtr = (LPSTR)st->Buffer[st->Index];
start.dwSampleSize = dlength-1;
start.wSampleFlags = st->Flags;
start.lpCallback = (void cdecl (far *)(unsigned int, unsigned int, unsigned int))&DigiCallback;
start.wLoopCount = 0;
if (st->IsScore) {
start.wVolume = (st->Volume>>8) * LockedData.ScoreVolume;
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);
} else {
start.wVolume = (st->Volume>>8) * LockedData.SoundVolume;
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);
}
start.wChannel = st->Stereo;
start.wSampleID = index+1;
start.dwSamplePitchAdd = st->Pitch;
st->Index ^= 1;
if (st->Remainder || st->QueueBuffer || st->Callback || st->FilePending) {
st->Service = TRUE;
LockedData.ServiceSomething = TRUE;
}
sosDIGIContinueSample(LockedData.DigiHandle, st->Handle, &start);
} else {
/*
** This is necessary because Stop_Sample may screw things
** up, otherwise. Can't rely on the _SAMPLE_DONE call.
*/
st->Active = FALSE;
if (!st->IsScore) {
// DPMI_Unlock(st->Original, st->OriginalSize);
}
}
break;
/*
** Sample is now looping (not used).
*/
case _SAMPLE_LOOPING:
break;
}
}
}
void far HMI_TimerCallback(void)
{
}
/***************************************************************************
* 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;
}
}

549
WWFLAT32/AUDIO/SOUNDINT.CPP Normal file
View File

@@ -0,0 +1,549 @@
/*
** 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)
#include "soundint.h"
//#include "mem.h"
/***************************************************************************
** 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. **
***************************************************************************/
/***************************************************************************
* SAVE_MY_REGS -- Inline function which will save assembly regs *
* *
* *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
#pragma aux save_my_regs = \
"pushfd" \
"pushad" \
"push ds" \
"push es" \
"push fs" \
"push gs" \
"push ds" \
"pop es";
#pragma aux enable = \
"sti";
#pragma aux disable = \
"cli";
/***************************************************************************
* RESTORE_MY_REGS -- Inline function which will restore saved registers *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
#pragma aux restore_my_regs = \
"pop gs" \
"pop fs" \
"pop es" \
"pop ds" \
"popad" \
"popfd";
/***************************************************************************
* 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 * trailer, WORD *trailersize)
{
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;
sosCODECDecompressData(&st->sosinfo, dsize);
}
dest = Audio_Add_Long_To_Pointer(dest, dsize);
}
datasize += dsize;
size -= dsize;
}
}
break;
}
return(datasize);
}
VOID far cdecl maintenance_callback(VOID)
{
save_my_regs();
int index;
SampleTrackerType *st;
if (!LockedData._int && LockedData.DigiHandle != -1 && LockedData.ServiceSomething) {
LockedData._int++;
enable();
LockedData.ServiceSomething = FALSE;
st = &LockedData.SampleTracker[0];
for (index = 0; index < LockedData.MaxSamples; index++) {
if (st->Active) {
/*
** General service routine to handle moving small blocks from the
** source into the low RAM staging buffers. If the source is
** compressed, then this will also uncompress it as the copy
** is performed.
*/
if (st->Service) {
if (st->DontTouch) {
LockedData.ServiceSomething = TRUE;
} else {
st->Service = FALSE;
#if(FALSE)
st->DataLength = SFX_MINI_STAGE_BUFFER_SIZE;
#else
st->DataLength = Sample_Copy( st,
&st->Source,
&st->Remainder,
&st->QueueBuffer,
&st->QueueSize,
st->Buffer[st->Index],
SFX_MINI_STAGE_BUFFER_SIZE,
st->Compression,
&st->Trailer[0],
&st->TrailerLen);
#endif
}
}
/*
** 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++;
}
LockedData._int--;
}
if (!LockedData._int) {
LockedData._int++;
st = &LockedData.SampleTracker[0];
for (index = 0; index < LockedData.MaxSamples; index++) {
/*
** If there are any samples that require fading, then do so at this
** time.
*/
if (st->Active && st->Reducer && st->Volume) {
if (st->Reducer >= st->Volume) {
st->Volume = 0;
} else {
st->Volume -= st->Reducer;
}
if (st->IsScore) {
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.ScoreVolume);
} else {
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, (st->Volume>>8) * LockedData.SoundVolume);
}
}
st++;
}
LockedData._int--;
}
restore_my_regs();
}
/***********************************************************************************************
* DigiCallback -- Low level double buffering handler. *
* *
* This routine is called in an interrupt to handle the double *
* buffering of digital audio. This routine is the interface between *
* the buffers maintained by Sound_Callback() and the HMI driver *
* itself. *
* *
* INPUT: driverhandle -- The handle to the HMI driver. *
* *
* callsource -- Code indicating the reason for the callback. *
* *
* sampleid -- The ID number of the sample itself. *
* *
* OUTPUT: none *
* *
* WARNINGS: This is called in an interrupt so it return as quickly as *
* possible. *
* *
* HISTORY: *
* 01/06/1994 JLB : Created. *
*=============================================================================================*/
VOID cdecl far DigiCallback(unsigned int driverhandle, unsigned int callsource, unsigned int sampleid)
{
SampleTrackerType *st;
int index;
/*
** Find the correct control structure for the handle specified.
*/
for (index = 0; index < LockedData.MaxSamples; index++) {
st = &LockedData.SampleTracker[index];
if (st->Active && st->Handle == sampleid) {
break;
}
}
if (index == LockedData.MaxSamples) {
return;
}
if (driverhandle == LockedData.DigiHandle) {
switch (callsource) {
/*
** The sample is now no longer audible. Don't stop the sample
** tracking if a servicing is needed. If it is needed then
** obviously the sample isn't quite done.
*/
case _SAMPLE_DONE:
st->Active = FALSE;
if (!st->IsScore) {
// DPMI_Unlock(st->Original, st->OriginalSize);
}
break;
/*
** The sample is finished processing, but not necessarily finished playing.
*/
case _SAMPLE_PROCESSED:
if (st->DataLength && st->Active) {
_SOS_START_SAMPLE start;
long dlength;
dlength = st->DataLength;
st->DataLength = 0;
Audio_Mem_Set(&start, 0, sizeof(start));
start.lpSamplePtr = (LPSTR)st->Buffer[st->Index];
start.dwSampleSize = dlength-1;
start.wSampleFlags = st->Flags;
start.lpCallback = (void cdecl (far *)(unsigned int, unsigned int, unsigned int))&DigiCallback;
start.wLoopCount = 0;
if (st->IsScore) {
start.wVolume = (st->Volume>>8) * LockedData.ScoreVolume;
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);
} else {
start.wVolume = (st->Volume>>8) * LockedData.SoundVolume;
sosDIGISetSampleVolume(LockedData.DigiHandle, st->Handle, start.wVolume);
}
start.wChannel = st->Stereo;
start.wSampleID = index+1;
start.dwSamplePitchAdd = st->Pitch;
st->Index ^= 1;
if (st->Remainder || st->QueueBuffer || st->Callback || st->FilePending) {
st->Service = TRUE;
LockedData.ServiceSomething = TRUE;
}
sosDIGIContinueSample(LockedData.DigiHandle, st->Handle, &start);
} else {
/*
** This is necessary because Stop_Sample may screw things
** up, otherwise. Can't rely on the _SAMPLE_DONE call.
*/
st->Active = FALSE;
if (!st->IsScore) {
// DPMI_Unlock(st->Original, st->OriginalSize);
}
}
break;
/*
** Sample is now looping (not used).
*/
case _SAMPLE_LOOPING:
break;
}
}
}
void far HMI_TimerCallback(void)
{
}
/***************************************************************************
* 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;
}
}

253
WWFLAT32/AUDIO/SOUNDINT.H Normal file
View File

@@ -0,0 +1,253 @@
/*
** 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:1;
/*
** This flags whether the sample is loading or has been started.
*/
unsigned Loading:1;
/*
** 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;
/*
** 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;
/*
** 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 in low ram.
*/
VOID *Buffer[2];
/*
** 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.
*/
WORD Index;
/*
** 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;
/*
** Samples maintain a priority which is used to determine
** which sounds live or die when the maximum number of
** sounds are being played.
*/
WORD Priority;
/*
** This is the handle as returned by sosDIGIStartSample function.
*/
WORD Handle;
/*
** This is the current volume of the sample as it is being played.
*/
WORD Volume;
WORD Reducer; // Amount to reduce volume per tick.
/*
** This flags whether the sample is in stereo.
*/
WORD Stereo;
/*
** This is the compression that the sound data is using.
*/
SCompressType Compression;
WORD 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.
*/
WORD 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)(WORD id, WORD *odd, VOID **buffer, LONG *size);
VOID *QueueBuffer; // Pointer to continued sample data.
LONG QueueSize; // Size of queue buffer attached.
WORD 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.
*/
WORD 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*SFX_MINI_STAGE_BUFFER_SIZE)+128;
short StreamBufferCount; // = 32;
SampleTrackerType SampleTracker[MAX_SFX];
unsigned int SoundVolume;
unsigned int ScoreVolume;
BOOL _int;
int MaxSamples;
int Rate;
} LockedDataType;
extern LockedDataType LockedData;
#pragma pack(4);
void Init_Locked_Data(void);
void Unlock_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, WORD *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 Audio_Mem_Set(void const *ptr, unsigned char value, long size);
void Mem_Copy(void const *source, void *dest, unsigned long bytes_to_copy);
long Decompress_Frame(void * source, void * dest, long size);
int Decompress_Frame_Lock(void);
int Decompress_Frame_Unlock(void);
int sosCODEC_Lock(void);
int sosCODEC_Unlock(void);
void __GETDS(void);
}

1467
WWFLAT32/AUDIO/SOUNDIO.BAK Normal file

File diff suppressed because it is too large Load Diff

1467
WWFLAT32/AUDIO/SOUNDIO.CPP Normal file

File diff suppressed because it is too large Load Diff

147
WWFLAT32/AUDIO/SOUNDLCK.CPP Normal file
View File

@@ -0,0 +1,147 @@
/*
** 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: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <dos.h>
#include <mem.h>
#include "soundint.h"
#include "wwmem.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*SFX_MINI_STAGE_BUFFER_SIZE)+128;
LockedData.StreamBufferCount = 32;
LockedData.SoundVolume = 255;
LockedData.ScoreVolume = 255;
LockedData._int = FALSE;
LockedData.MaxSamples = MAX_SFX;
/*
** 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();
}
void Unlock_Locked_Data(void)
{
/*
** Lock the sound specific c functions that will cause us problems if
** they are swapped out during an interrupt.
*/
DPMI_Unlock(&LockedData, 4096L);
DPMI_Unlock(Simple_Copy, 4096L);
DPMI_Unlock(Sample_Copy, 4096L);
DPMI_Unlock((void *)maintenance_callback, 4096L);
DPMI_Unlock((void *)DigiCallback, 4096L);
DPMI_Unlock((void *)HMI_TimerCallback, 4096L);
DPMI_Unlock(Audio_Add_Long_To_Pointer, 4096L);
/*
** Lock the library functions that will cause us problems if they are
** swapped out during an interrupt.
*/
DPMI_Unlock(Mem_Copy, 4096L);
DPMI_Unlock(Audio_Mem_Set, 4096L);
DPMI_Unlock(__GETDS, 4096L);
/*
** Finally unlock 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_Unlock();
sosCODEC_Unlock();
/*
** As a last step go though all of the sample tracker structures and make
** sure all the samples have been properly unlocked.
*/
for (int id = 0; id < LockedData.MaxSamples; id++) {
if (LockedData.SampleTracker[id].Original && !LockedData.SampleTracker[id].IsScore) {
DPMI_Unlock(LockedData.SampleTracker[id].Original, LockedData.SampleTracker[id].OriginalSize);
LockedData.SampleTracker[id].Original = NULL;
}
}
}