Initial commit of Command & Conquer Red Alert source code.

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

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

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

BIN
WIN32LIB/AUDIO/AUDIO.IDE Normal file

Binary file not shown.

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

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

1448
WIN32LIB/AUDIO/DIFFTB.INC Normal file

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,47 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*=========================================================================*/
/* The following prototypes are for the file: SOUNDIO.CPP */
/*=========================================================================*/
short Decompress_Frame(void * source, void * dest, short size);
int __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback);
int __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback);
int __cdecl File_Stream_Sample(char const *filename);
int __cdecl File_Stream_Sample_Vol(char const *filename, int volume);
void __cdecl _saveregs _loadds Sound_Callback(void);
void __cdecl far _saveregs _loadds maintenance_callback(void);
void __cdecl Load_Sample(char const *filename);
long __cdecl Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);
long __cdecl Sample_Read(int fh, void *buffer, long size);
void __cdecl Free_Sample(void const *sample);
BOOL __cdecl Sound_Init(int sfx, int score, int sample);
void far VQA_TimerCallback(void);
BOOL Audio_Init(int sample, int address, int inter, int dma);
void __cdecl Sound_End(void);
void __cdecl Stop_Sample(int handle);
BOOL __cdecl Sample_Status(int handle);
BOOL __cdecl Is_Sample_Playing(void const * sample);
void __cdecl Stop_Sample_Playing(void const * sample);
int __cdecl Play_Sample(void const *sample);
int __cdecl Play_Sample_Vol(void const *sample, int priority, int volume);
int __cdecl Set_Sound_Vol(int volume);
int __cdecl Set_Score_Vol(int volume);
void __cdecl Fade_Sample(int handle, int ticks);

1448
WIN32LIB/AUDIO/INDEXTB.INC Normal file

File diff suppressed because it is too large Load Diff

186
WIN32LIB/AUDIO/MAKEFILE Normal file
View File

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

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

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

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

@@ -0,0 +1,59 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;****************************************************************************
;* bNybbleTablexxxx - ADPCM Lookup table for nybbles
;****************************************************************************
align 4
bNybbleTableLow DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
align 4
bNybbleTableHigh DB 00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2
DB 01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2
DB 02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2
DB 03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2
DB 04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2
DB 05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2
DB 06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2
DB 07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2
DB 08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2
DB 09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2
DB 0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2
DB 0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2
DB 0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2
DB 0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2
DB 0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2
DB 0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2

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

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

Binary file not shown.

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*=========================================================================*/
/* The following prototypes are for the file: SOUNDIO.CPP */
/*=========================================================================*/
short Decompress_Frame(void * source, void * dest, short size);
int __cdecl Stream_Sample_Vol(void *buffer, long size, BOOL (*callback);
int __cdecl Stream_Sample(void *buffer, long size, BOOL (*callback);
int __cdecl File_Stream_Sample(char const *filename);
int __cdecl File_Stream_Sample_Vol(char const *filename, int volume);
void __cdecl _saveregs _loadds Sound_Callback(void);
void __cdecl far _saveregs _loadds maintenance_callback(void);
void __cdecl Load_Sample(char const *filename);
long __cdecl Load_Sample_Into_Buffer(char const *filename, void *buffer, long size);
long __cdecl Sample_Read(int fh, void *buffer, long size);
void __cdecl Free_Sample(void const *sample);
BOOL __cdecl Sound_Init(int sfx, int score, int sample);
void far VQA_TimerCallback(void);
BOOL Audio_Init(int sample, int address, int inter, int dma);
void __cdecl Sound_End(void);
void __cdecl Stop_Sample(int handle);
BOOL __cdecl Sample_Status(int handle);
BOOL __cdecl Is_Sample_Playing(void const * sample);
void __cdecl Stop_Sample_Playing(void const * sample);
int __cdecl Play_Sample(void const *sample);
int __cdecl Play_Sample_Vol(void const *sample, int priority, int volume);
int __cdecl Set_Sound_Vol(int volume);
int __cdecl Set_Score_Vol(int volume);
void __cdecl Fade_Sample(int handle, int ticks);

File diff suppressed because it is too large Load Diff

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

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

View File

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

View File

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

View File

@@ -0,0 +1,59 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;****************************************************************************
;* bNybbleTablexxxx - ADPCM Lookup table for nybbles
;****************************************************************************
align 4
bNybbleTableLow DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
DB 00h*2,01h*2,02h*2,03h*2,04h*2,05h*2,06h*2,07h*2,08h*2,09h*2,0Ah*2,0Bh*2,0Ch*2,0Dh*2,0Eh*2,0Fh*2
align 4
bNybbleTableHigh DB 00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2,00h*2
DB 01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2,01h*2
DB 02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2,02h*2
DB 03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2,03h*2
DB 04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2,04h*2
DB 05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2,05h*2
DB 06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2,06h*2
DB 07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2,07h*2
DB 08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2,08h*2
DB 09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2,09h*2
DB 0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2,0Ah*2
DB 0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2,0Bh*2
DB 0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2,0Ch*2
DB 0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2,0Dh*2
DB 0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2,0Eh*2
DB 0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2,0Fh*2

View File

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

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

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

View File

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

View File

@@ -0,0 +1,83 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
*
* File : soscomp.h
* Date Created : 6/1/94
* Description :
*
* Programmer(s) : Nick Skrepetos
* Last Modification : 10/1/94 - 11:37:9 AM
* Additional Notes : Modified by Denzil E. Long, Jr.
*
*****************************************************************************
* Copyright (c) 1994, HMI, Inc. All Rights Reserved *
****************************************************************************/
#ifndef _SOS_COMPRESS
#define _SOS_COMPRESS
/* compression types */
enum {
_ADPCM_TYPE_1,
};
/* define compression structure */
typedef struct _tagCOMPRESS_INFO {
char *lpSource;
char *lpDest;
unsigned long dwCompSize;
unsigned long dwUnCompSize;
unsigned long dwSampleIndex;
long dwPredicted;
long dwDifference;
short wCodeBuf;
short wCode;
short wStep;
short wIndex;
unsigned long dwSampleIndex2; //added BP for channel 2
long dwPredicted2; //added BP for channel 2
long dwDifference2; //added BP for channel 2
short wCodeBuf2; //added BP for channel 2
short wCode2; //added BP for channel 2
short wStep2; //added BP for channel 2
short wIndex2; //added BP for channel 2
short wBitSize;
short wChannels; //added BP for # of channels
} _SOS_COMPRESS_INFO;
/* compressed file type header */
typedef struct _tagCOMPRESS_HEADER {
unsigned long dwType; // type of compression
unsigned long dwCompressedSize; // compressed file size
unsigned long dwUnCompressedSize; // uncompressed file size
unsigned long dwSourceBitSize; // original bit size
char szName[16]; // file type, for error checking
} _SOS_COMPRESS_HEADER;
/* Prototypes */
extern "C" {
void __cdecl sosCODECInitStream(_SOS_COMPRESS_INFO *);
unsigned long __cdecl sosCODECCompressData(_SOS_COMPRESS_INFO *, unsigned long);
unsigned long __cdecl sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);
unsigned long __cdecl General_sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);
}
#endif

View File

@@ -0,0 +1,128 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosdata.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOS_DATA
#define _SOS_DATA
#include <stddef.h>
#pragma pack(4)
extern WORD _sosDIGIData_Start;
extern WORD _sosDIGIData_End;
extern WORD _wSOSDriverLinear[];
extern WORD _wSOSTimerLinear[];
extern LPSTR _lpSOSDriver[];
extern LPSTR _lpSOSTimer[];
extern LPSTR _lpSOSDriverCS[];
extern LPSTR _lpSOSTimerCS[];
extern BOOL _wSOSDriverLoaded[];
extern BOOL _wSOSTimerLoaded[];
extern BOOL _wSOSDriverInitialized[];
extern WORD _wSOSOutputRate[];
extern WORD _wSOSDMABuffersize[];
extern LONG _dwSOSDMABufferPhysical[];
extern LPSTR _lpSOSDMABuffer[];
extern BOOL _wTimerUsed;
extern VOID ( far *_lpSOSFillHandler[] )( VOID );
extern WORD _wSOSTimerType[];
extern WORD _wSOSDriverType[];
extern _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];
extern LPWORD _lpSOSDMAIrqCount[];
extern LPWORD _lpSOSDMAFillCount[];
extern WORD _wSOSTmrNextCount;
extern VOID ( interrupt far *_lpSOSOldTimer )( VOID );
extern WORD _wSOSDriverID[];
extern _SOS_CAPABILITIES _sSOSDriverCaps[];
extern WORD _wSOSDMAPortList[];
extern BYTE _bSOSDMAChannel[];
extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[];
extern BYTE _pSOSDriverPath[];
extern BYTE _pSOSTempDriverPath[];
extern BOOL _wTIMERUsed;
extern WORD _wTIMERValue;
extern VOID ( far * _lpTIMEREvents[] )( VOID );
extern WORD _wTIMEREventRate[];
extern WORD _dwTIMEREventFraction[];
extern WORD _dwTIMEREventFractionCurrent[];
extern BYTE _bSOSMIDITimerSongHandler[];
extern BYTE _bSOSMIDISongHandle;
extern WORD _wSOSTimerMemHandle[];
extern WORD _wSOSDriverMemHandle[];
extern WORD _wSOSRealSeg[];
extern _FILEHEADER _sDETFileHeader;
extern _DRIVERHEADER _sDETDriverHeader;
extern _FILEHEADER sLOADFileHeader;
extern _DRIVERHEADER sLOADDriverHeader;
extern BOOL _wDETInitialized;
extern WORD _wDETLinear;
extern LPSTR _lpDETDriverBuffer;
extern LPSTR _lpDETDriverBufferCS;
extern WORD _hDETFile;
extern DWORD _dwDETDriverIndex;
extern WORD _wDETDriverIndexCur;
extern WORD _wDETMemHandle;
extern LPSOSDEVICECAPS _lpDETDeviceCaps;
extern _SOS_CAPABILITIES _sDETCaps;
extern PSTR _pSOSErrorStrings[];
extern BOOL _wSOSBufferAllocated[];
extern BOOL _wSOSSystemInitialized;
extern VDS_STRUCT _sSOSVDSInfo;
extern _SOS_FILL_INFO _sSOSFillInfo;
extern WORD _wSOSTimerEventIndex;
extern WORD _wSOSTimerEntered;
extern WORD _wSOSDriverSize[];
extern WORD _wSOSTimerSize[];
#ifdef __cplusplus
extern "C" {
#endif
extern WORD _sosDIGIData1_Start;
extern WORD _sosDIGIData1_End;
extern WORD _sosDIGIData2_Start;
extern WORD _sosDIGIData2_End;
extern BYTE _bTIMERInstalled;
extern BYTE _bTIMERDPMI;
extern WORD wDetectPort;
extern WORD wDetectIRQ;
extern WORD wDetectDMA;
extern WORD wDetectParam;
#ifdef __cplusplus
}
#endif
#pragma pack()
#endif

View File

@@ -0,0 +1,83 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosdefs.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOSDEFS_DEFINED
#define _SOSDEFS_DEFINED
#undef _TRUE
#undef _FALSE
#undef _NULL
enum
{
_FALSE,
_TRUE
};
#define _NULL 0
#ifndef VOID
#define VOID void
#endif
typedef int BOOL;
typedef unsigned int UINT;
typedef unsigned char BYTE;
typedef unsigned WORD;
#ifndef LONG
typedef signed long LONG;
#endif
typedef unsigned long DWORD;
typedef BYTE * PBYTE;
typedef char near * PSTR;
typedef WORD * PWORD;
typedef LONG * PLONG;
typedef VOID * PVOID;
typedef BYTE far * LPBYTE;
typedef BYTE far * LPSTR;
typedef WORD far * LPWORD;
typedef LONG far * LPLONG;
typedef VOID far * LPVOID;
typedef BYTE huge * HPBYTE;
typedef BYTE huge * HPSTR;
typedef WORD huge * HPWORD;
typedef LONG huge * HPLONG;
typedef VOID huge * HPVOID;
typedef unsigned HANDLE;
#endif

View File

@@ -0,0 +1,219 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosfnct.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOS_FUNCTIONS
#define _SOS_FUNCTIONS
#pragma pack(4)
WORD sosDIGILockMemory ( VOID );
WORD sosDIGIUnLockMemory ( VOID );
WORD sosDIGIInitSystem ( LPSTR, WORD );
WORD sosDIGIUnInitSystem ( VOID );
WORD sosDIGIInitDriver ( WORD, _SOS_HARDWARE far *,
_SOS_INIT_DRIVER far *, WORD far * );
WORD sosDIGIUnInitDriver ( WORD, BOOL, BOOL );
WORD sosDIGILoadDriver ( WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );
WORD sosDIGIUnLoadDriver ( WORD );
WORD sosDIGIGetDeviceCaps ( WORD, LPSOSDEVICECAPS );
#ifdef PHARLAP
LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * );
#else
LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * );
#endif
WORD sosDIGIStopSample ( WORD, WORD );
WORD sosDIGISamplesPlaying ( WORD );
BOOL sosDIGISampleDone ( WORD, WORD );
BOOL sosDIGISampleFilling ( WORD, WORD );
WORD sosDIGIStartSample ( WORD, _SOS_START_SAMPLE far * );
WORD sosDIGIContinueSample ( WORD, WORD, _SOS_START_SAMPLE far * );
WORD sosDIGIDetectInit ( LPSTR );
WORD sosDIGIDetectUnInit ( VOID );
WORD sosDIGIDetectFindHardware ( WORD, _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectFindFirst ( _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectFindNext ( _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectGetSettings ( _SOS_HARDWARE far * );
WORD sosDIGIDetectGetCaps ( WORD, _SOS_CAPABILITIES far * );
WORD sosDIGIDetectVerifySettings( _SOS_HARDWARE far * );
PSTR sosGetErrorString ( WORD );
WORD sosDIGILoadTimer ( WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );
WORD sosDIGIUnLoadTimer ( WORD );
WORD sosTIMERRegisterEvent ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );
WORD sosTIMERInitSystem ( WORD, WORD );
WORD sosTIMERUnInitSystem ( WORD );
WORD sosTIMERSetRate ( WORD );
WORD sosTIMERRemoveEvent ( WORD );
WORD sosTIMERAlterEventRate ( WORD, WORD );
WORD sosTIMERGetEventRate ( WORD );
VOID far sosTIMEROldHandler ( VOID );
VOID far sosTIMERHandler ( VOID );
// functions in soscntl.c
WORD sosDIGISetSampleVolume ( WORD, WORD, WORD );
WORD sosDIGIGetSampleVolume ( WORD, WORD );
WORD sosDIGISetChannel ( WORD, WORD, WORD );
WORD sosDIGIGetChannel ( WORD, WORD );
WORD sosDIGIGetBytesProcessed ( WORD, WORD );
WORD sosDIGIGetLoopCount ( WORD, WORD );
WORD sosDIGISetPanLocation ( WORD, WORD, WORD );
WORD sosDIGIGetPanLocation ( WORD, WORD );
DWORD sosDIGISetPitch ( WORD, WORD, DWORD );
DWORD sosDIGIGetPitch ( WORD, WORD );
WORD sosDIGIGetDMAPosition ( WORD );
WORD sosDIGISetPanSpeed ( WORD, WORD, WORD );
WORD sosDIGIGetPanSpeed ( WORD, WORD );
WORD sosDIGIGetSampleID ( WORD, WORD );
WORD sosDIGIGetSampleHandle ( WORD, WORD );
WORD sosDIGISetMasterVolume ( WORD, WORD );
#ifdef PHARLAP
VOID sosFreeVDSPage ( unsigned short, unsigned short, DWORD );
WORD sosAllocVDSPage ( unsigned short *, unsigned short *, DWORD * );
#else
WORD sosAllocVDSPage ( LPSTR *, WORD *, WORD * );
VOID sosFreeVDSPage ( WORD, WORD, LONG );
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef PHARLAP
extern int __cdecl sosRealFree ( int );
extern BOOL __cdecl _sos_read( WORD, LPSTR, WORD, WORD * );
extern int __cdecl sosRealAlloc( int, int *, int * );
extern void __cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );
extern int __cdecl sosGetCS( VOID );
extern int __cdecl sosGetES( VOID );
#else
extern int __cdecl sosRealAlloc ( int, int *, int * );
extern int __cdecl sosRealFree ( int );
#endif
// sos driver functions
extern WORD __cdecl sosDRVLockMemory ( DWORD, DWORD );
extern WORD __cdecl sosDRVUnLockMemory ( DWORD, DWORD );
extern void __cdecl sosDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDRVGetCapsPtr ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDRVInit ( LPSTR, LPSTR, int, int, int, int, int, int );
extern void __cdecl sosDRVStart ( LPSTR, LPSTR, int, int );
extern void __cdecl sosDRVSetRate ( LPSTR, LPSTR, int );
extern void __cdecl sosDRVSetAction ( LPSTR, LPSTR );
extern void __cdecl sosDRVStop ( LPSTR, LPSTR );
extern void __cdecl sosDRVUnInit ( LPSTR, LPSTR );
extern void __cdecl sosDRVGetFillInfo ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );
extern void __cdecl sosFillSampleStructs ( PSTR, LPSTR );
extern WORD __cdecl sosDetDRVExist ( LPSTR, LPSTR );
extern WORD __cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );
extern WORD __cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );
extern WORD __cdecl sosDIGIInitForWindows( WORD );
extern WORD __cdecl sosDIGIUnInitForWindows( WORD );
extern LPSTR __cdecl sosAllocateFarMem ( WORD, PSTR, WORD * );
extern LPSTR __cdecl sosCreateAliasCS ( LPSTR );
extern VOID __cdecl sosFreeSelector ( LPSTR, DWORD );
extern LPSTR __cdecl sosMAKEDOSPtr ( PSTR );
extern VOID __cdecl sosDetDRVSetEnvString ( DWORD, PSTR );
extern PSTR __cdecl sosDetDRVGetEnvString ( DWORD );
extern VOID __cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );
extern VOID __cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );
extern WORD __cdecl sosDRVGetFreeMemory ( VOID );
extern WORD __cdecl sosDRVAllocVDSStruct ( WORD, WORD *, WORD * );
extern WORD __cdecl sosDRVFreeVDSStruct ( WORD, WORD );
extern WORD __cdecl sosDRVIsWindowsActive ( VOID );
extern WORD __cdecl sosDRVVDSGetBuffer ( WORD );
extern WORD __cdecl sosDRVVDSFreeBuffer ( WORD );
extern WORD __cdecl getDS( VOID );
extern WORD __cdecl sosDRVMakeDMASelector ( WORD );
extern WORD __cdecl sosDRVFreeDMASelector ( WORD );
extern void __cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );
extern void __cdecl sosTIMERDRVUnInit( void );
extern void __cdecl sosTIMERDRVHandler( void );
extern void __cdecl sosTIMERDRVFHandler( void );
extern void __cdecl sosTIMERDRVEnable( void );
extern void __cdecl sosTIMERDRVDisable( void );
extern void __cdecl sosTIMERDRVCallOld( void );
extern void __cdecl sosTIMERDRVSetRate( WORD );
extern void __cdecl sosDIGITimer_Start( void );
extern void __cdecl sosDIGITimer_End( void );
extern void __cdecl sosDIGIDrv_Start( void );
extern void __cdecl sosDIGIDrv_End( void );
#ifdef __cplusplus
}
#endif
// external functions for handling system initialization and
// uninitialization
WORD sosEXDIGInitDriver ( WORD, WORD, WORD, LPSTR,
_SOS_HARDWARE far *, WORD * );
WORD sosEXDIGIUnInitDriver ( VOID );
WORD sosEXDETFindDriver ( WORD, LPSTR, _SOS_HARDWARE far *,
_SOS_CAPABILITIES far * );
// memory locking prototypes
VOID sosDIGICaps_Start( VOID );
VOID sosDIGICaps_End( VOID );
VOID sosDIGIErr_Start( VOID );
VOID sosDIGIErr_End( VOID );
VOID sosDIGITmr_Start( VOID );
VOID sosDIGITmr_End( VOID );
VOID sosDIGIStart_Start( VOID );
VOID sosDIGIStart_End( VOID );
VOID sosDIGIPlyng_Start( VOID );
VOID sosDIGIPlyng_End( VOID );
VOID sosDIGIRate_Start( VOID );
VOID sosDIGIRate_End( VOID );
VOID sosDIGIDone_Start( VOID );
VOID sosDIGIDone_End( VOID );
VOID sosDIGIDetec_Start( VOID );
VOID sosDIGIDetec_End( VOID );
VOID sosDIGIInit_Start( VOID );
VOID sosDIGIInit_End( VOID );
VOID sosDIGILoad_Start( VOID );
VOID sosDIGILoad_End( VOID );
VOID sosDIGICntl_Start( VOID );
VOID sosDIGICntl_End( VOID );
#pragma pack()
#endif

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

@@ -0,0 +1,129 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosres.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#define _SOS_RESOURCE
#ifndef _SOS_RESOURCE
#define _SOS_RESOURCE
// structure for resource file header
typedef struct
{
// file version
WORD wVersion;
// file size
LONG dwFileSize;
// number of resources in file
WORD wResCount;
// offset of resource data from top of file
LONG dwResOffset;
// offset of sync track from top of file
LONG dwSyncTrackOffset;
} _RES_FILE_HEADER;
// structure for resource block header
typedef struct
{
// resource id
WORD wID;
// resource type
WORD wResType;
// offset of next block
LONG dwNextBlock;
// size of the current resource information
LONG dwResSize;
// rate to play block at
WORD wBlockRate;
// id for the sync track to use
WORD wSyncTrackID;
} _RES_BLOCK_HEADER;
// structure for sync mark tag
typedef struct _tagSYNCMARK
{
// ID of the type of mark being used
WORD wID;
// location in data of sync mark
LONG dwSyncOffset;
// length of sync block
LONG dwSyncSize;
// start sample data
_SOS_START_SAMPLE sampleData;
} _RES_SYNCMARK;
typedef union
{
// structure for sync mark tag
_RES_SYNCMARK syncMark;
} _RES_TAG;
// union for filter information for prepareWave
typedef union
{
// filter type
WORD wFilterID;
// structure for volume
struct volume
{
WORD wVolume;
};
// structure for delay
struct delay
{
WORD wDelaySamples;
};
} _SOS_FILTER;
#endif


View File

@@ -0,0 +1,54 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood Library *
* *
* File Name : SOUND.H *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : September 1, 1993 *
* *
* Last Update : September 1, 1993 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SOUND_H
#define SOUND_H
//#define HMI_DRIVER TRUE
//#include "sos.h"
#include "soscomp.h"
/*
** Maximum number of sound effects that may run at once.
*/
#define MAX_SFX 5
/*
** Size of temp HMI low memory staging buffer.
*/
#define SECONDARY_BUFFER_SIZE (1024*32)
#endif

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,120 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : SOUNDLCK.CPP *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : June 23, 1995 *
* *
* Last Update : June 23, 1995 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check
#define _WIN32
#endif // _WIN32
#define WIN32
#include <windows.h>
#include <windowsx.h>
#include <objbase.h>
#include "dsound.h"
#include <mem.h>
#include "wwmem.h"
#include "wwstd.h"
#include "soundint.h"
LockedDataType LockedData;
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* INIT_LOCKED_DATA -- Initializes sound driver locked data *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
void Init_Locked_Data(void)
{
/*
** Initialize all of the data elements that need to be locked.
*/
LockedData.DigiHandle = -1;
LockedData.ServiceSomething = FALSE;
LockedData.MagicNumber = 0xDEAF;
LockedData.UncompBuffer = NULL;
// LockedData.StreamBufferSize = (2*SECONDARY_BUFFER_SIZE)+128;
LockedData.StreamBufferSize = (SECONDARY_BUFFER_SIZE/4)+128;
LockedData.StreamBufferCount = 16;
LockedData.SoundVolume = 255;
LockedData.ScoreVolume = 255;
LockedData._int = FALSE;
#ifdef cuts
/*
** Lock the sound specific c functions that will cause us problems if
** they are swapped out during an interrupt.
*/
DPMI_Lock(&LockedData, 4096L);
DPMI_Lock(Simple_Copy, 4096L);
DPMI_Lock(Sample_Copy, 4096L);
DPMI_Lock((void *)maintenance_callback, 4096L);
DPMI_Lock((void *)DigiCallback, 4096L);
DPMI_Lock((void *)HMI_TimerCallback, 4096L);
DPMI_Lock(Audio_Add_Long_To_Pointer, 4096L);
DPMI_Lock(DPMI_Unlock, 4096L);
/*
** Lock the library functions that will cause us problems if they are
** swapped out during an interrupt.
*/
DPMI_Lock(Mem_Copy, 4096L);
DPMI_Lock(Audio_Mem_Set, 4096L);
DPMI_Lock(__GETDS, 4096L);
/*
** Finally lock the two assembly modules that need locking. This can
** be handled by calling the lock function that is local to thier module
** swapped out during an interrupt.
*/
Decompress_Frame_Lock();
sosCODEC_Lock();
#endif //cuts
}

View File

@@ -0,0 +1,39 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include "audio.h"
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
File_Stream_Sample_Vol("file", 0, 0);
return (0);
}

View File

@@ -0,0 +1,32 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#undef _WINDOWS_16_
#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check
#define _WIN32
#endif // _WIN32
#define WIN32
#define __WIN32
#include <windows.h>
#include <windowsx.h>
#include <ole2.h>
main
{}

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

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

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

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

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

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

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

@@ -0,0 +1,83 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
*
* File : soscomp.h
* Date Created : 6/1/94
* Description :
*
* Programmer(s) : Nick Skrepetos
* Last Modification : 10/1/94 - 11:37:9 AM
* Additional Notes : Modified by Denzil E. Long, Jr.
*
*****************************************************************************
* Copyright (c) 1994, HMI, Inc. All Rights Reserved *
****************************************************************************/
#ifndef _SOS_COMPRESS
#define _SOS_COMPRESS
/* compression types */
enum {
_ADPCM_TYPE_1,
};
/* define compression structure */
typedef struct _tagCOMPRESS_INFO {
char *lpSource;
char *lpDest;
unsigned long dwCompSize;
unsigned long dwUnCompSize;
unsigned long dwSampleIndex;
long dwPredicted;
long dwDifference;
short wCodeBuf;
short wCode;
short wStep;
short wIndex;
unsigned long dwSampleIndex2; //added BP for channel 2
long dwPredicted2; //added BP for channel 2
long dwDifference2; //added BP for channel 2
short wCodeBuf2; //added BP for channel 2
short wCode2; //added BP for channel 2
short wStep2; //added BP for channel 2
short wIndex2; //added BP for channel 2
short wBitSize;
short wChannels; //added BP for # of channels
} _SOS_COMPRESS_INFO;
/* compressed file type header */
typedef struct _tagCOMPRESS_HEADER {
unsigned long dwType; // type of compression
unsigned long dwCompressedSize; // compressed file size
unsigned long dwUnCompressedSize; // uncompressed file size
unsigned long dwSourceBitSize; // original bit size
char szName[16]; // file type, for error checking
} _SOS_COMPRESS_HEADER;
/* Prototypes */
extern "C" {
void __cdecl sosCODECInitStream(_SOS_COMPRESS_INFO *);
unsigned long __cdecl sosCODECCompressData(_SOS_COMPRESS_INFO *, unsigned long);
unsigned long __cdecl sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);
unsigned long __cdecl General_sosCODECDecompressData(_SOS_COMPRESS_INFO *, unsigned long);
}
#endif

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

@@ -0,0 +1,128 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosdata.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOS_DATA
#define _SOS_DATA
#include <stddef.h>
#pragma pack(4)
extern WORD _sosDIGIData_Start;
extern WORD _sosDIGIData_End;
extern WORD _wSOSDriverLinear[];
extern WORD _wSOSTimerLinear[];
extern LPSTR _lpSOSDriver[];
extern LPSTR _lpSOSTimer[];
extern LPSTR _lpSOSDriverCS[];
extern LPSTR _lpSOSTimerCS[];
extern BOOL _wSOSDriverLoaded[];
extern BOOL _wSOSTimerLoaded[];
extern BOOL _wSOSDriverInitialized[];
extern WORD _wSOSOutputRate[];
extern WORD _wSOSDMABuffersize[];
extern LONG _dwSOSDMABufferPhysical[];
extern LPSTR _lpSOSDMABuffer[];
extern BOOL _wTimerUsed;
extern VOID ( far *_lpSOSFillHandler[] )( VOID );
extern WORD _wSOSTimerType[];
extern WORD _wSOSDriverType[];
extern _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ];
extern LPWORD _lpSOSDMAIrqCount[];
extern LPWORD _lpSOSDMAFillCount[];
extern WORD _wSOSTmrNextCount;
extern VOID ( interrupt far *_lpSOSOldTimer )( VOID );
extern WORD _wSOSDriverID[];
extern _SOS_CAPABILITIES _sSOSDriverCaps[];
extern WORD _wSOSDMAPortList[];
extern BYTE _bSOSDMAChannel[];
extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[];
extern BYTE _pSOSDriverPath[];
extern BYTE _pSOSTempDriverPath[];
extern BOOL _wTIMERUsed;
extern WORD _wTIMERValue;
extern VOID ( far * _lpTIMEREvents[] )( VOID );
extern WORD _wTIMEREventRate[];
extern WORD _dwTIMEREventFraction[];
extern WORD _dwTIMEREventFractionCurrent[];
extern BYTE _bSOSMIDITimerSongHandler[];
extern BYTE _bSOSMIDISongHandle;
extern WORD _wSOSTimerMemHandle[];
extern WORD _wSOSDriverMemHandle[];
extern WORD _wSOSRealSeg[];
extern _FILEHEADER _sDETFileHeader;
extern _DRIVERHEADER _sDETDriverHeader;
extern _FILEHEADER sLOADFileHeader;
extern _DRIVERHEADER sLOADDriverHeader;
extern BOOL _wDETInitialized;
extern WORD _wDETLinear;
extern LPSTR _lpDETDriverBuffer;
extern LPSTR _lpDETDriverBufferCS;
extern WORD _hDETFile;
extern DWORD _dwDETDriverIndex;
extern WORD _wDETDriverIndexCur;
extern WORD _wDETMemHandle;
extern LPSOSDEVICECAPS _lpDETDeviceCaps;
extern _SOS_CAPABILITIES _sDETCaps;
extern PSTR _pSOSErrorStrings[];
extern BOOL _wSOSBufferAllocated[];
extern BOOL _wSOSSystemInitialized;
extern VDS_STRUCT _sSOSVDSInfo;
extern _SOS_FILL_INFO _sSOSFillInfo;
extern WORD _wSOSTimerEventIndex;
extern WORD _wSOSTimerEntered;
extern WORD _wSOSDriverSize[];
extern WORD _wSOSTimerSize[];
#ifdef __cplusplus
extern "C" {
#endif
extern WORD _sosDIGIData1_Start;
extern WORD _sosDIGIData1_End;
extern WORD _sosDIGIData2_Start;
extern WORD _sosDIGIData2_End;
extern BYTE _bTIMERInstalled;
extern BYTE _bTIMERDPMI;
extern WORD wDetectPort;
extern WORD wDetectIRQ;
extern WORD wDetectDMA;
extern WORD wDetectParam;
#ifdef __cplusplus
}
#endif
#pragma pack()
#endif

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

@@ -0,0 +1,83 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosdefs.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOSDEFS_DEFINED
#define _SOSDEFS_DEFINED
#undef _TRUE
#undef _FALSE
#undef _NULL
enum
{
_FALSE,
_TRUE
};
#define _NULL 0
#ifndef VOID
#define VOID void
#endif
typedef int BOOL;
typedef unsigned int UINT;
typedef unsigned char BYTE;
typedef unsigned WORD;
#ifndef LONG
typedef signed long LONG;
#endif
typedef unsigned long DWORD;
typedef BYTE * PBYTE;
typedef char near * PSTR;
typedef WORD * PWORD;
typedef LONG * PLONG;
typedef VOID * PVOID;
typedef BYTE far * LPBYTE;
typedef BYTE far * LPSTR;
typedef WORD far * LPWORD;
typedef LONG far * LPLONG;
typedef VOID far * LPVOID;
typedef BYTE huge * HPBYTE;
typedef BYTE huge * HPSTR;
typedef WORD huge * HPWORD;
typedef LONG huge * HPLONG;
typedef VOID huge * HPVOID;
typedef unsigned HANDLE;
#endif

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

