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

512
WIN32LIB/SRCDEBUG/ALLOC.CPP Normal file
View File

@@ -0,0 +1,512 @@
/*
** 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 Library *
* *
* File Name : ALLOC.CPP *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : February 1, 1992 *
* *
* Last Update : March 9, 1995 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Alloc -- Allocates system RAM. *
* Ram_Free -- Determines the largest free chunk of RAM. *
* Free -- Free an Alloc'ed block of RAM. *
* Resize_Alloc -- Change the size of an allocated block. *
* Heap_Size -- Size of the heap we have. *
* Total_Ram_Free -- Total amount of free RAM. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>
#include <bios.h>
#ifndef WWMEM_H
#include "wwmem.h"
#endif
extern "C" unsigned long Largest_Mem_Block ( void ) ;
/*
** Define the equates necessary to call a DPMI interrupt.
*/
#define DPMI_INT 0x0031
#define DPMI_LOCK_MEM 0x0600
#define DPMI_UNLOCK_MEM 0x0601
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
unsigned long MinRam=0L; // Record of least memory at worst case.
unsigned long MaxRam=0L; // Record of total allocated at worst case.
static unsigned long TotalRam = 0L;
static unsigned long Memory_Calls = 0L;
void (*Memory_Error)(void) = NULL;
extern void (*Memory_Error_Exit)(char *string)=NULL;
//#define MEM_CHECK
#ifdef MEM_CHECK
extern "C"{
extern void __cdecl Int3(void);
}
#endif //MEM_CHECK
/***************************************************************************
* DPMI_LOCK -- handles locking a block of DPMI memory *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
#include"mono.h"
void DPMI_Lock(VOID const *, long const )
{
}
/***************************************************************************
* DPMI_UNLOCK -- Handles unlocking a locked block of DPMI *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/23/1995 PWG : Created. *
*=========================================================================*/
void DPMI_Unlock(void const *, long const )
{
}
/***************************************************************************
* Alloc -- Allocates system RAM. *
* *
* This is the basic RAM allocation function. It is used for all *
* memory allocations needed by the system or the main program. *
* *
* INPUT: bytes_to_alloc -- LONG value of the number of bytes to alloc. *
* *
* flags -- Memory allocation control flags. *
* MEM_NORMAL: No special flags. *
* MEM_CLEAR: Zero out memory block. *
* MEM_NEW: Called by a new. *
* *
* OUTPUT: Returns with pointer to allocated block. If NULL was returned *
* it indicates a failure to allocate. Note: NULL will never be *
* returned if the standard library allocation error routine is *
* used. *
* *
* WARNINGS: If you replace the standard memory allocation error routine *
* and make it so that Alloc CAN return with a NULL, be sure *
* and check for this in your code. *
* *
* HISTORY: *
* 09/03/1991 JLB : Documented. *
* 08/09/1993 JLB : Updated with EMS memory support. *
* 04/28/1994 JAW : Updated to 32bit Protected mode. *
* 03/09/1995 JLB : Fixed *
* 09/28/1995 ST : Simplified for win95 *
*=========================================================================*/
void *Alloc(unsigned long bytes_to_alloc, MemoryFlagType flags)
{
#ifdef WIN32
void *mem_ptr;
#ifdef MEM_CHECK
bytes_to_alloc += 32;
#endif //MEM_CHECK
mem_ptr = malloc ( bytes_to_alloc );
if ( !mem_ptr && Memory_Error ){
Memory_Error();
}
if ( mem_ptr && ( flags & MEM_CLEAR ) ){
memset ( mem_ptr , 0 , bytes_to_alloc );
}
#ifdef MEM_CHECK
mem_ptr = (void*)((char*)mem_ptr + 16);
unsigned long *magic_ptr =(unsigned long*) ( ((char *)mem_ptr) - 16 );
*magic_ptr++ = (unsigned long)mem_ptr;
*magic_ptr++ = (unsigned long)mem_ptr;
*magic_ptr++ = (unsigned long)mem_ptr;
*magic_ptr = bytes_to_alloc - 32;
magic_ptr = (unsigned long*) ( ((char*)mem_ptr) + bytes_to_alloc - 32 );
*magic_ptr++ = (unsigned long)mem_ptr;
*magic_ptr++ = (unsigned long)mem_ptr;
*magic_ptr++ = (unsigned long)mem_ptr;
*magic_ptr = (unsigned long)mem_ptr;
#endif //MEM_CHECK
Memory_Calls++;
return ( mem_ptr );
#else
union REGS regs ;
struct SREGS sregs ;
unsigned char *retval=NULL; // Pointer to allocated block.
unsigned long original_size; // Original allocation size.
unsigned long bytesfree; // Number of free bytes.
long *longptr=NULL; // Pointer used to store selector
/*
** Save the original allocated space size so that we can clear the
** exact amount of RAM if they specified MEM_CLEAR.
*/
original_size = bytes_to_alloc;
/*
** Reserve one byte for the header of the memory we allocated.
** We will store the flags variable there for later use.
*/
bytes_to_alloc += (flags & MEM_LOCK) ? 5 : 1;
/*
** Initialize the total ram available value.
*/
if (!TotalRam) {
TotalRam = Total_Ram_Free(MEM_NORMAL);
}
// Try to allocate the memory out of the protected mode memory
// chain if we did not require a real mode allocation. If this
// fails we will have to try to allocate it out of real mode memory.
// Real mode memory is a last resort because some types of applications
// require real mode memory.
if (!(flags & MEM_REAL)) {
retval = (unsigned char*)malloc(bytes_to_alloc);
}
// Try to allocate the memory out of the real mode memory using DPMI
// service 0x100. Note that retval will be null if we are requesting
// real mode memory so that we do not have to explicitly check for the
// real mode flag. Remember we need to reserve room for the dos
// selector value at the beginning of our allocated block so rather than
// adding fifteen and rounding, we need to add 19 and round.
if (!retval) {
flags = (MemoryFlagType)(flags | MEM_REAL);
regs.x.eax = 0x100;
regs.x.ebx = (bytes_to_alloc + 19) >> 4;
if (regs.x.ebx & 0xFFFF0000) {
retval = NULL;
} else {
segread ( & sregs ) ;
int386x ( 0x31 , & regs, & regs , & sregs ) ;
if (regs.x.cflag)
retval = NULL;
else {
longptr = (long *)(((regs.x.eax & 0xFFFF) << 4)+ 1);
*longptr++ = regs.x.edx & 0xFFFF;
retval = (unsigned char *)longptr;
}
}
}
// If the alloc failed then we need to signify a memory error.
if (retval == NULL) {
if(Memory_Error != NULL)
Memory_Error();
return NULL;
}
// If the memory needs to be DPMI locked then we should store the
// original size in the header before we store the flags.
if (flags & MEM_LOCK) {
longptr = (long *)retval;
*longptr++ = original_size;
retval = (unsigned char *)longptr;
}
// Now that we know the alloc was sucessful (and for an extra byte
// more than the user wanted) we need to stick in the memory flags.
*retval++ = flags;
// If the memory needed to be DPMI locked then set it up so it
// is locked.
if (flags & MEM_LOCK) {
DPMI_Lock(retval, original_size);
}
/* Clear the space if they wanted it clear */
if (flags & MEM_CLEAR) {
unsigned char *ptr; // Working memory block pointer.
ptr = retval;
memset(ptr, '\0', original_size);
}
bytesfree = Total_Ram_Free(MEM_NORMAL);
if (bytesfree < MinRam) {
MinRam = bytesfree;
}
if (TotalRam-bytesfree > MaxRam) {
MaxRam = TotalRam-bytesfree;
}
Memory_Calls++;
return(retval);
#endif
}
/***************************************************************************
* Free -- Free an Alloc'ed block of RAM. *
* *
* FUNCTION: *
* *
* INPUT: A pointer to a block of RAM from Alloc. *
* *
* OUTPUT: None. *
* *
* WARNINGS: Don't use this for an Alloc_Block'ed RAM block. *
* *
* HISTORY: *
* 05/25/1990 : Created. *
***************************************************************************/
#ifdef WIN32
void Free(void const *pointer)
{
if ( pointer ){
#ifdef MEM_CHECK
unsigned long *magic_ptr = (unsigned long*) ( ((char*)pointer) - 16 );
if (*magic_ptr++ != (unsigned long)pointer ||
*magic_ptr++ != (unsigned long)pointer ||
*magic_ptr++ != (unsigned long)pointer ){
Int3();
}
magic_ptr = (unsigned long*) ( ((char*)pointer) + *magic_ptr );
if (*magic_ptr++ != (unsigned long)pointer ||
*magic_ptr++ != (unsigned long)pointer ||
*magic_ptr++ != (unsigned long)pointer ||
*magic_ptr++ != (unsigned long)pointer ){
Int3();
}
pointer = (void*) (((char*)pointer)-16);
#endif //MEM_CHECK
free ( (void*)pointer );
Memory_Calls--;
}
#else
void Free(void const *pointer)
{
union REGS regs ;
struct SREGS sregs ;
if (pointer) {
/*
** Get a pointer to the flags that we stored off.
*/
char *byteptr = ((char *)pointer) - 1;
/*
** Check to see if this was locked me and if it was unlock it.
*/
if (*byteptr & MEM_LOCK) {
long *longptr = ((long *)byteptr) - 1;
DPMI_Unlock(pointer, *longptr);
pointer = (void *)longptr;
} else
pointer = (void *)byteptr;
// If the pointer is a real mode pointer than it will point to the
// first megabyte of system memory. If it does than we need to
// use DPMI to free it.
if (*byteptr & MEM_REAL) {
regs.x.eax = 0x101;
regs.x.edx = *(((long *)pointer) - 1);
segread ( & sregs ) ;
int386x(0x31, &regs, &regs, &sregs);
} else {
free((void *)pointer);
}
Memory_Calls--;
}
#endif
}
/***************************************************************************
* Resize_Alloc -- Change the size of an allocated block. *
* *
* This routine will take a previously allocated block and change its *
* size without unnecessarily altering its contents. *
* *
* INPUT: pointer -- Pointer to the original memory allocation. *
* *
* new_size -- Size in bytes that it will be converted to. *
* *
* OUTPUT: Returns with a pointer to the new allocation. *
* *
* WARNINGS: ??? *
* *
* HISTORY: *
* 02/01/1992 JLB : Commented. *
*=========================================================================*/
void *Resize_Alloc(void *original_ptr, unsigned long new_size_in_bytes)
{
unsigned long *temp;
temp = (unsigned long*)original_ptr;
/* ReAlloc the space */
temp = (unsigned long *)realloc(temp, new_size_in_bytes);
if (temp == NULL) {
if(Memory_Error != NULL)
Memory_Error();
return NULL;
}
return(temp);
}
/***************************************************************************
* Ram_Free -- Determines the largest free chunk of RAM. *
* *
* Use this routine to determine the largest free chunk of available *
* RAM for allocation. It also performs a check of the memory chain. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with the size of the largest free chunk of RAM. *
* *
* WARNINGS: This does not return the TOTAL memory free, only the *
* largest free chunk. *
* *
* HISTORY: *
* 09/03/1991 JLB : Commented. *
*=========================================================================*/
long Ram_Free(MemoryFlagType)
{
// return(_memmax());
#if(0)
MEMORYSTATUS mem_info;
mem_info.dwLength=sizeof(mem_info);
GlobalMemoryStatus(&mem_info);
return ( mem_info.dwAvailPhys );
#endif
return ( 64*1024*1024 );
}
/***************************************************************************
* Heap_Size -- Size of the heap we have. *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/21/1994 SKB : Created. *
*=========================================================================*/
long Heap_Size(MemoryFlagType )
{
if (!TotalRam) {
TotalRam = Total_Ram_Free(MEM_NORMAL);
}
return(TotalRam);
}
/***************************************************************************
* Total_Ram_Free -- Total amount of free RAM. *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/21/1994 SKB : Created. *
* 03/09/1995 JLB : Uses prerecorded heap size maximum. *
*=========================================================================*/
long Total_Ram_Free(MemoryFlagType )
{
#if(0)
MEMORYSTATUS mem_info;
mem_info.dwLength=sizeof(mem_info);
GlobalMemoryStatus(&mem_info);
return ( mem_info.dwAvailPhys );
#endif
return ( 64*1024*1024 );
}

View File

@@ -0,0 +1,298 @@
;
; 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 : Profiler *
;* *
;* File Name : APROFILE.ASM *
;* *
;* Programmer : Steve Tall *
;* *
;* Start Date : November 17th, 1995 *
;* *
;* Last Update : November 20th, 1995 [ST] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* __PRO -- must be called at the beginning of each function *
;* __EPI -- must be called at the end of each function *
;* Copy_CHL -- initialise the profiler asm data *
;* Profiler_Callback -- windows callback for millisecond timer *
;* *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
p386
model flat
ideal
jumps
MAX_PROFILE_TIME = 60*1 ;1 minute(s)
PROFILE_RATE = 1000 ;1000 samples per sec
;
; Externs
;
;
global C ProfileFunctionAddress:dword
global C ProfilePtr:dword
global C ProfileList:dword
global C Stop_Profiler:near
global New_Profiler_Callback_:near
global Old_Profiler_Callback_:near
global C Profile_Init:near
global C Profile_End:near
global ___begtext:near
global BaseAddress:dword
global __PRO:near
global __EPI:near
global MyStack:dword
global MyStackPtr:dword
global ProAddress:dword
global EpiAddress:dword
codeseg
;*********************************************************************************************
;* __PRO -- registers the current procedure *
;* *
;* INPUT: Nothing *
;* *
;* OUTPUT: none *
;* *
;* Warnings: *
;* Assumes that ss:Esp points to return address in function to be registered *
;* *
;* HISTORY: *
;* 11/20/95 4:39PM ST : Created. *
;*===========================================================================================*
proc __PRO near
jmp [ProAddress]
; safe version of prologue code
Pro_Start: push eax
mov eax,[MyStackPtr]
push [ProfileFunctionAddress]
pop [eax*4+MyStack]
inc [MyStackPtr]
pop eax
push [dword ss:esp]
pop [ProfileFunctionAddress]
Pro_End: ret
; unsafe (but much faster) prologue code
; pop [ProfileFunctionAddress]
; jmp [ProfileFunctionAddress]
endp __PRO
;*********************************************************************************************
;* __EPI -- Registers the privious procedure as current again *
;* *
;* INPUT: Nothing *
;* *
;* OUTPUT: none *
;* *
;* Warnings: *
;* Assumes that calling procedure will pop ebp immediately on return so we dont have to *
;* preserve it. *
;* *
;* HISTORY: *
;* 11/20/95 4:42PM ST : Created. *
;*===========================================================================================*
proc __EPI near
jmp [EpiAddress]
; Safe version of epilogue code. Uncomment the push and pop for ultimate safety
Epi_Start: dec [MyStackPtr]
; push ebp
mov ebp,[MyStackPtr]
mov ebp,[ebp*4+MyStack]
mov [ProfileFunctionAddress],ebp
; pop ebp
Epi_End: ret
; Unsafe (but much faster) epilogue code. Makes lots of assumptions.
; push [dword esp+8]
; pop [ProfileFunctionAddress]
; ret
endp __EPI
;*********************************************************************************************
;* Profile_Init -- Initialises the .asm data required for profile session *
;* *
;* INPUT: Nothing *
;* *
;* OUTPUT: none *
;* *
;* Warnings: *
;* Assumes that '___begtext' is the first label in the code segment and that its *
;* address is within 15 bytes of the start of the code segment *
;* *
;* HISTORY: *
;* 11/20/95 4:44PM ST : Created. *
;*===========================================================================================*
proc Profile_Init C near
mov eax,offset ___begtext
and eax,0fffffff0h
mov [BaseAddress],eax
;mov [MyStackPtr],0
mov [ProfileList],PROFILE_RATE
mov [ProfilePtr],1
mov [ProAddress],offset Pro_Start
mov [EpiAddress],offset Epi_Start
ret
endp Profile_Init
;*********************************************************************************************
;* Profile_End -- disables the __PRO and __EPI procedures *
;* *
;* INPUT: Nothing *
;* *
;* OUTPUT: none *
;* *
;* Warnings: *
;* *
;* HISTORY: *
;* 11/20/95 4:44PM ST : Created. *
;*===========================================================================================*
proc Profile_End C near
mov [ProAddress],offset Pro_End
mov [EpiAddress],offset Epi_End
ret
endp Profile_End
;*********************************************************************************************
;* New_Profiler_Callback -- Windows callback used to register function hits *
;* *
;* INPUT: Nothing *
;* *
;* OUTPUT: none *
;* *
;* Note: *
;* The frequency that this is called depends on MAX_PROFILE_RATE defined here and in *
;* profile.h *
;* *
;* HISTORY: *
;* 11/20/95 4:47PM ST : Created. *
;*===========================================================================================*
proc New_Profiler_Callback_ near
push eax
push esi
mov esi,[ProfilePtr]
cmp esi,MAX_PROFILE_TIME*PROFILE_RATE
jge @@out
mov eax,[ProfileFunctionAddress]
sub eax,[BaseAddress]
mov [ProfileList+esi*4],eax
inc [ProfilePtr]
pop esi
pop eax
ret
@@out: call Stop_Profiler
pop esi
pop eax
ret
endp New_Profiler_Callback_
;*********************************************************************************************
;* Old_Profiler_Callback -- Windows callback used to register function hits *
;* *
;* INPUT: Windows timer callback stuff - not used *
;* *
;* OUTPUT: none *
;* *
;* Note: *
;* The frequency that this is called depends on MAX_PROFILE_RATE defined here and in *
;* profile.h *
;* *
;* HISTORY: *
;* 11/20/95 4:47PM ST : Created. *
;*===========================================================================================*
proc Old_Profiler_Callback_ near
push eax
push esi
mov esi,[ProfilePtr]
cmp esi,MAX_PROFILE_TIME*PROFILE_RATE
jge @@out
mov eax,[ProfileFunctionAddress]
sub eax,[BaseAddress]
mov [ProfileList+esi*4],eax
inc [ProfilePtr]
pop esi
pop eax
ret 14h
@@out: call Stop_Profiler
pop esi
pop eax
ret 14h
endp Old_Profiler_Callback_
dataseg
align 4
ProfileFunctionAddress dd 0 ;Ptr to function we are currently in
BaseAddress dd 0 ;Address of the code segment start
MyStackPtr dd 0 ;offset into my stack table
ProAddress dd Pro_Start ;jmp ptr for __PRO procedure
EpiAddress dd Epi_Start ;jmp ptr for __EPI procedure
label MyStack dword ;my stack table
dd 16*1024 dup (?)
end

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

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;
}
}

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;

View File

@@ -0,0 +1,604 @@
/*
** 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: F:\projects\c&c0\vcs\code\ccfile.cpv 2.20 27 Sep 1995 12:45:16 JOE_BOSTIC $ */
/***********************************************************************************************
*** 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 : Command & Conquer *
* *
* File Name : CCFILE.CPP *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : August 8, 1994 *
* *
* Last Update : March 20, 1995 [JLB] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* CCFileClass::CCFileClass -- Default constructor for file object. *
* CCFileClass::CCFileClass -- Filename based constructor for C&C file. *
* CCFileClass::Close -- Closes the file. *
* CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile. *
* CCFileClass::Is_Open -- Determines if the file is open. *
* CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system. *
* CCFileClass::Read -- Reads data from the file. *
* CCFileClass::Seek -- Moves the current file pointer in the file. *
* CCFileClass::Size -- Determines the size of the file. *
* CCFileClass::Write -- Writes data to the file (non mixfile files only). *
* CCFileClass::Error -- Handles displaying a file error message. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "function.h"
#include <direct.h>
#include <fcntl.h>
#include <io.h>
#include <dos.h>
#include <errno.h>
#include <share.h>
#include "ccfile.h"
/***********************************************************************************************
* CCFileClass::Error -- Handles displaying a file error message. *
* *
* Display an error message as indicated. If it is allowed to retry, then pressing a key *
* will return from this function. Otherwise, it will exit the program with "exit()". *
* *
* INPUT: error -- The error number (same as the DOSERR.H error numbers). *
* *
* canretry -- Can this routine exit normally so that retrying can occur? If this is *
* false, then the program WILL exit in this routine. *
* *
* filename -- Optional filename to report with this error. If no filename is *
* supplied, then no filename is listed in the error message. *
* *
* OUTPUT: none, but this routine might not return at all if the "canretry" parameter is *
* false or the player pressed ESC. *
* *
* WARNINGS: This routine may not return at all. It handles being in text mode as well as *
* if in a graphic mode. *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
void CCFileClass::Error(int , int , char const * )
{
if (!Force_CD_Available(RequiredCD)) {
Prog_End();
exit(EXIT_FAILURE);
}
}
/***********************************************************************************************
* CCFileClass::CCFileClass -- Filename based constructor for C&C file. *
* *
* Use this constructor for a file when the filename is known at construction time. *
* *
* INPUT: filename -- Pointer to the filename to use for this file object. *
* *
* OUTPUT: none *
* *
* WARNINGS: The filename pointer is presumed to be inviolate throughout the duration of *
* the file object. If this is not guaranteed, then use the default constructor *
* and then set the name manually. *
* *
* HISTORY: *
* 03/20/1995 JLB : Created. *
*=============================================================================================*/
CCFileClass::CCFileClass(char const *filename)
{
Set_Name(filename);
FromDisk = false;
Pointer = 0;
Position = 0;
Length = 0;
Start = 0;
}
/***********************************************************************************************
* CCFileClass::CCFileClass -- Default constructor for file object. *
* *
* This is the default constructor for a C&C file object. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 03/20/1995 JLB : Created. *
*=============================================================================================*/
CCFileClass::CCFileClass(void) : CDFileClass()
{
FromDisk = false;
Pointer = 0;
Position = 0;
Length = 0;
Start = 0;
}
/***********************************************************************************************
* CCFileClass::Write -- Writes data to the file (non mixfile files only). *
* *
* This routine will write data to the file, but NOT to a file that is part of a mixfile. *
* *
* INPUT: buffer -- Pointer to the buffer that holds the data to be written. *
* *
* size -- The number of bytes to write. *
* *
* OUTPUT: Returns the number of bytes actually written. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/08/1994 JLB : Created. *
*=============================================================================================*/
long CCFileClass::Write(void const *buffer, long size)
{
/*
** If this is part of a mixfile, then writing is not allowed. Error out with a fatal
** message.
*/
if (Pointer || FromDisk) {
Error(EACCES, false, File_Name());
}
return(CDFileClass::Write(buffer, size));
}
/***********************************************************************************************
* CCFileClass::Read -- Reads data from the file. *
* *
* This routine determines if the file is part of the mixfile system. If it is, then *
* the file is copied from RAM if it is located there. Otherwise it is read from disk *
* according to the correct position of the file within the parent mixfile. *
* *
* INPUT: buffer -- Pointer to the buffer to place the read data. *
* *
* size -- The number of bytes to read. *
* *
* OUTPUT: Returns the actual number of bytes read (this could be less than requested). *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/08/1994 JLB : Created. *
*=============================================================================================*/
long CCFileClass::Read(void *buffer, long size)
{
int opened = false;
if (!Is_Open()) {
if (Open()) {
opened = true;
}
}
/*
** If the file is part of a loaded mixfile, then a mere copy is
** all that is required for the read.
*/
if (Pointer) {
long maximum = Length - Position;
size = MIN(maximum, size);
if (size) {
Mem_Copy(Add_Long_To_Pointer(Pointer, Position), buffer, size);
Position += size;
}
if (opened) Close();
return(size);
}
/*
** If the file is part of a mixfile, but the mixfile is located
** on disk, then a special read operation is necessary.
*/
if (FromDisk) {
long maximum = Length - Position;
size = MIN(maximum, size);
if (size > 0) {
CDFileClass::Seek(Start + Position, SEEK_SET);
size = CDFileClass::Read(buffer, size);
Position += size;
}
if (opened) Close();
return(size);
}
long s = CDFileClass::Read(buffer, size);
if (opened) Close();
return(s);
}
/***********************************************************************************************
* CCFileClass::Seek -- Moves the current file pointer in the file. *
* *
* This routine will change the current file pointer to the position specified. It follows *
* the same rules the a normal Seek() does, but if the file is part of the mixfile system, *
* then only the position value needs to be updated. *
* *
* INPUT: pos -- The position to move the file to relative to the position indicated *
* by the "dir" parameter. *
* *
* dir -- The direction to affect the position change against. This can be *
* either SEEK_CUR, SEEK_END, or SEEK_SET. *
* *
* OUTPUT: Returns with the position of the new location. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/08/1994 JLB : Created. *
*=============================================================================================*/
long CCFileClass::Seek(long pos, int dir)
{
if (Pointer || FromDisk) {
switch (dir) {
case SEEK_END:
Position = Length;
break;
case SEEK_SET:
Position = 0;
break;
case SEEK_CUR:
default:
break;
}
Position += pos;
if (Position < 0) Position = 0;
if (Position > Length) Position = Length;
return(Position);
}
return(CDFileClass::Seek(pos, dir));
}
/***********************************************************************************************
* CCFileClass::Size -- Determines the size of the file. *
* *
* If the file is part of the mixfile system, then the size of the file is already *
* determined and available. Otherwise, go to the low level system to find the file *
* size. *
* *
* INPUT: none *
* *
* OUTPUT: Returns with the size of the file in bytes. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/08/1994 JLB : Created. *
*=============================================================================================*/
long CCFileClass::Size(void)
{
if (Pointer || FromDisk) return(Length);
return(CDFileClass::Size());
}
/***********************************************************************************************
* CCFileClass::Is_Available -- Checks for existence of file on disk or in mixfile. *
* *
* This routine will examine the mixfile system looking for the file. If the file could *
* not be found there, then the disk is examined directly. *
* *
* INPUT: none *
* *
* OUTPUT: bool; Is the file available for opening? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/08/1994 JLB : Created. *
*=============================================================================================*/
int CCFileClass::Is_Available(int )
{
if (MixFileClass::Offset(File_Name())) {
return(true);
}
return(CDFileClass::Is_Available());
}
/***********************************************************************************************
* CCFileClass::Is_Open -- Determines if the file is open. *
* *
* A mixfile is open if there is a pointer to the mixfile data. In absence of this, *
* the the file is open if the file handle is valid. *
* *
* INPUT: none *
* *
* OUTPUT: bool; Is the file open? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/08/1994 JLB : Created. *
*=============================================================================================*/
int CCFileClass::Is_Open(void) const
{
/*
** If the file is part of a cached file, then return that it is opened. A closed file
** doesn't have a valid pointer.
*/
if (Pointer) return(true);
return(CDFileClass::Is_Open());
}
/***********************************************************************************************
* CCFileClass::Close -- Closes the file. *
* *
* If this is a mixfile file, then only the pointers need to be adjusted. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/08/1994 JLB : Created. *
*=============================================================================================*/
void CCFileClass::Close(void)
{
FromDisk = false;
Pointer = 0;
Position = 0; // Starts at beginning offset.
Start = 0;
Length = 0;
CDFileClass::Close();
}
/***********************************************************************************************
* CCFileClass::Open -- Opens a file from either the mixfile system or the rawfile system. *
* *
* This routine will open the specified file. It examines the mixfile system to find a *
* match. If one is found then the file is "opened" in a special cached way. Otherwise *
* it is opened as a standard DOS file. *
* *
* INPUT: rights -- The access rights desired. *
* *
* OUTPUT: bool; Was the file opened successfully? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/08/1994 JLB : Created. *
*=============================================================================================*/
int CCFileClass::Open(int rights)
{
/*
** Always close the file if it was open.
*/
Close();
/*
** Perform a preliminary check to see if the specified file
** exists on the disk. If it does, then open this file regardless
** of whether it also exists in RAM. This is slower, but allows
** upgrade files to work.
*/
if ((rights & WRITE) || CDFileClass::Is_Available()) {
return(CDFileClass::Open(rights));
}
/*
** Check to see if file is part of a mixfile and that mixfile is currently loaded
** into RAM.
*/
MixFileClass *mixfile = 0;
if (MixFileClass::Offset(File_Name(), &Pointer, &mixfile, &Start, &Length)) {
/*
** If the mixfile is located on disk, then fake out the file system to read from
** the mixfile, but think it is reading from a solitary file.
*/
if (!Pointer) {
long start = Start;
long length = Length;
/*
** This is a legitimate open to the file. All access to the file through this
** file object will be appropriately adjusted for mixfile support however. Also
** note that the filename attached to this object is NOT the same as the file
** attached to the file handle.
*/
char const * dupfile = strdup(File_Name());
Open(mixfile->Filename, READ);
Searching(false); // Disable multi-drive search.
Set_Name(dupfile);
free((void *)dupfile);
Start = start;
Length = length;
FromDisk = true;
}
} else {
/*
** The file cannot be found in any mixfile, so it must reside as
** an individual file on the disk. Or else it is just plain missing.
*/
return(CDFileClass::Open(rights));
}
return(true);
}
/***********************************************************************************
** Backward compatibility section.
*/
//extern "C" {
static CCFileClass Handles[10];
#ifdef NEVER
bool __cdecl Set_Search_Drives(BYTE const *)
{
CCFileClass::Set_Search_Path(path);
return(true);
}
#endif
WORD __cdecl Open_File(BYTE const *file_name, WORD mode)
{
for (int index = 0; index < sizeof(Handles)/sizeof(Handles[0]); index++) {
if (!Handles[index].Is_Open()) {
if (Handles[index].Open(file_name, mode)) {
return(index);
}
break;
}
}
return(ERROR);
}
VOID __cdecl Close_File(WORD handle)
{
if (handle != ERROR && Handles[handle].Is_Open()) {
Handles[handle].Close();
}
}
LONG __cdecl Read_File(WORD handle, VOID *buf, ULONG bytes)
{
if (handle != ERROR && Handles[handle].Is_Open()) {
return(Handles[handle].Read(buf, bytes));
}
return(0);
}
LONG __cdecl Write_File(WORD handle, VOID const *buf, ULONG bytes)
{
if (handle != ERROR && Handles[handle].Is_Open()) {
return(Handles[handle].Write(buf, bytes));
}
return(0);
}
WORD __cdecl Find_File(BYTE const *file_name)
{
CCFileClass file(file_name);
return(file.Is_Available());
}
#ifdef NEVER
WORD __cdecl Delete_File(BYTE const *file_name)
{
return(CCFileClass(file_name).Delete());
}
WORD __cdecl Create_File(BYTE const *file_name)
{
return(CCFileClass(file_name).Create());
}
ULONG __cdecl Load_Data(BYTE const *name, VOID *ptr, ULONG size)
{
return(CCFileClass(name).Read(ptr, size));
}
#endif
VOID * __cdecl Load_Alloc_Data(BYTE const *name, WORD )
{
CCFileClass file(name);
return(Load_Alloc_Data(file));
}
ULONG __cdecl File_Size(WORD handle)
{
if (handle != ERROR && Handles[handle].Is_Open()) {
return(Handles[handle].Size());
}
return(0);
}
#ifdef NEVER
ULONG __cdecl Write_Data(BYTE const *name, VOID const *ptr, ULONG size)
{
return(CCFileClass(name).Write(ptr, size));
}
#endif
ULONG __cdecl Seek_File(WORD handle, LONG offset, WORD starting)
{
if (handle != ERROR && Handles[handle].Is_Open()) {
return(Handles[handle].Seek(offset, starting));
}
return(0);
}
#ifdef NEVER
bool __cdecl Multi_Drive_Search(bool on)
{
// return(CCFileClass::Multi_Drive_Search(on));
return(on);
}
VOID __cdecl WWDOS_Init(VOID)
{
}
VOID __cdecl WWDOS_Shutdown(VOID)
{
}
WORD __cdecl Find_Disk_Number(BYTE const *)
{
return(0);
}
#endif
//ULONG cdecl Load_Uncompress(BYTE const *file, BuffType uncomp_buff, BuffType dest_buff, VOID *reserved_data)
//{
// return(Load_Uncompress(CCFileClass(file), uncomp_buff, dest_buff, reserved_data));
// return(CCFileClass(file).Load_Uncompress(uncomp_buff, dest_buff, reserved_data));
//}
extern "C" {
int MaxDevice;
int DefaultDrive;
char CallingDOSInt;
}
void Unfragment_File_Cache(void)
{
}

130
WIN32LIB/SRCDEBUG/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,269 @@
;
; 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 : Support Library *
;* *
;* File Name : cliprect.asm *
;* *
;* Programmer : Julio R Jerez *
;* *
;* Start Date : Mar, 2 1995 *
;* *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* int Clip_Rect ( int * x , int * y , int * dw , int * dh , *
;* int width , int height ) ; *
;* int Confine_Rect ( int * x , int * y , int * dw , int * dh , *
;* int width , int height ) ; *
;* *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL C Clip_Rect :NEAR
GLOBAL C Confine_Rect :NEAR
CODESEG
;***************************************************************************
;* Clip_Rect -- clip a given rectangle against a given window *
;* *
;* INPUT: &x , &y , &w , &h -> Pointer to rectangle being clipped *
;* width , height -> dimension of clipping window *
;* *
;* OUTPUT: a) Zero if the rectangle is totally contained by the *
;* clipping window. *
;* b) A negative value if the rectangle is totally outside the *
;* the clipping window *
;* c) A positive value if the rectangle was clipped against the *
;* clipping window, also the values pointed by x, y, w, h will *
;* be modified to new clipped values *
;* *
;* 05/03/1995 JRJ : added comment *
;*=========================================================================*
; int Clip_Rect (int* x, int* y, int* dw, int* dh, int width, int height); *
PROC Clip_Rect C near
uses ebx,ecx,edx,esi,edi
arg x:dword
arg y:dword
arg w:dword
arg h:dword
arg width:dword
arg height: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, return the oroginal data)
; - trivially rejected (return with no action, return error code)
; - retangle must be iteratively clipped again edges of the clipping window
; and return the clipped rectangle
; get all four pointer into regisnters
mov esi,[x] ; esi = pointer to x
mov edi,[y] ; edi = pointer to x
mov eax,[w] ; eax = pointer to dw
mov ebx,[h] ; ebx = pointer to dh
; load the actual data into reg
mov esi,[esi] ; esi = x0
mov edi,[edi] ; edi = y0
mov eax,[eax] ; eax = dw
mov ebx,[ebx] ; ebx = dh
; create a wire frame of the type [x0,y0] , [x1,y1]
add eax,esi ; eax = x1 = x0 + dw
add ebx,edi ; ebx = y1 = y0 + dh
; we start we suthenland code0 and code1 set to zero
xor ecx,ecx ; cl = sutherland boolean code0
xor edx,edx ; dl = sutherland boolean code0
; now we start computing the to suthenland boolean code for x0 , x1
shld ecx,esi,1 ; bit3 of code0 = sign bit of (x0 - 0)
shld edx,eax,1 ; bit3 of code1 = sign bit of (x1 - 0)
sub esi,[width] ; get the difference (x0 - (width + 1))
sub eax,[width] ; get the difference (x1 - (width + 1))
dec esi
dec eax
shld ecx,esi,1 ; bit2 of code0 = sign bit of (x0 - (width + 1))
shld edx,eax,1 ; bit2 of code1 = sign bit of (x0 - (width + 1))
; now we start computing the to suthenland boolean code for y0 , y1
shld ecx,edi,1 ; bit1 of code0 = sign bit of (y0 - 0)
shld edx,ebx,1 ; bit1 of code1 = sign bit of (y0 - 0)
sub edi,[height] ; get the difference (y0 - (height + 1))
sub ebx,[height] ; get the difference (y1 - (height + 1))
dec edi
dec ebx
shld ecx,edi,1 ; bit0 of code0 = sign bit of (y0 - (height + 1))
shld edx,ebx,1 ; bit0 of code1 = sign bit of (y1 - (height + 1))
; Bit 2 and 0 of cl and bl are complemented
xor cl,5 ; reverse bit2 and bit0 in code0
xor dl,5 ; reverse bit2 and bit0 in code1
; now perform the rejection test
mov eax,-1 ; set return code to false
mov bl,cl ; save code0 for future use
test dl,cl ; if any two pair of bit in code0 and code1 is set
jnz ??clip_out ; then rectangle is outside the window
; now perform the aceptance test
xor eax,eax ; set return code to true
or bl,dl ; if all pair of bits in code0 and code1 are reset
jz ??clip_out ; then rectangle is insize the window. '
; we need to clip the rectangle iteratively
mov eax,-1 ; set return code to false
test cl,1000b ; if bit3 of code0 is set then the rectangle
jz ??left_ok ; spill out the left edge of the window
mov edi,[x] ; edi = a pointer to x0
mov ebx,[w] ; ebx = a pointer to dw
mov esi,[edi] ; esi = x0
mov [dword ptr edi],0 ; set x0 to 0 "this the left edge value"
add [ebx],esi ; adjust dw by x0, since x0 must be negative
??left_ok:
test cl,0010b ; if bit1 of code0 is set then the rectangle
jz ??bottom_ok ; spill out the bottom edge of the window
mov edi,[y] ; edi = a pointer to y0
mov ebx,[h] ; ebx = a pointer to dh
mov esi,[edi] ; esi = y0
mov [dword ptr edi],0 ; set y0 to 0 "this the bottom edge value"
add [ebx],esi ; adjust dh by y0, since y0 must be negative
??bottom_ok:
test dl,0100b ; if bit2 of code1 is set then the rectangle
jz ??right_ok ; spill out the right edge of the window
mov edi,[w] ; edi = a pointer to dw
mov esi,[x] ; esi = a pointer to x
mov ebx,[width] ; ebx = the width of the window
sub ebx,[esi] ; the new dw is the difference (width-x0)
mov [edi],ebx ; adjust dw to (width - x0)
jle ??clip_out ; if (width-x0) = 0 then the clipped retangle
; has no width we are done
??right_ok:
test dl,0001b ; if bit0 of code1 is set then the rectangle
jz ??clip_ok ; spill out the top edge of the window
mov edi,[h] ; edi = a pointer to dh
mov esi,[y] ; esi = a pointer to y0
mov ebx,[height] ; ebx = the height of the window
sub ebx,[esi] ; the new dh is the difference (height-y0)
mov [edi],ebx ; adjust dh to (height-y0)
jle ??clip_out ; if (width-x0) = 0 then the clipped retangle
; has no width we are done
??clip_ok:
mov eax,1 ; signal the calling program that the rectangle was modify
??clip_out:
ret
ENDP Clip_Rect
;***************************************************************************
;* Confine_Rect -- clip a given rectangle against a given window *
;* *
;* INPUT: &x,&y,w,h -> Pointer to rectangle being clipped *
;* width,height -> dimension of clipping window *
;* *
;* OUTPUT: a) Zero if the rectangle is totally contained by the *
;* clipping window. *
;* c) A positive value if the rectangle was shifted in position *
;* to fix inside the clipping window, also the values pointed *
;* by x, y, will adjusted to a new values *
;* *
;* NOTE: this function make not attempt to verify if the rectangle is *
;* bigger than the clipping window and at the same time wrap around*
;* it. If that is the case the result is meaningless *
;*=========================================================================*
; int Confine_Rect (int* x, int* y, int dw, int dh, int width, int height); *
PROC Confine_Rect C near
uses ebx, esi,edi
arg x:dword
arg y:dword
arg w:dword
arg h:dword
arg width :dword
arg height:dword
xor eax,eax
mov ebx,[x]
mov edi,[w]
mov esi,[ebx]
add edi,[ebx]
sub edi,[width]
neg esi
dec edi
test esi,edi
jl ??x_axix_ok
mov eax,1
test esi,esi
jl ??shift_right
mov [dword ptr ebx],0
jmp ??x_axix_ok
??shift_right:
inc edi
sub [ebx],edi
??x_axix_ok:
mov ebx,[y]
mov edi,[h]
mov esi,[ebx]
add edi,[ebx]
sub edi,[height]
neg esi
dec edi
test esi,edi
jl ??confi_out
mov eax,1
test esi,esi
jl ??shift_top
mov [dword ptr ebx],0
ret
??shift_top:
inc edi
sub [ebx],edi
??confi_out:
ret
ENDP Confine_Rect
END

114
WIN32LIB/SRCDEBUG/CRC.ASM Normal file
View File

@@ -0,0 +1,114 @@
;
; 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 Library *
;* *
;* File Name : CRC.ASM *
;* *
;* Programmer : Joe L. Bostic *
;* *
;* Start Date : June 12, 1992 *
;* *
;* Last Update : February 10, 1995 [BWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL C Calculate_CRC :NEAR
CODESEG
; LONG Calculate_CRC(VOID *buffer, LONG length);
PROC Calculate_CRC C near
USES esi
ARG buffer:DWORD
ARG length:DWORD
LOCAL crc:DWORD
; Load pointer to data block.
mov [crc],0
pushad
mov esi,[buffer]
cld
; Clear CRC to default (NULL) value.
xor ebx,ebx
; Fetch the length of the data block to CRC.
mov ecx,[length]
jecxz short ??fini
; Prepare the length counters.
mov edx,ecx
and dl,011b
shr ecx,2
; Perform the bulk of the CRC scanning.
jecxz short ??remainder
??accumloop:
lodsd
rol ebx,1
add ebx,eax
loop ??accumloop
; Handle the remainder bytes.
??remainder:
or dl,dl
jz short ??fini
mov ecx,edx
xor eax,eax
and ecx,0FFFFh
push ecx
??nextbyte:
lodsb
ror eax,8
loop ??nextbyte
pop ecx
neg ecx
add ecx,4
shl ecx,3
ror eax,cl
;??nextbyte:
; shl eax,8
; lodsb
; loop ??nextbyte
rol ebx,1
add ebx,eax
??fini:
mov [crc],ebx
popad
mov eax,[crc]
ret
ENDP Calculate_CRC
END

1000
WIN32LIB/SRCDEBUG/DDRAW.CPP Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
/*
** 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 : LIBRARY *
* *
* File Name : DELAY.C *
* *
* Programmer : Christopher Yates *
* *
* Last Update : 27 March, 1991 [CY] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "wwstd.h"
#include <timer.h>
void Delay(int duration)
{
unsigned long count;
TimerClass timer(BT_SYSTEM,TRUE);
while (duration--) {
count = timer.Time() + 1L;
while (count >= timer.Time()) {
;
}
}
#if(FALSE)
while (duration--)
Wait_Vert_Blank(VertBlank);
#endif
}
#if(FALSE)
void Vsync()
{
Wait_Vert_Blank(VertBlank);
}
#endif


View File

@@ -0,0 +1,113 @@
/*
** 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 : Descriptor management *
* *
* File Name : DESCMGMT.CPP *
* *
* Programmer : Jeff Wilson *
* *
* Start Date : March 28, 1994 *
* *
* Last Update : March 28, 1994 [] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* MAP_SEGMENT_TO_ADDRESS -- Maps a physical address into a selector *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "descmgmt.h"
#include "misc.h"
/***************************************************************************
* MAP_SEGMENT_TO_ADDRESS -- Maps a physical address into a selector *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: selector UWORD The selector mapped to address. exit on error. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 03/25/1994 jaw: Created. *
*=========================================================================*/
ULONG Map_Segment_To_Address(ULONG address, ULONG length)
{
// this function is not longer needed by RATIONAL SYSTEM DOS4GW
// linear addressing mode.
// a> the first megabyte of memory is mapped to linear adress 0 - 0x10000h
// b> all other addresses are linear offset from either ds: or es:
/*
UWORD segment;
UWORD curDS;
CD_DES desc;
CD_DES cur_desc;
// allocate a selector
if(_dos_allocmem(0, &segment) != 0) {
Exit(1, "Allocation of Descriptor.\n");
}
// get the data for this selector
if(_dx_ldt_rd(segment, (UCHAR *)&desc) != 0) {
Exit(1, "Reading Descriptor.\n");
}
// get the data for current data segment
curDS = GetDs();
if(_dx_ldt_rd(curDS, (UCHAR *)&cur_desc) != 0) {
Exit(1, "Reading Descriptor.\n");
}
// set limit
desc.limit0_15 = (USHORT)(length & 0xffff);
desc.limit16_19 = ((UCHAR)(length >> 16L)) | DOS_32;
// set base address
desc.base0_15 = (USHORT)(address & 0xffff);
desc.base16_23 = (UCHAR)((address >> 16) & 0xff);
desc.base24_31 = (UCHAR)((address >> 24) & 0xff);
// set rights mark as icurrent data segment
desc.arights = cur_desc.arights;
// write to LDT selector
if(_dx_ldt_wr(segment, (UCHAR *)&desc) != 0) {
Exit(1, "Failed writing descriptor.\n");
}
// return selector number
return segment;
*/
if ( address & 0xfff0ffff )
Exit ( 1 , "Error mapping real address to lineal address.\n" ) ;
return address ;
}

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/>.
;
; $Header: g:/library/wwlib32/system/rcs/detproc.asm 1.1 1994/04/18 09:13:53 jeff_wilson Exp $
;***************************************************************************
;** 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 : PROC.ASM *
;* *
;* Programmer : Joe L. Bostic *
;* *
;* Start Date : May 11, 1993 *
;* *
;* Last Update : May 11, 1993 [JLB] *
;* *
;* Converted to 32Bit -- JAW *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL C Processor :NEAR
PROC_80386 equ 0
PROC_80486 equ 1
PROC_80586 equ 2
DATASEG
cpu_id_586 dw 0
CODESEG
PROC Processor C near
USES ebx
LOCAL ptype:WORD
pushfd
; At least a 386 -- check for 486.
mov [WORD PTR ptype],PROC_80386 ; 80386
pushfd
pop eax
mov ebx,eax
xor eax,40000h
push eax
popfd
pushfd
pop eax
xor eax,ebx
je short ??fini
; At least a 486 -- check for 586(Pentium)
mov [ptype],PROC_80486 ; 80486
; Some machines have a problem with this fLAG
; and thus make us think they are a 586 but they are
; really a 486. A possible way around this is to
; capture the Illegal instruction vector, then do
; an instruction only available on the 586.
; for now this is just commented out
pushfd
pop eax
mov ebx,eax
xor eax,200000h
push eax
popfd
pushfd
pop eax
xor eax,ebx
je short ??fini
; At least a 586(Pentium) -- check for higher.
mov [ptype],PROC_80586 ; 80486
; mov eax,1
; DW 0fA2h ; CPUID opcode.
; shr ax,8
; and ax,0fh
; inc ax
; inc ax
; mov [cpu_id_586],ax
; Final cleanup and exit.
??fini:
popfd
sub eax,eax
mov ax,[ptype]
ret
ENDP Processor
END

View File

@@ -0,0 +1,165 @@
;
; 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/wwlib32/system/rcs/devices.asm 1.2 1994/04/28 12:41:41 jeff_wilson 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 : DEVICES.ASM *
;* *
;* Programmer : Christopher Yates *
;* *
;* Last Update : 12 December, 1990 [CY] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* *
; VOID Get_Devices(VOID); *
; WORD Is_Device_Real(WORD drive); *
;* *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;----------------------------------------------------------------------------
IDEAL
P386
MODEL USE32 FLAT
GLOBAL Get_Devices :NEAR
GLOBAL Is_Device_Real :NEAR
GLOBAL MaxDevice :BYTE
GLOBAL DefaultDrive :BYTE
; ----------------------------------------------------------------
;
; Here are prototypes for the routines defined within this module:
;
; VOID Get_Devices(VOID);
; WORD Is_Device_Real(WORD drive);
;
; ----------------------------------------------------------------
CODESEG
;***********************************************************
;
; GET_DEVICES
;
; VOID Get_Devices(VOID);
;
; This routine establishes the default disk drive and the maximum drive
; available in the current system.
;
;*
DOS equ 21h
PROC Get_Devices C near
USES eax,ebx,edx
sub eax,eax
mov ah,25 ; get current drive service
int DOS ; drive returned in al
mov [DefaultDrive],al ; save it
mov dl,al
mov ah,14 ; set current as current drive
int DOS
dec al ; al = max drives, make it n - 1
xor ah,ah ; clear high byte
mov edx,eax ; use dx to go backward to find out
sub ebx,ebx
??back_loop:
mov bl,dl ; find out about the drive in dl
inc bl
mov eax,0440Eh ; get the physical drive associated
int DOS ; with this letter
jnc short ??later ; if c clear, no error
cmp al,0Fh ; was it invalid? (0Fh = invalid)
jne short ??later ; yes, so LATER
dec edx
jmp ??back_loop ; try, try again
??later:
mov eax,edx ; restore ax
mov [MaxDevice],al ; save the max drive #
ret
ENDP Get_Devices
;***************************************************************
;***************************************************************
;
; IS_DEVICE_REAL
;
; WORD Is_Device_Real(WORD drive);
;
; This routine will tell whether or not a device is a true
; phisical one. Send it the drive # to check.
;
;*
PROC Is_Device_Real C near
USES ebx,edx
ARG drive:WORD
sub edx,edx
mov dx,[drive]
??next_drive:
push ebx
mov bl,dl ; find out about the drive in dl
inc bl
mov eax,0440Eh ; get the physical drive associated
int DOS ; with this letter
pop ebx
jnc short ??it_is_real ; jump if no error
cmp al,01 ; 1 = invalid command,
; 0F = invalid device
je short ??real ; 1? it is ok (RAM device)
jmp short ??invalid ; 0Fh, it was not a device
??it_is_real:
cmp al,0 ; was it a fixed device?
je short ??real ; yes, it's ok
dec al ; make it a drive #
cmp al,dl ; is it a valid drive?
je short ??real
??invalid: ; The device is invalid.
mov eax,0
jmp short ??out
??real: ; Return true, for valid device.
mov eax,1
??out:
ret
ENDP Is_Device_Real
;***************************************************************
END


View File

@@ -0,0 +1,204 @@
;
; 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/wwlib32/system/rcs/devtable.asm 1.2 1994/04/28 12:41:29 jeff_wilson 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 : DEVTABLE.ASM *
;* *
;* Programmer : Christopher Yates *
;* *
;* Last Update : 12 December, 1990 [CY] *
;* *
;* Updated to 32bit protected mode JAW *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* *
; VOID Init_Device_Table(BYTE *table); *
; WORD Max_Device(VOID); *
;* *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
DOS equ 21h
GLOBAL Max_Device :NEAR
GLOBAL get_max_device :NEAR
GLOBAL Init_Device_Table :NEAR
CODESEG
; ----------------------------------------------------------------
;
; Here are prototypes for the routines defined within this module:
;
; VOID Init_Device_Table(BYTE *table);
; WORD Max_Device(VOID);
;
; ----------------------------------------------------------------
;----------------------------------------------------------------------------
;
; WORD Max_Device(VOID);
;
PROC Max_Device C NEAR
call get_max_device ; get max devices in ax
ret
ENDP Max_Device
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;
;
; returns max devices in AX
PROC get_max_device C NEAR
USES ebx,edx
mov ah,25 ; get current drive service
int DOS ; drive returned in al
mov dl,al
mov ah,14 ; set current as current drive
int DOS
dec al ; al = max drives, make it n - 1
xor ah,ah ; clear high byte
sub edx,edx
mov edx,eax ; use dx to go backward to find out
; if DOS is lying (down)
??back_loop:
push ds
push ebx
mov bl,dl ; find out about the drive in dl
inc bl
mov eax,0440Eh ; get the physical drive associated
int DOS ; with this letter
pop ebx
pop ds
jnc short ??later ; if c clear, no error
cmp al,0Fh ; was it invalid? (0Fh = invalid)
jne short ??later ; yes, so LATER
dec edx
jmp ??back_loop ; try, try again
??later:
mov eax,edx ; restore ax
ret
ENDP get_max_device
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;
; VOID Init_Device_Table(BYTE *table);
;
PROC Init_Device_Table C NEAR
USES eax,ebx,edi,edx
ARG table:DWORD ; Pointer to device table.
LOCAL curr_drive:BYTE ; Copy of current drive number.
mov edi,[table]
call get_max_device ; get max devices in ax
add edi,eax
std
mov [curr_drive],al ; save it
??next_drive:
mov dl,[curr_drive] ; copy current drive #
cmp dl,0FFh ; are we done?
je short ??later ; if so, later
dec [curr_drive] ; dec our local drive #
push ds
push ebx
mov bl,dl ; find out about the drive in dl
inc bl
mov eax,0440Eh ; get the physical drive associated
int DOS ; with this letter
pop ebx
pop ds
jnc short ??it_is_real ; jump if no error
cmp al,01 ; 1 = invalid command,
; 0F = invalid device
je short ??set_as_current ; 1? it is ok (RAM device)
jmp short ??invalid ; 0Fh, it was not a device
??it_is_real:
cmp al,0 ; was it a fixed device?
je short ??set_as_current ; yes, it's ok
dec al ; make it a drive #
cmp al,dl ; is it a valid drive?
je short ??set_as_current
;
; Device was logical and not active, so clear the entry
;
??invalid:
xor al,al
stosb
cmp [curr_drive],0 ; are we done checking?
jge ??next_drive ; no, go to next
jmp short ??later
??set_as_current:
mov al,1
stosb
cmp dl,0 ; are we before the A drive (invalid)
jl short ??later ; yes, we are done checking
jmp ??next_drive ; keep processing
??later:
cld
ret
ENDP Init_Device_Table
;----------------------------------------------------------------------------
END


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,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();
}

File diff suppressed because it is too large Load Diff

257
WIN32LIB/SRCDEBUG/DS_DN.ASM Normal file
View File

@@ -0,0 +1,257 @@
;
; 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 : Draw Shape Routines for library. *
;* *
;* File Name : DS_DN.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : September 6, 1994 [IML] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Draw_Normal -- Draws a normal row of pixels to the viewport *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;***************************************************************************
;* Draw_Normal -- Draws a normal row of pixels to the viewport *
;* *
;* INPUT: *
;* ECX = number of pixels (not bytes) to draw *
;* EDX = XTotal initializer value *
;* ESI = shape (source) buffer address *
;* EDI = viewport (destination) address *
;* [WidthCount] = remaining bytes on the line *
;* *
;* OUTPUT: *
;* ESI - updated to current location in the shape data *
;* EDI - incr/decr by # pixels (not bytes) drawn/skipped *
;* [WidthCount] - bytes remaining on the line *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 04/14/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 06/02/1994 BR : Converted to 32-bit. *
;* 08/09/1994 IML : Optimized for 32-bit. *
;* 09/06/1994 IML : Integrated p_* and ds_* routines. *
;*=========================================================================*
PROC Draw_Normal NOLANGUAGE NEAR
mov [StashEDX],edx ; save edx
mov edx,[Flags]
mov eax,0 ; init to zero
sub [WidthCount],ecx ; decrement bytes remaining by pixels
; to draw
;--------------------------------------------------------------------
; Drawing Loop:
; - Get a data byte
; - If it's a 0, handle the run:
; - get repetition value
; - add it to EDI
; - subtract it from [WidthCount]
; - subtract it from ECX
; - if ECX>0, draw again, else exit
; - Otherwise:
; - draw the pixel
; - increment EDI to next pixel location
; - decrement [WidthCount]
; - loop until ECX is 0
;--------------------------------------------------------------------
test edx,SHAPE_EFFECTS ; are any effects flags set?
jnz short ??general_draw_continue ; if so use the general purpose loop
;--------------------------------------------------------------------
; Extra fast draw loop for shapes with no flags set.
;--------------------------------------------------------------------
??fast_draw_loop:
mov al,[esi] ; get a byte of the source
inc esi
or eax,eax ; is the byte a transparent run?
jz short ??fast_is_run ; if yes then handle the run
mov [edi],al ; store color value to viewport
inc edi ; point to next viewport pixel
dec ecx ; any source pixels left?
jnz short ??fast_draw_loop ; if not then go home
jmp ??out
??fast_is_run:
mov al,[esi]
inc esi
add edi,eax ; move the viewport pointer
sub ecx,eax ; chop down the width to do
jg short ??fast_draw_loop ; while more to do, loop back up
jmp ??out
;--------------------------------------------------------------------
; General purpose draw loop for shapes with one or more flags set.
;--------------------------------------------------------------------
??general_draw_loop:
test edx,SHAPE_FADING ; if fading is enabled test for
jz short ??no_fading_draw_loop ; transparency
or eax,eax
jz short ??is_transparent
??no_fading_draw_loop:
mov [edi],al ; store color value to viewport
??is_transparent:
inc edi ; point to next viewport pixel
dec ecx ; any source pixels left?
jz ??out ; if not then go home
??general_draw_continue:
mov al,[esi] ; get a byte of the source
inc esi
or eax,eax ; is the byte a transparent run?
jz ??general_is_run ; if yes then handle the run
??test_priority:
test edx,SHAPE_PRIORITY
jnz short ??priority
??test_predator:
test edx,SHAPE_PREDATOR
jnz short ??predator
??test_compact:
test edx,SHAPE_COMPACT
jnz ??compact
??test_shadow:
test edx,SHAPE_SHADOW
jnz ??shadow
??test_translucency:
test edx,SHAPE_GHOST
jz short ??test_fading
mov ebx,[IsTranslucent] ; is it a translucent color?
mov bh,[BYTE PTR ebx + eax]
or bh,bh
js short ??test_fading
and ebx,0FF00h ; clear all of ebx except bh
; we have the index to the translation table
; ((trans_colour * 256) + dest colour)
mov al,[edi] ; mov pixel at destination to al
add ebx,[Translucent] ; get the ptr to it!
; Add the (trans_color * 256) of the translation equ.
mov al,[BYTE PTR ebx + eax] ; get new pixel in al
jmp short ??test_fading
??test_fading:
test edx,SHAPE_FADING
jnz ??fading
jmp short ??general_draw_loop
??priority:
mov ebx,[MaskAdjust] ; get mask page offset
mov bl,[BYTE PTR ebx + edi] ; get mask value
and bl,CLEAR_UNUSED_BITS ; clear unused bits
cmp [PriLevel],bl ; are we in front of
jge short ??test_predator ; background?
mov ebx,[BackAdjust] ; get background page offset
mov al,[BYTE PTR ebx + edi] ; get background pixel
jmp ??general_draw_loop
??predator:
mov ebx,[PartialCount]
add ebx,[PartialPred]
or bh,bh
jnz short ??draw_pred ; is this a predator pixel?
mov [PartialCount],ebx
jmp short ??test_compact
??draw_pred:
xor bh,bh
mov [PartialCount],ebx
mov ebx,[PredValue] ; pick up a color offset a pseudo-
; random amount from the current
mov al,[edi + ebx] ; viewport address
jmp ??general_draw_loop
??compact:
mov ebx,[ColorTable] ; get the address of the color table
mov al,[BYTE PTR ebx + eax] ; convert it into the proper byte
jmp ??test_shadow
??shadow:
cmp al,SHADOW_COL
jne ??test_translucency ; is the table value a magic number?
mov al,[edi] ; get the destination color and
mov ebx,[ShadowingTable] ; index into the shadow table
mov al,[BYTE PTR ebx + eax]
jmp ??general_draw_loop
??fading:
mov [StashECX],ecx ; preserve ecx for later
mov ebx,[FadingTable] ; run color through fading table
mov ecx,[FadingNum]
??fade_loop:
mov al, [BYTE PTR ebx + eax]
dec ecx
jnz short ??fade_loop
mov ecx,[StashECX] ; restore ecx for main draw loop
jmp ??general_draw_loop
??general_is_run:
mov al,[esi]
inc esi
add edi,eax ; move the viewport pointer
sub ecx,eax ; chop down the width to do
jg ??general_draw_continue ; while more to do, loop back up
??out:
add [WidthCount],ecx ; adjust for source ending in a run
mov edx,[StashEDX]
ret
ENDP Draw_Normal
END
;**************************** End of ds_dn.asm *****************************

257
WIN32LIB/SRCDEBUG/DS_DR.ASM Normal file
View File

@@ -0,0 +1,257 @@
;
; 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 : Draw Shape Routines for library. *
;* *
;* File Name : DS_DR.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : September 6, 1994 [IML] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Draw_Reverse -- Draws a reversed row of pixels to the viewport *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;***************************************************************************
;* Draw_Reverse -- Draws a reversed row of pixels to the viewport *
;* *
;* INPUT: *
;* ECX = number of pixels (not bytes) to draw *
;* EDX = XTotal initializer value *
;* ESI = shape (source) buffer address *
;* EDI = viewport (destination) address *
;* [WidthCount] = remaining bytes on the line *
;* *
;* OUTPUT: *
;* ESI - updated to current location in the shape data *
;* EDI - incr/decr by # pixels (not bytes) drawn/skipped *
;* [WidthCount] - bytes remaining on the line *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 04/14/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 06/02/1994 BR : Converted to 32-bit. *
;* 08/09/1994 IML : Optimized for 32-bit. *
;* 09/06/1994 IML : Integrated p_* and ds_* routines. *
;*=========================================================================*
PROC Draw_Reverse NOLANGUAGE NEAR
mov [StashEDX],edx ; save edx
mov edx,[Flags]
mov eax,0 ; init to zero
sub [WidthCount],ecx ; decrement bytes remaining by pixels
; to draw
;--------------------------------------------------------------------
; Drawing Loop:
; - Get a data byte
; - If it's a 0, handle the run:
; - get repetition value
; - subtract it from EDI
; - subtract it from [WidthCount]
; - subtract it from ECX
; - if ECX>0, draw again, else exit
; - Otherwise:
; - draw the pixel
; - increment EDI to next pixel location
; - decrement [WidthCount]
; - loop until ECX is 0
;--------------------------------------------------------------------
test edx,SHAPE_EFFECTS ; are any effects flags set?
jnz short ??general_draw_continue ; if so use the general purpose loop
;--------------------------------------------------------------------
; Extra fast draw loop for shapes with no flags set.
;--------------------------------------------------------------------
??fast_draw_loop:
mov al,[esi] ; get a byte of the source
inc esi
or eax,eax ; is the byte a transparent run?
jz short ??fast_is_run ; if yes then handle the run
mov [edi],al ; store color value to viewport
dec edi ; point to next viewport pixel
dec ecx ; any source pixels left?
jnz short ??fast_draw_loop ; if not then go home
jmp ??out
??fast_is_run:
mov al,[esi]
inc esi
sub edi,eax ; move the viewport pointer
sub ecx,eax ; chop down the width to do
jg short ??fast_draw_loop ; while more to do, loop back up
jmp ??out
;--------------------------------------------------------------------
; General purpose draw loop for shapes with one or more flags set.
;--------------------------------------------------------------------
??general_draw_loop:
test edx,SHAPE_FADING ; if fading is enabled test for
jz short ??no_fading_draw_loop ; transparency
or eax,eax
jz short ??is_transparent
??no_fading_draw_loop:
mov [edi],al ; store color value to viewport
??is_transparent:
dec edi ; point to next viewport pixel
dec ecx ; any source pixels left?
jz ??out ; if not then go home
??general_draw_continue:
mov al,[esi] ; get a byte of the source
inc esi
or eax,eax ; is the byte a transparent run?
jz ??general_is_run ; if yes then handle the run
??test_priority:
test edx,SHAPE_PRIORITY
jnz short ??priority
??test_predator:
test edx,SHAPE_PREDATOR
jnz short ??predator
??test_compact:
test edx,SHAPE_COMPACT
jnz ??compact
??test_shadow:
test edx,SHAPE_SHADOW
jnz ??shadow
??test_translucency:
test edx,SHAPE_GHOST
jz short ??test_fading
mov ebx,[IsTranslucent] ; is it a translucent color?
mov bh,[BYTE PTR ebx + eax]
or bh,bh
js short ??test_fading
and ebx,0FF00h ; clear all of ebx except bh
; we have the index to the translation table
; ((trans_colour * 256) + dest colour)
mov al,[edi] ; mov pixel at destination to al
add ebx,[Translucent] ; get the ptr to it!
; Add the (trans_color * 256) of the translation equ.
mov al,[BYTE PTR ebx + eax] ; get new pixel in al
??test_fading:
test edx,SHAPE_FADING
jnz ??fading
jmp short ??general_draw_loop
??priority:
mov ebx,[MaskAdjust] ; get mask page offset
mov bl,[BYTE PTR ebx + edi] ; get mask value
and bl,CLEAR_UNUSED_BITS ; clear unused bits
cmp [PriLevel],bl ; are we in front of
jge short ??test_predator ; background?
mov ebx,[BackAdjust] ; get background page offset
mov al,[BYTE PTR ebx + edi] ; get background pixel
jmp ??general_draw_loop
??predator:
mov ebx,[PartialCount]
add ebx,[PartialPred]
or bh,bh
jnz short ??draw_pred ; is this a predator pixel?
mov [PartialCount],ebx
jmp short ??test_compact
??draw_pred:
xor bh,bh
mov [PartialCount],ebx
mov ebx,[PredValue] ; pick up a color offset a pseudo-
; random amount from the current
mov al,[edi + ebx] ; viewport address
jmp ??general_draw_loop
??compact:
mov ebx,[ColorTable] ; get the address of the color table
mov al,[BYTE PTR ebx + eax] ; convert it into the proper byte
jmp ??test_shadow
??shadow:
cmp al,SHADOW_COL
jne ??test_translucency ; is the table value a magic number?
mov al,[edi] ; get the destination color and
mov ebx,[ShadowingTable] ; index into the shadow table
mov al,[BYTE PTR ebx + eax]
jmp ??general_draw_loop
??fading:
mov [StashECX],ecx ; preserve ecx for later
mov ebx,[FadingTable] ; run color through fading table
mov ecx,[FadingNum]
??fade_loop:
mov al, [BYTE PTR ebx + eax]
dec ecx
jnz short ??fade_loop
mov ecx,[StashECX] ; restore ecx for main draw loop
jmp ??general_draw_loop
??general_is_run:
mov al,[esi]
inc esi
sub edi,eax ; move the viewport pointer
sub ecx,eax ; chop down the width to do
jg ??general_draw_continue ; while more to do, loop back up
??out:
add [WidthCount],ecx ; adjust for source ending in a run
mov edx,[StashEDX]
ret
ENDP Draw_Reverse
END
;**************************** End of ds_dr.asm *****************************

341
WIN32LIB/SRCDEBUG/DS_DS.ASM Normal file
View File

@@ -0,0 +1,341 @@
;
; 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 : Draw Shape Routines for library. *
;* *
;* File Name : DS_DS.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : September 6, 1994 [IML] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Draw_Scale -- Draws a scaled row of pixels to the viewport *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;***************************************************************************
;* Draw_Scale -- Draws a scaled row of pixels to the viewport *
;* *
;* INPUT: *
;* ECX = number of pixels (not bytes) to draw *
;* EDX = XTotal initializer value *
;* ESI = shape (source) buffer address *
;* EDI = viewport (destination) address *
;* [WidthCount] = remaining bytes on the line *
;* *
;* OUTPUT: *
;* ESI - updated to current location in the shape data *
;* EDI - incr/decr by # pixels (not bytes) drawn/skipped *
;* [WidthCount] - bytes remaining on the line *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 04/14/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 06/02/1994 BR : Converted to 32-bit. *
;* 08/09/1994 IML : Optimized for 32-bit. *
;* 09/06/1994 IML : Integrated p_* and ds_* routines. *
;*=========================================================================*
PROC Draw_Scale NOLANGUAGE NEAR
mov eax,0 ; init to 0
test [Flags],SHAPE_EFFECTS
jnz short ??general_draw_continue
jmp short ??fast_draw_continue
;--------------------------------------------------------------------
; Extra fast draw loop for shapes with no flags set.
;--------------------------------------------------------------------
;--------------------------------------------------------------------
; Load a new byte:
; - read the byte into AL
; - if it's a run, deal with it
; - otherwise,
; - decrement [WidthCount]
; - update EDX with [ScaleX]
; - see if it's drawable (upon proc entry, it won't be)
; - yes: draw a pixel
; - no : load a new byte
;--------------------------------------------------------------------
??fast_draw_loop:
mov al,[esi] ; get the next pixel from the source
inc esi
or eax,eax
jz short ??fast_is_run ; deal with a run
dec [WidthCount] ; count down # bytes processed
add edx,[ScaleX] ; add in the scale value
??fast_draw_continue:
or dh,dh ; are there any pixels to draw?
jz short ??fast_draw_loop
;--------------------------------------------------------------------
; Draw one pixel:
; - draw the pixel
; - increment destination pointer
; - decrement high byte of EDX (X-scale accumulator)
; - loop (while ECX>0) to see if it's drawable
;--------------------------------------------------------------------
mov [edi],al ; store color value to viewport
inc edi ; increment the destination index
dec dh ; decrement the pixels to write
dec ecx
jnz short ??fast_draw_continue
jmp ??out ; get the heck outta here
;--------------------------------------------------------------------
; Handle a run:
; - Get the run repetition value
; - subract it from [WidthCount]
; - multiply it by [ScaleX]
; - put high bytes from mul into EAX, low byte into DL (roundoff bits)
; - add high bytes (# pixels) to EDI
; - subtract them from ECX
; - clear EAX
; - if ECX>0, go get next byte
;--------------------------------------------------------------------
??fast_is_run:
mov al,[esi] ; get number of repeated values
inc esi
sub [WidthCount],eax ; adjust the remaining byte width
mov ebx,edx ; preserve dx for the multiply
mul [ScaleX] ; EDX:EAX = # pixels + roundoff bits
add eax,ebx ; add in the current x-total
mov edx,eax ; (assume EDX is empty)
shr eax,8 ; EAX = # pixels skipped
and edx,00FFh ; keep only low byte
add edi,eax ; add to EDI
sub ecx,eax ; subtract it from ECX
mov eax,0 ; clear EAX
or ecx,ecx
jg short ??fast_draw_loop ; if more to draw, process new byte
jmp ??out
;--------------------------------------------------------------------
; General purpose draw loop for shapes with one or more flags set.
;--------------------------------------------------------------------
;--------------------------------------------------------------------
; Load a new byte:
; - read the byte into AL
; - if it's a run, deal with it
; - otherwise,
; - decrement [WidthCount]
; - update EDX with [ScaleX]
; - see if it's drawable (upon proc entry, it won't be)
; - yes: draw a pixel
; - no : load a new byte
;--------------------------------------------------------------------
??general_draw_loop:
mov al,[esi] ; get the next pixel from the source
inc esi
or eax,eax
jz ??general_is_run ; deal with a run
dec [WidthCount] ; count down # bytes processed
add edx,[ScaleX] ; add in the scale value
??general_draw_continue:
or dh,dh ; are there any pixels to draw?
jz short ??general_draw_loop
;--------------------------------------------------------------------
; Draw one pixel:
; - draw the pixel
; - increment destination pointer
; - decrement high byte of EDX (X-scale accumulator)
; - loop (while ECX>0) to see if it's drawable
;--------------------------------------------------------------------
??draw:
mov [StashReg],eax ; save eax
mov [StashEDX],edx ; save edx
mov edx,[Flags]
??test_priority:
test edx,SHAPE_PRIORITY
jnz short ??priority
??test_predator:
test edx,SHAPE_PREDATOR
jnz short ??predator
??test_compact:
test edx,SHAPE_COMPACT
jnz ??compact
??test_shadow:
test edx,SHAPE_SHADOW
jnz ??shadow
??test_translucency:
test edx,SHAPE_GHOST
jnz ??translucency
??test_fading:
test edx,SHAPE_FADING
jnz ??fading
??test_transparency:
test edx,SHAPE_FADING ; if fading is enabled test for
jz short ??no_fading_draw_loop ; transparency
or eax,eax
jz short ??is_transparent
??no_fading_draw_loop:
mov [edi],al ; store color value to viewport
??is_transparent:
mov eax,[StashReg] ; restore eax
mov edx,[StashEDX] ; restore edx
inc edi ; increment the destination index
dec dh ; decrement the pixels to write
dec ecx
jnz ??general_draw_continue
jmp ??out ; get the heck outta here
??priority:
mov ebx,[MaskAdjust] ; get mask page offset
mov bl,[BYTE PTR ebx + edi] ; get mask value
and bl,CLEAR_UNUSED_BITS ; clear unused bits
cmp [PriLevel],bl ; are we in front of
jge short ??test_predator ; background?
mov ebx,[BackAdjust] ; get background page offset
mov al,[BYTE PTR ebx + edi] ; get background pixel
jmp short ??test_transparency
??predator:
mov ebx,[PartialCount]
add ebx,[PartialPred]
or bh,bh
jnz short ??draw_pred ; is this a predator pixel?
mov [PartialCount],ebx
jmp ??test_compact
??draw_pred:
xor bh,bh
mov [PartialCount],ebx
mov ebx,[PredValue] ; pick up a color offset a pseudo-
; random amount from the current
mov al,[edi + ebx] ; viewport address
jmp short ??test_transparency
??compact:
mov ebx,[ColorTable] ; get the address of the color table
mov al,[BYTE PTR ebx + eax] ; convert it into the proper byte
jmp ??test_shadow
??shadow:
cmp al,SHADOW_COL
jne ??test_translucency ; is the table value a magic number?
mov al,[edi] ; get the destination color and
mov ebx,[ShadowingTable] ; index into the shadow table
mov al,[BYTE PTR ebx + eax]
jmp ??test_transparency
??fading:
mov [StashECX],ecx ; preserve ecx for later
mov ebx,[FadingTable] ; run color through fading table
mov ecx,[FadingNum]
??fade_loop:
mov al, [BYTE PTR ebx + eax]
dec ecx
jnz short ??fade_loop
mov ecx,[StashECX] ; restore ecx for main draw loop
jmp ??test_transparency
??translucency:
mov ebx,[IsTranslucent] ; is it a translucent color?
mov bh,[BYTE PTR ebx + eax]
or bh,bh
js ??test_fading
and ebx,0FF00h ; clear all of ebx except bh
; we have the index to the translation table
; ((trans_colour * 256) + dest colour)
mov al,[edi] ; mov pixel at destination to al
add ebx,[Translucent] ; get the ptr to it!
; Add the (trans_color * 256) of the translation equ.
mov al,[BYTE PTR ebx + eax] ; get new pixel in al
jmp ??test_fading
;--------------------------------------------------------------------
; Handle a run:
; - Get the run repetition value
; - subract it from [WidthCount]
; - multiply it by [ScaleX]
; - put high bytes from mul into EAX, low byte into DL (roundoff bits)
; - add high bytes (# pixels) to EDI
; - subtract them from ECX
; - clear EAX
; - if ECX>0, go get next byte
;--------------------------------------------------------------------
??general_is_run:
mov al,[esi] ; get number of repeated values
inc esi
sub [WidthCount],eax ; adjust the remaining byte width
mov ebx,edx ; preserve dx for the multiply
mul [ScaleX] ; EDX:EAX = # pixels + roundoff bits
add eax,ebx ; add in the current x-total
mov edx,eax ; (assume EDX is empty)
shr eax,8 ; EAX = # pixels skipped
and edx,00FFh ; keep only low byte
add edi,eax ; add to EDI
sub ecx,eax ; subtract it from ECX
mov eax,0 ; clear EAX
or ecx,ecx
jg ??general_draw_loop ; if more to draw, process new byte
??out:
ret ; lets get out of here
ENDP Draw_Scale
END
;**************************** End of ds_ds.asm ******************************

View File

@@ -0,0 +1,341 @@
;
; 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 : Draw Shape Routines for library. *
;* *
;* File Name : DS_DSR.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : September 6, 1994 [IML] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Draw_Scale_Reverse -- Draws a scaled row of pixels to the viewport *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;*******p********************************************************************
;* Draw_Scale_Reverse -- Draws a scaled row of pixels to the viewport *
;* *
;* INPUT: *
;* ECX = number of pixels (not bytes) to draw *
;* EDX = XTotal initializer value *
;* ESI = shape (source) buffer address *
;* EDI = viewport (destination) address *
;* [WidthCount] = remaining bytes on the line *
;* *
;* OUTPUT: *
;* ESI - updated to current location in the shape data *
;* EDI - incr/decr by # pixels (not bytes) drawn/skipped *
;* [WidthCount] - bytes remaining on the line *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 04/14/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 06/02/1994 BR : Converted to 32-bit. *
;* 08/09/1994 IML : Optimized for 32-bit *
;* 09/06/1994 IML : Integrated p_* and ds_* routines. *
;*=========================================================================*
PROC Draw_Scale_Reverse NOLANGUAGE NEAR
mov eax,0 ; init to 0
test [Flags],SHAPE_EFFECTS
jnz short ??general_draw_continue
jmp short ??fast_draw_continue
;--------------------------------------------------------------------
; Extra fast draw loop for shapes with no flags set.
;--------------------------------------------------------------------
;--------------------------------------------------------------------
; Load a new byte:
; - read the byte into AL
; - if it's a run, deal with it
; - otherwise,
; - decrement [WidthCount]
; - update EDX with [ScaleX]
; - see if it's drawable (upon proc entry, it won't be)
; - yes: draw a pixel
; - no : load a new byte
;--------------------------------------------------------------------
??fast_draw_loop:
mov al,[esi] ; get the next pixel from the source
inc esi
or eax,eax
jz short ??fast_is_run ; deal with a run
dec [WidthCount] ; count down # bytes processed
add edx,[ScaleX] ; add in the scale value
??fast_draw_continue:
or dh,dh ; are there any pixels to draw?
jz short ??fast_draw_loop
;--------------------------------------------------------------------
; Draw one pixel:
; - draw the pixel
; - increment destination pointer
; - decrement high byte of EDX (X-scale accumulator)
; - loop (while ECX>0) to see if it's drawable
;--------------------------------------------------------------------
mov [edi],al ; store color value to viewport
dec edi ; decrement the destination index
dec dh ; decrement the pixels to write
dec ecx
jnz short ??fast_draw_continue
jmp ??out ; get the heck outta here
;--------------------------------------------------------------------
; Handle a run:
; - Get the run repetition value
; - subract it from [WidthCount]
; - multiply it by [ScaleX]
; - put high bytes from mul into EAX, low byte into DL (roundoff bits)
; - add high bytes (# pixels) to EDI
; - subtract them from ECX
; - clear EAX
; - if ECX>0, go get next byte
;--------------------------------------------------------------------
??fast_is_run:
mov al,[esi] ; get number of repeated values
inc esi
sub [WidthCount],eax ; adjust the remaining byte width
mov ebx,edx ; preserve dx for the multiply
mul [ScaleX] ; EDX:EAX = # pixels + roundoff bits
add eax,ebx ; add in the current x-total
mov edx,eax ; (assume EDX is empty)
shr eax,8 ; EAX = # pixels skipped
and edx,00FFh ; keep only low byte
sub edi,eax ; sub from EDI
sub ecx,eax ; subtract it from ECX
mov eax,0 ; clear EAX
or ecx,ecx
jg short ??fast_draw_loop ; if more to draw, process new byte
jmp ??out
;--------------------------------------------------------------------
; General purpose draw loop for shapes with one or more flags set.
;--------------------------------------------------------------------
;--------------------------------------------------------------------
; Load a new byte:
; - read the byte into AL
; - if it's a run, deal with it
; - otherwise,
; - decrement [WidthCount]
; - update EDX with [ScaleX]
; - see if it's drawable (upon proc entry, it won't be)
; - yes: draw a pixel
; - no : load a new byte
;--------------------------------------------------------------------
??general_draw_loop:
mov al,[esi] ; get the next pixel from the source
inc esi
or eax,eax
jz ??general_is_run ; deal with a run
dec [WidthCount] ; count down # bytes processed
add edx,[ScaleX] ; add in the scale value
??general_draw_continue:
or dh,dh ; are there any pixels to draw?
jz short ??general_draw_loop
;--------------------------------------------------------------------
; Draw one pixel:
; - draw the pixel
; - increment destination pointer
; - decrement high byte of EDX (X-scale accumulator)
; - loop (while ECX>0) to see if it's drawable
;--------------------------------------------------------------------
??draw:
mov [StashReg],eax ; save eax
mov [StashEDX],edx ; save edx
mov edx,[Flags]
??test_priority:
test edx,SHAPE_PRIORITY
jnz short ??priority
??test_predator:
test edx,SHAPE_PREDATOR
jnz short ??predator
??test_compact:
test edx,SHAPE_COMPACT
jnz ??compact
??test_shadow:
test edx,SHAPE_SHADOW
jnz ??shadow
??test_translucency:
test edx,SHAPE_GHOST
jnz ??translucency
??test_fading:
test edx,SHAPE_FADING
jnz ??fading
??test_transparency:
test edx,SHAPE_FADING ; if fading is enabled test for
jz short ??no_fading_draw_loop ; transparency
or eax,eax
jz short ??is_transparent
??no_fading_draw_loop:
mov [edi],al ; store color value to viewport
??is_transparent:
mov eax,[StashReg] ; restore eax
mov edx,[StashEDX] ; restore edx
dec edi ; decrement the destination index
dec dh ; decrement the pixels to write
dec ecx
jnz ??general_draw_continue
jmp ??out ; get the heck outta here
??priority:
mov ebx,[MaskAdjust] ; get mask page offset
mov bl,[BYTE PTR ebx + edi] ; get mask value
and bl,CLEAR_UNUSED_BITS ; clear unused bits
cmp [PriLevel],bl ; are we in front of
jge short ??test_predator ; background?
mov ebx,[BackAdjust] ; get background page offset
mov al,[BYTE PTR ebx + edi] ; get background pixel
jmp short ??test_transparency
??predator:
mov ebx,[PartialCount]
add ebx,[PartialPred]
or bh,bh
jnz short ??draw_pred ; is this a predator pixel?
mov [PartialCount],ebx
jmp ??test_compact
??draw_pred:
xor bh,bh
mov [PartialCount],ebx
mov ebx,[PredValue] ; pick up a color offset a pseudo-
; random amount from the current
mov al,[edi + ebx] ; viewport address
jmp short ??test_transparency
??compact:
mov ebx,[ColorTable] ; get the address of the color table
mov al,[BYTE PTR ebx + eax] ; convert it into the proper byte
jmp ??test_shadow
??shadow:
cmp al,SHADOW_COL
jne ??test_translucency ; is the table value a magic number?
mov al,[edi] ; get the destination color and
mov ebx,[ShadowingTable] ; index into the shadow table
mov al,[BYTE PTR ebx + eax]
jmp ??test_transparency
??fading:
mov [StashECX],ecx ; preserve ecx for later
mov ebx,[FadingTable] ; run color through fading table
mov ecx,[FadingNum]
??fade_loop:
mov al, [BYTE PTR ebx + eax]
dec ecx
jnz short ??fade_loop
mov ecx,[StashECX] ; restore ecx for main draw loop
jmp ??test_transparency
??translucency:
mov ebx,[IsTranslucent] ; is it a translucent color?
mov bh,[BYTE PTR ebx + eax]
or bh,bh
js ??test_fading
and ebx,0FF00h ; clear all of ebx except bh
; we have the index to the translation table
; ((trans_colour * 256) + dest colour)
mov al,[edi] ; mov pixel at destination to al
add ebx,[Translucent] ; get the ptr to it!
; Add the (trans_color * 256) of the translation equ.
mov al,[BYTE PTR ebx + eax] ; get new pixel in al
jmp ??test_fading
;--------------------------------------------------------------------
; Handle a run:
; - Get the run repetition value
; - subract it from [WidthCount]
; - multiply it by [ScaleX]
; - put high bytes from mul into EAX, low byte into DL (roundoff bits)
; - add high bytes (# pixels) to EDI
; - subtract them from ECX
; - clear EAX
; - if ECX>0, go get next byte
;--------------------------------------------------------------------
??general_is_run:
mov al,[esi] ; get number of repeated values
inc esi
sub [WidthCount],eax ; adjust the remaining byte width
mov ebx,edx ; preserve dx for the multiply
mul [ScaleX] ; EDX:EAX = # pixels + roundoff bits
add eax,ebx ; add in the current x-total
mov edx,eax ; (assume EDX is empty)
shr eax,8 ; EAX = # pixels skipped
and edx,00FFh ; keep only low byte
sub edi,eax ; sub from EDI
sub ecx,eax ; subtract it from ECX
mov eax,0 ; clear EAX
or ecx,ecx
jg ??general_draw_loop ; if more to draw, process new byte
??out:
ret ; lets get out of here
ENDP Draw_Scale_Reverse
END
;*************************** End of ds_dsr.asm ******************************

View File

@@ -0,0 +1,118 @@
;
; 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 : Draw Shape Routines for library. *
;* *
;* File Name : DS_LRS.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : June 2, 1994 [BR] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Left_Reverse_Skip -- Skips bytes in a data stream *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;********************* Model & Processor Directives ************************
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;***************************************************************************
;* Left_Reverse_Skip -- Skips bytes in a data stream *
;* *
;* INPUT: *
;* ECX = number of uncompressed bytes to skip *
;* ESI = shape (source) buffer data address *
;* EDI = viewport (destination) address *
;* [WidthCount] = shape's width *
;* *
;* OUTPUT: *
;* ECX - negative # pixels overrun, or 0 *
;* EDX - XTotal initializer value (0 since there's no scaling)*
;* ESI - updated to the current location in the shape data *
;* EDI - decremented by # pixels overrun *
;* [WidthCount] - decremented by # bytes skipped *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 04/14/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 05/28/1994 BR : Converted to 32-bit *
;*=========================================================================*
PROC Left_Reverse_Skip NOLANGUAGE NEAR
sub [WidthCount],ecx ; we process ECX bytes of real width
;--------------------------------------------------------------------
; Put shape data address in EDI so we can do a scasb on it
;--------------------------------------------------------------------
xchg esi,edi ; xchange ESI and EDI
jecxz ??out ; exit if ECX is 0 (no bytes to skip)
;--------------------------------------------------------------------
; Search through the string and count down the info we have handled.
; If we find a run (0 followed by a count byte), then handle it.
;--------------------------------------------------------------------
??cliptop:
mov eax,0 ; set al to 0 (we're scanning for 0)
repne scasb ; scan through source data
jz ??on_run ; if it is a run then deal with it
jecxz ??out ; if we're done then get outta here
;--------------------------------------------------------------------
; If we have a run then get the next byte which is the length.
;--------------------------------------------------------------------
??on_run:
mov al,[BYTE PTR edi] ; get the count of zeros to run
inc edi ; advance past the count
inc ecx ; the 0 found doesn't count
sub ecx,eax ; subtract the count from remaining
jg ??cliptop ; if more bytes left, scan again
;--------------------------------------------------------------------
; Put shape address back into ESI, adjust EDI
;--------------------------------------------------------------------
??out:
xchg esi,edi ; xchange ESI and EDI
add edi,ecx ; decrement EDI by overrun pixels
add [WidthCount],ecx ; adjust by # bytes overrun
mov edx,0 ; no scaling, so clear EDX
ret ; return back to the real function
ENDP Left_Reverse_Skip
END
;*************************** End of ds_lrs.asm *****************************


118
WIN32LIB/SRCDEBUG/DS_LS.ASM Normal file
View File

@@ -0,0 +1,118 @@
;
; 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 : Draw Shape Routines for library. *
;* *
;* File Name : DS_LS.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : June 2, 1994 [BR] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Left_Skip -- Skips bytes in a data stream *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;********************* Model & Processor Directives ************************
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;***************************************************************************
;* Left_Skip -- Skips bytes in a data stream *
;* *
;* INPUT: *
;* ECX = number of uncompressed bytes to skip *
;* ESI = shape (source) buffer data address *
;* EDI = viewport (destination) address *
;* [WidthCount] = shape's width *
;* *
;* OUTPUT: *
;* ECX - negative # pixels overrun, or 0 *
;* EDX - XTotal initializer value (0 since there's no scaling)*
;* ESI - updated to the current location in the shape data *
;* EDI - incremented by # pixels overrun *
;* [WidthCount] - decremented by # bytes skipped *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 04/14/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 06/02/1994 BR : Converted to 32-bit *
;*=========================================================================*
PROC Left_Skip NOLANGUAGE NEAR
sub [WidthCount],ecx ; we process ECX bytes of real width
;--------------------------------------------------------------------
; Put shape data address in EDI so we can do a scasb on it
;--------------------------------------------------------------------
xchg esi,edi ; xchange ESI and EDI
jecxz ??out ; exit if ECX is 0 (no bytes to skip)
;--------------------------------------------------------------------
; Search through the string and count down the info we have handled.
; If we find a run (0 followed by a count byte), then handle it.
;--------------------------------------------------------------------
??cliptop:
mov eax,0 ; set al to 0 (we're scanning for 0)
repne scasb ; scan through source data
jz ??on_run ; if it is a run then deal with it
jecxz ??out ; if we're done then get outta here
;--------------------------------------------------------------------
; If we have a run then get the next byte which is the length.
;--------------------------------------------------------------------
??on_run:
mov al,[BYTE PTR edi] ; get the count of zeros to run
inc edi ; advance past the count
inc ecx ; the 0 found doesn't count
sub ecx,eax ; subtract the count from remaining
jg ??cliptop ; if more bytes left, scan again
;--------------------------------------------------------------------
; Put shape address back into ESI, adjust EDI
;--------------------------------------------------------------------
??out:
xchg esi,edi ; xchange ESI and EDI
sub edi,ecx ; increment EDI by overrun pixels
add [WidthCount],ecx ; adjust by # bytes overrun
mov edx,0 ; no scaling, so clear EDX
ret ; return back to the real function
ENDP Left_Skip
END
;**************************** End of ds_ls.asm *****************************


View File

@@ -0,0 +1,159 @@
;
; 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 : Draw Shape Routines for library. *
;* *
;* File Name : DS_LSRS.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : June 2, 1994 [BR] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Left_Scale_Reverse_Skip -- Skips past a scaled row of pixels *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;********************* Model & Processor Directives ************************
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;***************************************************************************
;* Left_Scale_Reverse_Skip -- Skips past a scaled row of pixels *
;* *
;* INPUT: *
;* ECX = number of uncompressed bytes to skip *
;* ESI = shape (source) buffer data address *
;* EDI = viewport (destination) address *
;* [WidthCount] = shape's width *
;* *
;* OUTPUT: *
;* ECX - negative # pixels (not bytes) overrun, or 0 *
;* EDX - XTotal initializer value *
;* ESI - updated to the current location in the shape data *
;* EDI - decremented by # pixels (not bytes) overrun *
;* [WidthCount] - decremented by # bytes skipped *
;* *
;* The value returned in EDX reflects what XTotal's accumulated value *
;* should be at the new pixel location. If no bytes are overrun, this *
;* will be whatever is stored in [XTotalInit] (which will be 0 if no *
;* pixels are left-clipped). *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 04/20/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 06/02/1994 BR : Converted to 32-bit *
;*=========================================================================*
PROC Left_Scale_Reverse_Skip NOLANGUAGE NEAR
sub [WidthCount],ecx ; we process ECX bytes of real width
;--------------------------------------------------------------------
; Put shape data address in EDI so we can do a scasb on it
;--------------------------------------------------------------------
xchg esi,edi ; xchange ESI and EDI
jcxz ??getrem ; exit if no bytes to skip
;--------------------------------------------------------------------
; Search through the string and count down the info we have handled.
; If we find a run (0 followed by a count byte), then handle it.
;--------------------------------------------------------------------
??cliptop:
mov eax,0 ; set al to 0 (we're scanning for 0)
repne scasb ; scan through source data
jz short ??on_run ; if it is a run then deal with it
;--------------------------------------------------------------------
; Default exit point: store default x-scale bits & exit
;--------------------------------------------------------------------
??getrem:
mov edx,[XTotalInit] ; store out the remainder
jmp short ??out ; we're done, get outta here
;--------------------------------------------------------------------
; If we have a run then get the next byte which is the length.
;--------------------------------------------------------------------
??on_run:
mov al,[BYTE PTR edi] ; get the count of zeros to run
inc edi ; advance past the count
inc ecx ; the 0 found doesn't count
sub ecx,eax ; subtract the count from remaining
jg ??cliptop ; if more bytes left, scan again
jz ??getrem ; exactly enough bytes; exit
;--------------------------------------------------------------------
; Overrun exit point: ECX is negative by the # of bytes overrun.
; - adjust [WidthCount] by # of overrun bytes
; - compute the remainder at the new location (EDX)
; - compute the number of destination pixels to skip (ECX)
; - adjust EDI by # of overrun bytes
;--------------------------------------------------------------------
;
;............... adjust [WidthCount] by overrun bytes ...............
;
add [WidthCount],ecx ; adjust overrun in bytes
;
;................. put x-scale roundoff bits in EDX .................
;
mov eax,ecx ; get the number of bytes we overran
neg eax ; negate it since overun is negative
add eax,[LeftClipBytes] ; add the number of bytes we leftclip
mul [ScaleX] ; convert to pixels plus roundoff bits
mov edx,0 ; clear EDX
mov dl,al ; DL = x-scaling roundoff bits
;
;................ put negative overrun pixels in ECX ................
;
shr eax,8 ; EAX = total # left pixels
sub eax,[LeftClipPixels] ; EAX = # pixels overrun
mov ecx,eax ; store # overrun pixels
neg ecx ; make it negative
;
;................ adjust dest ptr by overrun pixels .................
;
sub esi,eax ; decrement ESI (EDI) by overrun pixels
;--------------------------------------------------------------------
; Put shape address back into ESI, adjust EDI
;--------------------------------------------------------------------
??out:
xchg esi,edi ; xchange ESI and EDI
ret ; return back to the real function
ENDP Left_Scale_Reverse_Skip
END
;**************************** End of ds_lsrs.asm ****************************


View File

@@ -0,0 +1,159 @@
;
; 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 : Draw Shape Routines for library. *
;* *
;* File Name : DS_LSS.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : June 2, 1994 [BR] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Left_Scale_Skip -- Skips past a scaled row of pixels on left side *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;********************* Model & Processor Directives ************************
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;***************************************************************************
;* Left_Scale_Skip -- Skips past a scaled row of pixels on left side *
;* *
;* INPUT: *
;* ECX = number of uncompressed bytes to skip *
;* ESI = shape (source) buffer data address *
;* EDI = viewport (destination) address *
;* [WidthCount] = shape's width *
;* *
;* OUTPUT: *
;* ECX - negative # pixels (not bytes) overrun, or 0 *
;* EDX - XTotal initializer value *
;* ESI - updated to the current location in the shape data *
;* EDI - incremented by # pixels (not bytes) overrun *
;* [WidthCount] - decremented by # bytes skipped *
;* *
;* The value returned in EDX reflects what XTotal's accumulated value *
;* should be at the new pixel location. If no bytes are overrun, this *
;* will be whatever is stored in [XTotalInit] (which will be 0 if no *
;* pixels are left-clipped). *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 09/08/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 06/02/1994 BR : Converted to 32-bit *
;*=========================================================================*
PROC Left_Scale_Skip NOLANGUAGE NEAR
sub [WidthCount],ecx ; we process ECX bytes of real width
;--------------------------------------------------------------------
; Put shape data address in EDI so we can do a scasb on it
;--------------------------------------------------------------------
xchg esi,edi ; xchange ESI and EDI
jcxz ??getrem ; exit if no bytes to skip
;--------------------------------------------------------------------
; Search through the string and count down the info we have handled.
; If we find a run (0 followed by a count byte), then handle it.
;--------------------------------------------------------------------
??cliptop:
mov eax,0 ; set al to 0 (we're scanning for 0)
repne scasb ; scan through source data
jz short ??on_run ; if it is a run then deal with it
;--------------------------------------------------------------------
; Default exit point: store default x-scale bits & exit
;--------------------------------------------------------------------
??getrem:
mov edx,[XTotalInit] ; store out the remainder
jmp short ??out ; we're done, get outta here
;--------------------------------------------------------------------
; If we have a run then get the next byte which is the length.
;--------------------------------------------------------------------
??on_run:
mov al,[BYTE PTR edi] ; get the count of zeros to run
inc edi ; advance past the count
inc ecx ; the 0 found doesn't count
sub ecx,eax ; subtract the count from remaining
jg ??cliptop ; if more bytes left, scan again
jz ??getrem ; exactly enough bytes; exit
;--------------------------------------------------------------------
; Overrun exit point: ECX is negative by the # of bytes overrun.
; - adjust [WidthCount] by # of overrun bytes
; - compute the remainder at the new location (EDX)
; - compute the number of destination pixels to skip (ECX)
; - adjust EDI by # of overrun bytes
;--------------------------------------------------------------------
;
;............... adjust [WidthCount] by overrun bytes ...............
;
add [WidthCount],ecx ; adjust overrun in bytes
;
;................. put x-scale roundoff bits in EDX .................
;
mov eax,ecx ; get the number of bytes we overran
neg eax ; negate it since overun is negative
add eax,[LeftClipBytes] ; add the number of bytes we leftclip
mul [ScaleX] ; convert to pixels plus roundoff bits
mov edx,0 ; clear EDX
mov dl,al ; DL = x-scaling roundoff bits
;
;................ put negative overrun pixels in ECX ................
;
shr eax,8 ; EAX = total # left pixels
sub eax,[LeftClipPixels] ; EAX = # pixels overrun
mov ecx,eax ; store # overrun pixels
neg ecx ; make it negative
;
;................ adjust dest ptr by overrun pixels .................
;
add esi,eax ; increment ESI (EDI) by overrun pixels
;--------------------------------------------------------------------
; Put shape address back into ESI, adjust EDI
;--------------------------------------------------------------------
??out:
xchg esi,edi ; xchange ESI and EDI
ret ; return back to the real function
ENDP Left_Scale_Skip
END
;**************************** End of ds_lss.asm *****************************


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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Draw Shape Routines for library. *
;* *
;* File Name : DS_RRS.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : May 28, 1994 [BR] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Right_Reverse_Skip -- Skips bytes in a data stream *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;********************* Model & Processor Directives ************************
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;***************************************************************************
;* Right_Reverse_Skip -- Skips bytes in a data stream *
;* *
;* INPUT: *
;* ECX = number of uncompressed bytes to skip *
;* ESI = shape buffer data address *
;* *
;* OUTPUT: *
;* ESI - updated to the current location in the shape data *
;* *
;* WARNINGS: This routine may overrun the number of requested bytes *
;* if it encounters a run of 0's; however, it's assumed that *
;* the shape data will never contain a run that goes past the *
;* right-hand edge of the shape. *
;* *
;* HISTORY: *
;* 04/14/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 05/28/1994 BR : Converted to 32-bit *
;*=========================================================================*
PROC Right_Reverse_Skip NOLANGUAGE NEAR
;--------------------------------------------------------------------
; Put shape data address in EDI so we can do a scasb on it
;--------------------------------------------------------------------
xchg esi,edi ; xchange ESI and EDI
jecxz ??out ; exit if ECX is 0 (no bytes to skip)
;--------------------------------------------------------------------
; Search through the string and count down the info we have handled.
; If we find a run (0 followed by a count byte), then handle it.
;--------------------------------------------------------------------
??cliptop:
mov eax,0 ; set al to 0 (we're scanning for 0)
repne scasb ; scan through source data
jz ??on_run ; if it is a run then deal with it
jecxz ??out ; if we're done then get outta here
;--------------------------------------------------------------------
; If we have a run then get the next byte which is the length.
;--------------------------------------------------------------------
??on_run:
mov al,[BYTE PTR edi] ; get the count of zeros to run
inc edi ; advance past the count
inc ecx ; the 0 found doesn't count
sub ecx,eax ; subtract the count from remaining
jg ??cliptop ; if more bytes left, scan again
;--------------------------------------------------------------------
; Put shape address back into ESI, adjust EDI
;--------------------------------------------------------------------
??out:
xchg esi,edi ; xchange ESI and EDI
ret ; return back to the real function
ENDP Right_Reverse_Skip
END
;**************************** End of ds_rrs.asm ****************************


110
WIN32LIB/SRCDEBUG/DS_RS.ASM Normal file
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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Draw Shape Routines for library. *
;* *
;* File Name : DS_RS.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : May 28, 1994 [BR] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Right_Skip -- Skips bytes in a data stream *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;********************* Model & Processor Directives ************************
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;***************************************************************************
;* Right_Skip -- Skips bytes in a data stream *
;* *
;* INPUT: *
;* ECX = number of uncompressed bytes to skip *
;* ESI = shape buffer data address *
;* *
;* OUTPUT: *
;* ESI - updated to the current location in the shape data *
;* *
;* WARNINGS: This routine may overrun the number of requested bytes *
;* if it encounters a run of 0's; however, it's assumed that *
;* the shape data will never contain a run that goes past the *
;* right-hand edge of the shape. *
;* *
;* HISTORY: *
;* 04/14/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 05/28/1994 BR : Converted to 32-bit *
;*=========================================================================*
PROC Right_Skip NOLANGUAGE NEAR
;--------------------------------------------------------------------
; Put shape data address in EDI so we can do a scasb on it
;--------------------------------------------------------------------
xchg esi,edi ; xchange ESI and EDI
jecxz ??out ; exit if ECX is 0 (no bytes to skip)
;--------------------------------------------------------------------
; Search through the string and count down the info we have handled.
; If we find a run (0 followed by a count byte), then handle it.
;--------------------------------------------------------------------
??cliptop:
mov eax,0 ; set al to 0 (we're scanning for 0)
repne scasb ; scan through source data
jz ??on_run ; if it is a run then deal with it
jecxz ??out ; if we're done then get outta here
;--------------------------------------------------------------------
; If we have a run then get the next byte which is the length.
;--------------------------------------------------------------------
??on_run:
mov al,[BYTE PTR edi] ; get the count of zeros to run
inc edi ; advance past the count
inc ecx ; the 0 found doesn't count
sub ecx,eax ; subtract the count from remaining
jg ??cliptop ; if more bytes left, scan again
;--------------------------------------------------------------------
; Put shape address back into ESI, adjust EDI
;--------------------------------------------------------------------
??out:
xchg esi,edi ; xchange ESI and EDI
ret ; return back to the real function
ENDP Right_Skip
END
;**************************** End of ds_rs.asm ******************************


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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Draw Shape Routines for library. *
;* *
;* File Name : DS_RSRS.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : June 1, 1994 [BR] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Right_Scale_Reverse_Skip -- Skips past a scaled row of pixels *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;********************* Model & Processor Directives ************************
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;***************************************************************************
;* Right_Scale_Reverse_Skip -- Skips past a scaled row of pixels *
;* *
;* INPUT: *
;* ECX = number of uncompressed bytes to skip *
;* ESI = shape buffer data address *
;* *
;* OUTPUT: *
;* ESI - updated to the current location in the shape data *
;* *
;* WARNINGS: This routine may overrun the number of requested bytes *
;* if it encounters a run of 0's; however, it's assumed that *
;* the shape data will never contain a run that goes past the *
;* right-hand edge of the shape. *
;* *
;* HISTORY: *
;* 04/20/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 06/01/1994 BR : Converted to 32-bit *
;*=========================================================================*
PROC Right_Scale_Reverse_Skip NOLANGUAGE NEAR
;--------------------------------------------------------------------
; Put shape data address in EDI so we can do a scasb on it
;--------------------------------------------------------------------
xchg esi,edi ; xchange ESI and EDI
jecxz ??out ; exit if ECX is 0 (no bytes to skip)
;--------------------------------------------------------------------
; Search through the string and count down the info we have handled.
; If we find a run (0 followed by a count byte), then handle it.
;--------------------------------------------------------------------
??cliptop:
mov eax,0 ; set al to 0 (we're scanning for 0)
repne scasb ; scan through source data
jz ??on_run ; if it is a run then deal with it
jecxz ??out ; if we're done then get outta here
;--------------------------------------------------------------------
; If we have a run then get the next byte which is the length.
;--------------------------------------------------------------------
??on_run:
mov al,[BYTE PTR edi] ; get the count of zeros to run
inc edi ; advance past the count
inc ecx ; the 0 found doesn't count
sub ecx,eax ; subtract the count from remaining
jg ??cliptop ; if more bytes left, scan again
;--------------------------------------------------------------------
; Put shape address back into ESI, adjust EDI
;--------------------------------------------------------------------
??out:
xchg esi,edi ; xchange ESI and EDI
ret ; return back to the real function
ENDP Right_Scale_Reverse_Skip
END
;*************************** End of ds_rsrs.asm ****************************


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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Draw Shape Routines for library. *
;* *
;* File Name : DS_RSS.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 24, 1993 *
;* *
;* Last Update : June 1, 1994 [BR] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Right_Scale_Skip -- Skips past a scaled row of pixels on right side *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;********************* Model & Processor Directives ************************
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;********************************* Code ************************************
CODESEG
;***************************************************************************
;* Right_Scale_Skip -- Skips past a scaled row of pixels on the right side *
;* *
;* INPUT: *
;* ECX = number of uncompressed bytes to skip *
;* ESI = shape buffer data address *
;* *
;* OUTPUT: *
;* ESI - updated to the current location in the shape data *
;* *
;* WARNINGS: This routine may overrun the number of requested bytes *
;* if it encounters a run of 0's; however, it's assumed that *
;* the shape data will never contain a run that goes past the *
;* right-hand edge of the shape. *
;* *
;* HISTORY: *
;* 04/20/1992 PWG : Created. *
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
;* 06/01/1994 BR : Converted to 32-bit *
;*=========================================================================*
PROC Right_Scale_Skip NOLANGUAGE NEAR
;--------------------------------------------------------------------
; Put shape data address in EDI so we can do a scasb on it
;--------------------------------------------------------------------
xchg esi,edi ; xchange ESI and EDI
jecxz ??out ; exit if ECX is 0 (no bytes to skip)
;--------------------------------------------------------------------
; Search through the string and count down the info we have handled.
; If we find a run (0 followed by a count byte), then handle it.
;--------------------------------------------------------------------
??cliptop:
mov eax,0 ; set al to 0 (we're scanning for 0)
repne scasb ; scan through source data
jz ??on_run ; if it is a run then deal with it
jecxz ??out ; if we're done then get outta here
;--------------------------------------------------------------------
; If we have a run then get the next byte which is the length.
;--------------------------------------------------------------------
??on_run:
mov al,[BYTE PTR edi] ; get the count of zeros to run
inc edi ; advance past the count
inc ecx ; the 0 found doesn't count
sub ecx,eax ; subtract the count from remaining
jg ??cliptop ; if more bytes left, scan again
;--------------------------------------------------------------------
; Put shape address back into ESI, adjust EDI
;--------------------------------------------------------------------
??out:
xchg esi,edi ; xchange ESI and EDI
ret ; return back to the real function
ENDP Right_Scale_Skip
END
;*************************** End of ds_rss.asm *****************************


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 A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Draw Shape Routines for library. *
;* *
;* File Name : DS_TABLE.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : August 20, 1993 *
;* *
;* Last Update : September 6, 1994 [IML] *
;* *
;* This module sets up a table of procedure addresses for combinations of *
;* NORMAL, HORZ_REV and SCALING flags. *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;********************** Model & Processor Directives ************************
IDEAL
P386
MODEL USE32 FLAT
;******************************** Includes *********************************
INCLUDE "shape.inc"
;******************************** Equates **********************************
;*=========================================================================*/
;* The following are defines used to control what functions are linked *
;* in for Draw_Shape. *
;*=========================================================================*/
USE_NORMAL EQU TRUE
USE_HORZ_REV EQU TRUE
USE_VERT_REV EQU TRUE
USE_SCALING EQU TRUE
;---------------------------------------------------------------------------
;
; Use a macro to make code a little cleaner.
; The parameter varname is optional.
; Syntax to use macro is :
; WANT equ expression
; USE func [,varname]
; If the 'varname' is defined, a table declaration is created like:
; GLOBAL TableName:DWORD
; Then, the table entry is created:
; If WANT is true, the table entry is created for the given function:
; varname DD func
; If WANT is not TRUE, a Not_Supported entry is put in the table:
; varname DD Not_Supported
; The resulting tables look like:
;
; GLOBAL ExampTable:DWORD
; ExampTable DD routine1
; DD routine2
; DD routine3
; ...
; Thus, each table is an array of function pointers.
;
;---------------------------------------------------------------------------
MACRO USE func, varname
IFNB <varname>
GLOBAL varname:DWORD
ENDIF
IF WANT
varname DD func
ELSE
varname DD Not_Supported
ENDIF
ENDM
;---------------------------------------------------------------------------
; Data Segment Tables:
; This code uses the USE macro to set up tables of function addresses.
; The tables have the following format:
; Tables defined are:
; LSkipTable
; RSkipTable
; DrawTable
;---------------------------------------------------------------------------
DATASEG
;---------------------------------------------------------------------------
WANT equ <TRUE>
USE Left_Skip, LSkipTable
WANT equ <TRUE>
USE Left_Reverse_Skip
WANT equ <TRUE>
USE Left_Skip
WANT equ <TRUE>
USE Left_Reverse_Skip
WANT equ <USE_SCALING>
USE Left_Scale_Skip
WANT equ <USE_SCALING>
USE Left_Scale_Reverse_Skip
WANT equ <USE_SCALING>
USE Left_Scale_Skip
WANT equ <USE_SCALING>
USE Left_Scale_Reverse_Skip
;---------------------------------------------------------------------------
WANT equ <TRUE>
USE Right_Skip, RSkipTable
WANT equ <TRUE>
USE Right_Reverse_Skip
WANT equ <TRUE>
USE Right_Skip
WANT equ <TRUE>
USE Right_Reverse_Skip
WANT equ <USE_SCALING>
USE Right_Scale_Skip
WANT equ <USE_SCALING>
USE Right_Scale_Reverse_Skip
WANT equ <USE_SCALING>
USE Right_Scale_Skip
WANT equ <USE_SCALING>
USE Right_Scale_Reverse_Skip
;---------------------------------------------------------------------------
WANT equ <TRUE>
USE Draw_Normal, DrawTable
WANT equ <TRUE>
USE Draw_Reverse
WANT equ <TRUE>
USE Draw_Normal
WANT equ <TRUE>
USE Draw_Reverse
WANT equ <USE_SCALING>
USE Draw_Scale
WANT equ <USE_SCALING>
USE Draw_Scale_Reverse
WANT equ <USE_SCALING>
USE Draw_Scale
WANT equ <USE_SCALING>
USE Draw_Scale_Reverse
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
END
;************************** End of ds_table.asm ****************************

View File

@@ -0,0 +1,91 @@
/*
** 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 library source *
* *
* File Name : EXIT.CPP *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : August 3, 1994 *
* *
* Last Update : August 3, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Exit -- Exit routine with message. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "misc.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
/***************************************************************************
* EXIT -- Exit routine with message. *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/03/1994 SKB : Created. *
*=========================================================================*/
void __cdecl Exit(INT errorval, const char *message, ...)
{
va_list argptr;
char errstring[256];
Prog_End();
if (message && *message) {
va_start (argptr, message);
vsprintf ((char *)errstring, (const char *)message, argptr);
va_end (argptr);
printf(errstring);
}
::exit(errorval);
}
void randomize ( void )
{
srand ( time ( NULL ) ) ;
}
#if(0)
unsigned long random ( unsigned long mod )
{
return rand () * mod / RAND_MAX ;
}
#endif

View File

@@ -0,0 +1,148 @@
;
; 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/./facing16.asm 1.10 1994/05/20 15:32:36 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 : Support Library *
;* *
;* File Name : FACING16.ASM *
;* *
;* Programmer : Joe L. Bostic *
;* *
;* Start Date : May 8, 1991 *
;* *
;* Last Update : February 6, 1995 [BWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Desired_Facing16 -- Converts coordinates into a facing number. *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL C Desired_Facing16 :NEAR
; INCLUDE "wwlib.i"
DATASEG
; 16 direction desired facing lookup table. Build the index according
; to the following bits:
;
; bit 4 = Is y2 < y1?
; bit 3 = Is x2 < x1?
; bit 2 = Is the ABS(x2-x1) < ABS(y2-y1)?
; bit 1 = Is the lesser absolute difference very close to zero?
; bit 0 = Is the lesser absolute difference very close to the greater dist?
NewFacing16 DB 3, 2, 4,-1, 1, 2,0,-1
DB 13,14,12,-1,15,14,0,-1
DB 5, 6, 4,-1, 7, 6,8,-1
DB 11,10,12,-1, 9,10,8,-1
CODESEG
;***************************************************************************
;* DESIRED_FACING16 -- Converts coordinates into a facing number. *
;* *
;* This converts coordinates into a desired facing number that ranges *
;* from 0 to 15 (0 equals North and going clockwise). *
;* *
;* INPUT: x1,y1 -- Position of origin point. *
;* *
;* x2,y2 -- Position of target. *
;* *
;* OUTPUT: Returns desired facing as a number from 0 to 255 but *
;* accurate to 22.5 degree increments. *
;* *
;* WARNINGS: If the two coordinates are the same, then -1 will be *
;* returned. It is up to you to handle this case. *
;* *
;* HISTORY: *
;* 08/14/1991 JLB : Created. *
;*=========================================================================*
; long Desired_Facing16(long x1, long y1, long x2, long y2);
PROC Desired_Facing16 C near
USES ebx, ecx, edx
ARG x1:DWORD
ARG y1:DWORD
ARG x2:DWORD
ARG y2:DWORD
xor ebx,ebx ; Index byte (built).
; Determine Y axis difference.
mov edx,[y1]
mov ecx,[y2]
sub edx,ecx ; DX = Y axis (signed).
jns short ??absy
inc ebx ; Set the signed bit.
neg edx ; ABS(y)
??absy:
; Determine X axis difference.
shl ebx,1
mov eax,[x1]
mov ecx,[x2]
sub ecx,eax ; CX = X axis (signed).
jns short ??absx
inc ebx ; Set the signed bit.
neg ecx ; ABS(x)
??absx:
; Determine the greater axis.
cmp ecx,edx
jb short ??dxisbig
xchg ecx,edx
??dxisbig:
rcl ebx,1 ; Y > X flag bit.
; Determine the closeness or farness of lesser axis.
mov eax,edx
inc eax ; Round up.
shr eax,1
inc eax ; Round up.
shr eax,1 ; 1/4 of greater axis.
cmp ecx,eax
rcl ebx,1 ; Very close to major axis bit.
sub edx,eax
cmp edx,ecx
rcl ebx,1 ; Very far from major axis bit.
xor eax,eax
mov al,[NewFacing16+ebx]
; Normalize to 0..FF range.
shl eax,4
ret
ENDP Desired_Facing16
END


View File

@@ -0,0 +1,140 @@
;
; 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 : Support Library *
;* *
;* File Name : FACING8.ASM *
;* *
;* Programmer : Joe L. Bostic *
;* *
;* Start Date : May 8, 1991 *
;* *
;* Last Update : February 6, 1995 [BWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Desired_Facing8 -- Determines facing to reach a position. *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL C Desired_Facing8 :NEAR
; INCLUDE "wwlib.i"
DATASEG
; 8 direction desired facing lookup table. Build the index according
; to the following bits:
;
; bit 3 = Is y2 < y1?
; bit 2 = Is x2 < x1?
; bit 1 = Is the ABS(x2-x1) < ABS(y2-y1)?
; bit 0 = Is the facing closer to a major axis?
NewFacing8 DB 1,2,1,0,7,6,7,0,3,2,3,4,5,6,5,4
CODESEG
;***************************************************************************
;* DESIRED_FACING8 -- Determines facing to reach a position. *
;* *
;* This routine will return with the most desirable facing to reach *
;* one position from another. It is accurate to a resolution of 0 to *
;* 7. *
;* *
;* INPUT: x1,y1 -- Position of origin point. *
;* *
;* x2,y2 -- Position of target. *
;* *
;* OUTPUT: Returns desired facing as a number from 0..255 with an *
;* accuracy of 32 degree increments. *
;* *
;* WARNINGS: If the two coordinates are the same, then -1 will be *
;* returned. It is up to you to handle this case. *
;* *
;* HISTORY: *
;* 07/15/1991 JLB : Documented. *
;* 08/08/1991 JLB : Same position check. *
;* 08/14/1991 JLB : New algorithm *
;* 02/06/1995 BWG : Convert to 32-bit *
;*=========================================================================*
; long Desired_Facing8(long x1, long y1, long x2, long y2);
PROC Desired_Facing8 C near
USES ebx, ecx, edx
ARG x1:DWORD
ARG y1:DWORD
ARG x2:DWORD
ARG y2:DWORD
xor ebx,ebx ; Index byte (built).
; Determine Y axis difference.
mov edx,[y1]
mov ecx,[y2]
sub edx,ecx ; DX = Y axis (signed).
jns short ??absy
inc ebx ; Set the signed bit.
neg edx ; ABS(y)
??absy:
; Determine X axis difference.
shl ebx,1
mov eax,[x1]
mov ecx,[x2]
sub ecx,eax ; CX = X axis (signed).
jns short ??absx
inc ebx ; Set the signed bit.
neg ecx ; ABS(x)
??absx:
; Determine the greater axis.
cmp ecx,edx
jb short ??dxisbig
xchg ecx,edx
??dxisbig:
rcl ebx,1 ; Y > X flag bit.
; Determine the closeness or farness of lesser axis.
mov eax,edx
inc eax ; Round up.
shr eax,1
cmp ecx,eax
rcl ebx,1 ; Close to major axis bit.
xor eax,eax
mov al,[NewFacing8+ebx]
; Normalize to 0..FF range.
shl eax,5
ret
ENDP Desired_Facing8
END

View File

@@ -0,0 +1,165 @@
;
; 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 : Support Library *
;* *
;* File Name : FACINGFF.ASM *
;* *
;* Programmer : Joe L. Bostic *
;* *
;* Start Date : May 8, 1991 *
;* *
;* Last Update : February 6, 1995 [BWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Desired_Facing256 -- Determines facing to reach a position. *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL C Desired_Facing256 :NEAR
; INCLUDE "wwlib.i"
INCLUDE "..\include\gbuffer.inc"
CODESEG
;***************************************************************************
;* Desired_Facing256 -- Desired facing algorithm 0..255 resolution. *
;* *
;* This is a desired facing algorithm that has a resolution of 0 *
;* through 255. *
;* *
;* INPUT: srcx,srcy -- Source coordinate. *
;* *
;* dstx,dsty -- Destination coordinate. *
;* *
;* OUTPUT: Returns with the desired facing to face the destination *
;* coordinate from the position of the source coordinate. North *
;* is 0, East is 64, etc. *
;* *
;* WARNINGS: This routine is slower than the other forms of desired *
;* facing calculation. Use this routine when accuracy is *
;* required. *
;* *
;* HISTORY: *
;* 12/24/1991 JLB : Adapted. *
;*=========================================================================*/
; LONG cdecl Desired_Facing256(LONG srcx, LONG srcy, LONG dstx, LONG dsty)
PROC Desired_Facing256 C near
USES ebx, ecx, edx
ARG srcx:DWORD
ARG srcy:DWORD
ARG dstx:DWORD
ARG dsty:DWORD
xor ebx,ebx ; Facing number.
; Determine absolute X delta and left/right direction.
mov ecx,[dstx]
sub ecx,[srcx]
jge short ??xnotneg
neg ecx
mov ebx,11000000b ; Set bit 7 and 6 for leftward.
??xnotneg:
; Determine absolute Y delta and top/bottom direction.
mov eax,[srcy]
sub eax,[dsty]
jge short ??ynotneg
xor ebx,01000000b ; Complement bit 6 for downward.
neg eax
??ynotneg:
; Set DX=64 for quadrants 0 and 2.
mov edx,ebx
and edx,01000000b
xor edx,01000000b
; Determine if the direction is closer to the Y axis and make sure that
; CX holds the larger of the two deltas. This is in preparation for the
; divide.
cmp eax,ecx
jb short ??gotaxis
xchg eax,ecx
xor edx,01000000b ; Closer to Y axis so make DX=64 for quad 0 and 2.
??gotaxis:
; If closer to the X axis then add 64 for quadrants 0 and 2. If
; closer to the Y axis then add 64 for quadrants 1 and 3. Determined
; add value is in DX and save on stack.
push edx
; Make sure that the division won't overflow. Reduce precision until
; the larger number is less than 256 if it appears that an overflow
; will occur. If the high byte of the divisor is not zero, then this
; guarantees no overflow, so just abort shift operation.
test eax,0FFFFFF00h
jnz short ??nooverflow
??again:
test ecx,0FFFFFF00h
jz short ??nooverflow
shr ecx,1
shr eax,1
jmp short ??again
??nooverflow:
; Make sure that the division won't underflow (divide by zero). If
; this would occur, then set the quotient to $FF and skip divide.
or ecx,ecx
jnz short ??nounderflow
mov eax,0FFFFFFFFh
jmp short ??divcomplete
; Derive a pseudo angle number for the octant. The angle is based
; on $00 = angle matches long axis, $00 = angle matches $FF degrees.
??nounderflow:
xor edx,edx
shld edx,eax,8 ; shift high byte of eax into dl
shl eax,8
div ecx
??divcomplete:
; Integrate the 5 most significant bits into the angle index. If DX
; is not zero, then it is 64. This means that the dividend must be negated
; before it is added into the final angle value.
shr eax,3
pop edx
or edx,edx
je short ??noneg
dec edx
neg eax
??noneg:
add eax,edx
add eax,ebx
and eax,0FFH
ret
ENDP Desired_Facing256
END

View File

@@ -0,0 +1,215 @@
;
; 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 : FADING.ASM *
;* *
;* Programmer : Joe L. Bostic *
;* *
;* Start Date : August 20, 1993 *
;* *
;* Last Update : August 20, 1993 [JLB] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL C Build_Fading_Table :NEAR
CODESEG
;***********************************************************
; BUILD_FADING_TABLE
;
; void *Build_Fading_Table(void *palette, void *dest, long int color, long int frac);
;
; This routine will create the fading effect table used to coerce colors
; from toward a common value. This table is used when Fading_Effect is
; active.
;
; Bounds Checking: None
;*
PROC Build_Fading_Table C near
USES ebx, ecx, edi, esi
ARG palette:DWORD
ARG dest:DWORD
ARG color:DWORD
ARG frac:DWORD
LOCAL matchvalue:DWORD ; Last recorded match value.
LOCAL targetred:BYTE ; Target gun red.
LOCAL targetgreen:BYTE ; Target gun green.
LOCAL targetblue:BYTE ; Target gun blue.
LOCAL idealred:BYTE
LOCAL idealgreen:BYTE
LOCAL idealblue:BYTE
LOCAL matchcolor:BYTE ; Tentative match color.
cld
; If the source palette is NULL, then just return with current fading table pointer.
cmp [palette],0
je ??fini
cmp [dest],0
je ??fini
; Fractions above 255 become 255.
mov eax,[frac]
cmp eax,0100h
jb short ??ok
mov [frac],0FFh
??ok:
; Record the target gun values.
mov esi,[palette]
mov ebx,[color]
add esi,ebx
add esi,ebx
add esi,ebx
lodsb
mov [targetred],al
lodsb
mov [targetgreen],al
lodsb
mov [targetblue],al
; Main loop.
xor ebx,ebx ; Remap table index.
; Transparent black never gets remapped.
mov edi,[dest]
mov [edi],bl
inc edi
; EBX = source palette logical number (1..255).
; EDI = running pointer into dest remap table.
??mainloop:
inc ebx
mov esi,[palette]
add esi,ebx
add esi,ebx
add esi,ebx
mov edx,[frac]
shr edx,1
; new = orig - ((orig-target) * fraction);
lodsb ; orig
mov dh,al ; preserve it for later.
sub al,[targetred] ; al = (orig-target)
imul dl ; ax = (orig-target)*fraction
shl ax,1
sub dh,ah ; dh = orig - ((orig-target) * fraction)
mov [idealred],dh ; preserve ideal color gun value.
lodsb ; orig
mov dh,al ; preserve it for later.
sub al,[targetgreen] ; al = (orig-target)
imul dl ; ax = (orig-target)*fraction
shl ax,1
sub dh,ah ; dh = orig - ((orig-target) * fraction)
mov [idealgreen],dh ; preserve ideal color gun value.
lodsb ; orig
mov dh,al ; preserve it for later.
sub al,[targetblue] ; al = (orig-target)
imul dl ; ax = (orig-target)*fraction
shl ax,1
sub dh,ah ; dh = orig - ((orig-target) * fraction)
mov [idealblue],dh ; preserve ideal color gun value.
; Sweep through the entire existing palette to find the closest
; matching color. Never matches with color 0.
mov eax,[color]
mov [matchcolor],al ; Default color (self).
mov [matchvalue],-1 ; Ridiculous match value init.
mov ecx,255
mov esi,[palette] ; Pointer to original palette.
add esi,3
; BH = color index.
mov bh,1
??innerloop:
; Recursion through the fading table won't work if a color is allowed
; to remap to itself. Prevent this from occuring.
add esi,3
cmp bh,bl
je short ??notclose
sub esi,3
xor edx,edx ; Comparison value starts null.
mov eax,edx
; Build the comparison value based on the sum of the differences of the color
; guns squared.
lodsb
sub al,[idealred]
mov ah,al
imul ah
add edx,eax
lodsb
sub al,[idealgreen]
mov ah,al
imul ah
add edx,eax
lodsb
sub al,[idealblue]
mov ah,al
imul ah
add edx,eax
jz short ??perfect ; If perfect match found then quit early.
cmp edx,[matchvalue]
ja short ??notclose
mov [matchvalue],edx ; Record new possible color.
mov [matchcolor],bh
??notclose:
inc bh ; Checking color index.
loop ??innerloop
mov bh,[matchcolor]
??perfect:
mov [matchcolor],bh
xor bh,bh ; Make BX valid main index again.
; When the loop exits, we have found the closest match.
mov al,[matchcolor]
stosb
cmp ebx,255
jne ??mainloop
??fini:
mov eax,[dest]
ret
ENDP Build_Fading_Table
END

View File

@@ -0,0 +1,238 @@
;
; 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 : First First *
;* *
;* File Name : FFIRST.ASM *
;* *
;* Programmer : Jeff Wilson *
;* *
;* Start Date : March 28, 1994 *
;* *
;* Last Update : April 15, 1994 [] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Find_First -- Find a file spec *
;* Find_Next -- Find next file in sreach params *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
GLOBAL Find_First :NEAR
GLOBAL Find_Next :NEAR
;============================================================================
CODESEG
;***************************************************************************
;* FIND_FIRST -- Find a file spec *
;* *
;* *
;* *
;* INPUT: *
;* file_name File spec to find. Maybe a wildcard name *
;* mode File type *
;* ffblk file data block ptr to write info into *
;* *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 04/15/1994 jaw: Created. *
;*=========================================================================*
PROC Find_First C near
USES ebx,ecx,edx,esi,edi,es,ds
ARG file_name:DWORD,mode:WORD,ffblk:DWORD
mov edx,[file_name]
mov cx,[mode]
mov eax,4e00h ;first firstg function
int 21h
;Find it?
jnc ??found_it ;=>yes
; ax holds the error code
;insure high word of eax is clear
or eax,0ffffffffh
jmp ??exit
??found_it:
; found something
;copy the DTA into the user block
mov eax,2f00h ;get DTA address
int 21h
mov ax,es ;switch selectors
mov dx,ds
mov ds,ax
mov es,dx
mov esi,ebx
mov edi,[ffblk]
add esi,21 ;SKIP RESERVED
add edi,4 ;SKIP RESERVED
sub eax,eax
mov al,[esi] ;get attrib byte
mov [es:edi+4],eax
inc esi
;get time
mov ax,[esi]
add esi,2
mov [es:edi+8],ax
;get date
mov ax,[esi]
add esi,2
mov [es:edi+10],ax
;get file size
mov eax,[esi]
add esi,4
mov [es:edi],eax
add edi,12
mov ecx,13
rep movsb ;copy the DTA name
mov ax,es
mov ds,ax
xor eax,eax
??exit:
ret
;====================
ENDP Find_First
;***************************************************************************
;* FIND_NEXT -- Find next file in sreach params *
;* *
;* *
;* *
;* INPUT: *
;* NONE *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 04/15/1994 jaw: Created. *
;*=========================================================================*
PROC Find_Next C near
USES ebx,ecx,edx,esi,edi,ds,es
ARG ffblk:DWORD
mov eax,04f00h ;Find Next function
int 21h
;Find anything?
jnc ??found_it ;=>no
; ax holds the error code
;insure high word of eax is clear
or eax,0ffffffffh
jmp ??exit
??found_it:
; found something
;copy the DTA into the user block
mov eax,2f00h ;get DTA address
int 21h
mov ax,es ;switch selectors
mov dx,ds
mov ds,ax
mov es,dx
mov esi,ebx
mov edi,[ffblk]
add esi,21 ;SKIP RESERVED
add edi,4 ;SKIP RESERVED
sub eax,eax
mov al,[esi] ;get attrib byte
mov [es:edi+4],eax
inc esi
;get time
mov ax,[esi]
add esi,2
mov [es:edi+8],ax
;get date
mov ax,[esi]
add esi,2
mov [es:edi+10],ax
;get file size
mov eax,[esi]
add esi,4
mov [es:edi],eax
add edi,12
mov ecx,13
rep movsb ;copy the DTA name
mov ax,es
mov ds,ax
xor eax,eax
??exit:
ret
ENDP Find_Next
END





View File

@@ -0,0 +1,94 @@
;
; 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 : Fix a selector *
;* *
;* File Name : FFIXSEL.ASM *
;* *
;* Programmer : Jeff Wilson *
;* *
;* Start Date : March 28, 1994 *
;* *
;* Last Update : March 28, 1994 [] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* FixSelector -- Fix the Priviledge level of a selector *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
EXTRN exit : near
GLOBAL FixSelector :NEAR
;============================================================================
CODESEG
;***************************************************************************
;* FIXSELECTOR -- Fix the Priviledge level of a selector *
;* *
;* *
;* *
;* INPUT: sel the selector to fix-up *
;* *
;* OUTPUT: UWORD The fixed up selector *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 03/28/1994 jaw Created. *
;*=========================================================================*
PROC FixSelector C near
USES ecx,edx
ARG sel:WORD
; Copy the Table Bit and IOPL from the Current CS
; Something is wrong the program should not be here unthe any circunstance
; movzx ecx,[sel]
; xor eax,eax
; mov ax,cs
; and ax,7
; or ax,cx
push 0
call exit
ret
;====================
ENDP FixSelector
END


View File

@@ -0,0 +1,78 @@
;
; 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 : Get the code selector *
;* *
;* File Name : FGETCS.ASM *
;* *
;* Programmer : Jeff Wilson *
;* *
;* Start Date : March 28, 1994 *
;* *
;* Last Update : March 28, 1994 [] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* GetCs -- Return the current Data selector. *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL GetCs :NEAR
;============================================================================
CODESEG
;***************************************************************************
;* GETCS -- Return the current Data selector. *
;* *
;* *
;* *
;* INPUT: NONE *
;* *
;* OUTPUT: UWORD selector of the default code segment *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 03/28/1994 jaw: Created. *
;*=========================================================================*
PROC GetCs C near
xor eax,eax
mov ax,cs
ret
;====================
ENDP GetCs
END


View File

@@ -0,0 +1,77 @@
;
; 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 : Get the data selector *
;* *
;* File Name : FGETDS.ASM *
;* *
;* Programmer : Jeff Wilson *
;* *
;* Start Date : March 28, 1994 *
;* *
;* Last Update : March 28, 1994 [] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* GetDs -- Return the current Data selector. *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL GetDs :NEAR
;============================================================================
CODESEG
;***************************************************************************
;* GETDS -- Return the current Data selector. *
;* *
;* *
;* *
;* INPUT: NONE *
;* *
;* OUTPUT: UWORD selector of the default data segment *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 03/28/1994 jaw: Created. *
;*=========================================================================*
PROC GetDs C near
xor eax,eax
mov ax,ds
ret
;====================
ENDP GetDs
END


View File

@@ -0,0 +1,118 @@
;
; 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 : Get the Defines selectors *
;* *
;* File Name : FGETSEL.ASM *
;* *
;* Programmer : Jeff Wilson *
;* *
;* Start Date : March 28, 1994 *
;* *
;* Last Update : March 28, 1994 [] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* GetDefaultSelectors -- Return the current default selectors. *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL GetDefaultSelectors :NEAR
GLOBAL DataSelector :WORD
GLOBAL ScreenSelector :WORD
GLOBAL GraphicsSelector :WORD
GLOBAL PspSelector :WORD
GLOBAL EnvSelector :WORD
GLOBAL DosMemSelector :WORD
GLOBAL Fp1167Selector :WORD
GLOBAL FpWeitekSelector :WORD
GLOBAL FpCyrixSelector :WORD
GLOBAL CodeSelector :WORD
DATASEG
; It is very important that this section remain untouch
; is not really needed by Rational System but is here to
; keep compatibility with the TNT dos extender.
DataSelector dw 0
ScreenSelector dw 0
GraphicsSelector dw 0
PspSelector dw 0
EnvSelector dw 0
DosMemSelector dw 0
Fp1167Selector dw 0
FpWeitekSelector dw 0
FpCyrixSelector dw 0
CodeSelector dw 0
;============================================================================
CODESEG
;***************************************************************************
;* GetDefaultSelectors -- Setup the defaults selector values to have the *
;* Correct Descriptor table and IOPL. *
;* *
;* *
;* *
;* INPUT: NONE *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 03/28/1994 jaw: Created. *
;*=========================================================================*
PROC GetDefaultSelectors C near
USES eax,esi,ecx
lea edi,[DataSelector]
lea ecx,[CodeSelector]
sub ecx,edi
shr ecx,1
mov ax,ds
rep stosw
mov ax,cs
mov [word ptr CodeSelector] , ax
ret
;====================
ENDP GetDefaultSelectors
END


View File

@@ -0,0 +1,41 @@
/*
** 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 : FILEIO Library *
* *
* File Name : FILEGLOB.C *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : April 11, 1994 *
* *
* Last Update : April 11, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <wwstd.h>
#include "_file.h"
/* Global varaiables */
WORD Hard_Error_Occured=0;

1070
WIN32LIB/SRCDEBUG/FILE.CPP Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,250 @@
/*
** 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 : Library - File Caching routines *
* *
* File Name : FILECACH.CPP *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : September 13, 1993 *
* *
* Last Update : April 18, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Make_File_Resident -- Makes a file resident even if not flaged so. *
* Flush_Unused_File_Cache -- Flushes the file cache of any non opened fi*
* Free_Resident_File -- Free the given file if it is resident. *
* Unfragment_File_Cache -- Does a garbage collection on the file heap. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WWSTD_H
#include <wwstd.h>
#endif
#ifndef _FILE_H
#include "_file.h"
#endif
#ifndef WWMEM_H
#include <wwmem.h>
#endif
#include <string.h>
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* UNFRAGMENT_FILE_CACHE -- Does a garbage collection on the file heap. *
* *
* INPUT: NONE. *
* *
* OUTPUT: NONE. *
* *
* WARNINGS: Can be a lengthy process. *
* *
* HISTORY: *
* 04/18/1994 SKB : Created. *
*=========================================================================*/
VOID Unfragment_File_Cache(VOID)
{
FileDataType *filedata;
FileDataType *parent;
UWORD idx;
// Let the memory system clean up the file heap.
Mem_Cleanup(FileCacheHeap);
// Now get our pointers back.
// Start after the parent PAK files since we will need to check our pointers
// with them.
filedata = &FileDataPtr[NumPAKFiles];
for (idx = NumPAKFiles; idx < NumPAKFiles; idx++, filedata++) {
while (filedata->Name) {
// Only process files that are in the file cache.
if (filedata->Ptr) {
// Is a inner PAK file?
if (filedata->Flag & FILEF_PACKED) {
parent = &FileDataPtr[filedata->Disk];
// Is it just a copied pointer of the parent?
if (parent->Ptr == filedata->Ptr) {
filedata->Ptr = Mem_Find(FileCacheHeap, filedata->Disk);
}
else
filedata->Ptr = Mem_Find(FileCacheHeap, idx);
}
}
else {
filedata->Ptr = Mem_Find(FileCacheHeap, idx);
}
}
}
// Now that the children have been taken care of, let us do the parents.
for (filedata = FileDataPtr, idx = 0; idx < NumPAKFiles; idx++, filedata++) {
// Only process files that are in the file cache.
if (filedata->Ptr) {
filedata->Ptr = Mem_Find(FileCacheHeap, idx);
}
}
}
/***************************************************************************
* MAKE_FILE_RESIDENT -- Makes a file resident even if not flaged so. *
* *
* INPUT: BYTE *filename - name of file to be made resident. *
* *
* OUTPUT: BOOL if successful. could fail in not enouph RAM or not found. *
* *
* WARNINGS: File must be in FileData table. *
* *
* HISTORY: *
* 09/13/1993 SKB : Created. *
*=========================================================================*/
BOOL Make_File_Resident(BYTE const *filename)
{
FileDataType *filedata; // Pointer to the current FileData.
FileDataType hold; // Hold buffer for record (DO NOT ACCESS DIRECTLY)
WORD fileindex;
WORD oldflag;
WORD handle;
fileindex = Find_File_Index(filename);
// if the file is not in the table, we can't make it resident
if (fileindex == ERROR) return(FALSE);
// Get a pointer for quicker pointer action.
filedata = &FileDataPtr[fileindex];
// Change the flags for a moment.
oldflag = filedata->Flag;
filedata->Flag |= FILEF_RESIDENT;
filedata->Flag &= ~FILEF_FLUSH;
// Make the file resident.
handle = Open_File(filename, READ);
Close_File(handle);
// Set flags back to normal.
filedata->Flag = oldflag;
return(TRUE);
}
/***************************************************************************
* Flush_Unused_File_Cache -- Flushes the file cache of any non opened files. *
* *
* INPUT: WORD flush_keep - TRUE to flush even files marked FILEF_KEEP.*
* *
* OUTPUT: WORD Number of file flushed. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/23/1993 SB : Created. *
*=========================================================================*/
WORD Flush_Unused_File_Cache(WORD flush_keeps)
{
WORD index;
WORD freed = 0;
FileDataType *filedata = NULL;
FileDataType hold; // Hold buffer for record (DO NOT ACCESS DIRECTLY)
// Loop throuph the file table looking for files that could be freed.
index = 0;
filedata = &FileDataPtr[index];;
while (filedata->Name && strlen(filedata->Name)) {
if (filedata->Ptr && !filedata->OpenCount &&
(flush_keeps || !(filedata->Flag & FILEF_KEEP)) ) {
Mem_Free(FileCacheHeap, filedata->Ptr);
filedata->Ptr = NULL;
freed++;
}
index++;
filedata = &FileDataPtr[index];;
}
return (freed);
}
/***************************************************************************
* FREE_RESIDENT_FILE -- Free the given file if it is resident. *
* *
* INPUT: BYTE *file to free *
* *
* OUTPUT: TRUE if file was free'd, FALSE otherwise *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/22/1992 CY : Created. *
*=========================================================================*/
BOOL cdecl Free_Resident_File(BYTE const *file)
{
WORD fileindex;
BOOL oldflag; // Previous file flag.
FileDataType *filedata; // Pointer to the current FileData.
FileDataType hold; // Hold buffer for record (DO NOT ACCESS DIRECTLY)
// if the file is not in the table, we can't free it
if ((fileindex = Find_File_Index(file)) == ERROR) {
return(FALSE);
}
// get a pointer for quicker calculations.
filedata = &FileDataPtr[fileindex];
// If it isn't resident, don't try to Free it
if (filedata->Ptr == NULL) {
return(TRUE);
}
// Change the flags for a moment.
oldflag = filedata->Flag;
filedata->Flag &= ~(FILEF_RESIDENT|FILEF_KEEP);
filedata->Flag |= FILEF_FLUSH;
// Get the file out of Memory if it was there.
Close_File(Open_File(file, READ));
// Set flags back to original.
filedata->Flag = oldflag;
return(TRUE);
}

View File

@@ -0,0 +1,154 @@
/*
** 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 : Library - File functions. *
* *
* File Name : FILECHNG.CPP *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : September 13, 1993 *
* *
* Last Update : September 13, 1993 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Delete_File -- Deletes the file from the disk. *
* Create_File -- Creates an empty file on disk. *
* Change_File_Size -- Change the size of a writting file. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WWSTD_H
#include "wwstd.h"
#endif
#ifndef _FILE_H
#include "_file.h"
#endif
#ifndef WWMEM_H
#include <wwmem.h>
#endif
#include <io.h>
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* CREATE_FILE -- Creates an empty file on disk. *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/24/1992 JLB : Created. *
*=========================================================================*/
WORD cdecl Create_File(BYTE const *file_name)
{
WORD fd;
if (!file_name) return(FALSE);
fd = Open_File(file_name, WRITE);
if (fd != ERROR) {
Close_File(fd);
return(TRUE);
}
return(FALSE);
}
/***************************************************************************
* DELETE_FILE -- Deletes the file from the disk. *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/24/1992 JLB : Created. *
*=========================================================================*/
WORD cdecl Delete_File(BYTE const *file_name)
{
WORD index;
FileDataType *filedata; // Pointer to the current FileData.
FileDataType hold; // Hold buffer for record (DO NOT ACCESS DIRECTLY)
if (!file_name) return(FALSE);
CallingDOSInt++;
ibm_setdisk(*StartPath - 'A');
index = Find_File_Index(file_name);
filedata = &FileDataPtr[index];
if (index != ERROR && filedata->Ptr) {
Mem_Free(FileCacheHeap, filedata->Ptr);
filedata->Ptr = NULL;
}
index = !FILEDELETE(file_name);
CallingDOSInt--;
return(index);
}
/***************************************************************************
* CHANGE_FILE_SIZE -- Change the size of a writting file. *
* *
* INPUT: WORD handle - handle of file. *
* ULONG new_size - size of new handle. *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 09/13/1993 SKB : Created. *
*=========================================================================*/
BOOL cdecl Change_File_Size(WORD handle, ULONG new_size)
{
WORD entry;
if (Is_Handle_Valid(handle, WRITING_NON_HANDLE, NULL)) {
entry = Get_DOS_Handle(handle);
if (entry != ERROR) {
return(chsize(entry, new_size) != ERROR);
}
}
return(FALSE);
}

View File

@@ -0,0 +1,72 @@
/*
** 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 : File IO System LIbrary *
* *
* File Name : FILEDATA.CPP *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : April 11, 1994 *
* *
* Last Update : April 11, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WWSTD_H
#include "wwstd.h"
#endif
#ifndef _FILE_H
#include "_file.h"
#endif
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/*
structure for FileDataType is:
BYTE *filename: initialize to actual file name on disk.
LONG size: initialize to actual file size on disk.
BYTE *ptr: initialize to a 0L below.
WORD disk: which floppy disk number (1+) file resides on.
LONG pos: initialize to a 0L below.
UBYTE priority: file priorities can be from 0 to 127. (127 = highest)
if you want the file to be attempted to be made
resident at runtime, add 128 to the file priority
to set the high bit. even though the files
priority will appear to be 128 to 255, it will
still remain 0 to 127.
*/
FileDataType FileData[] = {
{ "", 0L, 0L, 0, 0L, 0 }
/* Must have an empty entry!!! */
};

View File

@@ -0,0 +1,74 @@
/*
** 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 : FILEIO Library *
* *
* File Name : FILEGLOB.C *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : April 11, 1994 *
* *
* Last Update : April 11, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WWSTD_H
#include <wwstd.h>
#endif
#ifndef FILE_H
#include "_file.h"
#endif
#include <process.h>
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/* Global varaiables */
BYTE ExecPath[XMAXPATH + 1];
BYTE DataPath[XMAXPATH + 1];
BYTE StartPath[XMAXPATH + 1];
BOOL UseCD;
/* File System only Global varaiables */
BYTE CallingDOSInt; // Indicate we are performing a DOS function
BYTE MaxDevice,DefaultDrive;
BYTE MultiDriveSearch = TRUE; // Multiple drive search flag
FileDataType *FileDataPtr = NULL;
FileHandleType FileHandleTable[TABLE_MAX];
UWORD NumFiles; // Number of files, except PAK, in file table.
UWORD NumPAKFiles; // Number of PAK files in filetable.
VOID *FileCacheHeap = NULL; // Pointer to the cache in memory.
WORD DiskNumber; // Where file was found (-1 == current directory).
WORD MaxDirNum = 0;
WORD (*Open_Error)(FileErrorType, BYTE const *) = NULL;

View File

@@ -0,0 +1,276 @@
/*
** 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 : Library - Fileio information functions. *
* *
* File Name : FILE.CPP *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : September 13, 1993 *
* *
* Last Update : April 19, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Get_DOS_Handle -- Fetches system specific DOS file handle. *
* Find_Disk_Number -- Determine disk a file resides upon. *
* Set_File_Flags -- Sets flags for file if FileData table. *
* Get_File_Flags -- Gets the flags on a file in the FileData table. *
* Free_Handles -- Returns number of free file handles in WW system. *
* Multi_Drive_Search -- Turns Multi search drive on and off. *
* Clear_File_Flags -- Clears flags specified for file. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WWSTD_H
#include "wwstd.h"
#endif
#ifndef _FILE_H
#include "_file.h"
#endif
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* GET_DOS_HANDLE -- Fetches system specific DOS file handle. *
* *
* This routine will return with the system specific DOS file handle. *
* On the IBM, this is a WORD, on the Amiga, it is a LONG (BPTR). Use *
* this routine with caution, because the value returned is NOT *
* portable. *
* *
* INPUT: fh -- Westwood file system handle. *
* *
* OUTPUT: Returns with the system DOS file handle (WORD or LONG). *
* *
* WARNINGS: If you pass in an invalid file handle, or a file handle *
* that references a resident file, then the ERROR code is *
* returned. Be SURE to check for this. *
* *
* HISTORY: *
* 08/21/1991 JLB : Created. *
* 11/09/1991 JLB : Checks for illegal file handle passed in. *
*=========================================================================*/
WORD cdecl Get_DOS_Handle(WORD fh)
{
/*
** If an illegal file handle is passed in then always abort.
*/
if (fh >= 0 && fh < TABLE_MAX) {
if (!FileHandleTable[fh].Empty || FileHandleTable[fh].Handle) {
return(FileHandleTable[fh].Handle);
}
/*
** If it falls through here, then the file must be resident. It is
** illegal to get a DOS handle to a resident file.
*/
}
return(FILEOPENERROR);
}
/***************************************************************************
* FREE_HANDLES -- Returns number of free file handles in WW system. *
* *
* INPUT: NONE. *
* *
* OUTPUT: NONE. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 09/13/1993 SKB : Created. *
*=========================================================================*/
WORD cdecl Free_Handles(VOID)
{
WORD count; // Count of the number of free file handles.
WORD index; // Working file handle index var.
count = 0;
for (index = 0; index < TABLE_MAX; index++) {
if (FileHandleTable[index].Empty) count++;
}
return(count);
}
/***************************************************************************
* FIND_DISK_NUMBER -- Determine disk a file resides upon. *
* *
* This routine will determine the disk number that the specified *
* file resides upon. It determines this by scanning through the *
* FileData table. If the specified file is a packed file, then it *
* will reference the parent packed file to determine the disk number. *
* *
* INPUT: file_name -- Pointer to the file name to check. *
* *
* OUTPUT: Returns with the disk number that the file resides upon. If *
* ERROR is returned, then the file does not exist in the *
* FileTable. The number returned is 0=A, 1=B, etc. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/22/1991 JLB : Created. *
*=========================================================================*/
WORD cdecl Find_Disk_Number(BYTE const *file_name)
{
FileDataType *filedata; // Pointer to the current FileData.
WORD index; // FileTable index.
index = Find_File_Index(file_name);
if (index != ERROR) {
filedata = &FileDataPtr[index];
if (filedata->Flag & FILEF_PACKED) {
return (Find_Disk_Number(FileDataPtr[filedata->Disk].Name));
}
return(filedata->Disk);
}
return (index);
}
/***************************************************************************
* SET_FILE_FLAGS -- Sets flags for file if FileData table. *
* *
* INPUT: BYTE *filename - file to modify. *
* WORD flags - flags to set in file. *
* *
* OUTPUT: WORD - if file found in FileData table. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/04/1993 SKB : Created. *
*=========================================================================*/
WORD cdecl Set_File_Flags(BYTE const *filename, WORD flags)
{
FileDataType *filedata; // Pointer to the current FileData.
WORD index; // FileTable index.
index = Find_File_Index(filename);
if (index != ERROR) {
filedata = &FileDataPtr[index];
filedata->Flag |= flags;
return (TRUE);
}
return (FALSE);
}
/***************************************************************************
* CLEAR_FILE_FLAGS -- Clears flags specified for file. *
* *
* INPUT: BYTE *filename - file to modify. *
* WORD flags - flags to set in file. *
* *
* OUTPUT: WORD - if file found in FileData table. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/19/1994 SKB : Created. *
*=========================================================================*/
WORD cdecl Clear_File_Flags(BYTE const *filename, WORD flags)
{
FileDataType *filedata; // Pointer to the current FileData.
WORD index; // FileTable index.
index = Find_File_Index(filename);
if (index != ERROR) {
filedata = &FileDataPtr[index];
filedata->Flag &= ~flags;
return (TRUE);
}
return (FALSE);
}
/***************************************************************************
* GET_FILE_FLAGS -- Gets the flags on a file in the FileData table. *
* *
* *
* INPUT: BYTE *filename - file to modify. *
* *
* OUTPUT: *
* *
* OUTPUT: WORD - if file found in FileData table. *
* *
* HISTORY: *
* 10/04/1993 SKB : Created. *
*=========================================================================*/
WORD cdecl Get_File_Flags(BYTE const *filename)
{
FileDataType *filedata; // Pointer to the current FileData.
WORD index; // FileTable index.
index = Find_File_Index(filename);
if (index != ERROR) {
filedata = &FileDataPtr[index];
return (filedata->Flag);
}
return (FALSE);
}
/***************************************************************************
* MULTI_DRIVE_SEARCH -- Turns Multi search drive on and off. *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 09/13/1993 SKB : Created. *
*=========================================================================*/
BOOL cdecl Multi_Drive_Search(BOOL on)
{
BOOL old;
Hard_Error_Occured = 0;
old = MultiDriveSearch;
MultiDriveSearch = on;
return(old);
}

View File

@@ -0,0 +1,511 @@
/*
** 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 : Library - Fileio init routines. *
* *
* File Name : FILEINIT.C *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : September 13, 1993 *
* *
* Last Update : April 19, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* WWDOS_Init -- Initialize the fileio WWS fileio system. *
* WWDOS_Shutdown -- Clean up any things that needs to be to exit game. *
* Init_FileData_Table -- Initializes or reads in FileData Table. *
* Sort_FileData_Table -- Sorts the FileData table that is in memory. *
* Preload_Files -- Loads files marked with FILEF_PRELOAD into cache. *
* Init_File_Cache -- Initializes and allocs the file cache heap. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WWSTD_H
#include "wwstd.h"
#endif
#ifndef _FILE_H
#include "_file.h"
#endif
#ifndef WWMEM_H
#include <wwmem.h>
#endif
#ifndef MISC_H
#include <misc.h>
#endif
#include <direct.h>
#include <search.h>
#include <string.h>
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
PRIVATE FileInitErrorType cdecl Init_File_Cache(ULONG cachesize);
PRIVATE FileInitErrorType cdecl Init_FileData_Table(BYTE const *filename);
PRIVATE FileInitErrorType cdecl Set_Search_Drives( BYTE *cdpath );
PRIVATE FileInitErrorType cdecl Preload_Files(VOID);
PRIVATE int QSort_Comp_Func(const void *p1, const void *p2);
PRIVATE VOID Sort_FileData_Table(VOID);
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* WWDOS_INIT -- Initialize the fileio WWS fileio system. *
* *
* *
* INPUT: ULONG cachesize - size wanted for the cache. *
* BYTE *filedat - NULL or name of filedata table file. *
* BYTE *cdpath - NULL or secondary search path on a CD. *
* *
* OUTPUT: Returns all errors encountered or'd together. *
* *
* WARNINGS: User should call the WWDOS_Init function for all file *
* initialization. *
* *
* HISTORY: *
* 04/19/1994 SKB : Created. *
*=========================================================================*/
FileInitErrorType cdecl WWDOS_Init(ULONG cachesize, BYTE *filedata, BYTE *cdpath)
{
// FileInitErrorType errors;
unsigned errors ;
// This has not been completed yet, when it is, uncomment it and add errors.
Install_Hard_Error_Handler () ;
Get_Devices();
if (cachesize) {
errors = Init_File_Cache(cachesize);
} else {
errors = FI_SUCCESS;
}
errors = errors | Init_FileData_Table(filedata);
errors = errors | Set_Search_Drives(cdpath);
errors = errors | Preload_Files();
return ( FileInitErrorType ) errors ;
}
/***************************************************************************
* WWDOS_SHUTDOWN -- Clean up any things that needs to be in file syste to *
* exit game. *
* One could shut down the file system and open it back *
* up with a different size cache or filetable. *
* *
* INPUT: NONE. *
* *
* OUTPUT: NONE. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/19/1994 SKB : Created. *
*=========================================================================*/
VOID cdecl WWDOS_Shutdown(VOID)
{
FileDataType *filedata; // Pointer to the current FileData.
WORD file_handle;
FileHandleType *filehandletable; // Pointer to the current file handle.
// Close all open files.
filehandletable = FileHandleTable;
for (file_handle = 0; file_handle < TABLE_MAX; file_handle++, filehandletable++) {
if (!filehandletable->Empty) {
Close_File(file_handle);
}
}
// Free the file cache heap.
if (FileCacheHeap) {
// Get a pointer to the current filedata.
if (FileDataPtr) {
filedata = FileDataPtr;
} else {
filedata = FileData;
}
while(filedata->Name && filedata->Name[0]) {
filedata->Ptr = NULL;
filedata++;
}
Free(FileCacheHeap);
FileCacheHeap = NULL;
}
// Free up the file data.
if (FileDataPtr != FileData) {
Free(FileDataPtr);
}
FileDataPtr = NULL;
chdir(StartPath);
ibm_setdisk(*StartPath - 'A');
// This has not been completed yet, when it is, uncomment it and add errors.
Remove_Hard_Error_Handler();
}
/***************************************************************************
* INIT_FILE_CACHE -- Initializes and allocs the file cache heap. *
* *
* INPUT: ULONG cachesize - size of heap cache.. *
* *
* OUTPUT: FileInitErrorType error code. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/19/1994 SKB : Created. *
*=========================================================================*/
PRIVATE FileInitErrorType cdecl Init_File_Cache(ULONG cachesize)
{
// Allocate and initialize the file cache heap.
if (FileCacheHeap) {
return (FI_CACHE_ALREADY_INIT);
}
if ((Ram_Free(MEM_NORMAL) >= cachesize)) {
FileCacheHeap = Alloc(cachesize, MEM_NORMAL);
Mem_Init(FileCacheHeap, cachesize);
}
if (!FileCacheHeap) {
return (FI_CACHE_TOO_BIG);
}
return (FI_SUCCESS);
}
/***************************************************************************
* INIT_FILEDATA_TABLE -- Initializes or reads in FileData Table. *
* *
* INPUT: *
* *
* OUTPUT: FileInitErrorType error code. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 09/13/1993 SKB : Created. *
*=========================================================================*/
PRIVATE FileInitErrorType cdecl Init_FileData_Table(BYTE const *filename)
{
WORD fd;
ULONG fsize;
FileDataType *ptr;
WORD index;
BYTE fname[13];
/*
** Inialize the file handle table to reflect no files open.
*/
for (index = 0; index < TABLE_MAX; index++) {
FileHandleTable[index].Empty = TRUE;
}
// Set up our FileData ptr to be the initial FileData table.
FileDataPtr = FileData;
// Sort the filedata table.
// This needs to be done even if we load it off disk since the initial file data
// table might contain a filename.
Sort_FileData_Table();
// If there is a file name, then the filedata table will be loaded from disk.
if (filename) {
if (!Find_File(filename)) {
return (FI_FILEDATA_FILE_NOT_FOUND);
}
fd = Open_File(filename, READ);
fsize = File_Size(fd);
if ((Ram_Free(MEM_NORMAL) < fsize)) {
Close_File(fd);
return (FI_FILEDATA_TOO_BIG);
}
// Allocate some system memory.
// Setup the new FileDataPtr and this time.
FileDataPtr = ptr = (FileDataType *) Alloc(fsize, MEM_NORMAL);
// Load the file up into memory.
Read_File(fd, FileDataPtr, fsize);
Close_File(fd);
// Process the filetable. The filenames need their pointers adjusted.
// At this time we will also count the number of files and number of PAK files.
NumPAKFiles = NumFiles = 0;
// Make sure that the file name will have a NUL at the end.
fname[12] = 0;
while(TRUE) {
// Have we reached the end of the list?
if (!ptr->Name) break;
// Adjust the name pointer to point the the correct area.
ptr->Name = (BYTE *)FileDataPtr + (LONG) ptr->Name;
// Count up weather it is a PAK file or a normal file.
if (!NumFiles && strstr((char *) ptr->Name, (char *) ".PAK")) {
NumPAKFiles++;
// Mark that it has been processed so that Open_File() will not do it.
ptr->Flag |= FILEF_PROCESSED;
} else {
NumFiles++;
}
// Next record.
ptr++;
}
}
return (FI_SUCCESS);
}
/***************************************************************************
* Set_Search_Drives -- Sets up the CDRom and HardDrive paths. *
* *
* INPUT: BYTE *cdpath - path of data files on a CD. *
* Should pass in NULL for non CD products. *
* *
* OUTPUT: FileInitErrorType error code. *
* Varibable defined: *
* ExecPath = Full path of EXE file. *
* StartPath = Directory user started in. *
* DataPath = secondary search path (typically CD-ROM). *
* Note: format of paths is "C:\PATH" *
* *
* WARNINGS: The cdpath may be overiden by a "-CD<path>" command line *
* arguement that specifies another drive (HARD or CD) and path *
* where the data resides. Whenever a file is opened, it checks *
* the startup drive first, then the CD search path if the first *
* search was unsuccessful. *
* *
* HISTORY: *
* 01/14/1993 SB : Created. *
* 04/19/1994 SKB : Mods for 32 bit library. *
*=========================================================================*/
PRIVATE FileInitErrorType cdecl Set_Search_Drives( BYTE *cdpath )
{
BYTE *ptr;
#if LIB_EXTERNS_RESOLVED
// NOTE: THIS IS WRONG, THIS IS NOT THE WAY TO GET THE EXE's PATH.
// Locate the executable.
strcpy(ExecPath, _argv[0]);
// Find the very last '\' on the path.
ptr = strrchr((char *) ExecPath, (int) '\\');
#else
ptr = NULL;
#endif
// Remove the exe name to just have the path.
if (ptr == NULL) {
*ExecPath = 0;
}
else {
*ptr = 0;
}
// Did the user specify a second path?
ptr = Find_Argv("-CD");
// If so, set the data path to that.
if (ptr) {
strcpy(DataPath, ptr + 3);
}
// Otherwise check to see if there is a CD-Rom drive.
else {
if (cdpath && *cdpath) {
#if LIB_EXTERNS_RESOLVED
UseCD = GetCDDrive();
#else
UseCD = FALSE;
#endif
}
else {
UseCD = FALSE;
}
// If so, set the Drive to it and find out if any directories.
if ( UseCD ) {
strcpy( DataPath, "A:" );
strcat( DataPath, cdpath);
*DataPath = 'A'+UseCD;
}
// If not, set the Data path to the execacutable path.
else {
strcpy(DataPath, ExecPath);
}
}
// Finnally, set the starting path.
getcwd(StartPath, XMAXPATH);
// Make sure they are all uppercase.
strupr(StartPath);
strupr(DataPath);
strupr(ExecPath);
// Change directories to the secondary search path (DataPath).
if (*DataPath && chdir(DataPath)) {
return (FI_SEARCH_PATH_NOT_FOUND);
}
// Lastley, Make sure we are in the startup directory. This will overide
// the secondary data path if they are on the same drive.
if (chdir(StartPath)) {
return (FI_STARTUP_PATH_NOT_FOUND);
}
return (FI_SUCCESS);
}
/***************************************************************************
* PRELOAD_FILES -- Loads files marked with FILEF_PRELOAD into cache. *
* *
* *
* INPUT: none. *
* *
* OUTPUT: FileInitErrorType error code. *
* *
* WARNINGS: The FileData must be initialized and the file heap initialized*
* in order for this to work. *
* *
* HISTORY: *
* 04/19/1994 SKB : Created. *
*=========================================================================*/
PRIVATE FileInitErrorType cdecl Preload_Files(VOID)
{
FileDataType *filedata; // Working file data table pointer.
BOOL oldflag; // Previous file flag.
if (!FileDataPtr) {
return (FI_FILETABLE_NOT_INIT);
}
if (!FileCacheHeap) {
return (FI_NO_CACHE_FOR_PRELOAD);
}
/*
** Make all files flagged to be made resident at startup, resident.
*/
filedata = FileDataPtr;
while (filedata->Name && strlen(filedata->Name)) {
if (filedata->Flag & FILEF_PRELOAD) {
oldflag = filedata->Flag;
filedata->Flag |= FILEF_RESIDENT; // Make it resident.
filedata->Flag &= ~FILEF_FLUSH; // Don't purge on Close_File.
Close_File(Open_File(filedata->Name, READ));
filedata->Flag &= ~(FILEF_RESIDENT|FILEF_FLUSH); // Clear bits.
filedata->Flag |= oldflag & (FILEF_RESIDENT|FILEF_FLUSH); // Restore bits.
}
filedata++;
}
return (FI_SUCCESS);
}
/***************************************************************************
* SORT_FILEDATA_TABLE -- Sorts the FileData table that is in memory. *
* *
* INPUT: NONE *
* *
* OUTPUT: NONE. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 09/13/1993 SKB : Created. *
*=========================================================================*/
PRIVATE int QSort_Comp_Func(const void *p1, const void *p2)
{
return(strcmp(((FileDataType*)p1)->Name, ((FileDataType*)p2)->Name));
}
PRIVATE VOID Sort_FileData_Table(VOID)
{
/*
** Sort the filetable it but keep the pack file indexes correct.
*/
/*
** The number of pak files in the file table.
*/
NumPAKFiles = 0;
strupr(FileData[NumPAKFiles].Name);
while (strstr((char *) FileData[NumPAKFiles].Name, (char *) ".PAK")) {
strupr(FileData[NumPAKFiles].Name);
NumPAKFiles++;
}
/*
** Count the remaining files within the file table.
*/
NumFiles = 0;
while(FileData[NumFiles+NumPAKFiles].Name && FileData[NumFiles+NumPAKFiles].Name[0]) {
strupr(FileData[NumFiles+NumPAKFiles].Name);
NumFiles++;
}
/*
** Sort the file entries (past the pak files).
*/
if (NumFiles) {
qsort(&FileData[NumPAKFiles], NumFiles, sizeof(FileDataType), QSort_Comp_Func);
}
}


View File

@@ -0,0 +1,151 @@
/*
** 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 Library *
* *
* File Name : FILEIO.C *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : August 21, 1991 *
* *
* Last Update : September 13, 1993 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WWSTD_H
#include "wwstd.h"
#endif
#ifndef _FILE_H
#include "_file.h"
#endif
#include <dos.h>
#include <direct.h>
#include <io.h>
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
WORD ibm_getdisk(VOID)
{
unsigned disk;
CallingDOSInt++;
// disk = getdisk();
_dos_getdrive ( & disk ) ;
CallingDOSInt--;
return(disk-1);
}
WORD ibm_setdisk(WORD drive)
{
// WORD disk;
unsigned disk ;
CallingDOSInt++;
// disk = setdisk(drive);
_dos_setdrive ( drive+1 , & disk ) ;
CallingDOSInt--;
return(disk);
}
WORD ibm_close(WORD handle)
{
WORD success;
CallingDOSInt++;
success = close(handle);
CallingDOSInt--;
return(success);
}
WORD ibm_unlink(BYTE const *name)
{
WORD success;
CallingDOSInt++;
success = unlink(name);
CallingDOSInt--;
return(success);
}
LONG ibm_lseek(WORD handle, LONG offset, WORD where)
{
LONG new_offset;
CallingDOSInt++;
new_offset = lseek(handle, offset, where);
CallingDOSInt--;
return(new_offset);
}
UWORD ibm_read(WORD handle, VOID *ptr, UWORD bytes)
{
UWORD bytes_read;
CallingDOSInt++;
bytes_read = read(handle, ptr, bytes);
CallingDOSInt--;
return(bytes_read);
}
UWORD ibm_write(WORD handle, VOID *ptr, UWORD bytes)
{
UWORD bytes_written;
CallingDOSInt++;
bytes_written = write(handle, ptr, bytes);
CallingDOSInt--;
return(bytes_written);
}
WORD ibm_open(BYTE const *name, UWORD mode, WORD attrib)
{
WORD handle;
CallingDOSInt++;
handle = open(name, mode, attrib);
CallingDOSInt--;
return(handle);
}
WORD ibm_chdir(BYTE const *path)
{
WORD retval;
CallingDOSInt++;
retval = chdir(path);
CallingDOSInt--;
return(retval);
}


View File

@@ -0,0 +1,388 @@
/*
** 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 : FILEIO Library support routines. *
* *
* File Name : FILELIB.C *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : April 11, 1994 *
* *
* Last Update : April 11, 1994 [SKB] *
* *
* *
* *
*-------------------------------------------------------------------------*
* Notes: This file contains private functions to the fileio system. *
* While these functions may be used by any module in the fileio *
* system, they cannot be used by a user program. For this reason *
* they are put into this module. *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Cache_File -- Attempts to cache file in XMS if flags set. *
* Do_IO_Error -- Performs a non-recoverable error message display. *
* Do_Open_Error -- Does an error message that could return. *
* Is_Handle_Valid -- Determines validity of the specified file handle. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WWSTD_H
#include "wwstd.h"
#endif
#ifndef _FILE_H
#include "_file.h"
#endif
#ifndef WWMEM_H
#include <wwmem.h>
#endif
#include <fcntl.h>
#include <io.h>
#include <process.h>
#include <sys\stat.h>
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* DO_ERROR -- Does an error message that could return. *
* *
* This routine displays a file error message and unless the player *
* presses <ESC>, it will return. If the player presses <ESC>, then *
* it will terminate the program. *
* *
* INPUT: error -- Error message number. *
* *
* filename -- File name that the error occured on. *
* *
* OUTPUT: TRUE/FALSE; Should the process be repeated? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/09/1991 JLB : Created. *
*=========================================================================*/
#pragma argsused
WORD cdecl Do_Open_Error(FileErrorType errormsgnum, BYTE const *file_name)
{
BYTE *ptr=NULL; // Working file name pointer (just name and extension).
/*
** Since the file name may include a path, we must extract the true
** file name from the given string.
*/
if (file_name) {
#if LIB_EXTERNS_RESOLVED
ptr = strrchr((char *) file_name, (int) '\\');
#else
ptr = NULL;
#endif
if (ptr) {
ptr++;
} else {
ptr = (BYTE *) file_name;
}
}
#if LIB_EXTERNS_RESOLVED
strupr(ptr);
return (IO_Error(errormsgnum, ptr));
#else
return(0);
#endif
}
/***************************************************************************
* DO_IO_ERROR -- Performs a non-recoverable error message display. *
* *
* This routine will perform a non-recoverable file error message *
* display. It is called when an error is detected that has no *
* recovery or retry process defined. *
* *
* INPUT: errornum -- Error number detected. *
* *
* filename -- Name of the file that caused the error. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/09/1991 JLB : Created. *
*=========================================================================*/
#pragma argsused
VOID cdecl Do_IO_Error(FileErrorType errormsgnum, BYTE const *filename)
{
#if LIB_EXTERNS_RESOLVED
(VOID)IO_Error(errormsgnum, filename);
#endif
#if(TRUE)
Prog_End();
exit((int)errormsgnum);
#else
Program_End();
#endif
}
/***************************************************************************
* Read_File_With_Recovery -- read the same file on another directory if an error *
* occurs. *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/16/1993 QY : Created. *
*=========================================================================*/
LONG cdecl Read_File_With_Recovery( WORD handle, VOID *buf, UWORD bytes )
{
WORD newhandle;
LONG bytes_read;
do {
Hard_Error_Occured = 0;
// Make sure we are in the right path.
CHANGEDIR( DataPath );
// open the same file
newhandle = Open_File( FileHandleTable[ handle ].Name, FileHandleTable[ handle ].Mode );
Seek_File( newhandle, FileHandleTable[ handle ].Pos, SEEK_SET );
// dos close the old file
FILECLOSE( FileHandleTable[ handle ].Handle );
// copy FileHandleTable[ newhandle ] to FileHandleTable[ handle ]
Mem_Copy( &FileHandleTable[ newhandle ], &FileHandleTable[ handle ],
( ULONG ) sizeof( FileHandleTable[ newhandle ] ) );
// delete FileHandleTable[newhandle]
FileHandleTable[ newhandle ].Empty = TRUE;
// continue reading file
bytes_read = ( LONG ) FILEREAD( FileHandleTable[ handle ].Handle, buf, bytes );
// if still error, do it again; else return the number of bytes read
if ( !Hard_Error_Occured ) {
return( bytes_read );
}
if (!Do_Open_Error(COULD_NOT_OPEN, FileHandleTable[ handle ].Name)) {
return(FALSE);
}
} while (CHANGEDIR( DataPath ));
return (NULL);
}
/***************************************************************************
* Open_File_With_Recovery -- open the same file on another directory *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/16/1993 QY : Created. *
*=========================================================================*/
WORD cdecl Open_File_With_Recovery( BYTE const *file_name, UWORD mode )
{
WORD handle;
Hard_Error_Occured = FALSE;
handle = FILEOPEN(file_name, mode);
// Do not return if there was a HardError and Using a CD and we are looking at
// the CD.
if (!Hard_Error_Occured || !UseCD || (ibm_getdisk() != (*DataPath - 'A'))) {
return (handle);
}
#if DEBUGPRINT
Mono_Print(file_name); Mono_Print(":OPENERROR ");
#endif
Hard_Error_Occured = 0;
// It is possible that the CD has been poped out and put back in, let us
// change there and then try again.
ibm_setdisk(*DataPath - 'A');
CHANGEDIR( DataPath );
// open the same file
handle = FILEOPEN( file_name, mode );
// if still error, do it again; else return the dos handle
if ( !Hard_Error_Occured ) {
return( handle );
}
Hard_Error_Occured = 0;
return (FILEOPENERROR);
}
/***************************************************************************
* CACHE_FILE -- Attempts to cache file in XMS if flags set. *
* *
* *
* INPUT: WORD index - the index of the file in the FileData table. *
* WORD file_handle - WWS file handle of file. *
* *
* OUTPUT: BOOL : was it cached? *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/21/1993 SKB : Created. *
*=========================================================================*/
BOOL cdecl Cache_File(WORD index, WORD file_handle)
{
LONG filesize; // Size of the memory block needed.
LONG freecache; // Amount of free XMS.
FileDataType *filedata = NULL;
FileDataType hold;
FileHandleType *filehandletable;
WORD flag; // Type of system memory to cache file.
WORD file;
// Only files in the file table can be cached.
if (index == ERROR) {
return FALSE;
}
// Setup our pointer to the file we may want to cache.
filedata = &FileDataPtr[index];
// Should this be cached, and is it not yet cached?
if ((filedata->Flag & (FILEF_RESIDENT|FILEF_PRELOAD)) && !filedata->Ptr) {
filesize = filedata->Size;
/*
** If there is o room to cache the file, then turn off its cache file.
*/
if (filesize > Mem_Pool_Size(FileCacheHeap)) {
// Remove resident flags so that it will not keep trying to cache itself
// since there will never be enough room for it.
filedata->Flag &= ~(FILEF_PRELOAD|FILEF_KEEP|FILEF_RESIDENT|FILEF_FLUSH);
return FALSE;
}
// Go through freeing files until there is enouph space in the
// memory pool.
while (filesize > Mem_Avail(FileCacheHeap)) {
VOID *node;
// Get the oldest non used file pointer.
node = Mem_Find_Oldest(FileCacheHeap);
// If non was found, sorry no room for the new file.
if (!node) {
return (FALSE);
}
// Get a pointer to the structure for convenience.
filedata = &FileDataPtr[Mem_Get_ID(node)];
// Free it from the heap and update the file system so it knows that
// the file is no longer in memory.
Mem_Free(FileCacheHeap, filedata->Ptr);
filedata->Ptr = NULL;
}
// If there is not a big enough space we will have to take garbage
// collection hit. (OUCH!!!!!!)
if (filesize > Mem_Largest_Avail(FileCacheHeap)) {
Unfragment_File_Cache();
}
// Make sure we have a big enough space and if so, put the file into memory.
if (filesize < Mem_Largest_Avail(FileCacheHeap)) {
// Get some pointers to save code space and time.
filehandletable = &FileHandleTable[file_handle];
filedata = &FileDataPtr[index];
// Alloc the buffer in our file cache, then read the file in.
filedata->Ptr = Mem_Alloc(FileCacheHeap, filesize, index);
// Extra check - it should not fail.
if (!filedata->Ptr) return(FALSE);
// Mark it so that it never comes back as Oldest used.
Mem_In_Use(filedata->Ptr);
// Get the file into memory.
Read_File(file_handle, filedata->Ptr, filesize);
// reset the read index from the above read.
filehandletable->Pos = 0L;
// This makes caching inner pak file possible. No longer is the
// PAK'd file based off the parent file.
filehandletable->Start = 0;
// Close the parent file. Remove it's open count.
if (filedata->Flag & FILEF_PACKED) {
FileDataType p_hold;
FileDataType *parent;
parent = &FileDataPtr[filedata->Disk];
parent->OpenCount--;
}
FILECLOSE(filehandletable->Handle);
filehandletable->Handle = 0;
return (TRUE);
}
}
// The file was not cached, let the caller know.
return (FALSE);
}

View File

@@ -0,0 +1,41 @@
/*
** 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 *
* *
* File Name : FILESTUB.CPP *
* *
* Programmer : Bill Randolph *
* *
* Start Date : May 3, 1994 *
* *
* Last Update : May 3, 1994 [BR] *
* *
* This module is a temorary stub that contains IO_Error. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "wwstd.h"
#include "file.h"
WORD Text_IO_Error(FileErrorType, BYTE const *){return FALSE;}
WORD (*IO_Error)(FileErrorType, BYTE const *) = Text_IO_Error;
/************************* End of filestub.cpp *****************************/

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,90 @@
/*
** 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/wwlib32/misc/rcs/findargv.cpp 1.2 1994/04/22 10:29:28 scott_bowen 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 : findargv *
* *
* File Name : findargv.C *
* *
* Programmer : Jeff Wilson *
* *
* Start Date : January 14, 1993 *
* *
* Last Update : May 20, 1993 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Find_Argv -- Checks to see if string is in arguement *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "wwstd.h"
#include <dos.h>
#include <stdio.h>
#include <string.h>
#include <process.h>
/***************************************************************************
* Find_Argv -- Checks to see if string is in arguement *
* *
* INPUT: char *str - string to search for. *
* *
* OUTPUT: NULL if not found else pointer to string. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 01/14/1993 SB : Created. *
*=========================================================================*/
//static char command [ 256 ] ;
#pragma on (argsused)
char * __cdecl Find_Argv(char const)
{
return (NULL);
#ifdef NOT_FOR_WIN95
char * __cdecl Find_Argv(char const *str)
{
char * ptr ;
static startup_flag = 0 ;
if ( ! startup_flag )
{
startup_flag = 1 ;
getcmd ( command ) ;
}
if ( ! strlen(str) ) return NULL ;
return strstr ( command , str ) ;
#endif
}


View File

@@ -0,0 +1,312 @@
/*
** 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 Library *
* *
* File Name : FINDFILE.C *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : August 21, 1991 *
* *
* Last Update : September 29, 1993 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Find_File_Index -- Finds the FileTable index number for a given file. *
* Find_File -- Checks if a file is immediatly available. *
* Get_FileData -- Gets a pointer back to the correct file. *
* Find_File -- Checks if a file is immediatly available. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
#ifndef WWSTD_H
#include "wwstd.h"
#endif
#ifndef _FILE_H
#include "_file.h"
#endif
#include <direct.h>
#include <dos.h>
#include <fcntl.h>
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <search.h>
#include <sys\stat.h>
/***************************************************************************
* FIND_FILE -- Checks if a file is immediatly available. *
* *
* Use this function to determine if a file is immediatly available. *
* This routine will NOT request for the proper disk to be inserted *
* if the file could not be found. Use File_Exists for that feature. *
* The Westwood file I/O system does NOT have to be initialized as *
* a prerequisit to using this function. *
* *
* INPUT: file_name -- Name of the file to check. *
* *
* OUTPUT: Returns the disk number that the file exits on (A=1, B=2, etc) *
* *
* WARNINGS: This sets the current drive to the drive that contains the *
* specified file (if it is found). *
* *
* HISTORY: *
* 11/14/1991 JLB : Created. *
* 03/14/1992 JLB : Modified for Amiga compatability. *
* 01/11/1993 SKB : Modified for CD-ROM searches. *
*=========================================================================*/
WORD cdecl Find_File(BYTE const *file_name)
{
FileDataType *filedata = NULL;
WORD index; // File index (if any).
WORD disk; // Disk number of file (if in filetable).
/*
** If the filename is invalid then it errors out as if the file wasn't
** found (naturally).
*/
if (!file_name) return(FALSE);
/*
** Determine if the file has a file table entry. If it does, then
** special checks and processing must occur.
** Also, if it is in memory, return with it.
*/
index = Find_File_Index(file_name);
filedata = &FileDataPtr[index];
if (index != ERROR) {
// If the file is currently cached, return TRUE that it was found.
if (filedata->Ptr) {
return (TRUE);
}
}
/*
** Always check the current directory for the file. Only if it can't
** be found are furthur measures required.
*/
DiskNumber = ERROR; // This indicates file exists in current directory.
#if (LIB_CDROM)
ibm_setdisk(*StartPath - 'A');
#endif
/*
** Check the current directory by attempting to open with READ access.
*/
{
WORD handle;
CallingDOSInt++;
handle = open(file_name, O_RDONLY | O_BINARY, S_IREAD);
CallingDOSInt--;
if (handle != ERROR)
{
// WORD d;
unsigned d ;
CallingDOSInt++;
close(handle);
// d = getdisk();
_dos_getdrive ( & d) ;
CallingDOSInt--;
return(d);
}
}
if (index != ERROR) {
disk = filedata->Disk;
/*
** If the file is in a packed file, then search for the packed file
** instead of the specified one.
*/
if (index != ERROR && (filedata->Flag & FILEF_PACKED)) {
filedata = &FileDataPtr[disk];
return (Find_File(filedata->Name));
}
}
/*
** It could not be found on the current drive, so search the other
** drives if allowed to do so.
*/
if (!MultiDriveSearch) {
return(FALSE);
}
#if (LIB_CDROM)
// If we were unable to find the file on the hard drive, change
// drives to the CD rom drive and see if it is there.
ibm_setdisk(*DataPath - 'A');
{
WORD handle;
Hard_Error_Occured = 0;
handle = Open_File_With_Recovery( file_name, MODE_OLDFILE );
if (handle != FILEOPENERROR) {
FILECLOSE(handle);
return(ibm_getdisk() + 1);
}
}
ibm_setdisk(*StartPath - 'A');
return (FALSE);
#else
{
WORD start_drive; // Original current drive number.
/*
** Record the current drive for restoring later in case of failure.
*/
CallingDOSInt++;
start_drive = getdisk();
CallingDOSInt--;
/*
** Sweep backward from the last real drive to the first, looking for the
** file on each in turn.
*/
for (index = MaxDevice; index != -1; index--) {
if (Is_Device_Real(index)) {
CallingDOSInt++;
setdisk(index);
CallingDOSInt--;
{
WORD handle;
CallingDOSInt++;
handle = open(file_name, O_RDONLY | O_BINARY, S_IREAD);
CallingDOSInt--;
if (handle != ERROR) {
CallingDOSInt++;
close(handle);
CallingDOSInt--;
DiskNumber = index+1;
return (DiskNumber);
}
}
}
}
CallingDOSInt++;
setdisk(start_drive);
CallingDOSInt--;
}
return(FALSE);
#endif
}
/***************************************************************************
* FIND_FILE_INDEX -- Finds the FileTable index number for a given file. *
* *
* This function searches the FileTable and returns with the index of *
* the matching file. If the file doesn't exist in the table, then *
* ERROR is returned. It does not care about case. *
* *
* INPUT: filename -- Pointer to the filename to check. *
* *
* OUTPUT: Returns with the index into the FileTable. If the file does *
* not exist in the file table, then ERROR is returned. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 11/09/1991 JLB : Created. *
* 06/11/1993 JLB : Sorts and binary searches the file table. *
*=========================================================================*/
PRIVATE int Comp_Func(const void *p1, const void *p2)
{
return(strcmp((char *) ((FileDataType*)p1)->Name, (char *) ((FileDataType*)p2)->Name));
}
WORD cdecl Find_File_Index(BYTE const *filename)
{
FileDataType *filedata; // File entry pointer.
FileDataType key; // Working file data type var.
/*
** Perform a binary search on the presorted filetable.
*/
if (filename) {
filedata = NULL;
key.Name = (BYTE *) strupr((char *)filename);
if (strstr((char *)key.Name, (char *)".PAK")) {
/*
** If the FileData table was not loaded from the disk then the PAK files are
** not sorted so Perform a linear search for the pak files.
** Otherwise the files are sorted so speed things up by doing a bsearch.
*/
if (FileData == FileDataPtr) {
filedata = (FileDataType *) lfind(&key, FileDataPtr, (size_t *) &NumPAKFiles, sizeof(FileDataType), Comp_Func);
}
else {
filedata = (FileDataType *)bsearch(&key, FileDataPtr, NumPAKFiles, sizeof(FileDataType), Comp_Func);
}
} else {
/*
** Perform a binary search for the regular files.
*/
filedata = (FileDataType *)bsearch(&key, &FileDataPtr[NumPAKFiles], NumFiles, sizeof(FileDataType), Comp_Func);
}
// Return the element in the array if file was found in table.
if (filedata) {
return (filedata - FileDataPtr);
//return ((WORD)((((LONG)filedata) - ((LONG)FileDataPtr)) / sizeof(FileDataType)));
}
}
return(ERROR);
}


141
WIN32LIB/SRCDEBUG/FONT.CPP Normal file
View File

@@ -0,0 +1,141 @@
/*
** 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 : LIBRARY *
* *
* File Name : FONT.C *
* *
* Programmer : David Dettmer *
* *
* Last Update : July 20, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Char_Pixel_Width -- Return pixel width of a character. *
* String_Pixel_Width -- Return pixel width of a string of characters. *
* Get_Next_Text_Print_XY -- Calculates X and Y given ret value from Text_P*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "font.h"
#include <malloc.h>
#include <dos.h>
#include <fcntl.h>
#include <io.h>
#include <sys\stat.h>
#include <string.h>
#include <wwstd.h>
/***************************************************************************
* CHAR_PIXEL_WIDTH -- Return pixel width of a character. *
* *
* Retreives the pixel width of a character from the font width block. *
* *
* INPUT: Character. *
* *
* OUTPUT: Pixel width of a string of characters. *
* *
* WARNINGS: Set_Font must have been called first. *
* *
* HISTORY: *
* 01/31/1992 DRD : Created. *
* 06/30/1994 SKB : Converted to 32 bit library. *
*=========================================================================*/
int __cdecl Char_Pixel_Width(char chr)
{
int width;
width = (unsigned char)*(FontWidthBlockPtr + (unsigned char)chr) + FontXSpacing;
return(width);
}
/***************************************************************************
* STRING_PIXEL_WIDTH -- Return pixel width of a string of characters. *
* *
* Calculates the pixel width of a string of characters. This uses *
* the font width block for the widths. *
* *
* INPUT: Pointer to string of characters. *
* *
* OUTPUT: Pixel width of a string of characters. *
* *
* WARNINGS: Set_Font must have been called first. *
* *
* HISTORY: *
* 01/30/1992 DRD : Created. *
* 01/31/1992 DRD : Use Char_Pixel_Width. *
* 06/30/1994 SKB : Converted to 32 bit library. *
*=========================================================================*/
unsigned int __cdecl String_Pixel_Width(char const *string)
{
WORD width; // Working accumulator of string width.
WORD largest = 0; // Largest recorded width of the string.
if (!string) return(0);
width = 0;
while (*string) {
if (*string == '\r') {
string++;
largest = MAX(largest, width);
width = 0;
} else {
width += Char_Pixel_Width(*string++); // add each char's width
}
}
largest = MAX(largest, width);
return(largest);
}
/***************************************************************************
* GET_NEXT_TEXT_PRINT_XY -- Calculates X and Y given ret value from Text_P*
* *
* *
* INPUT: VVPC& vp - viewport that was printed to. *
* unsigned long offset - offset that Text_Print returned. *
* INT *x - x return value. *
* INT *y - y return value. *
* *
* OUTPUT: x and y are set. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 07/20/1994 SKB : Created. *
*=========================================================================*/
VOID __cdecl Get_Next_Text_Print_XY(GraphicViewPortClass& gp, unsigned long offset, INT *x, INT *y)
{
INT buffwidth;
if (offset) {
buffwidth = gp.Get_Width() + gp.Get_XAdd();
offset -= gp.Get_Offset();
*x = offset % buffwidth;
*y = offset / buffwidth;
} else {
*x = *y = 0;
}
}

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 ) );
}

124
WIN32LIB/SRCDEBUG/GETCD.CPP 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 : WWLIB *
* *
* File Name : GETCD.CPP *
* *
* Programmer : STEVE WETHERILL BASED ON JOE BOSTIC CODE *
* *
* Start Date : 5/13/94 *
* *
* Last Update : June 4, 1994 [SW] *
* *
*-------------------------------------------------------------------------*
*-------------------------------------------------------------------------*
* Functions: *
* GetCDClass::GetCDClass -- default constructor *
* GetCDClass::~GetCDClass -- destructor *
* GetCDClass::GetCDDrive -- returns the logical CD drive *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include "wwstd.h"
#include "playcd.h"
#include "wwmem.h"
/***************************************************************************
* GetCDClass -- default constructor *
* *
* *
* *
* INPUT: *
* none *
* OUTPUT: *
* none *
* WARNINGS: *
* *
* HISTORY: *
* 05/26/1994 SW : Created. *
* 12/4/95 ST : fixed for Win95 *
*=========================================================================*/
GetCDClass::GetCDClass(VOID)
{
char path[]={"a:\\"};
CDCount = 0;
CDIndex = 0;
/*
** Set all CD drive placeholders to empty
*/
memset (CDDrives, NO_CD_DRIVE, MAX_CD_DRIVES);
for (char i='c' ; i<='z' ; i++){
path[0]=i;
if (GetDriveType (path) == DRIVE_CDROM){
CDDrives[CDCount++] = (int) (i-'a');
}
}
/*
** Catch the case when there are NO CD-ROM drives available
*/
if (CDCount == 0) {
for (char i='a' ; i<='b' ; i++){
path[0]=i;
if (GetDriveType (path) == DRIVE_CDROM){
CDDrives[CDCount++] = (int) (i-'a');
}
}
}
}
/***************************************************************************
* GetCDClass -- destructor *
* *
* *
* *
* INPUT: *
* none *
* OUTPUT: *
* none *
* WARNINGS: *
* *
* HISTORY: *
* 05/26/1994 SW: Created. *
* 12/4/95 ST: fixed for Win95 *
*=========================================================================*/
GetCDClass::~GetCDClass(VOID)
{
// if(cdDrive_addrp.seg)
// DPMI_real_free(cdDrive_addrp); // free up those conventional buffers
}
/* ==================================================================== */

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,362 @@
/*
** 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 Library *
* *
* File Name : GETSHAPE.CPP *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : April 5, 1992 *
* *
* Last Update : May 25, 1994 [BR] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Get_Shape_Size -- Fetch the size of the shape in memory. *
* Get_Shape_Uncomp_Size -- gets shape's uncompressed size in bytes *
* Get_Shape_Data -- retrieves a shape's special prefix data *
* Extract_Shape_Count -- returns # of shapes in the given shape block *
* Extract_Shape -- Gets pointer to shape in given shape block *
* Get_Shape_Width -- gets shape width in pixels *
* Get_Shape_Height -- gets shape height in pixels *
* Set_Shape_Height -- modifies shape's height *
* Restore_Shape_Height -- restores a shape to its original height *
* Get_Shape_Original_Height -- gets shape's unmodified height *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
********************************* Includes **********************************
*/
#include "wwstd.h"
#include "shape.h"
/***************************************************************************
* Get_Shape_Size -- Fetch the size of the shape in memory. *
* *
* The shape size returned includes both the shape header & its data. *
* *
* INPUT: *
* shape pointer to shape *
* *
* OUTPUT: *
* shape's size in memory *
* *
* WARNINGS: *
* none *
* *
* HISTORY: *
* 06/09/1992 JLB : Created. *
* 08/19/1993 SKB : Split drawshp.asm into several modules. *
* 05/25/1994 BR : Converted to 32-bit *
*=========================================================================*/
int cdecl Get_Shape_Size(VOID const *shape)
{
Shape_Type *shp = (Shape_Type *)shape;
/*
------------------------- Return if NULL pointer -------------------------
*/
if (!shape)
return(0);
/*
-------------------------- Returns shape's size --------------------------
*/
return (shp->ShapeSize);
} /* end of Get_Shape_Size */
/***************************************************************************
* Get_Shape_Uncomp_Size -- gets shape's uncompressed size in bytes *
* *
* INPUT: *
* shape pointer to shape *
* *
* OUTPUT: *
* shape's size in bytes when uncompressed *
* *
* WARNINGS: *
* none *
* *
* HISTORY: *
* 06/09/1992 JLB : Created. *
* 08/19/1993 SKB : Split drawshp.asm into several modules. *
* 05/25/1994 BR : Converted to 32-bit *
*=========================================================================*/
int Get_Shape_Uncomp_Size(VOID const *shape)
{
Shape_Type *shp = (Shape_Type *)shape;
return (shp->DataLength);
} /* end of Get_Shape_Uncomp_Size */
/***************************************************************************
* Get_Shape_Data -- retrieves a shape's special prefix data *
* *
* MAKESHPS.EXE can store special data values along with a shape. These *
* values are inserted in the shape table >before< the shape's header. *
* So, this routine uses the 'data' parameter as a negative index from *
* the given shape pointer. *
* *
* INPUT: *
* shape pointer to shape *
* data index of WORD data value to get *
* *
* OUTPUT: *
* data value *
* *
* WARNINGS: *
* The shape pointer must be a pointer into a shape table created by *
* MAKESHPS.EXE; it >cannot< be a pointer to shape returned by Make_Shape! *
* *
* HISTORY: *
* 06/09/1992 JLB : Created. *
* 08/19/1993 SKB : Split drawshp.asm into several modules. *
* 05/25/1994 BR : Converted to 32-bit *
*=========================================================================*/
WORD cdecl Get_Shape_Data(VOID const *shape, WORD data)
{
WORD *word_ptr = (WORD *)shape;
WORD retval;
retval = *(word_ptr - (data+1));
return (retval);
} /* end of Get_Shape_Data */
/***************************************************************************
* Extract_Shape_Count -- returns # of shapes in the given shape block *
* *
* The # of shapes in a shape block is the first WORD in the block, so *
* this is the value returned. *
* *
* INPUT: *
* buffer pointer to shape block, created with MAKESHPS.EXE *
* *
* OUTPUT: *
* # shapes in the block *
* *
* WARNINGS: *
* none *
* *
* HISTORY: *
* 06/09/1992 JLB : Created. *
* 08/19/1993 SKB : Split drawshp.asm into several modules. *
* 05/25/1994 BR : Converted to 32-bit *
*=========================================================================*/
int cdecl Extract_Shape_Count(VOID const *buffer)
{
ShapeBlock_Type *block = (ShapeBlock_Type *)buffer;
return (block->NumShapes);
} /* end of Extract_Shape_Count */
/***************************************************************************
* Extract_Shape -- Gets pointer to shape in given shape block *
* *
* INPUT: *
* buffer pointer to shape block, created with MAKESHPS.EXE *
* shape index of shape to get *
* *
* OUTPUT: *
* pointer to shape in the shape block *
* *
* WARNINGS: *
* none *
* *
* HISTORY: *
* 06/09/1992 JLB : Created. *
* 08/19/1993 SKB : Split drawshp.asm into several modules. *
* 05/25/1994 BR : Converted to 32-bit *
*=========================================================================*/
VOID * cdecl Extract_Shape(VOID const *buffer, int shape)
{
ShapeBlock_Type *block = (ShapeBlock_Type*) buffer;
int numshapes; // Number of shapes
long offset; // Offset of shape data, from start of block
char *bytebuf = (char*) buffer;
/*
----------------------- Return if invalid argument -----------------------
*/
if (!buffer || shape < 0 || shape >= block->NumShapes)
return(NULL);
offset = block->Offsets[shape];
return(bytebuf + 2 + offset);
} /* end of Extract_Shape */
/***************************************************************************
* Get_Shape_Width -- gets shape width in pixels *
* *
* INPUT: *
* shape pointer to a shape *
* *
* OUTPUT: *
* shape width in pixels *
* *
* WARNINGS: *
* none *
* *
* HISTORY: *
* 06/09/1992 JLB : Created. *
* 08/19/1993 SKB : Split drawshp.asm into several modules. *
* 05/25/1994 BR : Converted to 32-bit *
*=========================================================================*/
int Get_Shape_Width(VOID const *shape)
{
Shape_Type *shp = (Shape_Type *)shape;
return (shp->Width);
} /* end of Get_Shape_Width */
/***************************************************************************
* Get_Shape_Height -- gets shape height in pixels *
* *
* INPUT: *
* shape pointer to a shape *
* *
* OUTPUT: *
* shape height in pixels *
* *
* WARNINGS: *
* none *
* *
* HISTORY: *
* 06/09/1992 JLB : Created. *
* 08/19/1993 SKB : Split drawshp.asm into several modules. *
* 05/25/1994 BR : Converted to 32-bit *
*=========================================================================*/
int Get_Shape_Height(VOID const *shape)
{
Shape_Type *shp = (Shape_Type *)shape;
return (shp->Height);
} /* end of Get_Shape_Height */
/***************************************************************************
* Set_Shape_Height -- modifies shape's height *
* *
* The new height must be shorter than the original height. This effect *
* chops off the lower portion of the shape, like it's sinking into the *
* ground. *
* *
* INPUT: *
* shape pointer to a shape *
* newheight new shape height *
* *
* OUTPUT: *
* old shape height *
* *
* WARNINGS: *
* none *
* *
* HISTORY: *
* 06/09/1992 JLB : Created. *
* 08/19/1993 SKB : Split drawshp.asm into several modules. *
* 05/25/1994 BR : Converted to 32-bit *
*=========================================================================*/
int cdecl Set_Shape_Height(VOID const *shape, WORD newheight)
{
Shape_Type *shp = (Shape_Type *)shape;
WORD oldheight;
oldheight = shp->Height;
shp->Height = newheight;
return(oldheight);
} /* end of Set_Shape_Height */
/***************************************************************************
* Restore_Shape_Height -- restores a shape to its original height *
* *
* INPUT: *
* shape pointer to a shape *
* *
* OUTPUT: *
* old shape height *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/09/1992 JLB : Created. *
* 08/19/1993 SKB : Split drawshp.asm into several modules. *
* 05/25/1994 BR : Converted to 32-bit *
*=========================================================================*/
int cdecl Restore_Shape_Height(VOID *shape)
{
Shape_Type *shp = (Shape_Type *)shape;
WORD oldheight;
oldheight = shp->Height;
shp->Height = shp->OriginalHeight;
return(oldheight);
} /* end of Restore_Shape_Height */
/***************************************************************************
* Get_Shape_Original_Height -- gets shape's unmodified height *
* *
* INPUT: *
* shape pointer to a shape *
* *
* OUTPUT: *
* shape's unmodified height *
* *
* WARNINGS: *
* none *
* *
* HISTORY: *
* 06/09/1992 JLB : Created. *
* 08/19/1993 SKB : Split drawshp.asm into several modules. *
* 05/25/1994 BR : Converted to 32-bit *
*=========================================================================*/
int Get_Shape_Original_Height(VOID const *shape)
{
Shape_Type *shp = (Shape_Type *)shape;
return (shp->OriginalHeight);
} /* end of Get_Shape_Original_Height */
/************************* end of getshape.cpp *****************************/

View File

@@ -0,0 +1,216 @@
;
; 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 : Hard/Critical Error Handler *
;* *
;* File Name : harderr.asm *
;* *
;* Programmer : Scott K. Bowen. *
;* *
;* Start Date : July 18, 1994 *
;* *
;* Last Update : July 26, 1994 [SKB] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Install_Hard_Error_Handler -- Setup for handling critical errors *
;* Remove_Hard_Erroror_Handler -- Remove the critical error handler stuff*
;* Critical_Error_Handler -- Catch critical error interrupt. *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
;INCLUDE "tntdos.inc"
;//////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////// Equates ////////////////////////////////////////
DOS_SYS_CALL EQU 21h ; to do TNT DOS-XNDR system calls.
LOCK_PAGES EQU 5 ; Lock pages subfunction using DX_MEM_MGT
UNLOCK_PAGES EQU 6 ; Unlock pages subfunction using DX_MEM_MGT
CRITERR_INT_NUM EQU 24h
DISK_ERROR_BIT EQU 01000000000000000b ; bit 7 of dh.
DISK_ERROR EQU 1 ; Value of Hard_Error_Occured if disk/floppy error.
OTHER_ERROR EQU 2 ; Value of Hard_Error_Occured if other type of error.
;
; Interrupt handler stack frame
;
_FLGS equ [DWORD PTR ebp+52] ; 386|DOS-Extender flags
_GS equ [WORD PTR ebp+48] ; original GS
_FS equ [WORD PTR ebp+44] ; original FS
_DS equ [WORD PTR ebp+40] ; original DS
_ES equ [WORD PTR ebp+36] ; original ES
_SS equ [WORD PTR ebp+32] ; original SS
_ESP equ [DWORD PTR ebp+28] ; original ESP
_EFLAGS equ [DWORD PTR ebp+24] ; original EFLAGS
_CS equ [DWORD PTR ebp+20] ; original CS
_EIP equ [DWORD PTR ebp+16] ; original EIP
_EBP equ [DWORD PTR ebp] ; original EBP
;
; DOS critical error stack frame
;
_DOS_FLAGS equ [WORD PTR es:ebx+22] ; interrupt stack frame from real
_DOS_CS equ [WORD PTR es:ebx+20] ; mode INT 21h
_DOS_IP equ [WORD PTR es:ebx+18] ;
_DOS_ES equ [WORD PTR es:ebx+16] ; regs at time INT 21h was issued
_DOS_DS equ [WORD PTR es:ebx+14] ; in real mode
_DOS_BP equ [WORD PTR es:ebx+12] ;
_DOS_DI equ [WORD PTR es:ebx+10] ;
_DOS_SI equ [WORD PTR es:ebx+8] ;
_DOS_DX equ [WORD PTR es:ebx+6] ;
_DOS_CX equ [WORD PTR es:ebx+4] ;
_DOS_BX equ [WORD PTR es:ebx+2] ;
_DOS_AX equ [WORD PTR es:ebx] ;
;
; Error codes put into Hard_Error_Code
;
DISK_WRITE_PROTECTED equ 00h
UNKOWN_DEVICE equ 01h
DRIVE_NOT_READY equ 02h
UNKOWN_COMMAND equ 03h
CRC_ERROR equ 04h
WRONG_DATA_LENGTH equ 05h
SEEK_ERROR equ 06h
UNKOWN_DEVICE_TYPE equ 07h
SECTOR_NOT_FOUND equ 08h
OUT_OF_PAPER equ 09h
WRITE_ERROR equ 0Ah
READ_ERROR equ 0Bh
GENERAL_ERROR equ 0Ch
;//////////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////// Prototypes ///////////////////////////////////////
GLOBAL Install_Hard_Error_Handler :NEAR
GLOBAL Remove_Hard_Error_Handler :NEAR
;//////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////// Global/Local Data //////////////////////////////////
DATASEG
LABEL LockedDataStart BYTE
Hard_Error_Occured DB 0 ; Hard disk error or other error.
Hard_Error_Code DB 0 ; Error Code.
LABEL LockedDataEnd BYTE
OldRMI DD ? ; original real mode critical err vector
OldPMIOffset DD ? ; original protected mode critical err vector
OldPMISelector DD ? ; original PM crit error selector.
InitFlags DD 0 ; Flags to indicate what has been initialized.
; InitFlags that are set to have a fully functional interrupt.
IF_SET_VECTORS equ 1 ; Vectors have been set.
IF_LOCKED_PM_CODE equ 2 ; Locked PM code for DPMI.
IF_LOCKED_PM_DATA equ 4 ; Locked PM data for DPMI.
IF_FUNCTIONAL equ 8 ; crit error is in and functional.
;//////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////// Code //////////////////////////////////////////
CODESEG
;***************************************************************************
;* INSTALL_HARD_ERROR_HANDLER -- Setup for handling critical errors. *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 07/26/1994 SKB : Created. *
;*=========================================================================*
PROC Install_Hard_Error_Handler C near
USES eax,ebx,ecx,ds,es
ret
ENDP Install_Hard_Error_Handler
;***************************************************************************
;* REMOVE_HARD_ERROROR_HANDLER -- Remove the critical error handler stuff *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 07/26/1994 SKB : Created. *
;*=========================================================================*
PROC Remove_Hard_Error_Handler C near
USES ebx,ecx,edx,ds,es
;
; Restore the original interrupt vectors and exit
;
ret
ENDP Remove_Hard_Error_Handler
;***************************************************************************
;* Critical_Error_Handler -- Catch critical error interrupt. *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 07/26/1994 SKB : Created. *
;*=========================================================================*
LABEL LockedCodeStart BYTE
PROC Critical_Error_Handler NEAR
ENDP Critical_Error_Handler
LABEL LockedCodeEnd BYTE
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,342 @@
/*
** 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 : Library *
* *
* File Name : ICONSET.C *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : June 9, 1991 *
* *
* Last Update : September 15, 1993 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Load_Icon_Set -- Loads an icons set and initializes it. *
* Free_Icon_Set -- Frees allocations made by Load_Icon_Set(). *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//#include "function.h"
#define _WIN32
#define WIN32_LEAN_AND_MEAN
#include <dos.h>
#include <stdlib.h>
#include <stdio.h>
#include <mem.h>
#include <wwstd.h>
#include <file.h>
#include "tile.h"
#include <iff.h>
extern int Misc;
void * Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize);
void Free_Icon_Set(void const *iconset);
long Get_Icon_Set_Size(void const *iconset);
int Get_Icon_Set_Width(void const *iconset);
int Get_Icon_Set_Height(void const *iconset);
void * Get_Icon_Set_Icondata(void const *iconset);
void * Get_Icon_Set_Trans(void const *iconset);
void * Get_Icon_Set_Remapdata(void const *iconset);
void * Get_Icon_Set_Palettedata(void const *iconset);
int Get_Icon_Set_Count(void const *iconset);
void * Get_Icon_Set_Map(void const *iconset);
//#define ICON_PALETTE_BYTES 16
//#define ICON_MAX 256
/***************************************************************************
** The terrain is rendered by using icons. These are the buffers that hold
** the icon data, remap tables, and remap index arrays.
*/
//PRIVATE char *IconPalette = NULL; // MCGA only.
//PRIVATE char *IconRemap = NULL; // MCGA only.
#define FORM_RPAL MAKE_ID('R','P','A','L')
#define FORM_RTBL MAKE_ID('R','T','B','L')
#define FORM_SSET MAKE_ID('S','S','E','T')
#define FORM_SINF MAKE_ID('S','I','N','F')
#define FORM_ICON MAKE_ID('I','C','O','N')
#define FORM_TRNS MAKE_ID('T','R','N','S')
#define FORM_MAP MAKE_ID('M','A','P',' ')
/***************************************************************************
* LOAD_ICON_SET -- Loads an icons set and initializes it. *
* *
* This routine will load an IFF icon set from disk. It handles all *
* of the necessary allocations. *
* *
* INPUT: filename -- Name of the icon file. *
* *
* buffer -- Pointer to paragraph aligned buffer to hold data. *
* *
* size -- Size of the buffer (in bytes). *
* *
* OUTPUT: none *
* *
* WARNINGS: In EEGA mode the iconset buffer will be free because the *
* icons will have been transferred to card ram. *
* *
* HISTORY: *
* 06/21/1991 JLB : Created. *
* 07/01/1991 JLB : Determines icon size from file. *
* 07/15/1991 JLB : Load and uncompress onto the same buffer. *
* 09/15/1993 JLB : Added EMS support. *
*=========================================================================*/
void * Load_Icon_Set(char const *filename, void *iconsetptr, long buffsize)
{
int fh; // File handle of iconset.
int bytespericon; // The number of bytes per icon.
unsigned long icons=0; // Number of icons loaded.
unsigned long size; // Size of the icon chunk (raw).
unsigned long transsize;
void *transptr=NULL;
unsigned long mapsize; // Icon map chunk size.
void *mapptr=NULL; // Icon map pointer.
void *returnptr=NULL; // Iconset pointer returned by routine.
BOOL allocated=FALSE; // Was the iconset block allocated?
IControl_Type *idata=NULL; // Icon data loaded.
long id; // ID of file openned.
struct {
char Width; // Width of icon in bytes.
char Height; // Height of icon in bytes.
char Format; // Graphic mode.
//lint -esym(754,Format)
char Bitplanes; // Number of bitplanes per icon.
} sinf;
/*
** Open the icon set for loading. If it is not a legal icon set
** data file, then abort.
*/
fh = Open_Iff_File(filename);
if (fh != WW_ERROR) {
Read_File(fh, &id, sizeof(long));
if (id == FORM_ICON) {
/*
** Determine the size of the icons and set up the graphic
** system accordingly. Also get the sizes of the various
** data blocks that have to be loaded.
*/
Read_Iff_Chunk(fh, FORM_SINF, &sinf, sizeof(sinf));
bytespericon = ((((int)sinf.Width)<<3)*(((int)sinf.Height)<<3)*(int)sinf.Bitplanes)>>3;
size = Get_Iff_Chunk_Size(fh,FORM_SSET);
transsize = Get_Iff_Chunk_Size(fh, FORM_TRNS);
mapsize = Get_Iff_Chunk_Size(fh, FORM_MAP);
/*
** Allocate the icon buffer if one isn't provided. First try EMS and
** then try conventional RAM.
*/
allocated = FALSE;
if (!iconsetptr) {
buffsize = size + transsize + mapsize + sizeof(IControl_Type);
Misc = buffsize;
iconsetptr = Alloc(buffsize, MEM_NORMAL);
allocated = (iconsetptr != NULL);
}
if (iconsetptr && (size+transsize+mapsize+sizeof(IControl_Type)) <= buffsize) {
idata = (IControl_Type *)iconsetptr;
memset(idata, 0, sizeof(IControl_Type));
/*
** Initialize the iconset header structure.
*/
idata->Width = (short)(((short)sinf.Width)<<3);
idata->Height = (short)(((short)sinf.Height)<<3);
idata->Allocated = (short)allocated;
idata->Icons = (long)iconsetptr + sizeof(IControl_Type);
idata->Map = idata->Icons + size;
idata->TransFlag = sizeof(IControl_Type) + size + mapsize;
idata->Size = buffsize;
{
long val;
val = Read_Iff_Chunk(fh, FORM_SSET, Add_Long_To_Pointer(iconsetptr, sizeof(IControl_Type)), size);
icons = (int)(val/(long)bytespericon);
idata = (IControl_Type *)iconsetptr;
}
if (mapsize) {
icons = mapsize;
}
idata->Count = (short)icons;
/*
** Limit buffer to only the size needed. This is done AFTER loading of the
** raw icon data because it might have been compressed and thus need any
** extra space to perform an overlapped decompression.
*/
if (buffsize > size + transsize + mapsize + sizeof(IControl_Type)) {
buffsize = size + transsize + mapsize + sizeof(IControl_Type);
}
transptr = Add_Long_To_Pointer(iconsetptr, idata->TransFlag);
Read_Iff_Chunk(fh, FORM_TRNS, transptr, transsize);
idata = (IControl_Type *)iconsetptr;
mapptr = (void*)idata->Map;
Read_Iff_Chunk(fh, FORM_MAP, mapptr, mapsize);
/*
** Let the graphic overlay know of the icon data. This could involve
** translation and other data manipulations.
*/
//Init_Stamps(iconsetptr);
returnptr = iconsetptr;
}
}
Close_Iff_File(fh);
}
return (returnptr); // Return with icon pointer.
}
/***************************************************************************
* FREE_ICON_SET -- Frees allocations made by Load_Icon_Set(). *
* *
* This routine is used to free up any allocations by Load_Icon_Set(). *
* Use this routine when a new icon set is to be loaded. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 06/21/1991 JLB : Created. *
*=========================================================================*/
void Free_Icon_Set(void const *iconset)
{
IControl_Type *icontrol;
icontrol = (IControl_Type *)iconset;
if (icontrol) {
if (icontrol->Allocated) {
Free((void *)iconset);
}
}
}
long Get_Icon_Set_Size(void const *iconset)
{
IControl_Type *icontrol;
long size=0;
icontrol = (IControl_Type *)iconset;
if (icontrol) {
size = icontrol->Size;
}
return(size);
}
int Get_Icon_Set_Width(void const *iconset)
{
IControl_Type *icontrol;
int width=0;
icontrol = (IControl_Type *)iconset;
if (icontrol) {
width = icontrol->Width;
}
return(width);
}
int Get_Icon_Set_Height(void const *iconset)
{
IControl_Type *icontrol;
int height=0;
icontrol = (IControl_Type *)iconset;
if (icontrol) {
height = icontrol->Height;
}
return(height);
}
void * Get_Icon_Set_Icondata(void const *iconset)
{
IControl_Type *icontrol;
icontrol = (IControl_Type *)iconset;
if (icontrol)
return(Add_Long_To_Pointer(iconset, (LONG)icontrol->Icons));
return(NULL);
}
void * Get_Icon_Set_Trans(void const *iconset)
{
IControl_Type *icontrol;
void *ptr=NULL;
icontrol = (IControl_Type *)iconset;
if (icontrol) {
ptr = Add_Long_To_Pointer((void *)iconset, icontrol->TransFlag);
}
return(ptr);
}
int Get_Icon_Set_Count(void const *iconset)
{
IControl_Type *icontrol;
int count;
icontrol = (IControl_Type *)iconset;
if (icontrol) {
count = icontrol->Count;
}
return(count);
}
void * Get_Icon_Set_Map(void const *iconset)
{
IControl_Type *icontrol;
icontrol = (IControl_Type *)iconset;
if (icontrol)
return(Add_Long_To_Pointer(iconset, (LONG)icontrol->Map));
return(NULL);
}

328
WIN32LIB/SRCDEBUG/IFF.CPP Normal file
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/>.
*/
/***************************************************************************
** 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 : IFF.C *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : May 16, 1991 *
* *
* Last Update : April 19, 1994 [SKB] *
* *
* *
* IFF reader code designed for loading pictures (ILBM or PBM). *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Close_Iff_File -- Closes an IFF file handle. *
* Get_Iff_Chunk_Size -- Get the size of the given IFF chunk. *
* Open_Iff_File -- Opens an IFF file for reading. *
* Read_Iff_Chunk -- Reads a chunk from an IFF file. *
* Write_Iff_Chunk -- Writes an IFF chuck out. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "iff.h"
#include "file.h"
#define ID_FORM MAKE_ID('F','O','R','M')
#ifdef MIN
#undef MIN
#endif
/***************************************************************************
* OPEN_IFF_FILE -- Opens an IFF file for reading. *
* *
* This function will open an IFF file for reading. It will perform *
* a the simple validity test of checking the first four bytes to make *
* sure they are "FORM". The value returned is the filehandle of the *
* opened file. *
* *
* INPUT: filename - ASCII name of the IFF file to be opened. *
* *
* OUTPUT: Returns the filehandle. If there is an error or the file *
* is not an IFF FORM then -1 will be returned. *
* *
* WARNINGS: You are responsible for error handling if this function *
* returns -1 (not an IFF file). *
* *
* HISTORY: *
* 05/16/1991 JLB : Created. *
* 04/19/1994 SKB : Update to 32 bit library. *
*=========================================================================*/
int __cdecl Open_Iff_File(char const *filename)
{
int fh; // File handle.
long type; // IFF file type.
/* We want to be able to open the file for READ | WRITE, but we do not
want the Open_File to create it. So check to see if it exists before
the Open_File */
// fh = Open_File(filename, READ); // Open the source file for READ
// Close_File(fh);
//fh = Open_File(filename, READ | WRITE); // Open the source file again
fh = Open_File(filename, READ); // Open the source file again
// Validate that it is a FORM type.
Read_File(fh, &type, 4L);
if (type == ID_FORM) {
// The file is valid (so far). Position the read so that the actual
// IFF file type code can be read.
Seek_File(fh, 4L, SEEK_CUR); // Skip the filesize bytes.
} else {
// This is NOT an IFF file. Close the source file and return with
// the error code.
Close_File(fh);
fh = WW_ERROR;
}
return fh;
}
/***************************************************************************
* CLOSE_IFF_FILE -- Closes an IFF file handle. *
* *
* The routine will close the file that was opened with the *
* Open_Iff_File() function. *
* *
* INPUT: fh - File handle that was returned from Open_Iff_File(). *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/16/1991 JLB : Created. *
* 04/19/1994 SKB : Update to 32 bit library. *
*=========================================================================*/
void __cdecl Close_Iff_File(int fh)
{
if (fh != WW_ERROR) Close_File(fh);
}
/***************************************************************************
* GET_IFF_CHUNK_SIZE -- Get the size of the given IFF chunk. *
* *
* INPUT: int file handle to open IFF file, long id to get size of *
* *
* OUTPUT: long size of the chunk or 0L if it was not found *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 06/03/1991 CY : Created. *
* 04/19/1994 SKB : Update to 32 bit library. *
*=========================================================================*/
unsigned long __cdecl Get_Iff_Chunk_Size(int fh, long id)
{
long form; // Chunk iff form name.
long chunksize; // Size of the chunk.
char first_iteration; // Check once the current chunk name
first_iteration = TRUE;
for (;;) {
if (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;
if (Read_File(fh, (char *) &chunksize, 4L) != 4L && !first_iteration) break;
#if(IBM)
chunksize = Reverse_Long(chunksize);
#endif
if (id == form) {
Seek_File(fh, -8L, SEEK_CUR); // Seek back to the start of
return(chunksize); // the chunk & return size
} else {
if (first_iteration) {
Seek_File(fh, 12L, SEEK_SET); // Start at beginning of file.
first_iteration = FALSE; // Don't do this again
} else {
/* Otherwise, go to the next chunk in the file */
chunksize = (chunksize + 1) & 0xFFFFFFFEL;
Seek_File(fh, chunksize, SEEK_CUR);
}
}
}
return(0L);
}
/***************************************************************************
* READ_IFF_CHUNK -- Reads a chunk from an IFF file. *
* *
* Once an IFF file is opened, various chunks must be read from it. *
* This routine will search through the IFF file and load in the *
* specified chunk. It will scan through the entire file when *
* searching for the chunk. It will load the FIRST chunk of the given *
* type. *
* *
* INPUT: fh - File handle of IFF file. *
* *
* id - Chunk ID code. *
* *
* buffer - Pointer to buffer to load the chunk. *
* *
* maxsize - Maximum data bytes to read. *
* *
* OUTPUT: Returns with the number of bytes read from the chunk. *
* If 0 is returned, this indicates that the chunk wasn't *
* found. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/16/1991 JLB : Created. *
* 04/19/1994 SKB : Update to 32 bit library. *
*=========================================================================*/
unsigned long __cdecl Read_Iff_Chunk(int fh, long id, void *buffer, unsigned long maxsize)
{
long form; // Chunk iff form name.
unsigned long chunksize; // Size of the chunk.
char first_iteration; // Check once the current chunk name
first_iteration = TRUE;
for (;;) {
if (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;
if (Read_File(fh, (char *) &chunksize, 4L) != 4L && !first_iteration) break;
#if(IBM)
chunksize = Reverse_Long(chunksize);
#endif
if (id == form) {
maxsize = MIN(maxsize, chunksize);
Read_File(fh, buffer, maxsize); // Read the buffer.
chunksize = (chunksize + 1) & 0xFFFFFFFEL;
if (maxsize < chunksize) {
Seek_File(fh, chunksize - maxsize, SEEK_CUR);
}
return(maxsize);
} else {
if (first_iteration) {
Seek_File(fh, 12L, SEEK_SET); // Start at beginning of file.
first_iteration = FALSE; // Don't do this again
} else {
/* Otherwise, go to the next chunk in the file */
chunksize = (chunksize + 1) & 0xFFFFFFFEL;
Seek_File(fh, chunksize, SEEK_CUR);
}
}
}
return(0L);
}
/***************************************************************************
* WRITE_IFF_CHUNK -- Writes an IFF chuck out. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/19/1994 SKB : Created. *
*=========================================================================*/
void __cdecl Write_Iff_Chunk(int file, long id, void *buffer, long length)
{
long pos; // Current position in the IFF file.
long oldpos; // Record of start of chunk offset.
long endpos; // end of file offset before we write our data
long value;
BOOL odd; // Is length odd?
char pad = 0; // Optional padding byte for even sized chunks.
/*
** Get the current end of file (before we write more data to the file)
*/
pos = Seek_File (file, 0L, SEEK_CUR);
endpos = Seek_File (file, 0L, SEEK_END);
Seek_File (file, pos, SEEK_SET);
if (length) {
value = id;
odd = (short)length & 0x01;
Write_File(file, &value, 4L);
oldpos = Seek_File(file, 0L, SEEK_CUR);
Write_File(file, &value, 4L);
Write_File(file, buffer, length);
pos = Seek_File(file, 0L, SEEK_CUR);
if (odd) {
Write_File(file, &pad, 1L);
}
/*
** Update the chunk size long.
*/
Seek_File(file, oldpos, SEEK_SET);
value = IFFize_LONG((pos - oldpos)-4);
Write_File(file, &value, 4L);
/*
** Update the file size LONG. if we are not just overwriting existing data
*/
// (MCC)
if ( endpos < pos ) {
Seek_File(file, 4L, SEEK_SET);
value = IFFize_LONG((pos+odd) - 8);
Write_File(file, &value, 4L);
}
/*
** Return to end of file.
*/
Seek_File(file, 0L, SEEK_END);
}
}

View File

@@ -0,0 +1,72 @@
/*
** 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 : LIBRARY *
* *
* File Name : INITDLAY.C *
* *
* Programmer : Barry Green *
* *
* Last Update : August 3, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Init_Delay -- I am not sure *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "wwstd.h"
#include "timer.h"
#include "video.h"
BOOL VertBlank;
/***************************************************************************
* INIT_DELAY -- I am not sure *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/03/1994 SKB : Created. *
*=========================================================================*/
VOID Init_Delay(VOID)
{
WORD nz, nnz;
nz = nnz = 0;
CountDown.Set(15, TRUE); // set to 1/4 second and start it
do {
if (Get_Vert_Blank())
nnz++;
else
nz++;
} while (CountDown.Time());
VertBlank = (nnz > nz);
}

View File

@@ -0,0 +1,75 @@
/*
** 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 : Initialize mono *
* *
* File Name : INITMONO.CPP *
* *
* Programmer : Jeff Wilson *
* *
* Start Date : March 28, 1994 *
* *
* Last Update : September 8, 1994 [IML] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WWSTD_H
#include "wwstd.h"
#endif
#ifndef MONO_H
#include "mono.h"
#endif
#ifndef DESCMGMT_H
#include "descmgmt.h"
#endif
/***************************************************************************
* INITIALIZE_MONO_SCREEN -- Initializes the Mono display data *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 01/21/1994 jaw: Created. *
*========================================================================*/
int Initialize_Mono_Screen(void)
{
// get a valid selector to mono screen.
// Map_Segment_To_Address(0x0b0000UL, 0x8000UL);
MonoScreen = 0xb0000 ;
return (int)0;
}



View File

@@ -0,0 +1,69 @@
/*
** 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 : LIBRARY *
* *
* File Name : IRANDOM.C *
* *
* Programmer : Barry W. Green *
* *
* Last Update : 10 Feb, 1995 [BWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <stdlib.h>
#include <time.h>
#include "misc.h"
/* IRANDOM ----------------------------------------------------------
IRandom returns a random value between min and max inclusive.
INPUTS: int min and int max
RETURNS: int random number
*/
int IRandom(int minval, int maxval)
{
int num,mask;
// Keep minval and maxval straight.
if (minval > maxval) {
minval ^= maxval;
maxval ^= minval;
minval ^= maxval;
}
mask = Get_Random_Mask(maxval - minval);
while( (num = (rand() & mask) + minval) > maxval ) ;
return(num);
}


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,533 @@
/*
** 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/>.
*/
/***********************************************************************************************
* *
* Project Name : Westwood Keyboard Library *
* *
* File Name : KEYBOARD.CPP *
* *
* Programmer : Philip W. Gorrow *
* *
* Start Date : 10/16/95 *
* *
* Last Update : October 26, 1995 [] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] *
* WWKeyboardClass::Get -- Logic to get a metakey from the buffer *
* WWKeyboardClass::Check -- Checks to see if a key is in the buffer *
* WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer *
* WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer *
* WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels *
* WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels *
* WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars *
* Check_Key -- compatability routine for old 32 bit library *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "keyboard.h"
#include "timer.h"
#include "mono.h"
void Message_Loop(void);
WWKeyboardClass *_Kbd;
/***********************************************************************************************
* WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
WWKeyboardClass::WWKeyboardClass(void)
{
_Kbd = this;
//
// Initialize the keyboard remap table for our system (note it would be bad if someone
// switched keyboard modes after this happened.
//
memset(VKRemap, 0, 256);
memset(AsciiRemap, 0, 2048);
for (short lp = 31; lp < 255; lp ++) {
if (isprint(lp)) {
int vk_key = VkKeyScan((unsigned char)lp);
if (vk_key > 0 && vk_key < 2048) {
AsciiRemap[vk_key] = (unsigned char)lp;
VKRemap[lp] = (unsigned char)(vk_key & 0xFF);
}
}
}
//
// Build a remap table of the different keys which are affected by the caps lock and
// the num lock.
//
memset(ToggleKeys, 0, 256);
for (lp = 0; lp < 255; lp++ ) {
if (isalpha(lp) && isupper(lp)) {
ToggleKeys[lp] = 1;
}
if (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) {
ToggleKeys[lp] = 2;
}
}
//
// Our buffer should start devoid of keys.
//
memset(Buffer, 0, 256);
Head = 0;
Tail = 0;
//
// There should be no starting queued mouse events for us to have to worry
// about.
//
MouseQX = 0;
MouseQY = 0;
MState = 0;
Conditional = 0;
CurrentCursor = NULL;
}
/***********************************************************************************************
* WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer *
* *
* INPUT: none *
* *
* OUTPUT: int - the key value that was pulled from buffer (includes bits) * *
* *
* WARNINGS: If the key was a mouse event MouseQX and MouseQY will be updated *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
int WWKeyboardClass::Buff_Get(void)
{
while (!Check()) {} // wait for key in buffer
int temp = Buffer[Head]; // get key out of the buffer
int newhead = Head; // save off head for manipulation
if (Is_Mouse_Key(temp)) { // if key is a mouse then
MouseQX = Buffer[(Head + 1) & 255]; // get the x and y pos
MouseQY = Buffer[(Head + 2) & 255]; // from the buffer
newhead += 3; // adjust head forward
} else {
newhead += 1; // adjust head forward
}
newhead &= 255;
Head = newhead;
return(temp);
}
BOOL WWKeyboardClass::Is_Mouse_Key(int key)
{
key &= 0xFF;
return (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);
}
/***********************************************************************************************
* WWKeyboardClass::Check -- Checks to see if a key is in the buffer *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
BOOL WWKeyboardClass::Check(void)
{
Message_Loop();
unsigned short temp; // store temp holding spot for key
if (Head == Tail) return(FALSE); // if no keys in buff then get out
temp = Buffer[Head]; // get key out of the buffer
return(temp); // send it back to main program
}
/***********************************************************************************************
* WWKeyboardClass::Get -- Logic to get a metakey from the buffer *
* *
* INPUT: none *
* *
* OUTPUT: int - the meta key taken from the buffer. *
* *
* WARNINGS: This routine will not return until a keypress is received *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
int WWKeyboardClass::Get(void)
{
int temp,bits; // store temp holding spot for key
while (!Check()) {} // wait for key in buffer
temp = Buff_Get(); // get key from the buffer
bits = temp & 0xFF00; // save of keyboard bits
if (!(bits & WWKEY_VK_BIT)) { // if its not a virtual key
temp = AsciiRemap[temp&0x1FF] | bits; // convert to ascii equivalent
}
return(temp); // return the key that we pulled out
}
/***********************************************************************************************
* WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] *
* *
* INPUT: int - the key to insert into the buffer *
* *
* OUTPUT: bool - true if key is sucessfuly inserted. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
BOOL WWKeyboardClass::Put(int key)
{
int temp = (Tail + 1) & 255;
if (temp != Head)
{
Buffer[Tail] = (short)key;
//
// Critical Line
//
Tail = temp;
return(TRUE);
}
return(FALSE);
}
/***********************************************************************************************
* WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
WWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl)
{
int bits = 0;
//
// Get the status of all of the different keyboard modifiers. Note, only pay attention
// to numlock and caps lock if we are dealing with a key that is affected by them. Note
// that we do not want to set the shift, ctrl and alt bits for Mouse keypresses as this
// would be incompatible with the dos version.
//
if (vk_key != VK_LBUTTON && vk_key != VK_MBUTTON && vk_key != VK_RBUTTON) {
int shift = (GetKeyState(VK_SHIFT) & 0xFF00) != 0;
int ctrl = (GetKeyState(VK_CONTROL) & 0xFF00) != 0;
int alt = (GetKeyState(VK_MENU) & 0xFF00) != 0;
int caps = ((GetKeyState(VK_CAPITAL) & 0x00FF) != 0) && (ToggleKeys[vk_key] == 1);
int nums = ((GetKeyState(VK_NUMLOCK) & 0x00FF) != 0) && (ToggleKeys[vk_key] == 2);
//
// Set the proper bits for whatever the key we got is.
//
if (shift || caps || nums) {
bits |= WWKEY_SHIFT_BIT;
}
if (ctrl) {
bits |= WWKEY_CTRL_BIT;
}
if (alt) {
bits |= WWKEY_ALT_BIT;
}
}
if (!AsciiRemap[vk_key|bits]) {
bits |= WWKEY_VK_BIT;
}
if (release) {
bits |= WWKEY_RLS_BIT;
}
if (dbl) {
bits |= WWKEY_DBL_BIT;
}
//
// Finally use the put command to enter the key into the keyboard
// system.
//
return(Put(vk_key|bits));
}
void WWKeyboardClass::Clear(void)
{
Head = Tail;
}
int WWKeyboardClass::To_ASCII(int key)
{
if ( key && WWKEY_RLS_BIT)
return(KN_NONE);
return(key);
}
WWKeyboardClass::Down(int key)
{
return(GetAsyncKeyState(key&0xFF));
}
VOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl)
{
shift = (key & WWKEY_SHIFT_BIT) != 0;
ctrl = (key & WWKEY_CTRL_BIT) != 0;
alt = (key & WWKEY_ALT_BIT) != 0;
rls = (key & WWKEY_RLS_BIT) != 0;
dbl = (key & WWKEY_DBL_BIT) != 0;
key = (key & 0xFF);
}
extern "C" {
void __cdecl Stop_Execution (void);
}
#pragma off(unreferenced)
void WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam)
{
switch (message) {
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
if ( wParam==VK_SCROLL ){
Stop_Execution();
} else {
Put_Key_Message(wParam);
}
break;
case WM_SYSKEYUP:
case WM_KEYUP:
Put_Key_Message(wParam, TRUE);
break;
case WM_LBUTTONDOWN:
Put_Key_Message(VK_LBUTTON);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_LBUTTONUP:
Put_Key_Message(VK_LBUTTON, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_LBUTTONDBLCLK:
Put_Key_Message(VK_LBUTTON, TRUE, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MBUTTONDOWN:
Put_Key_Message(VK_MBUTTON);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MBUTTONUP:
Put_Key_Message(VK_MBUTTON, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MBUTTONDBLCLK:
Put_Key_Message(VK_MBUTTON, TRUE, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_RBUTTONDOWN:
Put_Key_Message(VK_RBUTTON);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_RBUTTONUP:
Put_Key_Message(VK_RBUTTON, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_RBUTTONDBLCLK:
Put_Key_Message(VK_RBUTTON, TRUE, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MOUSEMOVE:
if (CurrentCursor)
SetCursor(CurrentCursor);
break;
}
}
#pragma on(unreferenced)
void Message_Loop(void)
{
MSG msg;
while (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {
if( !GetMessage( &msg, NULL, 0, 0 ) ){
return;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
/***************************************************************************
* CHECK_KEY -- compatability routine for old 32 bit library *
* *
* This routine checks to see if there is a key in the keyboard buffer *
* and returns it to the sender if there is. It does not remove the key *
* from the buffer. *
* *
* INPUT: none *
* *
* OUTPUT: The key that was pressed. *
* *
* WARNINGS: You must declare a WWKeyboardClass object before calling *
* this routine. *
* *
* HISTORY: *
* 10/26/1995 : Created. *
*=========================================================================*/
int Check_Key(void)
{
if (!_Kbd) return(KA_NONE);
return(_Kbd->Check() & ~WWKEY_SHIFT_BIT);
}
void Clear_KeyBuffer(void)
{
if (!_Kbd) return;
_Kbd->Clear();
}
int Check_Key_Num(void)
{
if (!_Kbd) return(KN_NONE);
int key = _Kbd->Check();
int flags = key & 0xFF00;
key = key & 0x00FF;
if (isupper(key)) {
key = tolower(key);
if ( !flags & WWKEY_VK_BIT ) {
flags |= WWKEY_SHIFT_BIT;
}
}
return(key | flags);
}
int Get_Key_Num(void)
{
if (!_Kbd) return(KN_NONE);
int key = _Kbd->Get();
int flags = key & 0xFF00;
key = key & 0x00FF;
if (isupper(key)) {
key = tolower(key);
if ( !flags & WWKEY_VK_BIT ) {
flags |= WWKEY_SHIFT_BIT;
}
}
return(key | flags);
}
int KN_To_KA(int key)
{
if ( key & WWKEY_RLS_BIT) {
return(KA_NONE);
}
if (!(key & WWKEY_VK_BIT)) {
int flags = key & 0xFF00;
key = key & 0x00FF;
if (flags & WWKEY_SHIFT_BIT) {
key = toupper(key);
flags &= ~WWKEY_SHIFT_BIT;
}
}else{
/*
** If its a numeric keypad key then fix it up
*/
if ((key & 0xff) >=VK_NUMPAD0 && (key & 0xff) <=VK_NUMPAD9){
key = (key & 0xff) - VK_NUMPAD0 + KA_0;
}
}
return(key);
}
int KN_To_VK(int key)
{
if (!_Kbd) return(KN_NONE);
if ( key & WWKEY_RLS_BIT) {
return(VK_NONE);
}
int flags = key & 0xFF00;
if (!(flags & WWKEY_VK_BIT)) {
key = _Kbd->VKRemap[key & 0x00FF] | flags;
}
key &= ~WWKEY_VK_BIT;
return(key);
}
int Key_Down(int key)
{
if (!_Kbd) return(FALSE);
return(_Kbd->Down(key));
}
int Get_Key(void)
{
int retval;
if (!_Kbd) return(KN_NONE);
retval = _Kbd->Get() & ~WWKEY_SHIFT_BIT;
if (retval & WWKEY_RLS_BIT) {
retval = KN_NONE;
}
return(retval);
}

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,286 @@
;
; 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/wwlib32/misc/rcs/lcwcomp.asm 1.1 1994/04/11 15:31:10 jeff_wilson 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 routine *
;* *
;* File Name : COMPRESS.ASM *
;* *
;* Programmer : Louis Castle *
;* *
;* Last Update : 20 August, 1990 [CY] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* *
; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length); *
;* *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL LCW_Compress :NEAR
CODESEG
; ----------------------------------------------------------------
;
; Here are prototypes for the routines defined within this module:
;
; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length);
;
; ----------------------------------------------------------------
;***********************************************************
;
; ULONG LCW_Compress(BYTE *source, BYTE *dest, ULONG length)
;
; returns the size of the compressed data in bytes
;
;*
PROC LCW_Compress C near
USES ebx,ecx,edx,edi,esi
ARG source:DWORD
ARG dest:DWORD
ARG datasize:DWORD
LOCAL inlen:DWORD
LOCAL a1stdest:DWORD
LOCAL a1stsrc:DWORD
LOCAL lenoff:DWORD
LOCAL ndest:DWORD
LOCAL count:DWORD
LOCAL matchoff:DWORD
LOCAL end_of_data:DWORD
cld
mov edi,[dest]
mov esi,[source]
mov edx,[datasize] ; get length of data to compress
; mov ax,ds
; mov es,ax
;
; compress data to the following codes in the format b = byte, w = word
; n = byte code pulled from compressed data
; Bit field of n command description
; n=0xxxyyyy,yyyyyyyy short run back y bytes and run x+3
; n=10xxxxxx,n1,n2,...,nx+1 med length copy the next x+1 bytes
; n=11xxxxxx,w1 med run run x+3 bytes from offset w1
; n=11111111,w1,w2 long run run w1 bytes from offset w2
; n=10000000 end end of data reached
;
cld ; make sure all string commands are forward
mov ebx,esi
add ebx,edx
mov [end_of_data],ebx
mov [inlen],1 ; set the in-length flag
mov [a1stdest],edi ; save original dest offset for size calc
mov [a1stsrc],esi ; save offset of first byte of data
mov [lenoff],edi ; save the offset of the legth of this len
sub eax,eax
mov al,081h ; the first byte is always a len
stosb ; write out a len of 1
lodsb ; get the byte
stosb ; save it
??loop:
mov [ndest],edi ; save offset of compressed data
mov edi,[a1stsrc] ; get the offset to the first byte of data
mov [count],1 ; set the count of run to 0
??searchloop:
sub eax,eax
mov al,[esi] ; get the current byte of data
cmp al,[esi+64]
jne short ??notrunlength
mov ebx,edi
mov edi,esi
mov ecx,[end_of_data]
sub ecx,edi
repe scasb
dec edi
mov ecx,edi
sub ecx,esi
cmp ecx,65
jb short ??notlongenough
mov [DWORD PTR inlen],0 ; clear the in-length flag
mov esi,edi
mov edi,[ndest] ; get the offset of our compressed data
mov ah,al
mov al,0FEh
stosb
xchg ecx,eax
stosw
mov al,ch
stosb
mov [ndest],edi ; save offset of compressed data
mov edi,ebx
jmp ??searchloop
??notlongenough:
mov edi,ebx
??notrunlength:
??oploop:
mov ecx,esi ; get the address of the last byte +1
sub ecx,edi ; get the total number of bytes left to comp
jz short ??searchdone
repne scasb ; look for a match
jne short ??searchdone ; if we don't find one we're done
mov ebx,[count]
mov ah,[esi+ebx-1]
cmp ah,[edi+ebx-2]
jne ??oploop
mov edx,esi ; save this spot for the next search
mov ebx,edi ; save this spot for the length calc
dec edi ; back up one for compare
mov ecx,[end_of_data] ; get the end of data
sub ecx,esi ; sub current source for max len
repe cmpsb ; see how many bytes match
; start of change MH 9-24-91
jne short ??notend ; if found mismatch then di - bx = match count
inc edi ; else cx = 0 and di + 1 - bx = match count
??notend:
; end of change MH 9-24-91
mov esi,edx ; restore si
mov eax,edi ; get the dest
sub eax,ebx ; sub the start for total bytes that match
mov edi,ebx ; restore dest
cmp eax,[count] ; see if its better than before
jb ??searchloop ; if not keep looking
mov [count],eax ; if so keep the count
dec ebx ; back it up for the actual match offset
mov [matchoff],ebx ; save the offset for later
jmp ??searchloop ; loop until we searched it all
??searchdone:
mov ecx,[count] ; get the count of the longest run
mov edi,[ndest] ; get the offset of our compressed data
cmp ecx,2 ; see if its not enough run to matter
jbe short ??lenin ; if its 0,1, or 2 its too small
cmp ecx,10 ; if not, see if it would fit in a short
ja short ??medrun ; if not, see if its a medium run
mov eax,esi ; if its short get the current address
sub eax,[matchoff] ; sub the offset of the match
cmp eax,0FFFh ; if its less than 12 bits its a short
ja short ??medrun ; if its not, its a medium
??shortrun:
sub ebx,ebx
mov bl,cl ; get the length (3-10)
sub bl,3 ; sub 3 for a 3 bit number 0-7
shl bl,4 ; shift it left 4
add ah,bl ; add in the length for the high nibble
xchg ah,al ; reverse the bytes for a word store
jmp short ??srunnxt ; do the run fixup code
??medrun:
cmp ecx,64 ; see if its a short run
ja short ??longrun ; if not, oh well at least its long
sub cl,3 ; back down 3 to keep it in 6 bits
or cl,0C0h ; the highest bits are always on
mov al,cl ; put it in al for the stosb
stosb ; store it
jmp short ??medrunnxt ; do the run fixup code
??lenin:
cmp [DWORD PTR inlen],0 ; is it doing a length?
jnz short ??len ; if so, skip code
??lenin1:
mov [lenoff],edi ; save the length code offset
mov al,80h ; set the length to 0
stosb ; save it
??len:
mov ebx,[lenoff] ; get the offset of the length code
cmp [BYTE PTR ebx],0BFh ; see if its maxed out
je ??lenin1 ; if so put out a new len code
??stolen:
inc [BYTE PTR ebx] ; inc the count code
lodsb ; get the byte
stosb ; store it
mov [DWORD PTR inlen],1 ; we are now in a length so save it
jmp short ??nxt ; do the next code
??longrun:
mov al,0ffh ; its a long so set a code of FF
stosb ; store it
mov eax,[count] ; send out the count
stosw ; store it
??medrunnxt:
mov eax,[matchoff] ; get the offset
sub eax,[a1stsrc] ; make it relative tot he start of data
??srunnxt:
stosw ; store it
; this code common to all runs
add esi,[count] ; add in the length of the run to the source
mov [DWORD PTR inlen],0 ; set the in leght flag to false
;=======================================================================
??nxt:
cmp esi,[end_of_data] ; see if we did the whole pic
jae short ??out ; if so, cool! were done
jmp ??loop
??out:
mov ax,080h ; remember to send an end of data code
stosb ; store it
mov eax,edi ; get the last compressed address
sub eax,[a1stdest] ; sub the first for the compressed size
ret
ENDP LCW_Compress
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/>.
;
; $Header: g:/library/wwlib32/misc/rcs/lcwuncmp.asm 1.1 1994/04/11 15:31:21 jeff_wilson 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 routine *
;* *
;* File Name : UNCOMP.ASM *
;* *
;* Programmer : Christopher Yates *
;* *
;* Last Update : 20 August, 1990 [CY] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* *
; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length); *
;* *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL C LCW_Uncompress :NEAR
CODESEG
; ----------------------------------------------------------------
;
; Here are prototypes for the routines defined within this module:
;
; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);
;
; ----------------------------------------------------------------
PROC LCW_Uncompress C near
USES ebx,ecx,edx,edi,esi
ARG source:DWORD
ARG dest:DWORD
ARG length:DWORD
;LOCALS
LOCAL a1stdest:DWORD
LOCAL maxlen:DWORD
LOCAL lastbyte:DWORD
LOCAL lastcom:DWORD
LOCAL lastcom1:DWORD
mov edi,[dest]
mov esi,[source]
mov edx,[length]
;
;
; uncompress data to the following codes in the format b = byte, w = word
; n = byte code pulled from compressed data
; Bit field of n command description
; n=0xxxyyyy,yyyyyyyy short run back y bytes and run x+3
; n=10xxxxxx,n1,n2,...,nx+1 med length copy the next x+1 bytes
; n=11xxxxxx,w1 med run run x+3 bytes from offset w1
; n=11111111,w1,w2 long copy copy w1 bytes from offset w2
; n=11111110,w1,b1 long run run byte b1 for w1 bytes
; n=10000000 end end of data reached
;
mov [a1stdest],edi
add edx,edi
mov [lastbyte],edx
cld ; make sure all lod and sto are forward
mov ebx,esi ; save the source offset
??loop:
mov eax,[lastbyte]
sub eax,edi ; get the remaining byte to uncomp
jz short ??out ; were done
mov [maxlen],eax ; save for string commands
mov esi,ebx ; mov in the source index
xor eax,eax
mov al,[esi]
inc esi
test al,al ; see if its a short run
js short ??notshort
mov ecx,eax ;put count nibble in cl
mov ah,al ; put rel offset high nibble in ah
and ah,0Fh ; only 4 bits count
shr cl,4 ; get run -3
add ecx,3 ; get actual run length
cmp ecx,[maxlen] ; is it too big to fit?
jbe short ??rsok ; if not, its ok
mov ecx,[maxlen] ; if so, max it out so it dosen't overrun
??rsok:
mov al,[esi] ; get rel offset low byte
lea ebx,[esi+1] ; save the source offset
mov esi,edi ; get the current dest
sub esi,eax ; get relative offset
rep movsb
jmp ??loop
??notshort:
test al,40h ; is it a length?
jne short ??notlength ; if not it could be med or long run
cmp al,80h ; is it the end?
je short ??out ; if so its over
mov cl,al ; put the byte in count register
and ecx,3Fh ; and off the extra bits
cmp ecx,[maxlen] ; is it too big to fit?
jbe short ??lenok ; if not, its ok
mov ecx,[maxlen] ; if so, max it out so it dosen't overrun
??lenok:
rep movsb
mov ebx,esi ; save the source offset
jmp ??loop
??out:
mov eax,edi
sub eax,[a1stdest]
jmp ??exit
??notlength:
mov cl,al ; get the entire code
and ecx,3Fh ; and off all but the size -3
add ecx,3 ; add 3 for byte count
cmp al,0FEh
jne short ??notrunlength
xor ecx,ecx
mov cx,[esi]
xor eax,eax
mov al,[esi+2]
lea ebx,[esi+3] ;save the source offset
cmp ecx,[maxlen] ; is it too big to fit?
jbe short ??runlenok ; if not, its ok
mov ecx,[maxlen] ; if so, max it out so it dosen't overrun
??runlenok:
test ecx,0ffe0h
jnz ??dont_use_stosb
rep stosb
jmp ??loop
??dont_use_stosb:
mov ah,al
mov edx,eax
shl eax,16
or eax,edx
test edi,3
jz ??aligned
mov [edi],eax
mov edx,edi
and edi,0fffffffch
lea edi,[edi+4]
and edx,3
dec dl
xor dl,3
sub ecx,edx
??aligned:
mov edx,ecx
shr ecx,2
rep stosd
and edx,3
jz ??loop
mov ecx,edx
rep stosb
jmp ??loop
??notrunlength:
cmp al,0FFh ; is it a long run?
jne short ??notlong ; if not use the code as the size
xor ecx,ecx
xor eax,eax
mov cx,[esi] ; if so, get the size
lea esi,[esi+2]
??notlong:
mov ax,[esi] ;get the real index
add eax,[a1stdest] ;add in the 1st index
lea ebx,[esi+2] ;save the source offset
cmp ecx,[maxlen] ;compare for overrun
mov esi,eax ;use eax as new source
jbe short ??runok ; if not, its ok
mov ecx,[maxlen] ; if so, max it out so it dosen't overrun
??runok:
test ecx,0ffe0h
jnz ??dont_use_movsb
rep movsb
jmp ??loop
??dont_use_movsb:
lea edx,[edi+0fffffffch]
cmp esi,edx
ja ??use_movsb
test edi,3
jz ??aligned2
mov eax,[esi]
mov [edi],eax
mov edx,edi
and edi,0fffffffch
lea edi,[edi+4]
and edx,3
dec dl
xor dl,3
sub ecx,edx
add esi,edx
??aligned2:
mov edx,ecx
shr ecx,2
and edx,3
rep movsd
mov ecx,edx
??use_movsb:
rep movsb
jmp ??loop
??exit:
mov eax,edi
mov ebx,[dest]
sub eax,ebx
ret
ENDP LCW_Uncompress
;***********************************************************
END

217
WIN32LIB/SRCDEBUG/LIB.CPP Normal file
View File

@@ -0,0 +1,217 @@
/*
** 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/./lib.c 1.16 1994/05/20 15:34:33 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 Routines *
* *
* File Name : LIB.C *
* *
* Programmer : Scott Bowen *
* *
* Start Date : January 14, 1993 *
* *
* Last Update : May 20, 1993 [PWG] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Add_Long_To_Pointer -- Pointer arithmatic when pointer could be XMS. *
* Find_Argv -- Checks to see if string is in arguement *
* Mono_Mem_Dump -- Dumps memory to mono monitor with hex and char. *
* Convert_HSV_To_RGB -- Converts HSV cordinates to RGB values *
* Convert_RGB_To_HSV -- Converts RGB to RSV coordinates. *
* Set_Search_Drives -- Sets up the CDRom and HardDrive paths. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <dos.h>
#include <stdio.h>
#include <string.h>
#include "misc.h"
//PRIVATE unsigned Divide_With_Round(unsigned num, unsigned den);
/***************************************************************************
* Divide_With_Round -- Divides integers and round to nearest integer. *
* *
* INPUT: int numberator. *
* int denominator. *
* *
* OUTPUT: Returns value rounded. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/13/1992 SB : Created. *
*=========================================================================*/
static unsigned Divide_With_Round(unsigned num, unsigned den)
{
// return num/den + (0 ro 1). 1 if the remainder is more than half the denominator.
return( (num / den) + (unsigned)((num % den) >= ((den + 1) >> 1)) );
}
#define HSV_BASE 255 // This is used to get a little better persion on HSV conversion.
#define RGB_BASE 63 // Not 64, this is really the max value.
/***************************************************************************
* Convert_RGB_To_HSV -- Converts RGB to RSV coordinates. *
* *
* INPUT: int r,g, and b values. *
* int *h, *s, and *v pointers. *
* *
* OUTPUT: Assigns values to *h, *s, and *v. *
* *
* WARNINGS: The reason we use a different base for HSV then RGB is *
* because we loose alot of persision by not using floating *
* point. Using the same base value (63) made it so that *
* about 50% of the time one RGB value would be one different *
* then the original if you went from RGB to HSV to RGB. *
* Using 255 drop it down to about 9% of the time we get an *
* off value. To get it perfect, we would have to make the *
* HSV base larger - but then you need to do all calculations *
* in long instead of unsigned int. *
* HISTORY: *
* 02/11/1992 SB : Created. *
*=========================================================================*/
void Convert_RGB_To_HSV(unsigned int r, unsigned int g, unsigned int b, unsigned int *h, unsigned int *s, unsigned int *v)
{
unsigned int m, r1, g1, b1, tmp;
// Convert RGB base to HSV base.
r = Divide_With_Round((r * HSV_BASE), RGB_BASE);
g = Divide_With_Round((g * HSV_BASE), RGB_BASE);
b = Divide_With_Round((b * HSV_BASE), RGB_BASE);
// Set hue to default.
*h = 0;
// Set v = Max(r,g,b) to find dominant primary color.
*v = (r > g) ? r : g;
if (b > *v) *v = b;
// Set m = min(r,g,b) to find amount of white.
m = (r < g) ? r : g;
if (b < m) m = b;
// Determine the normalized saturation.
if (*v != 0) {
*s = Divide_With_Round( (*v - m) * HSV_BASE ,*v);
} else {
*s = 0;
}
if (*s != 0) {
tmp = *v - m;
r1 = Divide_With_Round( (*v - r) * HSV_BASE, tmp);
g1 = Divide_With_Round( (*v - g) * HSV_BASE, tmp);
b1 = Divide_With_Round( (*v - b) * HSV_BASE, tmp);
// Find effect of second most predominant color.
// In which section of the hexagon of colors does the color lie?
if ((*v) == r) {
if (m == g) {
*h = 5 * HSV_BASE + b1;
} else {
*h = 1 * HSV_BASE - g1;
}
} else {
if ((*v) == g) {
if (m == b) {
*h = 1 * HSV_BASE + r1;
} else {
*h = 3 * HSV_BASE - b1;
}
} else {
// *v == b
if (m == r) {
*h = 3 * HSV_BASE + g1;
} else {
*h = 5 * HSV_BASE - r1;
}
}
}
// Divide by six and round.
*h = Divide_With_Round(*h, 6);
}
}
/***************************************************************************
* Convert_HSV_To_RGB -- Converts HSV cordinates to RGB values *
* *
* INPUT: int h,s, and v coordinates *
* int *r, *g, and *b pointers. *
* *
* OUTPUT: Assigns values to *r, *g, and *b. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 02/11/1992 SB : Created. *
*=========================================================================*/
void Convert_HSV_To_RGB(unsigned int h, unsigned int s, unsigned int v, unsigned int *r, unsigned int *g, unsigned int *b)
{
unsigned int i; // Integer part.
unsigned int f; // Fractional or remainder part. f/HSV_BASE gives fraction.
unsigned int tmp; // Tempary variable to help with calculations.
unsigned int values[7]; // Possible rgb values. Don't use zero.
h *= 6;
f = h % HSV_BASE;
// Set up possible red, green and blue values.
values[1] =
values[2] = v;
//
// The following lines of code change
// values[3] = (v * (HSV_BASE - ( (s * f) / HSV_BASE) )) / HSV_BASE;
// values[4] = values[5] = (v * (HSV_BASE - s)) / HSV_BASE;
// values[6] = (v * (HSV_BASE - (s * (HSV_BASE - f)) / HSV_BASE)) / HSV_BASE;
// so that the are rounded divides.
//
tmp = Divide_With_Round(s * f, HSV_BASE);
values[3] = Divide_With_Round(v * (HSV_BASE - tmp), HSV_BASE);
values[4] =
values[5] = Divide_With_Round(v * (HSV_BASE - s), HSV_BASE);
tmp = HSV_BASE - Divide_With_Round(s * (HSV_BASE - f), HSV_BASE);
values[6] = Divide_With_Round(v * tmp, HSV_BASE);
// This should not be rounded.
i = h / HSV_BASE;
i += (i > 4) ? -4 : 2;
*r = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);
i += (i > 4) ? -4 : 2;
*b = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);
i += (i > 4) ? -4 : 2;
*g = Divide_With_Round(values[i] * RGB_BASE, HSV_BASE);
}

378
WIN32LIB/SRCDEBUG/LOAD.CPP Normal file
View File

@@ -0,0 +1,378 @@
/*
** 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/wwlib32/file/rcs/load.cpp 1.4 1994/04/22 12:42:21 scott_bowen 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 : LOAD.C *
* *
* Programmer : Christopher Yates *
* *
* Last Update : September 17, 1993 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Load_Uncompress -- Load and uncompress the given file. *
* Uncompress_Data -- Uncompress standard CPS buffer. *
* Load_Data -- Loads a data file from disk. *
* Load_Alloc_Data -- Loads and allocates buffer for a file. *
* Write_Data -- Writes a block of data as a file to disk. *
* Uncompress_Data -- Uncompresses data from one buffer to another. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "iff.h"
#include "file.h"
#include <misc.h>
#include <wwstd.h>
#include <dos.h>
#include <wwmem.h>
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* LOAD_DATA -- Loads a data file from disk. *
* *
* This routine will load a data file from disk. It does no translation*
* on the data. *
* *
* INPUT: name -- Pointer to ASCII filename of the data file. *
* *
* ptr -- Buffer to load the data file into. *
* *
* size -- Maximum size of the buffer (in bytes). *
* *
* OUTPUT: Returns with the number of bytes read. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 06/24/1991 JLB : Created. *
*=========================================================================*/
unsigned long __cdecl Load_Data(char const *name, void *ptr, unsigned long size)
{
int fd;
fd = Open_File(name, READ);
size = Read_File(fd, ptr, size);
Close_File(fd);
return(size);
}
/***************************************************************************
* WRITE_DATA -- Writes a block of data as a file to disk. *
* *
* This routine will write a block of data as a file to the disk. It *
* is the compliment of Load_Data. *
* *
* INPUT: name -- Name of the file to create. *
* *
* ptr -- Pointer to the block of data to write. *
* *
* size -- Size of the data block to be written. *
* *
* OUTPUT: Returns with the number of bytes actually written. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/05/1992 JLB : Created. *
*=========================================================================*/
unsigned long __cdecl Write_Data(char const *name, void *ptr, unsigned long size)
{
int fd;
fd = Open_File(name, WRITE);
size = Write_File(fd, ptr, size);
Close_File(fd);
return(size);
}
/***************************************************************************
* LOAD_ALLOC_DATA -- Loads and allocates buffer for a file. *
* *
* The routine will allocate a buffer and load the specified file into *
* it. The kind of memory used for the buffer is determined by the *
* memory allocation flags passed in. *
* *
* INPUT: name -- Name of the file to load. *
* *
* flags -- Memory allocation flags to use when allocating. *
* *
* OUTPUT: Returns with a pointer to the buffer that contains the file's *
* data. *
* *
* WARNINGS: A memory error could occur if regular memory flags are *
* specified. If XMS memory is specified, then this routine *
* could likely return NULL. *
* *
* HISTORY: *
* 05/28/1992 JLB : Created. *
*=========================================================================*/
void * __cdecl Load_Alloc_Data(char const *name, MemoryFlagType flags)
{
int fd; // Working file handle.
unsigned long size; // Size of the file to load.
void *buffer; // Buffer to hold the file.
fd = Open_File(name, READ);
size = File_Size(fd);
buffer = Alloc(size, flags);
if (buffer) {
Read_File(fd, buffer, size);
}
Close_File(fd);
return(buffer);
}
/***************************************************************************
* LOAD_UNCOMPRESS -- Load and uncompress the given file. *
* *
* INPUT: char * - file name to uncompress *
* GraphicBufferClass& - to load the source data into *
* GraphicBufferClass& - for the picture *
* void * - ptr for header uncompressed data *
* *
* OUTPUT: unsigned long size of uncompressed data *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/28/1991 CY : Created. *
* 06/26/1991 JLB : Handles load & uncompress to same buffer. *
*=========================================================================*/
unsigned long __cdecl Load_Uncompress(char const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, void *reserved_data)
{
int fd; // Source file handle.
unsigned int isize=0; // Size of the file.
unsigned int skipsize; // Size of the skip data bytes.
void *uncomp_ptr; // Source buffer pointer.
char *newuncomp_ptr; // Adjusted source pointer.
uncomp_ptr = uncomp_buff.Get_Buffer(); // get a pointer to buffer
/*======================================================================*/
/* Read the file into the uncompression buffer. */
/*======================================================================*/
fd = Open_File(file, READ); // Open up the file to read from
Read_File(fd, (char *) &isize, 2L); // Read the file size
Read_File(fd, uncomp_ptr, 8L); // Read the header bytes in.
isize -= 8; // Remaining data in file.
/*======================================================================*/
/* Check for and read in the skip data block. */
/*======================================================================*/
skipsize = *(((short *)uncomp_ptr) + 3);
if (reserved_data && skipsize) {
Read_File(fd, reserved_data, (unsigned long) skipsize);
} else {
Seek_File(fd, skipsize, SEEK_CUR);
}
*( ((short *)uncomp_ptr+3) ) = 0; // K/O any skip value.
isize -= skipsize;
/*======================================================================*/
/* If the source and dest buffer are the same, we adjust the pointer so */
/* that the compressed data is loaded into the end of the buffer. In */
/* this way the uncompress code can write to the same buffer. */
/*======================================================================*/
newuncomp_ptr = (char *)Add_Long_To_Pointer(uncomp_buff.Get_Buffer(), uncomp_buff.Get_Size() - (isize+8L));
/*======================================================================*/
/* Duplicate the header bytes. */
/*======================================================================*/
Mem_Copy(uncomp_ptr,newuncomp_ptr,8);
/*======================================================================*/
/* Read in the main compressed part of the file. */
/*======================================================================*/
Read_File(fd, newuncomp_ptr + 8, (unsigned long)isize);
Close_File(fd);
/*======================================================================*/
/* Uncompress the file into the destination buffer (which may very well */
/* be the source buffer). */
/*======================================================================*/
return(Uncompress_Data(newuncomp_ptr, dest_buff.Get_Buffer()));
}
#if(0)
/***************************************************************************
* LOAD_UNCOMPRESS -- Load and uncompress the given file. *
* *
* INPUT: char *file name to uncompress, BuffType uncomp_buff to load *
* the source data into, BuffType dest_buff for the picture, *
* void *reserved_data pointer for header uncompressed data *
* *
* OUTPUT: unsigned long size of uncompressed data *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/28/1991 CY : Created. *
* 06/26/1991 JLB : Handles load & uncompress to same buffer. *
*=========================================================================*/
unsigned long __cdecl Load_Uncompress(char const *file, BuffType uncomp_buff, BuffType dest_buff, void *reserved_data)
{
int fd; // Source file handle.
unsigned int isize; // Size of the file.
unsigned int skipsize; // Size of the skip data bytes.
void *uncomp_ptr; // Source buffer pointer.
char *newuncomp_ptr; // Adjusted source pointer.
uncomp_ptr = Get_Buff(uncomp_buff); /* Get pointer to uncomp buffer */
/* Read the file into the uncomp_buff */
fd = Open_File(file, READ);
Read_File(fd, (char *) &isize, 2L); /* Read the file size */
#if(AMIGA)
isize = Reverse_Word(isize);
#endif
Read_File(fd, uncomp_ptr, 8L); // Read the header bytes in.
isize -= 8; // Remaining data in file.
/*
** Check for and read in the skip data block.
*/
skipsize = *(((short*)uncomp_ptr) + 3);
#if(AMIGA)
skipsize = Reverse_Word(skipsize);
#endif
if (reserved_data && skipsize) {
Read_File(fd, reserved_data, (unsigned long) skipsize);
} else {
Seek_File(fd, skipsize, SEEK_CUR);
}
*( ((short *)uncomp_ptr+3) ) = 0; // K/O any skip value.
isize -= skipsize;
/*
** If the source and dest buffer are the same, we
** adjust the pointer so that the compressed data is
** loaded into the end of the buffer. In this way the
** uncompress code can write to the same buffer.
*/
#if(IBM)
newuncomp_ptr = (char *)Add_Long_To_Pointer(Get_Buff(uncomp_buff), PageArraySize[uncomp_buff] - (isize+8L));
#else
newuncomp_ptr = Get_Buff(uncomp_buff);
newuncomp_ptr += PageArraySize[uncomp_buff] - ((isize+10) & 0xFFFE);
#endif
/*
** Duplicate the header bytes.
*/
Mem_Copy(uncomp_ptr,newuncomp_ptr,8);
/*
** Read in the main compressed part of the file.
*/
Read_File(fd, newuncomp_ptr + 8, (unsigned long)isize);
Close_File(fd);
return(Uncompress_Data(newuncomp_ptr, Get_Buff(dest_buff)));
}
#endif
/***************************************************************************
* Uncompress_Data -- Uncompresses data from one buffer to another. *
* *
* This routine takes data from a compressed file (sans the first two *
* size bytes) and uncompresses it to a destination buffer. The source *
* data MUST have the CompHeaderType at its start. *
* *
* INPUT: src -- Source compressed data pointer. *
* *
* dst -- Destination (paragraph aligned) pointer. *
* *
* OUTPUT: Returns with the size of the uncompressed data. *
* *
* WARNINGS: If LCW compression is used, the destination buffer must *
* be paragraph aligned. *
* *
* HISTORY: *
* 09/17/1993 JLB : Created. *
*=========================================================================*/
unsigned long __cdecl Uncompress_Data(void const *src, void *dst)
{
unsigned int skip; // Number of leading data to skip.
CompressionType method; // Compression method used.
unsigned long uncomp_size=NULL;
if (!src || !dst) return(NULL);
/*
** Interpret the data block header structure to determine
** compression method, size, and skip data amount.
*/
uncomp_size = ((CompHeaderType*)src)->Size;
#if(AMIGA)
uncomp_size = Reverse_Long(uncomp_size);
#endif
skip = ((CompHeaderType*)src)->Skip;
#if(AMIGA)
skip = Reverse_Word(skip);
#endif
method = (CompressionType) ((CompHeaderType*)src)->Method;
src = Add_Long_To_Pointer((void *)src, (long)sizeof(CompHeaderType) + (long)skip);
switch (method) {
default:
case NOCOMPRESS:
Mem_Copy((void *) src, dst, uncomp_size);
break;
case HORIZONTAL:
#if LIB_EXTERNS_RESOLVED
RLE_Uncompress((void *) src, dst, uncomp_size);
#endif
break;
case LCW:
LCW_Uncompress((void *) src, (void *) dst, (unsigned long) uncomp_size);
break;
}
return(uncomp_size);
}

View File

@@ -0,0 +1,140 @@
/*
** 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 Library *
* *
* File Name : LOADFONT.C *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : September 6, 1991 *
* *
* Last Update : June 27, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Load_Font -- Loads a font from disk. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "font.h"
#include <file.h>
#include <wwmem.h>
#include <wwstd.h>
#if(IBM)
#include <fcntl.h>
#include <io.h>
#include <errno.h>
int FontXSpacing = 0;
int FontYSpacing = 0;
void const *FontPtr = NULL;
char FontWidth = 8;
char FontHeight = 8;
// only font.c and set_font.c use the following
char *FontWidthBlockPtr = NULL;
/***************************************************************************
* LOAD_FONT -- Loads a font from disk. *
* *
* This loads a font from disk. This function must be called as a *
* precursor to calling Set_Font(). You need only call this function *
* once per desired font at the beginning of your code, but AFTER *
* Prog_Init() is called. *
* *
* INPUT: name - Pointer to font name to use (eg. "topaz.font") *
* *
* fontsize - Size in points of the font loaded. *
* *
* OUTPUT: Pointer to font data or NULL if unable to load. *
* *
* WARNINGS: Some system memory is grabbed by this routine. *
* *
* HISTORY: *
* 4/10/91 BS : 2.0 compatibily *
* 6/09/91 JLB : IBM and Amiga compatability. *
* 11/27/1991 JLB : Uses file I/O routines for disk access. *
* 01/29/1992 DRD : Modified to use new font format. *
* 02/01/1992 DRD : Added font file verification. *
* 06/29/1994 SKB : modified for 32 bit library *
*=========================================================================*/
void * __cdecl Load_Font(char const *name)
{
char valid;
int fh; // DOS file handle for font file.
unsigned short size; // Size of the data in the file (-2);
char *ptr = NULL; // Pointer to newly loaded font.
fh=Open_File(name,READ);
if ( fh>=0 ){
if ( Read_File(fh, (char *) &size, 2) != 2) return(NULL);
ptr = (char *) Alloc(size , MEM_NORMAL );
*(short *)ptr = size;
Read_File(fh, ptr + 2, size - 2);
Close_File(fh);
} else {
return ((void*)errno);
}
#ifdef cuts
if (Find_File(name)) {
fh = Open_File(name, READ);
if (Read_File(fh, (char *) &size, 2) != 2) return(NULL);
ptr = (char *) Alloc(size, MEM_NORMAL);
*(short *)ptr = size;
Read_File(fh, ptr + 2, size - 2);
Close_File(fh);
} else {
return (NULL);
}
#endif
//
// verify that the file loaded is a valid font file.
//
valid = FALSE;
if (*(ptr + 2) == 0) { // no compression
if (*(ptr + 3) == 5) { // currently only 5 data blocks are used.
valid = TRUE;
}
}
if ( !valid ) {
return (NULL);
}
return(ptr);
}
#endif

View File

@@ -0,0 +1,85 @@
/*
** 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 : Load_Palette *
* *
* File Name : LOADPAL.CPP *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : April 25, 1994 *
* *
* Last Update : April 27, 1994 [BR] *
* *
*-------------------------------------------------------------------------*
* Note: This module contains dependencies upon the file I/O system, *
* specifically Load_Data(). *
*-------------------------------------------------------------------------*
* Functions: *
* Load_Palette -- Loads a palette file into the given palette buffer. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
********************************* Includes **********************************
*/
#include <wwstd.h>
#include "wwstd.h"
#include "iff.h"
#include "palette.h"
/*
********************************* Constants *********************************
*/
/*
********************************** Globals **********************************
*/
/*
******************************** Prototypes *********************************
*/
/***************************************************************************
* Load_Palette -- Loads a palette file into the given palette buffer. *
* *
* INPUT: *
* BYTE * file_name - name of the file to load. *
* BYTE * palette_pointer - pointer to palette buffer. *
* *
* OUTPUT: *
* none *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/20/1991 BS : Created. *
* 04/27/1994 BR : Converted to 32-bit *
*=========================================================================*/
void __cdecl Load_Palette(char *palette_file_name, void *palette_pointer)
{
#if(IBM)
Load_Data(palette_file_name, palette_pointer, 768);
#else
Load_Data(palette_file_name, palette_pointer, (ULONG)(2<<BIT_PLANES));
#endif
}
/**************************** End of loadpal.cpp ***************************/

View File

@@ -0,0 +1,188 @@
/*
** 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 : IFF *
* *
* File Name : LOADPCX.CPP *
* *
* Programmer : Julio R. Jerez *
* *
* Start Date : May 2, 1995 *
* *
* Last Update : May 3, 1995 [JRJ] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* GraphicBufferClass* Read_PCX_File (char* name, void *Buff, long size ); *
* int Get_PCX_Palette (char * name, void& palette ) *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <wwlib32.h>
#include "filepcx.h"
/***************************************************************************
* READ_PCX_FILE -- read a pcx file into a Graphic Buffer *
* *
* GraphicBufferClass* Read_PCX_File (char* name, char* palette ,void *Buff, long size ); *
* *
* *
* INPUT: name is a NULL terminated string of the fromat [xxxx.pcx] *
* palette is optional, if palette != NULL the the color palette of *
* the pcx file will be place in the memory block pointed *
* by palette. *
* Buff is optinal, if Buff == NULL a new memory Buffer *
* will be allocated, otherwise the file will be placed *
* at location pointd by Buffer; *
* Size is the size in bytes of the memory block pointed by Buff *
* is also optional;
* *
* OUTPUT: on succes a pointer to a GraphicBufferClass cointaining the *
* pcx file, NULL othewise. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/03/1995 JRJ : Created. *
*=========================================================================*/
#define POOL_SIZE 2048
#define READ_CHAR() *file_ptr++ ; \
if ( file_ptr >= & pool [ POOL_SIZE ] ) { \
Read_File ( file_handle, pool , POOL_SIZE ) ; \
file_ptr = pool ; \
}
GraphicBufferClass* Read_PCX_File(char* name, char* Palette, void *Buff, long Size)
{
unsigned i , j ;
unsigned rle ;
unsigned color ;
unsigned scan_pos ;
char * file_ptr ;
int width ;
int height ;
int file_handle ;
char * buffer ;
PCX_HEADER header ;
RGB * pal ;
char pool [ POOL_SIZE ] ;
GraphicBufferClass * pic ;
// Open file name
file_handle = Open_File ( name , READ ) ;
if ( file_handle == WW_ERROR ) return NULL ;
Read_File ( file_handle, & header , sizeof (PCX_HEADER)) ;
if ( header.id != 10 && header.version != 5 &&
header.pixelsize != 8 ) return NULL ;
width = header.width - header.x + 1 ;
height = header.height - header.y + 1 ;
if ( Buff ) {
buffer = ( char * ) Buff;
i = Size / width;
height = MIN ( i - 1, height);
pic = new GraphicBufferClass( width, height, buffer ,Size);
if ( !(pic && pic->Get_Buffer()))return NULL ;
} else {
pic = new GraphicBufferClass( width, height, NULL, width*(height+4));
if ( !(pic && pic->Get_Buffer()))return NULL ;
}
buffer = (char *) pic->Get_Buffer() ;
file_ptr = pool ;
Read_File ( file_handle, pool , POOL_SIZE ) ;
if ( header.byte_per_line != width )
for ( scan_pos = j = 0 ; j < height ; j ++, scan_pos += width ) {
for ( i = 0 ; i < width ; ) {
rle = READ_CHAR ();
if ( rle > 192 ) {
rle -= 192 ;
color = READ_CHAR (); ;
memset ( buffer + scan_pos + i , color , rle ) ;
i += rle ;
} else * ( buffer + scan_pos + i ++ ) = (char)rle ;
}
if ( i == width )
rle = READ_CHAR () ;
// if ( rle > 192 ) rle = READ_CHAR ();
}
else for ( i = 0 ; i < width * height ; ) {
rle = READ_CHAR ();
rle &= 0xff;
if ( rle > 192 ) {
rle -= 192 ;
color = READ_CHAR ();
memset ( buffer + i , color , rle ) ;
i += rle ;
} else * ( buffer + i ++ ) = (char)rle ;
}
if ( Palette ) {
//Seek_File ( file_handle , - 256 * sizeof ( RGB ) , SEEK_END ) ;
Seek_File ( file_handle , 256 * sizeof ( RGB ) , SEEK_END ) ;
Read_File ( file_handle, Palette , 256L * sizeof ( RGB )) ;
pal = ( RGB * ) Palette ;
for ( i = 0 ; i < 256 ; i ++ ) {
pal -> red >>= 2 ;
pal -> green >>= 2 ;
pal -> blue >>= 2 ;
pal ++ ;
}
}
Close_File (file_handle) ;
return pic ;
}
/***************************************************************************
* READ_PCX_FILE -- read a pcx file into a Graphic Buffer *
* *
* GraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff, *
* char* palette) * *
* *
* *
* INPUT: name is a NULL terminated string of the fromat [xxxx.pcx] *
* Buff is a pointer to a BufferClass the will hold the pcx file *
* at location pointd by Buffer; *
* palette is optional, if palette != NULL the the color palette of *
* the pcx file will be place in the memory block pointed *
* by palette. *
* *
* OUTPUT: on succes a pointer to a GraphicBufferClass cointaining the *
* pcx file, NULL othewise. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/03/1995 JRJ : Created. *
*=========================================================================*/
GraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,char* palette)
{
return Read_PCX_File(name, palette, (void*)Buff.Get_Buffer(), Buff.Get_Size());
}

View File

@@ -0,0 +1,552 @@
/*
** 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/wwlib32/file/rcs/loadpict.cpp 1.1 1994/04/20 14:38:08 scott_bowen 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 : IFFEXTRA.C *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : June 11, 1991 *
* *
* Last Update : April 20, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* ILBM_To_Amiga -- Convert ILBM to bitplane Amiga format. *
* ILBM_To_MCGA -- Converts ILBM picture into MCGA format. *
* PBM_To_Amiga -- Converts a PBM picture into Amiga format. *
* Load_Picture -- Loads a picture file (CPS or LBM format). *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "iff.h"
#include "file.h"
#include <wwmem.h> // For Alloc.
#if(IBM)
#include <mem.h>
#endif
// Since we are not currently using AMIGA, this has been put in to
// give us back some code space. If it is needed for a utility,
// this module should be recompiled with that utility and set the
// define to TRUE.
#define MAKE_AMIGA_ART FALSE
/*
** An IFF picture file can have one of two formats:
** ILBM - InterLeaved Bit Map
** PBM - Packed Bit Map
*/
typedef enum {
FORM_ILBM,
FORM_PBM
} IFFForm_Type;
/*
** These are the various chunks that compose an IFF picture file.
*/
#define ID_FORM MAKE_ID('F','O','R','M')
#define ID_ILBM MAKE_ID('I','L','B','M')
#define ID_PBM MAKE_ID('P','B','M',' ')
#define ID_CMAP MAKE_ID('C','M','A','P')
#define ID_BODY MAKE_ID('B','O','D','Y')
#define ID_BMHD MAKE_ID('B','M','H','D')
/*
** The BMHD (Bit Map HeaDer) chunk in an IFF picture file contains the
** information necessary to extract that picture from the BODY chunk.
** It also indicates the size and depth of the source art.
*/
typedef struct {
unsigned short W, H; // Raster width and height in pixels.
short X, Y; // Pixel postion for this image.
char BPlanes; // Number of bitplanes.
unsigned char Masking; // Masking control byte.
// 0 = No masking.
// 1 = Has a mask.
// 2 = Has transparent color.
// 3 = Lasso.
unsigned char Compression; // Compression method.
// 0 = No compression.
// 1 = Byte run compression.
char pad;
unsigned short Transparent; // Transparent color number.
unsigned char XAspect, // Pixel aspect ratio of source art.
YAspect;
short PageWidth, // Source 'page' size in pixels.
PageHeight;
} BitMapHeader_Type;
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
PRIVATE void __cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, int planes);
PRIVATE void __cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes);
PRIVATE void __cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes);
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* ILBM_TO_MCGA -- Converts ILBM picture into MCGA format. *
* *
* This converts an ILBM picture (typical of DPaint LBM files) and *
* converts it to MCGA mode (byte per pixel). This function would be *
* used after the body of an ILBM picture is loaded. Because the *
* number of bitplanes can vary greatly, it is necessary to pass the *
* bitplane count to this function. The size (320 by 200) of the *
* source picture is presumed. *
* *
* INPUT: src - Buffer number for source ILBM picture. *
* *
* dest - Buffer number for place to put MCGA format. *
* *
* planes- The number of bitplanes in the ILBM picture. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/16/1991 JLB : Created. *
* 04/20/1994 SKB : Update to 32 bit library and make private. *
*=========================================================================*/
PRIVATE void __cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, int planes)
{
char *source; // Source pointer.
char *destination; // Destination pointer.
int index,j,i; // Working index values.
int bplane; // Bit plane counter.
char bytes[8]; // Byte array holding max bitplanes (8).
char value; // Composed byte(pixel) value.
source = (char *) src.Get_Buffer();
destination = (char *) dest.Get_Buffer();
memset(bytes, '\0', 8); // Makes sure upper bits will be clear.
// Each row is grouped and processed together.
for (index = 0; index < 200 /*bmhd.H*/; index++) {
// Process each line in groups of 8 bytes.
for (j = 0; j < 40 /*(bmhd.W>>3)*/; j++) {
// Get the bitplane bytes.
for (bplane = 0; bplane < planes /*bmhd.BPlanes*/; bplane++) {
bytes[bplane] = *(source + (bplane * 40 /*(bmhd.W>>3)*/));
}
source++;
// Roll the bits out to create 8 pixels (by bytes).
for (i = 0; i < 8; i++) {
// 8 bits per byte.
value = 0;
for (bplane = planes - 1/*bmhd.BPlanes-1*/; bplane >= 0; bplane--) {
value <<= 1; // Make room for next bit.
if (bytes[bplane] & 0x80) value |= 1; // Set the bit.
bytes[bplane] <<= 1;
}
*destination++ = value; // Output the pixel byte.
}
}
// Advance to next scan line.
source += 40 /* (bmhd.W >> 3)*/ * (planes /* bmhd.BPlanes */ - 1);
}
}
/***************************************************************************
* ILBM_TO_AMIGA -- Convert ILBM to bitplane Amiga format. *
* *
* This converts an InterLeaved BitMap picture into Amiga bitplane *
* format (8K per bitplane). The data of an ILBM picture is controlled *
* by the number of bitplanes it contains. The bitplane count is *
* passed into this program. *
* *
* INPUT: src - Buffer number for source ILBM picture data. *
* *
* dest - Buffer number for destination Amiga picture data. *
* *
* planes- The number of bitplanes in the source ILBM data. *
* *
* OUTPUT: none *
* *
* WARNINGS: The amount of data placed into the destination buffer is *
* controlled by the number of bitplanes specified. It is *
* 8000 per bitplane. *
* *
* HISTORY: *
* 05/20/1991 JLB : Created. *
* 04/20/1994 SKB : Update to 32 bit library and make private. *
* 04/20/1994 SKB : #if out for main library. Only used in utils maybe. *
*=========================================================================*/
#if MAKE_AMIGA_ART
PRIVATE void __cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes)
{
int row; // Working row counter.
int bp; // Working bitplane counter.
char *srcptr, // Source buffer pointer.
*dstptr; // Destination buffer pointer.
srcptr = (char *) src.Get_Buffer(); // Source buffer pointer.
dstptr = (char *) dest.Get_Buffer(); // Destination buffer pointer.
for (row = 0; row < 200; row++) {
for (bp = 0; bp < planes; bp++) {
Mem_Copy(srcptr,dstptr+(8000*bp),40);
srcptr += 40;
}
dstptr += 40;
}
}
#endif
/***************************************************************************
* PBM_TO_AMIGA -- Converts a PBM picture into Amiga format. *
* *
* This converts a PBM (Packed Bit Map) MCGA picture into Amiga *
* bitplane format. A PBM picture presumes 8 bitplanes, but this *
* can be controlled by the 'plane' parameter passed in. *
* *
* INPUT: src - Buffer number for the source PBM data. *
* *
* dest - Buffer number to place the Amiga format picture. *
* *
* planes- The number of bitplanes to extract from the PBM source *
* *
* OUTPUT: none *
* *
* WARNINGS: The amount of data placed into the destination buffer is *
* controlled by the number of bitplanes specified. It is *
* 8000 per bitplane. *
* *
* HISTORY: *
* 05/20/1991 JLB : Created. *
* 04/20/1994 SKB : Update to 32 bit library and make private. *
* 04/20/1994 SKB : #if out for main library. Only used in utils maybe. *
*=========================================================================*/
#if MAKE_AMIGA_ART
PRIVATE void __cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes)
{
int row, // Working row counter.
col, // Working column (by byte) counter.
bit; // Working bitplane counter.
unsigned char *destptr, // Destination byte pointer.
*srcptr; // Source byte pointer.
unsigned char value; // Working input MCGA pixel number.
destptr = (unsigned char *) dest.Get_Buffer();
srcptr = (unsigned char *) src.Get_Buffer();
memset(destptr, 0, 32000);
memset(destptr+32000, 0, 32000);
for (row = 0; row < 200; row++) {
for (col = 0; col < 320; col++) {
value = *srcptr++;
for (bit = 0; bit < planes; bit++) {
if (value & (0x01 << bit)) {
destptr[(short)((8000L * (long)bit) + (col>>3))] |= 0x80 >> (col & 0x07);
}
}
}
destptr += 40;
}
}
#endif
/***************************************************************************
* LOAD_PICTURE -- Loads a picture file (CPS or LBM format). *
* *
* This loads a picture file into a page buffer. The loaded file will *
* be in MCGA or Amiga mode as requested. Supported source formats *
* are CPS or all forms of IFF dpaint files. *
* *
* INPUT: filename - Source filename. The only files that are *
* processed as IFF are those files that end with *
* ".LBM". *
* *
* loadbuf - Buffer type number for the temporary loading *
* buffer. It will be trashed. *
* *
* destbuf - Buffer type number for the picture to be placed. *
* *
* palette - Palette buffer pointer. If this value is NULL *
* then no palette is loaded. *
* *
* format - Desired destination format. *
* BM_AMIGA - Destination buffer will contain the *
* picture in bitplane format (Amiga). *
* The buffer will contain data equal to *
* 8K times the number of bit planes. *
* *
* BM_MCGA - Destination buffer will contain the *
* picture in MCGA format (byte per pixel).*
* The buffer will be 64K in size. *
* *
* OUTPUT: int number of bitplanes read into the dest buffer *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/16/1991 JLB : Created. *
* 05/20/1991 JLB : Handles Amiga and IBM destination formats. *
*=========================================================================*/
int __cdecl Load_Picture(char const *filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char *palette, PicturePlaneType format)
{
int fh; // Input file handle.
long ifftype; // Iff form type.
int counter; // Count of the bytes decompressed.
int value; // Working compression code value.
int len; // int sized length value.
int index; // Working index values.
BitMapHeader_Type bmhd; // BMHD chunk data.
IFFForm_Type formtype; // ILBM, PBM.
char *src; // Working source body pointer.
char *dest; // Working destination body pointer.
//len = strlen(filename);
//strupr(filename);
fh = Open_File(filename,READ);
if (fh == WW_ERROR) return(FALSE);
Read_File(fh,&ifftype,4L);
Close_File(fh);
if (ifftype != ID_FORM) {
return((int)Load_Uncompress(filename, scratchbuf, destbuf, palette ) / 8000 ) ;
} else {
fh = Open_Iff_File(filename); // Opens and checks for IFF form.
if (fh == WW_ERROR) return(FALSE);
Read_File(fh, &ifftype, 4L);
if (ifftype == ID_ILBM) {
formtype = FORM_ILBM; // Inter-Leaved Bit Map.
} else {
if (ifftype == ID_PBM) {
formtype = FORM_PBM; // Packed Bit Map.
} else {
return FALSE; // Not a recognizable picture file.
}
}
// Load the BMHD chunk.
if (Read_Iff_Chunk(fh,ID_BMHD,(char*)&bmhd,sizeof(BitMapHeader_Type))) {
#if(IBM)
// Perform necessary IBM conversions to the data.
bmhd.W = Reverse_Short(bmhd.W);
bmhd.H = Reverse_Short(bmhd.H);
bmhd.X = Reverse_Short(bmhd.X);
bmhd.Y = Reverse_Short(bmhd.Y);
// this is a mistake Xaspect and YAspect are char type
// bmhd.XAspect = Reverse_Short(bmhd.XAspect);
// bmhd.YAspect = Reverse_Short(bmhd.YAspect);
value = bmhd.XAspect ;
bmhd.XAspect = bmhd.YAspect ;
bmhd.YAspect = ( unsigned char ) value ;
bmhd.PageWidth = Reverse_Short(bmhd.PageWidth);
bmhd.PageHeight = Reverse_Short(bmhd.PageHeight);
#endif
if (bmhd.Masking > 2) return FALSE; // Don't allow brushes.
if (bmhd.Compression > 1) return FALSE; // Unknown compression.
} else {
return FALSE; // Unable to read the required BMHD chunk.
}
// Load the palette if asked.
if (palette)
{
int pbytes ; // Number of CMAP bytes required.
unsigned char color; // Palette color value.
unsigned char *paletteptr; // Allocated buffer for palette conversions.
unsigned char *source; // Scratch source CMAP data pointer.
unsigned char *dest2; // Scratch destination palette pointer.
// Number of CMAP bytes that are needed.
pbytes = (1 << bmhd.BPlanes) * 3;
// Allocate the temporary palette buffer.
paletteptr = (unsigned char *)Alloc(pbytes, MEM_CLEAR);
source = paletteptr;
dest2 = palette;
// Read in only the bytes that are needed.
pbytes = (int)Read_Iff_Chunk(fh, ID_CMAP, (char *) paletteptr, pbytes);
if (pbytes) {
/*
** CMAP to machine specific palette conversion code. Conversion
** goes from CMAP three bytes per color register to the machine
** specific form.
*/
switch(format) {
default:
case BM_MCGA:
// Convert CMAP to IBM MCGA palette form.
for (index = 0; index < pbytes; index++) {
*dest2++ = *source++ >> 2;
}
break;
#if MAKE_AMIGA_ART
case BM_AMIGA:
// Convert CMAP to Amiga nibble packed palette form.
for (index = 0; index < pbytes; index += 3) {
*dest2++ = *(source++) >> 4;
color = (*(source++) & 0xf0);
color += *(source++) >> 4;
*dest2++ = color;
}
break;
#endif
}
}
Free(paletteptr);
}
// Load in BODY chunk.
dest = (char *) scratchbuf.Get_Buffer();
src = (char *) destbuf.Get_Buffer();
if (Read_Iff_Chunk(fh, ID_BODY, src, destbuf.Get_Size()))
{
for (index = 0; index < (short)bmhd.H; index++)
{
/* Height of source */
// Transfer (possibly uncompress) one row of data.
// PBM or ILBM reader. Bytes per row (all bitplanes).
counter = bmhd.BPlanes * (bmhd.W >> 3);
// If there is a mask then there is one more bitplane.
if (bmhd.Masking == 1)
counter += bmhd.W >> 3 ;
if (bmhd.Compression == 1)
{
// The data is compressed.
// Decompress one scanline (all bitplanes) at a time.
while (counter)
{
value = ( signed char ) *src++; // Decompression code.
if (value == -128) continue; // NOOP code.
if (value >= 0)
{
// Copy N+1 bytes.
len = ((short) value) + 1;
// Ignore the masking bitplane.
if ( bmhd.Masking != 1 ||
(bmhd.Masking==1 && counter > ((short)bmhd.W >> 3) ) )
{
memcpy(dest, src, len);
dest += len;
}
counter -= len;
src += len;
}
else
{
// Replicate -N+1 bytes.
len = (-((short) value)) + 1;
value = *src++;
// Ignore the masking bitplane.
if (bmhd.Masking != 1 || (bmhd.Masking==1 && counter > ((short)bmhd.W >> 3)))
{
memset(dest,value,len);
dest += len;
}
counter -= len;
}
}
}
else
{
// Plain data is just copied.
memcpy(dest,src,counter);
dest += counter;
src += counter;
}
}
/*
** Perform necessary conversions to the data in order to reach
** the desired format.
*/
switch (format) {
default:
case BM_MCGA: // Byte per pixel desired.
if (formtype == FORM_ILBM) {
ILBM_To_MCGA(scratchbuf, destbuf, bmhd.BPlanes);
} else {
Mem_Copy(scratchbuf.Get_Buffer(), destbuf.Get_Buffer(), 64000L);
}
break;
#if MAKE_AMIGA_ART
case BM_AMIGA: // Bitplane format desired.
if (formtype == FORM_ILBM) {
ILBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);
} else {
PBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);
}
break;
#endif
}
}
Close_Iff_File(fh);
}
return((short)bmhd.BPlanes); // Loaded the picture successfully.
}

1089
WIN32LIB/SRCDEBUG/MEM.CPP Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
;
; 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 : LIBRARY *
;* *
;* File Name : MEM_COPY.ASM *
;* *
;* Programmer : Scott Bowen *
;* *
;* Last Update : September 8, 1994 [IML] *
;* Ported to watcom c32 : 01/03/96 [JRJ] *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Mem_Copy -- Copies from one pointer to another. *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
;******************************************************************************
; 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.
OPTIMAL_BYTE_COPY equ 14
;******************************************************************************
; External declares so these functions can be called
;
GLOBAL C Mem_Copy : NEAR
GLOBAL C Largest_Mem_Block : near
CODESEG
;***************************************************************************
;* MEM_COPY -- Copies from one pointer to another. *
;* This routine copies bytes from source to dest. It takes care of *
;* overlapped memory, and unsigned long copies. *
;* *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 04/18/1994 SKB : Created. *
;*=========================================================================*
; void Mem_Copy(void *source, void *dest, unsigned long bytes_to_copy);
PROC Mem_Copy C near
USES ecx , esi , edi , ebx
ARG source:DWORD
ARG dest:DWORD
ARG bytes:DWORD
;********************************* Setup ******************************************
cld
mov esi,[source]
mov edi,[dest]
mov ecx,[bytes] ; get number of bytes to copy.
; check pointers for singularities
cmp esi,edi ; Compare source with dest.
je ??done ; No sence in copying the same pointer.
or esi,0
jz ??done
or edi,0
jz ??done
cmp ecx,OPTIMAL_BYTE_COPY ; see notes above about equate.
jge ??normal ; If >= MAX(2,OPTIMAL_BYTE_COPY), do normal dword copy.
;******************************** Special case <= 2 *******************************
;
; This section must be called for bytes <= 2 since the other case will crash. It
; optionally uses OPTIMAL_BYTE_COPY for the cut off point. This is because after
; extensive testing, it was proved that only at that point (14 or more bytes) does
; it become quicker to use the dword copy method.
cmp esi,edi ; Compare source with dest.
jge ??do_move ; if source greater do forward copy.
lea esi,[esi+ecx-1]
std ; Opps, wrong, force the pointers to decrement.
lea edi,[edi+ecx-1]
??do_move:
rep movsb ; move the one or two bytes.
cld
??done:
ret
;************************** back or forth, that is the question *******************
??normal:
mov ebx,ecx
cmp esi,edi ; Compare source with dest.
jge ??forward ; if source greater do forward copy.
;********************************* Backward ***************************************
??backward:
lea ecx,[edi+ebx]
std
lea edi,[edi+ebx-1]
and ecx,3 ; Get non aligned bytes.
lea esi,[esi+ebx-1]
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.
cld
ret
;********************************* Forward ***************************************
??forward:
cld
mov ecx,edi ; get destination pointer.
neg ecx
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.
mov ecx,ebx ; Get number of bytes left.
shr ecx,2 ; Do 4 bytes at a time.
rep movsd ; do the dword copy.
mov ecx, ebx
and ecx,03h
rep movsb ; finnish the remaining bytes.
ret
ENDP Mem_Copy
IF 0
PROC Largest_Mem_Block C near
uses esi , edi , ebx , ecx , edx
local mem_struct : dword : 16
mov eax , 0500h
lea edi , [ mem_struct ]
int 31h
mov eax , [ mem_struct ]
ret
ENDP Largest_Mem_Block
ENDIF
END


View File

@@ -0,0 +1,401 @@
/*
** 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 : Command & Conquer/ WW Library *
* *
* File Name : MODEMREG.CPP *
* *
* Programmer : Steve Tall *
* *
* Start Date : 10/18/96 *
* *
* Last Update : October 18th 1996 [ST] *
* *
*---------------------------------------------------------------------------------------------*
* Overview: *
* *
* Functions for obtaining modem infommation from the Win95 registry *
* *
* *
*---------------------------------------------------------------------------------------------*
* *
* Functions: *
* *
* Search_Registry_Key -- Search a registry key and all its subkeys for a given value *
* MREC::ModemRegistryEntryClass -- Constructor for ModemRegistryEntryClass *
* MREC::~ModemRegistryEntryClass -- Destructor.Free all the memory we allocated for modem info*
* *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "modemreg.h"
#include <stdio.h>
extern HKEY Get_Registry_Sub_Key (HKEY base_key, char *search_key, BOOL close);
/***********************************************************************************************
* Search_Registry_Key -- Search a registry key and all its subkeys for a given value *
* *
* *
* *
* INPUT: handle to key to search in *
* name of key to search for *
* value expected in key *
* *
* OUTPUT: Handle to key containing value. Null if not found. *
* *
* WARNINGS: This function reenters itself. *
* *
* HISTORY: *
* 10/18/96 4:01AM ST : Created *
*=============================================================================================*/
HKEY Search_Registry_Key (HKEY key_in, char *value_name, char *search_string)
{
int top_key_index = 0; // Index of topmost key
int retval; // Result of registry api calls
HKEY next_key; // handle of next key examine
HKEY next_search; // handle of next key to search
char *subkey_name = new char [256]; // Area to contain result of key enumeration
unsigned long subkey_name_length = 256; // Length of enumeration result area
FILETIME filetime; // Time key was last touched. Not used.
unsigned long value_type; // Type of data that is contained in a key.
unsigned char *key_value = new unsigned char [256]; // Area to return key values into
unsigned long key_value_length = 256; // Length of key value area
/*
** Scan through and enumerate all subkeys of this key. Exit the loop when there are
** no more sub keys to enumerate.
*/
do {
subkey_name_length = 256; // Has to be set each time through the loop
/*
** Get the next key
*/
retval = RegEnumKeyEx (key_in, top_key_index++, subkey_name, &subkey_name_length, NULL, NULL, NULL, &filetime);
if ( retval == ERROR_SUCCESS ){
/*
** Get a handle to this key so we can search it.
*/
next_key = Get_Registry_Sub_Key (key_in, subkey_name, FALSE);
if (next_key){
key_value_length = 256; // Has to be set each time through the loop
if ( RegQueryValueEx (next_key, value_name, NULL, &value_type, key_value, &key_value_length) == ERROR_SUCCESS){
/*
** If this value is type string then do a compare with the value we are looking for
*/
if (value_type == REG_SZ && !strcmp ((char*)key_value, search_string)){
/*
** This is our man. Delete our workspace and return the key handle
*/
delete [] subkey_name;
delete [] key_value;
return (next_key);
}
}
/*
** We didnt find our search value so search this key for more sub keys by reentering
** this function with the handle of the subkey.
*/
next_search = Search_Registry_Key (next_key, value_name, search_string);
RegCloseKey (next_key);
/*
** If the value was found in a subkey then just return with the key handle.
*/
if (next_search){
delete [] subkey_name;
delete [] key_value;
return (next_search);
}
}
}
} while (retval == ERROR_SUCCESS);
/*
** Clean up and exit.
*/
delete [] subkey_name;
delete [] key_value;
return (0);
}
/***********************************************************************************************
* MREC::ModemRegistryEntryClass -- Constructor for ModemRegistryEntryClass *
* *
* This function does all the work in the class. All the registry searching is done here *
* *
* INPUT: Modem number *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/18/96 4:12AM ST : Created *
*=============================================================================================*/
ModemRegistryEntryClass::ModemRegistryEntryClass (int modem_number)
{
HKEY key;
unsigned char return_buf[256];
DWORD retbuf_size = sizeof(return_buf);
int pnp = 0; //Not a plug n pray modem
/*
** Initialise all the info we expect from the registry to NULL.
** Any entries we cant find will just stay NULL.
*/
ModemName = NULL;
ModemDeviceName = NULL;
ErrorCorrectionEnable = NULL;
ErrorCorrectionDisable = NULL;
CompressionEnable = NULL;
CompressionDisable = NULL;
HardwareFlowControl = NULL;
NoFlowControl = NULL;
/*
** Modem info is stored under
** HKEY_LOCAL_MACHINE / System / CurrentControlSet / Services / Class / Modem / nnnn
** where nnnn is a four digit modem number.
*/
key = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, "System", FALSE);
if (!key) return;
key = Get_Registry_Sub_Key (key, "CurrentControlSet", TRUE);
if (!key) return;
key = Get_Registry_Sub_Key (key, "Services", TRUE);
if (!key) return;
key = Get_Registry_Sub_Key (key, "Class", TRUE);
if (!key) return;
key = Get_Registry_Sub_Key (key, "Modem", TRUE);
if (!key) return;
char which_modem[5];
sprintf (which_modem, "%04d", modem_number);
/*
** Get a handle to the modem key if it exists. Then extract the info we need.
*/
key = Get_Registry_Sub_Key (key, which_modem, TRUE);
if (!key) return;
/*
** Get the name of the modem. This is what will be displayed in the modem list presented
** to the user.
*/
if (RegQueryValueEx(key, "Model", NULL, NULL, return_buf, &retbuf_size) != ERROR_SUCCESS){
RegCloseKey (key);
return;
}
ModemName = new char [retbuf_size];
memcpy (ModemName, return_buf, retbuf_size);
/*
** Find out what COM port the modem is attached to. If this info isnt here, then its a
** Plug n Pray modem. Set the flag so we know to do the pnp search later.
*/
retbuf_size = sizeof (return_buf);
if (RegQueryValueEx(key, "AttachedTo", NULL, NULL, return_buf, &retbuf_size) != ERROR_SUCCESS){
/*
** Must be a plug n pray modem. Set the flag. We will look for the port later.
*/
pnp = 1;
ModemDeviceName = new char [strlen (ModemName)+1];
strcpy (ModemDeviceName, ModemName);
}else{
ModemDeviceName = new char [retbuf_size];
memcpy (ModemDeviceName, return_buf, retbuf_size);
}
/*
** The list of modem 'AT' commands is stored in the 'Settings' key.
*/
key = Get_Registry_Sub_Key (key, "Settings", TRUE);
if (!key) return;
/*
** Extract the control strings for error control.
*/
retbuf_size = sizeof (return_buf);
if (RegQueryValueEx(key, "ErrorControl_On", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){
ErrorCorrectionEnable = new char [retbuf_size];
memcpy (ErrorCorrectionEnable, return_buf, retbuf_size);
}
retbuf_size = sizeof (return_buf);
if (RegQueryValueEx(key, "ErrorControl_Off", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){
ErrorCorrectionDisable = new char [retbuf_size];
memcpy (ErrorCorrectionDisable, return_buf, retbuf_size);
}
/*
** Extract the control strings for data compression.
*/
retbuf_size = sizeof (return_buf);
if (RegQueryValueEx(key, "Compression_On", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){
CompressionEnable = new char [retbuf_size];
memcpy (CompressionEnable, return_buf, retbuf_size);
}
retbuf_size = sizeof (return_buf);
if (RegQueryValueEx(key, "Compression_Off", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){
CompressionDisable = new char [retbuf_size];
memcpy (CompressionDisable, return_buf, retbuf_size);
}
/*
** Extract the control strings for hardware flow control.
*/
retbuf_size = sizeof (return_buf);
if (RegQueryValueEx(key, "FlowControl_Hard", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){
HardwareFlowControl = new char [retbuf_size];
memcpy (HardwareFlowControl, return_buf, retbuf_size);
}
/*
** Extract the control strings for no flow control.
*/
retbuf_size = sizeof (return_buf);
if (RegQueryValueEx(key, "FlowControl_Off", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){
NoFlowControl = new char [retbuf_size];
memcpy (NoFlowControl, return_buf, retbuf_size);
}
RegCloseKey (key);
/*
** If this is a plug n pray modem then we need to search for the COM port it is
** attached to.
*/
if (pnp){
/*
** The driver name in the HKEY_LOCAL_MACHINE / Enum section will be Modem\nnnn where nnnn
** is a four digit modem number.
*/
char search_string [256] = {"Modem\\"};
strcat (search_string, which_modem);
/*
** Search through all the registry entries under HKEY_LOCAL_MACHINE / Enum
*/
key = Get_Registry_Sub_Key (HKEY_LOCAL_MACHINE, "Enum", FALSE);
if (!key) return;
HKEY newkey = Search_Registry_Key ( key, "Driver", search_string );
if (newkey){
retbuf_size = sizeof (return_buf);
/*
** Extract the PORTNAME value. This is the name of the port to use to communicate
** with the modem.
*/
retbuf_size = sizeof (return_buf);
if (RegQueryValueEx(newkey, "PORTNAME", NULL, NULL, return_buf, &retbuf_size) == ERROR_SUCCESS){
if (ModemDeviceName) delete [] ModemDeviceName;
ModemDeviceName = new char [retbuf_size];
memcpy (ModemDeviceName, return_buf, retbuf_size);
}
}
RegCloseKey (key);
}
}
/***********************************************************************************************
* MREC::~ModemRegistryEntryClass -- Destructor.Free all the memory we allocated for modem info*
* *
* *
* *
* INPUT: Nothing *
* *
* OUTPUT: Nothing *
* *
* WARNINGS: None *
* *
* HISTORY: *
* 10/18/96 11:39AM ST : Created *
*=============================================================================================*/
ModemRegistryEntryClass::~ModemRegistryEntryClass (void)
{
if (ModemName) delete [] ModemName;
if (ModemDeviceName) delete [] ModemDeviceName;
if (ErrorCorrectionEnable) delete [] ErrorCorrectionEnable;
if (ErrorCorrectionDisable) delete [] ErrorCorrectionDisable;
if (CompressionEnable) delete [] CompressionEnable;
if (CompressionDisable) delete [] CompressionDisable;
if (HardwareFlowControl) delete [] HardwareFlowControl;
if (NoFlowControl) delete [] NoFlowControl;
}

845
WIN32LIB/SRCDEBUG/MONO.ASM Normal file
View File

@@ -0,0 +1,845 @@
;
; 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 : Mono Screen system *
;* *
;* File Name : MONO.ASM *
;* *
;* Programmer : Jeff Wilson *
;* *
;* Start Date : March 28, 1994 *
;* *
;* Last Update : September 8, 1994 [IML] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;GLOBAL MonoScreen :DWORD
;GLOBAL MonoEnabled :DWORD
;
;GLOBAL C Mono_Set_Cursor :NEAR
;GLOBAL C Mono_Clear_Screen :NEAR
;GLOBAL C Mono_Scroll :NEAR
;GLOBAL C Mono_Put_Char :NEAR
;GLOBAL C Mono_Draw_Rect :NEAR
;
;GLOBAL C _Mono_Text_Print :NEAR
;GLOBAL C Mono_Text_Print :NEAR
;
;GLOBAL C Mono_Print :NEAR
;
;GLOBAL C Mono_View_Page :NEAR
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
;
; External declares so these functions can be called
;
GLOBAL MonoScreen :DWORD
GLOBAL MonoEnabled :DWORD
GLOBAL Mono_Set_Cursor :NEAR ; done
GLOBAL Mono_Clear_Screen :NEAR ; done
GLOBAL Mono_Scroll :NEAR ; done
GLOBAL Mono_Put_Char :NEAR ; done
GLOBAL Mono_Draw_Rect :NEAR ; done
GLOBAL _Mono_Text_Print :NEAR ; done
GLOBAL Mono_Text_Print :NEAR ; done
GLOBAL Mono_Print :NEAR ; done
GLOBAL Mono_View_Page :NEAR ; done
;
; Equates used in this file
;
NULL = 0 ; null code
CR = 13 ; carriage return code
CPL = 80 ; characters per line
LPS = 25 ; lines per screen
DATASEG
MonoX DD 0
MonoY DD 0
MonoOff DD 0
MonoScreen DD 0b0000h ;Deffault to Real mode!
MonoEnabled DD 0 ; Is mono printing enabled?
;====================================================================
CharData DB 0DAh,0C4h,0BFh,0B3h,0D9h,0C4h,0C0h,0B3h ; Single line
DB 0D5h,0CDh,0B8h,0B3h,0BEh,0CDh,0D4h,0B3h ; Double horz.
DB 0D6h,0C4h,0B7h,0BAh,0BDh,0C4h,0D3h,0BAh ; Double vert.
DB 0C9h,0CDh,0BBh,0BAh,0BCh,0CDh,0C8h,0BAh ; Double line.
; x,y,dist
BoxData DB 1,0,0 ; Upper left corner.
DB 1,0,1 ; Top edge.
DB 0,1,0 ; Upper right corner.
DB 0,1,2 ; Right edge.
DB -1,0,0 ; Bottom right corner.
DB -1,0,1 ; Bottom edge.
DB 0,-1,0 ; Bottom left corner.
DB 0,-1,2 ; Left edge.
DB 0,0,-1 ; End of list.
; Mono page segment layout array.
PageMap DD 0,1,2,3,4,5,6,7
;===================================================================
CODESEG
;***************************************************************************
;* Map_Segment_To_Address_ -- Translate a 16bit Seg:Offset address to a *
;* Linear address. *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;*=========================================================================*
; int Map_Segment_To_Address ( unsigned seg , unsigned offset );
;***************************************************************************
;* MONO_SET_CURSOR -- Sets the mono cursor to specified coordinates. *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;*=========================================================================*
; void Mono_Set_Cursor(int x, int y);
PROC Mono_Set_Cursor C near
USES eax , ebx , edx
ARG xpos : DWORD
ARG ypos : DWORD
cmp [MonoEnabled],0
je ??exit
; mov ax,cs
; and ax,7
; or ax,SS_DATA
; mov ds,ax
; mov es,ax
; sub eax,eax
mov eax,[ypos]
; mov ah,CPL
; imul ah
lea eax , [ eax + 4 * eax ] ; multiply by CPL
shl eax , 4
; sub ebx,ebx
mov ebx,[xpos]
add ebx,eax
; Update cursor position.
mov edx,03B4h
mov al,0Eh ; High byte register set.
out dx,al
inc edx
mov al,bh
out dx,al ; Set high byte.
dec edx
mov al,0Fh ; Low byte register set.
out dx,al
inc edx
mov al,bl
out dx,al ; Set low byte.
; Update the globals.
add ebx,ebx
mov [MonoOff],ebx
mov eax,[xpos]
mov [MonoX],eax
mov eax,[ypos]
mov [MonoY],eax
??exit:
ret
ENDP Mono_Set_Cursor
;***************************************************************************
;* MONO_CLEAR_SCREEN -- Clears the mono screen and homes cursor. *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;*=========================================================================*
; void Mono_Clear_Screen(void);
PROC Mono_Clear_Screen C near
USES eax , ecx , edi
cmp [MonoEnabled],0
je ??exit
; mov ax,cs
; and ax,7
; or ax,SS_DATA
; mov ds,ax
; mov es,ax
; mov eax,[MonoScreen] ; ES:DI = Mono RAM address.
; mov es,ax
; sub edi,edi
mov edi , [ MonoScreen ]
mov eax,02000200h ; Clear leave attrib bit normal.
mov ecx,8000h/4 ; Number of longs to clear.
rep stosd ; Clear the mono screen.
push 0
push 0
call Mono_Set_Cursor
add esp , 8
??exit:
ret
ENDP Mono_Clear_Screen
;***************************************************************************
;* MONO_SCROLL -- Scroll the mono screen up specified lines. *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;*=========================================================================*
; void Mono_Scroll(DWORD lines);
PROC Mono_Scroll C near
USES eax , ebx , ecx , edx , edi , esi
ARG lines : DWORD
cmp [MonoEnabled],0
je ??exit
; mov ax,cs
; and ax,7
; or ax,SS_DATA
; mov ds,ax
; mov es,ax
; xor eax,eax ; clear eax so no need for sign extend
mov eax, [lines] ; get lines available
or eax,eax ; any lines to scroll?
je short ??fini ; =>NO
mov ebx,eax ; set line counter
mov edx,[MonoY] ; get row count
ror edx,16 ; store it in high half of register
mov dx,[WORD PTR MonoOff] ; get column offset
ror edx,16
; mov eax,[MonoScreen] ; get selector for mono screen
; push ds ; save off data seg for later
; mov ds,ax ; set data source register
; mov es,ax ; and extra source register
sub eax,eax ; set to clear clear line
??looper:
mov ecx,(80*24) ; Number of words to move.
; xor edi,edi ; dst start at top of screen area
; mov esi,80*2 ; src start at next line down
mov edi , [ MonoScreen ]
lea esi , [ 80 * 2 + edi ]
rep movsw ; Scroll the screen upward.
dec dx ; decrement Y counter
ror edx,16 ; switch to mono offset
sub dx,80*2 ; fix MonoOffset
ror edx,16 ; switch to y counter
mov ecx,40 ; Clear out the last line.
rep stosd ; by storing words across it
dec ebx ; last line?
jne ??looper ; =>NO
; reset data values
; pop ds ; restore the ds segment
mov [WORD PTR MonoY],dx ; store of the mono y position
ror edx,16 ; switch to screen offset
mov [WORD PTR MonoOff],dx ; store of the mono offset
??fini:
??exit:
ret
ENDP Mono_Scroll
;***************************************************************************
;* MONO_PUT_CHAR -- Output a character to the mono screen. *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;*=========================================================================*
; void Mono_Put_Char(char character, int attrib=2);
PROC Mono_Put_Char C near
USES eax , edi
ARG character : BYTE
ARG attrib : DWORD
cmp [MonoEnabled],0
je ??exit
; mov ax,cs
; and ax,7
; or ax,SS_DATA
; mov ds,ax
mov edi,[MonoOff]
; mov eax,[MonoScreen]
; mov es,ax ; ES:DI = First character output pointer.
add edi , [ MonoScreen ]
; Output character to monochrome monitor.
mov al,[character]
mov ah,[BYTE PTR attrib]
; stosw
mov [ edi ] , ax
; Update cursor position.
inc [MonoX] ; X position moves.
mov eax,[MonoY]
push eax
mov eax,[MonoX]
push eax
call Mono_Set_Cursor
add esp,8
??exit:
ret
ENDP Mono_Put_Char
;***************************************************************************
;* MONO_DRAW_RECT -- Draw a rectangle using mono characters. *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;*=========================================================================*
; void Mono_Draw_Rect(int x, int y, int w, int h, int attrib=2, int thick=0);
PROC Mono_Draw_Rect C near
USES eax , ebx , ecx , esi , edi
ARG xpos:DWORD
ARG ypos:DWORD
ARG width:DWORD
ARG height:DWORD
ARG attrib:DWORD
ARG thick:DWORD
cmp [MonoEnabled],0
je ??exit
; mov ax,cs
; and ax,7
; or ax,SS_DATA
; mov ds,ax
; mov es,ax
mov esi,OFFSET BoxData
mov edi,OFFSET CharData
; mov cl,3
; sub eax,eax
mov eax,[thick]
and eax,011b
shl eax,3
add edi,eax
; Prep width and height.
cmp [width],2
jb ??fini
cmp [height],2
jb ??fini
sub [width],2
sub [height],2
; Preserve cursor position for later restore.
mov ecx,[MonoX]
push ecx
mov ecx,[MonoY]
push ecx
; Cursor starts at upper left corner.
mov ecx,[ypos]
push ecx
mov ecx,[xpos]
push ecx
call Mono_Set_Cursor
add esp,8
??drawloop:
; Determine the number of characters to output.
mov ecx,[width]
cmp [BYTE PTR esi+2],1
je short ??gotlen
mov ecx,[height]
cmp [BYTE PTR esi+2],2
je short ??gotlen
mov ecx,1
??gotlen:
jecxz ??donerun
??runloop:
sub ebx,ebx
mov bl,[BYTE PTR edi]
; mov ebx,eax
sub eax,eax
mov al,[BYTE PTR attrib]
push eax
push ebx
call Mono_Put_Char
add esp,8
movsx eax,[BYTE PTR esi+1]
; cbw
add eax,[MonoY]
push eax
movsx eax,[BYTE PTR esi]
; cbw
add eax,[MonoX]
dec eax ; Undo cursor advance.
push eax
call Mono_Set_Cursor ; Properly advance cursor.
add esp,8
loop ??runloop
??donerun:
; Advance to next control entry.
add esi,3
inc edi
cmp [BYTE PTR esi+2],-1
jne ??drawloop
; Restore cursor to original position.
call Mono_Set_Cursor
add esp,8
??fini:
??exit:
ret
ENDP Mono_Draw_Rect
;***************************************************************************
;* MONO_TEXT_PRINT -- Prints text to the mono screen at coordinates. *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;*=========================================================================*
; void Mono_Text_Print(void *text, int x, int y, int attrib, int update);
PROC _Mono_Text_Print C near
USES eax,ebx,ecx,edx,edi,esi
ARG text:DWORD
ARG xpos:DWORD
ARG ypos:DWORD
ARG attrib:DWORD
ARG update:DWORD
cmp [MonoEnabled],0
je ??exit
; mov ax,cs
; and ax,7
; or ax,SS_DATA
; mov ds,ax
; mov es,ax
; Preserve cursor coordinates for later restoration.
mov eax,[MonoY]
push eax
mov eax,[MonoX]
push eax
cmp [text],NULL
je ??fini
mov eax,[ypos]
push eax
mov eax,[xpos]
push eax
call Mono_Set_Cursor
add esp,8
mov esi,[text]
??charloop:
xor eax,eax
mov al,[BYTE PTR esi] ; Fetch character to output.
inc esi
; Stop processing on a NULL character.
or eax,eax
je short ??fini
; Special processing for a '\r' characters.
cmp eax,CR
je short ??cr
; Output character to monochrome monitor.
??normal:
; xor ah,ah
mov ebx,eax
mov eax,[attrib]
push eax
push ebx
call Mono_Put_Char
add esp,8
; Perform adjustments if wrapping past right margin.
cmp [WORD PTR MonoX],CPL
jb short ??nowrap
inc [ypos]
mov eax,[ypos]
push eax
; sub eax,eax
push 0
call Mono_Set_Cursor
add esp,8
jmp short ??nowrap
; Move to start of next line.
??cr:
inc [ypos]
mov eax,[ypos]
push eax
mov eax,[xpos]
push eax
call Mono_Set_Cursor
add esp,8
; Scroll the monochrome screen if necessary.
??nowrap:
cmp [MonoY],LPS
jb short ??noscroll
push 1
call Mono_Scroll
add esp,4
dec [ypos]
??noscroll:
jmp short ??charloop
??fini:
cmp [update],0
jne short ??noupdate
call Mono_Set_Cursor
??noupdate:
add esp,8
??exit:
ret
ENDP _Mono_Text_Print
;=====================================================================
PROC Mono_Text_Print C near
USES eax
ARG text:DWORD
ARG xpos:DWORD
ARG ypos:DWORD
ARG attrib:DWORD
cmp [MonoEnabled],0
je ??exit
; sub eax,eax
push 0
mov eax,[attrib]
push eax
mov eax,[ypos]
push eax
mov eax,[xpos]
push eax
mov eax,[text]
push eax
call _Mono_Text_Print
add esp,20
??exit:
ret
ENDP Mono_Text_Print
;***************************************************************************
;* MONO_PRINT -- Prints text to the mono screen at current pos. *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;*=========================================================================*
; void Mono_Print(void *text);
PROC Mono_Print C near
USES eax
ARG text:DWORD
cmp [MonoEnabled],0
je ??exit
; mov ax,cs
; and ax,7
; or ax,SS_DATA
; mov ds,ax
; mov es,ax
; mov eax,1
push 1
; mov eax,2
push 2
mov eax,[MonoY]
push eax
mov eax,[MonoX]
push eax
mov eax,[text]
push eax
call _Mono_Text_Print
add esp,20
??exit:
ret
ENDP Mono_Print
;***************************************************************************
;* Mono_View_Page -- page in a mono screen *
;* *
;* Displays the specified page in displayable mono memory area. *
;* *
;* INPUT: WORD page = which page of memory we will use for storage *
;* *
;* OUTPUT: old_page *
;* *
;* WARNINGS: none. *
;* *
;* HISTORY: *
;*=========================================================================*
; int cdecl Mono_View_Page(int page);
PROC Mono_View_Page C near
USES eax,ebx,ecx,edx,edi,esi
ARG page:DWORD
LOCAL oldpage:DWORD
cmp [MonoEnabled],0
je ??exit
cld
; mov ax,cs
; and ax,7
; or ax,SS_DATA
; mov ds,ax
; mov es,ax
; Prepare the original page number for return to caller.
mov ebx,[PageMap]
mov [oldpage],ebx
; If the desired page is already displayed, then don't do anything.
mov eax,[page]
cmp eax,ebx
je short ??fini
; Verify that page specified is legal.
cmp eax,7
ja short ??fini
; Find where the logical page to display is actually located.
mov ecx,8
mov edi,OFFSET PageMap
repne scasd
neg ecx
add ecx,7 ; ECX = where desired page is located.
; Swap the page ID bytes in the PageMap array.
sub edi,4
mov ebx,[PageMap]
mov eax,[edi]
mov [edi],ebx
mov [PageMap],eax
; Set DS and ES to point to each page.
; mov eax,[MonoScreen]
; mov ds,ax
mov esi , [ MonoScreen ]
; shl ecx,8
shl ecx , 12
; add ecx,edi ; NO Addition to selectors!
lea edi , [ esi + ecx ]
; mov edi,ecx
; xor esi,esi
; Exchange the two pages.
mov ecx,1000H/4
??looper:
mov edx,[edi]
mov ebx,[esi]
mov [edi],ebx
mov [esi],edx
add esi,4
add edi,4
loop ??looper
; Return with the original page number.
??fini:
??exit:
mov eax,[oldpage]
ret
ENDP Mono_View_Page
END


789
WIN32LIB/SRCDEBUG/MONO.CPP Normal file
View File

@@ -0,0 +1,789 @@
/*
** 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: F:\projects\c&c\vcs\code\monoc.cpv 2.12 06 Sep 1995 16:37:54 JOE_BOSTIC $ */
/***********************************************************************************************
*** 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 : Command & Conquer *
* *
* File Name : MONO.CPP *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : July 2, 1994 *
* *
* Last Update : October 17, 1994 [JLB] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* MonoClass::Clear -- Clears the monochrome screen object. *
* MonoClass::Draw_Box -- Draws a box using the IBM linedraw characters. *
* MonoClass::MonoClass -- The default constructor for monochrome screen object. *
* MonoClass::operator = -- Handles making one mono object have the same imagery as another. *
* MonoClass::Print -- Prints the text string at the current cursor coordinates. *
* MonoClass::Printf -- Prints a formatted string to the monochrome screen. *
* MonoClass::Scroll -- Scroll the monochrome screen up by the specified lines. *
* MonoClass::Set_Cursor -- Sets the monochrome cursor to the coordinates specified. *
* MonoClass::Text_Print -- Prints text to the monochrome object at coordinates indicated. *
* MonoClass::View -- Brings the mono object to the main display. *
* MonoClass::~MonoClass -- The default destructor for a monochrome screen object. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//#pragma inline
#include "mono.h"
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <stdarg.h>
#include <string.h>
extern void output(short port, short data);
#pragma aux output parm [dx] [ax] = \
"out dx,al" \
"inc dx" \
"mov al,ah" \
"out dx,al"
int MonoClass::Enabled = 0;
MonoClass * MonoClass::PageUsage[MonoClass::MAX_MONO_PAGES] = {0,0,0,0,0,0,0,0};
void * MonoClass::MonoSegment = (void*)0x000b0000;
/*
** These are the IBM linedraw characters.
*/
MonoClass::BoxDataType const MonoClass::CharData[MonoClass::COUNT] = {
{0xDA,0xC4,0xBF,0xB3,0xD9,0xC4,0xC0,0xB3}, // Single line
{0xD5,0xCD,0xB8,0xB3,0xBE,0xCD,0xD4,0xB3}, // Double horz.
{0xD6,0xC4,0xB7,0xBA,0xBD,0xC4,0xD3,0xBA}, // Double vert.
{0xC9,0xCD,0xBB,0xBA,0xBC,0xCD,0xC8,0xBA} // Double horz and vert.
};
/***********************************************************************************************
* MonoClass::MonoClass -- The default constructor for monochrome screen object. *
* *
* This is the constructor for monochrome screen objects. It handles allocating a free *
* monochrome page. If there are no more pages available, then this is a big error. The *
* page allocated may not be the visible one. Call the View function in order to bring *
* it to the displayed page. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
MonoClass::MonoClass(void)
{
int index;
Attrib = DEFAULT_ATTRIBUTE; // Normal text color.
X = Y = 0;
for (index = 0; index < MAX_MONO_PAGES; index++) {
if (!PageUsage[index]) {
PageUsage[index] = this;
Page = (char)index;
break;
}
}
if (index == MAX_MONO_PAGES) {
// Major error message should pop up here!
delete this;
}
}
/***********************************************************************************************
* MonoClass::~MonoClass -- The default destructor for a monochrome screen object. *
* *
* This is the default destructor for a monochrome screen object. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
MonoClass::~MonoClass(void)
{
PageUsage[Page] = 0;
}
/***********************************************************************************************
* MonoClass::Draw_Box -- Draws a box using the IBM linedraw characters. *
* *
* Use this routine to draw a box to the monochrome screen. The IBM line draw characters *
* are used to give the it a fancy appearance. There are several line draw modes supported. *
* *
* INPUT: x,y -- The coordinates of the upper left corner of the box. *
* *
* w,y -- The width and height (respectively) to make the box. *
* *
* attrib -- The text attribute to use when drawing the box outline characters. *
* *
* thick -- The thickness style to use. Examine the BoxStyleType enum for *
* elaboration on the supported styles. *
* *
* OUTPUT: none *
* *
* WARNINGS: The interior of the box is NOT cleared by this routine. It is advised that this *
* area be cleared before the box is drawn. *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
void MonoClass::Draw_Box(int x, int y, int w, int h, char attrib, BoxStyleType thick)
{
CellType cell;
char oldattrib = Attrib;
if (!Enabled || !w || !h) return;
cell.Attribute = attrib;
/*
** Draw the horizontal lines.
*/
for (int xpos = 0; xpos < w-2; xpos++) {
cell.Character = CharData[thick].TopEdge;
Store_Cell(cell, x+xpos+1, y);
cell.Character = CharData[thick].BottomEdge;
Store_Cell(cell, x+xpos+1, y+h-1);
}
/*
** Draw the vertical lines.
*/
for (int ypos = 0; ypos < h-2; ypos++) {
cell.Character = CharData[thick].LeftEdge;
Store_Cell(cell, x, y+ypos+1);
cell.Character = CharData[thick].RightEdge;
Store_Cell(cell, x+w-1, y+ypos+1);
}
/*
** Draw the four corners.
*/
if (w > 1 && h > 1) {
cell.Character = CharData[thick].UpperLeft;
Store_Cell(cell, x, y);
cell.Character = CharData[thick].UpperRight;
Store_Cell(cell, x+w-1, y);
cell.Character = CharData[thick].BottomRight;
Store_Cell(cell, x+w-1, y+h-1);
cell.Character = CharData[thick].BottomLeft;
Store_Cell(cell, x, y+h-1);
}
Attrib = oldattrib;
}
/***********************************************************************************************
* MonoClass::Set_Cursor -- Sets the monochrome cursor to the coordinates specified. *
* *
* Use this routine to set the monochrome's cursor position to the coordinates specified. *
* This is the normal way of controlling where the next Print or Printf will output the *
* text to. *
* *
* INPUT: x,y -- The coordinate to position the monochrome cursor. 0,0 is the upper left *
* corner. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
void MonoClass::Set_Cursor(int x, int y)
{
#if(0)
int pos = (y*COLUMNS)+x;
if (!Enabled) return;
X = (char)(x%COLUMNS);
Y = (char)(y%LINES);
if (Page == 0) {
_DX = CONTROL_PORT;
_AX = (short)(0x0E|(pos&0xFF00));
asm {
out dx,al
inc dx
mov al,ah
out dx,al
}
_DX = CONTROL_PORT;
_AX = (short)(0x0F|(pos<<8));
asm {
out dx,al
inc dx
mov al,ah
out dx,al
}
}
#else
int pos = (y*COLUMNS)+x;
if (!Enabled) return;
X = (char)(x%COLUMNS);
Y = (char)(y%LINES);
if (Page == 0) {
output(CONTROL_PORT,
(short)0x0E|(short)(pos&0xFF00));
output(CONTROL_PORT,
(short)0x0F|(short)(pos<<8));
}
#endif
}
/***********************************************************************************************
* MonoClass::Clear -- Clears the monochrome screen object. *
* *
* This routine will fill the monochrome screen object with spaces. It is clearing the *
* screen of data, making it free for output. The cursor is positioned at the upper left *
* corner of the screen by this routine. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
void MonoClass::Clear(void)
{
CellType cell;
if (!Enabled) return;
Set_Cursor(0, 0);
cell.Attribute = Attrib;
cell.Character = ' ';
for (int y = 0; y < LINES; y++) {
for (int x = 0; x < COLUMNS; x++) {
Store_Cell(cell, x, y);
}
}
}
/***********************************************************************************************
* MonoClass::Scroll -- Scroll the monochrome screen up by the specified lines. *
* *
* Use this routine to scroll the monochrome screen up by the number of lines specified. *
* This routine is typically called by the printing functions so that the monochrome screen *
* behaves in the expected manner -- printing at the bottom of the screen scrolls it up *
* to make room for new text. *
* *
* INPUT: lines -- The number of lines to scroll the monochrome screen. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
void MonoClass::Scroll(int lines)
{
CellType cell;
if (!Enabled || lines <= 0) return;
memmove( (void*)((long)MonoSegment + Offset(0, 0)),
(void*)((long)MonoSegment + Offset(0, lines)),
(LINES-lines)*COLUMNS*sizeof(CellType));
Y--;
cell.Attribute = Attrib;
cell.Character = ' ';
for (int l = LINES-lines; l < LINES; l++) {
for (int index = 0; index < COLUMNS; index++) {
Store_Cell(cell, index, l);
}
}
}
/***********************************************************************************************
* MonoClass::Printf -- Prints a formatted string to the monochrome screen. *
* *
* Use this routine to output a formatted string, using the standard formatting options, *
* to the monochrome screen object's current cursor position. *
* *
* INPUT: text -- Pointer to the text to print. *
* *
* ... -- Any optional parameters to supply in formatting the text. *
* *
* OUTPUT: none *
* *
* WARNINGS: The total formatted text length must not exceed 255 characters. *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
void MonoClass::Printf(char const *text, ...)
{
va_list va;
/*
** The buffer object is placed at the end of the local variable list
** so that if the sprintf happens to spill past the end, it isn't likely
** to trash anything (important). The buffer is then manually truncated
** to maximum allowed size before being printed.
*/
char buffer[256];
if (!Enabled) return;
va_start(va, text);
vsprintf(buffer, text, va);
buffer[sizeof(buffer)-1] = '\0';
Print(buffer);
va_end(va);
}
#ifdef NEVER
void MonoClass::Printf(int text, ...)
{
va_list va;
/*
** The buffer object is placed at the end of the local variable list
** so that if the sprintf happens to spill past the end, it isn't likely
** to trash anything (important). The buffer is then manually truncated
** to maximum allowed size before being printed.
*/
char buffer[256];
if (!Enabled) return;
va_start(va, text);
vsprintf(buffer, Text_String(text), va);
buffer[sizeof(buffer)-1] = '\0';
Print(buffer);
va_end(va);
}
#endif
/***********************************************************************************************
* MonoClass::Print -- Prints the text string at the current cursor coordinates. *
* *
* Use this routine to output the specified text string at the monochrome object's current *
* text coordinate position. *
* *
* INPUT: ptr -- Pointer to the string to print. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
void MonoClass::Print(char const *ptr)
{
char startcol = X;
char const * text;
CellType cell;
if (!ptr || !Enabled) return;
text = ptr;
cell.Attribute = Attrib;
while (*text) {
/*
** Sometimes the character string is used for cursor control instead
** of plain text output. Check for this case.
*/
switch (*text) {
/*
** The "return" code behaves as it did in the old C library
** mono system. That is, it returns the cursor position to
** the next line but at the starting column of the print.
*/
case '\r':
X = startcol;
Y++;
Scroll(Y-(LINES-1));
break;
/*
** The "newline" code behaves like the console newline character.
** That is, it moves the cursor down one line and at the first
** column.
*/
case '\n':
X = 0;
Y++;
Scroll(Y-(LINES-1));
break;
/*
** All other characters are output directly and the cursor moves
** rightward to match. If the cursor wraps past the right
** edge is it moved to the next now down at left margin. If the
** cursor goes off the bottom of the display, the display is scrolled
** upward a line.
*/
default:
cell.Character = *text;
Store_Cell(cell, X, Y);
X++;
if (X >= COLUMNS) {
X = 0;
Y++;
if (Y > (LINES-1)) {
Scroll(Y-(LINES-1));
}
}
break;
}
text++;
}
Set_Cursor(X, Y);
}
/***********************************************************************************************
* MonoClass::Text_Print -- Prints text to the monochrome object at coordinates indicated. *
* *
* Use this routine to output text to the monochrome object at the X and Y coordinates *
* specified. *
* *
* INPUT: text -- Pointer to the text string to display. *
* *
* x,y -- The X and Y character coordinates to start the printing at. *
* *
* attrib-- Optional parameter that specifies what text attribute code to use. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
void MonoClass::Text_Print(char const *text, int x, int y, char attrib)
{
char oldx = X;
char oldy = Y;
char oldattrib = Attrib;
X = (char)x;
Y = (char)y;
Attrib = attrib;
Print(text);
Attrib = oldattrib;
Set_Cursor(oldx, oldy);
}
#ifdef NEVER
void MonoClass::Text_Print(int text, int x, int y, char attrib)
{
char oldx = X;
char oldy = Y;
char oldattrib = Attrib;
if (text != TXT_NONE) {
X = (char)x;
Y = (char)y;
Attrib = attrib;
Print(Text_String(text));
Attrib = oldattrib;
Set_Cursor(oldx, oldy);
}
}
void MonoClass::Print(int text)
{
Print(Text_String(text));
}
#endif
/***********************************************************************************************
* MonoClass::operator = -- Handles making one mono object have the same imagery as another. *
* *
* The assignment operator will handle copying the imagery from one monochrome object to *
* another. Use this routine in to make two monochrome class objects visually identical. *
* *
* INPUT: src -- A reference to the source (right side) monochrome object. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
MonoClass & MonoClass::operator = (MonoClass const & src)
{
memcpy((void*)((long)MonoSegment + src.Offset(0, 0)), (void*)((long)MonoSegment + Offset(0, 0)), SIZE_OF_PAGE);
Set_Cursor(src.X, src.Y);
return(*this);
}
/***********************************************************************************************
* MonoClass::View -- Brings the mono object to the main display. *
* *
* Use this routine to display the mono object on the monochrome screen. It is possible *
* that the mono object exists on some background screen memory. Calling this routine will *
* perform the necessary memory swapping to bring the data to the front. The mono object *
* that was currently being viewed is not destroyed by this function. It is merely moved *
* off to some background page. It can be treated normally, except that is just isn't *
* visible. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/17/1994 JLB : Created. *
*=============================================================================================*/
void MonoClass::View(void)
{
MonoClass *displace; // The page that is being displaced.
if (Get_Current() == this) return;
/*
** If the visible page is already assigned to a real monochrome page
** object, then it must be swapped with the new one.
*/
displace = Get_Current();
if (displace) {
char temp[SIZE_OF_PAGE];
memcpy(&temp[0], MonoSegment, SIZE_OF_PAGE);
memcpy(MonoSegment, (void*)((long)MonoSegment + Offset(0, 0)), SIZE_OF_PAGE);
memcpy((void*)((long)MonoSegment + Offset(0, 0)), &temp[0], SIZE_OF_PAGE);
displace->Page = Page;
} else {
/*
** Just copy the new page over since the display page is not assigned
** to a real monochrome page object.
*/
memcpy(MonoSegment, (void*)((long)MonoSegment + Offset(0, 0)), SIZE_OF_PAGE);
}
PageUsage[Page] = displace;
PageUsage[0] = this;
Page = 0;
Set_Cursor(X, Y);
}
/************************************************************************************
** This is the set of C wrapper functions that access the MonoClass support routines.
** Since the C interface doesn't have the ability to write to non-visible pages, it
** will just blast the output to whichever mono page is currently visible. If there is
** no mono class object that is visible, then one will be created -- BUT NOT FREED.
** Typically, this is ok, since the C interface will create only one MonoClass object
** and the system supports up to 8.
*/
void Mono_Set_Cursor(int x, int y)
{
if (MonoClass::Is_Enabled()) {
MonoClass *mono = MonoClass::Get_Current();
if (!mono) {
mono = new MonoClass();
mono->View();
}
mono->Set_Cursor(x, y);
}
}
int Mono_Printf(char const *string, ...)
{
va_list va;
char buffer[256];
buffer[0] = '\0';
if (MonoClass::Is_Enabled()) {
MonoClass *mono = MonoClass::Get_Current();
if (!mono) {
mono = new MonoClass();
mono->View();
}
va_start(va, string);
vsprintf(buffer, string, va);
mono->Print(buffer);
va_end(va);
}
return((short)strlen(buffer));
}
void Mono_Clear_Screen(void)
{
if (MonoClass::Is_Enabled()) {
MonoClass *mono = MonoClass::Get_Current();
if (!mono) {
mono = new MonoClass();
mono->View();
}
mono->Clear();
}
}
void Mono_Text_Print(void const *text, int x, int y, int attrib)
{
if (MonoClass::Is_Enabled()) {
MonoClass *mono = MonoClass::Get_Current();
if (!mono) {
mono = new MonoClass();
mono->View();
}
mono->Text_Print((const char*)text, x, y, (char)attrib);
}
}
void Mono_Draw_Rect(int x, int y, int w, int h, int attrib, int thick)
{
if (MonoClass::Is_Enabled()) {
MonoClass *mono = MonoClass::Get_Current();
if (!mono) {
mono = new MonoClass();
mono->View();
}
mono->Draw_Box(x, y, w, h, (char)attrib, (MonoClass::BoxStyleType)thick);
}
}
void Mono_Print(void const *text)
{
if (MonoClass::Is_Enabled()) {
MonoClass *mono = MonoClass::Get_Current();
if (!mono) {
mono = new MonoClass();
mono->View();
}
mono->Print((const char*)text);
}
}
int Mono_X(void)
{
if (MonoClass::Is_Enabled()) {
MonoClass *mono = MonoClass::Get_Current();
if (!mono) {
mono = new MonoClass();
mono->View();
}
return(short)mono->Get_X();
}
return(0);
}
int Mono_Y(void)
{
if (MonoClass::Is_Enabled()) {
MonoClass *mono = MonoClass::Get_Current();
if (!mono) {
mono = new MonoClass();
mono->View();
}
return(short)mono->Get_X();
}
return(0);
}
void Mono_Put_Char(char , int )
{
}
void Mono_Scroll(int )
{
}
void Mono_View_Page(int )
{
}
#ifdef NEVER
int Mono_Printf(int string, ...)
{
va_list va;
char buffer[256];
buffer[0] = '\0';
if (MonoClass::Is_Enabled()) {
MonoClass *mono = MonoClass::Get_Current();
if (!mono) {
mono = new MonoClass();
mono->View();
}
va_start(va, string);
vsprintf(buffer, Text_String(string), va);
mono->Print(buffer);
va_end(va);
}
return((short)strlen(buffer));
}
#endif

View File

@@ -0,0 +1,77 @@
/*
** 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 : MONOPRNT.C *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : October 12, 1993 *
* *
* Last Update : November 2, 1993 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Mono_Printf -- Prints formated text to the monochrome screen. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include "mono.h"
/***************************************************************************
* Mono_Printf -- Prints formated text to the monochrome screen. *
* *
* This routine is used to print formatted text (similar to printf) to *
* the monochrome screen. *
* *
* INPUT: string -- The string that is to be printed. *
* *
* ... -- Any optional parameters that the string requires *
* to format properly. *
* *
* OUTPUT: Returns with the length of the string that it printed to the *
* monochrome screen. *
* *
* WARNINGS: The total length of the formatted string must not exceed *
* 255 bytes. *
* *
* HISTORY: *
* 11/02/1993 JLB : Created. *
*=========================================================================*/
int Mono_Printf(char const *string, ...)
{
va_list va;
char buffer[256];
if (!MonoEnabled) return(0);
va_start(va, string);
vsprintf(buffer, string, va);
Mono_Print(buffer);
va_end(va);
return(strlen(buffer));
}

View File

@@ -0,0 +1,176 @@
/*
** 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 *
* *
* File Name : PALTOPAL.CPP *
* *
* Programmer : Bill Randolph *
* *
* Start Date : May 2, 1994 *
* *
* Last Update : May 2, 1994 [BR] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Morph_Palette -- morphs a palette from source to destination *
* Palette_To_Palette -- morph src palette to a dst palette *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
********************************* Includes **********************************
*/
#include "wwstd.h"
#include "palette.h"
#include "timer.h"
/*
********************************* Constants *********************************
*/
#define SCALE(a,b,c) (((((long)(a)<<8) / (long)(b) ) * (unsigned long)(c)) >>8)
/*
********************************** Globals **********************************
*/
/*
******************************** Prototypes *********************************
*/
PRIVATE int __cdecl Palette_To_Palette(void *src_palette, void *dst_palette, unsigned long current_time, unsigned long delay);
/***************************************************************************
* Morph_Palette -- morphs a palette from source to destination *
* *
* INPUT: *
* void *src_pal - starting palette *
* void *dst_pal - ending palette *
* unsigned int delay - time delay in 60ths of a second *
* void *callback - user-defined callback, NULL if none *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/02/1994 BR : Created. *
*=========================================================================*/
void cdecl Morph_Palette (void *src_pal, void *dst_pal, unsigned int delay,
void (*callback) (void) )
{
int result;
unsigned long pal_start = TickCount.Time();
extern void (*cb_ptr) ( void ) ; // callback function pointer
// (void *)cb_ptr = callback;
cb_ptr = callback ;
/*===================================================================*/
/* Make sure that we don't go too fast but also make sure we keep */
/* processing the morph palette if we have one. */
/*===================================================================*/
while (1) {
if (src_pal && dst_pal) {
result = Palette_To_Palette (src_pal, dst_pal,
(TickCount.Time() - pal_start), (unsigned long)delay);
if (!result)
break;
if (callback) {
(*cb_ptr)();
}
}
}
return;
} /* end of Morph_Palette */
/***************************************************************************
* Palette_To_Palette -- morph src palette to a dst palette *
* *
* Creates & sets a palette that's in-between 'src_palette' & *
* 'dst_palette'; how close it is to dst_palette is based on how close *
* 'current_time' is to 'delay'. 'current_time' & 'delay' are based on *
* 0 being the start time. *
* *
* INPUT: void *src_palette = palette we want to morph from *
* void *dst_palette = palette we want to morph to *
* long current_time = time we started morph pal *
* long delay = time we want the morph to take*
* *
* OUTPUT: int if the time had elapsed and no chages were *
* necessary this routine returns FALSE *
* otherwise it will always return TRUE (this *
* was necessary to detect the end of the ice *
* effect. *
* *
* HISTORY: *
* 05/24/1993 MC : Created. *
*=========================================================================*/
PRIVATE int cdecl Palette_To_Palette(void *src_palette, void *dst_palette,
unsigned long current_time, unsigned long delay)
{
char colour;
char diff;
int chgval;
int lp;
int change;
static char palette[768];
char *src_pal = (char*)src_palette;
char *dst_pal = (char*)dst_palette;
/*======================================================================*/
/* Loop through each RGB value attempting to change it to the correct */
/* color. */
/*======================================================================*/
for (change = lp = 0; lp < 768; lp++) {
if (current_time < delay ) {
diff = dst_pal[lp] & (char)63;
diff -= src_pal[lp] & (char)63;
if (diff)
change = TRUE;
chgval = SCALE(diff, delay, current_time);
colour = src_pal[lp] & (char)63;
colour +=(char)chgval;
}
else {
colour = dst_pal[lp] & (char)63;
change = FALSE;
}
palette[lp] = colour;
}
/*======================================================================*/
/* Set the palette to the color that we created. */
/*======================================================================*/
Set_Palette(palette);
return(change);
} /* end of Palette_To_Palette */
/*************************** End of morphpal.cpp ***************************/


2246
WIN32LIB/SRCDEBUG/MOUSE.ASM Normal file

File diff suppressed because it is too large Load Diff

673
WIN32LIB/SRCDEBUG/MOUSE.CPP Normal file
View File

@@ -0,0 +1,673 @@
/*
** 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/>.
*/
/***********************************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : MOUSE.CPP *
* *
* Programmer : Philip W. Gorrow *
* *
* Start Date : 12/12/95 *
* *
* Last Update : December 12, 1995 [PWG] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* WWMouseClass::WWMouseClass -- Constructor for the Mouse Class *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "mouse.h"
#include <mmsystem.h>
static WWMouseClass *_Mouse=NULL;
void CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD res2, DWORD res3 );
extern BOOL GameInFocus;
/***********************************************************************************************
* MOUSECLASS::MOUSECLASS -- Constructor for the Mouse Class *
* *
* INPUT: GraphicViewPortClass * screen - pointer to screen mouse is created for *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 12/12/1995 PWG : Created. *
*=============================================================================================*/
WWMouseClass::WWMouseClass(GraphicViewPortClass *scr, int mouse_max_width, int mouse_max_height)
{
MouseCursor = new char[mouse_max_width * mouse_max_height];
MouseXHot = 0;
MouseYHot = 0;
CursorWidth = 0;
CursorHeight = 0;
MouseBuffer = new char[mouse_max_width * mouse_max_height];
MouseBuffX = -1;
MouseBuffY = -1;
MaxWidth = mouse_max_width;
MaxHeight = mouse_max_height;
MouseCXLeft = 0;
MouseCYUpper = 0;
MouseCXRight = 0;
MouseCYLower = 0;
MCFlags = 0;
MCCount = 0;
Screen = scr;
PrevCursor = NULL;
MouseUpdate = 0;
State = 1;
timeBeginPeriod ( 1000/ 60);
InitializeCriticalSection (&MouseCriticalSection);
//
// Install the timer callback event handler
//
EraseBuffer = new char[mouse_max_width * mouse_max_height];
EraseBuffX = -1;
EraseBuffY = -1;
EraseBuffHotX = -1;
EraseBuffHotY = -1;
EraseFlags = FALSE;
_Mouse = this;
TimerHandle = timeSetEvent( 1000/60 , 1 , ::Process_Mouse, 0 , TIME_PERIODIC);
/*
** Force the windows mouse pointer to stay withing the graphic view port region
*/
Set_Cursor_Clip();
}
WWMouseClass::~WWMouseClass()
{
MouseUpdate++;
if (MouseCursor) delete[] MouseCursor;
if (MouseBuffer) delete[] MouseBuffer;
if (TimerHandle) {
timeKillEvent(TimerHandle);
}
timeEndPeriod (1000/60);
DeleteCriticalSection(&MouseCriticalSection);
/*
** Free up the windows mouse pointer movement
*/
Clear_Cursor_Clip();
}
void Block_Mouse(GraphicBufferClass *buffer)
{
if (_Mouse){
_Mouse->Block_Mouse(buffer);
}
}
void Unblock_Mouse(GraphicBufferClass *buffer)
{
if (_Mouse){
_Mouse->Unblock_Mouse(buffer);
}
}
void WWMouseClass::Block_Mouse(GraphicBufferClass *buffer)
{
if (buffer == Screen->Get_Graphic_Buffer()){
EnterCriticalSection(&MouseCriticalSection);
}
}
void WWMouseClass::Unblock_Mouse(GraphicBufferClass *buffer)
{
if (buffer == Screen->Get_Graphic_Buffer()){
LeaveCriticalSection(&MouseCriticalSection);
}
}
void WWMouseClass::Set_Cursor_Clip(void)
{
if (Screen){
RECT region;
region.left = 0;
region.top = 0;
region.right = Screen->Get_Width();
region.bottom = Screen->Get_Height();
ClipCursor(&region);
}
}
void WWMouseClass::Clear_Cursor_Clip(void)
{
ClipCursor(NULL);
}
void WWMouseClass::Process_Mouse(void)
{
POINT pt; // define a structure to hold current cursor pos
//
// If the mouse is currently hidden or it has not been installed, then we
// have no need to redraw the mouse.
//
if (!Screen || !_Mouse || State > 0 || MouseUpdate || EraseFlags || !GameInFocus)
return;
//
// Make sure there are no conflicts with other
// threads that may try and lock the screen buffer
//
//Block_Mouse(Screen->Get_Graphic_Buffer());
//
// If the screen is already locked by another thread then just exit
//
if (Screen->Get_LockCount()!=0){
//Unblock_Mouse(Screen->Get_Graphic_Buffer());
return;
}
//
// Get the mouse's current real cursor position
//
GetCursorPos(&pt); // get the current cursor position
//
// If the mouse has moved then we are responsible to redraw the mouse
//
if (pt.x != MouseBuffX || pt.y != MouseBuffY) {
//
// If we can't lock the surface we need to draw to, we cannot update
// the mouse.
//
if (Screen->Lock()) {
//
// Erase the old mouse by dumping the mouses shadow buff
// to the screen (if its position had ever been recorded).
//
Low_Hide_Mouse();
//
// Verify that the mouse has not gone into a conditional hiden area
// If it has, mark it as being in one.
//
if (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {
MCFlags |= CONDHIDDEN;
}
//
// Show the mouse if we are allowed to.
//
if (!(MCFlags & CONDHIDDEN)) {
Low_Show_Mouse(pt.x, pt.y);
}
//
// Finally unlock the destination surface as we have sucessfully
// updated the mouse.
//
Screen->Unlock();
}
}
//
// Allow other threads to lock the screen again
//
//Unblock_Mouse(Screen->Get_Graphic_Buffer());
}
void *WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, void *cursor)
{
//
// If the pointer to the cursor we got is invalid, or its the same as the
// currently set cursor then just return.
if (!cursor || cursor == PrevCursor)
return(cursor);
//
// Wait until we have exclusive access to our data
//
MouseUpdate++;
//
// Since we are updating the mouse we need to hide the cursor so we
// do not get some sort of weird transformation.
//
Hide_Mouse();
//
// Now convert the shape to a mouse cursor with the given hotspots and
// set it as our current mouse.
//
void *retval = ASM_Set_Mouse_Cursor(this, xhotspot, yhotspot, cursor);
//
// Show the mouse which will force it to appear with the new shape we
// have assigned.
//
Show_Mouse();
//
// We are done updating the mouse cursor so on to bigger and better things.
//
MouseUpdate--;
//
// Return the previous mouse cursor which as conveniantly passed back by
// Asm_Set_Mouse_Cursor.
//
return(retval);
}
void WWMouseClass::Low_Hide_Mouse()
{
if (!State) {
if (MouseBuffX != -1 || MouseBuffY != -1) {
if (Screen->Lock()){
Mouse_Shadow_Buffer(this, Screen, MouseBuffer, MouseBuffX, MouseBuffY, MouseXHot, MouseYHot, 0);
Screen->Unlock();
}
}
MouseBuffX = -1;
MouseBuffY = -1;
}
State++;
}
void WWMouseClass::Hide_Mouse()
{
MouseUpdate++;
Low_Hide_Mouse();
MouseUpdate--;
}
void WWMouseClass::Low_Show_Mouse(int x, int y)
{
//
// If the mouse is already visible then just ignore the problem.
//
if (State == 0) return;
//
// Make the mouse a little bit more visible
//
State--;
//
// If the mouse is completely visible then draw it at its current
// position.
//
if (!State) {
//
// Try to lock the screen til we sucessfully get a lock.
//
if (Screen->Lock()){
//
// Save off the area behind the mouse.
//
Mouse_Shadow_Buffer(this, Screen, MouseBuffer, x, y, MouseXHot, MouseYHot, 1);
//
// Draw the mouse in its new location
//
::Draw_Mouse(this, Screen, x, y);
//
// Save off the positions that we saved the buffer from
//
MouseBuffX = x;
MouseBuffY = y;
//
// Unlock the screen and lets get moving.
//
Screen->Unlock();
}
}
}
void WWMouseClass::Show_Mouse()
{
POINT pt;
GetCursorPos(&pt);
MouseUpdate++;
Low_Show_Mouse(pt.x, pt.y);
MouseUpdate--;
}
void WWMouseClass::Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)
{
POINT pt;
MouseUpdate++;
//
// First of all, adjust all the coordinates so that they handle
// the fact that the hotspot is not necessarily the upper left
// corner of the mouse.
//
x1 -= (CursorWidth - MouseXHot);
x1 = MAX(0, x1);
y1 -= (CursorHeight - MouseYHot);
y1 = MAX(0, y1);
x2 += MouseXHot;
x2 = MIN(x2, Screen->Get_Width());
y2 += MouseYHot;
y2 = MIN(y2, Screen->Get_Height());
// The mouse could be in one of four conditions.
// 1) The mouse is visible and no conditional hide has been specified.
// (perform normal region checking with possible hide)
// 2) The mouse is hidden and no conditional hide as been specified.
// (record region and do nothing)
// 3) The mouse is visible and a conditional region has been specified
// (expand region and perform check with possible hide).
// 4) The mouse is already hidden by a previous conditional.
// (expand region and do nothing)
//
// First: Set or expand the region according to the specified parameters
if (!MCCount) {
MouseCXLeft = x1;
MouseCYUpper = y1;
MouseCXRight = x2;
MouseCYLower = y2;
} else {
MouseCXLeft = MIN(x1, MouseCXLeft);
MouseCYUpper = MIN(y1, MouseCYUpper);
MouseCXRight = MAX(x2, MouseCXRight);
MouseCYLower = MAX(y2, MouseCYLower);
}
//
// If the mouse isn't already hidden, then check its location against
// the hiding region and hide if necessary.
//
if (!(MCFlags & CONDHIDDEN)) {
GetCursorPos(&pt);
if (MouseBuffX >= MouseCXLeft && MouseBuffX <= MouseCXRight && MouseBuffY >= MouseCYUpper && MouseBuffY <= MouseCYLower) {
Low_Hide_Mouse();
MCFlags |= CONDHIDDEN;
}
}
//
// Record the fact that a conditional hide was called and then exit
//
//
MCFlags |= CONDHIDE;
MCCount++;
MouseUpdate--;
}
void WWMouseClass::Conditional_Show_Mouse(void)
{
MouseUpdate++;
//
// if there are any nested hides then dec the count
//
if (MCCount) {
MCCount--;
//
// If the mouse is now not hidden and it had actually been
// hidden before then display it.
//
if (!MCCount) {
if (MCFlags & CONDHIDDEN) {
Show_Mouse();
}
MCFlags = 0;
}
}
MouseUpdate--;
}
void WWMouseClass::Draw_Mouse(GraphicViewPortClass *scr)
{
POINT pt;
if (State != 0) return;
MouseUpdate++;
//
// Get the position that the mouse is currently located at
//
GetCursorPos(&pt);
if (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {
Hide_Mouse();
MCFlags |= CONDHIDDEN;
} else {
//
// If the mouse is already visible then just ignore the problem.
//
EraseFlags = TRUE;
//
// Try to lock the screen - dont do video stuff if we cant.
//
if (scr->Lock()){
//
// Save off the area behind the mouse into two different buffers, one
// which will be used to restore the mouse and the other which will
// be used to restore the hidden surface when we get a chance.
//
Mouse_Shadow_Buffer(this, scr, EraseBuffer, pt.x, pt.y, MouseXHot, MouseYHot, 1);
memcpy(MouseBuffer, EraseBuffer, MaxWidth * MaxHeight);
//
// Draw the mouse in its new location
//
::Draw_Mouse(this, scr, pt.x, pt.y);
//
// Save off the positions that we saved the buffer from
//
EraseBuffX = pt.x;
MouseBuffX = pt.x;
EraseBuffY = pt.y;
MouseBuffY = pt.y;
EraseBuffHotX = MouseXHot;
EraseBuffHotY = MouseYHot;
//
// Unlock the screen and lets get moving.
//
scr->Unlock();
}
}
MouseUpdate--;
}
void WWMouseClass::Erase_Mouse(GraphicViewPortClass *scr, int forced)
{
//
// If we are forcing the redraw of a mouse we already managed to
// restore then just get outta here.
//
if (forced && EraseBuffX == -1 && EraseBuffY == -1) return;
MouseUpdate++;
//
// If this is not a forced call, only update the mouse is we can legally
// lock the buffer.
//
if (!forced) {
#if(0)
if (scr->Lock()) {
//
// If the surface has not already been restore then restore it and erase the
// restoration coordinates so we don't accidentally do it twice.
//
if (EraseBuffX != -1 || EraseBuffY != -1) {
Mouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, 0);
EraseBuffX = -1;
EraseBuffY = -1;
}
//
// We are done writing to the buffer so unlock it.
//
scr->Unlock();
}
#endif
} else {
//
// If the surface has not already been restore then restore it and erase the
// restoration coordinates so we don't accidentally do it twice.
//
if (EraseBuffX != -1 || EraseBuffY != -1) {
if (scr->Lock()){
Mouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, EraseBuffHotX, EraseBuffHotY, 0);
scr->Unlock();
}
EraseBuffX = -1;
EraseBuffY = -1;
}
}
MouseUpdate--;
EraseFlags = FALSE;
}
int WWMouseClass::Get_Mouse_State(void)
{
return(State);
}
/***********************************************************************************************
* WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels *
* *
* INPUT: none *
* *
* OUTPUT: int - returns the mouses current x position in pixels *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
int WWMouseClass::Get_Mouse_X(void)
{
POINT pt;
GetCursorPos(&pt);
return(pt.x);
}
/***********************************************************************************************
* WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels *
* *
* INPUT: none *
* *
* OUTPUT: int - returns the mouses current y position in pixels *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
int WWMouseClass::Get_Mouse_Y(void)
{
POINT pt;
GetCursorPos(&pt);
return(pt.y);
}
/***********************************************************************************************
* WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars *
* *
* INPUT: int &x - variable to return the mouses x position in pixels *
* int &y - variable to return the mouses y position in pixels *
* *
* OUTPUT: none - output is via reference variables *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
void WWMouseClass::Get_Mouse_XY(int &x, int &y)
{
POINT pt;
GetCursorPos(&pt);
x = pt.x;
y = pt.y;
}
#pragma off(unreferenced)
void CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD res2, DWORD res3 )
{
static BOOL in_mouse_callback = false;
if (_Mouse && !in_mouse_callback) {
in_mouse_callback = TRUE;
_Mouse->Process_Mouse();
in_mouse_callback = FALSE;
}
}
#pragma on(unreferenced)
void Hide_Mouse(void)
{
if (!_Mouse) return;
_Mouse->Hide_Mouse();
}
void Show_Mouse(void)
{
if (!_Mouse) return;
_Mouse->Show_Mouse();
}
void Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)
{
if (!_Mouse) return;
_Mouse->Conditional_Hide_Mouse(x1, y1, x2, y2);
}
void Conditional_Show_Mouse(void)
{
if (!_Mouse) return;
_Mouse->Conditional_Show_Mouse();
}
int Get_Mouse_State(void)
{
if (!_Mouse) return(0);
return(_Mouse->Get_Mouse_State());
}
void *Set_Mouse_Cursor(int hotx, int hoty, void *cursor)
{
if (!_Mouse) return(0);
return(_Mouse->Set_Cursor(hotx,hoty,cursor));
}
int Get_Mouse_X(void)
{
if (!_Mouse) return(0);
return(_Mouse->Get_Mouse_X());
}
int Get_Mouse_Y(void)
{
if (!_Mouse) return(0);
return(_Mouse->Get_Mouse_Y());
}

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/>.
*/
/***************************************************************************
** 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 : Memory system. *
* *
* File Name : NEWDEL.CPP *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : June 21, 1994 *
* *
* Last Update : October 20, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* operator NEW -- Overides the global new function. *
* operator delete -- Overides the global delete function. *
* operator NEW[] -- Overides the array version of new. *
* operator delete[] -- Overides the array version of delete[] *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "wwmem.h"
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* OPERATOR NEW -- Overides the global new function. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/21/1994 SKB : Created. *
*=========================================================================*/
void * operator new(size_t size)
{
return (Alloc((unsigned long) size, MEM_NEW));
}
/***************************************************************************
* OPERATOR NEW[] -- Overides the array version of new. *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/21/1994 SKB : Created. *
*=========================================================================*/
void * operator new[](size_t size)
{
return (Alloc((unsigned long) size, MEM_NEW));
}
/***************************************************************************
* OPERATOR DELETE -- Overides the global delete function. *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 06/21/1994 SKB : Created. *
*=========================================================================*/
void operator delete(void *ptr)
{
Free(ptr);
}
/***************************************************************************
* OPERATOR DELETE[] -- Overides the array version of delete[] *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/20/1994 SKB : Created. *
*=========================================================================*/
void operator delete[](void *ptr)
{
Free(ptr);
}

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

150
WIN32LIB/SRCDEBUG/OPSYS.ASM Normal file
View File

@@ -0,0 +1,150 @@
;
; 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/wwlib32/system/rcs/opsys.asm 1.1 1994/04/18 09:14:12 jeff_wilson 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 : Operating System Flags *
;* *
;* File Name : OPSYS.ASM *
;* *
;* Programmer : Scott Bowen *
;* *
;* Start Date : January 26, 1993 *
;* *
;* Last Update : January 26, 1993 [SB] *
;* *
;* Updated to 32bit protected mode JAW *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Operating_System -- Determines what the operating system is. *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL C Operating_System :NEAR
GLOBAL C OperatingSystem :WORD
DOS equ 1
WIN31STD equ 2
WIN31ENH equ 3
WIN30ENH equ 4
WIN30STD equ 5
WIN30REAL equ 6
DATASEG
OperatingSystem dw 0
CODESEG
;***************************************************************************
;* Operating_System -- Determines what the operating system is. *
;* *
;* INPUT: NONE. *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 01/26/1993 SB : Created. *
;*=========================================================================*
PROC Operating_System C near
USES ebx,ecx,edx,es,edi
; Check for Windows 3.1
mov eax,160Ah ; WIN31CHECK
int 2fh
or ax,ax
jz short RunningUnderWin31
;check for Windows 3.0 enhanced mode
mov eax,1600h ; WIN386CHECK
int 2fh
mov bl,al
mov eax,WIN30ENH
test bl,7fh
jnz short Exit
;check for 3.0 WINOLDAP
mov eax,4680h ; IS_WINOLDAP_ACTIVE
int 2fh
or eax,eax
jnz short NotRunningUnderWin
; rule out MS-DOS 5.0 task switcher
mov eax,4b02h ; detect switcher
push ebx
push es
push edi
xor ebx,ebx
mov edi,ebx
mov es,bx
int 2fh
pop edi
pop es
pop ebx
or eax,eax
jz short NotRunningUnderWin ; MS-DOS 5.0 task switcher found.
; check for standrd mode Windows 3.0
mov eax,1605h ;PMODE_START
int 2fh
mov eax,WIN30STD
cmp ecx,-1
jz short Exit
;check for real mode Windows 3.0
mov eax,1606h ; PMODE_STOP
int 2fh
mov eax,WIN30REAL
jmp SHORT Exit
RunningUnderWin31:
; At this point: CX == 3 means Windows 3.1 enhanced mode.
; CX == 2 means Windows 3.1 standard mode.
mov eax,WIN31STD
cmp ecx,2
je short Exit
mov eax,WIN31ENH
jmp SHORT Exit
NotRunningUnderWin:
mov eax,DOS
Exit:
mov [WORD PTR OperatingSystem], ax
ret
ENDP Operating_System
;----------------------------------------------------------------------------
END

View File

@@ -0,0 +1,132 @@
;
; 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/wwlib32/file/rcs/pack2pln.asm 1.1 1994/04/22 18:07:46 scott_bowen 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 : PACK2PLN.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : November 20, 1991 *
;* *
;* Last Update : April 22, 1994 [SKB] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
;******************************************************************************
; External declares so these functions can be called
;
GLOBAL Pack_2_Plane:NEAR
CODESEG
;***************************************************************************
;* PACK_2_PLANE -- packed to planar scanline conversion *
;* *
;* INPUT: BYTE *buffer (far) -- pointer to planar output buffer *
;* BYTE *pageptr (far) -- pointer to current row in packed page *
;* WORD planebit -- current bit used in plane -- use only low byte *
;* *
;* OUTPUT: *
;* Return result in buffer. *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 11/20/1991 SB : Created. *
;* 04/22/1994 SKB : Converted to 32 bit library. *
;*=========================================================================*
; *
; This is the original function that is converted to asm
;
;PRIVATE VOID Pack_2_Plane(UBYTE * buffer, BYTE * pageptr, BYTE planebit)
;{
; WORD currbit=0x80; // current bit to be written to
; WORD pixel; // current pixel in row used as a counter;
;
; buffer--; // will be incremented at the start
; for (currbit = 0, pixel = 0; pixel < 320; pixel++) {
; if (!currbit) {
; currbit = 0x80; // reset bit 7
; buffer++; // go to next byte in buffer
; *buffer = 0; // clear byte so we only need to set bits needed
; }
; if (planebit & *pageptr++)
; *buffer |= currbit; // set bit in destination if plane was set is source
;
; currbit >>= 1; // shift destination bit one right
; }
;}
PROC Pack_2_Plane C NEAR
USES ebx,ecx,esi,edi
ARG buffer:DWORD
ARG page:DWORD
ARG planebit:WORD
mov edi,[buffer]
mov esi,[page]
mov ax,[planebit] ; move bit set for current plane (planebit) to ax
; the low byte will only be used
mov ecx,320d ; set counter to 320 columns (320x200 picture)
mov ah,80h ; set bit 7 of current_bit
dec edi ; this will get incremented at the start
??top_loop: ; while (columns left)
cmp ah,80h ; if current_bit is bit 7
jnz short ??same_dest
; Then
inc edi ; buffer++ increment pointer
mov [BYTE PTR edi],0 ; *buffer = 0
??same_dest: ; EndIf
mov bl,al
and bl,[esi] ; if (planebit & *pageptr)
jz short ??no_set_bit
or [BYTE PTR edi],ah ; Then *buffer |= current_bit
??no_set_bit:
inc esi ; pageptr++ goto next in source byte
ror ah,1 ; rotate current_bit right one
dec ecx ;
jnz ??top_loop
ret
ENDP Pack_2_Plane
END


View File

@@ -0,0 +1,152 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Library *
;* *
;* File Name : PAGFAULT.ASM *
;* *
;* Programmer : Julio R Jerez *
;* *
;* Date : April 25,1995 *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;
; Here are prototypes for the routines defined within this module:
; VOID Install_Page_Fault_Handle (void) ;
;
; ----------------------------------------------------------------
IDEAL ; the product runs in ideal mode
P386 ; use 386 real mode instructions
MODEL USE32 FLAT
LOCALS ?? ; ?? is the symbol for a local
WARN ; generate all warnings we can
JUMPS ; optimize jumps if possible
;---------------------------------------------------------------------------
; Make some general equates for easy compatability
;---------------------------------------------------------------------------
DPMI_INTR EQU 31h
PAGE_FAULT equ 0eh
RESET_VIDEO_MODE equ -1
GLOBAL C Install_Page_Fault_Handle : NEAR
GLOBAL C Set_Video_Mode : NEAR
GLOBAL C Remove_Mouse : NEAR
GLOBAL C Remove_Keyboard_Interrupt : NEAR
GLOBAL C Remove_Timer_Interrupt : NEAR
DATASEG
Old_Page_Fault_handle DF ?
Page_Fault_SS DD ?
Page_Fault_ESP DD ?
CODESEG
;***************************************************************************
;* INSTALL_PAGE_FAULT_HANDLE -- Installs new page fault handle *
;* This function will install a new page fault handle *
;* so in the event that we have a program crash thi handle will *
;* remove all interrupts and then will chain to the default Page *
;* Fault handle *
;* *
;* INPUT: none *
;* *
;* *
;* OUTPUT: none *
;* *
;* PROTO: VOID Install_Page_Fault_Handle( void); *
;* *
;* HISTORY: 04/25/96 Created *
;*=========================================================================*
PROC Install_Page_Fault_Handle C NEAR
USES eax,ebx,ecx,edx,esi,edi
mov eax,0202h ; get address of exception handle
mov bl,PAGE_FAULT
int DPMI_INTR
jc ??exit ; not action is taken
; save addrees of default handle
mov [dword ptr Old_Page_Fault_handle],edx
mov [word ptr Old_Page_Fault_handle+4],cx
; redirect default handle to a new Page Fault Handle
mov eax,0203h
mov bl,PAGE_FAULT
mov cx,cs
lea edx,[Page_Fault_Handle]
int DPMI_INTR
??exit:
ret
ENDP Install_Page_Fault_Handle
;***************************************************************************
;* PAGE_FAULT_HANDLE -- This *
;* *
;* *
;* *
;* HISTORY: 04/25/96 Created *
;*=========================================================================*
PROC Page_Fault_Handle far
; preserve used registers
push eax
push ebx
; save Page Fault satck frame
mov ax,ss
mov [Page_Fault_SS],eax
mov [Page_Fault_ESP],esp
; retrieve application original stack frame
mov eax , [ esp + ( 6 + 2 ) * 4 ]
mov ebx , [ esp + ( 7 + 2 ) * 4 ]
mov ss , bx
mov esp , eax
; set video mode to standard text mode
push RESET_VIDEO_MODE
call Set_Video_Mode
pop eax
call Remove_Mouse
call Remove_Keyboard_Interrupt
call Remove_Timer_Interrupt
; restore Page Fault stack frame
mov eax,[Page_Fault_SS]
mov ss , ax
mov esp, [Page_Fault_ESP]
; restore used registers and chain to default Page Fault Handle
pop ebx
pop eax
jmp [fword Old_Page_Fault_handle]
ENDP Page_Fault_Handle
;***************************************************************************
;* End of File. *
;***************************************************************************
END

410
WIN32LIB/SRCDEBUG/PAL.ASM Normal file
View File

@@ -0,0 +1,410 @@
;
; 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 Library *
;* *
;* File Name : PAL.ASM *
;* *
;* Programmer : Joe L. Bostic *
;* *
;* Start Date : May 30, 1992 *
;* *
;* Last Update : April 27, 1994 [BR] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Set_Palette_Range -- Sets changed values in the palette. *
;* Bump_Color -- adjusts specified color in specified palette *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
;********************** Model & Processor Directives ************************
IDEAL
P386
MODEL USE32 FLAT
;include "keyboard.inc"
FALSE = 0
TRUE = 1
;****************************** Declarations ********************************
GLOBAL C Set_Palette_Range:NEAR
GLOBAL C Bump_Color:NEAR
GLOBAL C CurrentPalette:BYTE:768
GLOBAL C PaletteTable:byte:1024
;********************************** Data ************************************
LOCALS ??
DATASEG
CurrentPalette DB 768 DUP(255) ; copy of current values of DAC regs
PaletteTable DB 1024 DUP(0)
IFNDEF LIB_EXTERNS_RESOLVED
VertBlank DW 0 ; !!!! this should go away
ENDIF
;********************************** Code ************************************
CODESEG
IF 1
;***************************************************************************
;* SET_PALETTE_RANGE -- Sets a palette range to the new pal *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* PROTO: *
;* *
;* WARNINGS: This routine is optimized for changing a small number of *
;* colors in the palette.
;* *
;* HISTORY: *
;* 03/07/1995 PWG : Created. *
;*=========================================================================*
PROC Set_Palette_Range C NEAR
ARG palette:DWORD
GLOBAL Set_DD_Palette_:near
GLOBAL Wait_Vert_Blank_:near
pushad
mov esi,[palette]
mov ecx,768/4
mov edi,offset CurrentPalette
cld
rep movsd
;call Wait_Vert_Blank_
mov eax,[palette]
call Set_DD_Palette_
popad
ret
ifdef NOT_FOR_WIN95
USES eax,ebx,ecx,edx,edi,esi
cld
;*=================================================================*/
;* Set up pointers to begin making palette comparison */
;*=================================================================*/
mov esi, [palette]
mov edi, OFFSET CurrentPalette
mov ebx, OFFSET PaletteTable
mov ecx, 0
??loop_top:
mov eax,[esi] ; read a dword from palette source
mov edx,[edi] ; read a dword from compare palette
and eax,00FFFFFFh ; palette entrys are only 3 bytes
and edx,00FFFFFFh ; long so and of extra
cmp eax,edx ; if they are not the same then
jne ??set_table ; add them into the table
add esi,3
add edi,3
inc cl ; adjust to next palette entry
jnz ??loop_top ; if we dont wrap to zero we have more
jmp ??set_pal ; so now go set the palette
??set_table:
shl eax,8 ; shift bgr value up register
mov al,cl ; store which palette entry num
mov [ebx],eax
add ebx,4
movsw ; copy the three gun values into
movsb ; the shadow palette. Use movsb
inc cl ; adjust to next palette entry
jnz ??loop_top ; if we dont wrap to zero we have more
??set_pal:
mov esi,ebx
mov ebx,OFFSET PaletteTable
sub esi,ebx ; if ebx didn't change there
jz ??exit ; is nothing to set
shr esi,2 ; find how many entrys
mov eax,[ebx]
movzx ecx,al ; we are currently on entry 0
add ebx,4
; Tell DAC of the color gun to start setting.
mov edx,03C8h
out dx,al ; First color set.
; Set the colors only during a VSync.
mov edx,03DAh ; CRTC register.
push ebx
mov bx,[VertBlank]
and bl,001h
shl bl,3
??in_vbi:
in al,dx ; read CRTC status
and al,008h ; only vertical sync bit
xor al,bl
je ??in_vbi ; in vertical sync
??out_vbi:
in al,dx ; read CRTC status
and al,008h ; only vertical sync bit
xor al,bl
jne ??out_vbi ; not in vertical sync
pop ebx
; Update the DAC data register.
mov dx,03C9h
;**************** Time Critical Section Start ******************
cli
??loop:
shr eax,8 ; shift down the red gun value
out dx,al ; write it to the video card
jmp $ + 2 ; force cache to flush, to create a time
shr eax,8 ; shift down the blue gun value
out dx,al ; write it to the video card
jmp $ + 2 ; force cache to flush, to create a time
shr eax,8 ; shift down the blue gun value
out dx,al ; write the green value to video card
jmp $ + 2 ; force cache to flush, to create a time
inc ecx ; move edx to next palette entry
mov eax,[ebx] ; get next value to set
add ebx,4 ; and post increment the palette value
cmp al,cl ; check if DAC position already correct
je ??correct_pos
mov edx,03C8h ; Tell DAC of the color gun to start setting.
out dx,al ; First color set.
mov dx,03C9h
??correct_pos:
dec esi
jnz ??loop
sti
;***************** Time Critical Section End *******************
??exit:
ret
endif ;NOT_FOR_WIN95
ENDP Set_Palette_Range
ELSE
;***************************************************************************
;* Set_Palette_Range -- Sets changed values in the palette. *
;* *
;* INPUT: *
;* VOID *palette - pointer to the new palette. *
;* *
;* OUTPUT: *
;* none *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 04/25/1994 SKB : Created. *
;* 04/27/1994 BR : Converted to 32-bit *
;*=========================================================================*
; VOID cdecl Set_Palette_Range(VOID *palette);
PROC Set_Palette_Range C NEAR
USES eax,ebx,ecx,edx,edi,esi
ARG palette:DWORD
LOCAL remain:DWORD ; 32-bit: converted to LONG
cld
mov bx,[VertBlank]
and bl,001h
shl bl,3
; Make a copy of the palette passed in.
mov edi,OFFSET CurrentPalette
mov esi,[palette]
mov [remain],768
; Search for differences between the current palette and the
; new palette. When a difference is found, output a block
; of color registers and keep scanning.
??bodyloop:
mov ecx,[remain]
repe cmpsb ; Search for differences.
je short ??exit
dec esi
dec edi
inc ecx
mov edx,0 ; clear EDX
mov eax,ecx
mov ecx,3
div ecx ; EAX = # of colors to set, EDX = Fraction.
or edx,edx
jz short ??nofrac
neg edx
add edx,3 ; Back offset skip needed.
inc eax ; Fractional color rounds up to whole color to set.
??nofrac:
; Set CX to be the number of color guns to set.
mov ecx,eax ; Colors * 3 bytes per color.
add ecx,eax
add ecx,eax
; Chop this DAC dump short if necessary in order to reduce
; sparkling.
mov [remain],0
cmp ecx,86*3 ; Number of color guns to set per vert retrace
jbe short ??ok
sub ecx,86*3
mov [remain],ecx
mov ecx,86*3
??ok:
; Adjust the palette offsets back to point to the RED color gun.
sub esi,edx
sub edi,edx
; Determine the color number to start setting.
neg eax
add eax,256 ; AX = Color to start setting (0..255).
; Tell DAC of the color gun to start setting.
mov edx,03C8h
out dx,al ; First color set.
; Set the colors only during a VSync.
mov edx,03DAh ; CRTC register.
??in_vbi:
in al,dx ; read CRTC status
and al,008h ; only vertical sync bit
xor al,bl
je ??in_vbi ; in vertical sync
??out_vbi:
in al,dx ; read CRTC status
and al,008h ; only vertical sync bit
xor al,bl
jne ??out_vbi ; not in vertical sync
;??wait:
; in al,dx
; test al,01000b
; jnz ??wait
;??retrace:
; in al,dx
; test al,01000b
; jz ??retrace
; Update the DAC data register.
mov dx,03C9h
;**************** Time Critical Section Start ******************
pushf
cli
??loop:
lodsb
stosb
out dx,al
jmp $ + 2 ; force cache to flush, to create a time
; delay to give DAC time to get value
loop ??loop
popf
;***************** Time Critical Section End *******************
cmp [remain],0
jnz ??bodyloop
??exit:
ret
ENDP Set_Palette_Range
ENDIF
;***************************************************************************
;* Bump_Color -- adjusts specified color in specified palette *
;* *
;* INPUT: *
;* VOID *palette - palette to modify *
;* WORD changable - color # to change *
;* WORD target - color to bend toward *
;* *
;* OUTPUT: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 04/27/1994 BR : Converted to 32-bit. *
;*=========================================================================*
; BOOL cdecl Bump_Color(VOID *palette, WORD changable, WORD target);
PROC Bump_Color C NEAR
USES ebx,ecx,edi,esi
ARG pal:DWORD, color:WORD, desired:WORD
LOCAL changed:WORD ; Has palette changed?
mov edi,[pal] ; Original palette pointer.
mov esi,edi
mov eax,0
mov ax,[color]
add edi,eax
add edi,eax
add edi,eax ; Offset to changable color.
mov ax,[desired]
add esi,eax
add esi,eax
add esi,eax ; Offset to target color.
mov [changed],FALSE ; Presume no change.
mov ecx,3 ; Three color guns.
; Check the color gun.
??colorloop:
mov al,[BYTE PTR esi]
sub al,[BYTE PTR edi] ; Carry flag is set if subtraction needed.
jz short ??gotit
mov [changed],TRUE
inc [BYTE PTR edi] ; Presume addition.
jnc short ??gotit ; oops, subtraction needed so dec twice.
dec [BYTE PTR edi]
dec [BYTE PTR edi]
??gotit:
inc edi
inc esi
loop ??colorloop
mov ax,[changed]
ret
ENDP Bump_Color
END
;*************************** End of pal.asm ********************************


View File

@@ -0,0 +1,382 @@
/*
** 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 : WWLIB *
* *
* File Name : PALETTE.C *
* *
* Programmer : BILL STOKES *
* *
* Start Date : 6/20/91 *
* *
* Last Update : August 2, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Note: This module contains dependencies upon the video system, *
* specifically Get_Video_Mode(). *
*-------------------------------------------------------------------------*
* Functions: *
* Set_Palette -- sets the current palette *
* Set_Palette_Color -- Set a color number in a palette to the data. *
* Fade_Palette_To -- Fades the current palette into another *
* Determine_Bump_Rate -- determines desired bump rate for fading *
* Bump_Palette -- increments the palette one step, for fading *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
********************************* Includes **********************************
*/
#include <mem.h>
#include "wwstd.h"
#include "palette.h"
#include "timer.h"
/*
********************************* Constants *********************************
*/
/*
********************************** Globals **********************************
*/
extern "C" extern unsigned char CurrentPalette[]; /* in pal.asm */
/*
******************************** Prototypes *********************************
*/
PRIVATE void __cdecl Determine_Bump_Rate(void *palette, int delay, short *ticks, short *rate);
PRIVATE BOOL __cdecl Bump_Palette(void *palette1, unsigned int step);
/*
******************************** Code *********************************
*/
/***************************************************************************
* Set_Palette -- sets the current palette *
* *
* INPUT: *
* void *palette - palette to set *
* *
* OUTPUT: *
* none *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/25/1994 SKB : Created. *
* 04/27/1994 BR : Converted to 32-bit *
*=========================================================================*/
void __cdecl Set_Palette(void *palette)
{
#if(IBM)
Set_Palette_Range(palette);
#else
Copy_Palette(palette,CurrentPalette);
LoadRGB4(&Main_Screen->ViewPort,palette,32L);
LoadRGB4(AltVPort,palette,32L);
#endif
} /* end of Set_Palette */
/***************************************************************************
* Set_Palette_Color -- Set a color number in a palette to the data. *
* *
* *
* INPUT: *
* void *palette - palette to set color in *
* int color - which color index to set *
* void *data - RGB data for color *
* *
* OUTPUT: *
* none *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/25/1994 SKB : Created. *
* 04/27/1994 BR : Converted to 32-bit *
*=========================================================================*/
void __cdecl Set_Palette_Color(void *palette, int color, void *data)
{
/*
---------------------- Return if 'palette' is NULL -----------------------
*/
if (!palette) return;
/*
------------------- Change the color & set the palette -------------------
*/
#if(IBM)
memcpy(&((unsigned char *)palette)[color * RGB_BYTES], data, RGB_BYTES);
Set_Palette_Range(palette);
#else
palette[color] = *(unsigned short*)data;
Set_Palette(palette);
#endif
} /* end of Set_Palette */
/***************************************************************************
* Fade_Palette_To -- Fades the current palette into another *
* *
* This will allow the palette to fade from current palette into the *
* palette that was passed in. This can be used to fade in and fade out. *
* *
* INPUT: *
* char *palette1 - this is the palette to fade to. *
* unsigned int delay - fade with this timer count down *
* void *callback - user-defined callback function *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 06/20/1991 BS : Created. *
*=========================================================================*/
void Fade_Palette_To(void *palette1, unsigned int delay, void (*callback)() )
{
BOOL changed; // Flag that palette has changed this tick.
short jump; // Gun values to jump per palette set.
unsigned long timer; // Tick count timer used for timing.
short ticksper; // The ticks (fixed point) per bit jump.
int tickaccum;
extern void (*cb_ptr)(void); // callback function pointer
// (void *)cb_ptr = callback;
cb_ptr = callback;
/*
---------------------- Return if 'palette1' is NULL ----------------------
*/
if (!palette1)
return;
/*
--------------------------- Get the bump rate ----------------------------
*/
Determine_Bump_Rate(palette1, delay, &ticksper, &jump);
tickaccum = 0; // init accumulated elapsed time
timer = TickCount.Time(); // timer = current time
do {
changed = FALSE;
tickaccum += ticksper; // tickaccum = time of next change * 256
timer += (tickaccum >> 8); // timer = time of next change (rounded)
tickaccum &= 0x0FF; // shave off high byte, keep roundoff bits
changed = Bump_Palette(palette1, jump); // increment palette
/*
.................. Wait for time increment to elapse ..................
*/
if (changed) {
while (TickCount.Time() < timer) {
/*
................. Update callback while waiting .................
*/
if (callback) {
#if LIB_EXTERNS_RESOLVED
Sound_Callback(); // should be removed!
#endif
(*cb_ptr)();
}
}
}
#if LIB_EXTERNS_RESOLVED
Sound_Callback(); // should be removed!
#endif
if (callback) {
(*cb_ptr)();
}
} while (changed);
} /* end of Fade_Palette_To */
/***************************************************************************
* Determine_Bump_Rate -- determines desired bump rate for fading *
* *
* INPUT: *
* unsigned char *palette - palette to fade to *
* int delay - desired time delay in 60ths of a second *
* short *ticks - output: loop ticks per color jump *
* short *rate - output: color gun increment rate *
* *
* OUTPUT: *
* none *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/27/1994 BR : Converted to 32-bit *
* 08/02/1994 SKB : Made private *
*=========================================================================*/
PRIVATE void __cdecl Determine_Bump_Rate(void *palette, int delay, short *ticks,
short *rate)
{
int gun1; // Palette 1 gun value.
int gun2; // Palette 2 gun value.
int diff; // Maximum color gun difference.
int tp; // Temporary tick accumulator.
int index; // Color gun working index.
long t; // Working tick intermediate value.
int adiff; // Absolute difference between guns.
/*
------------------------ Find max gun difference -------------------------
*/
diff = 0;
for (index = 0; index < PALETTE_BYTES; index++) {
gun1 = ((unsigned char *)palette)[index];
gun2 = CurrentPalette[index];
adiff = ABS(gun1-gun2);
diff = MAX(diff, adiff);
}
/*------------------------------------------------------------------------
ticks = (total time delay ) / (max gun diff)
The value is computed based on (delay * 256), for fixed-point math;
the lower bits represent the leftover from the division; 'ticks' is
returned still shifted, so the low bits can be used to accumulate the
time more accurately; the caller must shift the accumulated value down
8 bits to determine the actual elapsed time!
------------------------------------------------------------------------*/
t = ((long)delay) << 8;
if (diff) {
t /= diff;
t = MIN((long)t, (long)0x7FFF);
}
*ticks = (short)t;
/*------------------------------------------------------------------------
Adjust the color gun rate value if the time to fade is faster than can
reasonably be performed given the palette change, ie if (ticks>>8)==0,
and thus less than 1/60 of a second
------------------------------------------------------------------------*/
tp = *ticks;
*rate = 1;
while (*rate <= diff && *ticks < 256) {
*ticks += tp;
*rate += 1;
}
} /* end of Determine_Bump_Rate */
/***************************************************************************
* Bump_Palette -- increments the palette one step, for fading *
* *
* INPUT: *
* palette1 - palette to fade towards *
* step - max step amount, determined by Determine_Bump_Rate *
* *
* OUTPUT: *
* FALSE = no change, TRUE = changed *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/27/1994 BR : Created. *
* 08/02/1994 SKB : Made private *
*=========================================================================*/
#if(IBM)
PRIVATE BOOL __cdecl Bump_Palette(void *palette1, unsigned int step)
{
BOOL changed=FALSE; // Flag that palette has changed this tick.
int index; // Index to DAC register gun.
int gun1,gun2; // Palette 1 gun value.
unsigned char palette[PALETTE_BYTES]; // copy of current palette
/*
---------------------- Return if 'palette1' is NULL ----------------------
*/
if (!palette1)
return (FALSE);
/*
------------------------ Copy the current palette ------------------------
*/
memcpy(palette, CurrentPalette, 768);
/*
----------------------- Loop through palette bytes -----------------------
*/
for (index = 0; index < PALETTE_BYTES; index++) {
gun1 = ((unsigned char *)palette1)[index];
gun2 = palette[index];
/*
............. If the colors match, go on to the next one ..............
*/
if (gun1 == gun2) continue;
changed = TRUE;
/*
.................. Increment current palette's color ..................
*/
if (gun2 < gun1) {
gun2 += step;
gun2 = MIN(gun2, gun1); // make sure we didn't overshoot it
}
/*
.................. Decrement current palette's color ..................
*/
else {
gun2 -= step;
gun2 = MAX(gun2, gun1); // make sure we didn't overshoot it
}
palette[index] = (unsigned char)gun2;
}
/*
----------------- Set current palette to the new palette -----------------
*/
if (changed) {
Set_Palette(&palette[0]);
}
return (changed);
} /* end of Bump_Palette */
#else
/* This is already implemented in asm on the Amiga */
#endif
void (*cb_ptr)(void); // callback function pointer
/**************************** End of palette.cpp ***************************/


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