Initial commit of Command & Conquer Red Alert source code.
This commit is contained in:
58
VQ/VQM32/ALL.H
Normal file
58
VQ/VQM32/ALL.H
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMALL_H
|
||||
#define VQMALL_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* all.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* All VQMisc32 library definitions. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* July 5, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <vqm32\iff.h>
|
||||
#include <vqm32\mono.h>
|
||||
#include <vqm32\portio.h>
|
||||
#include <vqm32\profile.h>
|
||||
#include <vqm32\targa.h>
|
||||
#include <vqm32\compress.h>
|
||||
#include <vqm32\video.h>
|
||||
#include <vqm32\palette.h>
|
||||
#include <vqm32\vesavid.h>
|
||||
#include <vqm32\vesablit.h>
|
||||
#include <vqm32\graphics.h>
|
||||
#include <vqm32\mixfile.h>
|
||||
#include <vqm32\crc.h>
|
||||
#include <vqm32\huffman.h>
|
||||
#include <vqm32\mem.h>
|
||||
|
||||
#endif /* VQMALL_H */
|
||||
|
375
VQ/VQM32/AUDUNZAP.ASM
Normal file
375
VQ/VQM32/AUDUNZAP.ASM
Normal file
@@ -0,0 +1,375 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* audunzap.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* Audio uncompress (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Joe L. Bostic
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* February 9, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* AudioUnzap - Uncompress zapped audio sample.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
CODESEG
|
||||
|
||||
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
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* AudioUnzap - Uncompress zapped audio sample.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Size = AudioUnzap(Source, Dest, Size)
|
||||
;*
|
||||
;* long AudioUnzap(void *, void *, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Decompress the zapped audio sample data into a buffer.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Source - Pointer to encoded audio data.
|
||||
;* Dest - Pointer to buffer to decompress into.
|
||||
;* Size - Maximum size of dest buffer.
|
||||
;*
|
||||
;* RESULT
|
||||
;* Size - Number of uncompressed bytes.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C AudioUnzap:NEAR
|
||||
PROC AudioUnzap C NEAR USES ebx ecx edx esi edi
|
||||
|
||||
ARG source:DWORD
|
||||
ARG dest:DWORD
|
||||
ARG count:DWORD
|
||||
|
||||
LOCAL previous:BYTE
|
||||
LOCAL incount:DWORD
|
||||
|
||||
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).
|
||||
cld
|
||||
|
||||
??mainloop:
|
||||
cmp ecx,0 ;If dest full then exit
|
||||
jle ??fini
|
||||
|
||||
xor eax,eax
|
||||
mov al,[esi] ;Get code byte
|
||||
inc [incount]
|
||||
inc esi
|
||||
shl eax,2 ;AH contains code.
|
||||
shr al,2 ;AL contains sub-code data.
|
||||
|
||||
cmp ah,CODE_RAW ;Raw sequence?
|
||||
jne short ??try4bit
|
||||
|
||||
; The code contains either a 5 bit delta or a count of
|
||||
; raw samples to dump out.
|
||||
|
||||
test al,00100000b
|
||||
je short ??justraw
|
||||
|
||||
; The lower 5 bits are actually a signed delta.
|
||||
; Sign extend the delta and add it to the stream.
|
||||
|
||||
shl al,3
|
||||
sar al,3
|
||||
add dl,al
|
||||
mov [edi],dl
|
||||
dec ecx
|
||||
inc edi
|
||||
jmp ??mainloop
|
||||
|
||||
; The lower 5 bits hold a count of the number of raw
|
||||
; samples that follow this code. Dump these samples to
|
||||
; the output buffer.
|
||||
|
||||
??justraw:
|
||||
mov ebx,ecx
|
||||
xor ah,ah
|
||||
inc al
|
||||
mov ecx,eax
|
||||
shr ecx,1
|
||||
rep movsw
|
||||
adc ecx,ecx
|
||||
rep movsb
|
||||
mov ecx,ebx
|
||||
add [incount],eax
|
||||
sub ecx,eax
|
||||
dec edi
|
||||
mov dl,[edi] ;Set "previous" value.
|
||||
inc edi
|
||||
jmp ??mainloop
|
||||
|
||||
; Check to see if this is a 4 bit delta code sequence.
|
||||
|
||||
??try4bit:
|
||||
inc al ;Following codes use AL+1
|
||||
cmp ah,CODE_4BIT
|
||||
jne short ??try2bit
|
||||
|
||||
; A sequence of 4bit deltas follow. AL equals the
|
||||
; number of nibble packed delta bytes to process.
|
||||
|
||||
??bit4loop:
|
||||
mov ah,[esi] ;Fetch nibble packed delta codes
|
||||
mov bl,ah
|
||||
inc [incount]
|
||||
inc esi
|
||||
|
||||
; Add first delta to 'previous' sample already in DL.
|
||||
|
||||
and ebx,00001111b
|
||||
add dl,[_4bitdecode+ebx]
|
||||
pushf
|
||||
cmp [_4bitdecode+ebx],0
|
||||
jl short ??neg1
|
||||
|
||||
popf
|
||||
jnc short ??ok1
|
||||
mov dl,0FFh
|
||||
jmp short ??ok1
|
||||
|
||||
??neg1:
|
||||
popf
|
||||
jc short ??ok1
|
||||
|
||||
xor dl,dl
|
||||
|
||||
??ok1:
|
||||
mov dh,dl ;DH now holds new 'previous' sample.
|
||||
mov bl,ah
|
||||
shr bl,4
|
||||
add dh,[_4bitdecode+ebx]
|
||||
pushf
|
||||
cmp [_4bitdecode+ebx],0
|
||||
jl short ??neg2
|
||||
|
||||
popf
|
||||
jnc short ??ok2
|
||||
|
||||
mov dh,0FFh
|
||||
jmp short ??ok2
|
||||
|
||||
??neg2:
|
||||
popf
|
||||
jc short ??ok2
|
||||
|
||||
xor dh,dh
|
||||
|
||||
??ok2:
|
||||
mov [edi],dx ;Output the two sample bytes
|
||||
sub ecx,2
|
||||
add edi,2
|
||||
|
||||
; Put the correct 'previous' sample in DL where it belongs.
|
||||
|
||||
mov dl,dh
|
||||
|
||||
; If there are more deltas to process then loop back.
|
||||
|
||||
dec al
|
||||
jnz short ??bit4loop
|
||||
jmp ??mainloop
|
||||
|
||||
; Check to see if 2 bit deltas need to be processed.
|
||||
|
||||
??try2bit:
|
||||
cmp ah,CODE_2BIT
|
||||
jne ??zerodelta
|
||||
|
||||
; A sequence of 2bit deltas follow. AL equals the number of
|
||||
; packed delta bytes to process.
|
||||
|
||||
??bit2loop:
|
||||
mov ah,[esi] ;Fetch packed delat codes
|
||||
inc [incount]
|
||||
inc esi
|
||||
|
||||
; Add first delta to 'previous' sample already in DL.
|
||||
|
||||
mov bl,ah
|
||||
and ebx,000011b
|
||||
add dl,[_2bitdecode+ebx]
|
||||
pushf
|
||||
cmp [_2bitdecode+ebx],0
|
||||
jl short ??neg3
|
||||
|
||||
popf
|
||||
jnc short ??ok3
|
||||
|
||||
mov dl,0FFh
|
||||
jmp short ??ok3
|
||||
|
||||
??neg3:
|
||||
popf
|
||||
jc short ??ok3
|
||||
xor dl,dl
|
||||
|
||||
??ok3:
|
||||
mov dh,dl
|
||||
ror edx,8
|
||||
mov bl,ah
|
||||
shr ebx,2
|
||||
and bl,00000011b
|
||||
add dl,[_2bitdecode+ebx]
|
||||
pushf
|
||||
cmp [_2bitdecode+ebx],0
|
||||
jl short ??neg4
|
||||
|
||||
popf
|
||||
jnc short ??ok4
|
||||
|
||||
mov dl,0FFh
|
||||
jmp short ??ok4
|
||||
|
||||
??neg4:
|
||||
popf
|
||||
jc short ??ok4
|
||||
|
||||
xor dl,dl
|
||||
|
||||
??ok4:
|
||||
mov dh,dl
|
||||
ror edx,8
|
||||
mov bl,ah
|
||||
shr ebx,4
|
||||
and bl,00000011b
|
||||
add dl,[_2bitdecode+ebx]
|
||||
pushf
|
||||
cmp [_2bitdecode+ebx],0
|
||||
jl short ??neg5
|
||||
|
||||
popf
|
||||
jnc short ??ok5
|
||||
|
||||
mov dl,0FFh
|
||||
jmp short ??ok5
|
||||
|
||||
??neg5:
|
||||
popf
|
||||
jc short ??ok5
|
||||
|
||||
xor dl,dl
|
||||
|
||||
??ok5:
|
||||
mov dh,dl
|
||||
ror edx,8
|
||||
mov bl,ah
|
||||
shr ebx,6
|
||||
and bl,00000011b
|
||||
add dl,[_2bitdecode+ebx]
|
||||
pushf
|
||||
cmp [_2bitdecode+ebx],0
|
||||
jl short ??neg6
|
||||
|
||||
popf
|
||||
jnc short ??ok6
|
||||
|
||||
mov dl,0FFh
|
||||
jmp short ??ok6
|
||||
|
||||
??neg6:
|
||||
popf
|
||||
jc short ??ok6
|
||||
|
||||
xor dl,dl
|
||||
|
||||
??ok6:
|
||||
ror edx,8
|
||||
mov [edi],edx ;Output two sample bytes
|
||||
sub ecx,4
|
||||
add edi,4
|
||||
|
||||
; Put the correct 'previous' sample in DL where it belongs.
|
||||
|
||||
rol edx,8
|
||||
|
||||
; If there are more deltas to process then loop back.
|
||||
|
||||
dec al
|
||||
jnz ??bit2loop
|
||||
jmp ??mainloop
|
||||
|
||||
; There is a run of zero deltas. Zero deltas merely duplicate
|
||||
; the 'previous' sample the requested number of times.
|
||||
|
||||
??zerodelta:
|
||||
xor ebx,ebx
|
||||
mov bl,al
|
||||
mov al,dl
|
||||
sub ecx,ebx
|
||||
xchg ecx,ebx
|
||||
rep stosb
|
||||
mov ecx,ebx
|
||||
jmp ??mainloop
|
||||
|
||||
??fini:
|
||||
mov eax,[incount]
|
||||
ret
|
||||
|
||||
ENDP AudioUnzap
|
||||
|
||||
END
|
||||
|
398
VQ/VQM32/AUDZAP.CPP
Normal file
398
VQ/VQM32/AUDZAP.CPP
Normal file
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* Audzap.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Lossy audio compression. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Joe L. Bostic
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* AudioZap - Compress audio sample data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <mem.h>
|
||||
#include "compress.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* PRIVATE DECLARATIONS
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
#define MIN(a,b) (((a)<(b)) ? (a) : (b))
|
||||
#define MAX(a,b) (((a)>(b)) ? (a) : (b))
|
||||
|
||||
typedef enum {
|
||||
CODE_2BIT, /* Bit packed 2 bit delta. */
|
||||
CODE_4BIT, /* Nibble packed 4 bit delta. */
|
||||
CODE_RAW, /* Raw sample. */
|
||||
CODE_SILENCE /* Run of silence. */
|
||||
} SCodeType;
|
||||
|
||||
char _2bitencode[5] = {
|
||||
0,1,2,3
|
||||
};
|
||||
|
||||
long _2bitdecode[4] = {
|
||||
-2,-1,0,1
|
||||
};
|
||||
|
||||
char _4bitencode[19] = {
|
||||
0,1,2,2,3,4,5,6,7,(8),
|
||||
8,9,10,11,12,13,13,14,15
|
||||
};
|
||||
|
||||
long _4bitdecode[16] = {
|
||||
-9,-8,-6,-5,-4,-3,-2,
|
||||
-1,0,1,2,3,4,5,6,8
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* AudioZap - Compress audio sample data.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Size = AudioZap(Source, Dest, Size)
|
||||
*
|
||||
* long AudioZap(void *, void *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
* NOTE - If the compressed size is equal to or greater than the original
|
||||
* size then the data could not be compressed and the uncompressed data
|
||||
* should be written.
|
||||
*
|
||||
* INPUTS
|
||||
* Source - Pointer to buffer containing audio sample data.
|
||||
* Dest - Pointer to buffer to put encoded data.
|
||||
* Size - Number of bytes to compress.
|
||||
*
|
||||
* RESULT
|
||||
* Size - Size in bytes of encoded data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long AudioZap(void *source, void *dest, long size)
|
||||
{
|
||||
unsigned char *s = (unsigned char *)source;
|
||||
unsigned char *d = (unsigned char *)dest;
|
||||
long delta;
|
||||
unsigned long previous = 0x80;
|
||||
long outcount = 0;
|
||||
unsigned char *s4;
|
||||
unsigned long p4;
|
||||
long max4;
|
||||
unsigned char *lastraw = 0;
|
||||
long osize = size;
|
||||
unsigned long i;
|
||||
unsigned long dd;
|
||||
|
||||
/* Reduce very small amplitudes to silence. Usually a rather large
|
||||
* portion of a sample is hovering around the silence value. This is
|
||||
* due, in part, to the artifacting of the sample process. These low
|
||||
* amplitudes are not audible.
|
||||
*/
|
||||
max4 = size;
|
||||
s = (unsigned char *)source;
|
||||
|
||||
while (size > 0 && outcount < osize) {
|
||||
|
||||
/* First check for runs of zero deltas. If a run of at least
|
||||
* any can be found, then output it.
|
||||
*/
|
||||
s4 = s;
|
||||
max4 = MIN(63 + 1, size);
|
||||
|
||||
for (i = 0; i < max4; i++) {
|
||||
if (previous != *s4++)
|
||||
break;
|
||||
}
|
||||
|
||||
/* When there is a code transition, terminate any run of raw
|
||||
* samples.
|
||||
*/
|
||||
if (i > 2) {
|
||||
lastraw = 0;
|
||||
*d++ = ((i - 1)|(CODE_SILENCE << 6));
|
||||
outcount++;
|
||||
s += i;
|
||||
size -= i;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If there are fewer than 4 samples remaining, then using delta
|
||||
* compression is inefficient. Just drop into the raw routine
|
||||
*/
|
||||
if (size > 4) {
|
||||
s4 = s;
|
||||
p4 = previous;
|
||||
|
||||
/* Find out the number of lossless 2 bit deltas available. These
|
||||
* deltas are always present in quads. The compressed code is
|
||||
* the delta quad count followed by the deltas in bit packed bytes.
|
||||
*/
|
||||
max4 = MIN(64L * 4L + 4L + 4L, size);
|
||||
|
||||
for (i = 0; i < max4; i++) {
|
||||
delta = (((int)*s4++) - p4);
|
||||
|
||||
if ((delta < -2) || (delta > 1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
p4 += _2bitdecode[_2bitencode[delta + 2]];
|
||||
|
||||
if (((signed)p4) < 0) {
|
||||
p4 = 0;
|
||||
}
|
||||
|
||||
if (((signed)p4) > 255) {
|
||||
p4 = 255;
|
||||
}
|
||||
}
|
||||
|
||||
i >>= 2; // Delta 2 always occur in quads -- force this.
|
||||
|
||||
/* If there is the minimum benificial number of delta 2s available,
|
||||
* then compress them.
|
||||
*/
|
||||
if (i) {
|
||||
|
||||
/* When there is a code transition, terminate any run of raw
|
||||
* samples.
|
||||
*/
|
||||
lastraw = 0;
|
||||
|
||||
/* Output the delta 4 pair count. This is the number of pairs
|
||||
* minus the 'free' two pairs already assumed to be there.
|
||||
*/
|
||||
i = MIN(i, (63 + 1));
|
||||
*d++ = ((i - 1)|(CODE_2BIT << 6));
|
||||
outcount++;
|
||||
|
||||
for (dd = 0; dd < i; dd++) {
|
||||
int delta1, delta2, delta3, delta4;
|
||||
|
||||
delta1 = _2bitencode[((((int)*s++) - previous) + 2)];
|
||||
previous += _2bitdecode[delta1];
|
||||
|
||||
if (((signed)previous) < 0) {
|
||||
previous = 0;
|
||||
}
|
||||
|
||||
if (((signed)previous) > 255) {
|
||||
previous = 255;
|
||||
}
|
||||
|
||||
size--;
|
||||
delta2 = _2bitencode[((((int)*s++) - previous) + 2)];
|
||||
previous += _2bitdecode[delta2];
|
||||
|
||||
if (((signed)previous) < 0) {
|
||||
previous = 0;
|
||||
}
|
||||
|
||||
if (((signed)previous) > 255) {
|
||||
previous = 255;
|
||||
}
|
||||
|
||||
size--;
|
||||
delta3 = _2bitencode[((((int)*s++) - previous) + 2)];
|
||||
previous += _2bitdecode[delta3];
|
||||
|
||||
if (((signed)previous) < 0) {
|
||||
previous = 0;
|
||||
}
|
||||
|
||||
if (((signed)previous) > 255) {
|
||||
previous = 255;
|
||||
}
|
||||
|
||||
size--;
|
||||
delta4 = _2bitencode[((((int)*s++) - previous) + 2)];
|
||||
previous += _2bitdecode[delta4];
|
||||
|
||||
if (((signed)previous) < 0) {
|
||||
previous = 0;
|
||||
}
|
||||
|
||||
if (((signed)previous) > 255) {
|
||||
previous = 255;
|
||||
}
|
||||
|
||||
size--;
|
||||
*d++ = ((delta4 << 6)|(delta3 << 4)|(delta2 << 2)|delta1);
|
||||
outcount++;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
s4 = s;
|
||||
p4 = previous;
|
||||
|
||||
/* Find out the number of lossless 4 bit deltas follow. These
|
||||
* deltas are always present in pairs. The compressed code is
|
||||
* the delta pair count followed by the deltas in nibble packed
|
||||
* bytes.
|
||||
*/
|
||||
max4 = MIN(64L * 2L + 4L + 4L, size);
|
||||
|
||||
for (i = 0; i < max4; i++) {
|
||||
delta = (((int)*s4++) - p4);
|
||||
|
||||
if (delta < -9 || delta >= 9) {
|
||||
break;
|
||||
}
|
||||
|
||||
p4 += _4bitdecode[_4bitencode[(delta + 9)]];
|
||||
|
||||
if (((signed)p4) < 0) {
|
||||
p4 = 0;
|
||||
}
|
||||
|
||||
if (((signed)p4) > 255) {
|
||||
p4 = 255;
|
||||
}
|
||||
}
|
||||
|
||||
i >>= 1; // Delta 4 always occur in pairs -- force this.
|
||||
|
||||
/* If there is the minimum benificial number of delta 4s available,
|
||||
* then compress them.
|
||||
*/
|
||||
if (i) {
|
||||
|
||||
/* When there is a code transition, terminate any run of raw
|
||||
* samples.
|
||||
*/
|
||||
lastraw = 0;
|
||||
|
||||
/* Output the delta 4 pair count. This is the number of pairs
|
||||
* minus the 'free' two pairs already assumed to be there.
|
||||
*/
|
||||
i = MIN(i, (63 + 1));
|
||||
*d++ = ((i - 1)|(CODE_4BIT << 6));
|
||||
outcount++;
|
||||
|
||||
for (dd = 0; dd < i; dd++) {
|
||||
int delta1, delta2;
|
||||
|
||||
delta1 = _4bitencode[((((int)*s++) - previous) + 9)];
|
||||
previous += _4bitdecode[delta1];
|
||||
|
||||
if (((signed)previous) < 0) {
|
||||
previous = 0;
|
||||
}
|
||||
|
||||
if (((signed)previous) > 255) {
|
||||
previous = 255;
|
||||
}
|
||||
|
||||
size--;
|
||||
delta2 = _4bitencode[((((int)*s++) - previous) + 9)];
|
||||
previous += _4bitdecode[delta2];
|
||||
|
||||
if (((signed)previous) < 0) {
|
||||
previous = 0;
|
||||
}
|
||||
|
||||
if (((signed)previous) > 255) {
|
||||
previous = 255;
|
||||
}
|
||||
|
||||
size--;
|
||||
*d++ = ((delta2 << 4)|(delta1 & 0x0F));
|
||||
outcount++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Raw output since deltas were unsuccessful. If this is a run
|
||||
* of raw output, then merely tack it onto the run rather than
|
||||
* create a new code sequence.
|
||||
*/
|
||||
if (lastraw) {
|
||||
*lastraw = ((*lastraw) + 1);
|
||||
|
||||
/* There is only so much a run code can accomodate. If the limit
|
||||
* has been reached, then terminate this code. A new one will be
|
||||
* created if necessary.
|
||||
*/
|
||||
if ((*lastraw & 0x1F) == 0x1F) {
|
||||
lastraw = 0;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* If there is no current raw dump of samples, then check to see if
|
||||
* this sample can fit into a 5 bit delta. If it can, then store
|
||||
* it as such as a parasite to the "raw" code. This will save a byte
|
||||
* for any stray 5 bit deltas that happen along. It is expected that
|
||||
* this is more frequent than 6 or more bit deltas that would necessitate
|
||||
* the use of the RAW code.
|
||||
*/
|
||||
delta = (((int)*s) - previous);
|
||||
|
||||
if ((delta >= -16) && (delta <= 15)) {
|
||||
lastraw = 0;
|
||||
*d++ = ((CODE_RAW << 6)|0x20|(delta & 0x1F));
|
||||
outcount++;
|
||||
previous = *s++;
|
||||
size--;
|
||||
continue;
|
||||
} else {
|
||||
lastraw = d;
|
||||
*d++ = (CODE_RAW << 6);
|
||||
outcount++;
|
||||
}
|
||||
}
|
||||
|
||||
*d++ = previous = *s++;
|
||||
size--;
|
||||
outcount++;
|
||||
}
|
||||
|
||||
/* Check to see if the compression process actually resulted in smaller
|
||||
* data size. In some cases, the 'compressed' data is actually larger. In
|
||||
* this case, just output the raw frame. If the compressed and actual frame
|
||||
* size match, then it is presumed that no compression occurs.
|
||||
*/
|
||||
if (outcount >= osize) {
|
||||
memcpy(dest, source, (size_t)osize);
|
||||
outcount = osize;
|
||||
}
|
||||
|
||||
return(outcount);
|
||||
}
|
||||
|
9
VQ/VQM32/BCC32.CFG
Normal file
9
VQ/VQM32/BCC32.CFG
Normal file
@@ -0,0 +1,9 @@
|
||||
-c
|
||||
-3
|
||||
-d
|
||||
-H=c:\projects\vqm32\obj\headers.sym
|
||||
-wpro
|
||||
-weas
|
||||
-wpre
|
||||
-IC:\PROJECTS\INCLUDE;C:\DEV\BC4\INCLUDE;C:\DEV\TNT\INCLUDE
|
||||
-DPHARLAP_TNT=1
|
458
VQ/VQM32/CAPTOKEN.CPP
Normal file
458
VQ/VQM32/CAPTOKEN.CPP
Normal file
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* captoken.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Tokenize a caption script for playback processing.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* July 26, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "captoken.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* PRIVATE DECLARATIONS
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
#define STRING_LENGTH 256
|
||||
#define PADSIZE(size) (((size)+1)&(~1))
|
||||
|
||||
typedef enum {
|
||||
TOKEN_NULL = 0,
|
||||
TOKEN_BGCOL,
|
||||
TOKEN_FGCOL,
|
||||
TOKEN_XPOS,
|
||||
TOKEN_YPOS,
|
||||
TOKEN_ABS,
|
||||
TOKEN_LEFT,
|
||||
TOKEN_RIGHT,
|
||||
TOKEN_CENTER,
|
||||
TOKEN_FLASH,
|
||||
TOKEN_CPF,
|
||||
TOKEN_END
|
||||
} TokenTag;
|
||||
|
||||
typedef struct _Token {
|
||||
char *name;
|
||||
long tag;
|
||||
} Token;
|
||||
|
||||
/* Script tokens:
|
||||
* BG/BGCOL - Background pen color (EX: BG=<color name>)
|
||||
* FG/FGCOL - Foreground pen color (EX: FG=<color name>)
|
||||
* X/XPOS - X pixel position of text (EX: X=<pixel cord>)
|
||||
* Y/YPOS - Y pixel position of text (EX: Y=<pixel cord>)
|
||||
* ABS/ABSOLUTE - Absolute justification
|
||||
* LEFT - Left side justification
|
||||
* RIGHT - Right side justification
|
||||
* CENTER - Center justification
|
||||
* FLASH - Enable flashing of text
|
||||
* CPF - Print rate in characters per frame (EX: CPF=<rate>)
|
||||
* END - Terminate compilation of caption script
|
||||
*/
|
||||
Token tokens[] = {
|
||||
"BG", TOKEN_BGCOL,
|
||||
"BGCOL", TOKEN_BGCOL,
|
||||
"FG", TOKEN_FGCOL,
|
||||
"FGCOL", TOKEN_FGCOL,
|
||||
"X", TOKEN_XPOS,
|
||||
"XPOS", TOKEN_XPOS,
|
||||
"Y", TOKEN_YPOS,
|
||||
"YPOS", TOKEN_YPOS,
|
||||
"ABS", TOKEN_ABS,
|
||||
"ABSOLUTE", TOKEN_ABS,
|
||||
"LEFT", TOKEN_LEFT,
|
||||
"RIGHT", TOKEN_RIGHT,
|
||||
"CENTER", TOKEN_CENTER,
|
||||
"FLASH", TOKEN_FLASH,
|
||||
"CPF", TOKEN_CPF,
|
||||
"END", TOKEN_END,
|
||||
NULL, TOKEN_NULL,
|
||||
};
|
||||
|
||||
Token colors[] = {
|
||||
"BLACK", 0,
|
||||
"WHITE", 251,
|
||||
"RED", 252,
|
||||
"GREEN", 253,
|
||||
"SHADOW", 254,
|
||||
"CYCLE", 255,
|
||||
NULL, -1,
|
||||
};
|
||||
|
||||
/* Prototypes. */
|
||||
static long GetColorNum(char *name);
|
||||
static long IsNumeric(char *string);
|
||||
static void FormatString(char *string);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* BuildCaptions - Compile a caption script.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Size = BuildCaptions(Name, Buffer)
|
||||
*
|
||||
* long BuildCaptions(char *, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Generate a compiled caption script for use in VQA playback.
|
||||
*
|
||||
* INPUTS
|
||||
* Name - Name of caption script file to compile.
|
||||
* Buffer - Buffer to put compiled captions into.
|
||||
*
|
||||
* RESULT
|
||||
* Size - Size of compiled captions (in bytes).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long BuildCaptions(char *name, char *buffer)
|
||||
{
|
||||
FILE *fp;
|
||||
char *ptr;
|
||||
char *ptr1;
|
||||
long size = 0;
|
||||
long error;
|
||||
long i;
|
||||
long tag;
|
||||
CaptionText caption;
|
||||
char string[STRING_LENGTH];
|
||||
|
||||
/* Initialize the caption parameters. */
|
||||
memset(&caption, 0, sizeof(CaptionText));
|
||||
|
||||
/* Open the captions script file. */
|
||||
fp = fopen(name, "r");
|
||||
|
||||
if (fp != NULL) {
|
||||
error = 0;
|
||||
|
||||
while (!error) {
|
||||
if (fgets(string, STRING_LENGTH, fp) == NULL) {
|
||||
if (errno == 0) {
|
||||
error = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Replace the newline with a NULL terminator. */
|
||||
string[strlen(string) - 1] = 0;
|
||||
|
||||
/* Ignore comment lines. */
|
||||
if (string[0] == ';') continue;
|
||||
|
||||
ptr = strtok(string, "=");
|
||||
|
||||
if (ptr != NULL) {
|
||||
|
||||
/* Check for a comma */
|
||||
ptr1 = strchr(ptr, ',');
|
||||
|
||||
if (ptr1 != NULL) {
|
||||
*ptr1++ = 0;
|
||||
}
|
||||
|
||||
/* Is this a frame number. */
|
||||
if (IsNumeric(ptr) && IsNumeric(ptr1)) {
|
||||
i = atoi(ptr);
|
||||
|
||||
/* Frames must be defined in ascending order. */
|
||||
if ((unsigned short)i >= caption.OnFrame) {
|
||||
caption.OnFrame = i;
|
||||
caption.OffFrame = atoi(ptr1);
|
||||
caption.Size = sizeof(CaptionText);
|
||||
|
||||
/* Get caption text. */
|
||||
ptr = strtok(NULL, "");
|
||||
|
||||
if (ptr != NULL) {
|
||||
FormatString(ptr);
|
||||
i = strlen(ptr) + 1;
|
||||
caption.Size += PADSIZE(i);
|
||||
size += caption.Size;
|
||||
|
||||
/* Copy the caption structure. */
|
||||
memcpy(buffer, &caption, sizeof(CaptionText));
|
||||
buffer += sizeof(CaptionText);
|
||||
|
||||
/* Copy the caption text. */
|
||||
memcpy(buffer, ptr, i);
|
||||
buffer += i;
|
||||
|
||||
/* WORD align */
|
||||
if (PADSIZE(i) > i) {
|
||||
*buffer++ = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* Search for matching token. */
|
||||
tag = TOKEN_NULL;
|
||||
i = 0;
|
||||
|
||||
while (tokens[i].name != NULL) {
|
||||
if (strcmpi(tokens[i].name, ptr) == 0) {
|
||||
tag = tokens[i].tag;
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Get the data element. */
|
||||
ptr = strtok(NULL, "");
|
||||
|
||||
switch (tag) {
|
||||
case TOKEN_BGCOL:
|
||||
caption.BgPen = (char)GetColorNum(ptr);
|
||||
break;
|
||||
|
||||
case TOKEN_FGCOL:
|
||||
caption.FgPen = (char)GetColorNum(ptr);
|
||||
break;
|
||||
|
||||
case TOKEN_XPOS:
|
||||
caption.Xpos = (unsigned short)atoi(ptr);
|
||||
break;
|
||||
|
||||
case TOKEN_YPOS:
|
||||
caption.Ypos = (unsigned short)atoi(ptr);
|
||||
break;
|
||||
|
||||
case TOKEN_ABS:
|
||||
caption.Flags &= ~CTF_JUSTIFY;
|
||||
caption.Flags |= CTF_ABS;
|
||||
break;
|
||||
|
||||
case TOKEN_LEFT:
|
||||
caption.Flags &= ~CTF_JUSTIFY;
|
||||
caption.Flags |= CTF_LEFT;
|
||||
break;
|
||||
|
||||
case TOKEN_RIGHT:
|
||||
caption.Flags &= ~CTF_JUSTIFY;
|
||||
caption.Flags |= CTF_RIGHT;
|
||||
break;
|
||||
|
||||
case TOKEN_CENTER:
|
||||
caption.Flags &= ~CTF_JUSTIFY;
|
||||
caption.Flags |= CTF_CENTER;
|
||||
break;
|
||||
|
||||
case TOKEN_FLASH:
|
||||
if (strcmpi(ptr, "OFF") == 0) {
|
||||
caption.Flags &= ~CTF_FLASH;
|
||||
} else {
|
||||
caption.Flags |= CTF_FLASH;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_CPF:
|
||||
caption.CPF = (char)atoi(ptr);
|
||||
break;
|
||||
|
||||
/* Termination captions */
|
||||
case TOKEN_END:
|
||||
caption.Size = sizeof(CaptionText);
|
||||
caption.OnFrame = (unsigned short)-1;
|
||||
memcpy(buffer, &caption, sizeof(CaptionText));
|
||||
buffer += sizeof(CaptionText);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the script file. */
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return (size);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* GetColorNum - Get the color number from the color name.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Color = GetColorNum(Name)
|
||||
*
|
||||
* long GetColorNum(char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Look the color number that corresponds to the color name.
|
||||
*
|
||||
* INPUTS
|
||||
* Name - Name of color.
|
||||
*
|
||||
* RESULT
|
||||
* Color - Color number.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static long GetColorNum(char *name)
|
||||
{
|
||||
long color = -1;
|
||||
long i;
|
||||
|
||||
i = 0;
|
||||
|
||||
/* Scan for a matching name and return the corresponding color number. */
|
||||
while (colors[i].name != NULL) {
|
||||
if (strcmpi(colors[i].name, name) == 0) {
|
||||
color = colors[i].tag;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return (color);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* IsNumeric - Check if a string is numeric.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Condition = IsNumeric(String)
|
||||
*
|
||||
* long IsNumeric(char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Interogate the string to see if it represents a numeric value. Each
|
||||
* byte of the string must be between 0x30 and 0x39 inclusively.
|
||||
*
|
||||
* INPUTS
|
||||
* String - String to check.
|
||||
*
|
||||
* RESULT
|
||||
* Condition - 1 if numeric, 0 if not.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static long IsNumeric(char *string)
|
||||
{
|
||||
long flag = 1;
|
||||
|
||||
/* Ignore any proceeding sign designation. */
|
||||
if ((*string == '-') || (*string == '+')) {
|
||||
string++;
|
||||
}
|
||||
|
||||
/* Check to see if every byte in the string is a digit. */
|
||||
while (flag && (*string != 0)) {
|
||||
if (!isdigit(*string++)) {
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (flag);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* FormatString - Parse any format codes in the string.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* FormatString(String)
|
||||
*
|
||||
* void FormatString(char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Format a string with any embedded format commands contained in the
|
||||
* input string.
|
||||
*
|
||||
* Supported format commands:
|
||||
* /n - Insert carriage return. (0x0D)
|
||||
* /r - Insert carriage return. (0x0D)
|
||||
* // - Literal backslash.
|
||||
*
|
||||
* INPUTS
|
||||
* String - Pointer to string to format.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void FormatString(char *string)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
/* NULL strings are invalid. */
|
||||
if (string != NULL) {
|
||||
ptr = string;
|
||||
|
||||
/* Scan the string for embedded format commands. */
|
||||
while ((ptr = strchr(ptr, '/')) != NULL) {
|
||||
switch (*(ptr + 1)) {
|
||||
|
||||
/* Carriage return. */
|
||||
case 'n':
|
||||
case 'r':
|
||||
*ptr = 0x0D;
|
||||
break;
|
||||
|
||||
/* Literal backslash. */
|
||||
case '/':
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Remove the unwanted character. */
|
||||
strcpy((ptr + 1), (ptr + 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
80
VQ/VQM32/CAPTOKEN.H
Normal file
80
VQ/VQM32/CAPTOKEN.H
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMCAPTOKEN_H
|
||||
#define VQMCAPTOKEN_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* captoken.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Text caption script definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* July 26, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* CaptionText: This structure describes a line of text to be displayed
|
||||
* with the video/audio.
|
||||
*
|
||||
* Size - Size of caption in bytes.
|
||||
* OnFrame - Frame number to display caption.
|
||||
* OffFrame - Frame number to clear caption.
|
||||
* Flags - Display modifiers.
|
||||
* CPF - Characters to draw per frame.
|
||||
* Xpos - X pixel position to display caption.
|
||||
* Ypos - Y pixel position to display caption.
|
||||
* BgPen - Background pen to use.
|
||||
* FgPen - Foreground pen to use.
|
||||
* Text - Text string to display. (WORD aligned)
|
||||
*/
|
||||
typedef struct _CaptionText {
|
||||
unsigned short Size;
|
||||
unsigned short OnFrame;
|
||||
unsigned short OffFrame;
|
||||
unsigned char Flags;
|
||||
char CPF;
|
||||
unsigned short Xpos;
|
||||
unsigned short Ypos;
|
||||
char BgPen;
|
||||
char FgPen;
|
||||
char Text[];
|
||||
} CaptionText;
|
||||
|
||||
/* CaptionText flag definitions. */
|
||||
#define CTF_JUSTIFY (3<<0) /* Justification field. */
|
||||
#define CTF_ABS (0<<0) /* Use absolute X,Y positions. */
|
||||
#define CTF_CENTER (1<<0) /* Justify on Center */
|
||||
#define CTF_LEFT (2<<0) /* Justify on left */
|
||||
#define CTF_RIGHT (3<<0) /* Justify on right */
|
||||
#define CTF_FLASH (1<<4) /* Flash text. */
|
||||
|
||||
/* Function prototypes. */
|
||||
long BuildCaptions(char *name, char *buffer);
|
||||
|
||||
#endif /* VQMCAPTOKEN_H */
|
||||
|
76
VQ/VQM32/CHRWIDTH.CPP
Normal file
76
VQ/VQM32/CHRWIDTH.CPP
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* chrwidth.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Character pixel width.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* June 9, 1995
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* Char_Pixel_Width - Get the pixel width of a character.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "font.h"
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* Char_Pixel_Width - Get the pixel width of a character.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Width = Char_Pixel_Width(Character)
|
||||
*
|
||||
* long Char_Pixel_Width(char);
|
||||
*
|
||||
* FUNCTION
|
||||
* Gets the pixel width of the specified character.
|
||||
*
|
||||
* INPUTS
|
||||
* Character - Character to get the width for.
|
||||
*
|
||||
* RESULT
|
||||
* Width - Width in pixels.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
long cdecl __saveregs Char_Pixel_Width(char chr)
|
||||
#else
|
||||
#pragma saveregs
|
||||
long cdecl Char_Pixel_Width(char chr)
|
||||
#endif
|
||||
{
|
||||
return (*(FontWidthBlockPtr + chr) + FontXSpacing);
|
||||
}
|
59
VQ/VQM32/COMPRESS.H
Normal file
59
VQ/VQM32/COMPRESS.H
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMCOMP_H
|
||||
#define VQMCOMP_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* compress.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Compression definitions. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
unsigned long cdecl LCW_Compress(char const *source, char *dest,
|
||||
unsigned long length);
|
||||
unsigned long cdecl LCW_Uncompress(char const *source, char *dest,
|
||||
unsigned long length);
|
||||
long AudioZap(void *source, void *dest, long size);
|
||||
long cdecl AudioUnzap(void *source, void *dest, long);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VQMCOMP_H */
|
||||
|
133
VQ/VQM32/CRC.ASM
Normal file
133
VQ/VQM32/CRC.ASM
Normal file
@@ -0,0 +1,133 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* crc.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* CRC checksum calculation.
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Joe L. Bostic
|
||||
;*
|
||||
;* DATE
|
||||
;* January 26, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* Calculate_CRC - Calculate CRC checksum.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
CODESEG
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Calculate_CRC - Calculate CRC checksum.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* CRC = Calculate_CRC(Buffer, Length)
|
||||
;*
|
||||
;* long Calculate_CRC(void *, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Compute a CRC checksum for a block of memory.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Buffer - Pointer to buffer to calculate CRC for.
|
||||
;* Length - Length of buffer.
|
||||
;*
|
||||
;* RESULT
|
||||
;* CRC - CRC value.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Calculate_CRC:NEAR
|
||||
PROC Calculate_CRC C NEAR USES esi ebx ecx edx
|
||||
ARG buffer:NEAR PTR
|
||||
ARG length:DWORD
|
||||
|
||||
mov esi,[buffer]
|
||||
cld
|
||||
|
||||
; Clear CRC to default (NULL) value.
|
||||
xor ebx,ebx
|
||||
|
||||
mov ecx,[length] ;Get length of data block
|
||||
or ecx,ecx
|
||||
jz short ??fini
|
||||
|
||||
; Prepare the length counters.
|
||||
mov edx,ecx
|
||||
and dl,011b
|
||||
shr ecx,2
|
||||
|
||||
; Perform the bulk of the CRC scanning.
|
||||
or ecx,ecx
|
||||
jz 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
|
||||
|
||||
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 eax,ebx
|
||||
ret
|
||||
|
||||
ENDP Calculate_CRC
|
||||
|
||||
END
|
51
VQ/VQM32/CRC.H
Normal file
51
VQ/VQM32/CRC.H
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMCRC_H
|
||||
#define VQMCRC_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* CRC.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* CRC calculation definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Joe L. Bostic
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
long cdecl Calculate_CRC(void const *buffer, long length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VQMCRC_H */
|
395
VQ/VQM32/DRAWCHAR.ASM
Normal file
395
VQ/VQM32/DRAWCHAR.ASM
Normal file
@@ -0,0 +1,395 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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: U:\vq\projects\vqm32\drawchar.asv 1.1 08 May 1995 10:48:32 DENZIL_LONG $
|
||||
;***************************************************************************
|
||||
;** 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 : DRAWCHAR.ASM *
|
||||
;* *
|
||||
;* Programmer : Joe L. Bostic *
|
||||
;* *
|
||||
;* Start Date : August 20, 1993 *
|
||||
;* *
|
||||
;* Last Update : August 20, 1993 [JLB] *
|
||||
;* *
|
||||
;*-------------------------------------------------------------------------*
|
||||
;* Functions: *
|
||||
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
CODESEG
|
||||
|
||||
XPIXEL_MAX EQU 320
|
||||
YPIXEL_MAX EQU 200
|
||||
|
||||
FONTINFOBLOCK EQU 4
|
||||
FONTOFFSETBLOCK EQU 6
|
||||
FONTWIDTHBLOCK EQU 8
|
||||
FONTDATABLOCK EQU 10
|
||||
FONTHEIGHTBLOCK EQU 12
|
||||
|
||||
FONTINFOMAXHEIGHT EQU 4
|
||||
FONTINFOMAXWIDTH EQU 5
|
||||
|
||||
EXTRN FontPtr:NEAR PTR
|
||||
|
||||
;***********************************************************
|
||||
; DRAW_CHAR
|
||||
;
|
||||
; VOID Draw_Char(BYTE fontchar, WORD x_pixel, WORD y_pixel);
|
||||
;
|
||||
; Draws a character to the screen only if given coordinates that will allow
|
||||
; the entire character to be drawn on the screen else will exit.
|
||||
;
|
||||
; NOTE: This is a routine called by Text_Print.
|
||||
;
|
||||
;*
|
||||
GLOBAL C Draw_Char:NEAR
|
||||
PROC Draw_Char C NEAR USES eax ebx ecx edx esi edi
|
||||
ARG fontchar:DWORD
|
||||
ARG x_pixel:DWORD
|
||||
ARG y_pixel:DWORD
|
||||
|
||||
LOCAL infoblock:DWORD
|
||||
LOCAL offsetblock:DWORD
|
||||
LOCAL widthblock:DWORD
|
||||
LOCAL heightblock:DWORD
|
||||
LOCAL fwidth:DWORD
|
||||
LOCAL nextline:DWORD
|
||||
LOCAL startv:BYTE
|
||||
LOCAL dheight:BYTE
|
||||
LOCAL wheight:BYTE
|
||||
|
||||
mov esi,[FontPtr]
|
||||
|
||||
; Set up some working local variables.
|
||||
|
||||
xor eax,eax
|
||||
mov ax,[esi+FONTINFOBLOCK] ; get offset to info block
|
||||
mov [infoblock],eax ; save offset to info block
|
||||
mov ax,[esi+FONTOFFSETBLOCK] ; get offset to offset block
|
||||
mov [offsetblock],eax ; save offset to offset block
|
||||
mov ax,[esi+FONTWIDTHBLOCK] ; get offset to width block
|
||||
mov [widthblock],eax ; save offset to width block
|
||||
mov ax,[esi+FONTHEIGHTBLOCK] ; get offset to height block
|
||||
mov [heightblock],eax ; save offset to height block
|
||||
|
||||
; Fetch character data offset -- if NULL then undefined character.
|
||||
|
||||
mov ebx,[fontchar]
|
||||
and ebx,0FFh
|
||||
shl ebx,1 ; make word index
|
||||
add ebx,[offsetblock] ; add offset to offset block
|
||||
xor ecx,ecx
|
||||
mov cx,[esi+ebx] ; load offset to font data
|
||||
or ecx,ecx
|
||||
jz ??exit ; is this character a null? if so exit
|
||||
|
||||
; If the character is off the left/right edge of the screen then abort.
|
||||
|
||||
mov edx,[x_pixel]
|
||||
cmp edx,XPIXEL_MAX
|
||||
jae ??exit
|
||||
|
||||
; If the character is off the top/bottom edge of the screen then abort.
|
||||
|
||||
mov ebx,[fontchar] ; get char
|
||||
and ebx,0FFh
|
||||
add ebx,[widthblock] ; add offset to width block
|
||||
xor eax,eax
|
||||
mov al,[esi+ebx] ; get width for character
|
||||
mov [fwidth],eax ; save char width
|
||||
add eax,edx ; ax = char len + x
|
||||
cmp eax,XPIXEL_MAX
|
||||
ja ??exit
|
||||
|
||||
mov edi,edx ; save xpos in di
|
||||
|
||||
mov edx,[y_pixel]
|
||||
cmp edx,YPIXEL_MAX
|
||||
jae ??exit
|
||||
|
||||
mov ebx,[infoblock] ; get offset to offset block
|
||||
xor eax,eax
|
||||
; get font max height from info block
|
||||
mov al,[esi+ebx+FONTINFOMAXHEIGHT]
|
||||
mov [wheight],al ; save max height of character
|
||||
add eax,edx ; add height to y pos
|
||||
cmp eax,YPIXEL_MAX ; will it go off the bottom
|
||||
ja ??exit
|
||||
|
||||
??vdraw:
|
||||
mov ebx,[fontchar] ; get char
|
||||
and ebx,0FFh
|
||||
shl ebx,1 ; make 2 byte index
|
||||
add ebx,[heightblock] ; add offset to height block
|
||||
mov ah,[esi+ebx] ; get start vertical for character
|
||||
mov [startv],ah ; save start vertical for later
|
||||
mov al,[esi+ebx+1] ; get data height for character
|
||||
mov [dheight],al ; save data height for later
|
||||
add ah,al ; add background and data
|
||||
sub [wheight],ah ; remaining background height
|
||||
|
||||
add esi,ecx ; add font offset to font data
|
||||
|
||||
push edx
|
||||
mov eax,XPIXEL_MAX
|
||||
mul edx
|
||||
add edi,eax
|
||||
pop edx
|
||||
|
||||
mov eax,XPIXEL_MAX
|
||||
sub eax,[fwidth]
|
||||
mov [nextline],eax ; ?? to add to index for the nextline
|
||||
|
||||
add edi,0A0000h
|
||||
mov ebx,OFFSET ColorXlat ; setup up bx for xlat commands
|
||||
xor ecx,ecx
|
||||
mov cl,[startv] ; number of scan lines that are
|
||||
; background color
|
||||
or ecx,ecx ; if starting vertical is zero
|
||||
je short ??skiplead ; skip drawing top background lines
|
||||
|
||||
mov al,0
|
||||
xlat [ebx] ; get background color
|
||||
|
||||
or al,al ; check for none zero color
|
||||
jne short ??lheight ; update background color
|
||||
|
||||
push edx
|
||||
mov eax,XPIXEL_MAX
|
||||
mul ecx
|
||||
add edi,eax
|
||||
pop edx
|
||||
|
||||
mov ebx,OFFSET ColorXlat ; restore bx for xlat commands
|
||||
jmp SHORT ??skiplead
|
||||
|
||||
??lheight:
|
||||
mov edx,[fwidth] ; width of char
|
||||
|
||||
??lwidth:
|
||||
stosb ; write out line of pixels for width
|
||||
dec edx
|
||||
jne ??lwidth
|
||||
|
||||
??lnext:
|
||||
add edi,[nextline] ; goto next line at the start of char
|
||||
loop ??lheight ; any more lines
|
||||
|
||||
??skiplead:
|
||||
mov cl,[dheight] ; number of scan lines that are data
|
||||
or ecx,ecx ; is there any data to be drawn
|
||||
je short ??exit
|
||||
|
||||
??vheight:
|
||||
mov edx,[fwidth] ; width of char
|
||||
|
||||
??vwidth:
|
||||
lodsb ; get byte value from font data
|
||||
mov ah,al ; save hinibble
|
||||
and al,00FH ; get lonibble
|
||||
xlat [ebx] ; get new color
|
||||
or al,al
|
||||
je short ??chklowidth ; skip color zero
|
||||
|
||||
mov [edi],al ; write out pixel of lonibble
|
||||
|
||||
??chklowidth:
|
||||
inc edi
|
||||
dec edx
|
||||
je short ??vnext ; check if done with width of char
|
||||
|
||||
mov al,ah ; get byte value
|
||||
and al,0F0H ; get hinibble
|
||||
xlat [ebx] ; get new color
|
||||
or al,al
|
||||
je short ??chkhiwidth ; skip color zero
|
||||
|
||||
mov [edi],al ; write out pixel of hinibble
|
||||
|
||||
??chkhiwidth:
|
||||
inc edi
|
||||
dec edx
|
||||
jne ??vwidth ; check if done with width of char
|
||||
|
||||
??vnext:
|
||||
add edi,[nextline] ; next line at start of char
|
||||
loop ??vheight ; any more lines
|
||||
|
||||
|
||||
??trail:
|
||||
mov cl,[wheight] ; remaining height of background color
|
||||
or ecx,ecx ; if trailing height is zero
|
||||
jle short ??exit ; skip drawing bottom background lines
|
||||
|
||||
mov al,0
|
||||
xlat [ebx] ; get background color
|
||||
or al,al ; check for color zero
|
||||
je short ??exit ; skip drawing
|
||||
|
||||
??theight:
|
||||
mov edx,[fwidth] ; width of char
|
||||
|
||||
??twidth:
|
||||
stosb ; write out line of pixels for width
|
||||
dec edx
|
||||
jne ??twidth
|
||||
|
||||
??tnext:
|
||||
add edi,[nextline] ; next line at start of char
|
||||
loop ??theight ; any more lines
|
||||
|
||||
|
||||
??exit:
|
||||
ret
|
||||
|
||||
ENDP Draw_Char
|
||||
|
||||
;***********************************************************
|
||||
|
||||
|
||||
;***********************************************************
|
||||
; SET_FONT_PALETTE_RANGE
|
||||
;
|
||||
; VOID Set_Font_Palette_Range(VOID *palette, WORD start, WORD end);
|
||||
;
|
||||
; This routine changes the local Draw_Char color translation table
|
||||
; with the color numbers in palette.
|
||||
;
|
||||
; Bounds Checking: forces start and end to a range of 0-15
|
||||
;*
|
||||
GLOBAL C Set_Font_Palette_Range:NEAR
|
||||
PROC Set_Font_Palette_Range C NEAR USES eax ebx ecx edi esi
|
||||
ARG palette:NEAR PTR
|
||||
ARG start:DWORD
|
||||
ARG endval:DWORD
|
||||
|
||||
cld
|
||||
mov esi,[palette]
|
||||
mov ebx,[start]
|
||||
and ebx,0FH ; value 0-15
|
||||
|
||||
mov ecx,[endval]
|
||||
and ecx,0FH ; value 0-15
|
||||
|
||||
cmp ecx,ebx ; if end < start then exit
|
||||
jl short ??exit
|
||||
|
||||
sub ecx,ebx ; number of colors = end - start + 1
|
||||
inc ecx
|
||||
|
||||
mov edi,OFFSET ColorXlat ; get start of xlat table
|
||||
add edi,ebx ; add starting offset
|
||||
shl ebx,4 ; multiply start offset by 16
|
||||
add ebx,OFFSET ColorXlat ; add start of xlat table
|
||||
|
||||
; updates 0-15 for lonibble xlat
|
||||
; updates 0,16,32,...,240 for hinibble xlat
|
||||
|
||||
??setpal:
|
||||
lodsb ; get color number
|
||||
stosb ; save color number for lonibble xlat
|
||||
mov [ebx],al ; save color number for hinibble xlat
|
||||
add ebx,010H ; add 16 to index for hinibble offset
|
||||
loop ??setpal
|
||||
|
||||
??exit:
|
||||
ret
|
||||
|
||||
ENDP Set_Font_Palette_Range
|
||||
|
||||
;***********************************************************
|
||||
|
||||
|
||||
;***********************************************************
|
||||
; DRAW_CHAR_SETUP
|
||||
;
|
||||
; VOID Draw_Char_Setup(VOID);
|
||||
;
|
||||
; This routine sets up code segment variables for Draw_Char.
|
||||
;
|
||||
; NOTE: This is a routine called by Set_Font.
|
||||
;
|
||||
;*
|
||||
GLOBAL C Draw_Char_Setup:NEAR
|
||||
PROC Draw_Char_Setup C NEAR
|
||||
|
||||
ret
|
||||
|
||||
ENDP Draw_Char_Setup
|
||||
|
||||
DATASEG
|
||||
|
||||
ColorXlat DB 000H,001H,002H,003H,004H,005H,006H,007H
|
||||
DB 008H,009H,00AH,00BH,00CH,00DH,00EH,00FH
|
||||
|
||||
DB 001H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 002H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 003H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 004H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 005H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 006H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 007H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 008H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 009H,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00AH,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00BH,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00CH,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00DH,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00EH,000H,000H,000H,000H,000H,000H,000H
|
||||
DB 000H,000H,000H,000H,000H,000H,000H,000H
|
||||
|
||||
DB 00FH
|
||||
|
||||
;***********************************************************
|
||||
END
|
||||
|
216
VQ/VQM32/FILLRECT.ASM
Normal file
216
VQ/VQM32/FILLRECT.ASM
Normal 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* fillrect.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* Rectangle rendering.
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Joe L. Bostic
|
||||
;*
|
||||
;* DATE
|
||||
;* Febuary 8, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* Fill_Rect - Draw a filled rectangle.
|
||||
;* Eor_Region - Hilights or unhilights a region by EOR it.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
CODESEG
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Eor_Region - Hilights or unhilights a region by EOR it.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Eor_Region(X1, Y1, X2, Y2, Color)
|
||||
;*
|
||||
;* void Eor_Region(long, long, long, long, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* X1 - Starting X position.
|
||||
;* Y1 - Starting Y position.
|
||||
;* X2 - Ending X position.
|
||||
;* Y2 - Ending Y position.
|
||||
;* Color - Color to EOR.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Eor_Region:NEAR
|
||||
PROC Eor_Region C NEAR USES eax ebx ecx edx edi
|
||||
ARG x1_pixel:DWORD
|
||||
ARG y1_pixel:DWORD
|
||||
ARG x2_pixel:DWORD
|
||||
ARG y2_pixel:DWORD
|
||||
ARG color:DWORD
|
||||
LOCAL eorit:DWORD
|
||||
|
||||
mov [eorit],1
|
||||
jmp short Fill_Rect_Entry
|
||||
|
||||
ENDP Eor_Region
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Fill_Rect - Draw a filled rectangle.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Fill_Rect(X1, Y1, X2, Y2, Color)
|
||||
;*
|
||||
;* void Fill_Rect(long, long, long, long, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Fill a rectangle area with a specified color.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* X1 - Starting X position.
|
||||
;* Y1 - Starting Y position.
|
||||
;* X2 - Ending X position.
|
||||
;* Y2 - Ending Y position.
|
||||
;* Color - Color to draw rectangle
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Fill_Rect:NEAR
|
||||
PROC Fill_Rect C NEAR USES eax ebx ecx edx edi
|
||||
ARG x1_pixel:DWORD
|
||||
ARG y1_pixel:DWORD
|
||||
ARG x2_pixel:DWORD
|
||||
ARG y2_pixel:DWORD
|
||||
ARG color:DWORD
|
||||
LOCAL eorit:DWORD
|
||||
|
||||
mov [eorit],0
|
||||
|
||||
Fill_Rect_Entry:
|
||||
cld ; always go forward
|
||||
mov edi,0A0000h
|
||||
|
||||
; Verify bounds of x1_pixel.
|
||||
mov eax,[x1_pixel]
|
||||
cmp eax,320 ;XPIXEL_MAX
|
||||
jae short ??exit
|
||||
|
||||
; Verify bounds of x2_pixel.
|
||||
mov ebx,[x2_pixel]
|
||||
cmp ebx,320 ;XPIXEL_MAX
|
||||
jae short ??exit
|
||||
|
||||
; Backward rectangles are legal -- adjust for it.
|
||||
cmp eax,ebx
|
||||
jbe short ??okx
|
||||
xchg eax,ebx
|
||||
??okx:
|
||||
|
||||
; Verify bounds of y1_pixel.
|
||||
mov ecx,[y1_pixel]
|
||||
cmp ecx,200 ;YPIXEL_MAX
|
||||
jae short ??exit
|
||||
|
||||
; Verify bounds of y2_pixel.
|
||||
mov edx,[y2_pixel]
|
||||
cmp edx,200 ;YPIXEL_MAX
|
||||
jae short ??exit
|
||||
|
||||
; Backward rectangles are legal -- adjust for it.
|
||||
cmp ecx,edx
|
||||
jbe short ??oky
|
||||
xchg ecx,edx
|
||||
??oky:
|
||||
|
||||
; Set DX for height and BX for width.
|
||||
sub edx,ecx
|
||||
inc edx
|
||||
sub ebx,eax
|
||||
inc ebx
|
||||
|
||||
; Adjust DI to match offset into page of upper left corner.
|
||||
push edx
|
||||
push eax
|
||||
mov eax,320 ;XPIXEL_MAX
|
||||
mul ecx
|
||||
add edi,eax ; Add in Y offset.
|
||||
pop edx
|
||||
add edi,edx ; Add in X offset.
|
||||
pop edx
|
||||
|
||||
; Fill the region with the specified color.
|
||||
mov eax,320 ;XPIXEL_MAX
|
||||
sub eax,ebx
|
||||
xchg eax,[color]
|
||||
mov ah,al
|
||||
cmp [eorit],0
|
||||
je short ??loop
|
||||
|
||||
;------ EOR rectangle filling.
|
||||
??loop2:
|
||||
mov ecx,ebx ; Length of row
|
||||
??loop2in:
|
||||
lodsb
|
||||
xor al,ah
|
||||
stosb
|
||||
loop ??loop2in
|
||||
add edi,[color] ; Modulo add for next line prep.
|
||||
dec edx
|
||||
jg short ??loop2
|
||||
jmp short ??exit
|
||||
|
||||
;------ Conventional rectangle filling.
|
||||
??loop:
|
||||
mov ecx,ebx ; Length of row
|
||||
shr ecx,1
|
||||
rep stosw
|
||||
adc ecx,0
|
||||
rep stosb
|
||||
add edi,[color] ; Modulo add for next line prep.
|
||||
dec edx
|
||||
jg short ??loop
|
||||
|
||||
??exit:
|
||||
ret
|
||||
|
||||
ENDP Fill_Rect
|
||||
|
||||
END
|
||||
|
222
VQ/VQM32/FONT.CPP
Normal file
222
VQ/VQM32/FONT.CPP
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* font.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Font manipulation.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* March 9, 1995
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* Load_Font - Open a font for use.
|
||||
* Set_Font - Set the default system font.
|
||||
* String_Pixel_Width - Get the pixel width of a string.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include "font.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* PRIVATE DECLARATIONS
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/* min and max macros */
|
||||
#ifdef __cplusplus
|
||||
#ifndef max
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef min
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void const *FontPtr = NULL;
|
||||
char FontHeight = 8;
|
||||
char FontWidth = 8;
|
||||
int FontXSpacing = 0;
|
||||
int FontYSpacing = 0;
|
||||
char *FontWidthBlockPtr = NULL;
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* Load_Font - Open a font for use.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Font = Load_Font(Name)
|
||||
*
|
||||
* char *Load_Font(char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Open a graphics font for use by Text_Print(). Use free() to dispose
|
||||
* of the font.
|
||||
*
|
||||
* INPUTS
|
||||
* Name - Name of font file to open.
|
||||
*
|
||||
* RESULT
|
||||
* Font - Pointer to font, NULL if error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void *cdecl Load_Font(char const *name)
|
||||
{
|
||||
Font *font = NULL;
|
||||
long fh;
|
||||
short size;
|
||||
short valid;
|
||||
|
||||
/* Open the font. */
|
||||
if ((fh = open(name, (O_RDONLY|O_BINARY))) != -1) {
|
||||
|
||||
/* Get the size of the font. */
|
||||
if (read(fh, &size, 2) == 2) {
|
||||
|
||||
/* Allocate memory to contain the font. */
|
||||
if ((font = (Font *)malloc((unsigned long)size)) != NULL) {
|
||||
valid = 0;
|
||||
|
||||
/* Read in the body of the font. */
|
||||
if (read(fh, &font->CompMethod, (unsigned long)(size - 2))
|
||||
== (unsigned long)(size - 2)) {
|
||||
|
||||
/* Verify the validity of the font. */
|
||||
if ((font->CompMethod == 0) && (font->NumBlks == 5)) {
|
||||
font->Size = size;
|
||||
valid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the font if it is not valid. */
|
||||
if (valid == 0) {
|
||||
free(font);
|
||||
font = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the font. */
|
||||
close(fh);
|
||||
}
|
||||
|
||||
return ((char *)font);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* Set_Font - Set the default system font.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* OldFont = Set_Font(Font)
|
||||
*
|
||||
* char *Set_Font(char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Sets up the specified font as the default font used by the system.
|
||||
*
|
||||
* INPUTS
|
||||
* Font - Pointer to Font to set as default. (NULL returns current font)
|
||||
*
|
||||
* RESULT
|
||||
* OldFont - Previous font.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void *cdecl Set_Font(void const *font)
|
||||
{
|
||||
void const *oldfont;
|
||||
FontInfo *fi;
|
||||
|
||||
oldfont = FontPtr;
|
||||
|
||||
if (font != NULL) {
|
||||
FontWidthBlockPtr = ((char *)font + ((Font *)font)->WidthBlk);
|
||||
fi = (FontInfo *)((char *)font + ((Font *)font)->InfoBlk);
|
||||
FontHeight = fi->MaxHeight;
|
||||
FontWidth = fi->MaxWidth;
|
||||
FontPtr = font;
|
||||
}
|
||||
|
||||
return ((void *)oldfont);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* String_Pixel_Width - Get the pixel width of a string.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Width = String_Pixel_Width(String)
|
||||
*
|
||||
* long String_Pixel_Width(char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Calculates the pixel width of a string of characters.
|
||||
*
|
||||
* INPUTS
|
||||
* String - Pointer to string to calculate width for.
|
||||
*
|
||||
* RESULT
|
||||
* Width - Width of string in pixels.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
unsigned short String_Pixel_Width(char const *string)
|
||||
{
|
||||
long width = 0;
|
||||
long largest = 0;
|
||||
|
||||
while (*string != NULL) {
|
||||
if (*string == '\r') {
|
||||
string++;
|
||||
largest = max(largest, width);
|
||||
width = 0;
|
||||
} else {
|
||||
width += Char_Pixel_Width(*string++);
|
||||
}
|
||||
}
|
||||
|
||||
largest = max(largest, width);
|
||||
|
||||
return (largest);
|
||||
}
|
||||
|
105
VQ/VQM32/FONT.H
Normal file
105
VQ/VQM32/FONT.H
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMFONT_H
|
||||
#define VQMFONT_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* font.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Font definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* March 9, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Font: A Westwood style font.
|
||||
*
|
||||
* Size - Size of font.
|
||||
* CompMethod - Compression method of font. (0 = none)
|
||||
* NumBlks - Number of data blocks.
|
||||
* InfoBlk - Offset to font information block.
|
||||
* OffsetBlk - Offset to character offset block.
|
||||
* WidthBlk - Offset to character width block.
|
||||
* DataBlk - Offset to character data block.
|
||||
* HeightBlk - Offset to character height block.
|
||||
*/
|
||||
typedef struct _Font {
|
||||
unsigned short Size;
|
||||
unsigned char CompMethod;
|
||||
unsigned char NumBlks;
|
||||
unsigned short InfoBlk;
|
||||
unsigned short OffsetBlk;
|
||||
unsigned short WidthBlk;
|
||||
unsigned short DataBlk;
|
||||
unsigned short HeightBlk;
|
||||
} Font;
|
||||
|
||||
typedef struct _FontInfo {
|
||||
long huh;
|
||||
unsigned char MaxHeight;
|
||||
unsigned char MaxWidth;
|
||||
} FontInfo;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void const *FontPtr;
|
||||
extern int FontXSpacing;
|
||||
extern int FontYSpacing;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern char FontWidth;
|
||||
extern char FontHeight;
|
||||
extern char *FontWidthBlockPtr;
|
||||
|
||||
/* Function prototypes. */
|
||||
void *cdecl Load_Font(char const *name);
|
||||
void *cdecl Set_Font(void const *font);
|
||||
unsigned short cdecl String_Pixel_Width(char const *string);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
long cdecl __saveregs Char_Pixel_Width(char chr);
|
||||
#else
|
||||
long cdecl Char_Pixel_Width(char chr);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VQMFONT_H */
|
||||
|
55
VQ/VQM32/GRAPHICS.H
Normal file
55
VQ/VQM32/GRAPHICS.H
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMGRAPHICS_H
|
||||
#define VQMGRAPHICS_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* graphics.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Graphic rendering and manipulation definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* April 27, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cdecl Eor_Region(long sx, long sy, long dx, long dy, long color);
|
||||
void cdecl Fill_Rect(long x1, long y1, long x2, long y2, long color);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VQMGRAPHICS_H */
|
||||
|
708
VQ/VQM32/HUFFCMP.CPP
Normal file
708
VQ/VQM32/HUFFCMP.CPP
Normal file
@@ -0,0 +1,708 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* huffcmp.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Huffman order 0 compressor.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* May 19, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* HuffCompress - Compress data using huffman order 0 compression.
|
||||
* HuffCount - Count the frequency of occurence of every byte.
|
||||
* HuffScaleCounts - Scale down the frequency counts.
|
||||
* RLEHuffCounts - Run Length Encode the Huffman counts.
|
||||
* ConvertToCodes - Convert the Huffman tree into a table of codes.
|
||||
* HuffEncode - Huffman encode the data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <mem.h>
|
||||
#include "huffman.h"
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* HuffCompress - Compress data using huffman order 0 compression.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Size = HuffCompress(Data, Buffer, Size, Temp)
|
||||
*
|
||||
* long HuffCompress(unsigned char *, unsigned char *, long, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* This function performs an order 0 Huffman encoding of the input data.
|
||||
* The algorithm used is fairly straightforward. First a count is made of
|
||||
* all the bytes in the input data, then the counts are scaled down to
|
||||
* a single byte representation in the node array. After the counts are
|
||||
* scaled, a Huffman decoding tree is built from the node array. Then
|
||||
* a code array is built by traversing the tree for each symbol. Finally,
|
||||
* the input data is compressed.
|
||||
*
|
||||
* INPUTS
|
||||
* Data - Pointer to data to compress.
|
||||
* Buffer - Pointer to compressed data.
|
||||
* Size - Length of data to compress.
|
||||
* Temp - Pointer to temporary working buffer. (Must be >= 5120 bytes!)
|
||||
*
|
||||
* RESULT
|
||||
* Size - Compressed size.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long cdecl HuffCompress(unsigned char *data, unsigned char *buffer,
|
||||
long length, char *temp)
|
||||
{
|
||||
#if(1)
|
||||
TreeNode *nodes;
|
||||
HuffCode *codes;
|
||||
long size;
|
||||
long root;
|
||||
|
||||
/* Initialize variables */
|
||||
nodes = (TreeNode *)temp;
|
||||
temp += (514 * sizeof(TreeNode));
|
||||
codes = (HuffCode *)temp;
|
||||
|
||||
/* Analyze the frequency of the data. */
|
||||
HuffCount(data, nodes, length, 1);
|
||||
HuffScaleCounts(nodes);
|
||||
|
||||
/* Save the counts for the decompression. */
|
||||
size = RLEHuffCounts(nodes, buffer);
|
||||
buffer += size;
|
||||
|
||||
/* Build the Huffman decode tree and generate codes for encoding. */
|
||||
root = BuildHuffTree(nodes);
|
||||
ConvertToCodes(nodes, codes, 0, 0, root);
|
||||
|
||||
/* Encode the data. */
|
||||
size += HuffEncode(data, buffer, codes, length);
|
||||
|
||||
return (size);
|
||||
#else
|
||||
TreeNode *nodes;
|
||||
HuffCode *codes;
|
||||
unsigned long *counts;
|
||||
unsigned long max_count;
|
||||
long i;
|
||||
long size;
|
||||
long first;
|
||||
long last;
|
||||
long next;
|
||||
unsigned long symbol;
|
||||
unsigned long mask;
|
||||
|
||||
/* Initialize variables. */
|
||||
nodes = (TreeNode *)temp;
|
||||
temp += (514 * sizeof(TreeNode));
|
||||
counts = (unsigned long *)temp;
|
||||
codes = (HuffCode *)temp;
|
||||
|
||||
/* Zero the initial counts. */
|
||||
memset(temp, 0, 256 * sizeof(unsigned long));
|
||||
size = 0;
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Calculate the distribution of the data then scale down the counts so
|
||||
* they fit in an 8 bit value. This is done in order to limit the size of
|
||||
* the codes to 16 bits.
|
||||
*-----------------------------------------------------------------------*/
|
||||
i = 0;
|
||||
|
||||
while (i < length) {
|
||||
counts[((unsigned char *)data)[i]]++;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Scale down the counts. */
|
||||
max_count = 0;
|
||||
|
||||
/* Find the maximum count. */
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (counts[i] > max_count) {
|
||||
max_count = counts[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (max_count == 0) {
|
||||
counts[0] = 1;
|
||||
max_count = 1;
|
||||
}
|
||||
|
||||
max_count /= 255;
|
||||
max_count++;
|
||||
|
||||
/* Scale down the counts. */
|
||||
for (i = 0; i < 256; i++) {
|
||||
nodes[i].count = (unsigned long)(counts[i] / max_count);
|
||||
|
||||
/* Make sure that a node with a non-zero count does not get scaled
|
||||
* down to zero.
|
||||
*/
|
||||
if ((nodes[i].count == 0) && (counts[i] != 0)) {
|
||||
nodes[i].count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
nodes[HUFF_EOS].count = 1;
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* OUTPUT THE COUNTS
|
||||
*
|
||||
* In order to save space, we store runs of counts in the following format:
|
||||
*
|
||||
* Start, Stop, Counts..., Start, Stop, Counts..., ..., 0
|
||||
*
|
||||
* The list is terminated by storing a start value of zero (0).
|
||||
*
|
||||
* In order to efficiently use this format, we do not want to stop a run
|
||||
* because of just one or two zero counts. So we include zero counts of
|
||||
* less than three (3) in the run.
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Find the first occurance of a non-zero count. */
|
||||
first = 0;
|
||||
|
||||
while ((first < 255) && (nodes[first].count == 0)) {
|
||||
first++;
|
||||
}
|
||||
|
||||
/* Each time I hit the start of the loop, I assume that first is the
|
||||
* number for a run of non-zero values. The rest of the loop is
|
||||
* concerned with finding the value for last, which is the end of the
|
||||
* run, and the value of next, which is the start of the next run.
|
||||
* At the end of the loop, I assign next to first, so it starts in on
|
||||
* the next run.
|
||||
*/
|
||||
for (; first < 256; first = next) {
|
||||
last = first + 1;
|
||||
|
||||
for (;;) {
|
||||
|
||||
/* Find the end of the run of non-zeros. */
|
||||
for (; last < 256; last++) {
|
||||
if (nodes[last].count == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
last--;
|
||||
|
||||
/* Check the beginning of the next run of non-zero counts. */
|
||||
for (next = last + 1; next < 256; next++) {
|
||||
if (nodes[next].count != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Quit the run if we have reached the end. */
|
||||
if (next > 255) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Quit the run if there is more than three non-zero counts. */
|
||||
if ((next - last) > 3) {
|
||||
break;
|
||||
}
|
||||
|
||||
last = next;
|
||||
};
|
||||
|
||||
/* Output Start and Stop. */
|
||||
*buffer++ = first;
|
||||
*buffer++ = last;
|
||||
|
||||
/* Output the run of counts. */
|
||||
for (i = first; i <= last; i++) {
|
||||
*buffer++ = (char)nodes[i].count;
|
||||
}
|
||||
|
||||
size += (((last - first) + 1) + 2);
|
||||
}
|
||||
|
||||
/* Output terminator. */
|
||||
*buffer++ = 0;
|
||||
size++;
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Build the Huffman tree. All active nodes are scanned in order to locate
|
||||
* the two nodes with the minimum weights. These two weights are added
|
||||
* together and assigned to a new node. The new node makes the two minimum
|
||||
* nodes into its 0 child and 1 child. The two minimum nodes are then
|
||||
* marked as inactive. This process repeats until their is only one node
|
||||
* left, which is the root node.
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Node 513 is used to arbitratilly provide a node with a guaranteed
|
||||
* maximum value.
|
||||
*/
|
||||
nodes[513].count = 0xFFFF;
|
||||
|
||||
for (next = (HUFF_EOS + 1); ; next++) {
|
||||
first = 513;
|
||||
last = 513;
|
||||
|
||||
for (i = 0; i < next; i++) {
|
||||
|
||||
/* We are only concerned with non-zero count nodes. */
|
||||
if (nodes[i].count != 0) {
|
||||
if (nodes[i].count < nodes[first].count) {
|
||||
last = first;
|
||||
first = i;
|
||||
} else if (nodes[i].count < nodes[last].count) {
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (last == 513) {
|
||||
break;
|
||||
}
|
||||
|
||||
nodes[next].count = (nodes[first].count + nodes[last].count);
|
||||
nodes[first].count = 0;
|
||||
nodes[last].count = 0;
|
||||
nodes[next].child0 = (first << 3);
|
||||
nodes[next].child1 = (last << 3);
|
||||
}
|
||||
|
||||
next--;
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Convert the Huffman tree into an encoding table then encode the data.
|
||||
*-----------------------------------------------------------------------*/
|
||||
ConvertToCodes(nodes, codes, 0, 0, (next << 3));
|
||||
|
||||
/* Encode the data. */
|
||||
*buffer = 0;
|
||||
next = 0x80;
|
||||
i = 0;
|
||||
|
||||
do {
|
||||
if (i < length) {
|
||||
symbol = ((unsigned char *)data)[i];
|
||||
} else {
|
||||
symbol = HUFF_EOS;
|
||||
}
|
||||
|
||||
mask = 1L << (codes[symbol].bits - 1);
|
||||
|
||||
while (mask != 0) {
|
||||
|
||||
/* Set a bit in the output stream for each bit in the code. */
|
||||
if (mask & codes[symbol].code) {
|
||||
*buffer |= next;
|
||||
}
|
||||
|
||||
/* Next bit position. */
|
||||
next >>= 1;
|
||||
|
||||
/* Advance to the next byte in the output stream when the current
|
||||
* byte is full.
|
||||
*/
|
||||
if (next == 0) {
|
||||
buffer++;
|
||||
*buffer = 0;
|
||||
next = 0x80;
|
||||
size++;
|
||||
}
|
||||
|
||||
/* Next bit in the code. */
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
i++;
|
||||
} while (symbol != HUFF_EOS);
|
||||
|
||||
if (next != 0x80) {
|
||||
size++;
|
||||
}
|
||||
|
||||
return (size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* HuffCount - Count the frequency of occurence of every byte.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* HuffCount(Data, Nodes, Length, Zero)
|
||||
*
|
||||
* void HuffCounts(unsigned char *, TreeNode *, long, long);
|
||||
*
|
||||
* FUNCTION
|
||||
* This function counts the frequency of occurence of every byte in the
|
||||
* input data. The nodes must be initialized to zero prior to calling this
|
||||
* function for the first time, otherwise the counts will be flawed.
|
||||
*
|
||||
* INPUTS
|
||||
* Data - Pointer to data to analyze.
|
||||
* TreeNode - Pointer to array of nodes.
|
||||
* Length - Length of data to analyze.
|
||||
* Zero - Zero any previous counts flag. (TRUE = zero counts)
|
||||
*
|
||||
* RESULT
|
||||
* Size - Amount of buffer used to hold counts.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void cdecl HuffCount(unsigned char *data, TreeNode *nodes, long length,
|
||||
long zero)
|
||||
{
|
||||
long i;
|
||||
|
||||
/* Zero any previous counts. */
|
||||
if (zero) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
nodes[i].count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the distribution of the data. */
|
||||
i = 0;
|
||||
|
||||
while (i < length) {
|
||||
nodes[((unsigned char *)data)[i]].count++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* HuffScaleCounts - Scale down the frequency counts.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* HuffScaleCounts(Nodes)
|
||||
*
|
||||
* void HuffScaleCounts(TreeNode *);
|
||||
*
|
||||
* FUNCTION
|
||||
* In order to limit the size of the Huffman codes to 16 bits, we must
|
||||
* scale down the counts so they can be represented by a BYTE size value.
|
||||
*
|
||||
* INPUTS
|
||||
* Nodes - Pointer to nodes to scale counts for.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void cdecl HuffScaleCounts(TreeNode *nodes)
|
||||
{
|
||||
unsigned long max_count;
|
||||
unsigned long unscaled;
|
||||
long i;
|
||||
long first;
|
||||
long last;
|
||||
long next;
|
||||
|
||||
/* Scale down the counts so they fit in an 8 bit value. This is done in
|
||||
* order to limit the size of the codes to 16 bits.
|
||||
*/
|
||||
max_count = 0;
|
||||
|
||||
/* Find the maximum count. */
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (nodes[i].count > max_count) {
|
||||
max_count = nodes[i].count;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_count == 0) {
|
||||
nodes[0].count = 1;
|
||||
max_count = 1;
|
||||
}
|
||||
|
||||
max_count /= 255;
|
||||
max_count++;
|
||||
|
||||
/* Scale down the counts. */
|
||||
for (i = 0; i < 256; i++) {
|
||||
unscaled = nodes[i].count;
|
||||
nodes[i].count /= max_count;
|
||||
|
||||
/* Make sure that a node with a non-zero count does not get scaled
|
||||
* down to zero.
|
||||
*/
|
||||
if ((nodes[i].count == 0) && (unscaled != 0)) {
|
||||
nodes[i].count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
nodes[HUFF_EOS].count = 1;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* RLEHuffCounts - Run Length Encode the Huffman counts.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Size = RLEHuffCounts(Nodes, Buffer)
|
||||
*
|
||||
* long RLEHuffCounts(TreeNode *, unsigned char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* In order for the decoder to build the same model, we have to transmit
|
||||
* the symbol counts to it. To save space we do not save all 256 symbols
|
||||
* unconditionally, instead we run length encode the counts. The format
|
||||
* used to store the counts is as follows:
|
||||
*
|
||||
* Start, Stop, Counts[n], Start, Stop, Counts[n], .... 0
|
||||
*
|
||||
* Note: The sequence is terminated by a start value of 0. Also at least
|
||||
* 1 run of counts has to be stored, even if the first start value is 0.
|
||||
*
|
||||
* INPUTS
|
||||
* Nodes - Pointer to initialized nodes.
|
||||
* Buffer - Pointer to buffer to store RLE'd counts.
|
||||
*
|
||||
* RESULT
|
||||
* Size - Size of the RLE'd counts.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long cdecl RLEHuffCounts(TreeNode *nodes, unsigned char *buffer)
|
||||
{
|
||||
long i;
|
||||
long first;
|
||||
long last;
|
||||
long next;
|
||||
long size = 0;
|
||||
|
||||
/* Find the first occurance of a non-zero count. */
|
||||
first = 0;
|
||||
|
||||
while ((first < 255) && (nodes[first].count == 0)) {
|
||||
first++;
|
||||
}
|
||||
|
||||
/* Each time I hit the start of the loop, I assume that first is the
|
||||
* number for a run of non-zero values. The rest of the loop is
|
||||
* concerned with finding the value for last, which is the end of the
|
||||
* run, and the value of next, which is the start of the next run.
|
||||
* At the end of the loop, I assign next to first, so it starts in on
|
||||
* the next run.
|
||||
*/
|
||||
for (; first < 256; first = next) {
|
||||
last = first + 1;
|
||||
|
||||
for (;;) {
|
||||
|
||||
/* Find the end of the run of non-zeros. */
|
||||
for (; last < 256; last++) {
|
||||
if (nodes[last].count == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
last--;
|
||||
|
||||
/* Check the beginning of the next run of non-zero counts. */
|
||||
for (next = last + 1; next < 256; next++) {
|
||||
if (nodes[next].count != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Quit the run if we have reached the end. */
|
||||
if (next > 255) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Quit the run if there is more than three non-zero counts. */
|
||||
if ((next - last) > 3) {
|
||||
break;
|
||||
}
|
||||
|
||||
last = next;
|
||||
};
|
||||
|
||||
/* Output Start and Stop. */
|
||||
*buffer++ = first;
|
||||
*buffer++ = last;
|
||||
|
||||
/* Output the run of counts. */
|
||||
for (i = first; i <= last; i++) {
|
||||
*buffer++ = (unsigned char)nodes[i].count;
|
||||
}
|
||||
|
||||
size += (((last - first) + 1) + 2);
|
||||
}
|
||||
|
||||
/* Output terminator. */
|
||||
*buffer = 0;
|
||||
size++;
|
||||
|
||||
return (size);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* ConvertToCodes - Convert the Huffman tree into a table of codes.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* ConvertToCodes(Nodes, Codes, Code, Bits, Node)
|
||||
*
|
||||
* void ConvertToCodes(TreeNode *, HuffCode *, unsigned short, short,
|
||||
* short);
|
||||
*
|
||||
* FUNCTION
|
||||
* Since the Huffman tree is built as a decoding tree, there is no simple
|
||||
* way to get the encoding values for each symbol. This routine
|
||||
* recursively walks through the tree, adding the child bits to each code
|
||||
* until it gets to a leaf. When it gets to a leaf, it stores the code
|
||||
* value.
|
||||
*
|
||||
* INPUTS
|
||||
* Nodes - Pointer to the Huffman tree.
|
||||
* Codes - Pointer to the table of codes to generate.
|
||||
* Code - Code being built (initialize with 0).
|
||||
* Bits - Number of bits the code is comprised of (initialize with 0).
|
||||
* Node - Number of the current node.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void cdecl ConvertToCodes(TreeNode *nodes, HuffCode *codes,
|
||||
unsigned short code, short bits, short node)
|
||||
{
|
||||
node >>= 3;
|
||||
|
||||
if (node <= HUFF_EOS) {
|
||||
codes[node].code = code;
|
||||
codes[node].bits = bits;
|
||||
return;
|
||||
}
|
||||
|
||||
code <<= 1;
|
||||
bits++;
|
||||
ConvertToCodes(nodes, codes, code, bits, nodes[node].child0);
|
||||
ConvertToCodes(nodes, codes, code|1, bits, nodes[node].child1);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* HuffEncode - Huffman encode the data.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Size = HuffEncode(Data, Buffer, Codes, Length);
|
||||
*
|
||||
* long HuffEncode(unsigned char *, unsigned char *, HuffCodes *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Encoding of the data is simple. Each byte of data is taken as the index
|
||||
* of the codes array, the corresponding code is then put in the output.
|
||||
*
|
||||
* INPUTS
|
||||
* Data - Pointer to data to encode.
|
||||
* Buffer - Pointer to buffer to hold encoded data.
|
||||
* Codes - Pointer to array of Huffman codes.
|
||||
* Length - Length of data buffer to encode.
|
||||
*
|
||||
* RESULT
|
||||
* Size - Size of encoded data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long cdecl HuffEncode(unsigned char *data, unsigned char *buffer,
|
||||
HuffCode *codes, long length)
|
||||
{
|
||||
long i;
|
||||
long size;
|
||||
long next;
|
||||
unsigned long mask;
|
||||
unsigned long symbol;
|
||||
|
||||
/* Initialize */
|
||||
*buffer = 0;
|
||||
next = 0x80;
|
||||
i = 0;
|
||||
|
||||
do {
|
||||
if (i < length) {
|
||||
symbol = ((unsigned char *)data)[i];
|
||||
} else {
|
||||
symbol = HUFF_EOS;
|
||||
}
|
||||
|
||||
mask = 1L << (codes[symbol].bits - 1);
|
||||
|
||||
while (mask != 0) {
|
||||
|
||||
/* Set a bit in the output stream for each bit in the code. */
|
||||
if (mask & codes[symbol].code) {
|
||||
*buffer |= next;
|
||||
}
|
||||
|
||||
/* Next bit position. */
|
||||
next >>= 1;
|
||||
|
||||
/* Advance to the next byte in the output stream when the current
|
||||
* byte is full.
|
||||
*/
|
||||
if (next == 0) {
|
||||
buffer++;
|
||||
*buffer = 0;
|
||||
next = 0x80;
|
||||
size++;
|
||||
}
|
||||
|
||||
/* Next bit in the code. */
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
i++;
|
||||
} while (symbol != HUFF_EOS);
|
||||
|
||||
if (next != 0x80) {
|
||||
size++;
|
||||
}
|
||||
|
||||
return (size);
|
||||
}
|
||||
|
391
VQ/VQM32/HUFFDCMP.ASM
Normal file
391
VQ/VQM32/HUFFDCMP.ASM
Normal file
@@ -0,0 +1,391 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* huffdcmp.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* Huffman order 0 decompressor.
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* May 22, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* HuffDecompress - Decompress Huffman order 0 encoded data.
|
||||
;* BuildHuffTree - Build the Huffman decode tree.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
|
||||
STRUC TreeNode
|
||||
count DD ? ;Weight of the node
|
||||
child0 DW ? ;Child node 0
|
||||
child1 DW ? ;Child node 1
|
||||
ENDS TreeNode
|
||||
|
||||
HUFF_EOS EQU 256
|
||||
|
||||
CODESEG
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* HuffDecompress - Decompress Huffman order 0 encoded data.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Size = HuffDecompress(Data, Buffer, Length, Temp)
|
||||
;*
|
||||
;* long = HuffDecompress(unsigned char *, unsigned char *, long, char *);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Expand data that has been compressed with order 0 Huffman coding.
|
||||
;* The model (counts) are extracted from the data and a decode tree is
|
||||
;* built. The data is expanded by reading a bit and traversing the tree
|
||||
;* until a leaf node is encountered.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Data - Pointer to Huffman encoded data.
|
||||
;* Buffer - Pointer to decompress buffer.
|
||||
;* Length - Maximum decompress length.
|
||||
;* Temp - Pointer to temporary working buffer. (Must be >= 5120 bytes!)
|
||||
;*
|
||||
;* RESULT
|
||||
;* Size - Size of decompressed data.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C HuffDecompress:NEAR
|
||||
PROC HuffDecompress C NEAR USES esi edi ebx ecx edx
|
||||
|
||||
ARG data:NEAR PTR
|
||||
ARG buffer:NEAR PTR
|
||||
ARG length:DWORD
|
||||
ARG temp:NEAR PTR
|
||||
|
||||
LOCAL next:DWORD
|
||||
|
||||
;*---------------------------------------------------------------------------
|
||||
;* Read in the set of counts
|
||||
;*---------------------------------------------------------------------------
|
||||
|
||||
mov esi,[data] ;Compressed data
|
||||
mov ebx,[temp] ;Nodes array
|
||||
|
||||
mov ax,[esi] ;Get first and last count
|
||||
xor edx,edx ;i = 0
|
||||
xor ecx,ecx
|
||||
add esi,2
|
||||
|
||||
??getcounts:
|
||||
cmp al,dl ;Reached start of run?
|
||||
jne ??zerocount
|
||||
|
||||
;* Copy the run of counts to the nodes
|
||||
|
||||
sub ah,al ;Run length = Stop - Start
|
||||
xor ecx,ecx
|
||||
mov cl,ah
|
||||
xor eax,eax
|
||||
inc ecx ;Run length + 1
|
||||
|
||||
??copycounts:
|
||||
mov al,[esi] ;Get count
|
||||
inc edx ;i++
|
||||
mov [ebx],eax ;Write count to node
|
||||
inc esi
|
||||
add ebx,8 ;Next node
|
||||
dec ecx
|
||||
jnz ??copycounts
|
||||
|
||||
mov ax,[esi] ;Get next start
|
||||
inc esi
|
||||
cmp al,0 ;Terminator?
|
||||
je short ??nextcount
|
||||
|
||||
inc esi
|
||||
jmp short ??nextcount
|
||||
|
||||
;* Fill empty nodes with 0
|
||||
|
||||
??zerocount:
|
||||
mov [DWORD PTR ebx],ecx
|
||||
inc edx ;i++
|
||||
add ebx,8 ;Next node
|
||||
|
||||
??nextcount:
|
||||
cmp edx,256
|
||||
jl short ??getcounts
|
||||
|
||||
mov [WORD PTR ebx],1
|
||||
mov [data],esi
|
||||
|
||||
;*---------------------------------------------------------------------------
|
||||
;* Build the Huffman tree. All active nodes are scanned in order
|
||||
;* to locate the two nodes with the minimum weights. These two
|
||||
;* weights are added together and assigned a new node. The new
|
||||
;* node makes the two minimum nodes into its 0 child and 1 child.
|
||||
;* The two minimum nodes are then marked as inactive. This process
|
||||
;* repeats until their is only one node left, which is the root.
|
||||
;*---------------------------------------------------------------------------
|
||||
|
||||
mov eax,[temp] ;Nodes array
|
||||
mov esi,eax
|
||||
add eax,(513 * 8) ;Node[513] = guaranteed maximum
|
||||
mov [DWORD PTR eax],-1
|
||||
|
||||
mov [next],((HUFF_EOS + 1) * 8)
|
||||
|
||||
??sortnext:
|
||||
mov edx,(513 * 8) ;first = 513
|
||||
mov edi,edx ;last = 513
|
||||
xor ecx,ecx ;i = 0
|
||||
mov ebx,esi ;nodes[i]
|
||||
|
||||
??sortnodes:
|
||||
cmp [WORD PTR ebx],0 ;Only check non-zero nodes
|
||||
jz ??nextnode
|
||||
|
||||
;* nodes[i].count < nodes[first].count
|
||||
|
||||
mov eax,[DWORD PTR esi + edx]
|
||||
cmp eax,[DWORD PTR ebx]
|
||||
jbe ??checklast
|
||||
|
||||
mov edi,edx ;last = first
|
||||
mov edx,ecx ;first = i
|
||||
jmp short ??nextnode
|
||||
|
||||
;* nodes[i].count < nodes[last].count
|
||||
|
||||
??checklast:
|
||||
mov eax,[DWORD PTR esi + edi]
|
||||
cmp eax,[DWORD PTR ebx]
|
||||
jbe ??nextnode
|
||||
|
||||
mov edi,ecx ;last = i
|
||||
|
||||
??nextnode:
|
||||
add ecx,8 ;i++
|
||||
add ebx,8 ;nodes[i]
|
||||
cmp ecx,[next]
|
||||
jne short ??sortnodes
|
||||
|
||||
;* Tree done when last = 513
|
||||
|
||||
cmp edi,(513 * 8)
|
||||
je short ??decode
|
||||
|
||||
mov ebx,[next]
|
||||
add ebx,esi
|
||||
mov [WORD PTR ebx+4],dx ;nodes[next].child0 = first
|
||||
mov [WORD PTR ebx+6],di ;nodes[next].child1 = last
|
||||
|
||||
add edx,esi
|
||||
mov eax,[DWORD PTR edx] ;nodes[first].count
|
||||
add edi,esi
|
||||
mov [DWORD PTR ebx],eax
|
||||
|
||||
mov ecx,[DWORD PTR edi] ;nodes[last].count
|
||||
xor eax,eax
|
||||
add [DWORD PTR ebx],ecx
|
||||
|
||||
mov [DWORD PTR edx],eax ;nodes[first].count = 0
|
||||
mov [DWORD PTR edi],eax ;nodes[lats].count = 0
|
||||
add [next],8
|
||||
jmp ??sortnext
|
||||
|
||||
;*---------------------------------------------------------------------------
|
||||
;* Expand the compressed data. As each new symbol is decoded, the
|
||||
;* tree is traversed, starting at the root node, reading a bit in,
|
||||
;* and taking either the child0 or child1 path. Eventually, the
|
||||
;* tree winds down to a leaf node, and the corresponding symbol is
|
||||
;* output. If the symbol is the HUFF_EOS symbol the process
|
||||
;* terminates.
|
||||
;*---------------------------------------------------------------------------
|
||||
|
||||
??decode:
|
||||
sub [next],8 ;rootnode - 1
|
||||
xor ecx,ecx
|
||||
mov esi,[data] ;Input data buffer
|
||||
mov al,080h ;mask = 0x80
|
||||
mov edi,[buffer] ;Output buffer
|
||||
mov ah,[esi] ;Data byte
|
||||
mov ebx,[temp]
|
||||
inc esi
|
||||
|
||||
??decodeloop:
|
||||
mov edx,[next] ;node = root
|
||||
|
||||
??walktree:
|
||||
mov ecx,4
|
||||
add ecx,edx
|
||||
test al,ah
|
||||
jz short ??getnode
|
||||
|
||||
add ecx,2
|
||||
|
||||
??getnode:
|
||||
mov dx,[WORD PTR ebx + ecx] ;nodes[node].child
|
||||
shr al,1
|
||||
jnz short ??checkleaf
|
||||
|
||||
mov ah,[esi] ;Get next data byte
|
||||
mov al,080h ;Reset mask
|
||||
inc esi
|
||||
|
||||
??checkleaf:
|
||||
cmp edx,(HUFF_EOS * 8)
|
||||
jg short ??walktree
|
||||
je short ??done
|
||||
|
||||
shr edx,3
|
||||
mov [edi],dl
|
||||
inc edi
|
||||
jmp short ??decodeloop
|
||||
|
||||
??done:
|
||||
mov eax,edi
|
||||
sub eax,[buffer]
|
||||
ret
|
||||
|
||||
ENDP HuffDecompress
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* BuildHuffTree - Build the Huffman decode tree.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Root = BuildHuffTree(Nodes)
|
||||
;*
|
||||
;* long BuildHuffTree(TreeNode *);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Build the Huffman tree. All active nodes are scanned in order to
|
||||
;* locate the two nodes with the minimum weights. These two weights are
|
||||
;* added together and assigned a new node. The new node makes the two
|
||||
;* minimum nodes into its 0 child and 1 child. The two minimum nodes are
|
||||
;* then marked as inactive. This process repeats until their is only one
|
||||
;* node left, which is the root.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Nodes - Pointer to array of nodes.
|
||||
;*
|
||||
;* RESULT
|
||||
;* Root - Number of root node.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C BuildHuffTree:NEAR
|
||||
PROC BuildHuffTree C NEAR USES esi edi ebx ecx edx
|
||||
|
||||
ARG temp:NEAR PTR
|
||||
|
||||
LOCAL next:DWORD
|
||||
|
||||
mov eax,[temp] ;Nodes array
|
||||
mov esi,eax
|
||||
add eax,(513 * 8) ;Node[513] = guaranteed maximum
|
||||
mov [DWORD PTR eax],-1
|
||||
|
||||
mov [next],((HUFF_EOS + 1) * 8)
|
||||
|
||||
??sortnext:
|
||||
mov edx,(513 * 8) ;first = 513
|
||||
mov edi,edx ;last = 513
|
||||
xor ecx,ecx ;i = 0
|
||||
mov ebx,esi ;nodes[i]
|
||||
|
||||
??sortnodes:
|
||||
cmp [WORD PTR ebx],0 ;Only check non-zero nodes
|
||||
jz ??nextnode
|
||||
|
||||
;* nodes[i].count < nodes[first].count
|
||||
|
||||
mov eax,[DWORD PTR esi + edx]
|
||||
cmp eax,[DWORD PTR ebx]
|
||||
jbe ??checklast
|
||||
|
||||
mov edi,edx ;last = first
|
||||
mov edx,ecx ;first = i
|
||||
jmp short ??nextnode
|
||||
|
||||
;* nodes[i].count < nodes[last].count
|
||||
|
||||
??checklast:
|
||||
mov eax,[DWORD PTR esi + edi]
|
||||
cmp eax,[DWORD PTR ebx]
|
||||
jbe ??nextnode
|
||||
|
||||
mov edi,ecx ;last = i
|
||||
|
||||
??nextnode:
|
||||
add ecx,8 ;i++
|
||||
add ebx,8
|
||||
cmp ecx,[next]
|
||||
jne short ??sortnodes
|
||||
|
||||
;* Tree done when last = 513
|
||||
|
||||
cmp edi,(513 * 8)
|
||||
je short ??done
|
||||
|
||||
mov ebx,[next]
|
||||
add ebx,esi ;nodes[next]
|
||||
mov [WORD PTR ebx+4],dx ;nodes[next].child0 = first
|
||||
mov [WORD PTR ebx+6],di ;nodes[next].child1 = last
|
||||
|
||||
add edx,esi
|
||||
mov eax,[DWORD PTR edx] ;nodes[first].count
|
||||
add edi,esi
|
||||
mov [DWORD PTR ebx],eax
|
||||
|
||||
mov ecx,[DWORD PTR edi] ;nodes[last].count
|
||||
xor eax,eax
|
||||
add [DWORD PTR ebx],ecx
|
||||
|
||||
mov [DWORD PTR edx],eax ;nodes[first].count = 0
|
||||
mov [DWORD PTR edi],eax ;nodes[lats].count = 0
|
||||
add [next],8
|
||||
jmp ??sortnext
|
||||
|
||||
??done:
|
||||
mov eax,[next]
|
||||
sub eax,8
|
||||
ret
|
||||
|
||||
ENDP BuildHuffTree
|
||||
|
||||
END
|
||||
|
99
VQ/VQM32/HUFFMAN.H
Normal file
99
VQ/VQM32/HUFFMAN.H
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HUFFMAN_H
|
||||
#define HUFFMAN_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* huffman.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Huffman order 0 compress/decompress definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* May 19, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/* TreeNode: Huffman decoding tree node.
|
||||
*
|
||||
* count - Weight of the node in the tree.
|
||||
* child0 - Child node 0
|
||||
* child1 - Child node 1
|
||||
*/
|
||||
typedef struct _TreeNode {
|
||||
unsigned long count;
|
||||
unsigned short child0;
|
||||
unsigned short child1;
|
||||
} TreeNode;
|
||||
|
||||
|
||||
/* HuffCode: This structure is used for storing the code for each symbol
|
||||
* during encoding. A table of codes for each symbol is built
|
||||
* from the Huffman tree.
|
||||
*
|
||||
* code - Code used to represent a symbol.
|
||||
* bits - Length of code in bits.
|
||||
*/
|
||||
typedef struct _HuffCode {
|
||||
unsigned short code;
|
||||
short bits;
|
||||
} HuffCode;
|
||||
|
||||
|
||||
#define HUFF_EOS 256 /* End of stream symbol */
|
||||
|
||||
/* Prototypes */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
long cdecl HuffCompress(unsigned char *data, unsigned char *buffer,
|
||||
long length, char *work);
|
||||
|
||||
long cdecl HuffDecompress(unsigned char *data, unsigned char *buffer,
|
||||
long length, char *work);
|
||||
|
||||
void cdecl HuffCount(unsigned char *data, TreeNode *nodes, long length,
|
||||
long zero);
|
||||
|
||||
void cdecl HuffScaleCounts(TreeNode *nodes);
|
||||
long cdecl RLEHuffCounts(TreeNode *nodes, unsigned char *buffer);
|
||||
long cdecl BuildHuffTree(TreeNode *nodes);
|
||||
|
||||
void cdecl ConvertToCodes(TreeNode *nodes, HuffCode *codes,
|
||||
unsigned short code, short bits, short node);
|
||||
|
||||
long cdecl HuffEncode(unsigned char *data, unsigned char *buffer,
|
||||
HuffCode *codes, long length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HUFFMAN_H */
|
||||
|
699
VQ/VQM32/IFF.CPP
Normal file
699
VQ/VQM32/IFF.CPP
Normal file
@@ -0,0 +1,699 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* iff.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* IFF manager. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* OpenIFF - Open an IFF for reading or writting.
|
||||
* CloseIFF - Close an IFF.
|
||||
* ReadForm - Read the IFF FORM, size and type of the file.
|
||||
* WriteForm - Write IFF form ID, size and type fields.
|
||||
* ReadChunkHeader - Read the IFF chunk identification header.
|
||||
* WriteChunkHeader - Write an IFF chunk identification header.
|
||||
* WriteChunk - Write an IFF chunk with data from a buffer.
|
||||
* WriteChunkBytes - Write data from a buffer to the IFF stream.
|
||||
* SkipChunkBytes - Skip bytes in a chunk.
|
||||
* FindChunk - Scan for a specific chunk name.
|
||||
* IDtoStr - Convert a longword identifier to a NULL-terminated
|
||||
* string.
|
||||
* CurrentFilePos - Get the current file position.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys\stat.h>
|
||||
#include <mem.h>
|
||||
#include "iff.h"
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* OpenIFF - Open an IFF for reading or writting.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* IFFHandle = OpenIFF(Name, Mode)
|
||||
*
|
||||
* IFFHandle *OpenIFF(char *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Opens an IFF for a new read or write. The direction of the I/O is
|
||||
* given by the value of Mode, which can be either IFF_READ or IFF_WRITE.
|
||||
*
|
||||
* INPUTS
|
||||
* Name - Pointer to name of file to open.
|
||||
* Mode - IFF_READ or IFF_WRITE.
|
||||
*
|
||||
* RESULT
|
||||
* IFFHandle - Pointer to IFFHandle structure or NULL if error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
IFFHandle *OpenIFF(char *name, long mode)
|
||||
{
|
||||
IFFHandle *iff;
|
||||
|
||||
/* Allocate IFFHandle structure. */
|
||||
if ((iff = (IFFHandle *)malloc(sizeof(IFFHandle))) != NULL) {
|
||||
|
||||
/* Initialize handle.*/
|
||||
memset(iff, 0, sizeof(IFFHandle));
|
||||
iff->flags = mode;
|
||||
|
||||
switch (mode) {
|
||||
case IFFF_READ:
|
||||
iff->fh = open(name, O_RDONLY|O_BINARY);
|
||||
break;
|
||||
|
||||
case IFFF_WRITE:
|
||||
iff->fh = open(name, (O_CREAT|O_TRUNC|O_WRONLY|O_BINARY),
|
||||
(S_IREAD|S_IWRITE));
|
||||
|
||||
printf("\r");
|
||||
break;
|
||||
|
||||
case (IFFF_READ|IFFF_WRITE):
|
||||
iff->fh = open(name, (O_RDWR|O_BINARY), (S_IREAD|S_IWRITE));
|
||||
break;
|
||||
|
||||
default:
|
||||
iff->fh = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If something went wrong we must free up any resources
|
||||
* that we have opened.
|
||||
*/
|
||||
if (iff->fh == -1) {
|
||||
free(iff);
|
||||
iff = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (iff);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* CloseIFF - Close an IFF.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* CloseIFF(IFFHandle)
|
||||
*
|
||||
* void CloseIFF(IFFHandle *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Completes an IFF read or write operation.
|
||||
*
|
||||
* INPUTS
|
||||
* IFFHandle - Pointer to IFFHandle structure.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void CloseIFF(IFFHandle *iff)
|
||||
{
|
||||
long length;
|
||||
|
||||
/* Write the length of the FORM */
|
||||
if ((iff->flags & IFFF_WRITE) && ((iff->form.size == 0)
|
||||
|| (iff->scan > iff->form.size))) {
|
||||
|
||||
lseek(iff->fh, 4, SEEK_SET);
|
||||
length = REVERSE_LONG(iff->scan);
|
||||
write(iff->fh, &length, 4);
|
||||
}
|
||||
|
||||
close(iff->fh);
|
||||
free(iff);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* ReadForm - Read the IFF FORM, size and type of the file.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = ReadForm(IFFHandle, FormHeader)
|
||||
*
|
||||
* long ReadForm(IFFHandle *, FormHeader *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Read in the IFF form, size, type information. If the FormHeader
|
||||
* structure pointer is NULL then the FORM will be read into the
|
||||
* IFFHandles form structure.
|
||||
*
|
||||
* INPUTS
|
||||
* IFFHandle - Pointer to IFFHandle structure.
|
||||
* FormHeader - Pointer to FormHeader structure.
|
||||
*
|
||||
* RESULT
|
||||
* Error - 0 if successful or IFFERR_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long ReadForm(IFFHandle *iff, FormHeader *form)
|
||||
{
|
||||
FormHeader *ptr;
|
||||
long error;
|
||||
|
||||
/* Read the FORM into the IFFHandle or the provided FormHeader. */
|
||||
if (form == NULL) {
|
||||
ptr = &iff->form;
|
||||
} else {
|
||||
ptr = form;
|
||||
}
|
||||
|
||||
/* Read in IFF FORM from the file stream.. */
|
||||
if ((error = read(iff->fh, ptr, 12)) == 12) {
|
||||
ptr->size = REVERSE_LONG(ptr->size);
|
||||
iff->scan = 4;
|
||||
error = 0;
|
||||
} else {
|
||||
if (error == -1)
|
||||
error = IFFERR_READ;
|
||||
else if (error == 0)
|
||||
error = IFFERR_EOF;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* WriteForm - Write IFF form ID, size and type fields.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = WriteForm(IFFHandle)
|
||||
*
|
||||
* long WriteForm(IFFHandle, FormHeader *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Write out the IFF form, size, type information. If the size field
|
||||
* is zero then the IFF form size will be calculated and written by
|
||||
* the CloseIFF() function. If the FormHeader structure pointer is NULL
|
||||
* the the form from the IFFHandle will be written.
|
||||
*
|
||||
* INPUTS
|
||||
* IFFHandle - Pointer to IFFHandle structure.
|
||||
* FormHeader - Pointer to FormHeader structure.
|
||||
*
|
||||
* RESULT
|
||||
* Error - 0 if successful or IFFERR_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long WriteForm(IFFHandle *iff, FormHeader *form)
|
||||
{
|
||||
FormHeader *ptr;
|
||||
long error = 0;
|
||||
|
||||
/* Use the FORM from the IFFHandle or the provided FormHeader. */
|
||||
if (form == NULL) {
|
||||
ptr = &iff->form;
|
||||
} else {
|
||||
ptr = form;
|
||||
}
|
||||
|
||||
/* Write the IFF form to the file stream. */
|
||||
if (iff->flags & IFFF_WRITE) {
|
||||
ptr->size = REVERSE_LONG(ptr->size);
|
||||
|
||||
if (write(iff->fh, ptr, 12) == 12) {
|
||||
iff->scan = 4;
|
||||
} else {
|
||||
error = IFFERR_WRITE;
|
||||
}
|
||||
} else {
|
||||
error = IFFERR_WRITE;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* ReadChunkHeader - Read the IFF chunk identification header.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = ReadChunkHeader(IFFHandle)
|
||||
*
|
||||
* long ReadChunkHeader(IFFHandle *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Read the IFF identification header from the files data stream.
|
||||
*
|
||||
* INPUTS
|
||||
* IFFHandle - Pointer to IFFHandle structure.
|
||||
*
|
||||
* RESULT
|
||||
* Error - 0 if successful or IFFERR_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long ReadChunkHeader(IFFHandle *iff)
|
||||
{
|
||||
long error = 0;
|
||||
|
||||
/* Skip any part of the previous chunk that hasn't been processed. */
|
||||
if ((iff->cn.size != 0) && (iff->cn.scan < PADSIZE(iff->cn.size))) {
|
||||
error = lseek(iff->fh, (PADSIZE(iff->cn.size) - iff->cn.scan), SEEK_CUR);
|
||||
|
||||
if (error == -1) {
|
||||
error = IFFERR_READ;
|
||||
} else {
|
||||
error = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read in the next chunk header context. */
|
||||
if (!error) {
|
||||
if ((error = read(iff->fh, &iff->cn, 8)) == 8) {
|
||||
error = 0;
|
||||
iff->scan += 8;
|
||||
iff->cn.size = REVERSE_LONG(iff->cn.size);
|
||||
iff->cn.scan = 0;
|
||||
} else {
|
||||
if (error == -1) {
|
||||
error = IFFERR_READ;
|
||||
} else if (error == 0) {
|
||||
error = IFFERR_EOF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* WriteChunkHeader - Write an IFF chunk identification header.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = WriteChunkHeader(IFFHandle, ID, Size)
|
||||
*
|
||||
* long WriteChunkHeader(IFFHandle *, long, long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Write an IFF identification header to the files data stream.
|
||||
*
|
||||
* INPUTS
|
||||
* IFFHandle - Pointer to IFFHandle structure.
|
||||
* ID - ID code of chunk.
|
||||
* Size - Size of chunk in bytes (WORD aligned).
|
||||
*
|
||||
* RESULT
|
||||
* Error - 0 if successful or IFFERR_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long WriteChunkHeader(IFFHandle *iff, long id, long size)
|
||||
{
|
||||
long error = 0;
|
||||
|
||||
/* Make sure it is okay to write. */
|
||||
if (iff->flags & IFFF_WRITE) {
|
||||
iff->cn.id = id;
|
||||
iff->cn.size = REVERSE_LONG(size);
|
||||
iff->cn.scan = 0;
|
||||
|
||||
if (write(iff->fh, &iff->cn, 8) == 8) {
|
||||
iff->scan += 8;
|
||||
} else {
|
||||
error = IFFERR_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* WriteChunk - Write an IFF chunk with data from a buffer.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Actual = WriteChunk(IFFHandle, ID, Buffer, Size)
|
||||
*
|
||||
* long WriteChunk(IFFHandle *, long, char *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Write a IFF chunk at the current file position.
|
||||
*
|
||||
* INPUTS
|
||||
* IFFHandle - Pointer to IFFHandle structure.
|
||||
* ID - ID code of chunk.
|
||||
* Buffer - Pointer to buffer area with bytes to be written.
|
||||
* Size - Number of bytes to write.
|
||||
*
|
||||
* RESULT
|
||||
* Actual - (positive) Bytes written or (negative) IFFERR_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long WriteChunk(IFFHandle *iff, long id, char *buffer, long size)
|
||||
{
|
||||
Context cn;
|
||||
long actual;
|
||||
|
||||
/* Make sure we can write to this file. */
|
||||
if (iff->flags & IFFF_WRITE) {
|
||||
cn.id = id;
|
||||
cn.size = REVERSE_LONG(size);
|
||||
|
||||
/* Write chunk header. */
|
||||
if (write(iff->fh, &cn, 8) == 8) {
|
||||
iff->scan += 8;
|
||||
iff->cn.scan += 8;
|
||||
|
||||
/* Write chunk data. */
|
||||
actual = write(iff->fh, buffer, size);
|
||||
|
||||
if (actual == size) {
|
||||
iff->scan += actual;
|
||||
iff->cn.scan += actual;
|
||||
|
||||
/* Write chunk padding if necessary. */
|
||||
if (PADSIZE(size) > size) {
|
||||
id = 0;
|
||||
|
||||
if (write(iff->fh, &id, 1) == 1) {
|
||||
iff->scan++;
|
||||
iff->cn.scan++;
|
||||
} else {
|
||||
actual = IFFERR_WRITE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
actual = IFFERR_WRITE;
|
||||
}
|
||||
} else {
|
||||
actual = IFFERR_WRITE;
|
||||
}
|
||||
} else {
|
||||
actual = IFFERR_WRITE;
|
||||
}
|
||||
|
||||
return (actual);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* WriteChunkBytes - Write data from a buffer to the IFF stream.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Actual = WriteChunkBytes(IFFHandle, Buffer, Size)
|
||||
*
|
||||
* long WriteChunk(IFFHandle *, char *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Write a IFF chunk at the current file position.
|
||||
*
|
||||
* INPUTS
|
||||
* IFFHandle - Pointer to IFFHandle structure.
|
||||
* Buffer - Pointer to buffer area with bytes to be written.
|
||||
* Size - Number of bytes to write.
|
||||
*
|
||||
* RESULT
|
||||
* Actual - (positive) Bytes written or (negative) IFFERR_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long WriteChunkBytes(IFFHandle *iff, char *buffer, long size)
|
||||
{
|
||||
long actual;
|
||||
|
||||
/* Make sure we can write to this file. */
|
||||
if (iff->flags & IFFF_WRITE) {
|
||||
|
||||
/* Write data. */
|
||||
if ((actual = (unsigned short)write(iff->fh, buffer, size)) == size) {
|
||||
iff->scan += actual;
|
||||
iff->cn.scan += actual;
|
||||
} else {
|
||||
actual = IFFERR_WRITE;
|
||||
}
|
||||
} else {
|
||||
actual = IFFERR_WRITE;
|
||||
}
|
||||
|
||||
return (actual);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* ReadChunkBytes - Read data from a chunk into a buffer.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Actual = ReadChunkBytes(IFFHandle, Buffer, Length)
|
||||
*
|
||||
* long ReadChunkBytes(IFFHandle *, char *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Read in 'Length' number of bytes from the current chunk context.
|
||||
* If the specified length exceeds the number of bytes remaining in the
|
||||
* chunk ReadChunkBytes() will read in only the number of remaining
|
||||
* bytes. ReadChunkBytes() will never read beyond the scope of the
|
||||
* current chunk.
|
||||
*
|
||||
* INPUTS
|
||||
* IFFHandle - Pointer to IFFHandle structure.
|
||||
* Buffer - Pointer to buffer to read data into.
|
||||
* Length - Number of bytes to read.
|
||||
*
|
||||
* RESULT
|
||||
* Actual - (positive) Bytes written or (negative) IFFERR_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long ReadChunkBytes(IFFHandle *iff, char *buffer, long size)
|
||||
{
|
||||
long actual;
|
||||
|
||||
/* If the actual bytes remaining in the current chunk is less than
|
||||
* the requested bytes to read then adjust the read request size
|
||||
* to only read in the bytes that remain in the chunk.
|
||||
*/
|
||||
actual = (iff->cn.size - iff->cn.scan);
|
||||
|
||||
if (size > actual) {
|
||||
size = actual;
|
||||
}
|
||||
|
||||
/* Read in the requested number of bytes. */
|
||||
if ((actual = read(iff->fh, buffer, size)) != size) {
|
||||
actual = IFFERR_READ;
|
||||
} else {
|
||||
iff->scan += actual;
|
||||
iff->cn.scan += actual;
|
||||
}
|
||||
|
||||
return (actual);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SkipChunkBytes - Skip bytes in a chunk.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = SkipChunkBytes(IFFHandle, Skip)
|
||||
*
|
||||
* long SkipChunkBytes(IFFHandle *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Skip the specified number of bytes of the chunk.
|
||||
*
|
||||
* INPUTS
|
||||
* IFFHandle - Pointer to IFFHandle structure.
|
||||
* Skip - Number of bytes to skip.
|
||||
*
|
||||
* RESULT
|
||||
* Error - 0 if successful or FAIL_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long SkipChunkBytes(IFFHandle *iff, long skip)
|
||||
{
|
||||
long error = 0;
|
||||
|
||||
if (lseek(iff->fh, skip, SEEK_CUR) == -1) {
|
||||
error = IFFERR_READ;
|
||||
} else {
|
||||
iff->scan += skip;
|
||||
iff->cn.scan += skip;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* FindChunk - Scan for a specific chunk name.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = FindChunk(IFFHandle, ID)
|
||||
*
|
||||
* long FindChunk(IFFHandle *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Scan from the current file position for the next occurance of the
|
||||
* specified chunk ID. When a match is found the function will return
|
||||
* with the matching chunk as the current context.
|
||||
*
|
||||
* INPUTS
|
||||
* IFFHandle - Pointer to IFFHandle structure.
|
||||
* ID - ID code of chunk.
|
||||
*
|
||||
* RESULT
|
||||
* Error - 0 if successful or FAIL_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long FindChunk(IFFHandle *iff, long id)
|
||||
{
|
||||
long found = 0;
|
||||
long error = 0;
|
||||
|
||||
/* Invalid handle check. */
|
||||
if (iff != NULL) {
|
||||
|
||||
/* Scan until we have a match or an error. */
|
||||
while ((found == 0) && !(error = ReadChunkHeader(iff))) {
|
||||
|
||||
/* If we found a match the terminate scan, otherwise skip this
|
||||
* chunk and process the next.
|
||||
*/
|
||||
if (iff->cn.id == id) {
|
||||
found = 1;
|
||||
} else {
|
||||
error = SkipChunkBytes(iff, PADSIZE(iff->cn.size));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* IDtoStr - Convert a longword identifier to a NULL-terminated string.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* String = IDtoStr(ID, Buffer)
|
||||
*
|
||||
* char *IDtoStr(long, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Writes the ASCII equivalent of the given longword ID into buffer as a
|
||||
* NULL-terminated string.
|
||||
*
|
||||
* INPUTS
|
||||
* ID - Longword ID.
|
||||
* Buffer - Character buffer to accept string (at least 5 characters).
|
||||
*
|
||||
* RESULT
|
||||
* String - The value of "Buffer".
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
char *IDtoStr(long id, char *buf)
|
||||
{
|
||||
memcpy(buf, &id, 4);
|
||||
*(buf + 4) = 0;
|
||||
|
||||
return (buf);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* CurrentFilePos - Get the current file position.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Position = CurrentFilePos(IFFHandle)
|
||||
*
|
||||
* long CurrentFilePos(IFFHandle *);
|
||||
*
|
||||
* FUNCTION
|
||||
* This function returns the offset in bytes of the current file position
|
||||
* from the beginning of the IFF.
|
||||
*
|
||||
* INPUTS
|
||||
* IFFHandle - Pointer to IFFHandle structure.
|
||||
*
|
||||
* RESULT
|
||||
* Position - Offset in bytes from the beginning of the file to the
|
||||
* current position.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long CurrentFilePos(IFFHandle *iff)
|
||||
{
|
||||
long offset;
|
||||
|
||||
if ((offset = lseek(iff->fh, 0, SEEK_CUR)) == -1) {
|
||||
offset = IFFERR_READ;
|
||||
}
|
||||
|
||||
return (offset);
|
||||
}
|
||||
|
141
VQ/VQM32/IFF.H
Normal file
141
VQ/VQM32/IFF.H
Normal 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/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMIFF_H
|
||||
#define VQMIFF_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* iff.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* IFF (Interchange File Format) manager definitions.
|
||||
* (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* FormHeader - Structure associated with IFF forms.
|
||||
*
|
||||
* id - IFF form id (IE: "FORM")
|
||||
* size - Length of IFF in bytes
|
||||
* type - Form type (IE: "ILBM")
|
||||
*/
|
||||
typedef struct _FormHeader {
|
||||
long id;
|
||||
long size;
|
||||
long type;
|
||||
} FormHeader;
|
||||
|
||||
/* Context - Structure associated with chunks.
|
||||
*
|
||||
* id - Chunk identifier.
|
||||
* size - Size of chunk in bytes.
|
||||
* scan - Bytes read/written.
|
||||
*/
|
||||
typedef struct _Context {
|
||||
long id;
|
||||
long size;
|
||||
long scan;
|
||||
} Context;
|
||||
|
||||
/* IFFHandle - Structure associated with an active IFF read\write session.
|
||||
*
|
||||
* fh - DOS filehandle
|
||||
* flags - Internal flags used by IFF routines.
|
||||
* form - IFF form information.
|
||||
* scan - Bytes read/written
|
||||
* cn - Context of current chunk.
|
||||
*/
|
||||
typedef struct _IFFHandle {
|
||||
long fh;
|
||||
long flags;
|
||||
FormHeader form;
|
||||
long scan;
|
||||
Context cn;
|
||||
} IFFHandle;
|
||||
|
||||
/* bit masks for "flags" field. */
|
||||
#define IFFB_READ 0
|
||||
#define IFFB_WRITE 1
|
||||
#define IFFF_READ (1<<IFFB_READ)
|
||||
#define IFFF_WRITE (1<<IFFB_WRITE)
|
||||
|
||||
/* IFF return codes. Most functions return either zero for success or
|
||||
* one of these codes. The exceptions are the read/write functions which,
|
||||
* return positive values for number of bytes read or written, or a negative
|
||||
* error code.
|
||||
*
|
||||
* IFFERR_EOF - End of file.
|
||||
* IFFERR_READ - Read error.
|
||||
* IFFERR_WRITE - Write error.
|
||||
* IFFERR_NOMEM - Unable to allocate memory.
|
||||
*/
|
||||
#define IFFERR_EOF -1
|
||||
#define IFFERR_READ -2
|
||||
#define IFFERR_WRITE -3
|
||||
#define IFFERR_NOMEM -4
|
||||
|
||||
/* Macros to make things easier. */
|
||||
#define REVERSE_LONG(id) (unsigned long)((((unsigned long)(id)>>24) \
|
||||
&0x000000FFL)|(((unsigned long)(id)>>8) \
|
||||
&0x0000FF00L)|(((unsigned long)(id)<<8) \
|
||||
&0x00FF0000L)|(((unsigned long)(id)<<24)&0xFF000000L))
|
||||
|
||||
#define REVERSE_WORD(id) ((unsigned short)((((unsigned short)(id)<<8) \
|
||||
&0x00FF00)|(((unsigned short)(id)>>8)&0x0FF)))
|
||||
|
||||
#define PADSIZE(size) (((size)+1)&(~1))
|
||||
|
||||
#ifndef MAKE_ID
|
||||
#define MAKE_ID(a,b,c,d) ((long)((long)(d)<<24)|((long)(c)<<16)| \
|
||||
((long)(b)<<8)|(long)(a))
|
||||
#endif
|
||||
|
||||
/* Universal IFF identifiers */
|
||||
#define ID_FORM MAKE_ID('F','O','R','M')
|
||||
#define ID_LIST MAKE_ID('L','I','S','T')
|
||||
#define ID_PROP MAKE_ID('P','R','O','P')
|
||||
#define ID_NULL MAKE_ID(' ',' ',' ',' ')
|
||||
|
||||
/* Prototypes */
|
||||
IFFHandle *OpenIFF(char *, long);
|
||||
void CloseIFF(IFFHandle *);
|
||||
long ReadForm(IFFHandle *, FormHeader *);
|
||||
long WriteForm(IFFHandle *, FormHeader *);
|
||||
long ReadChunkHeader(IFFHandle *);
|
||||
long WriteChunkHeader(IFFHandle *, long, long);
|
||||
long WriteChunk(IFFHandle *, long, char *, long);
|
||||
long WriteChunkBytes(IFFHandle *, char *, long);
|
||||
long ReadChunkBytes(IFFHandle *, char *, long);
|
||||
long SkipChunkBytes(IFFHandle *, long);
|
||||
long FindChunk(IFFHandle *, long);
|
||||
char *IDtoStr(long, char *);
|
||||
long CurrentFilePos(IFFHandle *);
|
||||
|
||||
#endif /* VQMIFF_H */
|
||||
|
266
VQ/VQM32/LCWCOMP.ASM
Normal file
266
VQ/VQM32/LCWCOMP.ASM
Normal file
@@ -0,0 +1,266 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* lcwcomp.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* LCW compression code. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Louis Castle
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* January 26, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* LCW_Compress - LCW compress a buffer of memory.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
CODESEG
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* LCW_Compress - LCW compress a buffer of memory.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Size = LCW_Compress(Source, Dest, Length)
|
||||
;*
|
||||
;* long LCW_Compress(void *, void *, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Source - Pointer to data to compress.
|
||||
;* Dest - Pointer to buffer to put compressed data.
|
||||
;* Length - Length in bytes of data to compress.
|
||||
;*
|
||||
;* RESULT
|
||||
;* Size - Size in bytes of compresed data.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C LCW_Compress:NEAR
|
||||
PROC LCW_Compress C NEAR USES ebx ecx edx esi edi
|
||||
|
||||
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
|
||||
|
||||
mov esi,[source]
|
||||
mov edi,[dest]
|
||||
mov edx,[datasize]
|
||||
|
||||
cld ;Forward direction
|
||||
mov ebx,esi
|
||||
add ebx,edx
|
||||
mov [end_of_data],ebx ;Save end of source address
|
||||
mov [inlen],1 ;Set the in-length flag
|
||||
mov [a1stdest],edi ;Save original dest
|
||||
mov [a1stsrc],esi ;Save original source
|
||||
mov [lenoff],edi ;Save offset length
|
||||
|
||||
mov al,081h ;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 address of first byte
|
||||
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 [inlen],0 ;Clear the in-length flag
|
||||
mov esi,edi
|
||||
mov edi,[ndest]
|
||||
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 ;Address of the last byte +1
|
||||
sub ecx,edi ;Total number of bytes left
|
||||
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 address for the next search
|
||||
mov ebx,edi ;Save address 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
|
||||
jne short ??notend
|
||||
|
||||
inc edi
|
||||
|
||||
??notend:
|
||||
mov esi,edx
|
||||
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 paragraph 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:
|
||||
mov bl,cl ;Get the length (3-10)
|
||||
sub bl,3 ;Sub 3 for a 3 bit number 0-7
|
||||
shl bl,4
|
||||
add ah,bl
|
||||
xchg ah,al
|
||||
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 [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 [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
|
||||
add esi,[count] ;Add in the length of the run to the source
|
||||
mov [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 eax,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
|
221
VQ/VQM32/LCWUNCMP.ASM
Normal file
221
VQ/VQM32/LCWUNCMP.ASM
Normal file
@@ -0,0 +1,221 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* lcwuncmp.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* LCW uncompress routine. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Chris Yates
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* January 26, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* LCW_Uncompress - Uncompress LCW encoded data.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
CODESEG
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* LCW_Uncompress - Uncompress LCW encoded data.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Size = LCW_Uncompress(Source, Dest, Length)
|
||||
;*
|
||||
;* LONG LCW_Uncompress(void *, void *, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* 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
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Source - Pointer to LCW encoded data.
|
||||
;* Dest - Pointer to buffer to uncompress into.
|
||||
;* Length -
|
||||
;*
|
||||
;* RESULT
|
||||
;* Size - Size of uncompressed data in bytes.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C LCW_Uncompress:NEAR
|
||||
PROC LCW_Uncompress C NEAR USES ebx ecx edx esi edi
|
||||
|
||||
ARG source:DWORD
|
||||
ARG dest:DWORD
|
||||
ARG length:DWORD
|
||||
|
||||
LOCAL a1stdest:DWORD
|
||||
LOCAL maxlen:DWORD
|
||||
LOCAL lastbyte:DWORD
|
||||
LOCAL lastcom:DWORD
|
||||
LOCAL lastcom1:DWORD
|
||||
|
||||
mov esi,[source] ;ESI - Source address
|
||||
mov edi,[dest] ;EDI - Destination address
|
||||
mov edx,[length] ;EDX - Maximum length
|
||||
|
||||
mov [a1stdest],edi ;Save dest address
|
||||
add edx,edi ;Last address (Dest + length)
|
||||
mov [lastbyte],edx
|
||||
|
||||
cld ;Forward direction
|
||||
mov ebx,esi ;Save source address
|
||||
|
||||
??loop:
|
||||
; Exit if no bytes are remaining.
|
||||
|
||||
mov eax,[lastbyte]
|
||||
sub eax,edi
|
||||
jz short ??out
|
||||
|
||||
mov [maxlen],eax ;Save for string commands
|
||||
mov esi,ebx ;Restore source address
|
||||
lodsb
|
||||
or al,al ;See if its a short run
|
||||
js short ??notshort
|
||||
|
||||
mov ah,al ;Put rel offset high nibble in ah
|
||||
and ah,0Fh ; Only 4 bits count
|
||||
sub ecx,ecx
|
||||
mov ch,al ;Put count nibble in ch
|
||||
shr ch,4
|
||||
mov cl,ch
|
||||
xor ch,ch
|
||||
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:
|
||||
lodsb ;Get rel offset low byte
|
||||
mov ebx,esi ;Save the source address
|
||||
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
|
||||
|
||||
; If end code then exit.
|
||||
|
||||
cmp al,80h
|
||||
je short ??out
|
||||
|
||||
mov cl,al ;Put the byte in count register
|
||||
and ecx,3Fh ;Mask 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 short ??exit
|
||||
|
||||
??notlength:
|
||||
mov cl,al ;Get the entire code
|
||||
and ecx,3Fh ;Mask off all but the size -3
|
||||
add ecx,3 ;Add 3 for byte count
|
||||
cmp al,0FEh
|
||||
jne short ??notrunlength
|
||||
|
||||
sub eax,eax
|
||||
lodsw
|
||||
mov ecx,eax
|
||||
sub eax,eax
|
||||
lodsb
|
||||
mov ebx,esi ;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:
|
||||
rep stosb
|
||||
jmp ??loop
|
||||
|
||||
??notrunlength:
|
||||
cmp al,0FFh ;Is it a long run?
|
||||
jne short ??notlong ;If not use the code as the size
|
||||
|
||||
sub eax,eax
|
||||
lodsw ;If so, get the size
|
||||
mov ecx,eax ;Put int the count byte
|
||||
|
||||
??notlong:
|
||||
lodsw ;Get the rel index
|
||||
mov ebx,esi ;Save the source offset
|
||||
add eax,[a1stdest] ;Add in the first index
|
||||
mov esi,eax ;Use this as a source
|
||||
cmp ecx,[maxlen] ;Is it too big to fit?
|
||||
jbe short ??runok ;If not, its ok
|
||||
|
||||
mov ecx,[maxlen] ;If so, max it out so it dosen't overrun
|
||||
|
||||
??runok:
|
||||
rep movsb
|
||||
jmp ??loop
|
||||
|
||||
??exit:
|
||||
mov eax,edi
|
||||
mov ebx,[dest]
|
||||
sub eax,ebx ;Calculate bytes uncompressed.
|
||||
ret
|
||||
|
||||
ENDP LCW_Uncompress
|
||||
|
||||
END
|
||||
|
183
VQ/VQM32/MAKEFILE
Normal file
183
VQ/VQM32/MAKEFILE
Normal file
@@ -0,0 +1,183 @@
|
||||
#
|
||||
# Command & Conquer Red Alert(tm)
|
||||
# Copyright 2025 Electronic Arts Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
#****************************************************************************
|
||||
#
|
||||
# C O N F I D E N T I A L --- W E S T W O O D S T U D I O S
|
||||
#
|
||||
#----------------------------------------------------------------------------
|
||||
#
|
||||
# PROJECT
|
||||
# VQMisc 32-bit library. (Watcom/4GW)
|
||||
#
|
||||
# FILE
|
||||
# makefile
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Makefile for generating VQMisc32 library.
|
||||
#
|
||||
# PROGRAMMER
|
||||
# Denzil E. Long, Jr.
|
||||
#
|
||||
# DATE
|
||||
# Feburary 10, 1995
|
||||
#
|
||||
# ENVIROMENT
|
||||
# PRJ - Projects path.
|
||||
# PRJVCS - Version control archive path.
|
||||
# WATCOM - Watcom C installation path.
|
||||
#
|
||||
#****************************************************************************
|
||||
|
||||
.OPTIMIZE
|
||||
.ERASE
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# VERIFY ENVIROMENT
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
!ifndef %PRJ || %PRJVCS || %WATCOM
|
||||
!error Environment not configured.
|
||||
!endif
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# PROJECTS DEPENDENT MACROS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
PRJNAME = vqm32wp
|
||||
PRJDIR = $(%PRJ)\VQM32
|
||||
|
||||
OBJECTS = &
|
||||
iff.obj &
|
||||
profile.obj &
|
||||
audzap.obj &
|
||||
audunzap.obj &
|
||||
targa.obj &
|
||||
vertag.obj &
|
||||
sortpal.obj &
|
||||
palette.obj &
|
||||
mono.obj &
|
||||
lcwuncmp.obj &
|
||||
lcwcomp.obj &
|
||||
testvb.obj &
|
||||
vb.obj &
|
||||
mcgabuf.obj &
|
||||
video.obj &
|
||||
xmode.obj &
|
||||
xmodepg.obj &
|
||||
vesabuf.obj &
|
||||
vesablit.obj &
|
||||
vesavid.obj &
|
||||
soscodec.obj &
|
||||
drawchar.obj &
|
||||
textprnt.obj &
|
||||
font.obj &
|
||||
chrwidth.obj &
|
||||
mixfile.obj &
|
||||
crc.obj &
|
||||
fillrect.obj &
|
||||
captoken.obj &
|
||||
huffcmp.obj &
|
||||
huffdcmp.obj &
|
||||
mem.obj &
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# PATH MACROS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
!ifdef %LIB
|
||||
LIBPATH = $(%PRJ)\LIB;$(%LIB)
|
||||
!else
|
||||
LIBPATH = $(%PRJ)\LIB;$(%WATCOM)\LIB386
|
||||
!endif
|
||||
|
||||
!ifdef %INCLUDE
|
||||
INCLUDEPATH = $(%PRJ)\INCLUDE;$(%INCLUDE)
|
||||
!else
|
||||
INCLUDEPATH = $(%PRJ)\INCLUDE;$(%WATCOM)\H
|
||||
!endif
|
||||
|
||||
path_c = .\
|
||||
path_cpp = .\
|
||||
path_h = .\
|
||||
path_asm = .\
|
||||
path_i = .\
|
||||
path_obj = .\O
|
||||
path_lib = $(%PRJ)\LIB
|
||||
path_exe = .\
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# IMPLICIT RULE EXTENSIONS AND PATHS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
.EXTENSIONS :
|
||||
.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i
|
||||
|
||||
.c : $(path_c)
|
||||
.cpp : $(path_cpp)
|
||||
.h : $(path_h)
|
||||
.asm : $(path_asm)
|
||||
.i : $(path_i)
|
||||
.obj : $(path_obj)
|
||||
.lib : $(path_lib)
|
||||
.exe : $(path_exe)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# TOOLS, COMMANDS AND CONFIGURATIONS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
CC_CMD = wcc386
|
||||
CCP_CMD = wpp386
|
||||
ASM_CMD = tasm32
|
||||
LINK_CMD = wlink
|
||||
LIB_CMD = wlib
|
||||
|
||||
CC_OPTS = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq
|
||||
ASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /dPHARLAP_TNT=0
|
||||
LIB_OPTS = /b /c /q
|
||||
LINK_CFG = $(PRJNAME).lnk
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# DEFAULT TARGET
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
all : $(PRJNAME).lib .SYMBOLIC
|
||||
|
||||
$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# IMPLICIT RULES
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
.c.obj :
|
||||
$(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\$^. $<
|
||||
$(LIB_CMD) $(LIB_OPTS) $(path_lib)\$(PRJNAME).lib -+$(path_obj)\$]&
|
||||
|
||||
.cpp.obj :
|
||||
$(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\$^. $<
|
||||
$(LIB_CMD) $(LIB_OPTS) $(path_lib)\$(PRJNAME).lib -+$(path_obj)\$]&
|
||||
|
||||
.asm.obj:
|
||||
$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\$^.
|
||||
$(LIB_CMD) $(LIB_OPTS) $(path_lib)\$(PRJNAME).lib -+$(path_obj)\$]&
|
||||
|
||||
update: .SYMBOLIC
|
||||
@echo Updating VQMisc32 header files!
|
||||
@copy *.h $(%PRJ)\INCLUDE\VQM32 >NUL
|
||||
@copy *.i $(%PRJ)\INCLUDE\VQM32 >NUL
|
||||
|
174
VQ/VQM32/MAKEFILE.BAK
Normal file
174
VQ/VQM32/MAKEFILE.BAK
Normal file
@@ -0,0 +1,174 @@
|
||||
#
|
||||
# Command & Conquer Red Alert(tm)
|
||||
# Copyright 2025 Electronic Arts Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# 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
|
||||
# VQMisc 32-bit library. (Watcom/4GW)
|
||||
#
|
||||
# FILE
|
||||
# makefile
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Makefile for generating VQMisc32 library.
|
||||
#
|
||||
# PROGRAMMER
|
||||
# Denzil E. Long, Jr.
|
||||
#
|
||||
# DATE
|
||||
# Feburary 10, 1995
|
||||
#
|
||||
# ENVIROMENT
|
||||
# PRJ - Projects path.
|
||||
# PRJVCS - Version control archive path.
|
||||
# WATCOM - Watcom C installation path.
|
||||
#
|
||||
#****************************************************************************
|
||||
|
||||
.OPTIMIZE
|
||||
.ERASE
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# VERIFY ENVIROMENT
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
PRJ=.
|
||||
|
||||
!ifndef PRJ || %WATCOM
|
||||
!error Environment not configured.
|
||||
!endif
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# PROJECTS DEPENDENT MACROS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
PRJNAME = VQM32W
|
||||
PRJDIR = $(PRJ)\VQM32
|
||||
|
||||
OBJECTS = &
|
||||
iff.obj &
|
||||
profile.obj &
|
||||
audzap.obj &
|
||||
audunzap.obj &
|
||||
targa.obj &
|
||||
vertag.obj &
|
||||
sortpal.obj &
|
||||
palette.obj &
|
||||
lcwuncmp.obj &
|
||||
lcwcomp.obj &
|
||||
testvb.obj &
|
||||
vb.obj &
|
||||
mcgabuf.obj &
|
||||
video.obj &
|
||||
xmode.obj &
|
||||
xmodepg.obj &
|
||||
vesabuf.obj &
|
||||
vesablit.obj &
|
||||
vesavid.obj &
|
||||
soscodec.obj
|
||||
|
||||
# mono.obj &
|
||||
#----------------------------------------------------------------------------
|
||||
# PATH MACROS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
!ifdef %LIB
|
||||
LIBPATH = $(PRJ)\LIB;$(%LIB)
|
||||
!else
|
||||
LIBPATH = $(PRJ)\LIB;$(%WATCOM)\LIB386
|
||||
!endif
|
||||
|
||||
!ifdef %INCLUDE
|
||||
INCLUDEPATH = $(PRJ)\INCLUDE;$(%INCLUDE)
|
||||
!else
|
||||
INCLUDEPATH = $(PRJ)\INCLUDE;$(%WATCOM)\H
|
||||
!endif
|
||||
|
||||
path_c = .\
|
||||
path_cpp = .\
|
||||
path_h = .\
|
||||
path_asm = .\
|
||||
path_i = .\
|
||||
path_obj = .\O
|
||||
path_lib = $(PRJ)\LIB
|
||||
path_exe = .\
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# IMPLICIT RULE EXTENSIONS AND PATHS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
.EXTENSIONS :
|
||||
.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i
|
||||
|
||||
.c : $(path_c)
|
||||
.cpp : $(path_cpp)
|
||||
.h : $(path_h)
|
||||
.asm : $(path_asm)
|
||||
.i : $(path_i)
|
||||
.obj : $(path_obj)
|
||||
.lib : $(path_lib)
|
||||
.exe : $(path_exe)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# TOOLS, COMMANDS AND CONFIGURATIONS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
CC_CMD = wcc386
|
||||
CCP_CMD = wpp386
|
||||
ASM_CMD = tasm32
|
||||
LINK_CMD = wlink
|
||||
LIB_CMD = wlib
|
||||
|
||||
CC_OPTS = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq
|
||||
ASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /dPHARLAP_TNT=0
|
||||
LIB_OPTS = /b /c /q
|
||||
LINK_CFG = $(PRJNAME).lnk
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# DEFAULT TARGET
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
all : $(PRJNAME).lib .SYMBOLIC
|
||||
|
||||
$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# IMPLICIT RULES
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
.c.obj :
|
||||
$(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\$^. $<
|
||||
$(LIB_CMD) $(LIB_OPTS) $(path_lib)\$(PRJNAME).lib -+$(path_obj)\$]&
|
||||
|
||||
.cpp.obj :
|
||||
$(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\$^. $<
|
||||
$(LIB_CMD) $(LIB_OPTS) $(path_lib)\$(PRJNAME).lib -+$(path_obj)\$]&
|
||||
|
||||
.asm.obj:
|
||||
$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\$^.
|
||||
$(LIB_CMD) $(LIB_OPTS) $(path_lib)\$(PRJNAME).lib -+$(path_obj)\$]&
|
||||
|
||||
update: .SYMBOLIC
|
||||
@echo Updating VQMisc32 header files!
|
||||
@copy *.h $(PRJ)\INCLUDE\VQM32 >NUL
|
||||
@copy *.i $(PRJ)\INCLUDE\VQM32 >NUL
|
||||
|
234
VQ/VQM32/MAKEFILE.BOR
Normal file
234
VQ/VQM32/MAKEFILE.BOR
Normal file
@@ -0,0 +1,234 @@
|
||||
#
|
||||
# Command & Conquer Red Alert(tm)
|
||||
# Copyright 2025 Electronic Arts Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# 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
|
||||
# VQMisc32 library. (Borland/TNT)
|
||||
#
|
||||
# FILE
|
||||
# makefile
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Makefile for generating VQMisc32 library.
|
||||
#
|
||||
# PROGRAMMER
|
||||
# Denzil E. Long, Jr.
|
||||
#
|
||||
# DATE
|
||||
# Febuary 7, 1995
|
||||
#
|
||||
# ENVIROMENT
|
||||
# PRJ - Projects path.
|
||||
# PRJVCS - Version control archive path.
|
||||
# BCDIR - Borland C installation path.
|
||||
# TNTDIR - Pharlap/TNT installation path.
|
||||
#
|
||||
#****************************************************************************
|
||||
|
||||
.AUTODEPEND
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# VERIFY ENVIROMENT
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
!if !$d(PRJ) || !$d(PRJVCS) || !$d(BCDIR) || !$d(TNTDIR)
|
||||
!error Environment not configured.
|
||||
!endif
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# PROJECT DEPENDENT MACROS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
PRJNAME = VQM32BP
|
||||
PRJDIR = $(PRJ)\VQM32
|
||||
|
||||
OBJECTS = \
|
||||
iff.obj \
|
||||
profile.obj \
|
||||
audzap.obj \
|
||||
audunzap.obj \
|
||||
targa.obj \
|
||||
vertag.obj \
|
||||
sortpal.obj \
|
||||
palette.obj \
|
||||
mono.obj \
|
||||
lcwuncmp.obj \
|
||||
lcwcomp.obj \
|
||||
testvb.obj \
|
||||
vb.obj \
|
||||
mcgabuf.obj \
|
||||
video.obj \
|
||||
xmode.obj \
|
||||
xmodepg.obj \
|
||||
vesabuf.obj \
|
||||
vesablit.obj \
|
||||
vesavid.obj \
|
||||
soscodec.obj \
|
||||
drawchar.obj \
|
||||
textprnt.obj \
|
||||
font.obj \
|
||||
chrwidth.obj \
|
||||
mixfile.obj \
|
||||
crc.obj \
|
||||
fillrect.obj \
|
||||
captoken.obj \
|
||||
huffcmp.obj \
|
||||
huffdcmp.obj \
|
||||
mem.obj \
|
||||
portio.obj \
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# PATH MACROS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
!if $d(LIB)
|
||||
LIBPATH = $(PRJ)\LIB;$(LIB)
|
||||
!else
|
||||
LIBPATH = $(PRJ)\LIB;$(TNTDIR)\LIB;$(BCDIR)\LIB
|
||||
!endif
|
||||
|
||||
!if $d(INCLUDE)
|
||||
INCLUDEPATH = $(PRJ)\INCLUDE;$(INCLUDE)
|
||||
!else
|
||||
INCLUDEPATH = $(PRJ)\INCLUDE;$(TNTDIR)\INCLUDE;$(BCDIR)\INCLUDE
|
||||
!endif
|
||||
|
||||
.path.asm = $(PRJDIR)
|
||||
.path.c = $(PRJDIR)
|
||||
.path.cpp = $(PRJDIR)
|
||||
.path.h = $(PRJDIR)
|
||||
.path.exe = $(PRJDIR)
|
||||
.path.obj = $(PRJDIR)\OBJ
|
||||
.path.sym = $(PRJDIR)\OBJ
|
||||
.path.lib = $(PRJ)\LIB
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# TOOLS, COMMANDS AND CONFIGURATIONS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
CC_CMD = bcc32
|
||||
ASM_CMD = tasm32
|
||||
LINK_CMD = tlink32
|
||||
LIB_CMD = tlib
|
||||
|
||||
CC_CFG = bcc32.cfg
|
||||
ASM_CFG = tasm32.cfg
|
||||
LINK_CFG = tlink32.cfg
|
||||
LIB_CFG = tlib.cfg
|
||||
CFG_FILES = $(CC_CFG) $(ASM_CFG) $(LINK_CFG) $(LIB_CFG)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# DEFAULT TARGET
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
all: $(PRJNAME).lib
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# IMPLICIT RULES
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
.c.obj:
|
||||
$(CC_CMD) -P- -n$(.path.obj) {$< }
|
||||
|
||||
.cpp.obj:
|
||||
$(CC_CMD) -P -n$(.path.obj) {$< }
|
||||
|
||||
.asm.obj:
|
||||
$(ASM_CMD) @$(ASM_CFG) $<,$(.path.obj)\$&
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# BUILD THE LIBRARY
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
$(PRJNAME).lib: $(OBJECTS)
|
||||
- @del $(.path.lib)\$(PRJNAME).lib >&NUL
|
||||
$(LIB_CMD) $(.path.lib)\$(PRJNAME).lib @$(LIB_CFG) @&&|
|
||||
-+$(**: = -+)
|
||||
|
|
||||
- @copy *.h $(PRJ)\INCLUDE\VQM32 >&NUL
|
||||
- @copy *.i $(PRJ)\INCLUDE\VQM32 >&NUL
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# ALL OBJECTS DEPEND ON THE CONFIGURATION FILES
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
$(OBJECTS): $(CFG_FILES)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# COMPILER CONFIGURATION
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
$(CC_CFG): makefile
|
||||
copy &&|
|
||||
-c
|
||||
-3
|
||||
-d
|
||||
-H=$(.path.sym)\headers.sym
|
||||
-wpro
|
||||
-weas
|
||||
-wpre
|
||||
-I$(INCLUDEPATH)
|
||||
-DPHARLAP_TNT=1
|
||||
#-v
|
||||
| $(CC_CFG)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# ASSEMBLER CONFIGURATION
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
$(ASM_CFG): makefile
|
||||
copy &&|
|
||||
/t
|
||||
/m
|
||||
/w+
|
||||
/jJUMPS
|
||||
/ml
|
||||
/p
|
||||
/z
|
||||
/i$(PRJ)\INCLUDE
|
||||
/zi
|
||||
/dPHARLAP_TNT=1
|
||||
| $(ASM_CFG)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# LINKER CONFIGURATION
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
$(LINK_CFG): makefile
|
||||
copy &&|
|
||||
/c
|
||||
/m
|
||||
/Gm
|
||||
-L$(LIBPATH)
|
||||
-v
|
||||
| $(LINK_CFG)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# LIBRARIAN CONFIGURATION
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
$(LIB_CFG): makefile
|
||||
copy &&|
|
||||
/C /E
|
||||
| $(LIB_CFG)
|
||||
|
183
VQ/VQM32/MAKEFILE.WAT
Normal file
183
VQ/VQM32/MAKEFILE.WAT
Normal file
@@ -0,0 +1,183 @@
|
||||
#
|
||||
# Command & Conquer Red Alert(tm)
|
||||
# Copyright 2025 Electronic Arts Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
#****************************************************************************
|
||||
#
|
||||
# C O N F I D E N T I A L --- W E S T W O O D S T U D I O S
|
||||
#
|
||||
#----------------------------------------------------------------------------
|
||||
#
|
||||
# PROJECT
|
||||
# VQMisc 32-bit library. (Watcom/4GW)
|
||||
#
|
||||
# FILE
|
||||
# makefile
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Makefile for generating VQMisc32 library.
|
||||
#
|
||||
# PROGRAMMER
|
||||
# Denzil E. Long, Jr.
|
||||
#
|
||||
# DATE
|
||||
# Feburary 10, 1995
|
||||
#
|
||||
# ENVIROMENT
|
||||
# PRJ - Projects path.
|
||||
# PRJVCS - Version control archive path.
|
||||
# WATCOM - Watcom C installation path.
|
||||
#
|
||||
#****************************************************************************
|
||||
|
||||
.OPTIMIZE
|
||||
.ERASE
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# VERIFY ENVIROMENT
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
!ifndef %PRJ || %PRJVCS || %WATCOM
|
||||
!error Environment not configured.
|
||||
!endif
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# PROJECTS DEPENDENT MACROS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
PRJNAME = vqm32wp
|
||||
PRJDIR = $(%PRJ)\VQM32
|
||||
|
||||
OBJECTS = &
|
||||
iff.obj &
|
||||
profile.obj &
|
||||
audzap.obj &
|
||||
audunzap.obj &
|
||||
targa.obj &
|
||||
vertag.obj &
|
||||
sortpal.obj &
|
||||
palette.obj &
|
||||
mono.obj &
|
||||
lcwuncmp.obj &
|
||||
lcwcomp.obj &
|
||||
testvb.obj &
|
||||
vb.obj &
|
||||
mcgabuf.obj &
|
||||
video.obj &
|
||||
xmode.obj &
|
||||
xmodepg.obj &
|
||||
vesabuf.obj &
|
||||
vesablit.obj &
|
||||
vesavid.obj &
|
||||
soscodec.obj &
|
||||
drawchar.obj &
|
||||
textprnt.obj &
|
||||
font.obj &
|
||||
chrwidth.obj &
|
||||
mixfile.obj &
|
||||
crc.obj &
|
||||
fillrect.obj &
|
||||
captoken.obj &
|
||||
huffcmp.obj &
|
||||
huffdcmp.obj &
|
||||
mem.obj &
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# PATH MACROS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
!ifdef %LIB
|
||||
LIBPATH = $(%PRJ)\LIB;$(%LIB)
|
||||
!else
|
||||
LIBPATH = $(%PRJ)\LIB;$(%WATCOM)\LIB386
|
||||
!endif
|
||||
|
||||
!ifdef %INCLUDE
|
||||
INCLUDEPATH = $(%PRJ)\INCLUDE;$(%INCLUDE)
|
||||
!else
|
||||
INCLUDEPATH = $(%PRJ)\INCLUDE;$(%WATCOM)\H
|
||||
!endif
|
||||
|
||||
path_c = .\
|
||||
path_cpp = .\
|
||||
path_h = .\
|
||||
path_asm = .\
|
||||
path_i = .\
|
||||
path_obj = .\O
|
||||
path_lib = $(%PRJ)\LIB
|
||||
path_exe = .\
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# IMPLICIT RULE EXTENSIONS AND PATHS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
.EXTENSIONS :
|
||||
.EXTENSIONS : .exe .lib .obj .c .cpp .asm .h .i
|
||||
|
||||
.c : $(path_c)
|
||||
.cpp : $(path_cpp)
|
||||
.h : $(path_h)
|
||||
.asm : $(path_asm)
|
||||
.i : $(path_i)
|
||||
.obj : $(path_obj)
|
||||
.lib : $(path_lib)
|
||||
.exe : $(path_exe)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# TOOLS, COMMANDS AND CONFIGURATIONS
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
CC_CMD = wcc386
|
||||
CCP_CMD = wpp386
|
||||
ASM_CMD = tasm32
|
||||
LINK_CMD = wlink
|
||||
LIB_CMD = wlib
|
||||
|
||||
CC_OPTS = -i$(INCLUDEPATH) -j -zp1 -5s -mf -oaeilrt -s -zq
|
||||
ASM_OPTS = /t /m /w+ /jJUMPS /ml /p /z /dPHARLAP_TNT=0
|
||||
LIB_OPTS = /b /c /q
|
||||
LINK_CFG = $(PRJNAME).lnk
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# DEFAULT TARGET
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
all : $(PRJNAME).lib .SYMBOLIC
|
||||
|
||||
$(PRJNAME).lib : $(OBJECTS) .SYMBOLIC
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# IMPLICIT RULES
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
.c.obj :
|
||||
$(CC_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\$^. $<
|
||||
$(LIB_CMD) $(LIB_OPTS) $(path_lib)\$(PRJNAME).lib -+$(path_obj)\$]&
|
||||
|
||||
.cpp.obj :
|
||||
$(CCP_CMD) $(CC_OPTS) -fo=$(PATH_OBJ)\$^. $<
|
||||
$(LIB_CMD) $(LIB_OPTS) $(path_lib)\$(PRJNAME).lib -+$(path_obj)\$]&
|
||||
|
||||
.asm.obj:
|
||||
$(ASM_CMD) $(ASM_OPTS) $<,$(path_obj)\$^.
|
||||
$(LIB_CMD) $(LIB_OPTS) $(path_lib)\$(PRJNAME).lib -+$(path_obj)\$]&
|
||||
|
||||
update: .SYMBOLIC
|
||||
@echo Updating VQMisc32 header files!
|
||||
@copy *.h $(%PRJ)\INCLUDE\VQM32 >NUL
|
||||
@copy *.i $(%PRJ)\INCLUDE\VQM32 >NUL
|
||||
|
196
VQ/VQM32/MCGABUF.ASM
Normal file
196
VQ/VQM32/MCGABUF.ASM
Normal file
@@ -0,0 +1,196 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* mcgabuf.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* MCGA display routines. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Bill Randolph
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* Febuary 3, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* ClearVRAM - Clear all VRAM.
|
||||
;* MCGA_BufferCopy - Copy 320x200 buffer to MCGA VRAM
|
||||
;* MCGA_Blit - Bit blit a block to the MCGA screen.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
INCLUDE "vga.i"
|
||||
CODESEG
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* ClearVRAM - Clear all VRAM.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* ClearVRAM()
|
||||
;*
|
||||
;* void ClearVRAM(void);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* NONE
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C ClearVRAM:NEAR
|
||||
PROC ClearVRAM C NEAR USES eax ecx edi es
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov eax,01Ch ;Set ES selector to video memory
|
||||
mov es,ax
|
||||
mov edi,0
|
||||
ELSE
|
||||
mov edi,0A0000h
|
||||
ENDIF
|
||||
|
||||
SET_PLANE 0Fh ;Enable all planes for writing
|
||||
cld
|
||||
mov ecx,16000 ;Clear 320x200
|
||||
xor eax,eax
|
||||
rep stosd
|
||||
ret
|
||||
|
||||
ENDP ClearVRAM
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* MCGA_BufferCopy - Copy 320x200 buffer to MCGA VRAM
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* MCGA_BufferCopy(Buffer, Dummy)
|
||||
;*
|
||||
;* void MCGA_BufferCopy(char *, char *);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Buffer - Pointer to buffer to transfer.
|
||||
;* Dummy - Prototype placeholder.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C MCGA_BufferCopy:NEAR
|
||||
PROC MCGA_BufferCopy C NEAR USES ecx esi edi es
|
||||
|
||||
ARG buffer:NEAR PTR
|
||||
ARG dummy:NEAR PTR
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov eax,01Ch
|
||||
mov es,ax
|
||||
mov edi,0
|
||||
ELSE
|
||||
mov edi,0A0000h
|
||||
ENDIF
|
||||
|
||||
mov esi, [buffer]
|
||||
mov ecx,16000
|
||||
rep movsd ;Transfer the data
|
||||
ret
|
||||
|
||||
ENDP MCGA_BufferCopy
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* MCGA_Blit - Bit blit a block to the MCGA screen.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* MCGA_Blit(Buffer, Screen, Width, Height)
|
||||
;*
|
||||
;* void MCGA_Blit(char *, char *, long, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Buffer - Pointer to buffer to copy.
|
||||
;* Screen - Screen address to copy buffer to.
|
||||
;* Width - Width of block.
|
||||
;* Height - Height of block.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C MCGA_Blit:NEAR
|
||||
PROC MCGA_Blit C NEAR USES ecx edx esi edi
|
||||
|
||||
ARG buffer:NEAR PTR
|
||||
ARG screen:NEAR PTR
|
||||
ARG imgwidth:DWORD
|
||||
ARG imgheight:DWORD
|
||||
|
||||
IF PHARLAP_TNT
|
||||
push es
|
||||
mov eax,1Ch ;Set ES selector to VRAM
|
||||
mov es,ax
|
||||
ENDIF
|
||||
|
||||
mov esi,[buffer]
|
||||
mov edi,[screen]
|
||||
mov edx,320
|
||||
sub edx,[imgwidth] ;Compute modulo
|
||||
|
||||
??Do_row:
|
||||
mov ecx,[imgwidth]
|
||||
rep movsb
|
||||
add edi,edx
|
||||
dec [imgheight]
|
||||
jnz ??Do_row
|
||||
|
||||
IF PHARLAP_TNT
|
||||
pop es
|
||||
ENDIF
|
||||
|
||||
ret
|
||||
|
||||
ENDP MCGA_Blit
|
||||
|
||||
END
|
||||
|
134
VQ/VQM32/MEM.CPP
Normal file
134
VQ/VQM32/MEM.CPP
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* mem.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Memory management.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Phil Gorrow
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* July 5, 1995
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* DPMI_Lock - Lock a memory page.
|
||||
* DPMI_Unlock - Unlock a locked memory page.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
#include <dos.h>
|
||||
#include <mem.h>
|
||||
#include <vqm32\mem.h>
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* DPMI_Lock - Lock a memory page.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* DPMI_Lock(Address, Size)
|
||||
*
|
||||
* void DPMI_Lock(void *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* Address - Starting linear address of memory to lock.
|
||||
* Size - Size of region to lock in bytes.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void DPMI_Lock(void const *ptr, long const size)
|
||||
{
|
||||
union REGS regs;
|
||||
struct SREGS sregs;
|
||||
|
||||
memset(®s, 0, sizeof(REGS));
|
||||
segread(&sregs);
|
||||
|
||||
/* Lock the memory page.
|
||||
*
|
||||
* AX = 0x600
|
||||
* BX:CX = Starting linear address of memory to lock.
|
||||
* SI:DI = Size of region to lock in bytes.
|
||||
*/
|
||||
regs.x.eax = DPMI_LOCK;
|
||||
regs.x.ebx = ((long)ptr & 0xFFFF0000) >> 16;
|
||||
regs.x.ecx = ((long)ptr & 0x0000FFFF);
|
||||
regs.x.esi = ((long)size & 0xFFFF0000) >> 16;
|
||||
regs.x.edi = ((long)size & 0x0000FFFF);
|
||||
int386x(DPMI_INT, ®s, ®s, &sregs);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* DPMI_Unlock - Unlock a locked memory page.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* DPMI_Unlock(Address, Size)
|
||||
*
|
||||
* void DPMI_Unlock(void *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* Address - Starting linear address of memory to unlock.
|
||||
* Size - Size of region to unlock in bytes.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void DPMI_Unlock(void const *ptr, long const size)
|
||||
{
|
||||
union REGS regs;
|
||||
struct SREGS sregs;
|
||||
|
||||
/* Unlock memory page. */
|
||||
memset(®s, 0 ,sizeof(REGS));
|
||||
segread(&sregs);
|
||||
|
||||
regs.x.eax = DPMI_UNLOCK;
|
||||
regs.x.ebx = ((long)ptr & 0xFFFF0000) >> 16;
|
||||
regs.x.ecx = ((long)ptr & 0x0000FFFF);
|
||||
regs.x.esi = ((long)size & 0xFFFF0000) >> 16;
|
||||
regs.x.edi = ((long)size & 0x0000FFFF);
|
||||
int386x(DPMI_INT, ®s, ®s, &sregs);
|
||||
}
|
||||
|
||||
#endif /* __WATCOMC__ */
|
56
VQ/VQM32/MEM.H
Normal file
56
VQ/VQM32/MEM.H
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQAMEM_H
|
||||
#define VQAMEM_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* mem.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Memory management definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Phil Gorrow
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* July 5, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Definitions */
|
||||
#define DPMI_INT 0x0031
|
||||
#define DPMI_LOCK 0x0600
|
||||
#define DPMI_UNLOCK 0x0601
|
||||
|
||||
/* Prototypes */
|
||||
#ifdef __WATCOMC__
|
||||
void DPMI_Lock(void const *ptr, long const size);
|
||||
void DPMI_Unlock(void const *ptr, long const size);
|
||||
#else
|
||||
#define DPMI_Lock(a,b)
|
||||
#define DPMI_Unlock(a,b)
|
||||
#endif
|
||||
|
||||
#endif /* VQAMEM_H */
|
250
VQ/VQM32/MIXFILE.CPP
Normal file
250
VQ/VQM32/MIXFILE.CPP
Normal 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 S T U D I O S
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* mixfile.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* A mix file is basically a group of files concatinated together
|
||||
* proceeded by a header describing where in the file each individual
|
||||
* entry is located. These routines are provided to simplify the access
|
||||
* to these file entries.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* MixFile format:
|
||||
*
|
||||
* HEADER
|
||||
* (2 bytes) Count - The number of entries in this file.
|
||||
* (4 bytes) Size - Size of the mix file in bytes.
|
||||
*
|
||||
* SUBBLOCKS (There are "Count" number of these.)
|
||||
* (4 bytes) CRC - Entry descriptor (CRC of filename).
|
||||
* (4 bytes) Offset - Offset in bytes from beginning of the DATA chunk.
|
||||
* (4 bytes) Size - Size of entry.
|
||||
*
|
||||
* DATA
|
||||
* Entry data.
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* OpenMix - Open mix file for access.
|
||||
* CloseMix - Close a mix file.
|
||||
* OpenMixEntry - Open a mix file entry.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <mem.h>
|
||||
#include <string.h>
|
||||
#include "mixfile.h"
|
||||
#include "crc.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* PRIVATE DECLARATIONS
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
int compfunc(void const *ptr1, void const *ptr2);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* OpenMix - Open mix file for access.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* MixHandle = OpenMix(Name)
|
||||
*
|
||||
* MixHandle *OpenMix(char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Open a mix file for access.
|
||||
*
|
||||
* INPUTS
|
||||
* Name - Pointer to name of mix file to open.
|
||||
*
|
||||
* RESULT
|
||||
* MixHandle - Pointer to handle for mix file.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
MIXHandle *OpenMix(char *name)
|
||||
{
|
||||
MIXHeader mfhdr;
|
||||
MIXHandle *mix = NULL;
|
||||
long fh;
|
||||
long sbsize;
|
||||
long size;
|
||||
|
||||
/* Open mix file and read in header. */
|
||||
if ((fh = open(name, (O_RDONLY|O_BINARY))) != -1) {
|
||||
if (read(fh, &mfhdr, sizeof(MIXHeader)) == sizeof(MIXHeader)) {
|
||||
|
||||
/* Allocate handle based on the number of SubBlocks. */
|
||||
sbsize = (mfhdr.Count * sizeof(MIXSubBlock));
|
||||
size = sbsize + sizeof(MIXHandle);
|
||||
|
||||
if ((mix = (MIXHandle *)malloc(size)) != NULL) {
|
||||
memset(mix, 0, size);
|
||||
mix->Name = name;
|
||||
mix->Size = mfhdr.Size;
|
||||
mix->Count = mfhdr.Count;
|
||||
|
||||
/* Read in the SubBlock entries. */
|
||||
if (read(fh, &mix->Entries[0], sbsize) != sbsize) {
|
||||
free(mix);
|
||||
mix = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(fh);
|
||||
}
|
||||
|
||||
return (mix);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* CloseMix - Close a mix file.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* CloseMix(MixHandle)
|
||||
*
|
||||
* void CloseMix(MixHandle *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Close a mix file by freeing its handle.
|
||||
*
|
||||
* INPUTS
|
||||
* MixHandle - Pointer to MixHandle returned by OpenMix().
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void CloseMix(MIXHandle *mix)
|
||||
{
|
||||
free(mix);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* OpenMixEntry - Open a mix file entry.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* FH = OpenMixEntry(MixHandle, EntryName)
|
||||
*
|
||||
* short OpenMixEntry(MIXHandle *, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Opens an entry from the specified mix file handle. Use close() to close
|
||||
* the file when done.
|
||||
*
|
||||
* INPUTS
|
||||
* MixHandle - Pointer to MIXHandle containing entry to open.
|
||||
* EntryName - Pointer to name of mix file entry to open.
|
||||
*
|
||||
* RESULT
|
||||
* FH - DOS filehandle, -1 if unable to open.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long OpenMixEntry(MIXHandle *mix, char *name)
|
||||
{
|
||||
MIXSubBlock key;
|
||||
MIXSubBlock *block;
|
||||
long fh;
|
||||
|
||||
/* Search for the specified file in the mix file. */
|
||||
key.CRC = Calculate_CRC(name, strlen(name));
|
||||
block = (MIXSubBlock *)bsearch(&key, &mix->Entries[0], mix->Count,
|
||||
sizeof(MIXSubBlock), compfunc);
|
||||
|
||||
/* If the block exists for the requested filename. */
|
||||
if (block != NULL) {
|
||||
|
||||
/* Initialize the key for file access. */
|
||||
key.Offset = block->Offset;
|
||||
key.Offset += (mix->Count * sizeof(MIXSubBlock)) + sizeof(MIXHeader);
|
||||
|
||||
/* Open the mix file. */
|
||||
if ((fh = open(mix->Name, (O_RDONLY|O_BINARY))) != -1) {
|
||||
|
||||
/* Seek to the start of the file. */
|
||||
if (lseek(fh, key.Offset, SEEK_SET) == -1) {
|
||||
close(fh);
|
||||
fh = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (fh);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* compfunc - Compare function for bsearch().
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Result = compfunc(Entry1, Entry2);
|
||||
*
|
||||
* int compfunc(void const *, void const *);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* Entry1 - Pointer to first entry to compare.
|
||||
* Entry2 - Pointer to second entry to compare.
|
||||
*
|
||||
* RESULT
|
||||
* Result -
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int compfunc(void const *ptr1, void const *ptr2)
|
||||
{
|
||||
if (((MIXSubBlock *)ptr1)->CRC < ((MIXSubBlock *)ptr2)->CRC) return -1;
|
||||
if (((MIXSubBlock *)ptr1)->CRC > ((MIXSubBlock *)ptr2)->CRC) return 1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
105
VQ/VQM32/MIXFILE.H
Normal file
105
VQ/VQM32/MIXFILE.H
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMMIXFILE_H
|
||||
#define VQMMIXFILE_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* mixfile.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* A mix file is basically a group of files concatinated together
|
||||
* proceeded by a header describing where in the file each individual
|
||||
* entry is located. These definitions are provided to simplify the access
|
||||
* to these file entries.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Disable structure alignment.*/
|
||||
#ifdef __WATCOMC__
|
||||
#pragma pack(1);
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* STRUCTURE DEFINITIONS
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/* MIXHeader: Mix file data header.
|
||||
*
|
||||
* Count - Number of entries contained in this mix file.
|
||||
* Size - Size of Mix file.
|
||||
*/
|
||||
typedef struct _MIXHeader {
|
||||
short Count;
|
||||
long Size;
|
||||
} MIXHeader;
|
||||
|
||||
/* MIXSubBlock: Mix file entry descriptor.
|
||||
*
|
||||
* CRC - Unique entry identifier.
|
||||
* Offset - Offset from beginning of data segment to entry.
|
||||
* Size - Size of entry.
|
||||
*/
|
||||
typedef struct _MIXSubBlock {
|
||||
long CRC;
|
||||
long Offset;
|
||||
long Size;
|
||||
} MIXSubBlock;
|
||||
|
||||
/* MIXHandle: Mix file handle.
|
||||
*
|
||||
* Name - Pointer to the name of the mix file this handle is for.
|
||||
* Size - Size of entire mix file.
|
||||
* FH - DOS file handle of opened entry.
|
||||
* Count - Number of files contained in this mix.
|
||||
* Entries - Array of 'Count' MIXSubBlock structure entries.
|
||||
*/
|
||||
typedef struct _MIXHandle {
|
||||
char *Name;
|
||||
long Size;
|
||||
long FH;
|
||||
long Count;
|
||||
MIXSubBlock Entries[];
|
||||
} MIXHandle;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* PROTOTYPES
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
MIXHandle *OpenMix(char *name);
|
||||
void CloseMix(MIXHandle *mix);
|
||||
long OpenMixEntry(MIXHandle *mix, char *name);
|
||||
|
||||
/* Restore original alignment */
|
||||
#ifdef __WATCOMC__
|
||||
#pragma pack();
|
||||
#endif
|
||||
|
||||
#endif /* VQMMIXFILE_H */
|
||||
|
871
VQ/VQM32/MONO.ASM
Normal file
871
VQ/VQM32/MONO.ASM
Normal file
@@ -0,0 +1,871 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
;
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* mono.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* Mono screen print and output routines. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* Febuary 8, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* Mono_Enable - Enable mono output.
|
||||
;* Mono_Disable - Disable mono output.
|
||||
;* Mono_X - Get mono cursors X position.
|
||||
;* Mono_Y - Get mono cursors Y position.
|
||||
;* Mono_Set_Cursor - Set the mono cursor to specified coordinates.
|
||||
;* Mono_Clear_Screen - Clear the mono screen.
|
||||
;* Mono_Scroll - Scroll the mono screen up.
|
||||
;* Mono_Put_Char - Ouput a character to the mono screen.
|
||||
;* Mono_Draw_Rect - Draw a box on the mono screen.
|
||||
;* Mono_Text_Print - Print a string to the mono screen at a specified
|
||||
;* position.
|
||||
;* Mono_Print - Print a string to the mono screen.
|
||||
;* Mono_View_Page - View a mono page.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
|
||||
DATASEG
|
||||
|
||||
MonoEnabled DD 1
|
||||
MonoX DD 0
|
||||
MonoY DD 0
|
||||
MonoOff DD 0
|
||||
|
||||
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.
|
||||
|
||||
PageMap DD 0,1,2,3,4,5,6,7
|
||||
|
||||
CODESEG
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_Enable - Enable mono output.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Mono_Enable()
|
||||
;*
|
||||
;* void Mono_Enable(void);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Turn on the MonoEnabled flag.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* NONE
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_Enable:NEAR
|
||||
PROC Mono_Enable C NEAR
|
||||
|
||||
mov [MonoEnabled],1
|
||||
ret
|
||||
|
||||
ENDP Mono_Enable
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_Disable - Disable mono output.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Mono_Disable()
|
||||
;*
|
||||
;* void Mono_Disable(void);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Turn off the MonoEnabled flag.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* NONE
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_Disable:NEAR
|
||||
PROC Mono_Disable C NEAR
|
||||
|
||||
mov [MonoEnabled],0
|
||||
ret
|
||||
|
||||
ENDP Mono_Disable
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_X - Get mono cursors X position.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* X = Mono_X()
|
||||
;*
|
||||
;* long Mono_X(void);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Return the X position of the mono screen cursor.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* NONE
|
||||
;*
|
||||
;* RESULT
|
||||
;* X - X coordinate position.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_X:NEAR
|
||||
PROC Mono_X C NEAR
|
||||
|
||||
mov eax,[MonoX]
|
||||
ret
|
||||
|
||||
ENDP Mono_X
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_Y - Get mono cursors Y position.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Y = Mono_Y()
|
||||
;*
|
||||
;* long Mono_Y(void);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Return the Y position of the mono screen cursor.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* NONE
|
||||
;*
|
||||
;* RESULT
|
||||
;* Y - Y coordinate position.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_Y:NEAR
|
||||
PROC Mono_Y C NEAR
|
||||
|
||||
mov eax,[MonoY]
|
||||
ret
|
||||
|
||||
ENDP Mono_Y
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_Set_Cursor - Set the mono cursor to specified coordinates.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Mono_Set_Cursor(X, Y)
|
||||
;*
|
||||
;* void Mono_Set_Cursor(long, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* X - X coordinate position.
|
||||
;* Y - Y coordinate position.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_Set_Cursor:NEAR
|
||||
PROC Mono_Set_Cursor C NEAR USES eax ebx edx
|
||||
|
||||
ARG xpos:DWORD
|
||||
ARG ypos:DWORD
|
||||
|
||||
cmp [MonoEnabled],0
|
||||
je short ??fini
|
||||
|
||||
mov eax,[ypos]
|
||||
mov ah,80
|
||||
imul ah
|
||||
add eax,[xpos]
|
||||
mov ebx,eax
|
||||
|
||||
; Update cursor position.
|
||||
|
||||
mov dx,03B4h
|
||||
mov al,0Eh ;High byte register set.
|
||||
out dx,al
|
||||
inc dx
|
||||
mov al,bh
|
||||
out dx,al ;Set high byte.
|
||||
|
||||
dec dx
|
||||
mov al,0Fh ;Low byte register set.
|
||||
out dx,al
|
||||
inc dx
|
||||
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
|
||||
|
||||
??fini:
|
||||
ret
|
||||
|
||||
ENDP Mono_Set_Cursor
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_Clear_Screen - Clear the mono screen.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Mono_Clear_Screen()
|
||||
;*
|
||||
;* void Mono_Clear_Screen(void);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Clear the mono screen and set the mono cursor to the upperleft corner
|
||||
;* of the screen.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* NONE
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_Clear_Screen:NEAR
|
||||
PROC Mono_Clear_Screen C NEAR USES es eax ecx edi
|
||||
|
||||
; Exit if mono disabled
|
||||
|
||||
cmp [MonoEnabled],0
|
||||
je short ??fini
|
||||
|
||||
; Clear the mono screen
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov ax,034h
|
||||
mov es,ax ;Set ES selector to first MB
|
||||
ENDIF
|
||||
|
||||
mov edi,0B0000h ;EDI = Mono screen address
|
||||
xor eax,eax ;Set char & attributes to 0
|
||||
mov ecx,8000h/4 ;Number of longwords to clear
|
||||
rep stosd ;Clear the mono screen.
|
||||
call Mono_Set_Cursor C,eax,eax
|
||||
|
||||
??fini:
|
||||
ret
|
||||
|
||||
ENDP Mono_Clear_Screen
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_Scroll - Scroll the mono screen up.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Mono_Scroll(Lines)
|
||||
;*
|
||||
;* void Mono_Scroll(long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Move the contents of the mono screen up the specified number of lines
|
||||
;* while clearing out the bottom lines.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Lines - Number of lines to scroll the screen up.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_Scroll:NEAR
|
||||
PROC Mono_Scroll C NEAR USES es eax ebx ecx esi edi
|
||||
ARG lines:DWORD
|
||||
|
||||
; Exit if mono disabled
|
||||
|
||||
cmp [MonoEnabled],0
|
||||
je short ??fini
|
||||
|
||||
; Exit if lines to scroll is 0.
|
||||
|
||||
mov eax,[lines]
|
||||
or eax,eax
|
||||
je short ??fini
|
||||
|
||||
; Move the screen data up the specified lines
|
||||
|
||||
mov ebx,eax
|
||||
|
||||
??looper:
|
||||
IF PHARLAP_TNT
|
||||
mov ax,034h
|
||||
mov es,ax ;Set ES selector to first MB
|
||||
ENDIF
|
||||
|
||||
push ds ;Save DS selector
|
||||
mov ds,ax ;Set DS selector to first MB
|
||||
|
||||
mov ecx,((80*24)/2) ;Number of DWORDs to move
|
||||
mov esi,0B00A0h
|
||||
mov edi,0B0000h
|
||||
rep movsd
|
||||
|
||||
pop ds ;Restore DS selector
|
||||
dec [MonoY]
|
||||
sub [MonoOff],(80*2)
|
||||
|
||||
xor eax,eax
|
||||
mov ecx,(80/2)
|
||||
rep stosd
|
||||
|
||||
dec ebx
|
||||
jne ??looper
|
||||
|
||||
??fini:
|
||||
ret
|
||||
|
||||
ENDP Mono_Scroll
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_Put_Char - Ouput a character to the mono screen.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Mono_Put_Char(Character, Attributes)
|
||||
;*
|
||||
;* void Mono_Put_Char(long, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Character - ASCII character to output.
|
||||
;* Attributes - Display attributes
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_Put_Char:NEAR
|
||||
PROC Mono_Put_Char C NEAR USES es eax edi
|
||||
ARG character:DWORD
|
||||
ARG attrib:DWORD
|
||||
|
||||
; Exit if mono disabled
|
||||
|
||||
cmp [MonoEnabled],0
|
||||
je short ??fini
|
||||
|
||||
; Output character to the mono screen
|
||||
|
||||
cld
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov ax,034h
|
||||
mov es,ax ;Set ES selector to first MB
|
||||
ENDIF
|
||||
|
||||
mov edi,0B0000h ;EDI = mono screen
|
||||
add edi,[MonoOff] ;Add cursor offset
|
||||
mov eax,[character]
|
||||
mov ah,[BYTE PTR attrib]
|
||||
stosw
|
||||
|
||||
; Update cursor position.
|
||||
|
||||
inc [MonoX] ; X position moves.
|
||||
call Mono_Set_Cursor C,[MonoX],[MonoY]
|
||||
|
||||
??fini:
|
||||
ret
|
||||
|
||||
ENDP Mono_Put_Char
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_Draw_Rect - Draw a box on the mono screen.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Mono_Draw_Rect(X, Y, Width, Height, Attributes, Thickness)
|
||||
;*
|
||||
;* void Mono_Draw_Rect();
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Draw a rectangle text box on the mono screen.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* X - X coordinate position of upperleft corner.
|
||||
;* Y - Y coordinate position of upperleft corner.
|
||||
;* Width - Desired width.
|
||||
;* Height - Desired height.
|
||||
;* Attributes - Display attributes.
|
||||
;* Thickness - Line thickness.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_Draw_Rect:NEAR
|
||||
PROC Mono_Draw_Rect C NEAR
|
||||
ARG xpos:DWORD
|
||||
ARG ypos:DWORD
|
||||
ARG width:DWORD
|
||||
ARG height:DWORD
|
||||
ARG attrib:DWORD
|
||||
ARG thick:DWORD
|
||||
|
||||
; Exit if mono disabled
|
||||
|
||||
pushad
|
||||
cmp [MonoEnabled],0
|
||||
je ??fini
|
||||
|
||||
; Select the character table for the desired line thickness
|
||||
|
||||
mov edi,OFFSET CharData
|
||||
mov cl,3
|
||||
mov eax,[thick]
|
||||
and eax,011b
|
||||
shl eax,cl
|
||||
add edi,eax
|
||||
|
||||
; Prep width and height.
|
||||
|
||||
cmp [width],2
|
||||
jb ??fini
|
||||
|
||||
cmp [height],2
|
||||
jb ??fini
|
||||
|
||||
sub [width],2
|
||||
sub [height],2
|
||||
|
||||
; Set cursor position to upperleft corner of box
|
||||
|
||||
push [MonoY]
|
||||
push [MonoX] ;Save current cursor position
|
||||
call Mono_Set_Cursor C,[xpos],[ypos]
|
||||
|
||||
; Draw the rectangle
|
||||
|
||||
mov esi,OFFSET BoxData
|
||||
|
||||
; Determine the number of characters to output
|
||||
|
||||
??drawloop:
|
||||
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:
|
||||
xor eax,eax
|
||||
mov al,[BYTE PTR edi]
|
||||
call Mono_Put_Char C,eax,[attrib] ;Output the character.
|
||||
|
||||
mov al,[BYTE PTR esi+1]
|
||||
cbw
|
||||
cwde
|
||||
add eax,[MonoY]
|
||||
push eax
|
||||
mov al,[BYTE PTR esi]
|
||||
cbw
|
||||
cwde
|
||||
add eax,[MonoX]
|
||||
dec eax ; Undo cursor advance.
|
||||
push eax
|
||||
call Mono_Set_Cursor ; Properly advance cursor.
|
||||
add sp,8
|
||||
loop ??runloop
|
||||
|
||||
; Advance to next control entry.
|
||||
|
||||
??donerun:
|
||||
add esi,3
|
||||
inc edi
|
||||
cmp [BYTE PTR esi+2],-1
|
||||
jne ??drawloop
|
||||
|
||||
; Restore cursor to original position.
|
||||
|
||||
call Mono_Set_Cursor
|
||||
add sp,8
|
||||
|
||||
??fini:
|
||||
popad
|
||||
ret
|
||||
|
||||
ENDP Mono_Draw_Rect
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_Text_Print - Print a string to the mono screen at a specified
|
||||
;* position.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Mono_Text_Print(String, X, Y, Attributes, Update)
|
||||
;*
|
||||
;* void Mono_Text_Print(char *, long, long, long, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Print a NULL terminated string to the mono screen at the specified
|
||||
;* cooridinates and attributes.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* String - Pointer to NULL terminated string.
|
||||
;* X - X coordinate position.
|
||||
;* Y - Y coordinate position.
|
||||
;* Attributes - Display attributes
|
||||
;* Update - Update cursor position flag.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C _Mono_Text_Print:NEAR
|
||||
PROC _Mono_Text_Print C NEAR USES eax esi
|
||||
ARG text:NEAR PTR
|
||||
ARG xpos:DWORD
|
||||
ARG ypos:DWORD
|
||||
ARG attrib:DWORD
|
||||
ARG update:DWORD
|
||||
|
||||
; Save the current cursor position.
|
||||
|
||||
push [MonoY]
|
||||
push [MonoX]
|
||||
cmp [text],0 ;Exit if the string is NULL
|
||||
je short ??fini
|
||||
|
||||
call Mono_Set_Cursor C,[xpos],[ypos]
|
||||
|
||||
; Print string to the mono screen
|
||||
|
||||
mov esi,[text] ;Text pointer
|
||||
|
||||
??charloop:
|
||||
mov eax,[esi]
|
||||
inc esi
|
||||
or al,al ;Stop on a NULL
|
||||
je short ??fini
|
||||
|
||||
cmp al,13 ;Special processing for '\r'
|
||||
je short ??cr
|
||||
|
||||
; Output character to mono screen
|
||||
|
||||
??normal:
|
||||
xor ah,ah
|
||||
call Mono_Put_Char C,eax,[attrib]
|
||||
|
||||
; Perform adjustments if wrapping past right margin.
|
||||
|
||||
cmp [MonoX],80
|
||||
jb short ??nowrap
|
||||
|
||||
inc [ypos]
|
||||
call Mono_Set_Cursor C,0,[ypos]
|
||||
jmp short ??nowrap
|
||||
|
||||
; Move to start of next line.
|
||||
|
||||
??cr:
|
||||
inc [ypos]
|
||||
call Mono_Set_Cursor C,[xpos],[ypos]
|
||||
|
||||
; Scroll the monochrome screen if necessary.
|
||||
|
||||
??nowrap:
|
||||
cmp [MonoY],25
|
||||
jb short ??noscroll
|
||||
|
||||
call Mono_Scroll C,1
|
||||
dec [ypos]
|
||||
|
||||
??noscroll:
|
||||
jmp short ??charloop
|
||||
|
||||
??fini:
|
||||
cmp [update],0
|
||||
jne short ??noupdate
|
||||
|
||||
call Mono_Set_Cursor
|
||||
|
||||
??noupdate:
|
||||
pop eax
|
||||
pop eax
|
||||
ret
|
||||
|
||||
ENDP _Mono_Text_Print
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_Text_Print - Print a string to the mono screen. (ASM call)
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Mono_Text_Print(String, X, Y, Attributes)
|
||||
;*
|
||||
;* void Mono_Text_Print(char *, long, long, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Print a NULL terminated string to the mono screen at the specified
|
||||
;* cooridinates and attributes.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* String - Pointer to NULL terminated string.
|
||||
;* X - X coordinate position.
|
||||
;* Y - Y coordinate position.
|
||||
;* Attributes - Display attributes
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;* SEE ALSO
|
||||
;* _Mono_Text_Print
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_Text_Print:NEAR
|
||||
PROC Mono_Text_Print C NEAR USES
|
||||
ARG text:NEAR PTR
|
||||
ARG xpos:DWORD
|
||||
ARG ypos:DWORD
|
||||
ARG attrib:DWORD
|
||||
|
||||
; Exit if mono disabled
|
||||
|
||||
cmp [MonoEnabled],0
|
||||
je short ??fini
|
||||
|
||||
call _Mono_Text_Print C,[text],[xpos],[ypos],[attrib],0
|
||||
|
||||
??fini:
|
||||
ret
|
||||
|
||||
ENDP Mono_Text_Print
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_Print - Print a string to the mono screen.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Mono_Print(String)
|
||||
;*
|
||||
;* void Mono_Print(char *);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Print a string to the mono screen at the current cursor position and
|
||||
;* update the cursor position.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* String - Pointer to NULL terminated string.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_Print:NEAR
|
||||
PROC Mono_Print C NEAR
|
||||
ARG text:NEAR PTR
|
||||
|
||||
; Exit if mono disabled
|
||||
|
||||
cmp [MonoEnabled],0
|
||||
je short ??fini
|
||||
|
||||
call _Mono_Text_Print C,[text],[MonoX],[MonoY],2,1
|
||||
|
||||
??fini:
|
||||
ret
|
||||
|
||||
ENDP Mono_Print
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Mono_View_Page - View a mono page.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Oldpage = Mono_View_Page(Page)
|
||||
;*
|
||||
;* long Mono_View_Page(long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Displays the specified page in displayable mono memory.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Page - Page to view.
|
||||
;*
|
||||
;* RESULT
|
||||
;* Oldpage - Previous page.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Mono_View_Page:NEAR
|
||||
PROC Mono_View_Page C NEAR USES ds es eax ebx ecx edi esi
|
||||
ARG page:DWORD
|
||||
LOCAL oldpage:DWORD
|
||||
|
||||
; Prepare the original page number for return to caller.
|
||||
|
||||
cld
|
||||
mov ebx,[PageMap]
|
||||
mov [oldpage],ebx
|
||||
|
||||
; Exit of mono disabled
|
||||
|
||||
cmp [MonoEnabled],0
|
||||
je short ??fini
|
||||
|
||||
; 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
|
||||
push ds
|
||||
pop es
|
||||
lea edi,[PageMap]
|
||||
repne scasw
|
||||
neg ecx
|
||||
add ecx,7 ; CX = 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
|
||||
|
||||
shl ecx,8
|
||||
add ecx,eax
|
||||
mov esi,ecx
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov ax,034h
|
||||
mov ds,ax
|
||||
ENDIF
|
||||
|
||||
mov edi,0B0000h
|
||||
|
||||
; 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:
|
||||
mov eax,[oldpage]
|
||||
ret
|
||||
|
||||
ENDP Mono_View_Page
|
||||
|
||||
END
|
||||
|
66
VQ/VQM32/MONO.H
Normal file
66
VQ/VQM32/MONO.H
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMMONO_H
|
||||
#define VQMMONO_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* mono.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Mono screen definitions. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* Feburary 8, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cdecl Mono_Enable(void);
|
||||
void cdecl Mono_Disable(void);
|
||||
void cdecl Mono_Set_Cursor(long x, long y);
|
||||
void cdecl Mono_Clear_Screen(void);
|
||||
void cdecl Mono_Scroll(long lines);
|
||||
void cdecl Mono_Put_Char(long character, long attrib);
|
||||
void cdecl Mono_Draw_Rect(long x, long y, long w, long h, long attrib,
|
||||
long thick);
|
||||
|
||||
void cdecl Mono_Text_Print(void const *text, long x, long y, long attrib);
|
||||
void cdecl Mono_Print(void const *text);
|
||||
short cdecl Mono_View_Page(long page);
|
||||
short cdecl Mono_X(void);
|
||||
short cdecl Mono_Y(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VQMMONO_H */
|
319
VQ/VQM32/PALETTE.ASM
Normal file
319
VQ/VQM32/PALETTE.ASM
Normal file
@@ -0,0 +1,319 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* palette.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* Hardware level palette routines. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Bill Randolph
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* January 26, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* To write palette colors:
|
||||
;* - Out color # to 3c8h
|
||||
;* - Out RGB values to 3c9h (data must be written in three's; PEL address
|
||||
;* register auto-increments after 3 reads or writes)
|
||||
;*
|
||||
;* A time interval of about 240 ns is required between successive reads/
|
||||
;* writes; on very fast machines, this means that the system may not be
|
||||
;* able to handle a rapid-fire of RGB values. So, a "safe" routine is
|
||||
;* provided that has wait states between each out.
|
||||
;*
|
||||
;* Reference: Progammers Guide to the EGA & VGA Cards, Ferraro, 2nd ed.
|
||||
;* (Chapter 8.)
|
||||
;*
|
||||
;* Note that, if you set the palette in active scan, the screen will
|
||||
;* flash; to prevent this, wait for vertical retrace (Vertical Blank
|
||||
;* Interval), or turn the display off by using the Screen Off field in
|
||||
;* the Clocking Mode register (Hmmmm....).
|
||||
;*
|
||||
;* To read palette colors:
|
||||
;* - Out color # to 3c7h
|
||||
;* - In RGB values from 3c9h (data must be read in three's; PEL address
|
||||
;* register auto-increments after 3 reads or writes)
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* SetPalette - Set the palette without waiting to Vblank.
|
||||
;* ReadPalette - Read the palette from the display adapter.
|
||||
;* SetDAC - Set a single palette color in the DAC.
|
||||
;* TranslatePalette - Translate 24-bit color to 15-bit color.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
INCLUDE "vga.i"
|
||||
CODESEG
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* SetPalette - Set the palette without waiting to Vblank.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* SetPalette(Palette, Numbytes, SlowFlag)
|
||||
;*
|
||||
;* void SetPalette(char *, long, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Palette - Pointer to the palette to set.
|
||||
;* NumBytes - Number of bytes of palette to transfer (multiple of 3).
|
||||
;* SlowFlag - Slow palette set flag.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C SetPalette:NEAR
|
||||
PROC SetPalette C NEAR USES eax ecx edx esi ds
|
||||
|
||||
ARG palette:NEAR PTR
|
||||
ARG numbytes:DWORD
|
||||
ARG slowpal:DWORD
|
||||
|
||||
pushf
|
||||
cld
|
||||
|
||||
cmp [slowpal],0 ;Do slow palette?
|
||||
jne ??safe_palette_routine
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Fast palette set
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
mov esi,[palette]
|
||||
mov edx,PEL_WRITE_ADDR
|
||||
xor al,al
|
||||
out dx,al ;Select color to write too.
|
||||
inc al ;Step to the next color for next loop
|
||||
inc edx ;DX = PEL_DATA
|
||||
mov ecx,[numbytes] ;Max # colors to set
|
||||
rep outsb ;Write 256 * RGB out to the palette
|
||||
popf
|
||||
ret
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Safe palette set
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
??safe_palette_routine:
|
||||
mov esi,[palette]
|
||||
mov ecx,[numbytes]
|
||||
mov edx,PEL_WRITE_ADDR
|
||||
sub eax,eax
|
||||
out dx,al
|
||||
mov edx,PEL_DATA
|
||||
|
||||
??Write_loop:
|
||||
lodsb
|
||||
out dx,al ;Red
|
||||
jmp $+02 ;Delay (flush instruction cache)
|
||||
|
||||
lodsb
|
||||
out dx,al ;Green
|
||||
jmp $+02 ;Delay (flush instruction cache)
|
||||
|
||||
lodsb
|
||||
out dx,al ;Blue
|
||||
jmp $+02 ;Delay (flush instruction cache)
|
||||
|
||||
sub cx,3
|
||||
ja ??Write_loop
|
||||
|
||||
popf
|
||||
ret
|
||||
|
||||
ENDP SetPalette
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* ReadPalette - Read the palette from the display adapter.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* ReadPalette(Palette)
|
||||
;*
|
||||
;* void SetPalette(char *);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Palette - Pointer buffer to copy palette into.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C ReadPalette:NEAR
|
||||
PROC ReadPalette C NEAR USES ecx edx edi es
|
||||
|
||||
ARG palette:NEAR PTR
|
||||
|
||||
mov edi,[palette]
|
||||
mov ecx,256
|
||||
mov edx,PEL_READ_ADDR
|
||||
sub eax,eax
|
||||
out dx,al
|
||||
mov edx,PEL_DATA
|
||||
|
||||
??Read_loop:
|
||||
in al,dx ;Red
|
||||
stosb ;Save the byte
|
||||
jmp $+02 ;Delay (flush instruction cache)
|
||||
|
||||
in al,dx ;Green
|
||||
stosb ;Save the byte
|
||||
jmp $+02 ;Delay (flush instruction cache)
|
||||
|
||||
in al,dx ;Blue
|
||||
stosb ;Save the byte
|
||||
jmp $+02 ;Delay (flush instruction cache)
|
||||
|
||||
dec ecx
|
||||
jnz ??Read_loop
|
||||
ret
|
||||
|
||||
ENDP ReadPalette
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* SetDAC - Set a single palette color in the DAC.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* SetDAC(ColorNum, Red, Green, Blue)
|
||||
;*
|
||||
;* void SetPalette(long, char, char);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* ColorNum - Position number in palette of color to set.
|
||||
;* Red - Red gun value.
|
||||
;* Green - Green gun value.
|
||||
;* Blue - Blue gun value.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C SetDAC:NEAR
|
||||
PROC SetDAC C NEAR USES edx
|
||||
|
||||
ARG color_num:DWORD
|
||||
ARG red:BYTE
|
||||
ARG green:BYTE
|
||||
ARG blue:BYTE
|
||||
|
||||
mov edx,PEL_WRITE_ADDR
|
||||
mov eax,[color_num]
|
||||
out dx,al ;Set color position
|
||||
inc edx
|
||||
jmp $+02 ;Delay (flush instruction cache)
|
||||
|
||||
mov al,[red]
|
||||
out dx,al ;Set red gun
|
||||
jmp $+02 ;Delay (flush instruction cache)
|
||||
|
||||
mov al,[green]
|
||||
out dx,al ;Set green gun
|
||||
jmp $+02 ;Delay (flush instruction cache)
|
||||
|
||||
mov al,[blue]
|
||||
out dx,al ;Set blue gun
|
||||
ret
|
||||
|
||||
ENDP SetDAC
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* TranslatePalette - Translate 24-bit color to 15-bit color.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* TranslatePalette(Pal24, Pal15, NumBytes)
|
||||
;*
|
||||
;* void TranslatePalette(char *, char *, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Pal24 - Pointer to 24-bit palette. (Input)
|
||||
;* Pal15 - Pointer to 15-bit palette. (Output)
|
||||
;* NumBytes - Number of bytes to translate. (divisible by 3)
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C TranslatePalette:NEAR
|
||||
PROC TranslatePalette C NEAR USES ecx edx edi esi
|
||||
|
||||
ARG pal24:NEAR PTR
|
||||
ARG pal15:NEAR PTR
|
||||
ARG numbytes:DWORD
|
||||
|
||||
mov esi,[pal24]
|
||||
mov edi,[pal15]
|
||||
mov ecx,[numbytes]
|
||||
|
||||
??TranslatePalette:
|
||||
mov ah,[BYTE PTR esi] ;AH = red
|
||||
mov al,[BYTE PTR esi+1] ;AL = green
|
||||
mov dl,[BYTE PTR esi+2] ;DL = blue
|
||||
shr ah,1 ;Red = lower 5 bits of AH
|
||||
shl al,2 ;Green = upper 6 bits of AL
|
||||
shr dl,1 ;Blue = lower 5 bits of DL
|
||||
shl eax,2 ;Make room for blue
|
||||
and al,0E0h ;Trim off bottom bit of green
|
||||
or al,dl ;Load in blue bits
|
||||
mov [WORD PTR edi],ax ;Store the value
|
||||
add esi,3 ;Increment to next RGB values
|
||||
add edi,2 ;Increment to next palette word
|
||||
sub ecx,3
|
||||
ja ??TranslatePalette
|
||||
ret
|
||||
|
||||
ENDP TranslatePalette
|
||||
|
||||
END
|
59
VQ/VQM32/PALETTE.H
Normal file
59
VQ/VQM32/PALETTE.H
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMPALETTE_H
|
||||
#define VQMPALETTE_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* Palette.h (32-Bit protected mode)
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Palette definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* Febuary 3, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cdecl SetPalette(unsigned char *palette,long numbytes,unsigned long slowpal);
|
||||
void cdecl ReadPalette(void *palette);
|
||||
void cdecl SetDAC(long color, long red, long green, long blue);
|
||||
void cdecl TranslatePalette(void *pal24, void *pal15, long numbytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
void SortPalette(unsigned char *pal, long numcolors);
|
||||
|
||||
#endif /* VQMPALETTE_H */
|
||||
|
116
VQ/VQM32/PORTIO.ASM
Normal file
116
VQ/VQM32/PORTIO.ASM
Normal file
@@ -0,0 +1,116 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* portio.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* I/O Port access. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* January 26, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* inp - Read a byte from a hardware port.
|
||||
;* outp - Write a byte to a hardware port.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
CODESEG
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* inp - Read a byte from a hardware port.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Data = inp(PortID)
|
||||
;*
|
||||
;* short inp(unsinged short);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* PortID - Address if hardware port.
|
||||
;*
|
||||
;* RESULT
|
||||
;* Data - Data read from port.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C inp:NEAR
|
||||
PROC inp C NEAR USES edx
|
||||
ARG port:WORD
|
||||
|
||||
mov dx,[port]
|
||||
xor eax,eax
|
||||
in al,dx
|
||||
ret
|
||||
|
||||
ENDP inp
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* outp - Write a byte to a hardware port.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* outp(PortID, Value)
|
||||
;*
|
||||
;* void outp(unsinged short, short);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* PortID - Address if hardware port.
|
||||
;* Value - Value to write.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C outp:NEAR
|
||||
PROC outp C NEAR USES edx
|
||||
ARG port:WORD
|
||||
ARG value:WORD
|
||||
|
||||
mov dx,[port]
|
||||
mov ax,[value]
|
||||
out dx,al
|
||||
ret
|
||||
|
||||
ENDP outp
|
||||
|
||||
END
|
57
VQ/VQM32/PORTIO.H
Normal file
57
VQ/VQM32/PORTIO.H
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMPORTIO_H
|
||||
#define VQMPORTIO_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* Portio.h (32-Bit protected mode)
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Hardware port I/O
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* Febuary 3, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
short cdecl inp(unsigned short portid);
|
||||
void cdecl outp(unsigned short portid, short value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __BORLANDC__ */
|
||||
|
||||
#endif /* VQMPORTIO_H */
|
||||
|
431
VQ/VQM32/PROFILE.CPP
Normal file
431
VQ/VQM32/PROFILE.CPP
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* profile.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* INI file processing. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Bill Randolph
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* Get_Frame_Pathname - Get pathname for a given frame and file type.
|
||||
* GetINIInt - Get an integer value from an INI file.
|
||||
* GetINIString - Get a string from the INI file.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "profile.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* PRIVATE DECLARATIONS
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) (((a)>(b))?(a):(b))
|
||||
#endif
|
||||
#ifndef min
|
||||
#define min(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#define isspace(c) ((c==' ')||(c=='\t')||(c=='\n')||(c=='\r')?1:0)
|
||||
|
||||
static char *strtrim(char *string);
|
||||
static long FileGets(FILE *fp, char *buf, long buflen);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* Get_Frame_Pathname - Get pathname for a given frame and file type.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = Get_Frame_Pathname(IniFile, Frame, Extension, Buffer)
|
||||
*
|
||||
* long Get_Frame_Pathname(char *, long, char *, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* IniFile - Pointer to INI filename.
|
||||
* Frame - Number of frame to get filename for.
|
||||
* Extension - File extension type.
|
||||
* Buffer - Pointer to buffer to put pathname into.
|
||||
*
|
||||
* RESULT
|
||||
* Error - 0 if successful, or -1 if error.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
long Get_Frame_Pathname(char *inifile, long anim_frame, char *ext,
|
||||
char *outbuf)
|
||||
{
|
||||
char rootdir[_MAX_PATH]; // Root directory from INI file
|
||||
char extdir[_MAX_PATH]; // this extension's directory
|
||||
char entry_name[40]; // INI entry name
|
||||
char inibuf[80]; // string returned from INI file
|
||||
char *prefix; // 4-char prefix for this scene
|
||||
char *startstr; // starting frame #, string
|
||||
char *endstr; // ending frame #, string
|
||||
char *palstr; // palette filename string
|
||||
long startnum; // scene's starting frame #
|
||||
long endnum; // scene's ending frame #
|
||||
long total_frames; // accumulated frame total
|
||||
long scene_frames; // # frames in a given scene
|
||||
long scene_num; // scene #
|
||||
long file_frame; // file's frame #
|
||||
long rc;
|
||||
|
||||
/* Get directory for this file type */
|
||||
GetINIString("Path", "Root", "", rootdir, 80, inifile);
|
||||
|
||||
if (rootdir[strlen (rootdir) - 1] != '\\') {
|
||||
strcat(rootdir,"\\");
|
||||
}
|
||||
|
||||
GetINIString("Path", ext, "", extdir, 80, inifile);
|
||||
|
||||
if (extdir[strlen (extdir) - 1] != '\\') {
|
||||
strcat(extdir,"\\");
|
||||
}
|
||||
|
||||
/* VQG is a special case:
|
||||
*
|
||||
* The VQG files are named based upon the 1st 4 characters of the 'Name'
|
||||
* entry in the INI file, and their numbers match the actual animation
|
||||
* frame numbers, not the scene frame numbers.
|
||||
*/
|
||||
if (!stricmp(ext, "VQG")) {
|
||||
GetINIString("Common", "Name", "", inibuf, 80, inifile);
|
||||
|
||||
if (strlen(inibuf) > 4) {
|
||||
inibuf[4] = 0;
|
||||
}
|
||||
|
||||
sprintf(outbuf,"%s%s%s%04d.%s",rootdir,extdir,inibuf,anim_frame,ext);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Loop through scenes until the desired frame # is found
|
||||
*-----------------------------------------------------------------------*/
|
||||
total_frames = 0;
|
||||
scene_num = 1;
|
||||
|
||||
while (1) {
|
||||
|
||||
/* Get this scene's entry */
|
||||
sprintf(entry_name, "Scene%d", scene_num);
|
||||
rc = GetINIString("Scenes",entry_name,"",inibuf,80,inifile);
|
||||
|
||||
if (rc == 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Parse the INI entry */
|
||||
prefix = strtok(inibuf, ",");
|
||||
startstr = strtok(NULL, ",");
|
||||
endstr = strtok(NULL, ",");
|
||||
palstr = strtok(NULL, ",");
|
||||
|
||||
if ((prefix == NULL) || (startstr == NULL) || (endstr == NULL)) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
startnum = atoi(startstr);
|
||||
endnum = atoi(endstr);
|
||||
scene_frames = ((endnum - startnum) + 1);
|
||||
|
||||
/* requested frame is found */
|
||||
if (anim_frame < (total_frames + scene_frames)) {
|
||||
|
||||
/* Palette is a special case */
|
||||
if (!stricmp(ext, "PAL")) {
|
||||
if (palstr == NULL) {
|
||||
return (-1);
|
||||
} else {
|
||||
sprintf(outbuf, "%s%s%s.PAL", rootdir, extdir, palstr);
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
file_frame = ((anim_frame - total_frames) + startnum);
|
||||
sprintf(outbuf,"%s%s%s%04d.%s",rootdir,extdir,prefix,file_frame,ext);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Frame not found; go to next scene */
|
||||
total_frames += scene_frames;
|
||||
scene_num++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* GetINIInt - Get an integer value from an INI file.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Value = GetINIInt(Section, Entry, Default, ININame)
|
||||
*
|
||||
* long GetINIInt(char *, char *, long, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Retrieve an integer value from the INI file at the specified 'Section'
|
||||
* and 'Entry' fields. If no value is defined then return the passed in
|
||||
* 'Default' value.
|
||||
*
|
||||
* INPUTS
|
||||
* Section - Pointer to section name.
|
||||
* Entry - Pointer to entry name.
|
||||
* Default - Default value.
|
||||
* ININame - Pointer to INI filename.
|
||||
*
|
||||
* RESULT
|
||||
* Value - Integer value from INI file or 'Default'.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long GetINIInt(char const *section, char const *entry, long deflt,
|
||||
char *fname)
|
||||
{
|
||||
char buffer[20];
|
||||
|
||||
sprintf(buffer, "%d", deflt);
|
||||
GetINIString(section, entry, buffer, buffer, sizeof(buffer),
|
||||
fname);
|
||||
|
||||
return (atoi(buffer));
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* GetINIString - Get a string from the INI file.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Length = GetINIString(Section, Entry, Default, Buffer,
|
||||
* Length, ININame)
|
||||
*
|
||||
* long GetINIString(char *, char *, char *, char *, long,
|
||||
* char *);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* Section - Pointer to section name.
|
||||
* Entry - Pointer to entry name.
|
||||
* Default - Pointer to default string.
|
||||
* Buffer - Pointer to buffer to copy string into.
|
||||
* Length - Maximum length of string.
|
||||
* ININame - Pointer to INI filename.
|
||||
*
|
||||
* RESULT
|
||||
* Length - Length of string copied into the buffer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long GetINIString(char const *section, char const *entry,
|
||||
char const *def, char *retbuffer, long retlen, char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
long retval;
|
||||
char txt[80];
|
||||
char secname[40];
|
||||
long len;
|
||||
char *workptr;
|
||||
|
||||
/* Copy default value in case entry isn't found */
|
||||
strncpy(retbuffer, def, (retlen - 1));
|
||||
retbuffer[retlen - 1] = 0;
|
||||
retval = min(strlen(def), (unsigned)retlen);
|
||||
|
||||
/* Open the file */
|
||||
if ((fp = fopen(fname, "rt")) == NULL) {
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* Generate section name for search */
|
||||
sprintf(secname, "[%s]", section);
|
||||
len = strlen(secname);
|
||||
|
||||
/* Scan file for section name */
|
||||
while (1) {
|
||||
|
||||
/* Read line; return if end-of-file */
|
||||
if (FileGets(fp,txt,80)!=0) {
|
||||
fclose(fp);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* Skip comments */
|
||||
if (txt[0] == ';') continue;
|
||||
|
||||
/* Parse a section name */
|
||||
if (txt[0] == '[') {
|
||||
if (!memicmp(secname, txt, len)) break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan file for desired entry */
|
||||
len = strlen(entry);
|
||||
|
||||
while (1) {
|
||||
|
||||
/* Read line; return if end-of-file */
|
||||
if (FileGets(fp, txt, 80) != 0) {
|
||||
fclose(fp);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* Skip comments */
|
||||
if (txt[0] == ';') continue;
|
||||
|
||||
/* Return if start of next section reached */
|
||||
if (txt[0] == '[') {
|
||||
fclose(fp);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* Entry found; parse it */
|
||||
if (!memicmp(entry, txt, len) && (isspace(txt[len])
|
||||
|| txt[len] == '=')) {
|
||||
|
||||
fclose(fp);
|
||||
|
||||
/* Find '=' character */
|
||||
workptr = strchr(txt, '=');
|
||||
|
||||
/* Return if not found */
|
||||
if (workptr == NULL) return (retval);
|
||||
|
||||
/* Skip past '=' */
|
||||
workptr++;
|
||||
|
||||
/* Skip white space */
|
||||
while (isspace(*workptr) && strlen(workptr) > 0) {
|
||||
workptr++;
|
||||
}
|
||||
|
||||
/* Return if no string left */
|
||||
if ((*workptr) == 0) return (retval);
|
||||
|
||||
strtrim(workptr);
|
||||
strcpy(retbuffer,workptr);
|
||||
|
||||
return (strlen(workptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* strtrim - Trim off trailing spaces from a string.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* String = strtrim(String)
|
||||
*
|
||||
* char *strtrim(char *);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* String - Pointer to string to trim.
|
||||
*
|
||||
* RESULT
|
||||
* String - Pointer to trimmed string.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static char *strtrim(char *string)
|
||||
{
|
||||
long i;
|
||||
|
||||
/* Return if NULL ptr or zero-length string */
|
||||
if ((string == NULL) || (strlen(string) == 0)) {
|
||||
return (string);
|
||||
}
|
||||
|
||||
/* Find 1st non-white-space character from the right */
|
||||
i = (strlen(string) - 1);
|
||||
|
||||
while ((i > 0) && isspace(string[i])) {
|
||||
i--;
|
||||
}
|
||||
|
||||
/* Set end of string */
|
||||
i++;
|
||||
string[i] = 0;
|
||||
|
||||
return (string);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* FileGets - A better fgets.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = FileGets(FilePtr, Buffer, Length)
|
||||
*
|
||||
* long FileGets(FILE *, char *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* FilePtr - File pointer.
|
||||
* Buffer - Pointer to buffer to fill.
|
||||
* Length - Maximum length of buffer.
|
||||
*
|
||||
* RESULT
|
||||
* Error = 0 if successfull, or -1 if error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static long FileGets(FILE *fp, char *buf, long buflen)
|
||||
{
|
||||
if (fgets(buf, buflen, fp)) {
|
||||
buf[(strlen(buf) - 1)] = 0;
|
||||
return (0);
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
52
VQ/VQM32/PROFILE.H
Normal file
52
VQ/VQM32/PROFILE.H
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMPROFILE_H
|
||||
#define VQMPROFILE_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* Profile.h (32-Bit protected mode)
|
||||
*
|
||||
* DESCRIPTION
|
||||
* INI file profiling definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Prototypes */
|
||||
long GetINIInt(char const *section, char const *entry,
|
||||
long deflt, char *fname);
|
||||
|
||||
long GetINIString(char const *section, char const *entry,
|
||||
char const *def, char *retbuffer, long retlen, char *fname);
|
||||
|
||||
long Get_Frame_Pathname(char *inifile,long anim_frame,char *ext,
|
||||
char *outbuf);
|
||||
|
||||
#endif /* VQMPROFILE_H */
|
||||
|
82
VQ/VQM32/REALMODE.H
Normal file
82
VQ/VQM32/REALMODE.H
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMREALMODE_H
|
||||
#define VQMREALMODE_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* realmode.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Real-mode interfacing definitions and equates. Many of the definitions
|
||||
* and descriptions in this file were taken from other sources and
|
||||
* compiled here for use in MISC32 library.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* Febuary 6, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* REALPTR: Real-mode pointer (segment:offset16).
|
||||
*
|
||||
* The REALPTR data type is used in protected mode to hold real-mode
|
||||
* pointers. The type is an unsigned long value, were the upper 16 bits
|
||||
* are the segment number and the lower 16 bit are an offset. This type
|
||||
* and the associated macros are identical to that of the PHARLAP "pltypes.h"
|
||||
* definitions for easy of conversion to WATCOM/4GW.
|
||||
*/
|
||||
typedef unsigned long REALPTR;
|
||||
|
||||
#define RP_OFF(rp) ((unsigned short)(((unsigned long)(rp)) & 0xFFFF))
|
||||
#define RP_SEG(rp) ((unsigned short)(((unsigned long)(rp)) >> 16))
|
||||
#define RP_SET(rp, off, seg) (rp = ((unsigned long)(seg) << 16) + (off))
|
||||
#define RP_INCR(rp, incr) (rp += ((unsigned long)(incr)) & 0xFFFF)
|
||||
|
||||
#define MK_PTR(off, seg) (void *)((((unsigned long)seg&0xFFFF)<<4)+off)
|
||||
|
||||
/* RMInfo: Real-mode interrupt call structure.
|
||||
*
|
||||
* Information that needs to be passed down to the real-mode interrupt is
|
||||
* transfered using this structure. The address to this protected-mode
|
||||
* structure (allocated by user) is passed into DPMI function 0x300. DOS/4GW
|
||||
* will then use this information to set up the real-mode registers, switch
|
||||
* to real-mode and then execute the interrupt in real-mode.
|
||||
*/
|
||||
typedef struct _RMInfo {
|
||||
long edi;
|
||||
long esi;
|
||||
long ebp;
|
||||
long reservedbysystem;
|
||||
long ebx;
|
||||
long edx;
|
||||
long ecx;
|
||||
long eax;
|
||||
short flags;
|
||||
short es,ds,fs,gs,ip,cs,sp,ss;
|
||||
} RMInfo;
|
||||
|
||||
#endif /* VQMREALMODE_H */
|
||||
|
315
VQ/VQM32/SORTPAL.CPP
Normal file
315
VQ/VQM32/SORTPAL.CPP
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* sortpal.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Palette sorting routines. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
* Bill Randolph
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* SortPalette - Sort a palette.
|
||||
* Comp_Luminance - Compare the luminace of two 24-bit palette entries.
|
||||
* Comp_HSV - Compare the HSV of two 24-bit palette entries.
|
||||
* RGB_To_HSV - Convert RGB color to HSV color.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "palette.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* PRIVATE DECLARATIONS
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/* HSV color model */
|
||||
#define DIVIDE_WITH_ROUND(n,d) (unsigned short)(((n)/(d))+ \
|
||||
(unsigned short)(((n)%(d)) >= (((d)+1)>>1)))
|
||||
|
||||
#define HSV_BASE 255
|
||||
#define HUE_WEIGHT 10L
|
||||
#define SATURATION_WEIGHT 100L
|
||||
#define VALUE_WEIGHT 1000L
|
||||
|
||||
/* Prototypes */
|
||||
static int Comp_Luminance(const void *elem1, const void *elem2);
|
||||
static int Comp_HSV(const void *elem1, const void *elem2);
|
||||
static void RGB_To_HSV(unsigned short r, unsigned short g, unsigned short b,
|
||||
unsigned short *h, unsigned short *s, unsigned short *v);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SortPalette - Sort a palette.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* SortPalette(Palette, NumColors)
|
||||
*
|
||||
* void SortPalette(unsigned char *, long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Sort the palette colors.
|
||||
*
|
||||
* INPUTS
|
||||
* Palette - Pointer to palette to sort.
|
||||
* NumColors - Number of colors in the palette.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void SortPalette(unsigned char *pal, long numcolors)
|
||||
{
|
||||
qsort(pal, numcolors, 3, Comp_Luminance);
|
||||
|
||||
pal[0] = 0;
|
||||
pal[1] = 0;
|
||||
pal[2] = 0;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* Comp_Luminance - Compare the luminace of two 24-bit palette entries.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Result = Comp_Luminance(Color1, Color2)
|
||||
*
|
||||
* long Comp_Luminance(void *, void *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Compare the luminace of the two colors and determine which color is
|
||||
* brighter than the other.
|
||||
*
|
||||
* The computation used is:
|
||||
* Luminance = (red * .299) + (green * .587) + (blue * .114)
|
||||
*
|
||||
* INPUTS
|
||||
* Color1 - Pointer to palette entry.
|
||||
* Color2 - Pointer to palette entry.
|
||||
*
|
||||
* RESULT
|
||||
* Result - 0 = same, 1 = Color1 > Color2, -1 = Color1 < Color2
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int Comp_Luminance(const void *elem1, const void *elem2)
|
||||
{
|
||||
unsigned char *pal;
|
||||
long r,g,b;
|
||||
long total1,total2;
|
||||
|
||||
/* Compute luminance for color1 */
|
||||
pal = (unsigned char *)elem1;
|
||||
r = ((long)pal[0]);
|
||||
g = ((long)pal[1]);
|
||||
b = ((long)pal[2]);
|
||||
total1 = ((r * 19595L) + (g * 38470L) + (b * 7471L));
|
||||
|
||||
/* Compute luminance for color2 */
|
||||
pal = (unsigned char *)elem2;
|
||||
r = ((long)pal[0]);
|
||||
g = ((long)pal[1]);
|
||||
b = ((long)pal[2]);
|
||||
total2 = ((r * 19595L) + (g * 38470L) + (b * 7471L));
|
||||
|
||||
if (total1 < total2) {
|
||||
return (-1);
|
||||
} else if (total1 > total2) {
|
||||
return (1);
|
||||
} else {
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* Comp_HSV - Compare the HSV of two 24-bit palette entries.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Result = Comp_HSV(Color1, Color2)
|
||||
*
|
||||
* long Comp_HSV(void *, void *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Compare the HSV color values of two colors and determine the
|
||||
* relationship between the colors in the color space.
|
||||
*
|
||||
* INPUTS
|
||||
* Color1 - Pointer to 1st palette entry.
|
||||
* Color2 - Pointer to 2nd palette entry.
|
||||
*
|
||||
* RESULT
|
||||
* Result - 0 = same, 1 = Color1 > Color2, -1 = Color1 < Color2
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int Comp_HSV(const void *elem1, const void *elem2)
|
||||
{
|
||||
unsigned char *pal;
|
||||
unsigned char r,g,b;
|
||||
unsigned short h,s,v;
|
||||
unsigned long key1,key2;
|
||||
long retval;
|
||||
|
||||
/* Convert 1st element to HSV */
|
||||
pal = (unsigned char *)elem1;
|
||||
r = pal[0];
|
||||
g = pal[1];
|
||||
b = pal[2];
|
||||
|
||||
RGB_To_HSV((unsigned short)r,(unsigned short)g,(unsigned short)b,&h,&s,&v);
|
||||
key1 = ((h * HUE_WEIGHT) + (s * SATURATION_WEIGHT) + (v * VALUE_WEIGHT));
|
||||
|
||||
/* Convert 2nd element to HSV */
|
||||
pal = (unsigned char *)elem2;
|
||||
r = pal[0];
|
||||
g = pal[1];
|
||||
b = pal[2];
|
||||
|
||||
RGB_To_HSV((unsigned short)r,(unsigned short)g,(unsigned short)b,&h,&s,&v);
|
||||
key2 = ((h * HUE_WEIGHT) + (s * SATURATION_WEIGHT) + (v * VALUE_WEIGHT));
|
||||
|
||||
if (key1 != key2) {
|
||||
retval = ((key1 < key2) ? -1 : 1);
|
||||
} else {
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* RGB_To_HSV - Convert RGB color to HSV color.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* RGB_To_HSV(R, G, B, H, S, V)
|
||||
*
|
||||
* void RGB_To_HSV(unsigned short, unsigned short, unsigned short,
|
||||
* unsigned short *, unsigned short *, unsigned short *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Convert the RBG color to a HSV color. Assumes 8 bits per gun of R, G
|
||||
* and B data. Also the HSV is based on a 255 degree scale rather than
|
||||
* the more accurate 360 degree scale.
|
||||
*
|
||||
* INPUTS
|
||||
* R - Red gun value.
|
||||
* G - Green gun value.
|
||||
* B - Blue gun value.
|
||||
* H - Pointer to H value. (H will be set upon return of this function)
|
||||
* S - Pointer to S value. (S will be set upon return of this function)
|
||||
* V - Pointer to V value. (V will be set upon return of this function)
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
static void RGB_To_HSV(unsigned short r, unsigned short g, unsigned short b,
|
||||
unsigned short *h, unsigned short *s, unsigned short *v)
|
||||
{
|
||||
unsigned short m;
|
||||
unsigned short r1;
|
||||
unsigned short g1;
|
||||
unsigned short b1;
|
||||
unsigned short tmp;
|
||||
|
||||
/* 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 {
|
||||
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);
|
||||
}
|
||||
}
|
1271
VQ/VQM32/SOSCODEC.ASM
Normal file
1271
VQ/VQM32/SOSCODEC.ASM
Normal file
File diff suppressed because it is too large
Load Diff
90
VQ/VQM32/SOSCOMP.H
Normal file
90
VQ/VQM32/SOSCOMP.H
Normal 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/>.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* File : soscomp.h
|
||||
* Date Created : 6/1/94
|
||||
* Description :
|
||||
*
|
||||
* Programmer(s) : Nick Skrepetos
|
||||
* Last Modification : 10/1/94 - 11:37:9 AM
|
||||
* Additional Notes : Modified by Denzil E. Long, Jr.
|
||||
*
|
||||
*****************************************************************************
|
||||
* Copyright (c) 1994, HMI, Inc. All Rights Reserved *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _SOS_COMPRESS
|
||||
#define _SOS_COMPRESS
|
||||
|
||||
/* compression types */
|
||||
enum {
|
||||
_ADPCM_TYPE_1,
|
||||
};
|
||||
|
||||
/* define compression structure */
|
||||
typedef struct _tagCOMPRESS_INFO {
|
||||
char *lpSource;
|
||||
char *lpDest;
|
||||
unsigned long dwCompSize;
|
||||
unsigned long dwUnCompSize;
|
||||
short wBitSize;
|
||||
short wChannels;
|
||||
unsigned long dwSampleIndex;
|
||||
long dwPredicted;
|
||||
long dwDifference;
|
||||
short wCodeBuf;
|
||||
short wCode;
|
||||
short wStep;
|
||||
short wIndex;
|
||||
|
||||
unsigned long dwSampleIndex2; //added BP for channel 2
|
||||
long dwPredicted2; //added BP for channel 2
|
||||
long dwDifference2; //added BP for channel 2
|
||||
short wCodeBuf2; //added BP for channel 2
|
||||
short wCode2; //added BP for channel 2
|
||||
short wStep2; //added BP for channel 2
|
||||
short wIndex2; //added BP for channel 2
|
||||
} _SOS_COMPRESS_INFO;
|
||||
|
||||
/* compressed file type header */
|
||||
typedef struct _tagCOMPRESS_HEADER {
|
||||
unsigned long dwType; // type of compression
|
||||
unsigned long dwCompressedSize; // compressed file size
|
||||
unsigned long dwUnCompressedSize; // uncompressed file size
|
||||
unsigned long dwSourceBitSize; // original bit size
|
||||
char szName[16]; // file type, for error checking
|
||||
} _SOS_COMPRESS_HEADER;
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cdecl sosCODECInitStream(_SOS_COMPRESS_INFO *);
|
||||
unsigned long cdecl sosCODECCompressData(_SOS_COMPRESS_INFO *,unsigned long);
|
||||
unsigned long cdecl sosCODECDecompressData(_SOS_COMPRESS_INFO *,unsigned long);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
699
VQ/VQM32/TARGA.CPP
Normal file
699
VQ/VQM32/TARGA.CPP
Normal file
@@ -0,0 +1,699 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* targa.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Targa Image File reader. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* OpenTarga - Open Targa image file.
|
||||
* CloseTarga - Close Targa image file.
|
||||
* LoadTarga - Load Targa image file.
|
||||
* XFlipTarga - X flip the image.
|
||||
* YFlipTarga - Y flip the image.
|
||||
*
|
||||
* PRIVATE
|
||||
* DecodeImageData - Decompress Targa image data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <mem.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys\stat.h>
|
||||
#include "targa.h"
|
||||
|
||||
/* Private data declerations. */
|
||||
static long DecodeImageData(TGAHandle *, char *);
|
||||
static void InvertImageData(TGAHeader *, char *);
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* OpenTarga - Open Targa image file.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* TGAHandle = OpenTarga(Name, Mode)
|
||||
*
|
||||
* TGAHandle *OpenTarga(char *, unsigned short);
|
||||
*
|
||||
* FUNCTION
|
||||
* Open a Targa image file and read in its header. The file stream will
|
||||
* positioned after the ID field (if there is one).
|
||||
*
|
||||
* INPUTS
|
||||
* Name - Pointer to name of Targa file.
|
||||
* Mode - Access mode.
|
||||
*
|
||||
* RESULT
|
||||
* TGAHandle - Pointer to initialized TGAHandle or NULL if error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
TGAHandle *OpenTarga(char *name, unsigned short mode)
|
||||
{
|
||||
TGAHandle *tga;
|
||||
long size;
|
||||
long error = 0;
|
||||
|
||||
/* Allocate TGAHandle */
|
||||
if ((tga = (TGAHandle *)malloc(sizeof(TGAHandle))) != NULL) {
|
||||
|
||||
/* Initialize TGAHandle structure. */
|
||||
memset((void *)tga, 0, sizeof(TGAHandle));
|
||||
tga->mode = mode;
|
||||
|
||||
switch (mode) {
|
||||
|
||||
/* Open targa file for read. */
|
||||
case TGA_READMODE:
|
||||
if ((tga->fh = open(name, (O_RDONLY|O_BINARY))) != -1) {
|
||||
|
||||
/* Read in header. */
|
||||
size = read(tga->fh, &tga->header, sizeof(TGAHeader));
|
||||
|
||||
if (size != sizeof(TGAHeader)) {
|
||||
error = 1;
|
||||
}
|
||||
|
||||
/* Skip the ID field */
|
||||
if (!error && (tga->header.IDLength != 0)) {
|
||||
if (lseek(tga->fh, tga->header.IDLength, SEEK_CUR) == -1) {
|
||||
error = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Open targa file for write. */
|
||||
case TGA_WRITEMODE:
|
||||
if ((tga->fh = open(name, (O_CREAT|O_TRUNC|O_WRONLY|O_BINARY),
|
||||
(S_IREAD|S_IWRITE))) == -1) {
|
||||
|
||||
error = 1;
|
||||
} else {
|
||||
printf("\r");
|
||||
}
|
||||
break;
|
||||
|
||||
/* Open targa file for read/write.*/
|
||||
case TGA_RDWRMODE:
|
||||
if ((tga->fh = open(name, (O_RDWR|O_BINARY),
|
||||
(S_IREAD|S_IWRITE))) != -1) {
|
||||
|
||||
/* Read in header. */
|
||||
size = read(tga->fh, &tga->header, sizeof(TGAHeader));
|
||||
|
||||
if (size != sizeof(TGAHeader)) {
|
||||
error = 1;
|
||||
}
|
||||
|
||||
/* Skip the ID field */
|
||||
if (!error && (tga->header.IDLength != 0)) {
|
||||
if (lseek(tga->fh, tga->header.IDLength, SEEK_CUR) == -1) {
|
||||
error = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Close on any error! */
|
||||
if (error) {
|
||||
CloseTarga(tga);
|
||||
tga = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (tga);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* CloseTarga - Close Targa image file.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* CloseTarga(TGAHandle)
|
||||
*
|
||||
* void CloseTarga(TGAHandle *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Close the Targa image file and free its handle.
|
||||
*
|
||||
* INPUTS
|
||||
* TGAHandle - Pointer to TGAHandle returned by OpenTarga().
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void CloseTarga(TGAHandle *tga)
|
||||
{
|
||||
/* Ensure valid handle. */
|
||||
if (tga) {
|
||||
|
||||
/* Close the file if it is open. */
|
||||
if (tga->fh != -1) close(tga->fh);
|
||||
|
||||
/* Free TGAHandle */
|
||||
free(tga);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* LoadTarga - Load Targa Image File.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = LoadTarga(Name, Palette, ImageBuffer)
|
||||
*
|
||||
* long LoadTarga(char *, char *, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Open and load the Targa into the specified buffers. If either buffer
|
||||
* pointer is NULL then that field will not be processed.
|
||||
*
|
||||
* INPUTS
|
||||
* Name - Name of Targa image file to load.
|
||||
* Palette - Pointer to buffer to load the palette into.
|
||||
* ImageBuffer - Pointer to buffer to load the image data into.
|
||||
*
|
||||
* RESULT
|
||||
* Error - 0 if successful, or TGAERR_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long LoadTarga(char *name, char *palette, char *image)
|
||||
{
|
||||
TGAHandle *tga;
|
||||
long size;
|
||||
long depth;
|
||||
long i,n;
|
||||
char c;
|
||||
long error = 0;
|
||||
|
||||
/* Open the Targa */
|
||||
if ((tga = OpenTarga(name, TGA_READMODE)) != NULL) {
|
||||
|
||||
/* Process ColorMap (palette) */
|
||||
if (tga->header.ColorMapType == 1) {
|
||||
depth = (tga->header.CMapDepth >> 3);
|
||||
size = (tga->header.CMapLength * depth);
|
||||
|
||||
/* Load the palette from the TGA if a palette buffer is provided
|
||||
* otherwise we will skip it.
|
||||
*/
|
||||
if ((palette != NULL) && (tga->header.CMapLength > 0)) {
|
||||
|
||||
/* Adjust palette to the starting color entry. */
|
||||
palette += (tga->header.CMapStart * depth);
|
||||
|
||||
/* Read in the palette. */
|
||||
if (read(tga->fh, palette, size) == size) {
|
||||
|
||||
/* Swap the byte ordering of the palette entries. */
|
||||
for (i = 0; i < tga->header.CMapLength; i++) {
|
||||
#if(0)
|
||||
for (n = 0; n < depth; n++) {
|
||||
c = *(palette + n);
|
||||
*(palette + n) = *(palette + ((depth - 1) - n));
|
||||
*(palette + ((depth - 1) - n)) = c;
|
||||
}
|
||||
#else
|
||||
c = *palette;
|
||||
*palette = *(palette + (depth - 1));
|
||||
*(palette + (depth - 1)) = c;
|
||||
#endif
|
||||
|
||||
/* Next entry */
|
||||
palette += depth;
|
||||
}
|
||||
} else {
|
||||
error = TGAERR_READ;
|
||||
}
|
||||
} else {
|
||||
if (lseek(tga->fh, size, SEEK_CUR) == -1) {
|
||||
error = TGAERR_READ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Load the image data from the TGA if an image buffer is provided
|
||||
* otherwise we are done.
|
||||
*/
|
||||
if (!error && (image != NULL)) {
|
||||
depth = (tga->header.PixelDepth >> 3);
|
||||
size = ((tga->header.Width * tga->header.Height) * depth);
|
||||
|
||||
switch (tga->header.ImageType) {
|
||||
case TGA_CMAPPED:
|
||||
if (read(tga->fh, image, size) != size) {
|
||||
error = TGAERR_READ;
|
||||
}
|
||||
break;
|
||||
|
||||
case TGA_TRUECOLOR:
|
||||
if (read(tga->fh, image, size) == size) {
|
||||
InvertImageData(&tga->header, image);
|
||||
} else {
|
||||
error = TGAERR_READ;
|
||||
}
|
||||
break;
|
||||
|
||||
case TGA_CMAPPED_ENCODED:
|
||||
error = DecodeImageData(tga, image);
|
||||
break;
|
||||
|
||||
case TGA_TRUECOLOR_ENCODED:
|
||||
if ((error = DecodeImageData(tga, image)) == NULL) {
|
||||
InvertImageData(&tga->header, image);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error = TGAERR_NOTSUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Arrange the image so that the origin position (coordinate 0,0)
|
||||
* is the upperleft hand corner of the image.
|
||||
*/
|
||||
if (!error) {
|
||||
if (tga->header.ImageDescriptor & TGAF_XORIGIN) {
|
||||
XFlipTarga(&tga->header, image);
|
||||
}
|
||||
|
||||
if ((tga->header.ImageDescriptor & TGAF_YORIGIN) == 0) {
|
||||
YFlipTarga(&tga->header, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the Targa */
|
||||
CloseTarga(tga);
|
||||
} else {
|
||||
error = TGAERR_OPEN;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SaveTarga - Save a Targa Image File.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = SaveTarga(Name, TGAHeader, Palette, ImageBuffer)
|
||||
*
|
||||
* long SaveTarga(char *, TGAHeader *, char *, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* Name - Pointer to name of file to save.
|
||||
* TGAHeader - Pointer to initialized targa header structure.
|
||||
* Palette - Pointer to palette.
|
||||
* ImageBuffer - Pointer to raw image data.
|
||||
*
|
||||
* RESULT
|
||||
* Error - 0 if successful, or TGAERR_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long SaveTarga(char *name, TGAHeader *tgahd, char *palette, char *image)
|
||||
{
|
||||
TGAHandle *tga;
|
||||
long size;
|
||||
long depth;
|
||||
char *temppal;
|
||||
char *ptr;
|
||||
long i,n;
|
||||
char c;
|
||||
long error = 0;
|
||||
|
||||
/* Open the Targa for write. */
|
||||
if ((tga = OpenTarga(name, TGA_WRITEMODE)) != NULL) {
|
||||
|
||||
/* Write the header. */
|
||||
if (write(tga->fh, tgahd, sizeof(TGAHeader)) != sizeof(TGAHeader)) {
|
||||
error = TGAERR_WRITE;
|
||||
}
|
||||
|
||||
/* Write the palette. */
|
||||
if (!error && (palette != NULL) && (tgahd->CMapLength > 0)) {
|
||||
|
||||
/* Adjust palette to the starting color entry. */
|
||||
depth = (tgahd->CMapDepth >> 3);
|
||||
palette += (tgahd->CMapStart * depth);
|
||||
size = (tgahd->CMapLength * depth);
|
||||
|
||||
/* Allocate temporary buffer for palette manipulation. */
|
||||
if ((temppal = (char *)malloc(size)) != NULL) {
|
||||
memcpy(temppal, palette, size);
|
||||
ptr = temppal;
|
||||
|
||||
/* Swap the byte ordering of the palette entries. */
|
||||
for (i = 0; i < tga->header.CMapLength; i++) {
|
||||
for (n = 0; n < (depth >> 1); n++) {
|
||||
c = *(ptr + n);
|
||||
*(ptr + n) = *(ptr + (depth - n));
|
||||
*(ptr + (depth - n)) = c;
|
||||
}
|
||||
|
||||
/* Next entry */
|
||||
palette += depth;
|
||||
}
|
||||
|
||||
/* Write the palette. */
|
||||
if (write(tga->fh, temppal, size) != size) {
|
||||
error = TGAERR_WRITE;
|
||||
}
|
||||
|
||||
/* Free temporary palette buffer. */
|
||||
free(temppal);
|
||||
} else {
|
||||
error = TGAERR_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invert truecolor data. */
|
||||
if (tgahd->ImageType == TGA_TRUECOLOR) {
|
||||
InvertImageData(tgahd, image);
|
||||
}
|
||||
|
||||
/* Write the image. */
|
||||
if (!error && (image != NULL)) {
|
||||
depth = (tgahd->PixelDepth >> 3);
|
||||
size = (((tgahd->Width * tgahd->Height)) * depth);
|
||||
|
||||
if (write(tga->fh, image, size) != size) {
|
||||
error = TGAERR_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close targa file. */
|
||||
CloseTarga(tga);
|
||||
} else {
|
||||
error = TGAERR_OPEN;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* XFlipTarga - X flip the image.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* XFlipTarga(TGAHeader, Image)
|
||||
*
|
||||
* void XFlipTarga(TGAHeader *, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Flip the image in memory on its X axis. (left to right)
|
||||
*
|
||||
* INPUTS
|
||||
* TGAHeader - Pointer to initialized TGAHeader structure.
|
||||
* Image - Pointer to image buffer.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void XFlipTarga(TGAHeader *tga, char *image)
|
||||
{
|
||||
char *ptr,*ptr1;
|
||||
long x,y,d;
|
||||
char v,v1;
|
||||
char depth;
|
||||
|
||||
/* Pixel depth in bytes. */
|
||||
depth = (tga->PixelDepth >> 3);
|
||||
|
||||
for (y = 0; y < tga->Height; y++) {
|
||||
ptr = (image + ((tga->Width * depth) * y));
|
||||
ptr1 = (ptr + ((tga->Width * depth) - depth));
|
||||
|
||||
for (x = 0; x < (tga->Width / 2); x++) {
|
||||
for (d = 0; d < depth; d++) {
|
||||
v = *(ptr + d);
|
||||
v1 = *(ptr1 + d);
|
||||
*(ptr + d) = v1;
|
||||
*(ptr1 + d) = v;
|
||||
}
|
||||
|
||||
ptr += depth;
|
||||
ptr1 -= depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* YFlipTarga - Y flip the image.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* YFlipTarga(TGAHeader, Image)
|
||||
*
|
||||
* void YFlipTarga(TGAHeader *, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Flip the image in memory on its Y axis. (top to bottom)
|
||||
*
|
||||
* INPUTS
|
||||
* TGAHeader - Pointer to initialized TGAHeader structure.
|
||||
* Image - Pointer to image buffer.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void YFlipTarga(TGAHeader *tga, char *image)
|
||||
{
|
||||
char *ptr,*ptr1;
|
||||
long x,y;
|
||||
char v,v1;
|
||||
char depth;
|
||||
|
||||
/* Pixel depth in bytes. */
|
||||
depth = (tga->PixelDepth >> 3);
|
||||
|
||||
for (y = 0; y < (tga->Height >> 1); y++) {
|
||||
|
||||
/* Compute address of lines to exchange. */
|
||||
ptr = (image + ((tga->Width * y) * depth));
|
||||
ptr1 = (image + ((tga->Width * (tga->Height - 1)) * depth));
|
||||
ptr1 -= ((tga->Width * y) * depth);
|
||||
|
||||
/* Exchange all the pixels on this scan line. */
|
||||
for (x = 0; x < (tga->Width * depth); x++) {
|
||||
v = *ptr;
|
||||
v1 = *ptr1;
|
||||
*ptr = v1;
|
||||
*ptr1 = v;
|
||||
ptr++;
|
||||
ptr1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* DecodeImageData - Decompress Targa image data.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = DecodeImageData(TGAHandle, ImageBuffer)
|
||||
*
|
||||
* long DecodeImageData(TGAHandle *, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Decode the RLE compressed image data into the specified buffer from
|
||||
* the file I/O stream.
|
||||
*
|
||||
* INPUTS
|
||||
* TGAHandle - Pointer to TGAHandle returned by OpenTarga().
|
||||
* ImageBuffer - Pointer to buffer to decompress image into.
|
||||
*
|
||||
* RESULT
|
||||
* Error - 0 if successful, or TGAERR_??? error code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static long DecodeImageData(TGAHandle *tga, char *image)
|
||||
{
|
||||
char *packet;
|
||||
unsigned char count;
|
||||
unsigned char depth;
|
||||
unsigned long pixel_count;
|
||||
unsigned long size;
|
||||
unsigned long c,i;
|
||||
long error = 0;
|
||||
|
||||
/* Compute pixel depth in bytes. */
|
||||
depth = (tga->header.PixelDepth >> 3);
|
||||
|
||||
/* Total number of pixels compressed in this image. */
|
||||
pixel_count = (tga->header.Width * tga->header.Height);
|
||||
|
||||
/* Allocate packet buffer to hold maximum encoded data run. */
|
||||
if ((packet = (char *)malloc(128 * depth)) != NULL) {
|
||||
while ((pixel_count > 0) && !error) {
|
||||
|
||||
/* Read count. */
|
||||
if (read(tga->fh, &count, 1) == 1) {
|
||||
|
||||
/* If bit 8 of the count is set then we have a run of pixels,
|
||||
* otherwise the data is raw pixels.
|
||||
*/
|
||||
if (count & 0x80) {
|
||||
count &= 0x7F;
|
||||
count++;
|
||||
|
||||
/* Read in run pixel. */
|
||||
if (read(tga->fh, packet, depth) == depth) {
|
||||
|
||||
/* Repeat the pixel for the run count in the image buffer. */
|
||||
for (c = 0; c < count; c++) {
|
||||
for (i = 0; i < depth; i++) {
|
||||
*image++ = *(packet + i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error = TGAERR_READ;
|
||||
}
|
||||
} else {
|
||||
count++;
|
||||
size = (count * depth);
|
||||
|
||||
/* Read in raw pixels. */
|
||||
if (read(tga->fh, packet, size) == size) {
|
||||
|
||||
/* Copy the raw pixel data into the image buffer. */
|
||||
memcpy(image, packet, size);
|
||||
image += size;
|
||||
} else {
|
||||
error = TGAERR_READ;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the pixel count. */
|
||||
pixel_count -= count;
|
||||
} else {
|
||||
error = TGAERR_READ;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free packet buffer. */
|
||||
free(packet);
|
||||
} else {
|
||||
error = TGAERR_NOMEM;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* InvertImageData - Invert TrueColor image data.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* InvertImageData(TGAHeader, ImageData)
|
||||
*
|
||||
* void InvertImageData(TGAHeader *, char *);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* TGAHeader - Pointer to initialized TGAHeader structure.
|
||||
* ImageData - Pointer to TrueColor image data.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void InvertImageData(TGAHeader *tga, char *image)
|
||||
{
|
||||
long depth;
|
||||
long pixel_count;
|
||||
long i;
|
||||
char c;
|
||||
|
||||
/* Compute the pixel depth in bytes. */
|
||||
depth = (tga->PixelDepth >> 3);
|
||||
|
||||
/* Total number of pixels in this image. */
|
||||
pixel_count = (tga->Width * tga->Height);
|
||||
|
||||
/* 16-bit pixel layout is different that 24-bit and 32-bit. */
|
||||
if (depth > 2) {
|
||||
while (pixel_count > 0) {
|
||||
for (i = 0; i < (depth / 2); i++) {
|
||||
c = *(image + i);
|
||||
*(image + i) = *(image + ((depth - 1) - i));
|
||||
*(image + ((depth - 1) - i)) = c;
|
||||
}
|
||||
|
||||
/* Next pixel */
|
||||
pixel_count--;
|
||||
image += depth;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
|
130
VQ/VQM32/TARGA.H
Normal file
130
VQ/VQM32/TARGA.H
Normal 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/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMTARGA_H
|
||||
#define VQMTARGA_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* Targa.h (32-Bit protected mode)
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Targa Image File definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Targa Header definitions
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/* TGAHeader - Targa Image File header.
|
||||
*
|
||||
* IDLength - Size of Image ID field
|
||||
* ColorMapType - Color map type.
|
||||
* ImageType - Image type code.
|
||||
* CMapStart - Color map origin.
|
||||
* CMapLength - Color map length.
|
||||
* CMapDepth - Depth of color map entries.
|
||||
* XOffset - X origin of image.
|
||||
* YOffset - Y origin of image.
|
||||
* Width - Width of image.
|
||||
* Height - Height of image.
|
||||
* PixelDepth - Image pixel size
|
||||
* ImageDescriptor - Image descriptor byte.
|
||||
*/
|
||||
typedef struct _TGAHeader {
|
||||
char IDLength;
|
||||
char ColorMapType;
|
||||
char ImageType;
|
||||
short CMapStart;
|
||||
short CMapLength;
|
||||
char CMapDepth;
|
||||
short XOffset;
|
||||
short YOffset;
|
||||
short Width;
|
||||
short Height;
|
||||
char PixelDepth;
|
||||
char ImageDescriptor;
|
||||
} TGAHeader;
|
||||
|
||||
/* ImageType definiton */
|
||||
#define TGA_NOIMAGE 0 /* No image data included in file */
|
||||
#define TGA_CMAPPED 1 /* Color-mapped image data */
|
||||
#define TGA_TRUECOLOR 2 /* Truecolor image data */
|
||||
#define TGA_MONO 3 /* Monochrome image data */
|
||||
#define TGA_CMAPPED_ENCODED 9 /* Color-mapped image data (Encoded) */
|
||||
#define TGA_TRUECOLOR_ENCODED 10 /* Truecolor image data (Encoded) */
|
||||
#define TGA_MONO_ENCODED 11 /* Monochrome image data (Encoded) */
|
||||
|
||||
/* ImageDescriptor definition */
|
||||
#define TGAF_ATTRIB_BITS (0x0F<<0) /* Number of attribute bits per pixel */
|
||||
#define TGAF_XORIGIN (1<<4)
|
||||
#define TGAF_YORIGIN (1<<5)
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Targa Handle definitions
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/* TGAHandle - Targa Image File handle.
|
||||
*
|
||||
* fh - File handle returned by open().
|
||||
* mode - Access mode.
|
||||
* header - TGAHeader structure.
|
||||
*/
|
||||
typedef struct _TGAHandle {
|
||||
short fh;
|
||||
unsigned short mode;
|
||||
TGAHeader header;
|
||||
} TGAHandle;
|
||||
|
||||
/* Access modes. */
|
||||
#define TGA_READMODE 0
|
||||
#define TGA_WRITEMODE 1
|
||||
#define TGA_RDWRMODE 2
|
||||
|
||||
/* Error codes */
|
||||
#define TGAERR_OPEN -1
|
||||
#define TGAERR_READ -2
|
||||
#define TGAERR_WRITE -3
|
||||
#define TGAERR_SYNTAX -4
|
||||
#define TGAERR_NOMEM -5
|
||||
#define TGAERR_NOTSUPPORTED -6
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Function prototypes
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
TGAHandle *OpenTarga(char *, unsigned short);
|
||||
void CloseTarga(TGAHandle *);
|
||||
long LoadTarga(char *, char *, char *);
|
||||
long SaveTarga(char *, TGAHeader *, char *, char *);
|
||||
void XFlipTarga(TGAHeader *, char *);
|
||||
void YFlipTarga(TGAHeader *, char *);
|
||||
|
||||
#endif /* VQMTARGA_H */
|
||||
|
10
VQ/VQM32/TASM32.CFG
Normal file
10
VQ/VQM32/TASM32.CFG
Normal file
@@ -0,0 +1,10 @@
|
||||
/t
|
||||
/m
|
||||
/w+
|
||||
/jJUMPS
|
||||
/ml
|
||||
/p
|
||||
/z
|
||||
/iC:\PROJECTS\INCLUDE
|
||||
/zi
|
||||
/dPHARLAP_TNT=1
|
104
VQ/VQM32/TESTVB.CPP
Normal file
104
VQ/VQM32/TESTVB.CPP
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* testvb.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Video mode setting. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* Febuary 3, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* TestVBIBit - Test the polarity of the vertical blank bit.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys\timeb.h>
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#include "portio.h"
|
||||
#else
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* TestVBIBit - Test the polarity of the vertical blank bit.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Polarity = TestVBIBit()
|
||||
*
|
||||
* long TestVBIBit(void);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
* Polarity - Polarity of the vertical blank bit.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long TestVBIBit(void)
|
||||
{
|
||||
static struct timeb mytime;
|
||||
long curtime;
|
||||
long endtime;
|
||||
unsigned long high = 0;
|
||||
unsigned long low = 0;
|
||||
|
||||
/* Set the check time for .25 (1/4) of a second. */
|
||||
ftime(&mytime);
|
||||
curtime = ((mytime.time * 1000) + mytime.millitm);
|
||||
endtime = (curtime + (1000 / 4));
|
||||
|
||||
/* Sample the vertical blank bit for the specified period of time.
|
||||
* The state in which it is in the least is the vertical blank state,
|
||||
* the state in which it is in the most is the active scan state.
|
||||
*/
|
||||
while (endtime >= curtime) {
|
||||
ftime(&mytime);
|
||||
curtime = ((mytime.time * 1000) + mytime.millitm);
|
||||
|
||||
if (inp(0x3DA) & 0x08) {
|
||||
high++;
|
||||
} else {
|
||||
low++;
|
||||
}
|
||||
}
|
||||
|
||||
return (high > low);
|
||||
}
|
||||
|
||||
|
||||
|
56
VQ/VQM32/TEXT.H
Normal file
56
VQ/VQM32/TEXT.H
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMTEXT_H
|
||||
#define VQMTEXT_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* text.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Text printing definitions. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* March 13, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
long cdecl Text_Print(char *string, long x, long y, long fcol, long bcol);
|
||||
void cdecl Draw_Char(long character, long x, long y);
|
||||
void cdecl Set_Font_Palette_Range(void *palette, long start, long end);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VQMTEXT_H */
|
||||
|
178
VQ/VQM32/TEXTPRNT.ASM
Normal file
178
VQ/VQM32/TEXTPRNT.ASM
Normal file
@@ -0,0 +1,178 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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: J:\vq\projects\vqm32\textprnt.asv 1.5 27 Jul 1995 13:57:04 DENZIL_LONG $
|
||||
;***************************************************************************
|
||||
;** 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 : TEXTPRNT.ASM *
|
||||
;* *
|
||||
;* Programmer : David R. Dettmer *
|
||||
;* *
|
||||
;* Start Date : January 28, 1992 *
|
||||
;* *
|
||||
;* Last Update : February 3, 1992 [DRD] *
|
||||
;* *
|
||||
;*-------------------------------------------------------------------------*
|
||||
;* Functions: *
|
||||
;* *
|
||||
; VOID Text_Print(BYTE *string, WORD x_pixel, WORD y_pixel, *
|
||||
; WORD fcolor, WORD bcolor); *
|
||||
;* *
|
||||
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
CODESEG
|
||||
|
||||
XPIXEL_MAX EQU 320
|
||||
YPIXEL_MAX EQU 200
|
||||
|
||||
FONTINFOBLOCK EQU 4
|
||||
FONTOFFSETBLOCK EQU 6
|
||||
FONTWIDTHBLOCK EQU 8
|
||||
FONTDATABLOCK EQU 10
|
||||
FONTHEIGHTBLOCK EQU 12
|
||||
|
||||
FONTINFOMAXHEIGHT EQU 4
|
||||
FONTINFOMAXWIDTH EQU 5
|
||||
|
||||
EXTRN C Char_Pixel_Width:NEAR
|
||||
EXTRN C Draw_Char:NEAR
|
||||
EXTRN C Set_Font_Palette_Range:NEAR
|
||||
EXTRN FontPtr:NEAR PTR
|
||||
EXTRN FontYSpacing:DWORD
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; TEXT_PRINT
|
||||
;
|
||||
; VOID Text_Print(BYTE *string, WORD x_pixel, WORD y_pixel,
|
||||
; WORD fcolor, WORD bcolor);
|
||||
;
|
||||
; Print the given string to the LogicPage.
|
||||
;
|
||||
; Bounds Checking:
|
||||
;
|
||||
; if x_pixel < 0, then x_pixel = 0
|
||||
; if x_pixel >= XPIXEL_MAX, then exit
|
||||
; if y_pixel < 0, then y_pixel = 0
|
||||
; if y_pixel >= YPIXEL_MAX, then exit
|
||||
;*
|
||||
|
||||
GLOBAL C Text_Print:NEAR
|
||||
PROC Text_Print C NEAR USES ebx ecx edx edi esi
|
||||
ARG string:NEAR PTR
|
||||
ARG x_pixel:DWORD
|
||||
ARG y_pixel:DWORD
|
||||
ARG fcol:DWORD
|
||||
ARG bcol:DWORD
|
||||
|
||||
LOCAL fwidth:DWORD ;Pixel width of font.
|
||||
LOCAL fgbg:DWORD ;Two bytes of background & foreground colors.
|
||||
LOCAL lines:DWORD ;Number of lines
|
||||
LOCAL fontheight:DWORD
|
||||
|
||||
; Make sure there is a font available. If not, then bail.
|
||||
|
||||
xor eax,eax
|
||||
mov [lines],eax
|
||||
|
||||
mov eax,[FontPtr]
|
||||
or eax,eax
|
||||
je ??exit
|
||||
|
||||
movzx ebx,[WORD PTR eax+FONTINFOBLOCK]
|
||||
add ebx,eax
|
||||
movzx eax,[BYTE PTR ebx+FONTINFOMAXHEIGHT]
|
||||
mov [fontheight],eax
|
||||
mov esi,[string]
|
||||
|
||||
mov ebx,[x_pixel] ; x pixel
|
||||
cmp ebx,XPIXEL_MAX ; check max x pos
|
||||
jae short ??exit
|
||||
|
||||
mov ecx,[y_pixel] ; y pixel
|
||||
cmp ecx,YPIXEL_MAX ; check max y pos
|
||||
jge short ??exit
|
||||
|
||||
mov al,[BYTE PTR bcol]
|
||||
mov ah,[BYTE PTR fcol]
|
||||
mov [fgbg],eax
|
||||
lea eax,[fgbg]
|
||||
call Set_Font_Palette_Range C,eax,0,1
|
||||
|
||||
; start of loop to print string
|
||||
|
||||
xor edx,edx
|
||||
inc [lines]
|
||||
??loop:
|
||||
mov dl,[esi]
|
||||
inc esi
|
||||
|
||||
cmp edx,0 ; end of string
|
||||
je short ??exit
|
||||
|
||||
cmp edx,13 ; cmp to a '\r'
|
||||
jne short ??chkxy
|
||||
|
||||
; Advance the screen to the left edge and down one line. Check
|
||||
; to see if the coordinate would still be visible. If not, then
|
||||
; bail.
|
||||
|
||||
??onelinedown:
|
||||
mov ebx,[x_pixel] ; get original x position
|
||||
add ecx,[fontheight]
|
||||
add ecx,[FontYSpacing]
|
||||
cmp ecx,YPIXEL_MAX ; check y pos
|
||||
jae short ??exit
|
||||
inc [lines]
|
||||
jmp ??loop
|
||||
|
||||
??chkxy:
|
||||
call Char_Pixel_Width C,edx
|
||||
|
||||
; Check to see if this character would spill past the right edge
|
||||
; of the screen. If it would then drop down a line.
|
||||
|
||||
mov [fwidth],eax ; save width of char for later
|
||||
add eax,ebx
|
||||
|
||||
cmp eax,XPIXEL_MAX ; check x pos
|
||||
ja short ??onelinedown
|
||||
|
||||
call Draw_Char C,edx,ebx,ecx
|
||||
|
||||
add ebx,[fwidth] ; add font width
|
||||
jmp ??loop
|
||||
|
||||
; Exit routine and unlock string if it was in EMS.
|
||||
|
||||
??exit:
|
||||
mov eax,[lines]
|
||||
ret
|
||||
|
||||
ENDP Text_Print
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
END
|
||||
|
1
VQ/VQM32/TLIB.CFG
Normal file
1
VQ/VQM32/TLIB.CFG
Normal file
@@ -0,0 +1 @@
|
||||
/C /E
|
5
VQ/VQM32/TLINK32.CFG
Normal file
5
VQ/VQM32/TLINK32.CFG
Normal file
@@ -0,0 +1,5 @@
|
||||
/c
|
||||
/m
|
||||
/Gm
|
||||
-LC:\PROJECTS\LIB;C:\DEV\BC4\LIB
|
||||
-v
|
137
VQ/VQM32/VB.ASM
Normal file
137
VQ/VQM32/VB.ASM
Normal file
@@ -0,0 +1,137 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* vb.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* Vertical blank routines. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* January 26, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* WaitNoVB - Wait for active scan.
|
||||
;* WaitVB - Wait for vertical blank.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
INCLUDE "video.i"
|
||||
CODESEG
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* WaitNoVB - Wait for active scan.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* WaitNoVB()
|
||||
;*
|
||||
;* void WaitNoVB(void);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Sit and wait for the active scan of the display.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* NONE
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C WaitNoVB:NEAR
|
||||
PROC WaitNoVB C NEAR USES edx
|
||||
ARG vbibit:DWORD
|
||||
|
||||
mov eax,[vbibit]
|
||||
and al,1
|
||||
shl al,3
|
||||
mov ah,al
|
||||
|
||||
; loop while VBL bit != VQ_VertBlank
|
||||
|
||||
??no_scan_yet:
|
||||
mov edx,03DAH
|
||||
in al,dx
|
||||
and al,8
|
||||
xor al,ah
|
||||
jnz short ??no_scan_yet
|
||||
ret
|
||||
|
||||
ENDP WaitNoVB
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* WaitVB - Wait for vertical blank.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* WaitVB()
|
||||
;*
|
||||
;* void WaitVB(void);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Sit and wait for the vertical blank of the display.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* NONE
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C WaitVB:NEAR
|
||||
PROC WaitVB C NEAR USES
|
||||
ARG vbibit:DWORD
|
||||
|
||||
mov eax,[vbibit]
|
||||
and al,1
|
||||
shl al,3
|
||||
mov ah,al
|
||||
|
||||
; Loop while VBL bit = VQ_VertBlank
|
||||
|
||||
??no_vbl_yet:
|
||||
mov edx,03DAH
|
||||
in al,dx
|
||||
and al,8
|
||||
xor al,ah
|
||||
jz short ??no_vbl_yet
|
||||
ret
|
||||
|
||||
ENDP WaitVB
|
||||
|
||||
END
|
49
VQ/VQM32/VERTAG.CPP
Normal file
49
VQ/VQM32/VERTAG.CPP
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
* VQMisc32 library.
|
||||
*
|
||||
* FILE
|
||||
* vertag.c (32-Bit protected mode)
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Embedded version string. This string is prefixed with a tag ("$VER$")
|
||||
* which can be search for to find this string.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* Febuary 8, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
#define DEVNAME "Watcom/4GW"
|
||||
#else
|
||||
#define DEVNAME "Borland/TNT"
|
||||
#endif
|
||||
|
||||
char VerTag[] = {"$VER$VQM32 2.12 "DEVNAME" ("__DATE__" "__TIME__")"};
|
135
VQ/VQM32/VESABLIT.CPP
Normal file
135
VQ/VQM32/VESABLIT.CPP
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* vesablit.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* VESA bitblit routines. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Bill Randolph
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* VESA_Blit_640x480 - Blit to 640x480 256 color VESA mode.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <mem.h>
|
||||
#include <dos.h>
|
||||
#include "video.h"
|
||||
#include "vesavid.h"
|
||||
#include "vesablit.h"
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* VESA_Blit_640x480 - Blit to 640x480 256 color VESA mode.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* VESA_Blit_640x480(DisplayInfo, Buffer, X, Y, Width, Height)
|
||||
*
|
||||
* void VESA_Blit_640x480(DisplayInfo *, char *, long, long, long, long);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* DisplayInfo - Pointer to display information structure.
|
||||
* Buffer - Pointer to buffer to blit to VRAM.
|
||||
* X - Destination X coordinate of blit (upper left).
|
||||
* Y - Destination Y coordinate of blit (upper left).
|
||||
* Width - Width of blit.
|
||||
* Height - Height of blit.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void VESA_Blit_640x480(DisplayInfo *disp,unsigned char *buf,long x1,long y1,
|
||||
long width,long height)
|
||||
{
|
||||
VESAModeInfo *vminfo;
|
||||
long bank;
|
||||
long last_bank;
|
||||
long bank_offset;
|
||||
long scrn_offset;
|
||||
long grains_per_win;
|
||||
long part1;
|
||||
long part2;
|
||||
long i;
|
||||
|
||||
/* Initialize values */
|
||||
vminfo = (VESAModeInfo *)disp->Extended;
|
||||
scrn_offset = ((disp->XRes * y1) + x1);
|
||||
grains_per_win = ((long)vminfo->WinSize / (long)vminfo->WinGranularity);
|
||||
bank_offset = scrn_offset % 65536L;
|
||||
last_bank = -1;
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
|
||||
/* Compute which bank this scanline is in */
|
||||
bank = (scrn_offset / 65536L);
|
||||
|
||||
/* Set a new bank */
|
||||
if (bank != last_bank) {
|
||||
SetVESAWindow(bank);
|
||||
last_bank = bank;
|
||||
bank_offset = (scrn_offset % 65536L);
|
||||
}
|
||||
|
||||
/* Copy a full scanline */
|
||||
if ((bank_offset + width) < 65536L) {
|
||||
Copy_Row((char *)buf, (char *)bank_offset, width);
|
||||
buf += width;
|
||||
scrn_offset += disp->XRes;
|
||||
bank_offset += disp->XRes;
|
||||
}
|
||||
|
||||
/* Copy two partial scanlines */
|
||||
else {
|
||||
part1 = (65536L - bank_offset);
|
||||
part2 = (width - part1);
|
||||
Copy_Row((char *)buf, (char *)bank_offset, part1);
|
||||
|
||||
buf += part1;
|
||||
bank += grains_per_win;
|
||||
last_bank += grains_per_win;
|
||||
SetVESAWindow(bank);
|
||||
Copy_Row((char *)buf, (char *)0, part2);
|
||||
|
||||
buf += part2;
|
||||
scrn_offset += disp->XRes;
|
||||
bank_offset = (scrn_offset % 65536L);
|
||||
}
|
||||
}
|
||||
}
|
71
VQ/VQM32/VESABLIT.H
Normal file
71
VQ/VQM32/VESABLIT.H
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMVESABLIT_H
|
||||
#define VQMVESABLIT_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* VESABlit.h (32-Bit protected mode)
|
||||
*
|
||||
* DESCRIPTION
|
||||
* VESA bitblit routines.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* Febuary 3, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <vqm32\video.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* FUNCTION PROTOTYPES
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
void VESA_Blit_640x480(DisplayInfo *disp,unsigned char *buf,long x1,
|
||||
long y1,long width,long height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cdecl Blit_VESA640x480(DisplayInfo *disp,unsigned char *buf,long x1,
|
||||
long y1,long width,long height);
|
||||
|
||||
void cdecl Buf_320x200_To_VESA_320x200(unsigned char *buffer, long grain);
|
||||
void cdecl Buf_320x200_To_VESA_640x400(unsigned char *buffer, long grain);
|
||||
void cdecl Buf_320x200_To_VESA_32K(unsigned char *buffer,
|
||||
unsigned char *palette, long grain);
|
||||
|
||||
void cdecl Copy_Row(char *, char *, long);
|
||||
void cdecl Copy_Word_Row(char *source, char *dest, char *palette,
|
||||
long numbytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VQMVESABLIT_H */
|
||||
|
722
VQ/VQM32/VESABUF.ASM
Normal file
722
VQ/VQM32/VESABUF.ASM
Normal file
@@ -0,0 +1,722 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* vesabuf.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* VESA buffered blit routines. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Bill Randolph
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* Febuary 3, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* Buf_320x200_To_VESA_320x200 - Buffer copy, unscaled
|
||||
;* Buf_320x200_To_VESA_640x400 - Scales and copies 320x200 to 640x400
|
||||
;* Buf_320x200_To_VESA_32K - Copies 320x200 buffer to VESA 32K
|
||||
;* colors
|
||||
;* Copy_Row - Copy a row of pixels to VRAM.
|
||||
;* Copy_Word_Row - Copy a row of 15-bit pixels to VRAM
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
INCLUDE "video.i"
|
||||
CODESEG
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; DRAW_BLOCK_ROWS: draws 'numrows' rows of 2x2 blocks
|
||||
; Set ES:DI to current screen location
|
||||
; Set DS:SI to current source location
|
||||
; Uses: ax, cx, dx
|
||||
;---------------------------------------------------------------------------
|
||||
MACRO DRAW_BLOCK_ROWS numrows
|
||||
LOCAL ??Start_row
|
||||
LOCAL ??Not_finished_a_line
|
||||
LOCAL ??Done
|
||||
|
||||
mov edx,numrows
|
||||
??Start_row:
|
||||
mov ecx,320
|
||||
|
||||
??Not_finished_a_line:
|
||||
mov al,[BYTE PTR esi]
|
||||
mov ah,al
|
||||
inc esi
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov [WORD PTR es:edi],ax
|
||||
mov [WORD PTR es:edi+640],ax
|
||||
ELSE
|
||||
mov [WORD PTR edi],ax
|
||||
mov [WORD PTR edi+640],ax
|
||||
ENDIF
|
||||
|
||||
add edi,2
|
||||
dec ecx
|
||||
jnz ??Not_finished_a_line
|
||||
|
||||
add edi,640
|
||||
dec edx
|
||||
jz ??Done
|
||||
jmp ??Start_row
|
||||
|
||||
??Done:
|
||||
ENDM
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; DRAW_BLOCK_ROW: draws one row of 'numblks' 2x2 blocks
|
||||
; Set ES:DI to current screen location
|
||||
; Set DS:SI to current source location
|
||||
; Uses: ax, cx
|
||||
;---------------------------------------------------------------------------
|
||||
MACRO DRAW_BLOCK_ROW numblks
|
||||
LOCAL ??Not_done
|
||||
|
||||
mov ecx,numblks
|
||||
|
||||
??Not_done:
|
||||
mov al,[BYTE PTR esi]
|
||||
mov ah,al
|
||||
inc esi
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov [WORD PTR es:edi],ax
|
||||
mov [WORD PTR es:edi+640],ax
|
||||
ELSE
|
||||
mov [WORD PTR edi],ax
|
||||
mov [WORD PTR edi+640],ax
|
||||
ENDIF
|
||||
|
||||
add edi,2
|
||||
dec ecx
|
||||
jnz ??Not_done
|
||||
|
||||
ENDM
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; DRAW_PIXEL_ROW: draws 'numblks' 2x1 blocks
|
||||
; Set ES:DI to current screen location
|
||||
; Set DS:SI to current source location
|
||||
; Uses: ax, cx
|
||||
;---------------------------------------------------------------------------
|
||||
MACRO DRAW_PIXEL_ROW numblks
|
||||
LOCAL ??Not_done
|
||||
|
||||
mov ecx,numblks
|
||||
|
||||
??Not_done:
|
||||
mov al,[BYTE PTR esi]
|
||||
mov ah,al
|
||||
inc esi
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov [WORD PTR es:edi],ax
|
||||
ELSE
|
||||
mov [WORD PTR edi],ax
|
||||
ENDIF
|
||||
|
||||
add edi,2
|
||||
dec ecx
|
||||
jnz ??Not_done
|
||||
|
||||
ENDM
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Blit_VESA640x480 - Blit to 640x480 256 color VESA mode.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Blit_VESA640x480(DisplayInfo, Buffer, X, Y, Width, Height)
|
||||
;*
|
||||
;* void Blit_VESA640x480(DisplayInfo *, char *, long, long, long, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* DisplayInfo - Pointer to display information structure.
|
||||
;* Buffer - Pointer to buffer to blit to VRAM.
|
||||
;* X - Destination X coordinate of blit (upper left).
|
||||
;* Y - Destination Y coordinate of blit (upper left).
|
||||
;* Width - Width of blit.
|
||||
;* Height - Height of blit.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
; GLOBAL C Blit_VESA640x480:NEAR
|
||||
; PROC Blit_VESA640x480 C NEAR USES
|
||||
;
|
||||
; ARG disp:NEAR PTR DisplayInfo
|
||||
; ARG buffer:NEAR PTR
|
||||
; ARG x:DWORD
|
||||
; ARG y:DWORD
|
||||
; ARG width:DWORD
|
||||
; ARG height:DWORD
|
||||
;
|
||||
; LOCAL grain:DWORD
|
||||
; LOCAL scrn_offset:DWORD
|
||||
; LOCAL bank_offset:DWORD
|
||||
; LOCAL bank:DWORD
|
||||
; LOCAL xres:DWORD
|
||||
;
|
||||
;;----------------------------------------------------------------------------
|
||||
;; INITIALIZE
|
||||
;;----------------------------------------------------------------------------
|
||||
;
|
||||
; pushad
|
||||
;
|
||||
;; Calculate granularity units per window
|
||||
;
|
||||
; mov esi,[disp]
|
||||
; xor eax,eax
|
||||
; mov edi,[(DisplayInfo esi).Extended]
|
||||
; xor ebx,ebx
|
||||
; mov ax,[(VESAModeInfo edi).WinSize]
|
||||
; xor edx,edx
|
||||
; mov bx,[(VESAModeInfo edi).WinGranularity]
|
||||
; idiv ebx
|
||||
; mov [grain],eax
|
||||
;
|
||||
;; Calculate screen offset
|
||||
;
|
||||
; mov eax,[(DisplayInfo esi).XRes]
|
||||
; mov [xres],eax
|
||||
; imul [y]
|
||||
; add eax,[x]
|
||||
; mov [scrn_offset],eax
|
||||
;
|
||||
;; Calculate bank offset
|
||||
;
|
||||
; mov ebx,65536
|
||||
; idiv ebx
|
||||
; mov [bank_offset],edx
|
||||
; mov [bank],eax
|
||||
;
|
||||
; popad
|
||||
; ret
|
||||
;
|
||||
; ENDP Blit_VESA640x480
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Buf_320x200_To_VESA_320x200 - Buffer copy, unscaled
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Buf_320x200_To_VESA_320x200(Buffer, GrainPerWin)
|
||||
;*
|
||||
;* void Buf_320x200_To_VESA_320x200(char *, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* To center the buffer on the screen, it's upper-left corner goes at
|
||||
;* (160,140). This means the buffer spans VESA banks 1,2 & 3, so it must
|
||||
;* be copied in 3 parts:
|
||||
;*
|
||||
;* Bank 1: starting offset 24224, 65 lines
|
||||
;* Bank 2: starting offset 288, 102 lines
|
||||
;* Bank 3: starting offset 32, 33 lines
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Buffer - Pointer to buffer to transfer to VRAM
|
||||
;* GrainPerWin - Granularity units per 64k window.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Buf_320x200_To_VESA_320x200:NEAR
|
||||
PROC Buf_320x200_To_VESA_320x200 C NEAR USES ebx ecx edx esi edi
|
||||
|
||||
ARG buffer:NEAR PTR
|
||||
ARG grains_per_win:DWORD
|
||||
|
||||
LOCAL grain_num:DWORD
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Initialize
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
IF PHARLAP_TNT
|
||||
push es
|
||||
mov eax,01Ch ;Set ES selector to VRAM
|
||||
mov es,ax
|
||||
ENDIF
|
||||
|
||||
mov eax,[grains_per_win]
|
||||
mov esi,[buffer]
|
||||
mov [grain_num],eax
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy Bank 1
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
SET_WINDOW [grain_num]
|
||||
mov edi,24224 ;Starting screen address
|
||||
mov edx,65 ;Lines to copy
|
||||
|
||||
??SetBank1:
|
||||
mov ecx,80 ;DWORDS to copy
|
||||
rep movsd ;Move the pixels
|
||||
add edi,320 ;Wrap to start of next line
|
||||
dec edx ;Decrement our line counter
|
||||
jnz ??SetBank1 ;Draw more lines
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy Bank 2
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
mov eax,[grains_per_win]
|
||||
add [grain_num],eax
|
||||
|
||||
SET_WINDOW [grain_num]
|
||||
mov edi,288 ;Starting screen address
|
||||
mov edx,102 ;Lines to copy
|
||||
|
||||
??SetBank2:
|
||||
mov ecx,80 ;DWORDS to copy
|
||||
rep movsd ;Move the pixels
|
||||
add edi,320 ;Wrap to start of next line
|
||||
dec edx ;Decrement our line counter
|
||||
jnz ??SetBank2 ;Draw more lines
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy Bank 3
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
mov eax,[grains_per_win]
|
||||
add [grain_num],eax
|
||||
|
||||
SET_WINDOW [grain_num]
|
||||
mov edi,32 ;Starting screen address
|
||||
mov edx,33 ;Lines to copy
|
||||
|
||||
??SetBank3:
|
||||
mov ecx,80 ;DWORDS to copy
|
||||
rep movsd ;Move the pixels
|
||||
add edi,320 ;Wrap to start of next line
|
||||
dec edx ;Decrement our line counter
|
||||
jnz ??SetBank3 ;Draw more lines
|
||||
|
||||
IF PHARLAP_TNT
|
||||
pop es
|
||||
ENDIF
|
||||
ret
|
||||
|
||||
ENDP Buf_320x200_To_VESA_320x200
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Buf_320x200_To_VESA_640x400 - Scales and copies 320x200 to 640x400
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Buf_320x200_To_VESA_640x400(Buffer, GrainPerWin)
|
||||
;*
|
||||
;* void Buf_320x200_To_VESA_640x400(char *, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Buffer - Pointer to buffer to transfer to VRAM
|
||||
;* GrainPerWin - Granularity units per 64k window.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Buf_320x200_To_VESA_640x400:NEAR
|
||||
PROC Buf_320x200_To_VESA_640x400 C NEAR USES ebx ecx edx esi edi
|
||||
|
||||
ARG buffer:NEAR PTR
|
||||
ARG grains_per_win:DWORD
|
||||
|
||||
LOCAL grain_num:DWORD
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Initialize
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
IF PHARLAP_TNT
|
||||
push es
|
||||
mov eax,01Ch ;Set ES selector to VRAM
|
||||
mov es,ax
|
||||
ENDIF
|
||||
|
||||
mov esi,[buffer]
|
||||
mov [grain_num],0
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy Bank 0
|
||||
; - Skip down 40 scanlines (to center the image)
|
||||
; - Draw 62 scanlines (31 rows of blocks)
|
||||
; - Draw top half of 128 blocks
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
SET_WINDOW [grain_num]
|
||||
mov edi,25600 ;Starting screen address
|
||||
|
||||
DRAW_BLOCK_ROWS 62/2 ;Draw 31 rows of blocks
|
||||
DRAW_PIXEL_ROW 256/2 ;Draw top half of next 128 blocks
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy Bank 1
|
||||
; - Draw bottom half of previous 128 blocks
|
||||
; - Finish the scan line with full blocks
|
||||
; - Draw 100 scanlines of blocks
|
||||
; - last line: top half of 256 blocks
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
mov eax,[grains_per_win]
|
||||
add [grain_num],eax
|
||||
SET_WINDOW [grain_num]
|
||||
|
||||
sub esi,256/2 ;Draw bottom half of prev 128 blks
|
||||
mov edi,384
|
||||
DRAW_PIXEL_ROW 256/2
|
||||
|
||||
mov edi,0
|
||||
DRAW_BLOCK_ROW 384/2 ;Fill rest of this block row
|
||||
|
||||
add edi,640
|
||||
DRAW_BLOCK_ROWS 100/2 ;Draw the block rows
|
||||
DRAW_PIXEL_ROW 512/2 ;Draw top half of next 512 blocks
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy Bank 2
|
||||
; - Draw bottom half of previous 256 blocks
|
||||
; - Finish the scan line with full blocks
|
||||
; - Draw 101 scanlines of blocks
|
||||
; - last line: 64 full blocks plus top half of 256 blocks
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
mov eax,[grains_per_win]
|
||||
add [grain_num],eax
|
||||
SET_WINDOW [grain_num]
|
||||
|
||||
sub esi,512/2 ;Draw bottom half of prev 256 blks
|
||||
mov edi,128
|
||||
DRAW_PIXEL_ROW 512/2
|
||||
|
||||
mov edi,0
|
||||
DRAW_BLOCK_ROW 128/2 ;Fill rest of this block row
|
||||
|
||||
add edi,640
|
||||
DRAW_BLOCK_ROWS 101/2 ;Draw the block rows
|
||||
DRAW_BLOCK_ROW 128/2 ;Draw next 64 blocks
|
||||
DRAW_PIXEL_ROW 512/2 ;Top half of 256 blocks
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy Bank 3
|
||||
; - Draw bottom half of previous 256 blocks
|
||||
; - Finish the scan line with full blocks
|
||||
; - Draw 101 scanlines of blocks
|
||||
; - last line: 192 full blocks, top half of 128 blocks
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
mov eax,[grains_per_win]
|
||||
add [grain_num],eax
|
||||
SET_WINDOW [grain_num]
|
||||
|
||||
sub esi,512/2 ;Draw bottom half of prev 256 blks
|
||||
mov edi,0
|
||||
DRAW_PIXEL_ROW 512/2
|
||||
DRAW_BLOCK_ROWS 101/2 ;Draw the block rows
|
||||
DRAW_BLOCK_ROW 384/2 ;Last row of full blocks
|
||||
DRAW_PIXEL_ROW 256/2 ;Top half of 128 blocks
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy Bank 4
|
||||
; - Draw bottom half of previous 128 blocks
|
||||
; - Draw 30 scanlines of blocks
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
mov eax,[grains_per_win]
|
||||
add [grain_num],eax
|
||||
SET_WINDOW [grain_num]
|
||||
|
||||
sub esi,256/2 ;Draw bottom half of prev 256 blks
|
||||
mov edi,0
|
||||
DRAW_PIXEL_ROW 256/2
|
||||
DRAW_BLOCK_ROWS 30/2 ;Draw the block rows
|
||||
|
||||
IF PHARLAP_TNT
|
||||
pop es
|
||||
ENDIF
|
||||
|
||||
ret
|
||||
|
||||
ENDP Buf_320x200_To_VESA_640x400
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Buf_320x200_To_VESA_32K - Copies 320x200 buffer to VESA 32K colors
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Buf_320x200_To_VESA_32K(Buffer, Palette, GrainPerWin)
|
||||
;*
|
||||
;* void Buf_320x200_To_VESA_32K(char *, char *, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Buffer - Pointer to buffer to transfer to VRAM
|
||||
;* Palette - Pointer to 15-bit palette to use.
|
||||
;* GrainPerWin - Granularity units per 64k window.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Buf_320x200_To_VESA_32K:NEAR
|
||||
PROC Buf_320x200_To_VESA_32K C NEAR USES ebx ecx edx esi edi
|
||||
|
||||
ARG buffer:NEAR PTR
|
||||
ARG palette:NEAR PTR
|
||||
ARG grains_per_win:DWORD
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Initialize
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
IF PHARLAP_TNT
|
||||
push es
|
||||
mov eax,01Ch ;Set ES selector to VRAM
|
||||
mov es,ax
|
||||
ENDIF
|
||||
|
||||
mov esi,[buffer]
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy Bank 0
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
SET_WINDOW 0
|
||||
mov edi,0 ;Start at Bank 0, offset 0
|
||||
mov ecx,32768 ;# words we'll be setting
|
||||
|
||||
; Get the pixel's offset into the palette
|
||||
|
||||
??Buf0Loop:
|
||||
xor eax,eax
|
||||
mov ebx,[palette]
|
||||
mov al,[BYTE PTR esi]
|
||||
add ebx,eax
|
||||
inc esi
|
||||
add ebx,eax
|
||||
|
||||
; store the 15-bit palette value
|
||||
|
||||
mov ax,[WORD PTR ebx]
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov [WORD PTR es:edi],ax
|
||||
ELSE
|
||||
mov [WORD PTR edi],ax
|
||||
ENDIF
|
||||
|
||||
add edi,2
|
||||
dec ecx
|
||||
jnz ??Buf0Loop
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy Bank 1
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
SET_WINDOW [grains_per_win]
|
||||
mov edi,0 ;Start at Bank 1, offset 0
|
||||
mov ecx,31232 ;# words we'll be setting
|
||||
|
||||
; Get the pixel's offset into the palette
|
||||
|
||||
??Buf1Loop:
|
||||
xor eax,eax
|
||||
mov ebx,[palette]
|
||||
mov al,[BYTE PTR esi]
|
||||
add ebx,eax
|
||||
inc esi
|
||||
add ebx,eax
|
||||
|
||||
; Store the 15-bit palette value
|
||||
|
||||
mov ax,[WORD PTR ebx]
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov [WORD PTR es:edi],ax
|
||||
ELSE
|
||||
mov [WORD PTR edi],ax
|
||||
ENDIF
|
||||
|
||||
add edi,2
|
||||
dec ecx
|
||||
jnz ??Buf1Loop
|
||||
|
||||
IF PHARLAP_TNT
|
||||
pop es
|
||||
ENDIF
|
||||
|
||||
ret
|
||||
|
||||
ENDP Buf_320x200_To_VESA_32K
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Copy_Row - Copy a row of pixels to VRAM.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Copy_Row(Source, Dest, Length)
|
||||
;*
|
||||
;* void Copy_Row(char *, char *, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Source - Pointer to data to copy to VRAM
|
||||
;* Dest - Destination VRAM address.
|
||||
;* Length - Number of bytes to copy.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Copy_Row:NEAR
|
||||
PROC Copy_Row C NEAR USES ecx esi edi
|
||||
|
||||
ARG source:NEAR PTR
|
||||
ARG dest:NEAR PTR
|
||||
ARG numbytes:DWORD
|
||||
|
||||
IF PHARLAP_TNT
|
||||
push es
|
||||
mov eax,01Ch
|
||||
mov es,ax
|
||||
ENDIF
|
||||
|
||||
cld
|
||||
mov esi,[source]
|
||||
mov edi,[dest]
|
||||
mov ecx,[numbytes]
|
||||
rep movsb
|
||||
|
||||
IF PHARLAP_TNT
|
||||
pop es
|
||||
ENDIF
|
||||
|
||||
ret
|
||||
|
||||
ENDP Copy_Row
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Copy_Word_Row - Copy a row of 15-bit pixels to VRAM
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Copy_Word_Row(Source, Dest, Palette, Length)
|
||||
;*
|
||||
;* void Copy_Word_Row(char *, char *, char *, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Source - Pointer to data to transfer.
|
||||
;* Dest - Destination screen address.
|
||||
;* Palette - 15bit palette to use.
|
||||
;* Length - Bytes to transfer.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Copy_Word_Row:NEAR
|
||||
PROC Copy_Word_Row C NEAR USES ebx ecx esi edi
|
||||
|
||||
ARG source:NEAR PTR
|
||||
ARG dest:NEAR PTR
|
||||
ARG palette:NEAR PTR
|
||||
ARG numbytes:DWORD
|
||||
|
||||
IF PHARLAP_TNT
|
||||
push es
|
||||
mov eax,01Ch
|
||||
mov es,ax
|
||||
ENDIF
|
||||
|
||||
mov esi,[source]
|
||||
mov edi,[dest]
|
||||
mov ecx,[numbytes]
|
||||
|
||||
??loop:
|
||||
mov ebx,[palette]
|
||||
xor eax,eax
|
||||
mov al,[esi] ;Get pixel value
|
||||
shl eax,1 ;Adjust for word entry
|
||||
add ebx,eax ;Compute color address
|
||||
mov ax,[ebx] ;Get color
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov [es:edi],ax ;Set 16bit pixel
|
||||
ELSE
|
||||
mov [edi],ax ;Set 16bit pixel
|
||||
ENDIF
|
||||
|
||||
inc esi ;Next source pixel
|
||||
add edi,2 ;Next dest pixel
|
||||
dec ecx ;Decrement pixel count
|
||||
jnz ??loop
|
||||
|
||||
IF PHARLAP_TNT
|
||||
pop es
|
||||
ENDIF
|
||||
|
||||
ret
|
||||
|
||||
ENDP Copy_Word_Row
|
||||
|
||||
END
|
||||
|
457
VQ/VQM32/VESAVID.CPP
Normal file
457
VQ/VQM32/VESAVID.CPP
Normal file
@@ -0,0 +1,457 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* vesavid.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* VESA video manager. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* InitVESA - Initialize the VESA video manager.
|
||||
* UninitVESA - Uninitialize the VESA video manager.
|
||||
* SetVESAMode - Set the display to the specified VESA video mode.
|
||||
* ReadVESAModeInfo - Read the VESA mode information from the video card.
|
||||
* SetVESAWindow - Set VESA window A's start address.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <mem.h>
|
||||
#include <dos.h>
|
||||
|
||||
#ifndef __WATCOMC__
|
||||
#include <pldos32.h>
|
||||
#include <pharlap.h>
|
||||
#else
|
||||
#include "realmode.h"
|
||||
#endif
|
||||
|
||||
#include "vesavid.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* PRIVATE DECLARATIONS
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
static short _VInfoSel = NULL;
|
||||
static short _VInfoSeg = NULL;
|
||||
static short _ModeInfoSel = NULL;
|
||||
static short _ModeInfoSeg = NULL;
|
||||
|
||||
#else /* __WATCOMC__ */
|
||||
/* _regs - Registers used for calling software interrupts.
|
||||
* _rpVInfo - Real pointer to VInfo structure in conventional memory.
|
||||
* _rpModeInfo - Real pointer to ModeInfo structure in conventional memory.
|
||||
* _VInfo - Protected mode copy of VInfo structure.
|
||||
* _ModeInfo - Protected mode copy of ModeInfo structure.
|
||||
*/
|
||||
static SWI_REGS _regs;
|
||||
static REALPTR _rpVInfo = NULL;
|
||||
static REALPTR _rpModeInfo = NULL;
|
||||
static VESAInfo _VInfo;
|
||||
static VESAModeInfo _ModeInfo;
|
||||
|
||||
#endif /* __WATCOMC__ */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* InitVESA - Initialize the VESA video manager.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = InitVESA()
|
||||
*
|
||||
* long InitVESA(void);
|
||||
*
|
||||
* FUNCTION
|
||||
* Initialize the VESA video system. Get the VESA information from the
|
||||
* VESA video bios.
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
* Error - 0 if successful, or -1 error/VESA not supported.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long InitVESA(void)
|
||||
{
|
||||
#ifdef __WATCOMC__
|
||||
union REGS r;
|
||||
struct SREGS sr;
|
||||
RMInfo rmi;
|
||||
long error = -1;
|
||||
|
||||
/* Allocate real-mode memory for VESA structure. */
|
||||
r.x.eax = 0x0100;
|
||||
r.x.ebx = (sizeof(VESAInfo) + 15) >> 4;
|
||||
int386(0x31, &r, &r);
|
||||
|
||||
if (r.x.cflag == 0) {
|
||||
_VInfoSel = r.w.dx;
|
||||
_VInfoSeg = r.w.ax;
|
||||
|
||||
/* Allocate real-mode memory for VESAModeInfo structure. */
|
||||
r.x.eax = 0x0100;
|
||||
r.x.ebx = (sizeof(VESAModeInfo) + 15) >> 4;
|
||||
int386(0x31, &r, &r);
|
||||
|
||||
if (r.x.cflag == 0) {
|
||||
_ModeInfoSel = r.w.dx;
|
||||
_ModeInfoSeg = r.w.ax;
|
||||
|
||||
/* Clear VESAInfo structure. */
|
||||
memset(MK_PTR(0, _VInfoSeg), 0, sizeof(VESAInfo));
|
||||
|
||||
/* Get VESA information. */
|
||||
memset(&rmi, 0, sizeof(RMInfo));
|
||||
rmi.eax = 0x4F00;
|
||||
rmi.edi = 0;
|
||||
rmi.es = _VInfoSeg;
|
||||
|
||||
segread(&sr);
|
||||
r.w.ax = 0x0300;
|
||||
r.h.bl = 0x10;
|
||||
r.h.bh = 0;
|
||||
r.w.cx = 0;
|
||||
sr.es = FP_SEG(&rmi);
|
||||
r.x.edi = FP_OFF(&rmi);
|
||||
int386x(0x31, &r, &r, &sr);
|
||||
|
||||
if ((r.x.cflag == 0) && (rmi.eax == 0x004F)) {
|
||||
error = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (error != 0) {
|
||||
UninitVESA();
|
||||
}
|
||||
|
||||
return (error);
|
||||
|
||||
#else /* __WATCOMC__ */
|
||||
|
||||
unsigned short rseg;
|
||||
long paras;
|
||||
long error = -1;
|
||||
|
||||
/* Calculate size of VESAInfo structure in paragraphs */
|
||||
paras = (sizeof(VESAInfo) + 15) >> 4;
|
||||
|
||||
/* Allocate real-mode memory for VESA structure. */
|
||||
if (_dx_real_alloc(paras, (unsigned short *)&rseg,
|
||||
(unsigned short *)¶s) == 0) {
|
||||
|
||||
RP_SET(_rpVInfo, 0, rseg);
|
||||
|
||||
/* Calculate size of VESAModeInfo structure in paragraphs */
|
||||
paras = (sizeof(VESAModeInfo) + 15) >> 4;
|
||||
|
||||
/* Allocate real-mode memory for VESAModeInfo structure. */
|
||||
if (_dx_real_alloc(paras, (unsigned short *)&rseg,
|
||||
(unsigned short *)¶s) == 0) {
|
||||
|
||||
RP_SET(_rpModeInfo, 0, rseg);
|
||||
|
||||
/* Clear the input buffer */
|
||||
FillRealMem(_rpVInfo, 0, sizeof(VESAInfo));
|
||||
|
||||
/* Set up function call */
|
||||
_regs.eax = 0x4F00;
|
||||
_regs.edi = RP_OFF(_rpVInfo);
|
||||
_regs.es = RP_SEG(_rpVInfo);
|
||||
_dx_real_int(0x10, &_regs);
|
||||
|
||||
if (_regs.eax == 0x004F) {
|
||||
ReadRealMem(&_VInfo, _rpVInfo, sizeof(VESAInfo));
|
||||
error = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error != 0) {
|
||||
UninitVESA();
|
||||
}
|
||||
|
||||
return (error);
|
||||
|
||||
#endif /* __WATCOMC__ */
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* UninitVESA - Uninitialize the VESA video manager.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* UninitVESA()
|
||||
*
|
||||
* void UninitVESA(void);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void UninitVESA(void)
|
||||
{
|
||||
#ifdef __WATCOMC__
|
||||
union REGS r;
|
||||
|
||||
/* Free VESAInfo structure */
|
||||
if (_VInfoSeg != NULL) {
|
||||
r.x.eax = 0x0101;
|
||||
r.x.edx = _VInfoSel;
|
||||
int386(0x31, &r, &r);
|
||||
|
||||
_VInfoSeg = NULL;
|
||||
_VInfoSel = NULL;
|
||||
}
|
||||
|
||||
/* Free VESAModeInfo structure */
|
||||
if (_ModeInfoSeg != NULL) {
|
||||
r.x.eax = 0x0101;
|
||||
r.x.edx = _VInfoSel;
|
||||
int386(0x31, &r, &r);
|
||||
|
||||
_ModeInfoSeg = NULL;
|
||||
_ModeInfoSel = NULL;
|
||||
}
|
||||
|
||||
#else /* __WATCOMC__ */
|
||||
|
||||
/* Free VESAInfo structure */
|
||||
if (_rpVInfo != NULL) {
|
||||
_dx_real_free(RP_SEG(_rpVInfo));
|
||||
_rpVInfo = NULL;
|
||||
}
|
||||
|
||||
/* Free VESAModeInfo structure */
|
||||
if (_rpModeInfo != NULL) {
|
||||
_dx_real_free(RP_SEG(_rpModeInfo));
|
||||
_rpModeInfo = NULL;
|
||||
}
|
||||
#endif /* __WATCOMC__ */
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SetVESAMode - Set the display adapter to the given VESA video mode.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* VESAModeInfo = SetVESAMode(Mode)
|
||||
*
|
||||
* VESAModeInfo *SetVESAMode(long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Set the display adapter to the specified VESA video mode.
|
||||
*
|
||||
* INPUTS
|
||||
* Mode - VESA video mode to set the display to.
|
||||
*
|
||||
* RESULT
|
||||
* VESAModeInfo - Pointer to VESA mode information structure or NULL if
|
||||
* error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
VESAModeInfo *SetVESAMode(long mode)
|
||||
{
|
||||
VESAModeInfo *vminfo;
|
||||
|
||||
/* Get mode info */
|
||||
if ((vminfo = ReadVESAModeInfo(mode)) != NULL) {
|
||||
|
||||
/* If the mode is supported, set it. */
|
||||
if ((vminfo->Attributes & 0x01) != 0) {
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
{
|
||||
union REGS r;
|
||||
|
||||
r.x.eax = 0x4F02;
|
||||
r.x.ebx = mode;
|
||||
int386(0x10, &r, &r);
|
||||
|
||||
if (r.x.eax != 0x004F)
|
||||
vminfo = NULL;
|
||||
}
|
||||
|
||||
#else /* __WATCOMC__ */
|
||||
|
||||
/* Set up function call */
|
||||
_regs.eax = 0x4F02;
|
||||
_regs.ebx = mode;
|
||||
_dx_real_int(0x10, &_regs);
|
||||
|
||||
if (_regs.eax != 0x004F) {
|
||||
vminfo = NULL;
|
||||
}
|
||||
#endif /* __WATCOMC__ */
|
||||
}
|
||||
}
|
||||
|
||||
return (vminfo);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* ReadVESAModeInfo - Read the VESA mode information from the video card.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* VESAModeInfo = ReadVESAModeInfo(Mode)
|
||||
*
|
||||
* VESAModeInfo *ReadVESAModeInfo(long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Read information about the specified mode from the VESA video BIOS.
|
||||
*
|
||||
* INPUTS
|
||||
* Mode - Mode ID to get information about.
|
||||
*
|
||||
* RESULT
|
||||
* VESAModeInfo - Pointer to VESA mode information structure or NULL if
|
||||
* error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
VESAModeInfo *ReadVESAModeInfo(long mode)
|
||||
{
|
||||
VESAModeInfo *vminfo = NULL;
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
union REGS r;
|
||||
struct SREGS sr;
|
||||
RMInfo rmi;
|
||||
|
||||
/* Make sure we have real-mode memory. */
|
||||
if (_ModeInfoSeg != NULL) {
|
||||
memset(MK_PTR(0, _ModeInfoSeg), 0, sizeof(VESAModeInfo));
|
||||
|
||||
/* Get mode information. */
|
||||
memset(&rmi, 0, sizeof(RMInfo));
|
||||
rmi.eax = 0x4F01;
|
||||
rmi.ecx = mode;
|
||||
rmi.edi = 0;
|
||||
rmi.es = _ModeInfoSeg;
|
||||
|
||||
segread(&sr);
|
||||
r.w.ax = 0x0300;
|
||||
r.w.bx = 0x0010;
|
||||
r.w.cx = 0;
|
||||
sr.es = FP_SEG(&rmi);
|
||||
r.x.edi = FP_OFF(&rmi);
|
||||
int386x(0x31, &r, &r, &sr);
|
||||
|
||||
if ((r.x.cflag == 0) && (rmi.eax == 0x004F)) {
|
||||
vminfo = (VESAModeInfo *)MK_PTR(0, _ModeInfoSeg);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* __WATCOMC__ */
|
||||
|
||||
/* Make sure we have real-mode memory. */
|
||||
if (_rpModeInfo != NULL) {
|
||||
|
||||
/* Clear the input buffer */
|
||||
FillRealMem(_rpModeInfo, 0, sizeof(VESAModeInfo));
|
||||
|
||||
/* Set up function call */
|
||||
_regs.eax = 0x4F01;
|
||||
_regs.ecx = mode;
|
||||
_regs.edi = RP_OFF(_rpModeInfo);
|
||||
_regs.es = RP_SEG(_rpModeInfo);
|
||||
_dx_real_int(0x10, &_regs);
|
||||
|
||||
if (_regs.eax == 0x004F) {
|
||||
ReadRealMem(&_ModeInfo, _rpModeInfo, sizeof(VESAModeInfo));
|
||||
vminfo = &_ModeInfo;
|
||||
}
|
||||
}
|
||||
#endif /* __WATCOMC__ */
|
||||
|
||||
return (vminfo);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SetVESAWindow - Set VESA window A's start address.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* Error = SetVESAWindow(GrainNum)
|
||||
*
|
||||
* long SetVESAWindow(long);
|
||||
*
|
||||
* FUNCTION
|
||||
* This function invokes the Window Function, whose address is provided
|
||||
* in the VESAModeInfo structure. The 'GrainNum' must be in granularity
|
||||
* units as specified in the ModeInfo structure.
|
||||
*
|
||||
* INPUTS
|
||||
* GrainNum - Granularity number to set window to.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void SetVESAWindow(long grain)
|
||||
{
|
||||
#ifdef __WATCOMC__
|
||||
#else /* __WATCOMC__ */
|
||||
|
||||
RMC_BLK regp;
|
||||
|
||||
regp.eax = 0x4F05;
|
||||
regp.ebx = 0x00;
|
||||
regp.edx = grain;
|
||||
_dx_call_real(_ModeInfo.WinFunc, ®p, 0);
|
||||
#endif /* __WATCOMC__ */
|
||||
}
|
||||
|
182
VQ/VQM32/VESAVID.H
Normal file
182
VQ/VQM32/VESAVID.H
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMVESAVID_H
|
||||
#define VQMVESAVID_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* VESAVid.h (32-Bit protected mode)
|
||||
*
|
||||
* DESCRIPTION
|
||||
* VESA video manager definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* Febuary 3, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __WATCOMC__
|
||||
#include <pharlap.h>
|
||||
#else
|
||||
#include "realmode.h"
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* VESA Video Modes
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
#define VESA_640X400_256 0x100
|
||||
#define VESA_640X480_256 0x101
|
||||
#define VESA_800X600_16 0x102
|
||||
#define VESA_800X600_256 0x103
|
||||
#define VESA_1024X768_16 0x104
|
||||
#define VESA_1024X768_256 0x105
|
||||
#define VESA_1280X400_16 0x106
|
||||
#define VESA_1280X400_256 0x107
|
||||
#define VESA_TEXT_80X60 0x108
|
||||
#define VESA_TEXT_132X25 0x109
|
||||
#define VESA_TEXT_132X60 0x10C
|
||||
#define VESA_320X200_32K_1 0x10D
|
||||
#define VESA_320X200_32K_2 0x10E
|
||||
#define VESA_640X480_32K 0x110
|
||||
#define VESA_640X480_65K 0x111
|
||||
#define VESA_640X480_16M 0x112
|
||||
#define VESA_800X600_32K 0x113
|
||||
#define VESA_800X600_65K 0x114
|
||||
#define VESA_1024X768_32K 0x116
|
||||
#define VESA_1024X768_65K 0x117
|
||||
|
||||
#define VESA_MIN VESA_640X400_256
|
||||
#define VESA_MAX VESA_1024X768_65K
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Structure definitions
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/* VESAInfo - General information about this VESA implementation.
|
||||
* (Filled in by VESA BIOS Function 0)
|
||||
*
|
||||
* Signature - Will always be 'VESA'
|
||||
* Version - Version #
|
||||
* OEMString - OEM ID string
|
||||
* Capabilities - Not defined by VESA yet
|
||||
* AvailModes - List of available modes; terminated with -1 (0xffff)
|
||||
* TotalMemory - ???
|
||||
* Reserved - Pads structure to 256 bytes total
|
||||
*/
|
||||
typedef struct _VESAInfo {
|
||||
char Signature[4];
|
||||
unsigned short Version;
|
||||
REALPTR OEMString;
|
||||
unsigned long Capabilities;
|
||||
REALPTR AvailModes;
|
||||
unsigned short TotalMemory;
|
||||
unsigned char Reserved[236];
|
||||
} VESAInfo;
|
||||
|
||||
/* VESAModeInfo - Information about this VESA mode.
|
||||
* (Filled in by VESA BIOS Function 1)
|
||||
*
|
||||
* Attributes - bit 0: 1 = mode is supported
|
||||
* bit 1: 1 = optional info available
|
||||
* bit 2: 1 = std BIOS output functions valid in this mode
|
||||
* bit 3: 0 = monochrome, 1 = color
|
||||
* bit 4: 0 = text mode, 1 = graphics
|
||||
* WinA_Attributes - bit 0 = window exists, bit 1=readable, bit 2= writable
|
||||
* WinB_Attributes - bit 0 = window exists, bit 1=readable, bit 2= writable
|
||||
* WinGranularity - smallest address boundary window can be placed upon;
|
||||
* size is in KB (ie 64, 32, 4)
|
||||
* WinSize - size of windows in KB (ie 64, 32)
|
||||
* WinA_Segment - location of Window A in CPU space (usually 0xa000)
|
||||
* WinB_Segment - location of Window B in CPU space (usually 0xb000)
|
||||
* WinFunc - address of window-setting function (This is provided
|
||||
* as an alternative to Int 10 for speed.)
|
||||
* BytesPerScanline - # bytes per scan line
|
||||
*
|
||||
* Optional info (available if bit 1 of Attributes is set):
|
||||
*
|
||||
* XRes - X-resolution
|
||||
* YRes - Y-resolution
|
||||
* XCharSize - Horizontal size of char cell
|
||||
* YCharSize - Vertical size of char cell
|
||||
* NumPlanes - # of memory planes (???)
|
||||
* BitsPerPixel - # bites per pixel
|
||||
* NumBanks - # of banks (ie planes)
|
||||
* MemoryModel - 00h = Text mode
|
||||
* 01h = CGA mode
|
||||
* 02h = Hercules
|
||||
* 03h = 4 plane planar mode
|
||||
* 04h = packed pixel mode (1 byte/pixel)
|
||||
* 05h = non-chain 4, 256-color mode
|
||||
* 06-0Fh =
|
||||
* 10-FFh = OEM-specific
|
||||
* BankSize - Bank size in KB
|
||||
*/
|
||||
typedef struct _VESAModeInfo {
|
||||
unsigned short Attributes;
|
||||
unsigned char WinA_Attributes;
|
||||
unsigned char WinB_Attributes;
|
||||
unsigned short WinGranularity;
|
||||
unsigned short WinSize;
|
||||
unsigned short WinA_Segment;
|
||||
unsigned short WinB_Segment;
|
||||
REALPTR WinFunc;
|
||||
unsigned short BytesPerScanline;
|
||||
unsigned short XRes;
|
||||
unsigned short YRes;
|
||||
unsigned char XCharSize;
|
||||
unsigned char YCharSize;
|
||||
unsigned char NumPlanes;
|
||||
unsigned char BitsPerPixel;
|
||||
unsigned char NumBanks;
|
||||
unsigned char MemoryModel;
|
||||
unsigned char BankSize;
|
||||
unsigned char NumInputPages;
|
||||
unsigned char Reserved;
|
||||
unsigned char RedMaskSize;
|
||||
unsigned char RedFieldPosition;
|
||||
unsigned char GreenMaskSize;
|
||||
unsigned char GreenFieldPosition;
|
||||
unsigned char BlueMaskSize;
|
||||
unsigned char BlueFieldPosition;
|
||||
unsigned char RsvdMaskSize;
|
||||
unsigned char RsvdFieldPosition;
|
||||
unsigned char DirectColorModeInfo;
|
||||
unsigned char pad[216];
|
||||
} VESAModeInfo;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Function prototypes
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
long InitVESA(void);
|
||||
void UninitVESA(void);
|
||||
VESAModeInfo *SetVESAMode(long mode);
|
||||
VESAModeInfo *ReadVESAModeInfo(long mode);
|
||||
void SetVESAWindow(long grain_num);
|
||||
|
||||
#endif /* VQMVESAVID_H */
|
||||
|
203
VQ/VQM32/VESAVID.I
Normal file
203
VQ/VQM32/VESAVID.I
Normal file
@@ -0,0 +1,203 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
;
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* C O N F I D E N T I A L -- W E S T W O O D S T U D I O S
|
||||
;*
|
||||
;*----------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* vesavid.i
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* VESA video manager definitions. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* January 26, 1995
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; VESA video modes
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
VESA_640X400_256 EQU 0x100
|
||||
VESA_640X480_256 EQU 0x101
|
||||
VESA_800X600_16 EQU 0x102
|
||||
VESA_800X600_256 EQU 0x103
|
||||
VESA_1024X768_16 EQU 0x104
|
||||
VESA_1024X768_256 EQU 0x105
|
||||
VESA_1280X400_16 EQU 0x106
|
||||
VESA_1280X400_256 EQU 0x107
|
||||
VESA_TEXT_80X60 EQU 0x108
|
||||
VESA_TEXT_132X25 EQU 0x109
|
||||
VESA_TEXT_132X60 EQU 0x10C
|
||||
VESA_320X200_32K_1 EQU 0x10D
|
||||
VESA_320X200_32K_2 EQU 0x10E
|
||||
VESA_640X480_32K EQU 0x110
|
||||
VESA_640X480_65K EQU 0x111
|
||||
VESA_640X480_16M EQU 0x112
|
||||
VESA_800X600_32K EQU 0x113
|
||||
VESA_800X600_65K EQU 0x114
|
||||
VESA_1024X768_32K EQU 0x116
|
||||
VESA_1024X768_65K EQU 0x117
|
||||
|
||||
VESA_MIN EQU VESA_640X400_256
|
||||
VESA_MAX EQU VESA_1024X768_65K
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Structure definitions
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
; VESAInfo - General information about this VESA implementation.
|
||||
; (Filled in by VESA BIOS Function 0)
|
||||
;
|
||||
; Signature - Will always be 'VESA'
|
||||
; Ver - Version #
|
||||
; OEMString - OEM ID string
|
||||
; Capabilities - Not defined by VESA yet
|
||||
; AvailModes - List of available modes; terminated with -1 (0xffff)
|
||||
; TotalMemory - ???
|
||||
; Reserved - Pads structure to 256 bytes total
|
||||
|
||||
STRUC VESAInfo
|
||||
Signature DD ?
|
||||
Ver DW ?
|
||||
OEMString DD ?
|
||||
Capabilities DD ?
|
||||
AvailModes DD ?
|
||||
TotalMemory DW ?
|
||||
Reserved DB 236 DUP (?)
|
||||
ENDS VESAInfo
|
||||
|
||||
; VESAModeInfo - Information about this VESA mode.
|
||||
; (Filled in by VESA BIOS Function 1)
|
||||
;
|
||||
; Attributes - bit 0: 1 = mode is supported
|
||||
; bit 1: 1 = optional info available
|
||||
; bit 2: 1 = std BIOS output functions valid in this mode
|
||||
; bit 3: 0 = monochrome, 1 = color
|
||||
; bit 4: 0 = text mode, 1 = graphics
|
||||
; WinA_Attributes - bit 0 = window exists, bit 1=readable, bit 2= writable
|
||||
; WinB_Attributes - bit 0 = window exists, bit 1=readable, bit 2= writable
|
||||
; WinGranularity - smallest address boundary window can be placed upon;
|
||||
; size is in KB (ie 64, 32, 4)
|
||||
; WinSize - size of windows in KB (ie 64, 32)
|
||||
; WinA_Segment - location of Window A in CPU space (usually 0xa000)
|
||||
; WinB_Segment - location of Window B in CPU space (usually 0xb000)
|
||||
; WinFunc - address of window-setting function (This is provided
|
||||
; as an alternative to Int 10 for speed.)
|
||||
; BytesPerScanline - # bytes per scan line
|
||||
;
|
||||
; Optional info (available if bit 1 of Attributes is set):
|
||||
;
|
||||
; XRes - X-resolution
|
||||
; YRes - Y-resolution
|
||||
; XCharSize - Horizontal size of char cell
|
||||
; YCharSize - Vertical size of char cell
|
||||
; NumPlanes - # of memory planes (???)
|
||||
; BitsPerPixel - # bites per pixel
|
||||
; NumBanks - # of banks (ie planes)
|
||||
; MemoryModel - 00h = Text mode
|
||||
; 01h = CGA mode
|
||||
; 02h = Hercules
|
||||
; 03h = 4 plane planar mode
|
||||
; 04h = packed pixel mode (1 byte/pixel)
|
||||
; 05h = non-chain 4, 256-color mode
|
||||
; 06-0Fh =
|
||||
; 10-FFh = OEM-specific
|
||||
; BankSize - Bank size in KB
|
||||
|
||||
STRUC VESAModeInfo
|
||||
Attributes DW ?
|
||||
WinA_Attributes DB ?
|
||||
WinB_Attributes DB ?
|
||||
WinGranularity DW ?
|
||||
WinSize DW ?
|
||||
WinA_Segment DW ?
|
||||
WinB_Segment DW ?
|
||||
WinFunc DD ?
|
||||
BytesPerScanline DW ?
|
||||
XRes DW ?
|
||||
YRes DW ?
|
||||
XCharSize DB ?
|
||||
YCharSize DB ?
|
||||
NumPlanes DB ?
|
||||
BitsPerPixel DB ?
|
||||
NumBanks DB ?
|
||||
MemoryModel DB ?
|
||||
BankSize DB ?
|
||||
NumInputPages DB ?
|
||||
Reserved DB ?
|
||||
RedMaskSize DB ?
|
||||
RedFieldPosition DB ?
|
||||
GreenMaskSize DB ?
|
||||
GreenFieldPosition DB ?
|
||||
BlueMaskSize DB ?
|
||||
BlueFieldPosition DB ?
|
||||
RsvdMaskSize DB ?
|
||||
RsvdFieldPosition DB ?
|
||||
DirectColorModeInfo DB ?
|
||||
pad DB 216 DUP (?)
|
||||
ENDS VESAModeInfo
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Function definitions
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
GLOBAL C InitVESA:PROC
|
||||
GLOBAL C UninitVESA:PROC
|
||||
GLOBAL C SetVESAMode:PROC
|
||||
GLOBAL C ReadVESAModeInfo:PROC
|
||||
GLOBAL C SetVESAWindow:PROC
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
;
|
||||
; NAME
|
||||
; SET_WINDOW - Sets window A to the specified bank.
|
||||
;
|
||||
; SYNOPSIS
|
||||
; SET_WINDOW GrainNum
|
||||
;
|
||||
; FUNCTION
|
||||
; This routine uses the C Set_Window function rather than going through
|
||||
; the BIOS, for two reasons: (1) Speed, and (2) On the Cirrus Logic 54xx
|
||||
; VESA cards, BIOS calls make noise while playing digital audio.
|
||||
;
|
||||
; INPUTS
|
||||
; GrainNum - Granularity number.
|
||||
;
|
||||
; RESULT
|
||||
; NONE
|
||||
;
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
MACRO SET_WINDOW grain_num
|
||||
push esi
|
||||
push edi
|
||||
push es
|
||||
call SetVESAWindow C,grain_num
|
||||
pop es
|
||||
pop edi
|
||||
pop esi
|
||||
ENDM
|
||||
|
217
VQ/VQM32/VGA.I
Normal file
217
VQ/VQM32/VGA.I
Normal 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/>.
|
||||
;
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* vga.i
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* VGA hardware definitions. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* January 26, 1995
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; VGA Registers
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
R_SEQUENCER EQU 03C4h ;Sequencer Controller Index reg
|
||||
SEQ_RESET EQU 00h ;Reset
|
||||
SEQ_MAP_MASK EQU 02h ;Index in Sequencer of Map Mask reg
|
||||
SEQ_MEMORY_MODE EQU 04h ;Memory Mode
|
||||
|
||||
R_GRAPHICS_CONTROLLER EQU 03CEh ;Graphics Controller Index reg
|
||||
GC_READ_MAP EQU 04h ;Index in GController of Read Map reg
|
||||
GC_MODE EQU 05h ;Read/Write Modes
|
||||
GC_MISC EQU 06h ;Read/Write Modes
|
||||
GC_BITMASK EQU 08h ;Index in GController of BitMask reg
|
||||
|
||||
R_CRT_CONTROLLER EQU 03D4h ;CRT Controller Index reg
|
||||
CRT_VERT_TOTAL EQU 06h ;Vertical total
|
||||
CRT_OVERFLOW EQU 07h ;Overflow
|
||||
CRT_MAX_SCANLINE EQU 09h ;Max scan line
|
||||
CRT_STARTADDR_HIGH EQU 0Ch ;Bitmap start address high byte
|
||||
CRT_STARTADDR_LOW EQU 0Dh ;Bitmap start address low byte
|
||||
CRT_VERTRET_START EQU 010h ;Vertical retrace pulse start
|
||||
CRT_VERTRET_END EQU 011h ;Vertical retrace pulse end
|
||||
CRT_VERTDISP_END EQU 012h ;Vertical display end
|
||||
CRT_UNDERLINE EQU 014h ;Underline location
|
||||
CRT_START_VB EQU 015h ;Start vertical blank
|
||||
CRT_END_VB EQU 016h ;End vertical blank
|
||||
CRT_MODE_CONTROL EQU 017h ;Mode control
|
||||
R_MISC_OUTPUT EQU 03C2h ;Miscellaneous Output reg
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Palette Registers
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
PEL_READ_ADDR EQU 03C7h
|
||||
PEL_WRITE_ADDR EQU 03C8h
|
||||
PEL_DATA EQU 03C9h
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; XMode planes, for the Map Mask register
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
XPLANE_1 EQU 1
|
||||
XPLANE_2 EQU 2
|
||||
XPLANE_3 EQU 4
|
||||
XPLANE_4 EQU 8
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
;
|
||||
; NAME
|
||||
; SET_PLANE - Set an XMode plane.
|
||||
;
|
||||
; SYNOPSIS
|
||||
; SET_PLANE plane
|
||||
;
|
||||
; INPUTS
|
||||
; plane - Number of Xmode plane to set.
|
||||
;
|
||||
; USES
|
||||
; eax, edx
|
||||
;
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
MACRO SET_PLANE plane
|
||||
mov edx,R_SEQUENCER
|
||||
mov eax,SEQ_MAP_MASK
|
||||
out dx,al
|
||||
inc edx
|
||||
mov eax,plane
|
||||
out dx,al
|
||||
ENDM
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
;
|
||||
; NAME
|
||||
; SET_BITMASK - Set the BitMask register.
|
||||
;
|
||||
; SYNOPSIS
|
||||
; SET_BITMASK mask
|
||||
;
|
||||
; INPUTS
|
||||
; mask - Bitmask to use.
|
||||
;
|
||||
; USES
|
||||
; eax, edx
|
||||
;
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
MACRO SET_BITMASK mask
|
||||
mov edx,R_GRAPHICS_CONTROLLER
|
||||
mov eax,GC_BITMASK
|
||||
out dx,al
|
||||
inc edx
|
||||
mov eax,mask
|
||||
out dx,al
|
||||
ENDM
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
;
|
||||
; NAME
|
||||
; SET_WRITEMODE - Set the VGA writemode.
|
||||
;
|
||||
; SYNOPSIS
|
||||
; SET_WRITEMODE mode
|
||||
;
|
||||
; INPUTS
|
||||
; mode - Write mode.
|
||||
;
|
||||
; USES
|
||||
; eax, edx
|
||||
;
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
MACRO SET_WRITEMODE mode
|
||||
mov edx,R_GRAPHICS_CONTROLLER
|
||||
mov eax,GC_MODE
|
||||
out dx,al
|
||||
inc edx
|
||||
in al,dx ;Read the register
|
||||
and al,0FCh ;Turn off 2 lower bits
|
||||
or al,mode ;Set write mode
|
||||
out dx,al
|
||||
ENDM
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
;
|
||||
; NAME
|
||||
; OUTPORT - Output data to a VGA register.
|
||||
;
|
||||
; SYNOPSIS
|
||||
; OUTPORT port,register,data
|
||||
;
|
||||
; INPUTS
|
||||
; port - Port address.
|
||||
; register - Register to write to.
|
||||
; data - Data to write.
|
||||
;
|
||||
; USES
|
||||
; eax, edx
|
||||
;
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
MACRO OUTPORT port,register,data
|
||||
mov edx,port
|
||||
mov al,register
|
||||
out dx,al
|
||||
inc edx
|
||||
mov al,data
|
||||
out dx,al
|
||||
ENDM
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
;
|
||||
; NAME
|
||||
; INPORT - Input data from a VGA register.
|
||||
;
|
||||
; SYNOPSIS
|
||||
; data = INPORT port,register
|
||||
;
|
||||
; INPUTS
|
||||
; port - Port address.
|
||||
; register - Register to read from.
|
||||
;
|
||||
; RESULT
|
||||
; data - Value read from port in AL.
|
||||
;
|
||||
; USES
|
||||
; eax, edx
|
||||
;
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
MACRO INPORT port,register
|
||||
mov edx,port
|
||||
mov al,register
|
||||
out dx,al
|
||||
inc edx
|
||||
in al,dx
|
||||
ENDM
|
||||
|
282
VQ/VQM32/VIDEO.CPP
Normal file
282
VQ/VQM32/VIDEO.CPP
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* video.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Video mode setting. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* Febuary 3, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* SetVideoMode - Set the video mode.
|
||||
* GetDisplayInfo - Get the display info for the current video mode.
|
||||
* GetVBIBit - Get the vertical blank bit polarity.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <dos.h>
|
||||
#include <conio.h>
|
||||
|
||||
#ifndef __WATCOMC__
|
||||
#include <pharlap.h>
|
||||
#include <pldos32.h>
|
||||
#else
|
||||
#include "realmode.h"
|
||||
#endif
|
||||
|
||||
#include "video.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* PRIVATE DECLARATIONS
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
static DisplayInfo _Display = {-1,0,0,0,NULL};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SetVideoMode - Set the display to the specified video mode.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* DisplayInfo = SetVideoMode(Mode)
|
||||
*
|
||||
* DisplayInfo *SetVideoMode(long);
|
||||
*
|
||||
* FUNCTION
|
||||
* Set the video display adapter to the desired video mode.
|
||||
*
|
||||
* INPUTS
|
||||
* Mode - Desired video mode.
|
||||
*
|
||||
* RESULT
|
||||
* DisplayInfo - Pointer to DisplayInfo structure, otherwise 0 for error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DisplayInfo *SetVideoMode(long mode)
|
||||
{
|
||||
#ifdef __WATCOMC__
|
||||
union REGS regs;
|
||||
struct SREGS sregs;
|
||||
#else
|
||||
union _REGS regs;
|
||||
#endif
|
||||
|
||||
DisplayInfo *di = NULL;
|
||||
VESAModeInfo *vminfo;
|
||||
long error;
|
||||
|
||||
/* Initialize the video manager on the first invocation of
|
||||
* SetVideoMode()
|
||||
*/
|
||||
if (_Display.Mode == -1) {
|
||||
_Display.VBIbit = TestVBIBit();
|
||||
}
|
||||
|
||||
/* Clear the VRAM before enabling the mode so that there is
|
||||
* not any garbage on the screen.
|
||||
*/
|
||||
ClearVRAM();
|
||||
|
||||
/* If the requested mode is the same as the current mode then
|
||||
* we do not need to do anything.
|
||||
*/
|
||||
if (mode != _Display.Mode) {
|
||||
|
||||
/* Uninitialize VESA if the previous mode was a VESA mode and the new
|
||||
* mode is not.
|
||||
*/
|
||||
if (((_Display.Mode >= VESA_MIN) && (_Display.Mode <= VESA_MAX))
|
||||
&& ((mode < VESA_MIN) && (mode > VESA_MAX))) {
|
||||
|
||||
UninitVESA();
|
||||
}
|
||||
|
||||
/* Set display to an XMode. */
|
||||
if ((mode >= XMODE_MIN) && (mode <= XMODE_MAX)) {
|
||||
SetXMode(mode);
|
||||
ClearXMode();
|
||||
SetupXPaging();
|
||||
ShowXPage(0);
|
||||
_Display.Mode = mode;
|
||||
_Display.Extended = NULL;
|
||||
di = &_Display;
|
||||
|
||||
/* Set display resolution information */
|
||||
switch (mode) {
|
||||
case XMODE_320X200:
|
||||
_Display.XRes = 320;
|
||||
_Display.YRes = 200;
|
||||
break;
|
||||
|
||||
case XMODE_320X240:
|
||||
_Display.XRes = 320;
|
||||
_Display.YRes = 240;
|
||||
break;
|
||||
|
||||
case XMODE_320X400:
|
||||
_Display.XRes = 320;
|
||||
_Display.YRes = 400;
|
||||
break;
|
||||
|
||||
case XMODE_320X480:
|
||||
_Display.XRes = 320;
|
||||
_Display.YRes = 480;
|
||||
break;
|
||||
|
||||
case XMODE_360X400:
|
||||
_Display.XRes = 360;
|
||||
_Display.YRes = 400;
|
||||
break;
|
||||
|
||||
case XMODE_360X480:
|
||||
_Display.XRes = 360;
|
||||
_Display.YRes = 480;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((mode >= VESA_MIN) && (mode <= VESA_MAX)) {
|
||||
|
||||
/* Initialize the VESA manager if the current mode is not a VESA
|
||||
* mode.
|
||||
*/
|
||||
if ((_Display.Mode < VESA_MIN) || (_Display.Mode > VESA_MAX)) {
|
||||
error = InitVESA();
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
|
||||
/* Set the display to MCGA before going into VESA. This needs to be
|
||||
* done to ensure that the video ram selector is initialized. This
|
||||
* fixes a bug in some VESA BIOS'.
|
||||
*/
|
||||
#ifndef __WATCOMC__
|
||||
regs.x.ax = mode;
|
||||
_int86(0x10, ®s, ®s);
|
||||
#else
|
||||
segread(&sregs);
|
||||
regs.x.eax = mode;
|
||||
int386x(0x10, ®s, ®s, &sregs);
|
||||
#endif
|
||||
|
||||
if ((vminfo = SetVESAMode(mode)) != NULL) {
|
||||
_Display.Mode = mode;
|
||||
_Display.XRes = (long)vminfo->XRes;
|
||||
_Display.YRes = (long)vminfo->YRes;
|
||||
_Display.Extended = vminfo;
|
||||
di = &_Display;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifndef __WATCOMC__
|
||||
regs.x.ax = mode;
|
||||
_int86(0x10, ®s, ®s);
|
||||
#else
|
||||
segread(&sregs);
|
||||
regs.x.eax = mode;
|
||||
int386x(0x10, ®s, ®s, &sregs);
|
||||
#endif
|
||||
|
||||
_Display.Mode = mode;
|
||||
_Display.XRes = 320;
|
||||
_Display.YRes = 200;
|
||||
_Display.Extended = NULL;
|
||||
di = &_Display;
|
||||
}
|
||||
} else {
|
||||
di = &_Display;
|
||||
}
|
||||
|
||||
return (di);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* GetDisplayInfo - Get the display info for the current video mode.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* DisplayInfo = GetDisplayInfo()
|
||||
*
|
||||
* DisplayInfo *GetDisplayInfo(void);
|
||||
*
|
||||
* FUNCTION
|
||||
* Return a pointer to the current display information structure.
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
* DisplayInfo - Pointer to initialized display info or NULL if not valid.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DisplayInfo *GetDisplayInfo(void)
|
||||
{
|
||||
if (_Display.Mode != 0) {
|
||||
return (&_Display);
|
||||
} else {
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* GetVBIBit - Get the vertical blank bit polarity.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* VBIBit = GetVBIBit()
|
||||
*
|
||||
* long GetVBIBit(void);
|
||||
*
|
||||
* FUNCTION
|
||||
* Return the polarity of the vertical blank bit.
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
* VBIBit - Vertical blank bit polarity.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long GetVBIBit(void)
|
||||
{
|
||||
return (_Display.VBIbit);
|
||||
}
|
||||
|
115
VQ/VQM32/VIDEO.H
Normal file
115
VQ/VQM32/VIDEO.H
Normal 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/>.
|
||||
*/
|
||||
|
||||
#ifndef VQMVIDEO_H
|
||||
#define VQMVIDEO_H
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* Video.h (32-Bit protected mode)
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Video manager definitions.
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* Febuary 3, 1995
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <vqm32\vesavid.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* VGA video modes
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
#define TEXT 0x02
|
||||
#define MCGA 0x13
|
||||
#define XMODE_320X200 0x50
|
||||
#define XMODE_320X240 0x51
|
||||
#define XMODE_320X400 0x52
|
||||
#define XMODE_320X480 0x53
|
||||
#define XMODE_360X400 0x54
|
||||
#define XMODE_360X480 0x55
|
||||
|
||||
#define XMODE_MIN 0x50
|
||||
#define XMODE_MAX 0x55
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Structure definitions
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/* DisplayInfo - Information about the current display.
|
||||
*
|
||||
* Mode - Mode identification.
|
||||
* XRes - X resolution of mode.
|
||||
* YRes - Y resolution of mode.
|
||||
* VBIbit - Polarity of vertical blank bit.
|
||||
* Extended - Pointer to mode specific data structure.
|
||||
*/
|
||||
typedef struct _DisplayInfo {
|
||||
long Mode;
|
||||
long XRes;
|
||||
long YRes;
|
||||
long VBIbit;
|
||||
void *Extended;
|
||||
} DisplayInfo;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Function prototypes
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
DisplayInfo *SetVideoMode(long mode);
|
||||
DisplayInfo *GetDisplayInfo(void);
|
||||
long TestVBIBit(void);
|
||||
long GetVBIBit(void);
|
||||
|
||||
void SetupXPaging(void);
|
||||
void FlipXPage(void);
|
||||
unsigned char *GetXHidPage(void);
|
||||
unsigned char *GetXSeenPage(void);
|
||||
void DisplayXPage(long page);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cdecl WaitNoVB(short vbibit);
|
||||
void cdecl WaitVB(short vbibit);
|
||||
void cdecl ClearVRAM(void);
|
||||
long cdecl SetXMode(long mode);
|
||||
void cdecl ClearXMode(void);
|
||||
void cdecl ShowXPage(unsigned long StartOffset);
|
||||
void cdecl Xmode_BufferCopy_320x200(void *buff, void *screen);
|
||||
void cdecl Xmode_Blit(void *buffer, void *screen, long imgwidth, long imgheight);
|
||||
void cdecl MCGA_BufferCopy(unsigned char *buffer, unsigned char *dummy);
|
||||
void cdecl MCGA_Blit(unsigned char *buffer, unsigned char *screen,
|
||||
long imgwidth, long imgheight);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VQMVIDEO_H */
|
||||
|
80
VQ/VQM32/VIDEO.I
Normal file
80
VQ/VQM32/VIDEO.I
Normal file
@@ -0,0 +1,80 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
;
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* 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
|
||||
;*
|
||||
;*----------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* video.i
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* Video manager definitions. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* January 26, 1995
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
INCLUDE "vesavid.i"
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Video Modes
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
TEXT EQU 002h
|
||||
MCGA EQU 013h
|
||||
XMODE_320X200 EQU 050h
|
||||
XMODE_320X240 EQU 051h
|
||||
XMODE_320X400 EQU 052h
|
||||
XMODE_320X480 EQU 053h
|
||||
XMODE_360X400 EQU 054h
|
||||
XMODE_360X480 EQU 055h
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Structure definitions
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
; DisplayInfo - Information about the current display.
|
||||
;
|
||||
; Mode - Mode identification
|
||||
; XRes - X resolution
|
||||
; YRes - Y resolution
|
||||
; VBIbit - Polarity of vertical blank bit.
|
||||
; Extended - Pointer to mode specified data structure.
|
||||
|
||||
STRUC DisplayInfo
|
||||
Mode DD ?
|
||||
XRes DD ?
|
||||
YRes DD ?
|
||||
VBIbit DD ?
|
||||
Extended DD ?
|
||||
ENDS DisplayInfo
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Function definitions
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
GLOBAL C GetDisplayInfo:NEAR
|
||||
GLOBAL C GetVBIBit:NEAR
|
||||
|
748
VQ/VQM32/XMODE.ASM
Normal file
748
VQ/VQM32/XMODE.ASM
Normal file
@@ -0,0 +1,748 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; 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
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* FILE
|
||||
;* xmode.asm
|
||||
;*
|
||||
;* DESCRIPTION
|
||||
;* Xmode graphics display routines. (32-Bit protected mode)
|
||||
;*
|
||||
;* PROGRAMMER
|
||||
;* Bill Randolph
|
||||
;* Denzil E. Long, Jr.
|
||||
;*
|
||||
;* DATE
|
||||
;* Febuary 3, 1995
|
||||
;*
|
||||
;*---------------------------------------------------------------------------
|
||||
;*
|
||||
;* PUBLIC
|
||||
;* SetXMode - Set the specified Xmode video mode.
|
||||
;* ClearXMode - Clear the XMode VRAM.
|
||||
;* ShowXPage - Set a specific page for XMode display.
|
||||
;* Xmode_BufferCopy_320x200 - Copy 320x200 buffer to Xmode VRAM.
|
||||
;* Xmode_Blit - Bit blit a block to the XMode display.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
LOCALS ??
|
||||
INCLUDE "vga.i"
|
||||
INCLUDE "video.i"
|
||||
CODESEG
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* SetXMode - Set the specified Xmode video mode.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Error = SetXMode(Mode)
|
||||
;*
|
||||
;* long SetXMode(long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* This routines set the current display adapter to the specified Xmode.
|
||||
;* Portions of this routine were take from Dr. Dobb's, written in C, and
|
||||
;* portions were taken from Dominic's 320x200 code.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Mode - Xmode mode to set display to.
|
||||
;*
|
||||
;* RESULT
|
||||
;* Error - 0 if successful, or -1 if error.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C SetXMode:NEAR
|
||||
PROC SetXMode C NEAR USES edx
|
||||
|
||||
ARG mode:DWORD
|
||||
|
||||
??Set320x200:
|
||||
cmp [mode],XMODE_320X200 ;320x200?
|
||||
jne ??Set320x240
|
||||
|
||||
IF 0
|
||||
mov eax,MCGA
|
||||
int 10h
|
||||
|
||||
; Memory Mode:
|
||||
; bit3 (chain) = 0 (planes are accessed via Map Mask)
|
||||
; bit2 (odd/even) = 1 (use sequential addressing mode)
|
||||
|
||||
INPORT R_SEQUENCER,SEQ_MEMORY_MODE
|
||||
and al,not 08h ;Turn off chain 4
|
||||
or al,04h ;Turn off odd/even
|
||||
out dx,al
|
||||
|
||||
INPORT R_GRAPHICS_CONTROLLER,GC_MODE
|
||||
and al,not 10h ;Turn off odd/even
|
||||
out dx,al
|
||||
|
||||
INPORT R_GRAPHICS_CONTROLLER,GC_MISC
|
||||
and al,not 02h ;Turn off chain
|
||||
out dx,al
|
||||
|
||||
OUTPORT R_SEQUENCER,SEQ_MAP_MASK,0Fh
|
||||
INPORT R_CRT_CONTROLLER, CRT_MAX_SCANLINE
|
||||
and al,not 1fh ;Clear low 5 bits
|
||||
or al,1 ;Mode = 0 => 400 lines
|
||||
out dx,al ;Mode =1 => 200
|
||||
|
||||
INPORT R_CRT_CONTROLLER,CRT_UNDERLINE
|
||||
and al,not 40h ;Turn off doubleword
|
||||
out dx,al
|
||||
|
||||
INPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL
|
||||
or al,40h ;Turn on byte mode bit,
|
||||
out dx,al ; so mem scanned linearly
|
||||
ENDIF
|
||||
|
||||
; The following section of code is from Roger Stevens' XMode
|
||||
; example code; it's the same as 320x400, except the value sent
|
||||
; to CRT_MAX_SCANLINE is 41, not 40.
|
||||
|
||||
mov eax,MCGA
|
||||
int 10h
|
||||
|
||||
OUTPORT R_SEQUENCER,SEQ_MEMORY_MODE,06h
|
||||
INPORT R_CRT_CONTROLLER,CRT_VERTRET_END
|
||||
and al,07Fh
|
||||
out dx,al
|
||||
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_MAX_SCANLINE,41h
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_UNDERLINE,00h
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL,0E3h
|
||||
|
||||
mov eax,0
|
||||
jmp ??Done
|
||||
|
||||
??Set320x240:
|
||||
cmp [mode],XMODE_320X240 ;320x240?
|
||||
jne ??Set320x400
|
||||
|
||||
; Start by setting MCGA to let the BIOS program the registers;
|
||||
; then, reprogram the registers that need it.
|
||||
|
||||
mov eax,MCGA
|
||||
int 10h
|
||||
|
||||
; Memory Mode:
|
||||
; bit3 (chain) = 0 (planes are accessed via Map Mask)
|
||||
; bit2 (odd/even) = 1 (use sequential addressing mode)
|
||||
; bit1 (extended mem) = 1 (>64K video RAM)
|
||||
; bit0 (alpha/graph) = 0 (graphics mode)
|
||||
|
||||
OUTPORT R_SEQUENCER,SEQ_MEMORY_MODE,06h
|
||||
|
||||
; Issue a Sequencer Reset
|
||||
OUTPORT R_SEQUENCER,SEQ_RESET,01h
|
||||
|
||||
; Misc Output: (set to 1100 0011)
|
||||
; Bit 7: VSync polarity (1=negative)
|
||||
; Bit 6: HSync polarity (1=negative)
|
||||
; Bit 5: page bit for odd/even (0=low 64K)
|
||||
; Bit 4: Video drivers (0=enable)
|
||||
; Bit 3,2: clock select (0=25-MHz clock)
|
||||
; Bit 1: VRAM access (1 = enable CPU to access)
|
||||
; Bit 0: I/O Address (1=color emulation)
|
||||
|
||||
mov edx,R_MISC_OUTPUT
|
||||
mov al,0C3h
|
||||
out dx,al
|
||||
|
||||
; Clear Sequencer Reset
|
||||
|
||||
OUTPORT R_SEQUENCER,SEQ_RESET,03h
|
||||
|
||||
; Read Vertical Retrace End, and with 07f to clear high bit
|
||||
; (clearing bit 7 enables writing to registers 0-7)
|
||||
|
||||
INPORT R_CRT_CONTROLLER,CRT_VERTRET_END
|
||||
and al,07Fh
|
||||
out dx,al
|
||||
|
||||
; Program the CRT Controller to display 480 scanlines, but to
|
||||
; double each scanline so only 240 are displayed:
|
||||
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_UNDERLINE,00h
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL,0E3h
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_VERT_TOTAL,0Dh
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_OVERFLOW,03Eh
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_VERTRET_START,0EAh
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_VERTRET_END,0ACh
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_VERTDISP_END,0DFh
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_START_VB,0E7h
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_END_VB,06h
|
||||
OUTPORT R_CRT_CONTROLLER,CRT_MAX_SCANLINE,041h
|
||||
|
||||
xor eax,eax
|
||||
jmp ??Done
|
||||
|
||||
??Set320x400:
|
||||
cmp [mode],XMODE_320X400 ;320x400
|
||||
jne ??Set320x480
|
||||
|
||||
mov eax,MCGA
|
||||
int 10h
|
||||
|
||||
OUTPORT R_SEQUENCER,04h,06h
|
||||
INPORT R_CRT_CONTROLLER,011h
|
||||
and al,07Fh
|
||||
out dx,al
|
||||
|
||||
OUTPORT R_CRT_CONTROLLER,09h,40h
|
||||
OUTPORT R_CRT_CONTROLLER,014h,00h
|
||||
OUTPORT R_CRT_CONTROLLER,017h,0E3h
|
||||
|
||||
xor eax,eax
|
||||
jmp ??Done
|
||||
|
||||
??Set320x480:
|
||||
cmp [mode],XMODE_320X480 ;320x480?
|
||||
jne ??Set360x400
|
||||
|
||||
mov eax,MCGA
|
||||
int 10h
|
||||
|
||||
mov edx,R_SEQUENCER
|
||||
mov eax,0604h
|
||||
out dx,ax
|
||||
|
||||
mov eax,0100h
|
||||
out dx,ax
|
||||
|
||||
mov edx,R_MISC_OUTPUT
|
||||
mov al,0C3h
|
||||
out dx,al
|
||||
|
||||
mov edx,R_SEQUENCER
|
||||
mov eax,0300h
|
||||
out dx,ax
|
||||
|
||||
mov edx,R_CRT_CONTROLLER
|
||||
mov al,011h
|
||||
out dx,al
|
||||
|
||||
mov edx,03D5h
|
||||
in al,dx
|
||||
and al,07Fh
|
||||
out dx,al
|
||||
|
||||
mov edx,R_CRT_CONTROLLER
|
||||
mov eax,04009h
|
||||
out dx,ax
|
||||
mov eax,00014h
|
||||
out dx,ax
|
||||
mov eax,0E317h
|
||||
out dx,ax
|
||||
mov eax,00D06h
|
||||
out dx,ax
|
||||
mov eax,03E07h
|
||||
out dx,ax
|
||||
mov eax,0EA10h
|
||||
out dx,ax
|
||||
mov eax,0AC11h
|
||||
out dx,ax
|
||||
mov eax,0DF12h
|
||||
out dx,ax
|
||||
mov eax,0E715h
|
||||
out dx,ax
|
||||
mov eax,00616h
|
||||
out dx,ax
|
||||
mov eax,04009h
|
||||
out dx,ax
|
||||
|
||||
xor eax,eax
|
||||
jmp ??Done
|
||||
|
||||
??Set360x400:
|
||||
cmp [mode],XMODE_360X400 ;360x400
|
||||
jne ??Set360x480
|
||||
|
||||
mov eax,MCGA
|
||||
int 10h
|
||||
|
||||
mov edx,R_SEQUENCER
|
||||
mov eax,0604h
|
||||
out dx,ax
|
||||
|
||||
mov eax,0100h
|
||||
out dx,ax
|
||||
|
||||
mov edx,R_MISC_OUTPUT
|
||||
mov al,067h
|
||||
out dx,al
|
||||
|
||||
mov edx,R_SEQUENCER
|
||||
mov eax,0300h
|
||||
out dx,ax
|
||||
|
||||
mov edx,R_CRT_CONTROLLER
|
||||
mov al,011h
|
||||
out dx,al
|
||||
|
||||
mov edx,03D5h
|
||||
in al,dx
|
||||
and al,07Fh
|
||||
out dx,al
|
||||
|
||||
mov edx,R_CRT_CONTROLLER
|
||||
mov eax,06B00h
|
||||
out dx,ax
|
||||
mov eax,05901h
|
||||
out dx,ax
|
||||
mov eax,05A02h
|
||||
out dx,ax
|
||||
mov eax,08E03h
|
||||
out dx,ax
|
||||
mov eax,05E04h
|
||||
out dx,ax
|
||||
mov eax,08A05h
|
||||
out dx,ax
|
||||
mov eax,04009
|
||||
out dx,ax
|
||||
mov eax,00014h
|
||||
out dx,ax
|
||||
mov eax,0E317h
|
||||
out dx,ax
|
||||
mov eax,02D13h
|
||||
out dx,ax
|
||||
|
||||
xor eax,eax
|
||||
jmp ??Done
|
||||
|
||||
??Set360x480:
|
||||
cmp [mode],XMODE_360X480 ;360x480?
|
||||
jne ??Unknown_mode
|
||||
|
||||
mov eax,MCGA
|
||||
int 10h
|
||||
|
||||
mov edx,R_SEQUENCER
|
||||
mov eax,0604h
|
||||
out dx,ax
|
||||
|
||||
mov eax,0100h
|
||||
out dx,ax
|
||||
|
||||
mov edx,R_MISC_OUTPUT
|
||||
mov al,0E7h
|
||||
out dx,al
|
||||
|
||||
mov edx,R_SEQUENCER
|
||||
mov eax,0300h
|
||||
out dx,ax
|
||||
|
||||
mov edx,R_CRT_CONTROLLER
|
||||
mov al,011h
|
||||
out dx,al
|
||||
|
||||
mov edx,03D5h
|
||||
in al,dx
|
||||
and al,07Fh
|
||||
out dx,al
|
||||
|
||||
mov edx,R_CRT_CONTROLLER
|
||||
mov eax,06B00h
|
||||
out dx,ax
|
||||
mov eax,05901h
|
||||
out dx,ax
|
||||
mov eax,05A02h
|
||||
out dx,ax
|
||||
mov eax,08E03h
|
||||
out dx,ax
|
||||
mov eax,05E04h
|
||||
out dx,ax
|
||||
mov eax,08A05h
|
||||
out dx,ax
|
||||
mov eax,04009h
|
||||
out dx,ax
|
||||
mov eax,00014h
|
||||
out dx,ax
|
||||
mov eax,0E317h
|
||||
out dx,ax
|
||||
mov eax,00D06h
|
||||
out dx,ax
|
||||
mov eax,03E07h
|
||||
out dx,ax
|
||||
mov eax,0EA10h
|
||||
out dx,ax
|
||||
mov eax,0AC11h
|
||||
out dx,ax
|
||||
mov eax,0DF12h
|
||||
out dx,ax
|
||||
mov eax,0E715h
|
||||
out dx,ax
|
||||
mov eax,00616h
|
||||
out dx,ax
|
||||
mov eax,02D13h
|
||||
out dx,ax
|
||||
|
||||
xor eax,eax
|
||||
jmp ??Done
|
||||
|
||||
??Unknown_mode:
|
||||
mov eax,0FFFFFFFFh ;Unknown mode
|
||||
|
||||
??Done:
|
||||
ret
|
||||
|
||||
ENDP SetXMode
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* ClearXMode - Clear the XMode VRAM.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* ClearXMode()
|
||||
;*
|
||||
;* void ClearXMode(void);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* NONE
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C ClearXMode:NEAR
|
||||
PROC ClearXMode C NEAR USES eax ecx edi es
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov eax,01Ch
|
||||
mov es,ax ;Set ES selector to VRAM
|
||||
mov edi,0
|
||||
ELSE
|
||||
mov edi,0A0000h
|
||||
ENDIF
|
||||
SET_PLANE 0Fh
|
||||
mov ecx,((320*240*2)/4/4)
|
||||
xor eax,eax
|
||||
rep stosd
|
||||
ret
|
||||
|
||||
ENDP ClearXMode
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* ShowXPage - Set a specific page for XMode display.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* ShowXPage(Offset)
|
||||
;*
|
||||
;* void ShowXPage();
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* Show the page at the specified offset in the bitmap. Page-flip takes
|
||||
;* effect on the next active scan cycle.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Offset - Offset to set page to.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C ShowXPage:NEAR
|
||||
PROC ShowXPage C NEAR USES eax ebx ecx edx
|
||||
|
||||
ARG StartOffset:DWORD
|
||||
|
||||
mov edx,R_CRT_CONTROLLER
|
||||
mov bl,CRT_STARTADDR_LOW
|
||||
mov bh,[byte ptr StartOffset]
|
||||
mov cl,CRT_STARTADDR_HIGH
|
||||
mov ch,[byte ptr StartOffset+1]
|
||||
mov eax,ebx
|
||||
out dx,ax
|
||||
mov eax,ecx
|
||||
out dx,ax
|
||||
ret
|
||||
|
||||
ENDP ShowXPage
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Xmode_BufferCopy_320x200 - Copy 320x200 buffer to Xmode VRAM.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* Xmode_BufferCopy_320x200(Buffer, Screen)
|
||||
;*
|
||||
;* void Xmode_BufferCopy_320x200(char *, char *);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;* BitBlt copy to VRAM.
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Buffer - Pointer to buffer to copy to XMode VRAM.
|
||||
;* Screen - XMode VRAM screen address to copy buffer to.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Xmode_BufferCopy_320x200:NEAR
|
||||
PROC Xmode_BufferCopy_320x200 C NEAR USES eax ecx edx edi esi es
|
||||
|
||||
ARG buffer:NEAR PTR
|
||||
ARG screen:NEAR PTR
|
||||
|
||||
LOCAL save_esi:DWORD
|
||||
LOCAL save_edi:DWORD
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Initialize
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov eax,01Ch ;Set ES selector to VRAM.
|
||||
mov es,ax
|
||||
ENDIF
|
||||
|
||||
mov esi,[buffer] ;Set pointers
|
||||
mov edi,[screen]
|
||||
mov [save_esi],esi
|
||||
mov [save_edi],edi
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy plane 1
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
SET_PLANE XPLANE_1
|
||||
mov ecx,4000
|
||||
|
||||
x_loop_1:
|
||||
mov al,[esi + 8] ;Get pixel
|
||||
mov ah,[esi + 12] ;Get pixel
|
||||
ror eax,16
|
||||
mov al,[esi] ;Get pixel
|
||||
mov ah,[esi + 4] ;Get pixel
|
||||
mov [es:edi],eax ;Write plane 1 pixels to VRAM
|
||||
|
||||
add esi,16 ;Next source pixel position
|
||||
add edi,4 ;Next VRAM position
|
||||
dec ecx
|
||||
jnz short x_loop_1
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy plane 2
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
mov esi,[save_esi] ;Restore pointers
|
||||
mov edi,[save_edi]
|
||||
inc esi ;Adjust source pointer to plane 2
|
||||
|
||||
SET_PLANE XPLANE_2
|
||||
mov ecx,4000
|
||||
|
||||
x_loop_2:
|
||||
mov al,[esi + 8] ;Get pixel
|
||||
mov ah,[esi + 12] ;Get pixel
|
||||
ror eax,16
|
||||
mov al,[esi] ;Get pixel
|
||||
mov ah,[esi + 4] ;Get pixel
|
||||
mov [es:edi],eax ;Write plane 2 pixels to VRAM
|
||||
|
||||
add esi,16 ;Next source pixel position
|
||||
add edi,4 ;Next VRAM position
|
||||
dec ecx
|
||||
jnz short x_loop_2
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy plane 3
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
mov esi,[save_esi] ;Restore pointers
|
||||
mov edi,[save_edi]
|
||||
add esi,2 ;Adjust source pointer to plane 3
|
||||
|
||||
SET_PLANE XPLANE_3
|
||||
mov ecx,4000
|
||||
|
||||
x_loop_3:
|
||||
mov al,[esi + 8] ;Get pixel
|
||||
mov ah,[esi + 12] ;Get pixel
|
||||
ror eax,16
|
||||
mov al,[esi] ;Get pixel
|
||||
mov ah,[esi + 4] ;Get pixel
|
||||
mov [es:edi],eax ;Write plane 3 pixels to VRAM
|
||||
|
||||
add esi,16 ;Next source pixel position
|
||||
add edi,4 ;Next VRAM position
|
||||
dec ecx
|
||||
jnz short x_loop_3
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Copy plane 4
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
mov esi,[save_esi] ;Restore pointers
|
||||
mov edi,[save_edi]
|
||||
add esi,3 ;Adjust source pointer to plane 4
|
||||
|
||||
SET_PLANE XPLANE_4
|
||||
mov ecx,4000
|
||||
x_loop_4:
|
||||
mov al,[esi + 8] ;Get pixel
|
||||
mov ah,[esi + 12] ;Get pixel
|
||||
ror eax,16
|
||||
mov al,[esi] ;Get pixel
|
||||
mov ah,[esi + 4] ;Get pixel
|
||||
mov [es:edi],eax ;Write plane 4 pixels to VRAM
|
||||
|
||||
add esi,16 ;Next source pixel position
|
||||
add edi,4 ;Next screen position
|
||||
dec ecx
|
||||
jnz short x_loop_4
|
||||
ret
|
||||
|
||||
ENDP Xmode_BufferCopy_320x200
|
||||
|
||||
|
||||
;****************************************************************************
|
||||
;*
|
||||
;* NAME
|
||||
;* Xmode_Blit - Bit blit a block to the XMode display.
|
||||
;*
|
||||
;* SYNOPSIS
|
||||
;* XMode_Blit(Buffer, Screen, Width, Height)
|
||||
;*
|
||||
;* void XMode_Blit(char *, char *, long, long);
|
||||
;*
|
||||
;* FUNCTION
|
||||
;*
|
||||
;* INPUTS
|
||||
;* Buffer - Pointer buffer to blit to screen.
|
||||
;* Screen - Screen address to blit buffer to.
|
||||
;* Width - Width of buffer.
|
||||
;* Height - Height of buffer.
|
||||
;*
|
||||
;* RESULT
|
||||
;* NONE
|
||||
;*
|
||||
;* WARNINGS
|
||||
;* Assumes the screen to be 320 pixels wide and the source buffer width
|
||||
;* to be divisible by 16.
|
||||
;*
|
||||
;****************************************************************************
|
||||
|
||||
GLOBAL C Xmode_Blit:NEAR
|
||||
PROC Xmode_Blit C NEAR USES ecx edx esi edi es
|
||||
|
||||
ARG buffer:NEAR PTR
|
||||
ARG screen:NEAR PTR
|
||||
ARG imgwidth:DWORD
|
||||
ARG imgheight:DWORD
|
||||
|
||||
LOCAL rowcount:DWORD
|
||||
LOCAL xplane:DWORD
|
||||
LOCAL edi_startval:DWORD
|
||||
LOCAL esi_startval:DWORD
|
||||
LOCAL xadd:DWORD
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Initialize
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
IF PHARLAP_TNT
|
||||
mov eax,01Ch ;Set ES selector to VRAM
|
||||
mov es,ax
|
||||
ENDIF
|
||||
|
||||
mov esi,[buffer]
|
||||
mov edi,[screen]
|
||||
mov [esi_startval],esi
|
||||
mov [edi_startval],edi
|
||||
|
||||
mov edx,320 ;Compute modulo
|
||||
sub edx,[imgwidth]
|
||||
shr edx,2
|
||||
mov [xadd],edx
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Transfer the data on plane at a time.
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
mov [xplane],1
|
||||
|
||||
??Do_plane:
|
||||
SET_PLANE [xplane] ;Set plane to transfer to
|
||||
mov eax,[imgheight]
|
||||
mov [rowcount],eax
|
||||
mov edx,[xadd]
|
||||
|
||||
??Do_row:
|
||||
mov ecx,[imgwidth] ;Length of row to copy in DWORDS
|
||||
shr ecx,4
|
||||
|
||||
; Transfer a row of pixels
|
||||
|
||||
??Not_done:
|
||||
mov al,[esi + 8] ;Get pixel
|
||||
mov ah,[esi + 12] ;Get pixel
|
||||
ror eax,16
|
||||
mov al,[esi] ;Get pixel
|
||||
mov ah,[esi + 4] ;Get pixel
|
||||
mov [es:edi],eax ;Write pixels to VRAM plane
|
||||
|
||||
add esi,16 ;Next source position
|
||||
add edi,4 ;Next VRAM position
|
||||
dec ecx
|
||||
jnz ??Not_done
|
||||
|
||||
add edi,edx ;Next VRAM row
|
||||
dec [rowcount] ;Decrement the row count
|
||||
jnz ??Do_row
|
||||
|
||||
; Go to next X-Plane
|
||||
|
||||
inc [esi_startval]
|
||||
mov eax,[esi_startval]
|
||||
mov esi,eax
|
||||
mov eax,[edi_startval]
|
||||
mov edi,eax
|
||||
shl [xplane],1
|
||||
cmp [xplane],16
|
||||
jnz ??Do_plane
|
||||
ret
|
||||
|
||||
ENDP Xmode_Blit
|
||||
|
||||
END
|
||||
|
201
VQ/VQM32/XMODEPG.CPP
Normal file
201
VQ/VQM32/XMODEPG.CPP
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** 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
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* FILE
|
||||
* xmodepg.c
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Xmode page access. (32-Bit protected mode)
|
||||
*
|
||||
* PROGRAMMER
|
||||
* Bill Randolph
|
||||
* Denzil E. Long, Jr.
|
||||
*
|
||||
* DATE
|
||||
* January 26, 1995
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* PUBLIC
|
||||
* SetupXPaging - Setup Xmode paging variables.
|
||||
* FlipXPage - Page flip to next Xmode page.
|
||||
* ShowXPage - Show the specified Xmode page.
|
||||
* GetXHidPage - Get the address of the current Xmode HidPage.
|
||||
* GetXSeenPage - Get the address of the current Xmode SeenPage.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <dos.h>
|
||||
#include "video.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* PRIVATE DECLARATIONS
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
#define PAGE0_START_OFFSET 0
|
||||
#define PAGE1_START_OFFSET ((320 * 240) / 4)
|
||||
|
||||
/* PageFlip page values. */
|
||||
static unsigned long PageStartOffsets[2] = {
|
||||
PAGE0_START_OFFSET,
|
||||
PAGE1_START_OFFSET
|
||||
};
|
||||
|
||||
static long DisplayedPage;
|
||||
static long NonDisplayedPage;
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* SetupXPaging - Setup Xmode paging variables.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* SetupXPaging()
|
||||
*
|
||||
* void SetupXPaging(void);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void SetupXPaging(void)
|
||||
{
|
||||
DisplayedPage = 1;
|
||||
NonDisplayedPage = DisplayedPage ^ 1;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* FlipXPage - Page flip to next Xmode page.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* FlipXPage()
|
||||
*
|
||||
* void FlipXPage(void);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void FlipXPage(void)
|
||||
{
|
||||
ShowXPage(PageStartOffsets[NonDisplayedPage]);
|
||||
DisplayedPage = NonDisplayedPage;
|
||||
NonDisplayedPage = DisplayedPage ^ 1;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* ShowXPage - Show the specified Xmode page.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* ShowXPage(page)
|
||||
*
|
||||
* void ShowXPage(long);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* Page - Xmode page number to show.
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void DisplayXPage(long page)
|
||||
{
|
||||
ShowXPage(PageStartOffsets[page & 1]);
|
||||
DisplayedPage = page;
|
||||
NonDisplayedPage = DisplayedPage ^ 1;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* GetXHidPage - Get the address of the current Xmode HidPage.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* HidPage = GetXHidPage()
|
||||
*
|
||||
* unsigned char *GetXHidPage(void);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
* HidPage - Address of Xmode HidPage.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
unsigned char *GetXHidPage(void)
|
||||
{
|
||||
return((unsigned char *)PageStartOffsets[NonDisplayedPage]);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* GetXSeenPage - Get the address of the current Xmode SeenPage.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* SeenPage = GetXSeenPage()
|
||||
*
|
||||
* unsigned char *GetXSeenPage(void);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
* SeePage - Address of the Xmode SeenPage.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
unsigned char *GetXSeenPage(void)
|
||||
{
|
||||
return ((unsigned char *)PageStartOffsets[DisplayedPage]);
|
||||
}
|
||||
|
Reference in New Issue
Block a user