@@ -0,0 +1,219 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosfnct.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#ifndef _SOS_FUNCTIONS
#define _SOS_FUNCTIONS
#pragma pack(4)
WORD sosDIGILockMemory ( VOID );
WORD sosDIGIUnLockMemory ( VOID );
WORD sosDIGIInitSystem ( LPSTR, WORD );
WORD sosDIGIUnInitSystem ( VOID );
WORD sosDIGIInitDriver ( WORD, _SOS_HARDWARE far *,
_SOS_INIT_DRIVER far *, WORD far * );
WORD sosDIGIUnInitDriver ( WORD, BOOL, BOOL );
WORD sosDIGILoadDriver ( WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );
WORD sosDIGIUnLoadDriver ( WORD );
WORD sosDIGIGetDeviceCaps ( WORD, LPSOSDEVICECAPS );
#ifdef PHARLAP
LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * );
#else
LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * );
#endif
WORD sosDIGIStopSample ( WORD, WORD );
WORD sosDIGISamplesPlaying ( WORD );
BOOL sosDIGISampleDone ( WORD, WORD );
BOOL sosDIGISampleFilling ( WORD, WORD );
WORD sosDIGIStartSample ( WORD, _SOS_START_SAMPLE far * );
WORD sosDIGIContinueSample ( WORD, WORD, _SOS_START_SAMPLE far * );
WORD sosDIGIDetectInit ( LPSTR );
WORD sosDIGIDetectUnInit ( VOID );
WORD sosDIGIDetectFindHardware ( WORD, _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectFindFirst ( _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectFindNext ( _SOS_CAPABILITIES far *, WORD far * );
WORD sosDIGIDetectGetSettings ( _SOS_HARDWARE far * );
WORD sosDIGIDetectGetCaps ( WORD, _SOS_CAPABILITIES far * );
WORD sosDIGIDetectVerifySettings( _SOS_HARDWARE far * );
PSTR sosGetErrorString ( WORD );
WORD sosDIGILoadTimer ( WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * );
WORD sosDIGIUnLoadTimer ( WORD );
WORD sosTIMERRegisterEvent ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle );
WORD sosTIMERInitSystem ( WORD, WORD );
WORD sosTIMERUnInitSystem ( WORD );
WORD sosTIMERSetRate ( WORD );
WORD sosTIMERRemoveEvent ( WORD );
WORD sosTIMERAlterEventRate ( WORD, WORD );
WORD sosTIMERGetEventRate ( WORD );
VOID far sosTIMEROldHandler ( VOID );
VOID far sosTIMERHandler ( VOID );
// functions in soscntl.c
WORD sosDIGISetSampleVolume ( WORD, WORD, WORD );
WORD sosDIGIGetSampleVolume ( WORD, WORD );
WORD sosDIGISetChannel ( WORD, WORD, WORD );
WORD sosDIGIGetChannel ( WORD, WORD );
WORD sosDIGIGetBytesProcessed ( WORD, WORD );
WORD sosDIGIGetLoopCount ( WORD, WORD );
WORD sosDIGISetPanLocation ( WORD, WORD, WORD );
WORD sosDIGIGetPanLocation ( WORD, WORD );
DWORD sosDIGISetPitch ( WORD, WORD, DWORD );
DWORD sosDIGIGetPitch ( WORD, WORD );
WORD sosDIGIGetDMAPosition ( WORD );
WORD sosDIGISetPanSpeed ( WORD, WORD, WORD );
WORD sosDIGIGetPanSpeed ( WORD, WORD );
WORD sosDIGIGetSampleID ( WORD, WORD );
WORD sosDIGIGetSampleHandle ( WORD, WORD );
WORD sosDIGISetMasterVolume ( WORD, WORD );
#ifdef PHARLAP
VOID sosFreeVDSPage ( unsigned short, unsigned short, DWORD );
WORD sosAllocVDSPage ( unsigned short *, unsigned short *, DWORD * );
#else
WORD sosAllocVDSPage ( LPSTR *, WORD *, WORD * );
VOID sosFreeVDSPage ( WORD, WORD, LONG );
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef PHARLAP
extern int __cdecl sosRealFree ( int );
extern BOOL __cdecl _sos_read( WORD, LPSTR, WORD, WORD * );
extern int __cdecl sosRealAlloc( int, int *, int * );
extern void __cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD );
extern int __cdecl sosGetCS( VOID );
extern int __cdecl sosGetES( VOID );
#else
extern int __cdecl sosRealAlloc ( int, int *, int * );
extern int __cdecl sosRealFree ( int );
#endif
// sos driver functions
extern WORD __cdecl sosDRVLockMemory ( DWORD, DWORD );
extern WORD __cdecl sosDRVUnLockMemory ( DWORD, DWORD );
extern void __cdecl sosDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDRVGetCapsPtr ( LPSTR, LPSTR, _SOS_CAPABILITIES far * );
extern void __cdecl sosDRVInit ( LPSTR, LPSTR, int, int, int, int, int, int );
extern void __cdecl sosDRVStart ( LPSTR, LPSTR, int, int );
extern void __cdecl sosDRVSetRate ( LPSTR, LPSTR, int );
extern void __cdecl sosDRVSetAction ( LPSTR, LPSTR );
extern void __cdecl sosDRVStop ( LPSTR, LPSTR );
extern void __cdecl sosDRVUnInit ( LPSTR, LPSTR );
extern void __cdecl sosDRVGetFillInfo ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * );
extern void __cdecl sosFillSampleStructs ( PSTR, LPSTR );
extern WORD __cdecl sosDetDRVExist ( LPSTR, LPSTR );
extern WORD __cdecl sosDetDRVGetSettings ( LPSTR, LPSTR );
extern WORD __cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR );
extern WORD __cdecl sosDIGIInitForWindows( WORD );
extern WORD __cdecl sosDIGIUnInitForWindows( WORD );
extern LPSTR __cdecl sosAllocateFarMem ( WORD, PSTR, WORD * );
extern LPSTR __cdecl sosCreateAliasCS ( LPSTR );
extern VOID __cdecl sosFreeSelector ( LPSTR, DWORD );
extern LPSTR __cdecl sosMAKEDOSPtr ( PSTR );
extern VOID __cdecl sosDetDRVSetEnvString ( DWORD, PSTR );
extern PSTR __cdecl sosDetDRVGetEnvString ( DWORD );
extern VOID __cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR );
extern VOID __cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR );
extern WORD __cdecl sosDRVGetFreeMemory ( VOID );
extern WORD __cdecl sosDRVAllocVDSStruct ( WORD, WORD *, WORD * );
extern WORD __cdecl sosDRVFreeVDSStruct ( WORD, WORD );
extern WORD __cdecl sosDRVIsWindowsActive ( VOID );
extern WORD __cdecl sosDRVVDSGetBuffer ( WORD );
extern WORD __cdecl sosDRVVDSFreeBuffer ( WORD );
extern WORD __cdecl getDS( VOID );
extern WORD __cdecl sosDRVMakeDMASelector ( WORD );
extern WORD __cdecl sosDRVFreeDMASelector ( WORD );
extern void __cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) );
extern void __cdecl sosTIMERDRVUnInit( void );
extern void __cdecl sosTIMERDRVHandler( void );
extern void __cdecl sosTIMERDRVFHandler( void );
extern void __cdecl sosTIMERDRVEnable( void );
extern void __cdecl sosTIMERDRVDisable( void );
extern void __cdecl sosTIMERDRVCallOld( void );
extern void __cdecl sosTIMERDRVSetRate( WORD );
extern void __cdecl sosDIGITimer_Start( void );
extern void __cdecl sosDIGITimer_End( void );
extern void __cdecl sosDIGIDrv_Start( void );
extern void __cdecl sosDIGIDrv_End( void );
#ifdef __cplusplus
}
#endif
// external functions for handling system initialization and
// uninitialization
WORD sosEXDIGInitDriver ( WORD, WORD, WORD, LPSTR,
_SOS_HARDWARE far *, WORD * );
WORD sosEXDIGIUnInitDriver ( VOID );
WORD sosEXDETFindDriver ( WORD, LPSTR, _SOS_HARDWARE far *,
_SOS_CAPABILITIES far * );
// memory locking prototypes
VOID sosDIGICaps_Start( VOID );
VOID sosDIGICaps_End( VOID );
VOID sosDIGIErr_Start( VOID );
VOID sosDIGIErr_End( VOID );
VOID sosDIGITmr_Start( VOID );
VOID sosDIGITmr_End( VOID );
VOID sosDIGIStart_Start( VOID );
VOID sosDIGIStart_End( VOID );
VOID sosDIGIPlyng_Start( VOID );
VOID sosDIGIPlyng_End( VOID );
VOID sosDIGIRate_Start( VOID );
VOID sosDIGIRate_End( VOID );
VOID sosDIGIDone_Start( VOID );
VOID sosDIGIDone_End( VOID );
VOID sosDIGIDetec_Start( VOID );
VOID sosDIGIDetec_End( VOID );
VOID sosDIGIInit_Start( VOID );
VOID sosDIGIInit_End( VOID );
VOID sosDIGILoad_Start( VOID );
VOID sosDIGILoad_End( VOID );
VOID sosDIGICntl_Start( VOID );
VOID sosDIGICntl_End( VOID );
#pragma pack()
#endif

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

@@ -0,0 +1,129 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
File : sosres.h
Programmer(s) : Don Fowler, Nick Skrepetos
Date :
Purpose : Include Files For Zortech C++ Compiler
Last Updated :
****************************************************************************
Copyright(c) 1993,1994 Human Machine Interfaces
All Rights Reserved
****************************************************************************/
#define _SOS_RESOURCE
#ifndef _SOS_RESOURCE
#define _SOS_RESOURCE
// structure for resource file header
typedef struct
{
// file version
WORD wVersion;
// file size
LONG dwFileSize;
// number of resources in file
WORD wResCount;
// offset of resource data from top of file
LONG dwResOffset;
// offset of sync track from top of file
LONG dwSyncTrackOffset;
} _RES_FILE_HEADER;
// structure for resource block header
typedef struct
{
// resource id
WORD wID;
// resource type
WORD wResType;
// offset of next block
LONG dwNextBlock;
// size of the current resource information
LONG dwResSize;
// rate to play block at
WORD wBlockRate;
// id for the sync track to use
WORD wSyncTrackID;
} _RES_BLOCK_HEADER;
// structure for sync mark tag
typedef struct _tagSYNCMARK
{
// ID of the type of mark being used
WORD wID;
// location in data of sync mark
LONG dwSyncOffset;
// length of sync block
LONG dwSyncSize;
// start sample data
_SOS_START_SAMPLE sampleData;
} _RES_SYNCMARK;
typedef union
{
// structure for sync mark tag
_RES_SYNCMARK syncMark;
} _RES_TAG;
// union for filter information for prepareWave
typedef union
{
// filter type
WORD wFilterID;
// structure for volume
struct volume
{
WORD wVolume;
};
// structure for delay
struct delay
{
WORD wDelaySamples;
};
} _SOS_FILTER;
#endif


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

@@ -0,0 +1,54 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood Library *
* *
* File Name : SOUND.H *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : September 1, 1993 *
* *
* Last Update : September 1, 1993 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SOUND_H
#define SOUND_H
//#define HMI_DRIVER TRUE
//#include "sos.h"
#include "soscomp.h"
/*
** Maximum number of sound effects that may run at once.
*/
#define MAX_SFX 5
/*
** Size of temp HMI low memory staging buffer.
*/
#define SECONDARY_BUFFER_SIZE (1024*32)
#endif

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

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

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

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

2207
WIN32LIB/AUDIO/SOUNDIO.CPP Normal file

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,120 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
***************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : SOUNDLCK.CPP *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : June 23, 1995 *
* *
* Last Update : June 23, 1995 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check
#define _WIN32
#endif // _WIN32
#define WIN32
#include <windows.h>
#include <windowsx.h>
#include <objbase.h>
#include "dsound.h"
#include <mem.h>
#include "wwmem.h"
#include "wwstd.h"
#include "soundint.h"
LockedDataType LockedData;
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* INIT_LOCKED_DATA -- Initializes sound driver locked data *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
void Init_Locked_Data(void)
{
/*
** Initialize all of the data elements that need to be locked.
*/
LockedData.DigiHandle = -1;
LockedData.ServiceSomething = FALSE;
LockedData.MagicNumber = 0xDEAF;
LockedData.UncompBuffer = NULL;
// LockedData.StreamBufferSize = (2*SECONDARY_BUFFER_SIZE)+128;
LockedData.StreamBufferSize = (SECONDARY_BUFFER_SIZE/4)+128;
LockedData.StreamBufferCount = 16;
LockedData.SoundVolume = 255;
LockedData.ScoreVolume = 255;
LockedData._int = FALSE;
#ifdef cuts
/*
** Lock the sound specific c functions that will cause us problems if
** they are swapped out during an interrupt.
*/
DPMI_Lock(&LockedData, 4096L);
DPMI_Lock(Simple_Copy, 4096L);
DPMI_Lock(Sample_Copy, 4096L);
DPMI_Lock((void *)maintenance_callback, 4096L);
DPMI_Lock((void *)DigiCallback, 4096L);
DPMI_Lock((void *)HMI_TimerCallback, 4096L);
DPMI_Lock(Audio_Add_Long_To_Pointer, 4096L);
DPMI_Lock(DPMI_Unlock, 4096L);
/*
** Lock the library functions that will cause us problems if they are
** swapped out during an interrupt.
*/
DPMI_Lock(Mem_Copy, 4096L);
DPMI_Lock(Audio_Mem_Set, 4096L);
DPMI_Lock(__GETDS, 4096L);
/*
** Finally lock the two assembly modules that need locking. This can
** be handled by calling the lock function that is local to thier module
** swapped out during an interrupt.
*/
Decompress_Frame_Lock();
sosCODEC_Lock();
#endif //cuts
}

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

@@ -0,0 +1,39 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include "audio.h"
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
File_Stream_Sample_Vol("file", 0, 0);
return (0);
}

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

@@ -0,0 +1,32 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#undef _WINDOWS_16_
#ifndef _WIN32 // Denzil 6/2/98 Watcom 11.0 complains without this check
#define _WIN32
#endif // _WIN32
#define WIN32
#define __WIN32
#include <windows.h>
#include <windowsx.h>
#include <ole2.h>
main
{}

View File

@@ -0,0 +1,328 @@
/*
** 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/>.
*/
/* $Header: g:/library/source/rcs/./dipthong.c 1.15 1994/05/20 15:35:17 joe_bostic Exp $ */
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
***************************************************************************
* *
* Project Name : Westwood Library *
* *
* File Name : DIPTHONG.C *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : February 23, 1992 *
* *
* Last Update : February 13, 1995 [BWG] *
* *
* DIGRAM or DIATOMIC encoding is the correct term for this method. *
* This is a fixed dictionary digram encoding optimized for English text. *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Extract_String -- Extracts a string pointer from a string data block. *
* UnDip_Text -- Undipthongs a text string into specified buffer. *
* Dip_Text -- Compresses text by using dipthonging. *
* Fixup_Text -- Converts dipthonged foreign text into normal text. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//#include "function.h"
//#include "ems.h"
#include <keyboard.h>
#include "dipthong.h"
/***************************************************************************
* Fixup_Text -- Converts dipthonged foreign text into normal text. *
* *
* Takes text that has been processed (or undipped) to hold foriegn *
* language character pairs (needed for Window_Print) and converts it *
* so that Text_Print will print it properly. Typically this would be *
* used after text has been undipped but before it will be Text_Printed.*
* Text that is to be Window_Printed doesn't and mustn't have its text *
* processed by this routine. *
* *
* INPUT: source -- Pointer to the source string to process. *
* *
* dest -- Destination buffer to hold the processed string. *
* *
* OUTPUT: none *
* *
* WARNINGS: This routine will only reduce the size of the string if it *
* modifies it at all. Because of this it is quite legal to *
* pass the same pointers to this routine so that it will *
* modify the string "in place". *
* *
* HISTORY: *
* 08/13/1993 JLB : Created. *
* 10/06/1994 JLB : Handles source string in EMS. *
*=========================================================================*/
void Fixup_Text(char const *source, char *dest)
{
if (source && dest) {
char const *src;
char temp;
src = source;
while (*src) {
if (*src == KA_EXTEND) {
src++;
temp = *src++;
temp += 127;
*dest++ = temp;
} else {
*dest++ = *src++;
}
}
*dest = '\0';
}
}
/***************************************************************************
* Dip_Text -- Compresses text by using dipthonging. *
* *
* This routine is used to compress text by using dipthonging. Text *
* that is compressed in this fashion usually is reduced in size by *
* approximately 40%. *
* *
* INPUT: source -- Pointer to the source string to compress. *
* *
* dest -- Pointer to the buffer that will hold the dipthong *
* text output. *
* *
* OUTPUT: Returns the number of bytes output into the output buffer. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/13/1993 JLB : Created. *
*=========================================================================*/
int Dip_Text(char const *source, char *dest)
{
unsigned char first, // First character in pair.
next; // Second character in pair.
int common, // Common character index.
dipthong; // Dipthong character index.
unsigned long length=0; // Length of output string
first = *source++;
next = *source;
while (first) {
if (first > 127) {
/*
** Characters greater than 127 cannot be dipthonged. They must
** be preceeded with an extended character code.
*/
*dest++ = (char)KA_EXTEND;
first -= 127;
length++;
} else {
/*
** Normal characters can be dipthonged. First see if there is a
** match in the Common table.
*/
for (common = 0; common < 16; common++) {
if (Common[common] == first) {
/*
** Common character found. See if there is a matching
** Dipthong character.
*/
for (dipthong = 0; dipthong < 8; dipthong++) {
if (Dipthong[common][dipthong] == next) {
first = (unsigned char) (common << 3);
first |= (unsigned char)dipthong;
first |= (unsigned char)0x80;
source++;
}
}
}
}
}
/*
** Output the translated character to the destination buffer.
*/
*dest++ = first;
length++;
first = *source++;
next = *source;
}
*dest = '\0';
return(length);
}
/***************************************************************************
* UnDip_Text -- Undipthongs a text string into specified buffer. *
* *
* This routine is used to undipthong a text string and place the *
* undipped text into the buffer specified. Since dipthonged text is *
* compressed, in order for the text to be used it must be undipped *
* first. *
* *
* INPUT: source -- Pointer to the dipped string. *
* *
* dest -- Pointer to the destination buffer. *
* *
* OUTPUT: Returns the number of bytes placed into the destination *
* buffer. *
* *
* WARNINGS: Be sure the destination buffer is big enough to hold the *
* undipped text. *
* *
* HISTORY: *
* 08/13/1993 JLB : Created. *
* 10/06/1994 JLB : Handles source string in EMS. *
*=========================================================================*/
int UnDip_Text(char const *source, char *dest)
{
int c; // Source input character.
int common; // Common character index.
int len; // Length of output string.
char const *src;
len = 0; // Presume no translation.
/*
** Sweep through the source text and dipthong it.
*/
src = source;
c = *src++;
while (c) {
/*
** Convert a dipthong character into it's component
** ASCII characters.
*/
if (c & 0x80) {
c &= 0x7F;
common = (c & 0x78) >> 3;
*dest++ = Common[common];
len++;
c = Dipthong[common][c & 0x07];
}
*dest++ = (unsigned char)c;
len++;
c = *src++;
}
/*
** End the output text with a '\0'.
*/
*dest++ = '\0';
return(len);
}
/***************************************************************************
* Extract_String -- Extracts a string pointer from a string data block. *
* *
* This routine is used to find a pointer to the specified string *
* inside a string block. String data blocks are created with the *
* TEXTMAKE utility. The data block my reside in XMS or EMS memory, *
* but of course the returned string pointer will also point to *
* such memory. In this case, the string must be placed in real *
* memory before it can be used. *
* *
* INPUT: data -- Pointer to the string data block. *
* *
* string -- The string number to extract (if < 0 then NULL *
* is returned). *
* *
* OUTPUT: Returns with pointer to the string number specified. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/13/1993 JLB : Created. *
* 08/13/1993 JLB : Handles EMS or XMS data pointer. *
*=========================================================================*/
#define TXT_GUEST 4567+3
#define TXT_LOGIN 4567+4
#define TXT_LOGIN_TO_INTERNET 4567+5
#define TXT_YOUR_HANDLE 4567+6
#define TXT_YOUR_PASSWORD 4567+7
#define TXT_INTERNET_HOST 4567+8
#define TXT_INTERNET_JOIN 4567+9
#define TXT_INTERNET_GAME_TYPE 4567+10
#define TXT_JOIN_INTERNET_GAME 4567+11
#define TXT_ENTER_IP_ADDRESS 4567+12
#define TXT_WINSOCK_CONNECTING 4567+13
#define TXT_WINSOCK_NOT_CONNECTING 4567+14
#define TXT_WINSOCK_UNABLE_TO_CONNECT_TO_SERVER 4567+15
#define TXT_WINSOCK_CONTACTING_SERVER 4567+16
#define TXT_WINSOCK_SERVER_ADDRESS_LOOKUP_FAILED 4567+17
#define TXT_WINSOCK_UNABLE_TO_ACCEPT_CLIENT 4567+18
#define TXT_WINSOCK_UNABLE_TO_CONNECT 4567+19
#define TXT_WINSOCK_CONNECTION_LOST 4567+20
#define TXT_WINSOCK_RESOLVING_HOST_ADDRESS 4567+21
static char InternetTxt[22][40]={
"Internet H2H",
"Host Internet Game",
"Join Internet Game",
"Guest",
"Login",
"Login to Planet Westwood",
"Planet Westwood Handle",
"Planet Westwood Password",
"Host Game",
"Join Game",
"Choose Type of Internet Game",
"Join Internet Game",
"Address of Host",
"Connecting...",
"Connection Error!",
"Unable to connect to host!",
"Connecting to host...",
"Unable to resolve host address!",
"Unable to accept client connection",
"Unable to connect!",
"Connection lost!",
"Resolving address of host..."
};
char *Extract_String(void const *data, int string)
{
unsigned short int const *ptr;
if (!data || string < 0) return(NULL);
if (string >= 4567) return (InternetTxt[string-4567]);
ptr = (unsigned short int const *)data;
return (((char*)data) + ptr[string]);
}

View File

@@ -0,0 +1,24 @@
/*
** 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/>.
*/
int Dip_Text(char const *source, char *dest);
int UnDip_Text(char const *source, char *dest);
char *Extract_String(void const *data, int string);
void Fixup_Text(char const *source, char *dest);
extern char Common[];
extern char Dipthong[16][8];

192
WIN32LIB/DIPTHONG/MAKEFILE Normal file
View File

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


View File

@@ -0,0 +1,170 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WWFLAT path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef COMPILER
!error COMPILER Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = dipthong
PROJ_DIR = $(WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(WIN32LIB)\lib
!include $(WIN32LIB)\\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = \
dipthong.obj \
_diptabl.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.path.asm = $(PROJ_DIR)
.path.c = $(PROJ_DIR)
.path.cpp = $(PROJ_DIR)
.path.h = $(PROJ_DIR)
.path.obj = $(PROJ_DIR)
.path.lib = $(WIN32LIB)\lib
.path.exe = $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = bcc32
CPP_CMD = bcc32
LIB_CMD = tlib
LINK_CMD = tlink32
ASM_CMD = tasm32
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(WIN32LIB)\LIB;$(COMPILER)\LIB
INCLUDEPATH = $(WIN32LIB)\INCLUDE;$(COMPILER)\INCLUDE
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj:
$(C_CMD) $(CC_CFG) $<
.cpp.obj:
$(CPP_CMD) $(CC_CFG) $<
.asm.obj:
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS)
copy *.h $(WIN32LIB)\\include
copy *.inc $(WIN32LIB)\\include
copy *.cpp $(WIN32LIB)\\srcdebug
copy *.asm $(WIN32LIB)\\srcdebug
$(LIB_CMD) $< $(LIB_CFG) @&&|
+-dipthong.obj &
+-_diptabl.obj
|
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(WWVCS)\\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..

View File

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


View File

@@ -0,0 +1,58 @@
/*
** 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/>.
*/
/* $Header: g:/library/source/rcs/./_diptabl.c 1.11 1994/05/20 15:36:04 joe_bostic Exp $ */
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
***************************************************************************
* *
* Project Name : Westwood Library *
* *
* File Name : _DIPTABL.C *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : July 3, 1991 *
* *
* Last Update : July 3, 1991 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char Common[16]={' ','e','t','a','i','n','o','s','r','l','h','c','d','u','p','m'};
char Dipthong[16][8]={
{'t','a','s','i','o',' ','w','b'},
{' ','r','n','s','d','a','l','m'},
{'h',' ','i','e','o','r','a','s'},
{'n','r','t','l','c',' ','s','y'},
{'n','s','t','c','l','o','e','r'},
{' ','d','t','g','e','s','i','o'},
{'n','r',' ','u','f','m','s','w'},
{' ','t','e','p','.','i','c','a'},
{'e',' ','o','i','a','d','u','r'},
{' ','l','a','e','i','y','o','d'},
{'e','i','a',' ','o','t','r','u'},
{'e','t','o','a','k','h','l','r'},
{' ','e','i','u',',','.','o','a'},
{'n','s','r','c','t','l','a','i'},
{'l','e','o','i','r','a','t','p'},
{'e','a','o','i','p',' ','b','m'},
};


View File

@@ -0,0 +1,462 @@
;
; 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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : BITBLIT.ASM *
;* *
;* Programmer : Julio R. Jerez *
;* *
;* Start Date : Feb 6, 1995 *
;* *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
PROC Linear_Blit_To_Linear C near
USES ebx,ecx,edx,esi,edi
;*===================================================================
;* define the arguements that our function takes.
;*===================================================================
ARG this_object :DWORD ; this is a member function
ARG dest :DWORD ; what are we blitting to
ARG x_pixel :DWORD ; x pixel position in source
ARG y_pixel :DWORD ; y pixel position in source
ARG dest_x0 :dword
ARG dest_y0 :dword
ARG pixel_width :DWORD ; width of rectangle to blit
ARG pixel_height:DWORD ; height of rectangle to blit
ARG trans :DWORD ; do we deal with transparents?
;*===================================================================
; Define some locals so that we can handle things quickly
;*===================================================================
LOCAL x1_pixel :dword
LOCAL y1_pixel :dword
LOCAL dest_x1 : dword
LOCAL dest_y1 : dword
LOCAL scr_ajust_width:DWORD
LOCAL dest_ajust_width:DWORD
LOCAL source_area : dword
LOCAL dest_area : dword
;This Clipping algorithm is a derivation of the very well known
;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency
;it is probably the most commontly implemented algorithm both in software
;and hardware for clipping lines, rectangles, and convex polygons against
;a rectagular clipping window. For reference see
;"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes
; pages 113 to 177".
; Briefly consist in computing the Sutherland code for both end point of
; the rectangle to find out if the rectangle is:
; - trivially accepted (no further clipping test, display rectangle)
; - trivially rejected (return with no action)
; - retangle must be iteratively clipped again edges of the clipping window
; and the remaining retangle is display.
; Clip Source Rectangle against source Window boundaries.
mov esi,[this_object] ; get ptr to src
xor ecx,ecx ; Set sutherland code to zero
xor edx,edx ; Set sutherland code to zero
; compute the difference in the X axis and get the bit signs into ecx , edx
mov edi,[(GraphicViewPort esi).GVPWidth] ; get width into register
mov ebx,[x_pixel] ; Get first end point x_pixel into register
mov eax,[x_pixel] ; Get second end point x_pixel into register
add ebx,[pixel_width] ; second point x1_pixel = x + width
shld ecx, eax,1 ; the sign bit of x_pixel is sutherland code0 bit4
mov [x1_pixel],ebx ; save second for future use
inc edi ; move the right edge by one unit
shld edx,ebx,1 ; the sign bit of x1_pixel is sutherland code0 bit4
sub eax,edi ; compute the difference x0_pixel - width
sub ebx,edi ; compute the difference x1_pixel - width
shld ecx,eax,1 ; the sign bit of the difference is sutherland code0 bit3
shld edx,ebx,1 ; the sign bit of the difference is sutherland code0 bit3
; the following code is just a repeticion of the above code
; in the Y axis.
mov edi,[(GraphicViewPort esi).GVPHeight] ; get height into register
mov ebx,[y_pixel]
mov eax,[y_pixel]
add ebx,[pixel_height]
shld ecx,eax,1
mov [y1_pixel ],ebx
inc edi
shld edx,ebx,1
sub eax,edi
sub ebx,edi
shld ecx,eax,1
shld edx,ebx,1
; Here we have the to Sutherland code into cl and dl
xor cl,5 ; bit 2 and 0 are complented, reverse then
xor dl,5 ; bit 2 and 0 are complented, reverse then
mov al,cl ; save code1 in case we have to clip iteratively
test dl,cl ; if any bit in code0 and its counter bit
jnz ??real_out ; in code1 is set then the rectangle in outside
or al,dl ; if all bit of code0 the counter bit in
jz ??clip_against_dest ; in code1 is set to zero, then all
; end points of the rectangle are
; inside the clipping window
; if we are here the polygon have to be clip iteratively
test cl,1000b ; if bit 4 in code0 is set then
jz ??scr_left_ok ; x_pixel is smaller than zero
mov [x_pixel],0 ; set x_pixel to cero.
??scr_left_ok:
test cl,0010b ; if bit 2 in code0 is set then
jz ??scr_bottom_ok ; y_pixel is smaller than zero
mov [ y_pixel ],0 ; set y_pixel to cero.
??scr_bottom_ok:
test dl,0100b ; if bit 3 in code1 is set then
jz ??scr_right_ok ; x1_pixel is greater than the width
mov eax,[(GraphicViewPort esi).GVPWidth] ; get width into register
mov [ x1_pixel ],eax ; set x1_pixel to width.
??scr_right_ok:
test dl,0001b ; if bit 0 in code1 is set then
jz ??clip_against_dest ; y1_pixel is greater than the width
mov eax,[(GraphicViewPort esi).GVPHeight] ; get height into register
mov [ y1_pixel ],eax ; set y1_pixel to height.
; Clip Source Rectangle against destination Window boundaries.
??clip_against_dest:
; build the destination rectangle before clipping
; dest_x1 = dest_x0 + ( x1_pixel - x_pixel )
; dest_y1 = dest_y0 + ( y1_pixel - y_pixel )
mov eax,[dest_x0] ; get dest_x0 into eax
mov ebx,[dest_y0] ; get dest_y0 into ebx
sub eax,[x_pixel] ; subtract x_pixel from eax
sub ebx,[y_pixel] ; subtract y_pixel from ebx
add eax,[x1_pixel] ; add x1_pixel to eax
add ebx,[y1_pixel] ; add y1_pixel to ebx
mov [dest_x1],eax ; save eax into dest_x1
mov [dest_y1],ebx ; save eax into dest_y1
; The followin code is a repeticion of the Sutherland clipping
; descrived above.
mov esi,[dest] ; get ptr to src
xor ecx,ecx
xor edx,edx
mov edi,[(GraphicViewPort esi).GVPWidth] ; get width into register
mov eax,[dest_x0]
mov ebx,[dest_x1]
shld ecx,eax,1
inc edi
shld edx,ebx,1
sub eax,edi
sub ebx,edi
shld ecx,eax,1
shld edx,ebx,1
mov edi,[( GraphicViewPort esi) . GVPHeight ] ; get height into register
mov eax,[dest_y0]
mov ebx,[dest_y1]
shld ecx,eax,1
inc edi
shld edx,ebx,1
sub eax,edi
sub ebx,edi
shld ecx,eax,1
shld edx,ebx,1
xor cl,5
xor dl,5
mov al,cl
test dl,cl
jnz ??real_out
or al,dl
jz ??do_blit
test cl,1000b
jz ??dest_left_ok
mov eax,[ dest_x0 ]
mov [ dest_x0 ],0
sub [ x_pixel ],eax
??dest_left_ok:
test cl,0010b
jz ??dest_bottom_ok
mov eax,[ dest_y0 ]
mov [ dest_y0 ],0
sub [ y_pixel ],eax
??dest_bottom_ok:
test dl,0100b
jz ??dest_right_ok
mov ebx,[ (GraphicViewPort esi) . GVPWidth ] ; get width into register
mov eax,[ dest_x1 ]
mov [ dest_x1 ],ebx
sub eax,ebx
sub [ x1_pixel ],eax
??dest_right_ok:
test dl,0001b
jz ??do_blit
mov ebx,[ (GraphicViewPort esi) . GVPHeight ] ; get width into register
mov eax,[ dest_y1 ]
mov [ dest_y1 ],ebx
sub eax,ebx
sub [ y1_pixel ],eax
; Here is where we do the actual blit
??do_blit:
cld
mov ebx,[this_object]
mov esi,[(GraphicViewPort ebx).GVPOffset]
mov eax,[(GraphicViewPort ebx).GVPXAdd]
add eax,[(GraphicViewPort ebx).GVPWidth]
add eax,[(GraphicViewPort ebx).GVPPitch]
mov ecx,eax
mul [y_pixel]
add esi,[x_pixel]
mov [source_area],ecx
add esi,eax
add ecx,[x_pixel ]
sub ecx,[x1_pixel ]
mov [scr_ajust_width ],ecx
mov ebx,[dest]
mov edi,[(GraphicViewPort ebx).GVPOffset]
mov eax,[(GraphicViewPort ebx).GVPXAdd]
add eax,[(GraphicViewPort ebx).GVPWidth]
add eax,[(GraphicViewPort ebx).GVPPitch]
mov ecx,eax
mul [ dest_y0 ]
add edi,[ dest_x0 ]
mov [ dest_area ],ecx
add edi,eax
mov eax,[ dest_x1 ]
sub eax,[ dest_x0 ]
jle ??real_out
sub ecx,eax
mov [ dest_ajust_width ],ecx
mov edx,[ dest_y1 ]
sub edx,[ dest_y0 ]
jle ??real_out
cmp esi,edi
jz ??real_out
jl ??backupward_blit
; ********************************************************************
; Forward bitblit
test [ trans ],1
jnz ??forward_Blit_trans
; the inner loop is so efficient that
; the optimal consept no longer apply because
; the optimal byte have to by a number greather than 9 bytes
cmp eax,10
jl ??forward_loop_bytes
??forward_loop_dword:
mov ecx,edi
mov ebx,eax
neg ecx
and ecx,3
sub ebx,ecx
rep movsb
mov ecx,ebx
shr ecx,2
rep movsd
mov ecx,ebx
and ecx,3
rep movsb
add esi,[ scr_ajust_width ]
add edi,[ dest_ajust_width ]
dec edx
jnz ??forward_loop_dword
ret
??forward_loop_bytes:
mov ecx,eax
rep movsb
add esi,[ scr_ajust_width ]
add edi,[ dest_ajust_width ]
dec edx
jnz ??forward_loop_bytes
ret
??forward_Blit_trans:
mov ecx,eax
and ecx,01fh
lea ecx,[ ecx + ecx * 4 ]
neg ecx
shr eax,5
lea ecx,[ ??transp_reference + ecx * 2 ]
mov [ y1_pixel ],ecx
??forward_loop_trans:
mov ecx,eax
jmp [ y1_pixel ]
??forward_trans_line:
REPT 32
local transp_pixel
mov bl,[ esi ]
test bl,bl
jz transp_pixel
mov [ edi ],bl
transp_pixel:
inc esi
inc edi
ENDM
??transp_reference:
dec ecx
jge ??forward_trans_line
add esi,[ scr_ajust_width ]
add edi,[ dest_ajust_width ]
dec edx
jnz ??forward_loop_trans
ret
; ************************************************************************
; backward bitblit
??backupward_blit:
mov ebx,[ source_area ]
dec edx
add esi,eax
imul ebx,edx
std
lea esi,[ esi + ebx - 1 ]
mov ebx,[ dest_area ]
add edi,eax
imul ebx,edx
lea edi,[ edi + ebx - 1]
test [ trans ],1
jnz ??backward_Blit_trans
cmp eax,15
jl ??backward_loop_bytes
??backward_loop_dword:
push edi
push esi
lea ecx,[edi+1]
mov ebx,eax
and ecx,3 ; Get non aligned bytes.
sub ebx,ecx ; remove that from the total size to be copied later.
rep movsb ; do the copy.
sub esi,3
mov ecx,ebx ; Get number of bytes left.
sub edi,3
shr ecx,2 ; Do 4 bytes at a time.
rep movsd ; do the dword copy.
mov ecx,ebx
add esi,3
add edi,3
and ecx,03h
rep movsb ; finnish the remaining bytes.
pop esi
pop edi
sub esi,[ source_area ]
sub edi,[ dest_area ]
dec edx
jge ??backward_loop_dword
cld
ret
??backward_loop_bytes:
push edi
mov ecx,eax ; remove that from the total size to be copied later.
push esi
rep movsb ; do the copy.
pop esi
pop edi
sub esi,[ source_area ]
sub edi,[ dest_area ]
dec edx
jge ??backward_loop_bytes
cld
ret
??backward_Blit_trans:
mov ecx,eax
and ecx,01fh
lea ecx,[ ecx + ecx * 4 ]
neg ecx
shr eax,5
lea ecx,[ ??back_transp_reference + ecx * 2 ]
mov [ y1_pixel ],ecx
??backward_loop_trans:
mov ecx,eax
push edi
push esi
jmp [ y1_pixel ]
??backward_trans_line:
REPT 32
local transp_pixel
mov bl,[ esi ]
test bl,bl
jz transp_pixel
mov [ edi ],bl
transp_pixel:
dec esi
dec edi
ENDM
??back_transp_reference:
dec ecx
jge ??backward_trans_line
pop esi
pop edi
sub esi,[ source_area ]
sub edi,[ dest_area ]
dec edx
jge ??backward_loop_trans
cld
ret
??real_out:
ret
ENDP Linear_Blit_To_Linear
END

View File

@@ -0,0 +1,131 @@
/*
** 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 A S S O C I A T E S **
***************************************************************************
* *
* Project Name : Westwood 32 Bit Library *
* *
* File Name : BUFFER.CPP *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : May 18, 1994 *
* *
* Last Update : June 1, 1994 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* BC::BufferClass -- The default (void) constructor for a buffer class *
* BC::~BufferClass -- The destructor for the buffer class *
* BC::BufferClass -- The standard constructor for a buffer class *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BUFFER_H
#include "buffer.h"
#endif
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* BC::BufferClass -- The standard constructor for a buffer class *
* *
* INPUT: VOID * buffer to which should be included in buffer class *
* LONG size of the buffer which we included *
* *
* OUTPUT: NONE *
* *
* WARNINGS: If the buffer passed to this function is equal to NULL, *
* the buffer will be allocated using new. *
* *
* HISTORY: *
* 06/01/1994 PWG : Created. *
*=========================================================================*/
BufferClass::BufferClass(VOID *buffer, LONG size)
{
Size = size; // find size of physical buffer
if (buffer) { // if buffer is specified
Buffer = (BYTE *)buffer; // point to it and mark
Allocated = FALSE; // it as user allocated
} else {
Buffer = new BYTE[Size]; // otherwise allocate it and
Allocated = TRUE; // mark it system alloced
}
}
/***************************************************************************
* BC::BufferClass -- constructor for BufferClass with size only *
* *
* INPUT: LONG the size of the buffer that needs to be allocated *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 06/01/1994 PWG : Created. *
*=========================================================================*/
BufferClass::BufferClass(LONG size)
{
Size = size;
Buffer = new BYTE[Size]; // otherwise allocate it and
Allocated = TRUE; // mark it system alloced
}
/***************************************************************************
* BC::BufferClass -- The default (void) constructor for a buffer class *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* NOTES: The primary function of this class is to be called by a *
* derived class which will fill in the values after the *
* fact. *
* *
* HISTORY: *
* 06/01/1994 PWG : Created. *
*=========================================================================*/
BufferClass::BufferClass(VOID)
{
Buffer = NULL;
Size = 0;
Allocated = FALSE;
}
/***************************************************************************
* BC::~BUFFERCLASS -- The destructor for the buffer class *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 06/01/1994 PWG : Created. *
*=========================================================================*/
BufferClass::~BufferClass(VOID)
{
if (Allocated) {
delete[] Buffer;
}
}

124
WIN32LIB/DRAWBUFF/BUFFER.H Normal file
View File

@@ -0,0 +1,124 @@
/*
** 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 A S S O C I A T E S **
***************************************************************************
* *
* Project Name : Westwood 32 Bit Library *
* *
* File Name : GBUFFER.H *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : May 26, 1994 *
* *
* Last Update : July 5, 1994 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* BC::Get_Size -- Returns the buffer size of the BufferClass instance *
* BC::Get_Buffer -- Returns pointer to buffer inherent to BufferClass *
* BC::BufferClass -- inline constructor for BufferClass with size only *
* BC::To_Page -- Copys a buffer class to a page with definable x, y, w, h*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BUFFER_H
#define BUFFER_H
/*=========================================================================*/
/* If we have not already loaded the standard library header, than we can */
/* load it. */
/*=========================================================================*/
#ifndef WWSTD_H
#include "wwstd.h"
#endif
class GraphicViewPortClass;
/*=========================================================================*/
/* BufferClass - A base class which holds buffer information including a */
/* pointer and the size of the buffer. */
/*=========================================================================*/
class BufferClass {
public:
/*===================================================================*/
/* Define the base constructor and destructors for the class */
/*===================================================================*/
BufferClass(void *ptr, long size);
BufferClass(long size);
BufferClass();
~BufferClass();
/*===================================================================*/
/* Define functions which work with the buffer class. */
/*===================================================================*/
long To_Page(GraphicViewPortClass &view);
long To_Page(int w, int h, GraphicViewPortClass &view);
long To_Page(int x, int y, int w, int h, GraphicViewPortClass &view);
/*===================================================================*/
/* define functions to get at the protected data members */
/*===================================================================*/
void *Get_Buffer(void);
long Get_Size(void);
private:
/*===================================================================*/
/* Define the operators we do not want to happen which are the copy */
/* and equal constructors. These are bad because the Allocated flag */
/* could be copied and the associated buffer freed. If this were to */
/* gappen it could cause weird general protection fault. */
/*===================================================================*/
BufferClass(BufferClass const &);
BufferClass &operator=(BufferClass const &);
protected:
void *Buffer;
long Size;
BOOL Allocated;
};
/***************************************************************************
* BC::GET_SIZE -- Returns the buffer size of the BufferClass instance *
* *
* INPUT: none *
* *
* OUTPUT: long the size of the buffer *
* *
* HISTORY: *
* 06/01/1994 PWG : Created. *
*=========================================================================*/
inline long BufferClass::Get_Size(void)
{
return(Size);
}
/***************************************************************************
* BC::GET_BUFFER -- Returns pointer to buffer inherent to BufferClass *
* *
* INPUT: none *
* *
* OUTPUT: void * to the inherent buffer. *
* *
* HISTORY: *
* 06/01/1994 PWG : Created. *
*=========================================================================*/
inline void *BufferClass::Get_Buffer(void)
{
return(Buffer);
}
#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/>.
*/
/***************************************************************************
** 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 : BUFFGLBL.CPP *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : January 10, 1995 *
* *
* Last Update : January 10, 1995 [PWG] *
* *
* This module holds the global fixup tables for the MCGA buffer class. *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "gbuffer.h"
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/*=========================================================================*/
/* Globals required by GraphicBufferClass for function pointers. These */
/* pointers will be set to the proper function when set mode is called. */
/*=========================================================================*/
BOOL (*GVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);
BOOL (*GVPC_Scale_To_VVPC)( void *, void *, int, int, int, int, int, int, int, int, BOOL, char *);
#ifdef not_any_more_it_doesnt
/*=========================================================================*/
/* Globals required by VideoBufferClass for function pointers. These */
/* pointers will be set to the proper function when set mode is called. */
/*=========================================================================*/
void (*VVPC_Clear_Func)(void *, unsigned char);
long (*VVPC_To_Buffer_Func)(void *,int x, int y, int w, int h, void *buff, long size);
void (*VVPC_Put_Pixel_Func)(void *,int x, int y, unsigned char color);
int (*VVPC_Get_Pixel_Func)(void *, int x, int y);
long (*VVPC_Buffer_To_Page)(int x, int y, int w, int h, void *Buffer, void *view);
BOOL (*VVPC_Blit_to_GVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);
BOOL (*VVPC_Blit_to_VVPC_Func)(void *, void *, int, int, int, int, int, int, BOOL);
BOOL (*VVPC_Scale_To_GVPC)( void *, void *, int, int, int, int, int, int, int, int, BOOL, char *);
BOOL (*VVPC_Scale_To_VVPC)( void *, void *, int, int, int, int, int, int, int, int, BOOL, char *);
LONG (*VVPC_Print_Func)( void *, const char *, int, int, int, int);
void (*VVPC_Draw_Stamp)(void *, void *, int, int, int, void *);
long (*VVPC_Size_Of_Region)(void *, int, int);
#endif //not_any_more_it_doesnt
/*=========================================================================*/
/* We need to keep a pointer to the logic page hanging around somewhere */
/*=========================================================================*/
GraphicViewPortClass *LogicPage;
BOOL IconCacheAllowed = TRUE;
/*
** Pointer to a function we will call if we detect loss of focus
*/
void (*Gbuffer_Focus_Loss_Function)(void) = NULL;

130
WIN32LIB/DRAWBUFF/CLEAR.ASM Normal file
View File

@@ -0,0 +1,130 @@
;
; 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 : Clear the Full Graphics Buffer *
;* *
;* File Name : CLEAR.ASM *
;* *
;* Programmer : Phil Gorrow *
;* *
;* Start Date : June 7, 1994 *
;* *
;* Last Update : August 23, 1994 [SKB] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* GVPC::Clear -- Clears a virtual viewport instance *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
;***************************************************************************
;* VVPC::CLEAR -- Clears a virtual viewport instance *
;* *
;* INPUT: UBYTE the color (optional) to clear the view port to *
;* *
;* OUTPUT: none *
;* *
;* NOTE: This function is optimized to handle viewport with no XAdd *
;* value. It also handles DWORD aligning the destination *
;* when speed can be gained by doing it. *
;* HISTORY: *
;* 06/07/1994 PWG : Created. *
;* 08/23/1994 SKB : Clear the direction flag to always go forward. *
;*=========================================================================*
PROC Buffer_Clear C near
USES eax,ebx,ecx,edx,esi,edi
ARG this_object:DWORD ; this is a member function
ARG color:BYTE ; what color should we clear to
cld ; always go forward
mov ebx,[this_object] ; get a pointer to viewport
mov edi,[(GraphicViewPort ebx).GVPOffset] ; get the correct offset
mov edx,[(GraphicViewPort ebx).GVPHeight] ; ecx = height of viewport
mov esi,[(GraphicViewPort ebx).GVPWidth] ; edx = width of viewport
push [dword (GraphicViewPort ebx).GVPPitch] ; extra pitch of direct draw surface
mov ebx,[(GraphicViewPort ebx).GVPXAdd] ; esi = add for each line
add ebx,[esp] ; Yes, I know its nasty but
add esp,4 ; it works!
;*===================================================================
; Convert the color byte to a DWORD for fast storing
;*===================================================================
mov al,[color] ; get color to clear to
mov ah,al ; extend across WORD
mov ecx,eax ; extend across DWORD in
shl eax,16 ; several steps
mov ax,cx
;*===================================================================
; Find out if we should bother to align the row.
;*===================================================================
cmp esi , OPTIMAL_BYTE_COPY ; is it worth aligning them?
jl ??byte_by_byte ; if not then skip
;*===================================================================
; Figure out the alignment offset if there is any
;*===================================================================
push ebx
??dword_aligned_loop:
mov ecx , edi
mov ebx , esi
neg ecx
and ecx , 3
sub ebx , ecx
rep stosb
mov ecx , ebx
shr ecx , 2
rep stosd
mov ecx , ebx
and ecx , 3
rep stosb
add edi , [ esp ]
dec edx ; decrement the height
jnz ??dword_aligned_loop ; if more to do than do it
pop eax
ret
;*===================================================================
; If not enough bytes to bother aligning copy each line across a byte
; at a time.
;*===================================================================
??byte_by_byte:
mov ecx,esi ; get total width in bytes
rep stosb ; store the width
add edi,ebx ; handle the xadd
dec edx ; decrement the height
jnz ??byte_by_byte ; if any left then next line
??exit:
ret
ENDP Buffer_Clear
END

View File

@@ -0,0 +1,67 @@
/*
** 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/>.
*/
#ifndef DRAWBUFF_H
#define DRAWBUFF_H
#ifndef WWSTD_H
#include "wwstd.h"
#endif
class GraphicViewPortClass;
class GraphicBufferClass;
/*=========================================================================*/
/* Define functions which have not under-gone name mangling */
/*=========================================================================*/
extern "C" {
/*======================================================================*/
/* Externs for all of the common functions between the video buffer */
/* class and the graphic buffer class. */
/*======================================================================*/
long __cdecl Buffer_Size_Of_Region(void *thisptr, int w, int h);
void __cdecl Buffer_Put_Pixel(void * thisptr, int x, int y, unsigned char color);
int __cdecl Buffer_Get_Pixel(void * thisptr, int x, int y);
void __cdecl Buffer_Clear(void *thisptr, unsigned char color);
long __cdecl Buffer_To_Buffer(void *thisptr, int x, int y, int w, int h, void *buff, long size);
long __cdecl Buffer_To_Page(int x, int y, int w, int h, void *Buffer, void *view);
BOOL __cdecl Linear_Blit_To_Linear( void *thisptr, void * dest, int x_pixel, int y_pixel, int dx_pixel,
int dy_pixel, int pixel_width, int pixel_height, BOOL trans);
BOOL __cdecl Linear_Scale_To_Linear( void *, void *, int, int, int, int, int, int, int, int, BOOL, char *);
LONG __cdecl Buffer_Print(void *thisptr, const char *str, int x, int y, int fcolor, int bcolor);
/*======================================================================*/
/* Externs for all of the graphic buffer class only functions */
/*======================================================================*/
VOID __cdecl Buffer_Draw_Line(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);
VOID __cdecl Buffer_Fill_Rect(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);
VOID __cdecl Buffer_Remap(void * thisptr, int sx, int sy, int width, int height, void *remap);
VOID __cdecl Buffer_Fill_Quad(void * thisptr, VOID *span_buff, int x0, int y0, int x1, int y1,
int x2, int y2, int x3, int y3, int color);
void __cdecl Buffer_Draw_Stamp(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);
void __cdecl Buffer_Draw_Stamp_Clip(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int ,int,int,int);
void * __cdecl Get_Font_Palette_Ptr ( void );
}
extern GraphicViewPortClass *LogicPage;
extern BOOL AllowHardwareBlitFills;
#endif

View File

@@ -0,0 +1,93 @@
;
; 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 : DRAWBUFF.INC *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : January 16, 1995 *
;* *
;* Last Update : January 16, 1995 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
; Externs from REGIONSZ.ASM module of the DRAWBUFF library
GLOBAL C Buffer_Size_Of_Region :NEAR
; Externs from GETPIX.ASM module of the DRAWBUFF library
GLOBAL C Buffer_Get_Pixel :NEAR
; Externs from PUTPIX.ASM module of the DRAWBUFF library
GLOBAL C Buffer_Put_Pixel :NEAR
; Externs from CLEAR.ASM module of the DRAWBUFF library
GLOBAL C Buffer_Clear :NEAR
; Externs from BITBLIT.ASM module of the DRAWBUFF library
GLOBAL C Linear_Blit_To_Linear :NEAR
; Externs from TOBUFF.ASM module of the DRAWBUFF library
GLOBAL C Buffer_To_Buffer :NEAR
; Externs from TOPAGE.ASM module of the DRAWBUFF library
GLOBAL C Buffer_To_Page :NEAR
; Externs from SCALE.ASM module of the DRAWBUFF library
GLOBAL C Linear_Scale_To_Linear :NEAR
; Externs from TXTPRNT.ASM module of the DRAWBUFF library
GLOBAL C Buffer_Print :NEAR
;*-------------------------------------------------------------------------*
;* Define Buffer only assembly GLOBALS *
;*-------------------------------------------------------------------------*
; Externs from DRAWLINE.ASM module of the DRAWBUFF library
GLOBAL C Buffer_Draw_Line:NEAR
; Externs from FILLQUAD.ASM module of the DRAWBUFF library
GLOBAL C Buffer_Fill_Quad :NEAR
; Externs from FILLRECT.ASM module of the DRAWBUFF library
GLOBAL C Buffer_Fill_Rect :NEAR
; Externs from REMAP.ASM module of the DRAWBUFF library
GLOBAL C Buffer_Remap :NEAR
; Externs from STAMP.ASM module of the DRAWBUFF library
GLOBAL C Buffer_Draw_Stamp :NEAR
GLOBAL C get_clip : NEAR
struc RECTANGLE
x0 dd ?
y0 dd ?
x1 dd ?
y1 dd ?
ends RECTANGLE

View File

@@ -0,0 +1,464 @@
;
; 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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : DRAWLINE.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : June 16, 1994 *
;* *
;* Last Update : August 30, 1994 [IML] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* VVC::Scale -- Scales a virtual viewport to another virtual viewport *
;* Normal_Draw -- jump loc for drawing scaled line of normal pixel *
;* __DRAW_LINE -- Assembly routine to draw a line *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
;***************************************************************************
;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport *
;* *
;* INPUT: WORD sx_pixel - the starting x pixel position *
;* WORD sy_pixel - the starting y pixel position *
;* WORD dx_pixel - the destination x pixel position *
;* WORD dy_pixel - the destination y pixel position *
;* WORD color - the color of the line to draw *
;* *
;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel *
;* with the graphic viewport it has been assigned to. *
;* *
;* HISTORY: *
;* 06/16/1994 PWG : Created. *
;* 08/30/1994 IML : Fixed clipping bug. *
;*=========================================================================*
PROC Buffer_Draw_Line C NEAR
USES eax,ebx,ecx,edx,esi,edi
;*==================================================================
;* Define the arguements that the function takes.
;*==================================================================
ARG this_object:DWORD ; associated graphic view port
ARG x1_pixel:DWORD ; the start x pixel position
ARG y1_pixel:DWORD ; the start y pixel position
ARG x2_pixel:DWORD ; the dest x pixel position
ARG y2_pixel:DWORD ; the dest y pixel position
ARG color:DWORD ; the color we are drawing
;*==================================================================
;* Define the local variables that we will use on the stack
;*==================================================================
LOCAL clip_min_x:DWORD
LOCAL clip_max_x:DWORD
LOCAL clip_min_y:DWORD
LOCAL clip_max_y:DWORD
LOCAL clip_var:DWORD
LOCAL accum:DWORD
LOCAL bpr:DWORD
;*==================================================================
;* Take care of find the clip minimum and maximums
;*==================================================================
mov ebx,[this_object]
xor eax,eax
mov [clip_min_x],eax
mov [clip_min_y],eax
mov eax,[(GraphicViewPort ebx).GVPWidth]
mov [clip_max_x],eax
add eax,[(GraphicViewPort ebx).GVPXAdd]
add eax,[(GraphicViewPort ebx).GVPPitch]
mov [bpr],eax
mov eax,[(GraphicViewPort ebx).GVPHeight]
mov [clip_max_y],eax
;*==================================================================
;* Adjust max pixels as they are tested inclusively.
;*==================================================================
dec [clip_max_x]
dec [clip_max_y]
;*==================================================================
;* Set the registers with the data for drawing the line
;*==================================================================
mov eax,[x1_pixel] ; eax = start x pixel position
mov ebx,[y1_pixel] ; ebx = start y pixel position
mov ecx,[x2_pixel] ; ecx = dest x pixel position
mov edx,[y2_pixel] ; edx = dest y pixel position
;*==================================================================
;* This is the section that "pushes" the line into bounds.
;* I have marked the section with PORTABLE start and end to signify
;* how much of this routine is 100% portable between graphics modes.
;* It was just as easy to have variables as it would be for constants
;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used
;* to clip the line (default is the screen)
;* PORTABLE start
;*==================================================================
cmp eax,[clip_min_x]
jl short ??clip_it
cmp eax,[clip_max_x]
jg short ??clip_it
cmp ebx,[clip_min_y]
jl short ??clip_it
cmp ebx,[clip_max_y]
jg short ??clip_it
cmp ecx,[clip_min_x]
jl short ??clip_it
cmp ecx,[clip_max_x]
jg short ??clip_it
cmp edx,[clip_min_y]
jl short ??clip_it
cmp edx,[clip_max_y]
jle short ??on_screen
;*==================================================================
;* Takes care off clipping the line.
;*==================================================================
??clip_it:
call NEAR PTR ??set_bits
xchg eax,ecx
xchg ebx,edx
mov edi,esi
call NEAR PTR ??set_bits
mov [clip_var],edi
or [clip_var],esi
jz short ??on_screen
test edi,esi
jne short ??off_screen
shl esi,2
call [DWORD PTR cs:??clip_tbl+esi]
jc ??clip_it
xchg eax,ecx
xchg ebx,edx
shl edi,2
call [DWORD PTR cs:??clip_tbl+edi]
jmp ??clip_it
??on_screen:
jmp ??draw_it
??off_screen:
jmp ??out
;*==================================================================
;* Jump table for clipping conditions
;*==================================================================
??clip_tbl DD ??nada,??a_up,??a_dwn,??nada
DD ??a_lft,??a_lft,??a_dwn,??nada
DD ??a_rgt,??a_up,??a_rgt,??nada
DD ??nada,??nada,??nada,??nada
??nada:
clc
retn
??a_up:
mov esi,[clip_min_y]
call NEAR PTR ??clip_vert
stc
retn
??a_dwn:
mov esi,[clip_max_y]
neg esi
neg ebx
neg edx
call NEAR PTR ??clip_vert
neg ebx
neg edx
stc
retn
;*==================================================================
;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)]
;*==================================================================
??clip_vert:
push edx
push eax
mov [clip_var],edx ; clip_var = yb
sub [clip_var],ebx ; clip_var = (yb-ya)
neg eax ; eax=-xa
add eax,ecx ; (ebx-xa)
mov edx,esi ; edx=miny
sub edx,ebx ; edx=(miny-ya)
imul edx
idiv [clip_var]
pop edx
add eax,edx
pop edx
mov ebx,esi
retn
??a_lft:
mov esi,[clip_min_x]
call NEAR PTR ??clip_horiz
stc
retn
??a_rgt:
mov esi,[clip_max_x]
neg eax
neg ecx
neg esi
call NEAR PTR ??clip_horiz
neg eax
neg ecx
stc
retn
;*==================================================================
;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)]
;*==================================================================
??clip_horiz:
push edx
mov [clip_var],ecx ; clip_var = xb
sub [clip_var],eax ; clip_var = (xb-xa)
sub edx,ebx ; edx = (yb-ya)
neg eax ; eax = -xa
add eax,esi ; eax = (minx-xa)
imul edx ; eax = (minx-xa)(yb-ya)
idiv [clip_var] ; eax = (minx-xa)(yb-ya)/(xb-xa)
add ebx,eax ; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)]
pop edx
mov eax,esi
retn
;*==================================================================
;* Sets the condition bits
;*==================================================================
??set_bits:
xor esi,esi
cmp ebx,[clip_min_y] ; if y >= top its not up
jge short ??a_not_up
or esi,1
??a_not_up:
cmp ebx,[clip_max_y] ; if y <= bottom its not down
jle short ??a_not_down
or esi,2
??a_not_down:
cmp eax,[clip_min_x] ; if x >= left its not left
jge short ??a_not_left
or esi,4
??a_not_left:
cmp eax,[clip_max_x] ; if x <= right its not right
jle short ??a_not_right
or esi,8
??a_not_right:
retn
;*==================================================================
;* Draw the line to the screen.
;* PORTABLE end
;*==================================================================
??draw_it:
sub edx,ebx ; see if line is being draw down
jnz short ??not_hline ; if not then its not a hline
jmp short ??hline ; do special case h line
??not_hline:
jg short ??down ; if so there is no need to rev it
neg edx ; negate for actual pixel length
xchg eax,ecx ; swap x's to rev line draw
sub ebx,edx ; get old edx
??down:
push edx
push eax
mov eax,[bpr]
mul ebx
mov ebx,eax
mov eax,[this_object]
add ebx,[(GraphicViewPort eax).GVPOffset]
pop eax
pop edx
mov esi,1 ; assume a right mover
sub ecx,eax ; see if line is right
jnz short ??not_vline ; see if its a vertical line
jmp ??vline
??not_vline:
jg short ??right ; if so, the difference = length
??left:
neg ecx ; else negate for actual pixel length
neg esi ; negate counter to move left
??right:
cmp ecx,edx ; is it a horiz or vert line
jge short ??horiz ; if ecx > edx then |x|>|y| or horiz
??vert:
xchg ecx,edx ; make ecx greater and edx lesser
mov edi,ecx ; set greater
mov [accum],ecx ; set accumulator to 1/2 greater
shr [accum],1
;*==================================================================
;* at this point ...
;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
;* esi=adder; accum=accumulator
;* in a vertical loop the adder is conditional and the inc constant
;*==================================================================
??vert_loop:
add ebx,eax
mov eax,[color]
??v_midloop:
mov [ebx],al
dec ecx
jl ??out
add ebx,[bpr]
sub [accum],edx ; sub the lesser
jge ??v_midloop ; any line could be new
add [accum],edi ; add greater for new accum
add ebx,esi ; next pixel over
jmp ??v_midloop
??horiz:
mov edi,ecx ; set greater
mov [accum],ecx ; set accumulator to 1/2 greater
shr [accum],1
;*==================================================================
;* at this point ...
;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
;* esi=adder; accum=accumulator
;* in a vertical loop the adder is conditional and the inc constant
;*==================================================================
??horiz_loop:
add ebx,eax
mov eax,[color]
??h_midloop:
mov [ebx],al
dec ecx ; dec counter
jl ??out ; end of line
add ebx,esi
sub [accum],edx ; sub the lesser
jge ??h_midloop
add [accum],edi ; add greater for new accum
add ebx,[bpr] ; goto next line
jmp ??h_midloop
;*==================================================================
;* Special case routine for horizontal line draws
;*==================================================================
??hline:
cmp eax,ecx ; make eax < ecx
jl short ??hl_ac
xchg eax,ecx
??hl_ac:
sub ecx,eax ; get len
inc ecx
push edx
push eax
mov eax,[bpr]
mul ebx
mov ebx,eax
mov eax,[this_object]
add ebx,[(GraphicViewPort eax).GVPOffset]
pop eax
pop edx
add ebx,eax
mov edi,ebx
cmp ecx,15
jg ??big_line
mov al,[byte color]
rep stosb ; write as many words as possible
jmp short ??out ; get outt
??big_line:
mov al,[byte color]
mov ah,al
mov ebx,eax
shl eax,16
mov ax,bx
test edi,3
jz ??aligned
mov [edi],al
inc edi
dec ecx
test edi,3
jz ??aligned
mov [edi],al
inc edi
dec ecx
test edi,3
jz ??aligned
mov [edi],al
inc edi
dec ecx
??aligned:
mov ebx,ecx
shr ecx,2
rep stosd
mov ecx,ebx
and ecx,3
rep stosb
jmp ??out
;*==================================================================
;* a special case routine for vertical line draws
;*==================================================================
??vline:
mov ecx,edx ; get length of line to draw
inc ecx
add ebx,eax
mov eax,[color]
??vl_loop:
mov [ebx],al ; store bit
add ebx,[bpr]
dec ecx
jnz ??vl_loop
??out:
ret
ENDP Buffer_Draw_Line
END

View File

@@ -0,0 +1,68 @@
/*
** 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 A S S O C I A T E S **
***************************************************************************
* *
* Project Name : Westwood 32 Bit Library *
* *
* File Name : DRAWRECT.C *
* *
* Programmer : Christopher Yates *
* *
* Last Update : August 20, 1993 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Draw_Rect -- Draws a rectangle to the LogicPage. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "gbuffer.h"
/***************************************************************************
* Draw_Rect -- Draws a rectangle to the LogicPage. *
* *
* This routine will draw a rectangle to the LogicPage. The rectangle *
* doesn't have to be aligned on the vertical or horizontal axis. In *
* fact, it doesn't even have to be a rectangle. The "square" can be *
* skewed. *
* *
* INPUT: x1_pixel, y1_pixel -- One corner. *
* *
* x2_pixel, y2_pixel -- The other corner. *
* *
* color -- The color to draw the lines. *
* *
* OUTPUT: none *
* *
* WARNINGS: None, but the rectangle will be clipped to the current *
* draw line clipping rectangle. *
* *
* HISTORY: *
* 08/20/1993 JLB : Created. *
*=========================================================================*/
VOID GraphicViewPortClass::Draw_Rect(int x1_pixel, int y1_pixel, int x2_pixel, int y2_pixel, unsigned char color)
{
Lock();
Draw_Line(x1_pixel, y1_pixel, x2_pixel, y1_pixel, color);
Draw_Line(x1_pixel, y2_pixel, x2_pixel, y2_pixel, color);
Draw_Line(x1_pixel, y1_pixel, x1_pixel, y2_pixel, color);
Draw_Line(x2_pixel, y1_pixel, x2_pixel, y2_pixel, color);
Unlock();
}

View File

@@ -0,0 +1,669 @@
;
; 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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : FILLQUAD.ASM *
;* *
;* Programmer : Ian M. Leslie *
;* *
;* Start Date : August 11, 1994 *
;* *
;* Last Update : August 30, 1994 [IML] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Fill_Quad -- Flood fills an arbitrary convex quadrilateral *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
SLOT_VACANT EQU 80008000h
NULL EQU 0h
CODESEG
;***************************************************************************
;* VVC::FILL_QUAD -- Flood fills an arbitrary convex quadrilateral *
;* *
;* INPUT: DWORD this_object - associated graphic viewport *
;* DWORD span_buff - pointer to span array *
;* DWORD x0_pixel - the zeroth x pixel position *
;* DWORD y0_pixel - the zeroth y pixel position *
;* DWORD x1_pixel - the first x pixel position *
;* DWORD y1_pixel - the first y pixel position *
;* DWORD x2_pixel - the second x pixel position *
;* DWORD y2_pixel - the second y pixel position *
;* DWORD x3_pixel - the third x pixel position *
;* DWORD y3_pixel - the third y pixel position *
;* DWORD color - the color of the quad to fill *
;* *
;* Bounds Checking: Compares quad points with the graphic viewport it *
;* has been assigned to. *
;* *
;* Rasterization Rules: FILL_QUAD is designed to be used within a quad *
;* mesh. There is no pixel overlapping or stitching *
;* effects at shared borders. FILL_QUAD is NOT *
;* recommended for isolated quads. * *
;* HISTORY: *
;* 08/11/1994 IML : Created. *
;* 08/26/1994 IML : Various optimizations. *
;* 08/30/1994 IML : Added rasterization rules for shared borders. *
;*=========================================================================*
PROC Buffer_Fill_Quad C NEAR
USES eax,ebx,ecx,edx,esi,edi
;*==================================================================
;* Define the arguments that the function takes.
;*==================================================================
ARG this_object:DWORD ; associated graphic viewport
ARG span_buff:DWORD ; pointer to span array
ARG x0_pixel:DWORD ; the zeroth x pixel position
ARG y0_pixel:DWORD ; the zeroth y pixel position
ARG x1_pixel:DWORD ; the first x pixel position
ARG y1_pixel:DWORD ; the first y pixel position
ARG x2_pixel:DWORD ; the second x pixel position
ARG y2_pixel:DWORD ; the second y pixel position
ARG x3_pixel:DWORD ; the third x pixel position
ARG y3_pixel:DWORD ; the third y pixel position
ARG color:DWORD ; the color of the quad
;*==================================================================
;* Define the local variables that we will use on the stack.
;*==================================================================
LOCAL clip_min_x:DWORD ; boundary of viewport
LOCAL clip_max_x:DWORD ;
LOCAL clip_min_y:DWORD ;
LOCAL clip_max_y:DWORD ;
LOCAL clip_var:DWORD
LOCAL left_clip_base:DWORD:2 ; storage for additional edges
LOCAL left_clip_index:DWORD ; generated by clipping
LOCAL right_clip_base:DWORD:2 ;
LOCAL right_clip_index:DWORD ;
LOCAL scanline_min:DWORD ; vertical extent of quad
LOCAL scanline_max:DWORD
LOCAL realignment:DWORD
LOCAL bpr:DWORD ; bytes per row of associated buffer
;*==================================================================
;* Extract essential GraphicViewPort info.
;*==================================================================
mov ebx,[this_object]
mov eax,[(GraphicViewPort ebx).GVPXPos]
mov [clip_min_x],eax
mov eax,[(GraphicViewPort ebx).GVPYPos]
mov [clip_min_y],eax
mov eax,[(GraphicViewPort ebx).GVPWidth]
mov [clip_max_x],eax
add eax,[(GraphicViewPort ebx).GVPXAdd]
add eax,[(GraphicViewPort ebx).GVPPitch]
mov [bpr],eax
mov eax,[(GraphicViewPort ebx).GVPHeight]
mov [clip_max_y],eax
;*==================================================================
;* Adjust top and right edges of viewport for rasterization rules.
;*==================================================================
dec [clip_max_y]
dec [clip_min_y]
;*==================================================================
;* Find the vertical extent of the quad BEFORE clipping.
;* y0_pixel = y0, y1_pixel = y1, y2_pixel = y2, y3_pixel = y3
;*==================================================================
mov eax,[y0_pixel]
cmp eax,[y1_pixel]
jle short ??y1_not_smaller
mov eax,[y1_pixel]
??y1_not_smaller:
cmp eax,[y2_pixel]
jle short ??y2_not_smaller
mov eax,[y2_pixel]
??y2_not_smaller:
cmp eax,[y3_pixel]
jle short ??y3_not_smaller
mov eax,[y3_pixel]
??y3_not_smaller:
cmp eax,[clip_min_y]
jge short ??no_clamp_min_min
mov eax,[clip_min_y]
??no_clamp_min_min:
cmp eax,[clip_max_y]
jle short ??no_clamp_max_min
mov eax,[clip_max_y]
; scanline_min = MIN (y0, y1, y2, y3)
??no_clamp_max_min: ; scanline_min = MAX (scanline_min, clip_min_y)
mov [scanline_min],eax ; scanline_min = MIN (scanline_min, clip_max_y)
mov eax,[y0_pixel]
cmp eax,[y1_pixel]
jge short ??y1_not_greater
mov eax,[y1_pixel]
??y1_not_greater:
cmp eax,[y2_pixel]
jge short ??y2_not_greater
mov eax,[y2_pixel]
??y2_not_greater:
cmp eax,[y3_pixel]
jge short ??y3_not_greater
mov eax,[y3_pixel]
??y3_not_greater:
cmp eax,[clip_min_y]
jge short ??no_clamp_min_max
mov eax,[clip_min_y]
??no_clamp_min_max:
cmp eax,[clip_max_y]
jle short ??no_clamp_max_max
mov eax,[clip_max_y]
; scanline_max = MAX (y0, y1, y2, y3)
??no_clamp_max_max: ; scanline_max = MAX (scanline_max, clip_min_y)
mov [scanline_max],eax ; scanline_max = MIN (scanline_max, clip_max_y)
;*==================================================================
;* Initialize memory for spans.
;*==================================================================
sub eax,[scanline_min]
je ??abort_fill_quad ; don't render quads with zero height
mov ebx,eax
mov eax,[span_buff] ; check span_buff for NULL ptr
cmp eax,NULL
je ??abort_fill_quad
sal ebx,2
??span_initialize_loop:
mov [DWORD PTR eax + ebx],SLOT_VACANT
sub ebx,4
jl short ??exit_span_initialize
mov [DWORD PTR eax + ebx],SLOT_VACANT
sub ebx,4
jl short ??exit_span_initialize
mov [DWORD PTR eax + ebx],SLOT_VACANT
sub ebx,4
jl short ??exit_span_initialize
mov [DWORD PTR eax + ebx],SLOT_VACANT
sub ebx,4
jge short ??span_initialize_loop
;*==================================================================
;* Clip and scan convert the four edges defining the quad.
;*==================================================================
??exit_span_initialize:
mov [left_clip_index],0
mov [right_clip_index],0
mov eax,[x0_pixel]
mov ebx,[y0_pixel]
mov ecx,[x1_pixel]
mov edx,[y1_pixel]
call NEAR PTR ??clip_and_scan_convert
mov eax,[x1_pixel]
mov ebx,[y1_pixel]
mov ecx,[x2_pixel]
mov edx,[y2_pixel]
call NEAR PTR ??clip_and_scan_convert
mov eax,[x2_pixel]
mov ebx,[y2_pixel]
mov ecx,[x3_pixel]
mov edx,[y3_pixel]
call NEAR PTR ??clip_and_scan_convert
mov eax,[x3_pixel]
mov ebx,[y3_pixel]
mov ecx,[x0_pixel]
mov edx,[y0_pixel]
call NEAR PTR ??clip_and_scan_convert
;*==================================================================
;* Scan convert up to 2 additional left and right vertical edges
;* generated by the clipping process.
;*==================================================================
cmp [left_clip_index],0
je short ??no_left_edge
mov eax,[clip_min_x]
mov ebx,[left_clip_base]
mov ecx,eax
mov edx,[left_clip_base + 4]
call NEAR PTR ??scan_convert
??no_left_edge:
cmp [right_clip_index],0
je short ??no_right_edge
mov eax,[clip_max_x]
mov ebx,[right_clip_base]
mov ecx,eax
mov edx,[right_clip_base + 4]
call NEAR PTR ??scan_convert
;*==================================================================
;* Fill the quad with specified color. Use DWORD copies where
;* appropriate.
;*==================================================================
??no_right_edge:
mov eax,[this_object]
mov edi,[(GraphicViewPort eax).GVPOffset]
mov eax,[scanline_min] ; eax = scanline_min
mov ebx,[scanline_max]
sub ebx,[scanline_min] ; ebx = span count
mov esi,[span_buff] ; esi = address of top span
mul [bpr]
add edi,eax ; edi = address of top scanline
; containing quad
mov al,[BYTE PTR color] ; extend pixel color into eax ready
mov ah,al ; for DWORD copies
mov edx,eax
shl eax,16
mov ax,dx
cld ; only fill forwards
jmp ??skip_span ; rasterization rule: don't
; render topmost span
??quad_fill_loop:
cmp [DWORD PTR esi],SLOT_VACANT ; test for unused spans due to clipping
je ??skip_span
xor ecx,ecx
xor edx,edx
mov cx,[WORD PTR esi]
mov dx,[WORD PTR esi + 2]
sub ecx,edx
push edi
jns short ??not_negative_count
add edi,ecx
neg ecx ; ecx = span width
??not_negative_count:
add edi,edx ; edi = address of start of span
cmp ecx,OPTIMAL_BYTE_COPY ; does span width justify DWORD copies?
jl short ??byte_copy
mov edx,ecx
mov ecx,edi
and ecx,3 ; if (ecx == 0) edi is already
jz short ??dword_copy_no_alignment ; DWORD aligned
xor ecx,3
inc ecx ; ecx = number of pixels before alignment
sub edx,ecx
rep stosb
??dword_copy_no_alignment:
mov ecx,edx ; ecx = remaining pixels on span
shr ecx,2 ; copy (ecx / 4) DWORDS
rep stosd
mov ecx,edx
and ecx,3 ; ecx = remaining pixels on span
??byte_copy:
rep stosb ; byte copy remaining pixels on span
pop edi
??skip_span:
add edi,[bpr] ; edi = address of start of next scanline
add esi,4 ; esi = address of next span
dec ebx
jge short ??quad_fill_loop ; is span count >= 0?
??abort_fill_quad:
ret
;*==================================================================
;* This is the section that "pushes" the edge into bounds.
;* I have marked the section with PORTABLE start and end to signify
;* how much of this routine is 100% portable between graphics modes.
;* It was just as easy to have variables as it would be for constants
;* so the global vars clip_min_x, clip_min_y, clip_max_x, clip_max_y
;* are used to clip the edge (default is the screen).
;* PORTABLE start.
;*==================================================================
;*==================================================================
;* Clip an edge against the viewport.
;*==================================================================
??clip_and_scan_convert:
call NEAR PTR ??set_left_right_bits
xchg eax,ecx
xchg ebx,edx
mov edi,esi
call NEAR PTR ??set_left_right_bits
mov [clip_var],edi
or [clip_var],esi
jz ??clip_up_down ; trivial acceptance?
test edi,esi
jne ??exit ; trivial rejection?
shl esi,2
call [DWORD PTR cs:??clip_tbl+esi]
xchg eax,ecx
xchg ebx,edx
shl edi,2
call [DWORD PTR cs:??clip_tbl+edi]
??clip_up_down:
call NEAR PTR ??set_up_down_bits
xchg eax,ecx
xchg ebx,edx
mov edi,esi
call NEAR PTR ??set_up_down_bits
mov [clip_var],edi
or [clip_var],esi
jz ??scan_convert ; trivial acceptance?
test edi,esi
jne ??exit ; trivial rejection?
shl esi,2
call [DWORD PTR cs:??clip_tbl+esi]
xchg eax,ecx
xchg ebx,edx
shl edi,2
call [DWORD PTR cs:??clip_tbl+edi]
jmp ??scan_convert
;*==================================================================
;* Subroutine table for clipping conditions.
;*==================================================================
??clip_tbl DD ??nada,??a_lft,??a_rgt,??nada
DD ??a_up,??nada,??nada,??nada
DD ??a_dwn
;*==================================================================
;* Subroutines for clipping conditions.
;*==================================================================
??nada:
retn
??a_up:
mov esi,[clip_min_y]
call NEAR PTR ??clip_vert
retn
??a_dwn:
mov esi,[clip_max_y]
call NEAR PTR ??clip_vert
retn
??a_lft:
mov esi,[clip_min_x]
call NEAR PTR ??clip_horiz
push ebx
mov esi,[left_clip_index]
cmp ebx,[clip_min_y]
jge ??no_left_min_clip
mov ebx,[clip_min_y]
??no_left_min_clip:
cmp ebx,[clip_max_y]
jle ??no_left_max_clip
mov ebx,[clip_max_y]
??no_left_max_clip:
mov [left_clip_base + esi],ebx ; a left edge will be generated
mov [left_clip_index],4 ; store off yb
pop ebx
retn
??a_rgt:
mov esi,[clip_max_x]
call NEAR PTR ??clip_horiz
push ebx
mov esi,[right_clip_index]
cmp ebx,[clip_min_y]
jge ??no_right_min_clip
mov ebx,[clip_min_y]
??no_right_min_clip:
cmp ebx,[clip_max_y]
jle ??no_right_max_clip
mov ebx,[clip_max_y]
??no_right_max_clip:
mov [right_clip_base + esi],ebx ; a right edge will be generated
mov [right_clip_index],4 ; store off yb
pop ebx
retn
;*==================================================================
;* Clip a line against a horizontal edge at clip_y.
;* (eax,ebx) = (xa,ya), (ecx,edx) = (xb,yb)
;* xa' = xa+[(clip_y-ya)(xb-xa)/(yb-ya)]
;* ya' = clip_y
;*==================================================================
??clip_vert:
push edx
push eax
mov [clip_var],edx ; clip_var = yb
sub [clip_var],ebx ; clip_var = (yb-ya)
neg eax ; eax = -xa
add eax,ecx ; eax = (xb-xa)
mov edx,esi ; edx = clip_y
sub edx,ebx ; edx = (clip_y-ya)
imul edx ; eax = (clip_y-ya)(xb-xa)
idiv [clip_var] ; eax = (clip_y-ya)(xb-xa)/(yb-ya)
pop edx
add eax,edx ; eax = xa+[(clip_y-ya)(xb-xa)/(yb-ya)]
pop edx
mov ebx,esi ; ebx = clip_y
retn
;*==================================================================
;* Clip a line against a vertical edge at clip_x.
;* (eax,ebxx) = (xa,ya), (ecx,edxx) = (xb,yb)
;* ya' = ya+[(clip_x-xa)(yb-ya)/(xb-xa)]
;* xa' = clip_x
;*==================================================================
??clip_horiz:
push edx
mov [clip_var],ecx ; clip_var = xb
sub [clip_var],eax ; clip_var = (xb-xa)
sub edx,ebx ; edx = (yb-ya)
neg eax ; eax = -xa
add eax,esi ; eax = (clip_x-xa)
imul edx ; eax = (clip_x-xa)(yb-ya)
idiv [clip_var] ; eax = (clip_x-xa)(yb-ya)/(xb-xa)
add ebx,eax ; ebx = ya+[(clip_x-xa)(yb-ya)/(xb-xa)]
pop edx
mov eax,esi ; eax = clip_x
retn
;*==================================================================
;* Set the condition bits for the subroutine table.
;*==================================================================
??set_left_right_bits:
xor esi,esi
cmp eax,[clip_min_x] ; if x >= left its not left
jge short ??a_not_left
or esi,1
??a_not_left:
cmp eax,[clip_max_x] ; if x <= right its not right
jle short ??a_not_right
or esi,2
??a_not_right:
retn
??set_up_down_bits:
xor esi,esi
cmp ebx,[clip_min_y] ; if y >= top its not up
jge short ??a_not_up
or esi,4
??a_not_up:
cmp ebx,[clip_max_y] ; if y <= bottom its not down
jle short ??a_not_down
or esi,8
??a_not_down:
retn
;*==================================================================
;* PORTABLE end.
;*==================================================================
;*==================================================================
;* Scan convert an edge.
;* (eax,ebx) = (xa,ya), (ecx,edx) = (xb,yb)
;*==================================================================
??scan_convert:
cmp ebx,edx
je ??exit ; if (ya == yb) don't scan convert
jl short ??no_swap ; if (ya < yb) swap vertices
xchg eax,ecx
xchg ebx,edx
??no_swap:
sub edx,ebx ; edx = (yb - ya)
sub ebx,[scanline_min]
sal ebx,2
add ebx,[span_buff] ; ebx = span_buff + 4(ya - clip_min_y)
sub ecx,eax ; ecx = (xb - xa)
je ??v_scan ; if the edge is vertical use a
; special case routine
push eax
mov eax,ecx ; eax = (xb - xa)
mov ecx,edx ; ecx = (yb - ya)
sal edx,1
mov [realignment],edx ; realignment = 2(yb - ya)
cwd
idiv cx
cwde
movsx edx,dx
mov edi,eax ; edi = (xb - xa) / (yb - ya)
mov esi,edx
mov edx,ecx
pop eax ; eax = xa
neg edx ; edx = -(yb - ya)
sal esi,1 ; esi = 2[(xb - xa) % (yb - ya)]
jns short ??r_scan ; scan to the left or right?
neg esi
;*==================================================================
;* Edge scan conversion DDA moving down and to the left.
;* eax = xpos, ebx = span to reference
;*==================================================================
cmp ebx,[span_buff]
jg ??l_scan_convert
??l_scan_convert_loop:
cmp [DWORD PTR ebx],SLOT_VACANT ; if the left slot of span is
jne short ??l_next_slot ; vacant fill it with xpos
mov [ebx],ax
??l_next_slot:
mov [ebx + 2],ax ; otherwise fill the right slot
; with xpos
??l_scan_convert:
dec ecx
jl short ??exit
add ebx,4
add eax,edi
add edx,esi
jle short ??l_scan_convert_loop
dec eax
sub edx,[realignment]
jmp ??l_scan_convert_loop
;*==================================================================
;* Edge scan conversion DDA moving down and to the right.
;* eax = xpos, ebx = span to reference
;*==================================================================
??r_scan:
cmp ebx,[span_buff]
jg ??r_scan_convert
??r_scan_convert_loop:
cmp [DWORD PTR ebx],SLOT_VACANT ; if the left slot of span is
jne short ??r_next_slot ; vacant fill it with xpos
mov [ebx],ax
??r_next_slot:
mov [ebx + 2],ax ; otherwise fill the right slot
; with xpos
??r_scan_convert:
dec ecx
jl short ??exit
add ebx,4
add eax,edi
add edx,esi
jle short ??r_scan_convert_loop
inc eax
sub edx,[realignment]
jmp ??r_scan_convert_loop
;*==================================================================
;* Scan convert a vertical edge.
;* eax = xpos, ebx = span to reference
;*==================================================================
??v_scan:
cmp ebx,[span_buff]
jg ??v_scan_convert
??v_scan_convert_loop:
cmp [DWORD PTR ebx],SLOT_VACANT ; if the left slot of span is
jne short ??v_next_slot ; vacant fill it with xpos
mov [ebx],ax
??v_next_slot:
mov [ebx + 2],ax ; otherwise fill the right slot
; with xpos
??v_scan_convert:
add ebx,4
dec edx
jge ??v_scan_convert_loop
??exit:
retn
ENDP Buffer_Fill_Quad
END

View File

@@ -0,0 +1,275 @@
;
; 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 : GraphicViewPortClass *
;* *
;* File Name : CLEAR.ASM *
;* *
;* Programmer : Phil Gorrow *
;* *
;* Start Date : June 7, 1994 *
;* *
;* Last Update : June 7, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* GVPC::Fill_Rect -- draws a filled rectangle to a graphics buffer *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
;***************************************************************************
;* GVPC::FILL_RECT -- Fills a rectangular region of a graphic view port *
;* *
;* INPUT: WORD the left hand x pixel position of region *
;* WORD the upper x pixel position of region *
;* WORD the right hand x pixel position of region *
;* WORD the lower x pixel position of region *
;* UBYTE the color (optional) to clear the view port to *
;* *
;* OUTPUT: none *
;* *
;* NOTE: This function is optimized to handle viewport with no XAdd *
;* value. It also handles DWORD aligning the destination *
;* when speed can be gained by doing it. *
;* HISTORY: *
;* 06/07/1994 PWG : Created. *
;*=========================================================================*
PROC Buffer_Fill_Rect C near
USES eax,ebx,ecx,edx,esi,edi,ebp
;*===================================================================
;* define the arguements that our function takes.
;*===================================================================
ARG this_object:DWORD ; this is a member function
ARG x1_pixel:WORD
ARG y1_pixel:WORD
ARG x2_pixel:WORD
ARG y2_pixel:WORD
ARG color:BYTE ; what color should we clear to
;*===================================================================
; Define some locals so that we can handle things quickly
;*===================================================================
LOCAL VPwidth:DWORD ; the width of the viewport
LOCAL VPheight:DWORD ; the height of the viewport
LOCAL VPxadd:DWORD ; the additional x offset of viewport
LOCAL VPbpr:DWORD ; the number of bytes per row of viewport
;*===================================================================
;* save off the viewport characteristics on the stack
;*===================================================================
mov ebx,[this_object] ; get a pointer to viewport
mov eax,[(GraphicViewPort ebx).GVPWidth] ; get width from viewport
mov ecx,[(GraphicViewPort ebx).GVPHeight] ; get height from viewport
mov edx,[(GraphicViewPort ebx).GVPXAdd] ; get xadd from viewport
add edx,[(GraphicViewPort ebx).GVPPitch] ; extra pitch of direct draw surface
mov [VPwidth],eax ; store the width of locally
mov [VPheight],ecx
mov [VPxadd],edx
add eax,edx
mov [VPbpr],eax
;*===================================================================
;* move the important parameters into local registers
;*===================================================================
movsx eax,[x1_pixel]
movsx ebx,[y1_pixel]
movsx ecx,[x2_pixel]
movsx edx,[y2_pixel]
;*===================================================================
;* Convert the x2 and y2 pixel to a width and height
;*===================================================================
cmp eax,ecx
jl ??no_swap_x
xchg eax,ecx
??no_swap_x:
sub ecx,eax
cmp ebx,edx
jl ??no_swap_y
xchg ebx,edx
??no_swap_y:
sub edx,ebx
inc ecx
inc edx
;*===================================================================
;* Bounds check source X.
;*===================================================================
cmp eax, [VPwidth] ; compare with the max
jge ??out ; starts off screen, then later
jb short ??sx_done ; if it's not negative, it's ok
;------ Clip source X to left edge of screen.
add ecx, eax ; Reduce width (add in negative src X).
xor eax, eax ; Clip to left of screen.
??sx_done:
;*===================================================================
;* Bounds check source Y.
;*===================================================================
cmp ebx, [VPheight] ; compare with the max
jge ??out ; starts off screen, then later
jb short ??sy_done ; if it's not negative, it's ok
;------ Clip source Y to top edge of screen.
add edx, ebx ; Reduce height (add in negative src Y).
xor ebx, ebx ; Clip to top of screen.
??sy_done:
;*===================================================================
;* Bounds check width versus width of source and dest view ports
;*===================================================================
push ebx ; save off ebx for later use
mov ebx,[VPwidth] ; get the source width
sub ebx, eax ; Maximum allowed pixel width (given coordinates).
sub ebx, ecx ; Pixel width undershoot.
jns short ??width_ok ; if not signed no adjustment necessary
add ecx, ebx ; Reduce width to screen limits.
??width_ok:
pop ebx ; restore ebx to old value
;*===================================================================
;* Bounds check height versus height of source view port
;*===================================================================
push eax ; save of eax for later use
mov eax, [VPheight] ; get the source height
sub eax, ebx ; Maximum allowed pixel height (given coordinates).
sub eax, edx ; Pixel height undershoot.
jns short ??height_ok ; if not signed no adjustment necessary
add edx, eax ; Reduce height to screen limits.
??height_ok:
pop eax ; restore eax to old value
;*===================================================================
;* Perform the last minute checks on the width and height
;*===================================================================
or ecx,ecx
jz ??out
or edx,edx
jz ??out
cmp ecx,[VPwidth]
ja ??out
cmp edx,[VPheight]
ja ??out
;*===================================================================
;* Get the offset into the virtual viewport.
;*===================================================================
xchg edi,eax ; save off the contents of eax
xchg esi,edx ; and edx for size test
mov eax,ebx ; move the y pixel into eax
mul [VPbpr] ; multiply by bytes per row
add edi,eax ; add the result into the x position
mov ebx,[this_object]
add edi,[(GraphicViewPort ebx).GVPOffset]
mov edx,esi ; restore edx back to real value
mov eax,ecx ; store total width in ecx
sub eax,[VPwidth] ; modify xadd value to include clipped
sub [VPxadd],eax ; width bytes (subtract a negative number)
;*===================================================================
; Convert the color byte to a DWORD for fast storing
;*===================================================================
mov al,[color] ; get color to clear to
mov ah,al ; extend across WORD
mov ebx,eax ; extend across DWORD in
shl eax,16 ; several steps
mov ax,bx
;*===================================================================
; If there is no row offset then adjust the width to be the size of
; the entire viewport and adjust the height to be 1
;*===================================================================
mov esi,[VPxadd]
or esi,esi ; set the flags for esi
jnz ??row_by_row_aligned ; and act on them
xchg eax,ecx ; switch bit pattern and width
mul edx ; multiply by edx to get size
xchg eax,ecx ; switch size and bit pattern
mov edx,1 ; only 1 line off view port size to do
;*===================================================================
; Find out if we should bother to align the row.
;*===================================================================
??row_by_row_aligned:
mov ebp,ecx ; width saved in ebp
cmp ecx,OPTIMAL_BYTE_COPY ; is it worth aligning them?
jl ??row_by_row ; if not then skip
;*===================================================================
; Figure out the alignment offset if there is any
;*===================================================================
mov ebx,edi ; get output position
and ebx,3 ; is there a remainder?
jz ??aligned_loop ; if not we are aligned
xor ebx,3 ; find number of align bytes
inc ebx ; this number is off by one
sub ebp,ebx ; subtract from width
;*===================================================================
; Now that we have the alignment offset copy each row
;*===================================================================
??aligned_loop:
mov ecx,ebx ; get number of bytes to align
rep stosb ; and move them over
mov ecx,ebp ; get number of aligned bytes
shr ecx,2 ; convert to DWORDS
rep stosd ; and move them over
mov ecx,ebp ; get number of aligned bytes
and ecx,3 ; find the remainder
rep stosb ; and move it over
add edi,esi ; fix the line offset
dec edx ; decrement the height
jnz ??aligned_loop ; if more to do than do it
jmp ??exit ; we are all done
;*===================================================================
; If not enough bytes to bother aligning copy each line across a byte
; at a time.
;*===================================================================
??row_by_row:
mov ecx,ebp ; get total width in bytes
rep stosb ; store the width
add edi,esi ; handle the xadd
dec edx ; decrement the height
jnz ??row_by_row ; if any left then next line
??out:
??exit:
ret
ENDP Buffer_Fill_Rect
END

View File

@@ -0,0 +1,106 @@
;
; 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 : GraphicViewPortClass *
;* *
;* File Name : GETPIXEL.ASM *
;* *
;* Programmer : Phil Gorrow *
;* *
;* Start Date : June 7, 1994 *
;* *
;* Last Update : June 7, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* VVPC::Buffer_Get_Pixel -- get the colour of a pixel at given coords *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
;***************************************************************************
;* VVPC::GET_PIXEL -- Gets a pixel from the current view port *
;* *
;* INPUT: WORD the x pixel on the screen. *
;* WORD the y pixel on the screen. *
;* *
;* OUTPUT: UBYTE the pixel at the specified location *
;* *
;* WARNING: If pixel is to be placed outside of the viewport then *
;* this routine will abort. *
;* *
;* HISTORY: *
;* 06/07/1994 PWG : Created. *
;*=========================================================================*
PROC Buffer_Get_Pixel C near
USES ebx,ecx,edx,edi
ARG this_object:DWORD ; this is a member function
ARG x_pixel:DWORD ; x position of pixel to set
ARG y_pixel:DWORD ; y position of pixel to set
;*===================================================================
; Get the viewport information and put bytes per row in ecx
;*===================================================================
mov ebx,[this_object] ; get a pointer to viewport
xor eax,eax
mov edi,[(GraphicViewPort ebx).GVPOffset] ; get the correct offset
mov ecx,[(GraphicViewPort ebx).GVPHeight] ; edx = height of viewport
mov edx,[(GraphicViewPort ebx).GVPWidth] ; ecx = width of viewport
;*===================================================================
; Verify that the X pixel offset if legal
;*===================================================================
mov eax,[x_pixel] ; find the x position
cmp eax,edx ; is it out of bounds
jae short ??exit ; if so then get out
add edi,eax ; otherwise add in offset
;*===================================================================
; Verify that the Y pixel offset if legal
;*===================================================================
mov eax,[y_pixel] ; get the y position
cmp eax,ecx ; is it out of bounds
jae ??exit ; if so then get out
add edx,[(GraphicViewPort ebx).GVPXAdd] ; otherwise find bytes per row
add edx,[(GraphicViewPort ebx).GVPPitch] ; otherwise find bytes per row
mul edx ; offset = bytes per row * y
add edi,eax ; add it into the offset
;*===================================================================
; Write the pixel to the screen
;*===================================================================
xor eax,eax ; clear the word
mov al,[edi] ; read in the pixel
??exit:
ret
ENDP Buffer_Get_Pixel
END

View File

@@ -0,0 +1,711 @@
/*
** 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 A S S O C I A T E S **
***************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : GBUFFER.CPP *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : May 3, 1994 *
* *
* Last Update : October 9, 1995 [] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* VVPC::VirtualViewPort -- Default constructor for a virtual viewport *
* VVPC:~VirtualViewPortClass -- Destructor for a virtual viewport *
* VVPC::Clear -- Clears a graphic page to correct color *
* VBC::VideoBufferClass -- Lowlevel constructor for video buffer class *
* GVPC::Change -- Changes position and size of a Graphic View Port *
* VVPC::Change -- Changes position and size of a Video View Port *
* Set_Logic_Page -- Sets LogicPage to new buffer *
* GBC::DD_Init -- Inits a direct draw surface for a GBC *
* GBC::Init -- Core function responsible for initing a GBC *
* GBC::Lock -- Locks a Direct Draw Surface *
* GBC::Unlock -- Unlocks a direct draw surface *
* GBC::GraphicBufferClass -- Default constructor (requires explicit init)*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef GBUFFER_H
#include "gbuffer.h"
#include "misc.h"
#endif
#pragma inline
int TotalLocks;
BOOL AllowHardwareBlitFills = TRUE;
//int CacheAllowed;
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* GVPC::GRAPHICVIEWPORTCLASS -- Constructor for basic view port class *
* m *
* INPUT: GraphicBufferClass * gbuffer - buffer to attach to *
* int x - x offset into buffer *
* int y - y offset into buffer *
* int w - view port width in pixels *
* int h - view port height in pixels *
* *
* OUTPUT: Constructors may not have a return value *
* *
* HISTORY: *
* 05/09/1994 PWG : Created. *
*=========================================================================*/
GraphicViewPortClass::GraphicViewPortClass(GraphicBufferClass *gbuffer, int x, int y, int w, int h) :
LockCount(0),
GraphicBuff(NULL)
{
Attach(gbuffer, x, y, w, h);
}
/***************************************************************************
* GVPC::GRAPHICVIEWPORTCLASS -- Default constructor for view port class *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 05/09/1994 PWG : Created. *
*=========================================================================*/
GraphicViewPortClass::GraphicViewPortClass(void)
{
}
/***************************************************************************
* GVPC::~GRAPHICVIEWPORTCLASS -- Destructor for GraphicViewPortClass *
* *
* INPUT: none *
* *
* OUTPUT: A destructor may not return a value. *
* *
* HISTORY: *
* 05/10/1994 PWG : Created. *
*=========================================================================*/
GraphicViewPortClass::~GraphicViewPortClass(void)
{
Offset = 0;
Width = 0; // Record width of Buffer
Height = 0; // Record height of Buffer
XAdd = 0; // Record XAdd of Buffer
XPos = 0; // Record XPos of Buffer
YPos = 0; // Record YPos of Buffer
Pitch = 0; // Record width of Buffer
IsDirectDraw = FALSE;
LockCount = 0;
GraphicBuff = NULL;
}
/***************************************************************************
* GVPC::ATTACH -- Attaches a viewport to a buffer class *
* *
* INPUT: GraphicBufferClass *g_buff - pointer to gbuff to attach to *
* int x - x position to attach to *
* int y - y position to attach to *
* int w - width of the view port *
* int h - height of the view port *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 05/10/1994 PWG : Created. *
*=========================================================================*/
void GraphicViewPortClass::Attach(GraphicBufferClass *gbuffer, int x, int y, int w, int h)
{
/*======================================================================*/
/* Can not attach a Graphic View Port if it is actually the physical */
/* representation of a Graphic Buffer. */
/*======================================================================*/
if (this == Get_Graphic_Buffer()) {
return;
}
/*======================================================================*/
/* Verify that the x and y coordinates are valid and placed within the */
/* physical buffer. */
/*======================================================================*/
if (x < 0) // you cannot place view port off
x = 0; // the left edge of physical buf
if (x >= gbuffer->Get_Width()) // you cannot place left edge off
x = gbuffer->Get_Width() - 1; // the right edge of physical buf
if (y < 0) // you cannot place view port off
y = 0; // the top edge of physical buf
if (y >= gbuffer->Get_Height()) // you cannot place view port off
y = gbuffer->Get_Height() - 1; // bottom edge of physical buf
/*======================================================================*/
/* Adjust the width and height of necessary */
/*======================================================================*/
if (x + w > gbuffer->Get_Width()) // if the x plus width is larger
w = gbuffer->Get_Width() - x; // than physical, fix width
if (y + h > gbuffer->Get_Height()) // if the y plus height is larger
h = gbuffer->Get_Height() - y; // than physical, fix height
/*======================================================================*/
/* Get a pointer to the top left edge of the buffer. */
/*======================================================================*/
Offset = gbuffer->Get_Offset() + ((gbuffer->Get_Width()+gbuffer->Get_Pitch()) * y) + x;
/*======================================================================*/
/* Copy over all of the variables that we need to store. */
/*======================================================================*/
XPos = x;
YPos = y;
XAdd = gbuffer->Get_Width() - w;
Width = w;
Height = h;
Pitch = gbuffer->Get_Pitch();
GraphicBuff = gbuffer;
IsDirectDraw= gbuffer->IsDirectDraw;
}
/***************************************************************************
* GVPC::CHANGE -- Changes position and size of a Graphic View Port *
* *
* INPUT: int the new x pixel position of the graphic view port *
* int the new y pixel position of the graphic view port *
* int the new width of the viewport in pixels *
* int the new height of the viewport in pixels *
* *
* OUTPUT: BOOL whether the Graphic View Port could be sucessfully *
* resized. *
* *
* WARNINGS: You may not resize a Graphic View Port which is derived *
* from a Graphic View Port Buffer, *
* *
* HISTORY: *
* 09/14/1994 SKB : Created. *
*=========================================================================*/
BOOL GraphicViewPortClass::Change(int x, int y, int w, int h)
{
/*======================================================================*/
/* Can not change a Graphic View Port if it is actually the physical */
/* representation of a Graphic Buffer. */
/*======================================================================*/
if (this == Get_Graphic_Buffer()) {
return(FALSE);
}
/*======================================================================*/
/* Since there is no allocated information, just re-attach it to the */
/* existing graphic buffer as if we were creating the */
/* GraphicViewPort. */
/*======================================================================*/
Attach(Get_Graphic_Buffer(), x, y, w, h);
return(TRUE);
}
/***************************************************************************
* GBC::DD_INIT -- Inits a direct draw surface for a GBC *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 10/09/1995 : Created. *
*=========================================================================*/
void GraphicBufferClass::DD_Init(GBC_Enum flags)
{
//
// Create the direct draw surface description
//
memset (&VideoSurfaceDescription , 0 , sizeof ( VideoSurfaceDescription ));
VideoSurfaceDescription.dwSize = sizeof( VideoSurfaceDescription );
VideoSurfaceDescription.dwFlags = DDSD_CAPS;
VideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if (!(flags & GBC_VISIBLE)) {
VideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
VideoSurfaceDescription.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH;
VideoSurfaceDescription.dwHeight = Height;
VideoSurfaceDescription.dwWidth = Width;
}
//
// Need to set the DDSCAPS_MODEX flag if we want a 320 wide mode
//
if ( Width == 320 ) {
VideoSurfaceDescription.ddsCaps.dwCaps |= DDSCAPS_MODEX;
}
//
// Call CreateSurface
//
DirectDrawObject->CreateSurface( &VideoSurfaceDescription , &VideoSurfacePtr , NULL);
AllSurfaces.Add_DD_Surface (VideoSurfacePtr);
if ( GBC_VISIBLE & flags ){
PaletteSurface=VideoSurfacePtr;
}
Allocated = FALSE; // even if system alloced, dont flag it cuz
// we dont want it freed.
IsDirectDraw = TRUE; // flag it as a video surface
Offset = NOT_LOCKED; // flag it as unavailable for reading or writing
LockCount = 0; // surface is not locked
}
void GraphicBufferClass::Attach_DD_Surface (GraphicBufferClass * attach_buffer)
{
VideoSurfacePtr->AddAttachedSurface (attach_buffer->Get_DD_Surface());
}
/***************************************************************************
* GBC::INIT -- Core function responsible for initing a GBC *
* *
* INPUT: int - the width in pixels of the GraphicBufferClass *
* int - the heigh in pixels of the GraphicBufferClass *
* void * - pointer to user supplied buffer (system will *
* allocate space if buffer is NULL) *
* long - size of the user provided buffer *
* GBC_Enum - flags if this is defined as a direct draw *
* surface *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 10/09/1995 : Created. *
*=========================================================================*/
void GraphicBufferClass::Init(int w, int h, void *buffer, long size, GBC_Enum flags)
{
Size = size; // find size of physical buffer
Width = w; // Record width of Buffer
Height = h; // Record height of Buffer
//
// If the surface we are creating is a direct draw object then
// we need to do a direct draw init. Otherwise we will do
// a normal alloc.
//
if (flags & (GBC_VIDEOMEM | GBC_VISIBLE)) {
DD_Init(flags);
} else {
if (buffer) { // if buffer is specified
Buffer = (BYTE *)buffer; // point to it and mark
Allocated = FALSE; // it as user allocated
} else {
if (!Size) Size = w*h;
Buffer = new BYTE[Size]; // otherwise allocate it and
Allocated = TRUE; // mark it system alloced
}
Offset = (long)Buffer; // Get offset to the buffer
IsDirectDraw = FALSE;
}
Pitch = 0; // Record width of Buffer
XAdd = 0; // Record XAdd of Buffer
XPos = 0; // Record XPos of Buffer
YPos = 0; // Record YPos of Buffer
GraphicBuff = this; // Get a pointer to our self
}
/***********************************************************************************************
* GBC::Un_Init -- releases the video surface belonging to this gbuffer *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 6/6/96 12:44PM ST : Created *
*=============================================================================================*/
void GraphicBufferClass::Un_Init (void)
{
if ( IsDirectDraw ){
if ( VideoSurfacePtr ){
while ( LockCount ){
if (VideoSurfacePtr->Unlock ( NULL ) == DDERR_SURFACELOST){
if (Gbuffer_Focus_Loss_Function){
Gbuffer_Focus_Loss_Function();
}
AllSurfaces.Restore_Surfaces();
}
}
AllSurfaces.Remove_DD_Surface (VideoSurfacePtr);
VideoSurfacePtr->Release();
VideoSurfacePtr = NULL;
}
}
}
/***************************************************************************
* GBC::GRAPHICBUFFERCLASS -- Default constructor (requires explicit init) *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 10/09/1995 : Created. *
*=========================================================================*/
GraphicBufferClass::GraphicBufferClass(void)
{
GraphicBuff = this; // Get a pointer to our self
VideoSurfacePtr = NULL;
memset(&VideoSurfaceDescription, 0, sizeof(DDSURFACEDESC));
}
/***************************************************************************
* GBC::GRAPHICBUFFERCLASS -- Constructor for fixed size buffers *
* *
* INPUT: long size - size of the buffer to create *
* int w - width of buffer in pixels (default = 320) *
* int h - height of buffer in pixels (default = 200) *
* void *buffer - a pointer to the buffer if any (optional) *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/13/1994 PWG : Created. *
*=========================================================================*/
GraphicBufferClass::GraphicBufferClass(int w, int h, void *buffer, long size)
{
Init(w, h, buffer, size, GBC_NONE);
}
/*=========================================================================*
* GBC::GRAPHICBUFFERCLASS -- inline constructor for GraphicBufferClass *
* *
* INPUT: int w - width of buffer in pixels (default = 320) *
* int h - height of buffer in pixels (default = 200) *
* void *buffer - a pointer to the buffer if any (optional) *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 05/03/1994 PWG : Created. *
*=========================================================================*/
GraphicBufferClass::GraphicBufferClass(int w, int h, void *buffer)
{
Init(w, h, buffer, w * h, GBC_NONE);
}
/*====================================================================================*
* GBC::GRAPHICBUFFERCLASS -- contructor for GraphicsBufferClass with special flags *
* *
* INPUT: int w - width of buffer in pixels (default = 320) *
* int h - height of buffer in pixels (default = 200) *
* void *buffer - unused *
* unsigned flags - flags for creation of special buffer types *
* GBC_VISIBLE - buffer is a visible screen surface *
* GBC_VIDEOMEM - buffer resides in video memory *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 09-21-95 04:19pm ST : Created *
*====================================================================================*/
GraphicBufferClass::GraphicBufferClass(int w, int h, GBC_Enum flags)
{
Init(w, h, NULL, w * h, flags);
}
/*=========================================================================*
* GBC::~GRAPHICBUFFERCLASS -- Destructor for the graphic buffer class *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 05/03/1994 PWG : Created. *
*=========================================================================*/
GraphicBufferClass::~GraphicBufferClass()
{
//
// Release the direct draw surface if it exists
//
Un_Init();
}
/***************************************************************************
* SET_LOGIC_PAGE -- Sets LogicPage to new buffer *
* *
* INPUT: GraphicBufferClass * the buffer we are going to set *
* *
* OUTPUT: GraphicBufferClass * the previous buffer type *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/23/1995 PWG : Created. *
*=========================================================================*/
GraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass *ptr)
{
GraphicViewPortClass *old = LogicPage;
LogicPage = ptr;
return(old);
}
/***************************************************************************
* SET_LOGIC_PAGE -- Sets LogicPage to new buffer *
* *
* INPUT: GraphicBufferClass & the buffer we are going to set *
* *
* OUTPUT: GraphicBufferClass * the previous buffer type *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/23/1995 PWG : Created. *
*=========================================================================*/
GraphicViewPortClass *Set_Logic_Page(GraphicViewPortClass &ptr)
{
GraphicViewPortClass *old = LogicPage;
LogicPage = &ptr;
return(old);
}
/***************************************************************************
* GBC::LOCK -- Locks a Direct Draw Surface *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 10/09/1995 : Created. *
* 10/09/1995 : Code stolen from Steve Tall *
*=========================================================================*/
extern void Colour_Debug (int call_number);
extern BOOL GameInFocus;
extern void Block_Mouse(GraphicBufferClass *buffer);
extern void Unblock_Mouse(GraphicBufferClass *buffer);
BOOL GraphicBufferClass::Lock(void)
{
HRESULT result;
int restore_attempts=0;
//
// If its not a direct draw surface then the lock is always sucessful.
//
if (!IsDirectDraw) return(TRUE);
/*
** If the video surface pointer is null then return
*/
if (!VideoSurfacePtr) return (FALSE);
/*
** If we dont have focus then return failure
*/
if (!GameInFocus) return (FALSE);
Block_Mouse(this);
//
// If surface is already locked then inc the lock count and return true
//
if (LockCount){
LockCount++;
Unblock_Mouse(this);
return(TRUE);
}
//
// If it isn't locked at all then we will have to request that Direct
// Draw actually lock the surface.
//
if (VideoSurfacePtr){
while (!LockCount && restore_attempts<2) {
result = VideoSurfacePtr->Lock ( NULL
, &(VideoSurfaceDescription)
, DDLOCK_WAIT
, NULL);
switch (result){
case DD_OK :
Offset = (unsigned long)VideoSurfaceDescription.lpSurface;
Pitch = VideoSurfaceDescription.lPitch;
Pitch -= Width;
LockCount++; // increment count so we can track if
TotalLocks++; // Total number of times we have locked (for debugging)
//Colour_Debug (1);
Unblock_Mouse(this);
return (TRUE); // we locked it multiple times.
case DDERR_SURFACELOST :
if (Gbuffer_Focus_Loss_Function){
Gbuffer_Focus_Loss_Function();
}
AllSurfaces.Restore_Surfaces();
restore_attempts++;
break;
default :
Unblock_Mouse(this);
return (FALSE);
}
}
}
//Colour_Debug(1);
Unblock_Mouse(this);
return (FALSE); //Return false because we couldnt lock or restore the surface
}
/***************************************************************************
* GBC::UNLOCK -- Unlocks a direct draw surface *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 10/09/1995 : Created. *
* 10/09/1995 : Code stolen from Steve Tall *
*=========================================================================*/
BOOL GraphicBufferClass::Unlock(void)
{
//
// If there is no lock count or this is not a direct draw surface
// then just return true as there is no harm done.
//
if (!(LockCount && IsDirectDraw)) {
return(TRUE);
}
//
// If lock count is directly equal to one then we actually need to
// unlock so just give it a shot.
//
if (LockCount == 1 && VideoSurfacePtr) {
Block_Mouse(this);
if ( VideoSurfacePtr->Unlock ( NULL ) != DD_OK ){
Unblock_Mouse(this);
return(FALSE);
} else {
Offset=NOT_LOCKED;
LockCount--;
Unblock_Mouse(this);
return(TRUE);
}
}
//Colour_Debug (0);
LockCount--;
return(TRUE);
}
/***********************************************************************************************
* GVPC::DD_Linear_Blit_To_Linear -- blit using the hardware blitter *
* *
* *
* *
* INPUT: destination vvpc *
* x coord to blit from *
* y coord to blit from *
* x coord to blit to *
* y coord to blit to *
* width to blit *
* height to blit *
* *
* OUTPUT: DD_OK if successful *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 09-22-95 11:05am ST : Created *
*=============================================================================================*/
HRESULT GraphicViewPortClass::DD_Linear_Blit_To_Linear (
GraphicViewPortClass &dest
, int source_x
, int source_y
, int dest_x
, int dest_y
, int width
, int height
, BOOL mask )
{
RECT source_rectangle;
RECT dest_rectangle;
int key_source=0;
if ( mask ){
key_source=DDBLT_KEYSRC;
}
source_rectangle.left = source_x;
source_rectangle.top = source_y;
source_rectangle.right = source_x+width;
source_rectangle.bottom = source_y+height;
dest_rectangle.left = dest_x;
dest_rectangle.top = dest_y;
dest_rectangle.right = dest_x+width;
dest_rectangle.bottom = dest_y+height;
return ( dest.GraphicBuff->Get_DD_Surface()->Blt ( &dest_rectangle,
GraphicBuff->Get_DD_Surface(),
&source_rectangle,
key_source | DDBLT_WAIT | DDBLT_ASYNC,
NULL ) );
}

1366
WIN32LIB/DRAWBUFF/GBUFFER.H Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
;
; 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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 Bit Library *
;* *
;* File Name : GBUFFER.INC *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : May 26, 1994 *
;* *
;* Last Update : May 26, 1994 [PWG] *
;* *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;******************************************************************************
; Much testing was done to determine that only when there are 14 or more bytes
; being copied does it speed the time it takes to do copies in this algorithm.
; For this reason and because 1 and 2 byte copies crash, is the special case
; used. SKB 4/21/94. Tested on 486 66mhz. Copied by PWG 6/7/04.
OPTIMAL_BYTE_COPY equ 14
STRUC GraphicViewPort
GVPOffset DD ? ; offset to virtual viewport
GVPWidth DD ? ; width of virtual viewport
GVPHeight DD ? ; height of virtual viewport
GVPXAdd DD ? ; x mod to get to next line
GVPXPos DD ? ; x pos relative to Graphic Buff
GVPYPos DD ? ; y pos relative to Graphic Buff
GVPPitch dd ? ; modulo of graphic view port
GVPBuffPtr DD ? ; ptr to associated Graphic Buff
ENDS

View File

@@ -0,0 +1,115 @@
;
; 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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : BITBLIT.ASM *
;* *
;* Programmer : Julio R. Jerez *
;* *
;* Start Date : Feb 6, 1995 *
;* *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
INCLUDE ".\drawbuff.inc"
INCLUDE "gbuffer.inc"
; typedef struct {
; int x0 , y0 ;
; int x1 , y1 ;
; } CLIP_WIN ;
; Note for efficiency reasons x1 must be >= x0 and y1 >= y0
; int get_clip ( CLIP_WIN * window , CLIP_WIN * sorce_rect ) ;
CODESEG
PROC get_clip C near
USES eax , ebx
;*===================================================================
;* define the arguements that our function takes.
;*===================================================================
ARG win : dword
ARG rect : dword
mov edi , [ rect ]
mov esi , [ win ]
xor eax , eax
xor edx , edx
mov ecx , [ (RECTANGLE edi) . x0 ]
mov ebx , [ (RECTANGLE edi) . x1 ]
sub ecx , [ (RECTANGLE esi) . x0 ]
sub ebx , [ (RECTANGLE esi) . x0 ]
shld eax , ecx , 1
shld edx , ebx , 1
; mov ebx , [ (RECTANGLE esi) . x1 ]
; inc ebx
; mov [ rect ] , ebx
mov ecx , [ (RECTANGLE edi) . x0 ]
mov ebx , [ (RECTANGLE edi) . x1 ]
sub ecx , [ (RECTANGLE esi) . x1 ]
sub ebx , [ (RECTANGLE esi) . x1 ]
dec ecx
dec ebx
shld eax , ecx , 1
shld edx , ebx , 1
mov ecx , [ (RECTANGLE edi) . y0 ]
mov ebx , [ (RECTANGLE edi) . y1 ]
sub ecx , [ (RECTANGLE esi) . y0 ]
sub ebx , [ (RECTANGLE esi) . y0 ]
shld eax , ecx , 1
shld edx , ebx , 1
; mov ebx , [ (RECTANGLE esi) . y1 ]
; inc ebx
; mov [ rect ] , ebx
mov ecx , [ (RECTANGLE edi) . y0 ]
mov ebx , [ (RECTANGLE edi) . y1 ]
sub ecx , [ (RECTANGLE esi) . y1 ]
sub ebx , [ (RECTANGLE esi) . y1 ]
dec ecx
dec ebx
shld eax , ecx , 1
shld edx , ebx , 1
xor al , 5
xor dl , 5
mov ah , dl
ret
ENDP get_clip
END

View File

@@ -0,0 +1,106 @@
;
; 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 : GraphicViewPortClass *
;* *
;* File Name : GETPIXEL.ASM *
;* *
;* Programmer : Phil Gorrow *
;* *
;* Start Date : June 7, 1994 *
;* *
;* Last Update : June 7, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* VVPC::Buffer_Get_Pixel -- get the colour of a pixel at given coords *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
;***************************************************************************
;* VVPC::GET_PIXEL -- Gets a pixel from the current view port *
;* *
;* INPUT: WORD the x pixel on the screen. *
;* WORD the y pixel on the screen. *
;* *
;* OUTPUT: UBYTE the pixel at the specified location *
;* *
;* WARNING: If pixel is to be placed outside of the viewport then *
;* this routine will abort. *
;* *
;* HISTORY: *
;* 06/07/1994 PWG : Created. *
;*=========================================================================*
PROC Buffer_Get_Pixel C near
USES ebx,ecx,edx,edi
ARG this_object:DWORD ; this is a member function
ARG x_pixel:DWORD ; x position of pixel to set
ARG y_pixel:DWORD ; y position of pixel to set
;*===================================================================
; Get the viewport information and put bytes per row in ecx
;*===================================================================
mov ebx,[this_object] ; get a pointer to viewport
xor eax,eax
mov edi,[(GraphicViewPort ebx).GVPOffset] ; get the correct offset
mov ecx,[(GraphicViewPort ebx).GVPHeight] ; edx = height of viewport
mov edx,[(GraphicViewPort ebx).GVPWidth] ; ecx = width of viewport
;*===================================================================
; Verify that the X pixel offset if legal
;*===================================================================
mov eax,[x_pixel] ; find the x position
cmp eax,edx ; is it out of bounds
jae short ??exit ; if so then get out
add edi,eax ; otherwise add in offset
;*===================================================================
; Verify that the Y pixel offset if legal
;*===================================================================
mov eax,[y_pixel] ; get the y position
cmp eax,ecx ; is it out of bounds
jae ??exit ; if so then get out
add edx,[(GraphicViewPort ebx).GVPXAdd] ; otherwise find bytes per row
add edx,[(GraphicViewPort ebx).GVPPitch] ; otherwise find bytes per row
mul edx ; offset = bytes per row * y
add edi,eax ; add it into the offset
;*===================================================================
; Write the pixel to the screen
;*===================================================================
xor eax,eax ; clear the word
mov al,[edi] ; read in the pixel
??exit:
ret
ENDP Buffer_Get_Pixel
END

View File

@@ -0,0 +1,609 @@
/*
** 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 : Drawbuff - Westwood win95 library *
* *
* File Name : Iconcach.CPP *
* *
* Programmer : Steve Tall *
* *
* Start Date : November 8th, 1995 *
* *
* Last Update : November 13th, 1995 [ST] *
* *
*---------------------------------------------------------------------------------------------*
* Overview: This file cantains members of the IconCacheClass and associated non member *
* functions. All functions are to do with caching individual icons from icon sets *
* into video memory to improve the speed of subsequent drawing *
* *
* Functions: *
* Cache_New_Icon -- Call the Cache_It member to cache a registered icon to video memory *
* Invalidate_Cached_Icons -- Uncache all the icons *
* Restore_Cached_Icons -- restore cached icons after a focus loss *
* Register_Icon_Set -- register an icon set as cachable *
* Get_Free_Cache_Slot -- find an empty cache slot *
* IconCacheClass::IconCacheClass -- IconCacheClass constructor *
* IconCacheClass::~IconCacheClass -- IconCacheClass destructor *
* IconCacheClass::Restore -- restore the icons surface and recache it *
* IconCacheClass::Cache_It -- cache an icon into video memory *
* IconCacheClass::Uncache_It -- restore the video memory used by a cached icon *
* IconCacheClass::Draw_It -- use the blitter to draw the cached icon *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#define WIN32_LEAN_AND_MEAN
#define _WIN32
#include <windows.h>
#include "ddraw.h"
#include "misc.h"
#include "iconcach.h"
#include "gbuffer.h"
static DDSURFACEDESC VideoSurfaceDescription;
IconCacheClass CachedIcons[MAX_CACHED_ICONS];
extern "C"{
IconSetType IconSetList[MAX_ICON_SETS];
short IconCacheLookup[MAX_LOOKUP_ENTRIES];
}
int CachedIconsDrawn=0; //Counter of number of cache hits
int UnCachedIconsDrawn=0; //Counter of number of cache misses
BOOL CacheMemoryExhausted; //Flag set if we have run out of video RAM
/***********************************************************************************************
* Optimise_Video_Memory_Cache -- optimises usage of video memory *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: TRUE if memory was freed up *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/29/95 12:47PM ST : Created *
*=============================================================================================*/
BOOL Optimize_Video_Memory_Cache (void)
{
if (CacheMemoryExhausted &&
(UnCachedIconsDrawn+CachedIconsDrawn > 1000) &&
UnCachedIconsDrawn > CachedIconsDrawn){
int cache_misses[MAX_CACHED_ICONS];
int cache_hits[MAX_CACHED_ICONS];
int total_cache_misses=0;
int total_cache_hits=0;
int counter;
int i;
int j;
int temp;
BOOL swapped;
/*
** make list of icons that have failed to cache more than 5 times
*/
for (counter=0 ; counter<MAX_CACHED_ICONS ; counter++){
if (CachedIcons[counter].TimesFailed>5){
cache_misses[total_cache_misses++] = counter;
}
}
/*
** Make list of icons that have been drawn less than 3 times
*/
for (counter=0 ; counter<MAX_CACHED_ICONS ; counter++){
if (CachedIcons[counter].TimesDrawn<3){
cache_hits[total_cache_hits++] = counter;
}
}
/*
** Sort drawn icons into order
*/
if (total_cache_hits > 1){
for (i = 0 ; i<total_cache_hits ; i++){
swapped=FALSE;
for (j=0 ; j<total_cache_hits-1 ; j++){
if (CachedIcons[cache_hits[j]].TimesDrawn > CachedIcons[cache_hits[j+1]].TimesDrawn){
temp=cache_hits[j];
cache_hits[j]=cache_hits[j+1];
cache_hits[j+1]=temp;
swapped = TRUE;
}
}
if (!swapped) break;
}
}
/*
** Uncache icons up to the number of failed icons
*/
for (counter=0 ; counter<total_cache_misses && counter<total_cache_hits; counter++){
CachedIcons[cache_hits[counter]].Uncache_It();
}
CacheMemoryExhausted=FALSE;
CachedIconsDrawn=0;
UnCachedIconsDrawn=0;
return (TRUE);
}
return (FALSE);
}
/***********************************************************************************************
* Cache_New_Icon -- cache a registered icon to video memory *
* *
* *
* *
* INPUT: icon_index -- index into registered icon table of icon to cache *
* icon_ptr -- ptr to icon data *
* *
* OUTPUT: BOOL success *
* *
* WARNINGS: icon must already have been registered and assigned an index *
* *
* HISTORY: *
* 11/13/95 9:36AM ST : Created *
*=============================================================================================*/
BOOL Cache_New_Icon (int icon_index, void *icon_ptr)
{
if (!CacheMemoryExhausted){
return (CachedIcons[icon_index].Cache_It(icon_ptr));
} else {
CachedIcons[icon_index].TimesFailed++;
if (Optimize_Video_Memory_Cache()){
return (CachedIcons[icon_index].Cache_It(icon_ptr));
} else {
return (FALSE);
}
}
}
/***********************************************************************************************
* Invalidat_Cached_Icons -- used to release any icons that have been cached *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/13/95 9:37AM ST : Created *
*=============================================================================================*/
void Invalidate_Cached_Icons (void)
{
for (int i=0 ; i<MAX_CACHED_ICONS ; i++){
CachedIcons[i].Uncache_It();
}
memset (&IconCacheLookup[0] , -1 ,MAX_LOOKUP_ENTRIES*sizeof(IconCacheLookup[0]));
for (i=0 ; i<MAX_ICON_SETS ; i++){
IconSetList[i].IconSetPtr=NULL;
}
CacheMemoryExhausted=FALSE;
}
/***********************************************************************************************
* Restore_Cached_Icons -- re-cache icons into video memory after a loss of focus *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: Assumes that the pointers that were originally used to cache the icons *
* are still valid. *
* *
* HISTORY: *
* 11/13/95 9:38AM ST : Created *
*=============================================================================================*/
void Restore_Cached_Icons (void)
{
for (int i=0 ; i<MAX_CACHED_ICONS ; i++){
CachedIcons[i].Restore();
}
CacheMemoryExhausted=FALSE;
}
/***********************************************************************************************
* Register_Icon_Set -- used to register an icon set as cachable *
* *
* *
* *
* INPUT: icon_data - ptr to icon set *
* pre_cache -- should we pre-cache the icon data? *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/13/95 9:39AM ST : Created *
*=============================================================================================*/
void Register_Icon_Set (void *icon_data , BOOL pre_cache)
{
for (int i=0 ; i<MAX_ICON_SETS ; i++){
if (!IconSetList[i].IconSetPtr){
IconSetList[i].IconSetPtr = (IControl_Type*)icon_data;
if (i){
IControl_Type *previous_set = IconSetList[i-1].IconSetPtr;
IconSetList[i].IconListOffset = IconSetList[i-1].IconListOffset + ((int)previous_set->Count)*2;
if (IconSetList[i].IconListOffset > MAX_LOOKUP_ENTRIES*2){
IconSetList[i].IconSetPtr = NULL;
}
} else {
IconSetList[i].IconListOffset = 0;
}
if (pre_cache){
for (i=0 ; i<256 ; i++){
Is_Icon_Cached(icon_data,i);
}
}
return;
}
}
}
/***********************************************************************************************
* Get_Free_Cache_Slot -- find a free slot in which to cache an icon *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: int - icon index *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/13/95 9:40AM ST : Created *
*=============================================================================================*/
int Get_Free_Cache_Slot (void)
{
for (int i=0 ; i<MAX_CACHED_ICONS ; i++){
if (!CachedIcons[i].Get_Is_Cached()){
return (i);
}
}
return (-1);
}
/***********************************************************************************************
* ICC::IconCacheClass -- constructor for icon cache class *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/13/95 9:41AM ST : Created *
*=============================================================================================*/
IconCacheClass::IconCacheClass (void)
{
IsCached =FALSE;
SurfaceLost =FALSE;
DrawFrequency =0;
CacheSurface =NULL;
IconSource =NULL;
}
/***********************************************************************************************
* ICC::~IconCacheClass -- destructor for icon cache class *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/13/95 9:41AM ST : Created *
*=============================================================================================*/
IconCacheClass::~IconCacheClass (void)
{
if (IsCached && CacheSurface){
CacheSurface->Release();
}
}
/***********************************************************************************************
* ICC::Restore -- Restores the icons video surface memory and reloads it based on the original*
* icon pointer *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: Relies on the icons original pointer still being valie *
* *
* HISTORY: *
* 11/13/95 9:43AM ST : Created *
*=============================================================================================*/
void IconCacheClass::Restore (void)
{
if (IsCached && CacheSurface){
CacheSurface->Restore();
if (IconSource){
Cache_It(IconSource);
}
}
}
/***********************************************************************************************
* ICC::Cache_It -- allocate video memory and copy an icon to it *
* *
* *
* *
* INPUT: icon_ptr -- ptr to icon data *
* *
* OUTPUT: bool -- success? *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/13/95 9:44AM ST : Created *
*=============================================================================================*/
BOOL IconCacheClass::Cache_It (void *icon_ptr)
{
DDSCAPS surface_capabilities;
BOOL return_value;
/*
** If we dont have a direct draw interface yet then just fail
*/
if (!DirectDrawObject) return(FALSE);
/*
** Set up the description of the surface we want to create
*/
memset (&VideoSurfaceDescription , 0 , sizeof ( VideoSurfaceDescription ));
VideoSurfaceDescription.dwSize = sizeof( VideoSurfaceDescription );
VideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
VideoSurfaceDescription.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
VideoSurfaceDescription.dwHeight = ICON_WIDTH;
VideoSurfaceDescription.dwWidth = ICON_HEIGHT;
/*
** If this cache object doesnt already have a surface then create one
*/
if (!CacheSurface){
if (DD_OK!=DirectDrawObject->CreateSurface( &VideoSurfaceDescription , &CacheSurface , NULL)){
CacheMemoryExhausted = TRUE;
return(FALSE);
}
}
/*
** Make sure the surface we created isnt really in system memory
*/
if (DD_OK != CacheSurface->GetCaps(&surface_capabilities)){
return(FALSE);
}
if ((DDSCAPS_SYSTEMMEMORY & surface_capabilities.dwCaps) == DDSCAPS_SYSTEMMEMORY){
CacheSurface->Release();
return(FALSE);
}
return_value=FALSE;
/*
** Lock the surface so we can copy the icon to it
*/
if (DD_OK== CacheSurface->Lock ( NULL
, &(VideoSurfaceDescription)
, DDLOCK_WAIT
, NULL)){
/*
** Copy the icon to the surface and flag that icon is cached
*/
Cache_Copy_Icon (icon_ptr , VideoSurfaceDescription.lpSurface , VideoSurfaceDescription.lPitch);
IsCached=TRUE;
SurfaceLost=FALSE;
IconSource=icon_ptr;
return_value=TRUE;
}
CacheSurface->Unlock(NULL);
return (return_value);
}
/***********************************************************************************************
* ICC::Uncache_It -- release the video memory used to cache an icon *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/13/95 9:48AM ST : Created *
*=============================================================================================*/
void IconCacheClass::Uncache_It(void)
{
if (IsCached && CacheSurface){
CacheSurface->Release();
IsCached=FALSE;
CacheSurface=NULL;
IconSource=NULL;
CacheMemoryExhausted=FALSE;
}
}
/***********************************************************************************************
* ICC::Draw_It -- use the blitter to draw a cached icon *
* *
* *
* *
* INPUT: surface to draw to *
* x coord to draw to (relative to window) *
* y coord to draw to (relative to window) *
* window left coord *
* window top coord *
* window width *
* window height *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/13/95 9:48AM ST : Created *
*=============================================================================================*/
void IconCacheClass::Draw_It (LPDIRECTDRAWSURFACE dest_surface , int x_pixel, int y_pixel, int window_left , int window_top , int window_width , int window_height)
{
RECT source_rectangle;
RECT dest_rectangle;
int clip;
HRESULT return_code;
/*
** Set up the source and destination coordinates as required by direct draw
*/
source_rectangle.left = 0;
source_rectangle.top = 0;
source_rectangle.right = ICON_WIDTH;
source_rectangle.bottom = ICON_HEIGHT;
dest_rectangle.left = window_left+x_pixel;
dest_rectangle.top = window_top+y_pixel;
dest_rectangle.right = dest_rectangle.left+ICON_WIDTH;
dest_rectangle.bottom = dest_rectangle.top+ICON_HEIGHT;
/*
** Clip the coordinates to the window
*/
if (dest_rectangle.left<window_left){
source_rectangle.left += window_left-dest_rectangle.left;
dest_rectangle.left=window_left;
}
if (dest_rectangle.right>=window_left+window_width){
clip = dest_rectangle.right-(window_left+window_width);
source_rectangle.right -= clip;
dest_rectangle.right -= clip;
}
if (dest_rectangle.top<window_top){
source_rectangle.top += window_top-dest_rectangle.top;
dest_rectangle.top=window_top;
}
if (dest_rectangle.bottom>=window_top+window_height){
clip = dest_rectangle.bottom-(window_top+window_height);
source_rectangle.bottom -= clip;
dest_rectangle.bottom -= clip;
}
if (source_rectangle.left>=source_rectangle.right){
return;
}
if (source_rectangle.top>=source_rectangle.bottom){
return;
}
/*
** Do the blit
*/
return_code = dest_surface->Blt (&dest_rectangle ,
CacheSurface ,
&source_rectangle ,
DDBLT_WAIT |
DDBLT_ASYNC ,
NULL);
if (return_code == DDERR_SURFACELOST && Gbuffer_Focus_Loss_Function){
Gbuffer_Focus_Loss_Function();
}
if ( return_code != DDERR_SURFACELOST && return_code != DD_OK ) {
char temp[100];
sprintf(temp,"DD Error code %d\n", return_code & 0xFFFF);
OutputDebugString(temp);
}
TimesDrawn++;
}

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 : Drawbuff - Westwood win95 library *
* *
* File Name : Iconcach.H *
* *
* Programmer : Steve Tall *
* *
* Start Date : November 8th, 1995 *
* *
* Last Update : November 16th, 1995 [ST] *
* *
*---------------------------------------------------------------------------------------------*
* Overview: This file cantains definition of the IconCacheClass and associated non member *
* function prototypes. *
* *
* Functions: *
* IconCacheClass::Get_Is_Cached -- member to allow access to private IsCached flag *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef ICONCACH_H
#define ICONCACH_H
#include <tile.h>
#define ICON_WIDTH 24 // Icons must be this width to be cached
#define ICON_HEIGHT 24 // Icons must be this height to be cached
#define MAX_CACHED_ICONS 500 // Maximum number of icons that can be cached
#define MAX_ICON_SETS 100 // Maximum number of icon sets that can be registered
#define MAX_LOOKUP_ENTRIES 3000 // Size of icon index table
/*
** IconCacheClass for tracking individual icons cached into video memory
**
** Use Register_Icon_Set to identify a set of icons as cachable. Once registered, the icons
** will be cached automatically when drawn.
** Use Invalidate_Cached_Icons at the end of icon drawing to release the video memory used by the
** caching system.
** Restore_Cached_Icons may be used to reload the icons into video memory after a focus loss.
**
*/
class IconCacheClass {
public:
IconCacheClass (void); // class constructor
~IconCacheClass (void); // class destructor
void Restore(void); // restore the surface
BOOL Cache_It (void * icon_ptr); // Cache the icon to video memory
void Uncache_It (void); // Restore the video memory and flag the icon as uncached
void Draw_It (LPDIRECTDRAWSURFACE dest_surface , int x_pixel, int y_pixel, int window_left , int window_top , int window_width , int window_height);
inline BOOL Get_Is_Cached(void); // Return the IsCached member
int TimesDrawn; // counter of times cached icon has been drawn
int TimesFailed; // counter of times cached icon has failed to draw
private:
LPDIRECTDRAWSURFACE CacheSurface; // Ptr to direct draw surface where icon resides
BOOL IsCached; // Flag to say whether an icon is cached
BOOL SurfaceLost; // Flag to indicate that our icons surface has been lost
int DrawFrequency; // Number of times icon has been drawn
void *IconSource; // Ptr to original icon data in system memory
};
/*
** Structure to keep track of registered icon sets
**
*/
typedef struct tIconSetType{
IControl_Type *IconSetPtr; // Ptr to icon set data
int IconListOffset; // Offset into icon index table for this icon set
}IconSetType;
extern IconCacheClass CachedIcons[MAX_CACHED_ICONS];
extern void Invalidate_Cached_Icons (void);
extern void Restore_Cached_Icons (void);
extern void Register_Icon_Set (void *icon_data , BOOL pre_cache);
//
// Prototypes for assembly language procedures in STMPCACH.ASM
//
extern "C" void Clear_Icon_Pointers (void);
extern "C" void Cache_Copy_Icon (void const *icon_ptr ,void * , int);
extern "C" int Is_Icon_Cached (void const *icon_data , int icon);
extern "C" int Get_Icon_Index (void *icon_ptr);
extern "C" int Get_Free_Index (void);
extern "C" BOOL Cache_New_Icon (int icon_index, void *icon_ptr);
extern "C" int Get_Free_Cache_Slot(void);
extern int CachedIconsDrawn;
extern int UnCachedIconsDrawn;
/***********************************************************************************************
* ICC::Get_Is_Cached -- member to allow access to the private IsCached flag *
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: IsCached *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 11/13/95 9:42AM ST : Created *
*=============================================================================================*/
inline BOOL IconCacheClass::Get_Is_Cached (void)
{
return (IsCached);
}
#endif //ICONCACH_H

203
WIN32LIB/DRAWBUFF/MAKEFILE Normal file
View File

@@ -0,0 +1,203 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WIN32LIB path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef %WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef %WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef %WATCOM
!error COMPILER Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = drawbuff
PROJ_DIR = $(%WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(%WIN32LIB)\lib
!include $(%WIN32LIB)\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = &
bitblit.obj &
buffer.obj &
buffglbl.obj &
clear.obj &
drawline.obj &
drawrect.obj &
fillquad.obj &
fillrect.obj &
gbuffer.obj &
getclip.obj &
getpix.obj &
putpix.obj &
regionsz.obj &
remap.obj &
scale.obj &
stamp.obj &
szregion.obj &
tobuff.obj &
topage.obj &
txtprnt.obj &
iconcach.obj &
stmpcach.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.asm: $(PROJ_DIR)
.c: $(PROJ_DIR)
.cpp: $(PROJ_DIR)
.h: $(PROJ_DIR)
.obj: $(PROJ_DIR)
.lib: $(%WIN32LIB)\lib
.exe: $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = wcc386
CPP_CMD = wpp386
LIB_CMD = wlib
LINK_CMD = wlink
ASM_CMD = tasm
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(%WIN32LIB)\LIB;$(%WATCOM)\LIB
INCLUDEPATH = $(%WIN32LIB)\INCLUDE;$(%WATCOM)\H
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
*$(C_CMD) $(CC_CFG) $<
.cpp.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
*$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\$^*.cpp
.asm.obj: $(%WIN32LIB)\project.cfg
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib .SYMBOLIC
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc
copy *.h $(%WIN32LIB)\include
copy *.inc $(%WIN32LIB)\include
copy *.cpp $(%WIN32LIB)\srcdebug
copy *.asm $(%WIN32LIB)\srcdebug
$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc
#---------------------------------------------------------------------------
# Objects now have a link file which is NOT generated everytime. Instead
# it just has its own dependacy rule.
#---------------------------------------------------------------------------
objects.lbc : $(OBJECTS)
%create $^@
for %index in ($(OBJECTS)) do %append $^@ +%index
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(%WWVCS)\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..
#**************************** End of makefile ******************************


View File

@@ -0,0 +1,206 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WWFLAT path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef COMPILER
!error COMPILER Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = drawbuff
PROJ_DIR = $(WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(WIN32LIB)\lib
!include $(WIN32LIB)\\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = \
bitblit.obj \
buffer.obj \
buffglbl.obj \
clear.obj \
drawline.obj \
drawrect.obj \
fillquad.obj \
fillrect.obj \
gbuffer.obj \
getclip.obj \
getpix.obj \
putpix.obj \
regionsz.obj \
remap.obj \
scale.obj \
stamp.obj \
szregion.obj \
tobuff.obj \
topage.obj \
txtprnt.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.path.asm = $(PROJ_DIR)
.path.c = $(PROJ_DIR)
.path.cpp = $(PROJ_DIR)
.path.h = $(PROJ_DIR)
.path.obj = $(PROJ_DIR)
.path.lib = $(WIN32LIB)\lib
.path.exe = $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = bcc32
CPP_CMD = bcc32
LIB_CMD = tlib
LINK_CMD = tlink32
ASM_CMD = tasm32
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(WIN32LIB)\LIB;$(COMPILER)\LIB
INCLUDEPATH = $(WIN32LIB)\INCLUDE;$(COMPILER)\INCLUDE
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj:
$(C_CMD) $(CC_CFG) $<
.cpp.obj:
$(CPP_CMD) $(CC_CFG) $<
.asm.obj:
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS)
copy *.h $(WIN32LIB)\\include
copy *.inc $(WIN32LIB)\\include
copy *.cpp $(WIN32LIB)\\srcdebug
copy *.asm $(WIN32LIB)\\srcdebug
$(LIB_CMD) $< $(LIB_CFG) @&&|
-+bitblit.obj &
-+buffer.obj &
-+buffglbl.obj &
-+clear.obj &
-+drawline.obj &
-+drawrect.obj &
-+fillquad.obj &
-+fillrect.obj &
-+gbuffer.obj &
-+getclip.obj &
-+getpix.obj &
-+putpix.obj &
-+regionsz.obj &
-+remap.obj &
-+scale.obj &
-+stamp.obj &
-+szregion.obj &
-+tobuff.obj &
-+topage.obj &
-+txtprnt.obj
|
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(WWVCS)\\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..

View File

@@ -0,0 +1,110 @@
;
; 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 : GraphicViewPortClass *
;* *
;* File Name : PUTPIXEL.ASM *
;* *
;* Programmer : Phil Gorrow *
;* *
;* Start Date : June 7, 1994 *
;* *
;* Last Update : June 8, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* VVPC::Put_Pixel -- Puts a pixel on a virtual viewport *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
;***************************************************************************
;* VVPC::PUT_PIXEL -- Puts a pixel on a virtual viewport *
;* *
;* INPUT: WORD the x position for the pixel relative to the upper *
;* left corner of the viewport *
;* WORD the y pos for the pixel relative to the upper left *
;* corner of the viewport *
;* UBYTE the color of the pixel to write *
;* *
;* OUTPUT: none *
;* *
;* WARNING: If pixel is to be placed outside of the viewport then *
;* this routine will abort. *
;* *
;* HISTORY: *
;* 06/08/1994 PWG : Created. *
;*=========================================================================*
PROC Buffer_Put_Pixel C near
USES eax,ebx,ecx,edx,edi
ARG this_object:DWORD ; this is a member function
ARG x_pixel:DWORD ; x position of pixel to set
ARG y_pixel:DWORD ; y position of pixel to set
ARG color:BYTE ; what color should we clear to
;*===================================================================
; Get the viewport information and put bytes per row in ecx
;*===================================================================
mov ebx,[this_object] ; get a pointer to viewport
xor eax,eax
mov edi,[(GraphicViewPort ebx).GVPOffset] ; get the correct offset
mov ecx,[(GraphicViewPort ebx).GVPHeight] ; edx = height of viewport
mov edx,[(GraphicViewPort ebx).GVPWidth] ; ecx = width of viewport
;*===================================================================
; Verify that the X pixel offset if legal
;*===================================================================
mov eax,[x_pixel] ; find the x position
cmp eax,edx ; is it out of bounds
jae short ??exit ; if so then get out
add edi,eax ; otherwise add in offset
;*===================================================================
; Verify that the Y pixel offset if legal
;*===================================================================
mov eax,[y_pixel] ; get the y position
cmp eax,ecx ; is it out of bounds
jae ??exit ; if so then get out
add edx,[(GraphicViewPort ebx).GVPXAdd] ; otherwise find bytes per row
add edx,[(GraphicViewPort ebx).GVPPitch] ; add in direct draw pitch
mul edx ; offset = bytes per row * y
add edi,eax ; add it into the offset
;*===================================================================
; Write the pixel to the screen
;*===================================================================
mov al,[color] ; read in color value
mov [edi],al ; write it to the screen
??exit:
ret
ENDP Buffer_Put_Pixel
END

View File

@@ -0,0 +1,60 @@
/*
** 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 : WWLIB 32 *
* *
* File Name : REGIONSZ.CPP *
* *
* Programmer : Phil W. Gorrow *
* *
* Start Date : November 3, 1994 *
* *
* Last Update : November 3, 1994 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Size_Of_Region -- Calculates the size of a given region *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* SIZE_OF_REGION -- Calculates the size of a given region *
* *
* INPUT: int width - the width of the region *
* int height - the height of the region *
* *
* OUTPUT: long - the size of the region *
* *
* HISTORY: *
* 11/03/1994 PWG : Created. *
*=========================================================================*/
long Size_Of_Region(int width, int height)
{
return(width * height);
}

175
WIN32LIB/DRAWBUFF/REMAP.ASM Normal file
View File

@@ -0,0 +1,175 @@
;
; 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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : REMAP.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : July 1, 1994 *
;* *
;* Last Update : July 1, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
PROC Buffer_Remap C NEAR
USES eax,ebx,ecx,edx,esi,edi
;*===================================================================
;* Define the arguements that our function takes.
;*===================================================================
ARG this_object:DWORD
ARG x0_pixel:DWORD
ARG y0_pixel:DWORD
ARG region_width:DWORD
ARG region_height:DWORD
ARG remap :DWORD
;*===================================================================
; Define some locals so that we can handle things quickly
;*===================================================================
local x1_pixel : DWORD
local y1_pixel : DWORD
local win_width : dword
local counter_x : dword
cmp [ remap ] , 0
jz ??real_out
; Clip Source Rectangle against source Window boundaries.
mov esi , [ this_object ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register
mov ebx , [ x0_pixel ]
mov eax , [ x0_pixel ]
add ebx , [ region_width ]
shld ecx , eax , 1
mov [ x1_pixel ] , ebx
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register
mov ebx , [ y0_pixel ]
mov eax , [ y0_pixel ]
add ebx , [ region_height ]
shld ecx , eax , 1
mov [ y1_pixel ] , ebx
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
xor cl , 5
xor dl , 5
mov al , cl
test dl , cl
jnz ??real_out
or al , dl
jz ??do_remap
test cl , 1000b
jz ??scr_left_ok
mov [ x0_pixel ] , 0
??scr_left_ok:
test cl , 0010b
jz ??scr_bottom_ok
mov [ y0_pixel ] , 0
??scr_bottom_ok:
test dl , 0100b
jz ??scr_right_ok
mov eax , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register
mov [ x1_pixel ] , eax
??scr_right_ok:
test dl , 0001b
jz ??do_remap
mov eax , [ (GraphicViewPort esi) . GVPHeight ] ; get width into register
mov [ y1_pixel ] , eax
??do_remap:
cld
mov edi , [ (GraphicViewPort esi) . GVPOffset ]
mov eax , [ (GraphicViewPort esi) . GVPXAdd ]
mov ebx , [ x1_pixel ]
add eax , [ (GraphicViewPort esi) . GVPWidth ]
add eax , [ (GraphicViewPort esi) . GVPPitch ]
mov esi , eax
mul [ y0_pixel ]
add edi , [ x0_pixel ]
sub ebx , [ x0_pixel ]
jle ??real_out
add edi , eax
sub esi , ebx
mov ecx , [ y1_pixel ]
sub ecx , [ y0_pixel ]
jle ??real_out
mov eax , [ remap ]
mov [ counter_x ] , ebx
xor edx , edx
??outer_loop:
mov ebx , [ counter_x ]
??inner_loop:
mov dl , [ edi ]
mov dl , [ eax + edx ]
mov [ edi ] , dl
inc edi
dec ebx
jnz ??inner_loop
add edi , esi
dec ecx
jnz ??outer_loop
??real_out:
ret
ENDP Buffer_Remap
END

570
WIN32LIB/DRAWBUFF/SCALE.ASM Normal file
View File

@@ -0,0 +1,570 @@
;
; 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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : SCALE.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : June 16, 1994 *
;* *
;* Last Update : June 21, 1994 [PWG] *
;* New version : feb 12, 1995 [JRJ] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* VVC::Scale -- Scales a virtual viewport to another virtual viewport *
;* Normal_Draw -- jump loc for drawing scaled line of normal pixel *
;* Normal_Remapped_Draw -- jump loc for draw scaled line of remap pixel *
;* Transparent_Draw -- jump loc for scaled line of transparent pixels *
;* Transparent_Remapped_Draw -- jump loc for scaled remap trans pixels *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
;***************************************************************************
;* VVC::SCALE -- Scales a virtual viewport to another virtual viewport *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 06/16/1994 PWG : Created. *
;*=========================================================================*
PROC Linear_Scale_To_Linear C NEAR
USES eax,ebx,ecx,edx,esi,edi
;*===================================================================
;* Define the arguements that our function takes.
;*===================================================================
ARG this_object:DWORD ; pointer to source view port
ARG dest:DWORD ; pointer to destination view port
ARG src_x:DWORD ; source x offset into view port
ARG src_y:DWORD ; source y offset into view port
ARG dst_x:DWORD ; dest x offset into view port
ARG dst_y:DWORD ; dest y offset into view port
ARG src_width:DWORD ; width of source rectangle
ARG src_height:DWORD ; height of source rectangle
ARG dst_width:DWORD ; width of dest rectangle
ARG dst_height:DWORD ; width of dest height
ARG trans:DWORD ; is this transparent?
ARG remap:DWORD ; pointer to table to remap source
;*===================================================================
;* Define local variables to hold the viewport characteristics
;*===================================================================
local src_x0 : dword
local src_y0 : dword
local src_x1 : dword
local src_y1 : dword
local dst_x0 : dword
local dst_y0 : dword
local dst_x1 : dword
local dst_y1 : dword
local src_win_width : dword
local dst_win_width : dword
local dy_intr : dword
local dy_frac : dword
local dy_acc : dword
local dx_frac : dword
local counter_x : dword
local counter_y : dword
local remap_counter :dword
local entry : dword
;*===================================================================
;* Check for scale error when to or from size 0,0
;*===================================================================
cmp [dst_width],0
je ??all_done
cmp [dst_height],0
je ??all_done
cmp [src_width],0
je ??all_done
cmp [src_height],0
je ??all_done
mov eax , [ src_x ]
mov ebx , [ src_y ]
mov [ src_x0 ] , eax
mov [ src_y0 ] , ebx
add eax , [ src_width ]
add ebx , [ src_height ]
mov [ src_x1 ] , eax
mov [ src_y1 ] , ebx
mov eax , [ dst_x ]
mov ebx , [ dst_y ]
mov [ dst_x0 ] , eax
mov [ dst_y0 ] , ebx
add eax , [ dst_width ]
add ebx , [ dst_height ]
mov [ dst_x1 ] , eax
mov [ dst_y1 ] , ebx
; Clip Source Rectangle against source Window boundaries.
mov esi , [ this_object ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register
mov eax , [ src_x0 ]
mov ebx , [ src_x1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register
mov eax , [ src_y0 ]
mov ebx , [ src_y1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
xor cl , 5
xor dl , 5
mov al , cl
test dl , cl
jnz ??all_done
or al , dl
jz ??clip_against_dest
mov bl , dl
test cl , 1000b
jz ??src_left_ok
xor eax , eax
mov [ src_x0 ] , eax
sub eax , [ src_x ]
imul [ dst_width ]
idiv [ src_width ]
add eax , [ dst_x ]
mov [ dst_x0 ] , eax
??src_left_ok:
test cl , 0010b
jz ??src_bottom_ok
xor eax , eax
mov [ src_y0 ] , eax
sub eax , [ src_y ]
imul [ dst_height ]
idiv [ src_height ]
add eax , [ dst_y ]
mov [ dst_y0 ] , eax
??src_bottom_ok:
test bl , 0100b
jz ??src_right_ok
mov eax , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register
mov [ src_x1 ] , eax
sub eax , [ src_x ]
imul [ dst_width ]
idiv [ src_width ]
add eax , [ dst_x ]
mov [ dst_x1 ] , eax
??src_right_ok:
test bl , 0001b
jz ??clip_against_dest
mov eax , [ (GraphicViewPort esi) . GVPHeight ] ; get width into register
mov [ src_y1 ] , eax
sub eax , [ src_y ]
imul [ dst_height ]
idiv [ src_height ]
add eax , [ dst_y ]
mov [ dst_y1 ] , eax
; Clip destination Rectangle against source Window boundaries.
??clip_against_dest:
mov esi , [ dest ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register
mov eax , [ dst_x0 ]
mov ebx , [ dst_x1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register
mov eax , [ dst_y0 ]
mov ebx , [ dst_y1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
xor cl , 5
xor dl , 5
mov al , cl
test dl , cl
jnz ??all_done
or al , dl
jz ??do_scaling
mov bl , dl
test cl , 1000b
jz ??dst_left_ok
xor eax , eax
mov [ dst_x0 ] , eax
sub eax , [ dst_x ]
imul [ src_width ]
idiv [ dst_width ]
add eax , [ src_x ]
mov [ src_x0 ] , eax
??dst_left_ok:
test cl , 0010b
jz ??dst_bottom_ok
xor eax , eax
mov [ dst_y0 ] , eax
sub eax , [ dst_y ]
imul [ src_height ]
idiv [ dst_height ]
add eax , [ src_y ]
mov [ src_y0 ] , eax
??dst_bottom_ok:
test bl , 0100b
jz ??dst_right_ok
mov eax , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register
mov [ dst_x1 ] , eax
sub eax , [ dst_x ]
imul [ src_width ]
idiv [ dst_width ]
add eax , [ src_x ]
mov [ src_x1 ] , eax
??dst_right_ok:
test bl , 0001b
jz ??do_scaling
mov eax , [ (GraphicViewPort esi) . GVPHeight ] ; get width into register
mov [ dst_y1 ] , eax
sub eax , [ dst_y ]
imul [ src_height ]
idiv [ dst_height ]
add eax , [ src_y ]
mov [ src_y1 ] , eax
??do_scaling:
cld
mov ebx , [ this_object ]
mov esi , [ (GraphicViewPort ebx) . GVPOffset ]
mov eax , [ (GraphicViewPort ebx) . GVPXAdd ]
add eax , [ (GraphicViewPort ebx) . GVPWidth ]
add eax , [ (GraphicViewPort ebx) . GVPPitch ]
mov [ src_win_width ] , eax
mul [ src_y0 ]
add esi , [ src_x0 ]
add esi , eax
mov ebx , [ dest ]
mov edi , [ (GraphicViewPort ebx) . GVPOffset ]
mov eax , [ (GraphicViewPort ebx) . GVPXAdd ]
add eax , [ (GraphicViewPort ebx) . GVPWidth ]
add eax , [ (GraphicViewPort ebx) . GVPPitch ]
mov [ dst_win_width ] , eax
mul [ dst_y0 ]
add edi , [ dst_x0 ]
add edi , eax
mov eax , [ src_height ]
xor edx , edx
mov ebx , [ dst_height ]
idiv [ dst_height ]
imul eax , [ src_win_width ]
neg ebx
mov [ dy_intr ] , eax
mov [ dy_frac ] , edx
mov [ dy_acc ] , ebx
mov eax , [ src_width ]
xor edx , edx
shl eax , 16
idiv [ dst_width ]
xor edx , edx
shld edx , eax , 16
shl eax , 16
mov ecx , [ dst_y1 ]
mov ebx , [ dst_x1 ]
sub ecx , [ dst_y0 ]
jle ??all_done
sub ebx , [ dst_x0 ]
jle ??all_done
mov [ counter_y ] , ecx
cmp [ trans ] , 0
jnz ??transparency
cmp [ remap ] , 0
jnz ??normal_remap
; *************************************************************************
; normal scale
mov ecx , ebx
and ecx , 01fh
lea ecx , [ ecx + ecx * 2 ]
shr ebx , 5
neg ecx
mov [ counter_x ] , ebx
lea ecx , [ ??ref_point + ecx + ecx * 2 ]
mov [ entry ] , ecx
??outter_loop:
push esi
push edi
xor ecx , ecx
mov ebx , [ counter_x ]
jmp [ entry ]
??inner_loop:
REPT 32
mov cl , [ esi ]
add ecx , eax
adc esi , edx
mov [ edi ] , cl
inc edi
ENDM
??ref_point:
dec ebx
jge ??inner_loop
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??skip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??skip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??outter_loop
ret
; *************************************************************************
; normal scale with remap
??normal_remap:
mov ecx , ebx
mov [ dx_frac ], eax
and ecx , 01fh
mov eax , [ remap ]
shr ebx , 5
imul ecx , - 13
mov [ counter_x ] , ebx
lea ecx , [ ??remapref_point + ecx ]
mov [ entry ] , ecx
??remapoutter_loop:
mov ebx , [ counter_x ]
push esi
mov [ remap_counter ] , ebx
push edi
xor ecx , ecx
xor ebx , ebx
jmp [ entry ]
??remapinner_loop:
REPT 32
mov bl , [ esi ]
add ecx , [ dx_frac ]
adc esi , edx
mov cl , [ eax + ebx ]
mov [ edi ] , cl
inc edi
ENDM
??remapref_point:
dec [ remap_counter ]
jge ??remapinner_loop
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??remapskip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??remapskip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??remapoutter_loop
ret
;****************************************************************************
; scale with trnsparency
??transparency:
cmp [ remap ] , 0
jnz ??trans_remap
; *************************************************************************
; normal scale with transparency
mov ecx , ebx
and ecx , 01fh
imul ecx , -13
shr ebx , 5
mov [ counter_x ] , ebx
lea ecx , [ ??trans_ref_point + ecx ]
mov [ entry ] , ecx
??trans_outter_loop:
xor ecx , ecx
push esi
push edi
mov ebx , [ counter_x ]
jmp [ entry ]
??trans_inner_loop:
REPT 32
local trans_pixel
mov cl , [ esi ]
test cl , cl
jz trans_pixel
mov [ edi ] , cl
trans_pixel:
add ecx , eax
adc esi , edx
inc edi
ENDM
??trans_ref_point:
dec ebx
jge ??trans_inner_loop
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??trans_skip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??trans_skip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??trans_outter_loop
ret
; *************************************************************************
; normal scale with remap
??trans_remap:
mov ecx , ebx
mov [ dx_frac ], eax
and ecx , 01fh
mov eax , [ remap ]
shr ebx , 5
imul ecx , - 17
mov [ counter_x ] , ebx
lea ecx , [ ??trans_remapref_point + ecx ]
mov [ entry ] , ecx
??trans_remapoutter_loop:
mov ebx , [ counter_x ]
push esi
mov [ remap_counter ] , ebx
push edi
xor ecx , ecx
xor ebx , ebx
jmp [ entry ]
??trans_remapinner_loop:
REPT 32
local trans_pixel
mov bl , [ esi ]
test bl , bl
jz trans_pixel
mov cl , [ eax + ebx ]
mov [ edi ] , cl
trans_pixel:
add ecx , [ dx_frac ]
adc esi , edx
inc edi
ENDM
??trans_remapref_point:
dec [ remap_counter ]
jge ??trans_remapinner_loop
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??trans_remapskip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??trans_remapskip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??trans_remapoutter_loop
ret
??all_done:
ret
endp
END

View File

@@ -0,0 +1,210 @@
;
; 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/>.
;
; $Header: g:/library/source/rcs/./shadow.asm 1.9 1994/05/20 15:30:49 joe_bostic Exp $
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : LIBRARY *
;* *
;* File Name : SHADOW.ASM *
;* *
;* Programmer : Christopher Yates *
;* *
;* Last Update : February 28, 1995 [BG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* *
;* void Shadow_Blit(int xpix, int ypix, int width, int height, GVPC src, GVPC dst, void *shadowbuff);
;* *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
INCLUDE ".\keystruc.inc"
GLOBAL C Shadow_Blit : NEAR
GLOBAL C RealModePtr : DWORD
GLOBAL C Hide_Mouse : NEAR
GLOBAL C Show_Mouse : NEAR
CODESEG
; void Shadow_Blit(int xpix, int ypix, int width, int height, GVPC src, VBC dst, void *shadowbuff);
; Warning: Shadow_Blit appears to be relatively stupid, in that while it is
; optimized to perform word or dword blits, it only does so if the
; entire region is word or dword-sized. In other words, if you blit
; a region that is 200 pixels wide (clearly dword-sized), then it
; will use the dword loop. However, if you blit a region that is
; 201 pixels wide, the dumb thing will use the byte loop for the
; entire blit.
PROC Shadow_Blit C near
USES eax,ebx,ecx,edx,esi,edi
ARG x:DWORD
ARG y:DWORD
ARG region_width:DWORD
ARG region_height:DWORD
ARG srcpage:DWORD
ARG dstpage:DWORD
ARG shadow:DWORD
LOCAL modulo:DWORD ; Row modulo
LOCAL hidemouse:DWORD ; Was the mouse hidden?
LOCAL dwordwidth:DWORD
LOCAL bytewidth:DWORD
cld ; Always move forward.
mov [hidemouse],0 ; Presume mouse hasn't been hidden.
; Fetch the segment of the seenpage.
mov ebx,[dstpage]
mov ebx,[(GraphicViewPort ebx).GVPOffset]
; Determine if the mouse needs to be hidden at all. If this happens to be
; a shadow blit to non visible page (who knows why!?) then don't bother to
; hide the mouse since it isn't necessary.
; cmp ebx,0A0000h
; setne [BYTE PTR hidemouse] ; Flag that mouse need not be hidden.
; jne short ??itsok
mov esi,[RealModePtr]
cmp [(KeyboardType esi).MState],0
je short ??itsok
mov [hidemouse],1
call Hide_Mouse C ; Hides mouse again (just to be sure).
??itsok:
mov edi,[srcpage]
mov esi,[(GraphicViewPort edi).GVPOffset]
mov eax,[(GraphicViewPort edi).GVPWidth]
add eax,[(GraphicViewPort edi).GVPXAdd]
add eax,[(GraphicViewPort edi).GVPPitch]
push eax ; save width+xadd for later calc
mov edx,[y]
mul edx
add eax,[x]
add esi,eax
; At this point, esi points to the source page and ebx points to the dest page
sub ebx,esi ; esi+ebx == dest page pointer
mov edi,[shadow] ; EDI points to shadow buffer.
mov ecx,[region_height] ; get the height of the window in cx
mov edx,[RealModePtr]
; Calculate the row add module.
pop eax ; restore width+xadd
sub eax,[region_width]
mov [modulo],eax
mov eax,[region_width]
shr eax,2
mov [dwordwidth],eax
mov eax,[region_width]
and eax,3
mov [bytewidth],eax
;---------------------------------------
; DOUBLE WORD shadow blit if possible.
;---------------------------------------
??dloop_top:
push ecx
mov ecx,[dwordwidth]
??lcontinue:
repe cmpsd ; check the entire row for changed longs
je short ??loop_top
; If this row would interfere with the mouse image, then hide it.
cmp [hidemouse],0
jnz short ??dok
mov eax,[(KeyboardType edx).MouseY]
sub eax,[(KeyboardType edx).MouseYHot]
cmp eax,[y]
jg short ??dok
add eax,[(KeyboardType edx).MouseHeight]
cmp eax,[y]
jb short ??dok
mov [hidemouse],1 ; Manual hide of the mouse.
call Hide_Mouse C
??dok:
mov eax,[esi-4]
mov [ebx+esi-4],eax ; Update destination page.
mov [edi-4],eax ; Update shadow buffer.
or ecx,ecx
jne short ??lcontinue
;---------------------------------------
; Row loop start for BYTES.
;---------------------------------------
??loop_top:
mov ecx,[bytewidth]
; Column loop start -- by bytes.
??continue:
repe cmpsb ; check the entire row for changed longs
je short ??done_x
; If this row would interfere with the mouse image, then hide it.
cmp [hidemouse],0
jnz short ??bok
mov eax,[(KeyboardType edx).MouseY]
sub eax,[(KeyboardType edx).MouseYHot]
cmp eax,[y]
jg short ??bok
add eax,[(KeyboardType edx).MouseHeight]
cmp eax,[y]
jl short ??bok
mov [hidemouse],1 ; Manual hide of the mouse.
call Hide_Mouse C
??bok:
mov al,[esi-1]
mov [ebx+esi-1],al ; Update destination page.
mov [edi-1],al ; Update shadow buffer.
or ecx,ecx
jne short ??continue
??done_x:
inc [y]
add esi,[modulo]
pop ecx
dec ecx
jnz ??dloop_top
??fini:
; Re show the mouse if it was hidden by this routine.
cmp [hidemouse],0
je short ??reallyfini
call Show_Mouse C
??reallyfini:
ret
ENDP Shadow_Blit
END

600
WIN32LIB/DRAWBUFF/STAMP.ASM Normal file
View File

@@ -0,0 +1,600 @@
;
; 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 : STAMP.ASM *
;* *
;* Programmer : Joe L. Bostic *
;* *
;* Start Date : August 23, 1993 *
;* *
;* Last Update : August 23, 1993 [JLB] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
INCLUDE "stamp.inc"
global C Init_Stamps:near
global LastIconset:dword
global MapPtr:dword
global IconCount:dword
global IconSize:dword
global StampPtr:dword
DATASEG
LastIconset DD 0 ; Pointer to last iconset initialized.
StampPtr DD 0 ; Pointer to icon data.
IsTrans DD 0 ; Pointer to transparent icon flag table.
MapPtr DD 0 ; Pointer to icon map.
IconWidth DD 0 ; Width of icon in pixels.
IconHeight DD 0 ; Height of icon in pixels.
IconSize DD 0 ; Number of bytes for each icon data.
IconCount DD 0 ; Number of icons in the set.
EVEN
CODESEG
GLOBAL C Buffer_Draw_Stamp:near
GLOBAL C Buffer_Draw_Stamp_Clip:near
; 256 color icon system.
;***********************************************************
; INIT_STAMPS
;
; VOID cdecl Init_Stamps(VOID *icondata);
;
; This routine initializes the stamp data.
; Bounds Checking: NONE
;
;*
PROC Init_Stamps C near USES eax ebx edx edi
ARG icondata:DWORD
; Verify legality of parameter.
cmp [icondata],0
je short ??fini
; Don't initialize if already initialized to this set (speed reasons).
mov edi,[icondata]
cmp [LastIconset],edi
je short ??fini
mov [LastIconset],edi
; Record number of icons in set.
movzx eax,[(IControl_Type edi).Count]
mov [IconCount],eax
; Record width of icon.
movzx eax,[(IControl_Type edi).Width]
mov [IconWidth],eax
; Record height of icon.
movzx ebx,[(IControl_Type edi).Height]
mov [IconHeight],ebx
; Record size of icon (in bytes).
mul ebx
mov [IconSize],eax
; Record hard pointer to icon map data.
mov eax,[(IControl_Type edi).Map]
add eax,edi
mov [MapPtr],eax
??nomap:
; Record hard pointer to icon data.
mov eax,edi
add eax,[(IControl_Type edi).Icons]
mov [StampPtr],eax
; Record the transparent table.
mov eax,edi
add eax,[(IControl_Type edi).TransFlag]
mov [IsTrans],eax
??fini:
ret
ENDP Init_Stamps
;***********************************************************
;***********************************************************
; DRAW_STAMP
;
; VOID cdecl Buffer_Draw_Stamp(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap);
;
; This routine renders the icon at the given coordinate.
;
; The remap table is a 256 byte simple pixel translation table to use when
; drawing the icon. Transparency check is performed AFTER the remap so it is possible to
; remap valid colors to be invisible (for special effect reasons).
; This routine is fastest when no remap table is passed in.
;*
PROC Buffer_Draw_Stamp C near
ARG this_object:DWORD ; this is a member function
ARG icondata:DWORD ; Pointer to icondata.
ARG icon:DWORD ; Icon number to draw.
ARG x_pixel:DWORD ; X coordinate of icon.
ARG y_pixel:DWORD ; Y coordinate of icon.
ARG remap:DWORD ; Remap table.
LOCAL modulo:DWORD ; Modulo to get to next row.
LOCAL iwidth:DWORD ; Icon width (here for speedy access).
LOCAL doremap:BYTE ; Should remapping occur?
pushad
cmp [icondata],0
je ??out
; Initialize the stamp data if necessary.
mov eax,[icondata]
cmp [LastIconset],eax
je short ??noreset
call Init_Stamps C,eax
??noreset:
; Determine if the icon number requested is actually in the set.
; Perform the logical icon to actual icon number remap if necessary.
mov ebx,[icon]
cmp [MapPtr],0
je short ??notmap
mov edi,[MapPtr]
mov bl,[edi+ebx]
??notmap:
cmp ebx,[IconCount]
jae ??out
mov [icon],ebx ; Updated icon number.
; If the remap table pointer passed in is NULL, then flag this condition
; so that the faster (non-remapping) icon draw loop will be used.
cmp [remap],0
setne [doremap]
; Get pointer to position to render icon. EDI = ptr to destination page.
mov ebx,[this_object]
mov edi,[(GraphicViewPort ebx).GVPOffset]
mov eax,[(GraphicViewPort ebx).GVPWidth]
add eax,[(GraphicViewPort ebx).GVPXAdd]
add eax,[(GraphicViewPort ebx).GVPPitch]
push eax ; save viewport full width for lower
mul [y_pixel]
add edi,eax
add edi,[x_pixel]
; Determine row modulo for advancing to next line.
pop eax ; retrieve viewport width
sub eax,[IconWidth]
mov [modulo],eax
; Setup some working variables.
mov ecx,[IconHeight] ; Row counter.
mov eax,[IconWidth]
mov [iwidth],eax ; Stack copy of byte width for easy BP access.
; Fetch pointer to start of icon's data. ESI = ptr to icon data.
mov eax,[icon]
mul [IconSize]
mov esi,[StampPtr]
add esi,eax
; Determine whether simple icon draw is sufficient or whether the
; extra remapping icon draw is needed.
cmp [BYTE PTR doremap],0
je short ??istranscheck
;************************************************************
; Complex icon draw -- extended remap.
; EBX = Palette pointer (ready for XLAT instruction).
; EDI = Pointer to icon destination in page.
; ESI = Pointer to icon data.
; ECX = Number of pixel rows.
;;; mov edx,[remap]
mov ebx,[remap]
xor eax,eax
??xrowloop:
push ecx
mov ecx,[iwidth]
??xcolumnloop:
lodsb
;;; mov ebx,edx
;;; add ebx,eax
;;; mov al,[ebx] ; New real color to draw.
xlatb
or al,al
jz short ??xskip1 ; Transparency skip check.
mov [edi],al
??xskip1:
inc edi
loop ??xcolumnloop
pop ecx
add edi,[modulo]
loop ??xrowloop
jmp short ??out
;************************************************************
; Check to see if transparent or generic draw is necessary.
??istranscheck:
mov ebx,[IsTrans]
add ebx,[icon]
cmp [BYTE PTR ebx],0
jne short ??rowloop
;************************************************************
; Fast non-transparent icon draw routine.
; ES:DI = Pointer to icon destination in page.
; DS:SI = Pointer to icon data.
; CX = Number of pixel rows.
mov ebx,ecx
shr ebx,2
mov edx,[modulo]
mov eax,[iwidth]
shr eax,2
??loop1:
mov ecx,eax
rep movsd
add edi,edx
mov ecx,eax
rep movsd
add edi,edx
mov ecx,eax
rep movsd
add edi,edx
mov ecx,eax
rep movsd
add edi,edx
dec ebx
jnz ??loop1
jmp short ??out
;************************************************************
; Transparent icon draw routine -- no extended remap.
; ES:DI = Pointer to icon destination in page.
; DS:SI = Pointer to icon data.
; CX = Number of pixel rows.
??rowloop:
push ecx
mov ecx,[iwidth]
??columnloop:
lodsb
or al,al
jz short ??skip1 ; Transparency check.
mov [edi],al
??skip1:
inc edi
loop ??columnloop
pop ecx
add edi,[modulo]
loop ??rowloop
; Cleanup and exit icon drawing routine.
??out:
popad
ret
ENDP Buffer_Draw_Stamp
;***********************************************************
; DRAW_STAMP_CLIP
;
; VOID cdecl MCGA_Draw_Stamp_Clip(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap, LONG min_x, LONG min_y, LONG max_x, LONG max_y);
;
; This routine renders the icon at the given coordinate.
;
; The remap table is a 256 byte simple pixel translation table to use when
; drawing the icon. Transparency check is performed AFTER the remap so it is possible to
; remap valid colors to be invisible (for special effect reasons).
; This routine is fastest when no remap table is passed in.
;*
PROC Buffer_Draw_Stamp_Clip C near
ARG this_object:DWORD ; this is a member function
ARG icondata:DWORD ; Pointer to icondata.
ARG icon:DWORD ; Icon number to draw.
ARG x_pixel:DWORD ; X coordinate of icon.
ARG y_pixel:DWORD ; Y coordinate of icon.
ARG remap:DWORD ; Remap table.
ARG min_x:DWORD ; Clipping rectangle boundary
ARG min_y:DWORD ; Clipping rectangle boundary
ARG max_x:DWORD ; Clipping rectangle boundary
ARG max_y:DWORD ; Clipping rectangle boundary
LOCAL modulo:DWORD ; Modulo to get to next row.
LOCAL iwidth:DWORD ; Icon width (here for speedy access).
LOCAL skip:DWORD ; amount to skip per row of icon data
LOCAL doremap:BYTE ; Should remapping occur?
pushad
cmp [icondata],0
je ??out2
; Initialize the stamp data if necessary.
mov eax,[icondata]
cmp [LastIconset],eax
je short ??noreset2
call Init_Stamps C,eax
??noreset2:
; Determine if the icon number requested is actually in the set.
; Perform the logical icon to actual icon number remap if necessary.
mov ebx,[icon]
cmp [MapPtr],0
je short ??notmap2
mov edi,[MapPtr]
mov bl,[edi+ebx]
??notmap2:
cmp ebx,[IconCount]
jae ??out2
mov [icon],ebx ; Updated icon number.
; Setup some working variables.
mov ecx,[IconHeight] ; Row counter.
mov eax,[IconWidth]
mov [iwidth],eax ; Stack copy of byte width for easy BP access.
; Fetch pointer to start of icon's data. ESI = ptr to icon data.
mov eax,[icon]
mul [IconSize]
mov esi,[StampPtr]
add esi,eax
; Update the clipping window coordinates to be valid maxes instead of width & height
; , and change the coordinates to be window-relative
mov ebx,[min_x]
add [max_x],ebx
add [x_pixel],ebx ; make it window-relative
mov ebx,[min_y]
add [max_y],ebx
add [y_pixel],ebx ; make it window-relative
; See if the icon is within the clipping window
; First, verify that the icon position is less than the maximums
mov ebx,[x_pixel]
cmp ebx,[max_x]
jge ??out2
mov ebx,[y_pixel]
cmp ebx,[max_y]
jge ??out2
; Now verify that the icon position is >= the minimums
add ebx,[IconHeight]
cmp ebx,[min_y]
jle ??out2
mov ebx,[x_pixel]
add ebx,[IconWidth]
cmp ebx,[min_x]
jle ??out2
; Now, clip the x, y, width, and height variables to be within the
; clipping rectangle
mov ebx,[x_pixel]
cmp ebx,[min_x]
jge ??nominxclip
; x < minx, so must clip
mov ebx,[min_x]
sub ebx,[x_pixel]
add esi,ebx ; source ptr += (minx - x)
sub [iwidth],ebx ; icon width -= (minx - x)
mov ebx,[min_x]
mov [x_pixel],ebx
??nominxclip:
mov eax,[IconWidth]
sub eax,[iwidth]
mov [skip],eax
; Check for x+width > max_x
mov eax,[x_pixel]
add eax,[iwidth]
cmp eax,[max_x]
jle ??nomaxxclip
; x+width is greater than max_x, so must clip width down
mov eax,[iwidth] ; eax = old width
mov ebx,[max_x]
sub ebx,[x_pixel]
mov [iwidth],ebx ; iwidth = max_x - xpixel
sub eax,ebx
add [skip],eax ; skip += (old width - iwidth)
??nomaxxclip:
; check if y < miny
mov eax,[min_y]
cmp eax,[y_pixel] ; if(miny <= y_pixel), no clip needed
jle ??nominyclip
sub eax,[y_pixel]
sub ecx,eax ; height -= (miny - y)
mul [IconWidth]
add esi,eax ; icon source ptr += (width * (miny - y))
mov eax,[min_y]
mov [y_pixel],eax ; y = miny
??nominyclip:
; check if (y+height) > max y
mov eax,[y_pixel]
add eax,ecx
cmp eax,[max_y] ; if (y + height <= max_y), no clip needed
jle ??nomaxyclip
mov ecx,[max_y] ; height = max_y - y_pixel
sub ecx,[y_pixel]
??nomaxyclip:
; If the remap table pointer passed in is NULL, then flag this condition
; so that the faster (non-remapping) icon draw loop will be used.
cmp [remap],0
setne [doremap]
; Get pointer to position to render icon. EDI = ptr to destination page.
mov ebx,[this_object]
mov edi,[(GraphicViewPort ebx).GVPOffset]
mov eax,[(GraphicViewPort ebx).GVPWidth]
add eax,[(GraphicViewPort ebx).GVPXAdd]
add eax,[(GraphicViewPort ebx).GVPPitch]
push eax ; save viewport full width for lower
mul [y_pixel]
add edi,eax
add edi,[x_pixel]
; Determine row modulo for advancing to next line.
pop eax ; retrieve viewport width
sub eax,[iwidth]
mov [modulo],eax
; Determine whether simple icon draw is sufficient or whether the
; extra remapping icon draw is needed.
cmp [BYTE PTR doremap],0
je short ??istranscheck2
;************************************************************
; Complex icon draw -- extended remap.
; EBX = Palette pointer (ready for XLAT instruction).
; EDI = Pointer to icon destination in page.
; ESI = Pointer to icon data.
; ECX = Number of pixel rows.
mov ebx,[remap]
xor eax,eax
??xrowloopc:
push ecx
mov ecx,[iwidth]
??xcolumnloopc:
lodsb
xlatb
or al,al
jz short ??xskip1c ; Transparency skip check.
mov [edi],al
??xskip1c:
inc edi
loop ??xcolumnloopc
pop ecx
add edi,[modulo]
add esi,[skip]
loop ??xrowloopc
jmp short ??out2
;************************************************************
; Check to see if transparent or generic draw is necessary.
??istranscheck2:
mov ebx,[IsTrans]
add ebx,[icon]
cmp [BYTE PTR ebx],0
jne short ??rowloopc
;************************************************************
; Fast non-transparent icon draw routine.
; ES:DI = Pointer to icon destination in page.
; DS:SI = Pointer to icon data.
; CX = Number of pixel rows.
mov ebx,ecx
mov edx,[modulo]
mov eax,[iwidth]
;
; Optimise copy by dword aligning the destination
;
??loop1c:
push eax
rept 3
test edi,3
jz ??aligned
movsb
dec eax
jz ??finishedit
endm
??aligned:
mov ecx,eax
shr ecx,2
rep movsd
mov ecx,eax
and ecx,3
rep movsb
??finishedit:
add edi,edx
add esi,[skip]
pop eax
dec ebx
jnz ??loop1c
jmp short ??out2
;************************************************************
; Transparent icon draw routine -- no extended remap.
; ES:DI = Pointer to icon destination in page.
; DS:SI = Pointer to icon data.
; CX = Number of pixel rows.
??rowloopc:
push ecx
mov ecx,[iwidth]
??columnloopc:
lodsb
or al,al
jz short ??skip1c ; Transparency check.
mov [edi],al
??skip1c:
inc edi
loop ??columnloopc
pop ecx
add edi,[modulo]
add esi,[skip]
loop ??rowloopc
; Cleanup and exit icon drawing routine.
??out2:
popad
ret
ENDP Buffer_Draw_Stamp_Clip
END

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/>.
;
; This is the control structure at the start of a loaded icon set. It must match
; the structure in ICONSET.C! This structure MUST be a multiple of 16 bytes long.
ifdef NO_WAY_THIS_WILL_BE_DEFINED_HAHAHAHA
STRUC IControl_Type
Width DW ? ; Width in pixels (per icon).
Height DW ? ; Height in pixels (per icon).
Count DW ? ; Number of icons in this set.
Allocated DW ? ; Was this iconset allocated?
Size DD ? ; Size of entire iconset memory block.
Icons DD ? ; Offset from buffer start to icon data.
Palettes DD ? ; Offset from buffer start to palette data.
Remaps DD ? ; Offset from buffer start to remap index data.
TransFlag DD ? ; Offset for transparency flag data.
Map DD ? ; Icon map offset.
ENDS
else
STRUC IControl_Type
Width DW ? ; Width in pixels (per icon).
Height DW ? ; Height in pixels (per icon).
Count DW ? ; Number of icons in this set.
Allocated DW ? ; Was this iconset allocated?
MapWidth DW ?
MapHeight DW ?
Size DD ? ; Size of entire iconset memory block.
Icons DD ? ; Offset from buffer start to icon data.
Palettes DD ? ; Offset from buffer start to palette data.
Remaps DD ? ; Offset from buffer start to remap index data.
TransFlag DD ? ; Offset for transparency flag data.
ColorMap DD ?
Map DD ? ; Icon map offset.
ENDS
endif
ICON256 EQU 1

View File

@@ -0,0 +1,284 @@
;
; 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 : STAMP.ASM *
;* *
;* Programmer : Joe L. Bostic *
;* *
;* Start Date : August 23, 1993 *
;* *
;* Last Update : August 23, 1993 [JLB] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
JUMPS
MAX_CACHED_ICONS=300
ICON_WIDTH =24
ICON_HEIGHT =24
MAX_ICON_SETS =100
global C IconPointers:dword
global C Init_Stamps:near
global C IconCacheLookup:word
global LastIconset:dword
global MapPtr:dword
global IconCount:dword
global IconSize:dword
global StampPtr:dword
global IconEntry:dword
global IconData:dword
global Clear_Icon_Pointers_:near
global Cache_Copy_Icon_:near
global Is_Icon_Cached_:near
global Get_Icon_Index_:near
global Get_Free_Index_:near
global Cache_New_Icon_:near
global Is_Stamp_Registered_:near
global Get_Free_Cache_Slot_:near
struc IconSetType
IconSetPtr dd ?
IconListOffset dd ?
ends
global C IconSetList:IconSetType
codeseg
;************************************************************************************************
;* Cache_Copy_Icon -- copy an icon to its video memory cache *
;* *
;* *
;* INPUT: eax - ptr to icon_data *
;* edx - ptr to video surface *
;* ebx - pitch of video surface *
;* *
;* OUTPUT: none *
;* *
;* PROTO: extern "C" Cache_Copy_Icon (void const *icon_ptr , *
;* VideoSurfaceDescription.lpSurface , *
;* VideoSurfaceDescription.lPitch); *
;* *
;* HISTORY: *
;* 11/8/95 3:16PM ST: Created *
;*==============================================================================================*
proc Cache_Copy_Icon_ near
pushad
mov esi,eax
mov edi,edx
sub ebx,ICON_WIDTH
mov dl,ICON_HEIGHT ;icon height
??each_line_lp: mov ecx,ICON_WIDTH/4
rep movsd
lea edi,[edi+ebx]
dec dl
jnz ??each_line_lp
popad
ret
endp Cache_Copy_Icon_
;************************************************************************************************
;* Is_Icon_Cached -- has an icon been cached? If not, is it cacheable? *
;* *
;* *
;* INPUT: eax - ptr to icon_data *
;* edx - icon number *
;* *
;* OUTPUT: eax - index of cached icon or -1 if not cached *
;* *
;* PROTO: extern "C" int Is_Icon_Cached (void const *icon_data , int icon); *
;* *
;* HISTORY: *
;* 11/8/95 2:16PM ST: Created *
;*==============================================================================================*
proc Is_Icon_Cached_ near
mov [IconData],eax ;save the icon data ptr for later
push edx
test eax,eax
je ??out
; Initialize the stamp data if necessary.
cmp [LastIconset],eax
je short ??noreset
call Init_Stamps C,eax
; Determine if the icon number requested is actually in the set.
; Perform the logical icon to actual icon number remap if necessary.
??noreset: cmp [MapPtr],0
je short ??notmap
push edi
mov edi,[MapPtr]
mov dl,[edi+edx]
pop edi
??notmap: cmp edx,[IconCount]
jl ??in_range
pop edx
mov eax,-1
ret
; See if the stamp is registered - if not then it cant be cached
??in_range: mov eax,[IconData]
call Is_Stamp_Registered_
cmp eax,-1
jnz ??got_entry
pop edx
ret
; Stamp is registered - if its cached already then just return the index
??got_entry: mov eax,[(IconSetType eax).IconListOffset]
cmp [word eax+edx*2+IconCacheLookup],-1
jz ??not_cached
; it is cached and [eax+edx] is the index
movzx eax,[word eax+edx*2+IconCacheLookup]
pop edx
ret
;
; The stamps set is registered but we havn't seen this stamp before
; so try caching it
;
??not_cached: mov [IconEntry],eax
add [IconEntry],edx
add [IconEntry],edx
call Get_Free_Cache_Slot_
test eax,eax
jge ??got_free_slot
pop edx ;eax is -1 here anyway
ret
; We found a free caching slot so try caching the stamp into it
??got_free_slot:imul edx,[IconSize]
add edx,[StampPtr]
push eax
call Cache_New_Icon_ ;takes icon index in eax, ptr to icon in edx
test eax,eax
jz ??cache_failed
; Success! Add the index into the table
pop eax
mov edx,[IconEntry]
mov [edx+IconCacheLookup],ax
and eax,0ffffh
pop edx
ret
; Couldnt cache the new Icon - return -1 to say icon isnt cached
??cache_failed: pop eax
??out: pop edx
mov eax,-1
ret
endp Is_Icon_Cached_
;************************************************************************************************
;* Is_Stamp_Registered -- has an icon's set been previously registered? *
;* *
;* *
;* INPUT: eax - ptr to icon_data *
;* *
;* OUTPUT: eax - ptr to registration entry or -1 if not registered *
;* *
;* PROTO: extern "C" int Is_Stamp_Registered (void const *icon_data); *
;* *
;* HISTORY: *
;* 11/10/95 10:00AM ST: Created *
;*==============================================================================================*
proc Is_Stamp_Registered_
push edi
push ecx
mov edi,offset IconSetList
mov ecx,MAX_ICON_SETS
??each_set_lp: cmp eax,[edi]
jz ??got_icon_set
add edi,size IconSetType
dec ecx
jnz ??each_set_lp
mov eax,-1
pop ecx
pop edi
ret
??got_icon_set: mov eax,edi
pop ecx
pop edi
ret
endp Is_Stamp_Registered_
dataseg
IconEntry dd 0 ;Temporary pointer to icon index entry in table
IconData dd 0 ;Temporary ptr to icon set data
end

View File

@@ -0,0 +1,101 @@
;
; 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 : Calculate size of an MCGA region *
;* *
;* File Name : REGIONSZ.ASM *
;* *
;* Programmer : Barry W. Green *
;* *
;* Start Date : March 1, 1995 *
;* *
;* Last Update : March 1, 1995 [BWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* VVPC::Size_Of_Region - calculate graphic buffer region size *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
GLOBAL Buffer_Size_Of_Region : NEAR
CODESEG
;***************************************************************************
;* VVPC::Size_Of_Region - calculate buffer region size *
;* *
;* INPUT: DWORD the width of the region *
;* *
;* DWORD the height of the region *
;* *
;* OUTPUT: calculated size of the region (size = width * height) *
;* *
;* *
;* HISTORY: *
;* 03/01/1995 BWG : Created. *
;*=========================================================================*
PROC Buffer_Size_Of_Region C near
USES ebx,ecx,edx
ARG this_object:DWORD ; this is a member function
ARG region_width:DWORD ; width of region
ARG region_height:DWORD ; height of region
;*===================================================================
; Get the viewport information
;*===================================================================
mov ebx,[this_object] ; get a pointer to viewport
xor eax,eax
mov ecx,[(GraphicViewPort ebx).GVPHeight] ; ecx = height of viewport
mov edx,[(GraphicViewPort ebx).GVPWidth] ; edx = width of viewport
;*===================================================================
; Verify that the width is legal
;*===================================================================
mov eax,[region_width] ; find the width
cmp eax,edx ; is it too wide?
jb short ??wok ; if not, leave it alone
mov eax,edx ; otherwise clip it
;*===================================================================
; Verify that the height is ok
;*===================================================================
??wok: mov ebx,[region_height] ; get the height
cmp ebx,ecx ; is it too tall?
jb ??hok ; if not, leave it alone
mov ebx,ecx ; otherwise clip it
;*===================================================================
; Now multiply 'em to calculate the size of the region
;*===================================================================
??hok: mul ebx ; size = w * h
ret
ENDP Buffer_Size_Of_Region
END

View File

@@ -0,0 +1,14 @@
IMPORTS
DirectDrawCreate=DDRAW.DirectDrawCreate
DirectSoundCreate=DSOUND.DirectSoundCreate
DirectPlayEnumerate=DPLAY.DirectPlayEnumerate
DirectPlayCreate=DPLAY.DirectPlayCreate

View File

@@ -0,0 +1,183 @@
#
# 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 .EXE makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 20, 1995 *
#* *
#* Last Update : *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WWFLAT path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the executable program you're building *
#* PROJ_LIBS = Westwood libraries to link your EXE to *
#* OBJECTS = list of objects in your current working directory *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .xxx: = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef %WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef %WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef %WATCOM
!error WATCOM Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
#---------------------------------------------------------------------------
# PROJ_NAME = library name
# PROJ_DIR = directory containing source & objects
#---------------------------------------------------------------------------
PROJ_NAME = TEST
PROJ_DIR = $(%WIN32LIB)\drawbuff\TEST
LIB_DIR = $(%WIN32LIB)\lib
!include $(%WIN32LIB)\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = &
$(PROJ_NAME).obj &
testasm.obj
CPS_FILES = &
test1.cps &
test2.cps
PROJ_LIBS = &
drawbuff.lib &
mem.lib &
misc.lib &
iff.lib &
rawfile.lib &
tile.lib &
font.lib &
profile.lib
#PROJ_LIBS = &
# drawbuff.lib &
# win32lib.lib
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.asm: $(PROJ_DIR)
.c: $(PROJ_DIR)
.cpp: $(PROJ_DIR)
.h: $(PROJ_DIR)
.obj: $(PROJ_DIR)
.lib: $(%WIN32LIB)\lib
.exe: $(PROJ_DIR)
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = wcc386
CPP_CMD = wpp386
LIB_CMD = wlib
LINK_CMD = wlink
ASM_CMD = tasm
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR
#---------------------------------------------------------------------------
LIBPATH = $(%WIN32LIB)\LIB;$(%WATCOM)\LIB386\NT
INCLUDEPATH = $(%WIN32LIB)\INCLUDE;$(%WATCOM)\H
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(C_CMD) $(CC_CFG) $<
.cpp.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\$^*.cpp
.asm.obj: $(%WIN32LIB)\project.cfg
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target
#---------------------------------------------------------------------------
all: $(PROJ_NAME).exe
#---------------------------------------------------------------------------
# Build the EXE
#---------------------------------------------------------------------------
$(PROJ_NAME).exe: $(OBJECTS) $(PROJ_NAME).lnk $(PROJ_LIBS) $(CPS_FILES)
$(LINK_CMD) $(LINK_CFG) name $^@ @$(PROJ_NAME).lnk
$(PROJ_LIBS):
echo updating base library $^@
cd ..
wmake
cd $(PROJ_DIR)
$(PROJ_NAME).lnk : $(OBJECTS)
%create $^@
for %index in ($(OBJECTS)) do %append $^@ file %index
for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\%index
%append $^@ library $(LIB_DIR)\ddraw.lib
#**************************** End of makefile ******************************

View File

@@ -0,0 +1,187 @@
#
# 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 .EXE makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 20, 1995 *
#* *
#* Last Update : *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WWFLAT path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the executable program you're building *
#* PROJ_LIBS = Westwood libraries to link your EXE to *
#* OBJECTS = list of objects in your current working directory *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .xxx: = full pathname where various file types live *
#* *
#***************************************************************************
.AUTODEPEND
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef COMPILER
!error COMPILER Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
#---------------------------------------------------------------------------
# PROJ_NAME = library name
# PROJ_DIR = directory containing source & objects
#---------------------------------------------------------------------------
PROJ_NAME = test
PROJ_DIR = $(WIN32LIB)\drawbuff\$(PROJ_NAME)
LIB_DIR = $(WIN32LIB)\lib
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = \
$(PROJ_NAME).obj
CPS_FILES = \
test1.cps \
test2.cps
!if 0
PROJ_LIBS = \
drawbuff.lib \
win32lib.lib
!else
PROJ_LIBS = \
drawbuff.lib \
mem.lib \
misc.lib \
iff.lib \
rawfile.lib \
tile.lib \
font.lib
!endif
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.path.asm = $(PROJ_DIR)
.path.c = $(PROJ_DIR)
.path.cpp = $(PROJ_DIR)
.path.h = $(PROJ_DIR)
.path.obj = $(PROJ_DIR)
.path.lib = $(WIN32LIB)\lib
.path.exe = $(PROJ_DIR)
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = bcc32
CPP_CMD = bcc32
LIB_CMD = tlib
LINK_CMD = tlink32
ASM_CMD = tasm32
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR
#---------------------------------------------------------------------------
LIBPATH = $(WIN32LIB)\LIB;$(COMPILER)\LIB
INCLUDEPATH = $(WIN32LIB)\INCLUDE;$(COMPILER)\INCLUDE
!include $(WIN32LIB)\\project.cfg
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj:
$(C_CMD) $(CC_CFG) $<
.cpp.obj:
$(CPP_CMD) $(CC_CFG) $<
.asm.obj:
$(ASM_CMD) $(ASM_CFG) $<
.lbm.cps:
$(WIN32LIB)\\TOOLS\WWCOMP $*.lbm $*.cps
#---------------------------------------------------------------------------
# Default target
#---------------------------------------------------------------------------
all: $(PROJ_NAME).exe $(CPS_FILES)
#---------------------------------------------------------------------------
# Build the EXE
#---------------------------------------------------------------------------
$(PROJ_NAME).exe: $(OBJECTS) $(PROJ_LIBS)
$(LINK_CMD) @&&|
$(LINK_CFG) +
$(COMPILER)\\LIB\\c0w32.obj+
$(OBJECTS)
$<,$*
$(PROJ_LIBS) +
import32.lib +
cw32i.lib
$*.def
|
$(PROJ_LIBS):
echo updating base library $^@
cd ..
make
cd $(PROJ_DIR)
#**************************** End of makefile ******************************

View File

@@ -0,0 +1,180 @@
#
# 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 .EXE makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 20, 1995 *
#* *
#* Last Update : *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WWFLAT path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the executable program you're building *
#* PROJ_LIBS = Westwood libraries to link your EXE to *
#* OBJECTS = list of objects in your current working directory *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .xxx: = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef %WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef %WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef %WATCOM
!error WATCOM Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
#---------------------------------------------------------------------------
# PROJ_NAME = library name
# PROJ_DIR = directory containing source & objects
#---------------------------------------------------------------------------
PROJ_NAME = TEST
PROJ_DIR = $(%WIN32LIB)\drawbuff\TEST
LIB_DIR = $(%WIN32LIB)\lib
!include $(%WIN32LIB)\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = &
$(PROJ_NAME).obj
CPS_FILES = &
test1.cps &
test2.cps
PROJ_LIBS = &
drawbuff.lib &
mem.lib &
misc.lib &
iff.lib &
rawfile.lib &
tile.lib &
font.lib
#PROJ_LIBS = &
# drawbuff.lib &
# win32lib.lib
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.asm: $(PROJ_DIR)
.c: $(PROJ_DIR)
.cpp: $(PROJ_DIR)
.h: $(PROJ_DIR)
.obj: $(PROJ_DIR)
.lib: $(%WIN32LIB)\lib
.exe: $(PROJ_DIR)
#---------------------------------------------------------------------------
# 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
#---------------------------------------------------------------------------
LIBPATH = $(%WIN32LIB)\LIB;$(%WATCOM)\LIB386\NT
INCLUDEPATH = $(%WIN32LIB)\INCLUDE;$(%WATCOM)\H
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(C_CMD) $(CC_CFG) $<
.cpp.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(CPP_CMD) $(CC_CFG) $<
.asm.obj: $(%WIN32LIB)\project.cfg
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target
#---------------------------------------------------------------------------
all: $(PROJ_NAME).exe
#---------------------------------------------------------------------------
# Build the EXE
#---------------------------------------------------------------------------
$(PROJ_NAME).exe: $(OBJECTS) $(PROJ_NAME).lnk $(PROJ_LIBS) $(CPS_FILES)
$(LINK_CMD) $(LINK_CFG) name $^@ @$(PROJ_NAME).lnk
$(PROJ_LIBS):
echo updating base library $^@
cd ..
wmake
cd $(PROJ_DIR)
$(PROJ_NAME).lnk : $(OBJECTS)
%create $^@
for %index in ($(OBJECTS)) do %append $^@ file %index
for %index in ($(PROJ_LIBS)) do %append $^@ library $(LIB_DIR)\%index
%append $^@ library $(LIB_DIR)\ddraw.lib
#**************************** End of makefile ******************************

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,14 @@
IMPORTS
DirectDrawCreate=DDRAW.DirectDrawCreate
DirectSoundCreate=DSOUND.DirectSoundCreate
DirectPlayEnumerate=DPLAY.DirectPlayEnumerate
DirectPlayCreate=DPLAY.DirectPlayCreate

View File

@@ -0,0 +1,34 @@
/*
** 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/>.
*/
#include "stdio.h"
extern "C" {
void func_1(void);
}
void func_2(void)
{
printf("There\r");
}
void main(void)
{
func_1();
func_2();
}

View File

@@ -0,0 +1,80 @@
;
; 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/>.
;
IDEAL
P386
MODEL USE32 FLAT
jumps
codeseg
masm
;
; Change a DAC colour register directly
;
; register number in al
;
; bh=red bl=green cl=blue
;
set_dac_col proc near
pushad
cli
push eax
mov dx,03dah
in al,dx
jmp @@1
@@1: mov dx,03c8h
pop eax
out dx,al
jmp @@2
@@2: inc dl
mov al,bh
out dx,al
jmp @@3
@@3: mov al,bl
out dx,al
jmp @@4
@@4: mov al,cl
out dx,al
jmp @@5
@@5: sti
popad
ret
set_dac_col endp
ideal
global Set_Palette_Register_:near
proc Set_Palette_Register_ near
pushad
and cl,63
mov bh,dl
and bh,63
and bl,63
call set_dac_col
popad
ret
endp Set_Palette_Register_
end

View File

@@ -0,0 +1,292 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : TOBUFFER.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : June 8, 1994 *
;* Last Update : Feb 10, 1995 [jrj] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* VVC::TOBUFFER -- Copies a virtual viewport to a linear buffer *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
TRANSP equ 0
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
;***************************************************************************
;* VIVC::TOBUFFER -- Copies a virtual viewport to a linear buffer *
;* *
;* INPUT: BYTE * dest - buffer to copy to *
;* size - size of the buffer to copy to *
;* x_pixel - x pixel on viewport to copy from *
;* y_pixel - y pixel on viewport to copy from *
;* pixel_width - the width of copy region *
;* pixel_height - the height of copy region *
;* *
;* OUTPUT: none *
;* *
;* WARNINGS: Coordinates and dimensions will be adjusted if they exceed *
;* the boundaries. In the event that no adjustment is *
;* possible this routine will abort. If the size of the *
;* region to copy exceeds the size passed in for the buffer *
;* the routine will automatically abort. *
;* *
;* HISTORY: *
;* 06/15/1994 PWG : Created. *
;*=========================================================================*
PROC Buffer_To_Buffer C near
USES ebx,ecx,edx,esi,edi
;*===================================================================
;* define the arguements that our function takes.
;*===================================================================
ARG this_object:DWORD ; this is a class member function
ARG x_pixel:DWORD ; Page X pixel coordinate.
ARG y_pixel:DWORD ; Page Y pixel coordinate.
ARG pixel_width:DWORD ; Width of region in pixels.
ARG pixel_height:DWORD ; Height of region in pixels.
ARG dest:DWORD ; the buffer to copy to
ARG buffer_size:DWORD ; the size of the buffer
;*===================================================================
; Define some locals so that we can handle things quickly
;*===================================================================
LOCAL x1_pixel :dword
LOCAL y1_pixel :dword
LOCAL dest_x1 : dword
LOCAL dest_y1 : dword
LOCAL dest_ajust_width:DWORD
LOCAL scr_ajust_width:DWORD
LOCAL dest_area : dword
; Clip dest Rectangle against source Window boundaries.
mov [ dest_x1 ] , 0
mov [ dest_y1 ] , 0
mov esi , [ this_object ] ; get ptr to dest
xor ecx , ecx
xor edx , edx
mov edi , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register
mov ebx , [ x_pixel ]
mov eax , [ x_pixel ]
add ebx , [ pixel_width ]
shld ecx , eax , 1
mov [ x1_pixel ] , ebx
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register
mov ebx , [ y_pixel ]
mov eax , [ y_pixel ]
add ebx , [ pixel_height ]
shld ecx , eax , 1
mov [ y1_pixel ] , ebx
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
xor cl , 5
xor dl , 5
mov al , cl
test dl , cl
jnz ??real_out
or al , dl
jz ??do_blit
test cl , 1000b
jz ??scr_left_ok
mov eax , [ x_pixel ]
neg eax
mov [ x_pixel ] , 0
mov [ dest_x1 ] , eax
??scr_left_ok:
test cl , 0010b
jz ??scr_bottom_ok
mov eax , [ y_pixel ]
neg eax
mov [ y_pixel ] , 0
mov [ dest_y1 ] , eax
??scr_bottom_ok:
test dl , 0100b
jz ??scr_right_ok
mov eax , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register
mov [ x1_pixel ] , eax
??scr_right_ok:
test dl , 0001b
jz ??do_blit
mov eax , [ (GraphicViewPort esi) . GVPHeight ] ; get width into register
mov [ y1_pixel ] , eax
??do_blit:
cld
mov eax , [ (GraphicViewPort esi) . GVPXAdd ]
add eax , [ (GraphicViewPort esi) . GVPWidth ]
add eax , [ (GraphicViewPort esi) . GVPPitch ]
mov esi , [ (GraphicViewPort esi) . GVPOffset ]
mov ecx , eax
mul [ y_pixel ]
add esi , [ x_pixel ]
add esi , eax
add ecx , [ x_pixel ]
sub ecx , [ x1_pixel ]
mov [ scr_ajust_width ] , ecx
mov edi , [ dest ]
mov eax , [ pixel_width ]
sub eax , [ x1_pixel ]
add eax , [ x_pixel ]
mov [ dest_ajust_width ] , eax
mov eax , [ dest_y1 ]
mul [ pixel_width ]
add eax , [ dest_x1 ]
add edi , eax
mov edx , [ y1_pixel ]
mov eax , [ x1_pixel ]
sub edx , [ y_pixel ]
jle ??real_out
sub eax , [ x_pixel ]
jle ??real_out
mov ebx , [ pixel_width ]
imul ebx , edx
cmp ebx , [ buffer_size ]
jg ??real_out
; ********************************************************************
; Forward bitblit only
IF TRANSP
cmp [ transp ] , 0
jnz ??forward_Blit_trans
ENDIF
; the inner loop is so efficient that
; the optimal consept no longer apply because
; the optimal byte have to by a number greather than 9 bytes
cmp eax , 10
jl ??forward_loop_bytes
??forward_loop_dword:
mov ecx , edi
mov ebx , eax
neg ecx
and ecx , 3
sub ebx , ecx
rep movsb
mov ecx , ebx
shr ecx , 2
rep movsd
mov ecx , ebx
and ecx , 3
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_dword
ret
??forward_loop_bytes:
mov ecx , eax
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??forward_loop_bytes
ret
IF TRANSP
??forward_Blit_trans:
mov ecx , eax
and ecx , 01fh
lea ecx , [ ecx + ecx * 4 ]
neg ecx
shr eax , 5
lea ecx , [ ??transp_reference + ecx * 2 ]
mov [ y1_pixel ] , ecx
??forward_loop_trans:
mov ecx , eax
jmp [ y1_pixel ]
??forward_trans_line:
REPT 32
local transp_pixel
mov bl , [ esi ]
test bl , bl
jz transp_pixel
mov [ edi ] , bl
transp_pixel:
inc esi
inc edi
ENDM
??transp_reference:
dec ecx
jge ??forward_trans_line
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_trans
ret
ENDIF
??real_out:
ret
ENDP Buffer_To_Buffer
END

View File

@@ -0,0 +1,294 @@
;
; 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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : TOPAGE.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : June 8, 1994 *
;* *
;* Last Update : June 15, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Buffer_To_Page -- Copies a linear buffer to a virtual viewport *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
TRANSP equ 0
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
CODESEG
;***************************************************************************
;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport *
;* *
;* INPUT: WORD x_pixel - x pixel on viewport to copy from *
;* WORD y_pixel - y pixel on viewport to copy from *
;* WORD pixel_width - the width of copy region *
;* WORD pixel_height - the height of copy region *
;* BYTE * src - buffer to copy from *
;* VVPC * dest - virtual viewport to copy to *
;* *
;* OUTPUT: none *
;* *
;* WARNINGS: Coordinates and dimensions will be adjusted if they exceed *
;* the boundaries. In the event that no adjustment is *
;* possible this routine will abort. If the size of the *
;* region to copy exceeds the size passed in for the buffer *
;* the routine will automatically abort. *
;* *
;* HISTORY: *
;* 06/15/1994 PWG : Created. *
;*=========================================================================*
PROC Buffer_To_Page C near
USES eax,ebx,ecx,edx,esi,edi
;*===================================================================
;* define the arguements that our function takes.
;*===================================================================
ARG x_pixel :DWORD ; x pixel position in source
ARG y_pixel :DWORD ; y pixel position in source
ARG pixel_width :DWORD ; width of rectangle to blit
ARG pixel_height:DWORD ; height of rectangle to blit
ARG src :DWORD ; this is a member function
ARG dest :DWORD ; what are we blitting to
; ARG trans :DWORD ; do we deal with transparents?
;*===================================================================
; Define some locals so that we can handle things quickly
;*===================================================================
LOCAL x1_pixel :dword
LOCAL y1_pixel :dword
local scr_x : dword
local scr_y : dword
LOCAL dest_ajust_width:DWORD
LOCAL scr_ajust_width:DWORD
LOCAL dest_area : dword
cmp [ src ] , 0
jz ??real_out
; Clip dest Rectangle against source Window boundaries.
mov [ scr_x ] , 0
mov [ scr_y ] , 0
mov esi , [ dest ] ; get ptr to dest
xor ecx , ecx
xor edx , edx
mov edi , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register
mov ebx , [ x_pixel ]
mov eax , [ x_pixel ]
add ebx , [ pixel_width ]
shld ecx , eax , 1
mov [ x1_pixel ] , ebx
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register
mov ebx , [ y_pixel ]
mov eax , [ y_pixel ]
add ebx , [ pixel_height ]
shld ecx , eax , 1
mov [ y1_pixel ] , ebx
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
xor cl , 5
xor dl , 5
mov al , cl
test dl , cl
jnz ??real_out
or al , dl
jz ??do_blit
test cl , 1000b
jz ??dest_left_ok
mov eax , [ x_pixel ]
neg eax
mov [ x_pixel ] , 0
mov [ scr_x ] , eax
??dest_left_ok:
test cl , 0010b
jz ??dest_bottom_ok
mov eax , [ y_pixel ]
neg eax
mov [ y_pixel ] , 0
mov [ scr_y ] , eax
??dest_bottom_ok:
test dl , 0100b
jz ??dest_right_ok
mov eax , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register
mov [ x1_pixel ] , eax
??dest_right_ok:
test dl , 0001b
jz ??do_blit
mov eax , [ (GraphicViewPort esi) . GVPHeight ] ; get width into register
mov [ y1_pixel ] , eax
??do_blit:
cld
mov eax , [ (GraphicViewPort esi) . GVPXAdd ]
add eax , [ (GraphicViewPort esi) . GVPWidth ]
add eax , [ (GraphicViewPort esi) . GVPPitch ]
mov edi , [ (GraphicViewPort esi) . GVPOffset ]
mov ecx , eax
mul [ y_pixel ]
add edi , [ x_pixel ]
add edi , eax
add ecx , [ x_pixel ]
sub ecx , [ x1_pixel ]
mov [ dest_ajust_width ] , ecx
mov esi , [ src ]
mov eax , [ pixel_width ]
sub eax , [ x1_pixel ]
add eax , [ x_pixel ]
mov [ scr_ajust_width ] , eax
mov eax , [ scr_y ]
mul [ pixel_width ]
add eax , [ scr_x ]
add esi , eax
mov edx , [ y1_pixel ]
mov eax , [ x1_pixel ]
sub edx , [ y_pixel ]
jle ??real_out
sub eax , [ x_pixel ]
jle ??real_out
; ********************************************************************
; Forward bitblit only
IF TRANSP
test [ trans ] , 1
jnz ??forward_Blit_trans
ENDIF
; the inner loop is so efficient that
; the optimal consept no longer apply because
; the optimal byte have to by a number greather than 9 bytes
cmp eax , 10
jl ??forward_loop_bytes
??forward_loop_dword:
mov ecx , edi
mov ebx , eax
neg ecx
and ecx , 3
sub ebx , ecx
rep movsb
mov ecx , ebx
shr ecx , 2
rep movsd
mov ecx , ebx
and ecx , 3
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_dword
ret
??forward_loop_bytes:
mov ecx , eax
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??forward_loop_bytes
ret
IF TRANSP
??forward_Blit_trans:
mov ecx , eax
and ecx , 01fh
lea ecx , [ ecx + ecx * 4 ]
neg ecx
shr eax , 5
lea ecx , [ ??transp_reference + ecx * 2 ]
mov [ y1_pixel ] , ecx
??forward_loop_trans:
mov ecx , eax
jmp [ y1_pixel ]
??forward_trans_line:
REPT 32
local transp_pixel
mov bl , [ esi ]
inc esi
test bl , bl
jz transp_pixel
mov [ edi ] , bl
transp_pixel:
inc edi
ENDM
??transp_reference:
dec ecx
jge ??forward_trans_line
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_trans
ret
ENDIF
??real_out:
ret
ENDP Buffer_To_Page
END

View File

@@ -0,0 +1,502 @@
;
; 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 : TXTPRNT.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : January 17, 1995 *
;* *
;* Last Update : January 17, 1995 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Buffer_Print -- Assembly Buffer text print routine *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
;*=========================================================================*
;* Extern the font pointer which is defined by the font class *
;*=========================================================================*
GLOBAL C FontPtr:DWORD
GLOBAL C FontXSpacing:DWORD
GLOBAL C FontYSpacing:DWORD
GLOBAL C ColorXlat:BYTE
;*=========================================================================*
;* Define the necessary equates for structures and bounds checking *
;*=========================================================================*
; The header of the font file looks like object:
; UWORD FontLength; 0
; BYTE FontCompress; 2
; BYTE FontDataBlocks; 3
; UWORD InfoBlockOffset; 4
; UWORD OffsetBlockOffset; 6
; UWORD WidthBlockOffset; 8
; UWORD DataBlockOffset; 10
; UWORD HeightOffset; 12
; For this reason the following equates have these values:
FONTINFOBLOCK EQU 4
FONTOFFSETBLOCK EQU 6
FONTWIDTHBLOCK EQU 8
FONTDATABLOCK EQU 10
FONTHEIGHTBLOCK EQU 12
FONTINFOMAXHEIGHT EQU 4
FONTINFOMAXWIDTH EQU 5
LOCALS ??
;*=========================================================================*
;* Define the color xlate table in the data segment *
;*=========================================================================*
DATASEG
ColorXlat DB 000H,001H,002H,003H,004H,005H,006H,007H
DB 008H,009H,00AH,00BH,00CH,00DH,00EH,00FH
DB 001H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 002H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 003H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 004H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 005H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 006H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 007H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 008H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 009H,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 00AH,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 00BH,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 00CH,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 00DH,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 00EH,000H,000H,000H,000H,000H,000H,000H
DB 000H,000H,000H,000H,000H,000H,000H,000H
DB 00FH
CODESEG
;***************************************************************************
;* Buffer_PRINT -- Assembly buffer text print routine *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* PROTO: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 01/17/1995 PWG : Created. *
;*=========================================================================*
PROC Buffer_Print C near
USES ebx,ecx,edx,esi,edi
ARG this_object:DWORD
ARG string:DWORD
ARG x_pixel:DWORD
ARG y_pixel:DWORD
ARG fcolor:DWORD
ARG bcolor:DWORD
LOCAL infoblock:DWORD ; pointer to info block
LOCAL offsetblock:DWORD ; pointer to offset block (UWORD *)
LOCAL widthblock:DWORD ; pointer to width block (BYTE *)
LOCAL heightblock:DWORD ; pointer to height block (UWORD *)
LOCAL curline:DWORD ; pointer to first column of current row.
LOCAL bufferwidth:DWORD ; width of buffer (vpwidth + Xadd)
LOCAL nextdraw:DWORD ; bufferwidth - width of cur character.
LOCAL startdraw:DWORD ; where next character will start being drawn.
LOCAL char:DWORD ; current character value.
local ptr_string:dword ; pointer to string
LOCAL maxheight:BYTE ; max height of characters in font.
LOCAL bottomblank:BYTE ; amount of empty space below current character.
LOCAL charheight:BYTE ; true height of current character.
LOCAL vpwidth:DWORD
LOCAL vpheight:DWORD
LOCAL original_x:DWORD ; Starting X position.
mov eax,[string] ; check that the string is not NULL
mov [ptr_string],eax
cmp eax,0
jz ??done
;-------------------------------- Where to draw -----------------------------------------------
; Set up memory location to start drawing.
mov ebx,[this_object] ; get a pointer to dest
mov eax,[(GraphicViewPort ebx).GVPHeight] ; get height of viewport
mov [vpheight],eax ; save off height of viewport
mov eax,[(GraphicViewPort ebx).GVPWidth] ; get width of viewport
mov [vpwidth],eax ; save it off for later
add eax,[(GraphicViewPort ebx).GVPXAdd] ; add in xadd for bytes_per_line
add eax,[(GraphicViewPort ebx).GVPPitch] ; add in pitch of direct draw surface
mov [bufferwidth],eax ; save it off for later use.
mul [y_pixel] ; multiply rowsize * y_pixel start.
mov edi,[(GraphicViewPort ebx).GVPOffset] ; get start of the viewport
add edi,eax ; add y position to start of vp
mov [curline],edi ; save 0,y address for line feed stuff.
add edi,[x_pixel] ; add to get starting column in starting row.
mov [startdraw],edi ; save it off.
mov eax,[x_pixel]
mov [original_x],eax
;-------------------------------- Create block pointers ----------------------------------------
; Get the pointer to the font.
; We could check for NULL but why waste the time.
; It is up to programmer to make sure it is set.
mov esi,[FontPtr] ; Get the font pointer
or esi,esi
jz ??overflow
; Set up some pointers to the different memory blocks.
; esi (FontPtr) is added to each to get the true address of each block.
; Many registers are used for P5 optimizations.
; ebx is used for InfoBlock which is then used in the next section.
movzx eax,[WORD PTR esi+FONTOFFSETBLOCK] ; get offset to offset block
movzx ebx,[WORD PTR esi+FONTINFOBLOCK] ; get offset to info block (must be ebx for height test)
movzx ecx,[WORD PTR esi+FONTWIDTHBLOCK] ; get offset to width block
movzx edx,[WORD PTR esi+FONTHEIGHTBLOCK] ; get offset to height block
add eax,esi ; add offset of FontPtr to offset block
add ebx,esi ; add offset of FontPtr to info block
add ecx,esi ; add offset of FontPtr to width block
add edx,esi ; add offset of FontPtr to height block
mov [offsetblock],eax ; save offset to offset block
mov [infoblock],ebx ; save offset to info block
mov [widthblock],ecx ; save offset to width block
mov [heightblock],edx ; save offset to height block
;------------------------------------------ Test for fit ----------------------------------------------
; Test to make sure the height of the max character will fit on this line
; and and not fall out of the viewport.
; remember we set ebx to FONTINFOBLOCK above.
movzx eax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.
mov [maxheight],al ; save it for later use.
add eax,[y_pixel] ; add current y_value.
cmp eax,[vpheight] ; are we over the edge?
jg ??overflow ; if so, we're outa here.
mov [y_pixel],eax ; save for next line feed. y value for next line.
cld ; Make sure we are always forward copying.
;------------------------ Set palette foreground and background ----------------------------------
mov eax,[fcolor] ; foreground color
mov [ColorXlat+1],al
mov [ColorXlat+16],al
mov eax,[bcolor] ; background color
mov [ColorXlat],al
;-------------------------------------------------------------------------------------------------
;----------------------------------------- Main loop ----------------------------------------------
; Now we go into the main loop of reading each character in the string and doing
; something with it.
??next_char:
; while (*string++)
xor eax,eax ; zero out since we will just load al.
mov esi,[string] ; get address on next character.
lodsb ; load the character into al.
test eax,0FFH ; test to see if character is a NULL
jz ??done ; character is NULL, get outa here.
mov edi,[startdraw] ; Load the starting address.
mov [string],esi ; save index into string. (incremented by lodsb)
cmp al,10 ; is the character a carry return?
je ??line_feed ; if so, go to special case.
cmp al,13 ; is the character a line feed?
je ??line_feed ; if so, go to special case.
mov [char],eax ; save the character off for later reference.
mov ebx,eax ; save it in ebx for later use also.
add eax,[widthblock] ; figure address of width of character.
mov ecx,[x_pixel] ; get current x_pixel.
movzx edx,[BYTE PTR eax] ; get the width of the character in dl.
add ecx,edx ; add width of char to current x_pixel.
mov eax,[FontXSpacing]
add ecx,eax
add [startdraw],edx ; save start draw for next character.
add [startdraw],eax ; adjust for the font spacing value
cmp ecx,[vpwidth] ; is the pixel greater then the vp width?
jg ??force_line_feed ; if so, force a line feed.
mov [x_pixel],ecx ; save value of start of next character.
mov ecx,[bufferwidth] ; get amount to next y same x (one row down)
sub ecx,edx ; take the current width off.
mov [nextdraw],ecx ; save it to add to edi when done with a row.
; At this point we got the character. It is now time to find out specifics
; about drawing the darn thing.
; ebx = char so they can be used as an indexes.
; edx = width of character for loop later.
; get offset of data for character into esi.
shl ebx,1 ; mult by 2 to later use as a WORD index.
mov esi,[offsetblock] ; get pointer to begining of offset block.
add esi,ebx ; index into offset block.
movzx esi,[WORD PTR esi] ; get true offset into data block from FontPtr.
add esi,[FontPtr] ; Now add FontPtr address to get true address.
; Get top and bottom blank sizes and the true height of the character.
add ebx,[heightblock] ; point ebx to element in height array.
mov al,[ebx+1] ; load the data height into dl.
mov cl,[ebx] ; load the first data row into cl.
mov bl,[maxheight] ; get the max height of characters.
mov [charheight],al ; get number of rows with data.
add al,cl ; add the two heights.
sub bl,al ; subract topblank + char height from maxheight.
mov [bottomblank],bl ; save off the number of blank rows on the bottom.
; leaving this section:
; dl is still the width of the character.
; cl is the height of the top blank area.
mov ebx,OFFSET ColorXlat ; setup ebx for xlat commands.
mov dh,dl ; save the width of the character to restore each loop.
cmp cl,0 ; is there any blank rows on top?
jz ??draw_char ; if not go and draw the real character.
xor eax,eax ; get color 0 for background.
xlat [ebx] ; get translated color into al
test al,al ; is it transparent black
jnz ??loop_top ; if not go and write the color
;----------------------------------------- skip Top blank area ----------------------------------------
; this case, the top is transparrent, but we need to increase our dest pointer to correct row.
movzx eax,cl ; get number of rows into eax;
mov ecx,edx ; save width since edx will be destroyed by mul.
mul [bufferwidth] ; multiply that by the width of the buffer.
mov edx,ecx ; restore the width
add edi,eax ; update the pointer.
jmp short ??draw_char ; now go draw the character.
;----------------------------------------- fill Top blank area ----------------------------------------
; edi was set a long time ago.
; al is the translated color
??loop_top:
stosb ; store the value
dec dh ; decrement our width.
jnz ??loop_top ; if more width, continue on.
add edi,[nextdraw] ; add amount for entire row.
dec cl ; decrement or row count
mov dh,dl ; restore width in dh for loop.
jz ??draw_char ; we are done here, go draw the character.
jmp short ??loop_top ; go back to top of loop.
;----------------------------------------- Draw character ----------------------------------------------
??draw_char:
movzx ecx,[charheight] ; get the height of character to count down rows.
test ecx,ecx ; is there any data? (blank would not have any)
jz ??next_char ; if no data, go on to next character.
??while_data:
lodsb ; get byte value from font data
mov ah,al ; save hinibble
and eax,0F00FH ; mask of low nibble in al hi nibble in ah.
xlat [ebx] ; get new color
test al,al ; is it a transparent?
jz short ??skiplo ; skip over write
mov [es:edi],al ; write it out
??skiplo:
inc edi
dec dh ; decrement our width.
jz short ??nextrow ; check if done with width of char
mov al,ah ; restore to get
; test the time difference between looking up in a large table when shr al,4 is not done as
; compared to using only a 16 byte table when using the shr al,4
;shr al,4 ; shift the hi nibble down to low nibble
xlat [ebx] ; get new color
test al,al ; is it a transparent?
jz short ??skiphi ; skip over write
mov [es:edi],al ; write it out
??skiphi:
inc edi
dec dh ; decrement our width.
jnz short ??while_data ; check if done with width of char
??nextrow:
add edi,[nextdraw] ; go to next line.
dec ecx ; decrement the number of rows to go
mov dh,dl ; restore our column count for row.
jnz ??while_data ; more data for character.
; Now it is time to setup for clearing out the bottom of the character.
movzx ecx,[bottomblank] ; get amount on bottom that is blank
cmp ecx,0 ; if there is no blank bottom...
jz ??next_char ; then skip to go to next character
xor eax,eax ; get color 0 for background.
xlat [ebx] ; get translated color into al
test al,al ; is it transparent black
jz ??next_char ; skip the top black section to let the background through
mov dh,dl ; restore width in dh for loop.
;----------------------------------------- Blank below character -----------------------------------
??loop_bottom:
stosb ; store the value
dec dh ; decrement our width.
jnz ??loop_bottom ; if more width, continue on.
add edi,[nextdraw] ; add amount for entire row.
mov dh,dl ; restore width in dh for loop.
dec cl ; decrement or row count
jz ??next_char ; we are done here, go to the next character.
jmp short ??loop_bottom ; go back to top of loop.
;----------------------------------- end of next_char (main) loop ------------------------------------
;-------------------------------------------------------------------------------------------------
;----------------------------------- special case line feeds ----------------------------------------
??force_line_feed:
; decrement pointer *string so that it will be back at same character
; when it goes through the loop.
mov eax,[string] ; get string pointer.
dec eax ; decrement it to point to previos char
mov [string],eax ; save it back off.
xor eax,eax
; Now go into the line feed code.....
??line_feed:
mov bl,al
mov edx,[y_pixel] ; get the current y pixel value.
movzx ecx,[maxheight] ; get max height for later use.
add ecx,[FontYSpacing]
add edx,ecx ; add max height to y_pixel
cmp edx,[vpheight] ; are we over the edge?
jg ??overflow ; if so, we are outa here.
mov eax,[bufferwidth] ; get bytes to next line.
mov edi,[curline] ; get start of current line.
mul ecx ; mult max height * next line.
add edi,eax ; add adjustment to current line.
add [y_pixel],ecx ; increment to our next y position.
;;; DRD
mov [curline],edi ; save it off for next line_feed.
; Move the cursor to either the left edge of the screen
; or the left margin of the print position depending
; on whether <CR> or <LF> was specified. <CR> = left margin
; <LF> = left edge of screen
xor eax,eax
cmp bl,10
je ??lfeed
mov eax,[original_x]
??lfeed:
mov [x_pixel],eax ; zero out x_pixel
add edi,eax
;;; DRD mov [curline],edi ; save it off for next line_feed.
mov [startdraw],edi ; save it off so we know where to draw next char.w
jmp ??next_char
??overflow:
mov [startdraw],0 ; Indicate that there is no valid next pos.
??done:
mov eax,[startdraw] ; return this so calling routine
ret ; can figure out where to draw next.
ENDP Buffer_Print
;***************************************************************************
;* GET_FONT_PALETTE_PTR -- Returns a pointer to the 256 byte font palette *
;* *
;* INPUT: none *
;* *
;* OUTPUT: none *
;* *
;* PROTO: void *Get_Font_Palette_Ptr(void); *
;* *
;* HISTORY: *
;* 08/18/1995 PWG : Created. *
;*=========================================================================*
GLOBAL C Get_Font_Palette_Ptr:NEAR
PROC Get_Font_Palette_Ptr C near
mov eax, OFFSET ColorXlat
ret
ENDP Get_Font_Palette_Ptr
END
END

View File

@@ -0,0 +1,39 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** 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 : WWLIB32 Example *
* *
* File Name : DEFINES.H *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : August 3, 1994 *
* *
* Last Update : August 3, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#define USER_TIMER_FREQ 60

View File

@@ -0,0 +1,40 @@
/*
** 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 : WWLIB32 Example *
* *
* File Name : EXTERNS.H *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : August 3, 1994 *
* *
* Last Update : August 3, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
extern char NoTimer;
extern char NoKeyBoard;

View File

@@ -0,0 +1,50 @@
/*
** 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 : WWLIB32 Example *
* *
* File Name : FUNCTION.H *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : August 3, 1994 *
* *
* Last Update : August 3, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "wwlib32.h"
#include "defines.h"
#include "structs.h"
#include "externs.h"
/*=========================================================================*/
/* The following prototypes are for the file: MAIN.CPP */
/*=========================================================================*/
extern WORD Main_Program(WORD argc, BYTE *argv[]);
/*=========================================================================*/

Some files were not shown because too many files have changed in this diff Show More