Initial commit of Command & Conquer Red Alert source code.

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

77
WWFLAT32/IFF/FILEPCX.H Normal file
View File

@@ -0,0 +1,77 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : iff *
;* *
;* File Name : FILEPCX.H *
;* *
;* Programmer : Julio R. Jerez *
;* *
;* Start Date : May 2, 1995 *
;* *
;* Last Update : May 2, 1995 [JRJ] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette,void *buff, long size);
;* GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette, BufferClass& Buff);
;* int Write_PCX_File (char* name, GraphicViewPortClass& pic, BYTE* palette );*
;*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
#include <string.h>
#include <buffer.h>
#include <gbuffer.h>
#include <file.h>
#ifndef PCX_H
#define PCX_H
typedef struct {
char red ;
char green ;
char blue ;
} RGB ;
typedef struct {
char id ;
char version ;
char encoding ;
char pixelsize ;
short x ;
short y ;
short width ;
short height ;
short xres ;
short yres ;
RGB ega_palette [ 16 ] ;
char nothing ;
char color_planes ;
short byte_per_line ;
short palette_type ;
char filler [ 58 ] ;
} PCX_HEADER ;
GraphicBufferClass* Read_PCX_File (char* name, BYTE* palette= NULL,void *buff=NULL, long size=0);
GraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,BYTE* palette= NULL) ;
int Write_PCX_File (char* name, GraphicViewPortClass& pic ,BYTE* palette ) ;
#endif

168
WWFLAT32/IFF/IFF.BAK Normal file
View File

@@ -0,0 +1,168 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
***************************************************************************
* *
* Project Name : Part of the FILEIO Library *
* *
* File Name : IFF.H *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : April 20, 1994 *
* *
* Last Update : April 20, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef IFF_H
#define IFF_H
#ifndef MISC_H
#include <misc.h> // This is needed fro Reverse_WORD and _LONG
#endif
#ifndef MEMFLAGS_H
#include <memflag.h> // This is needed for MemoryFlagType.
#endif
#ifndef GBUFFER_H
#include <gbuffer.h>
#endif
#define LZW_SUPPORTED FALSE
/*=========================================================================*/
/* Iff and Load Picture system defines and enumerations */
/*=========================================================================*/
#define MAKE_ID(a,b,c,d) ((LONG) ((LONG) d << 24) | ((LONG) c << 16) | ((LONG) b << 8) | (LONG)(a))
#define IFFize_WORD(a) Reverse_WORD(a)
#define IFFize_LONG(a) Reverse_LONG(a)
//lint -strong(AJX,PicturePlaneType)
typedef enum {
BM_AMIGA, // Bit plane format (8K per bitplane).
BM_MCGA, // Byte per pixel format (64K).
BM_DEFAULT=BM_MCGA // Default picture format.
} PicturePlaneType;
/*
** This is the compression type code. This value is used in the compressed
** file header to indicate the method of compression used. Note that the
** LZW method may not be supported.
*/
//lint -strong(AJX,CompressionType)
typedef enum {
NOCOMPRESS, // No compression (raw data).
LZW12, // LZW 12 bit codes.
LZW14, // LZW 14 bit codes.
HORIZONTAL, // Run length encoding (RLE).
LCW // Westwood proprietary compression.
} CompressionType;
/*
** Compressed blocks of data must start with this header structure.
** Note that disk based compressed files have an additional two
** leading bytes that indicate the size of the entire file.
*/
//lint -strong(AJX,CompHeaderType)
typedef struct {
BYTE Method; // Compression method (CompressionType).
BYTE pad; // Reserved pad byte (always 0).
LONG Size; // Size of the uncompressed data.
WORD Skip; // Number of bytes to skip before data.
} CompHeaderType;
/*=========================================================================*/
/* The following prototypes are for the file: IFF.CPP */
/*=========================================================================*/
WORD cdecl Open_Iff_File(BYTE const *filename);
VOID cdecl Close_Iff_File(WORD fh);
ULONG cdecl Get_Iff_Chunk_Size(WORD fh, LONG id);
ULONG cdecl Read_Iff_Chunk(WORD fh, LONG id, VOID *buffer, ULONG maxsize);
VOID cdecl Write_Iff_Chunk(WORD file, LONG id, VOID *buffer, LONG length);
/*=========================================================================*/
/* The following prototypes are for the file: LOADPICT.CPP */
/*=========================================================================*/
WORD cdecl Load_Picture(BYTE const *filename, BufferClass& scratchbuf, BufferClass& destbuf, UBYTE *palette=NULL, PicturePlaneType format=BM_DEFAULT);
/*=========================================================================*/
/* The following prototypes are for the file: LOAD.CPP */
/*=========================================================================*/
ULONG cdecl Load_Data(BYTE const *name, VOID *ptr, ULONG size);
ULONG cdecl Write_Data(BYTE const *name, VOID *ptr, ULONG size);
VOID * cdecl Load_Alloc_Data(BYTE const *name, MemoryFlagType flags);
ULONG cdecl Load_Uncompress(BYTE const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, VOID *reserved_data=NULL);
ULONG cdecl Uncompress_Data(VOID const *src, VOID *dst);
VOID cdecl Set_Uncomp_Buffer(WORD buffer_segment, UWORD size_of_buffer);
/*=========================================================================*/
/* The following prototypes are for the file: WRITELBM.CPP */
/*=========================================================================*/
PUBLIC BOOL Write_LBM_File(WORD lbmhandle, BufferClass& buff, WORD bitplanes, UBYTE *palette);
/*========================= Assembly Functions ============================*/
#ifdef __cplusplus
extern "C" {
#endif
/*=========================================================================*/
/* The following prototypes are for the file: PACK2PLN.ASM */
/*=========================================================================*/
extern VOID Pack_2_Plane(VOID *buffer, VOID * pageptr, WORD planebit);
/*=========================================================================*/
/* The following prototypes are for the file: LCWCOMP.ASM */
/*=========================================================================*/
extern ULONG LCW_Compress(VOID *source, VOID *dest, ULONG length);
/*=========================================================================*/
/* The following prototypes are for the file: LCWUNCMP.ASM */
/*=========================================================================*/
extern ULONG LCW_Uncompress(VOID *source, VOID *dest, ULONG length);
#ifdef __cplusplus
}
#endif
/*=========================================================================*/
#endif //IFF_H


325
WWFLAT32/IFF/IFF.CPP Normal file
View File

@@ -0,0 +1,325 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
***************************************************************************
* *
* Project Name : Westwood Library *
* *
* File Name : IFF.C *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : May 16, 1991 *
* *
* Last Update : April 19, 1994 [SKB] *
* *
* *
* IFF reader code designed for loading pictures (ILBM or PBM). *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Close_Iff_File -- Closes an IFF file handle. *
* Get_Iff_Chunk_Size -- Get the size of the given IFF chunk. *
* Open_Iff_File -- Opens an IFF file for reading. *
* Read_Iff_Chunk -- Reads a chunk from an IFF file. *
* Write_Iff_Chunk -- Writes an IFF chuck out. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <wwstd.h>
#include "iff.h"
#include "file.h"
#define ID_FORM MAKE_ID('F','O','R','M')
/***************************************************************************
* OPEN_IFF_FILE -- Opens an IFF file for reading. *
* *
* This function will open an IFF file for reading. It will perform *
* a the simple validity test of checking the first four bytes to make *
* sure they are "FORM". The value returned is the filehandle of the *
* opened file. *
* *
* INPUT: filename - ASCII name of the IFF file to be opened. *
* *
* OUTPUT: Returns the filehandle. If there is an error or the file *
* is not an IFF FORM then -1 will be returned. *
* *
* WARNINGS: You are responsible for error handling if this function *
* returns -1 (not an IFF file). *
* *
* HISTORY: *
* 05/16/1991 JLB : Created. *
* 04/19/1994 SKB : Update to 32 bit library. *
*=========================================================================*/
WORD cdecl Open_Iff_File(BYTE const *filename)
{
WORD fh; // File handle.
LONG type; // IFF file type.
/* We want to be able to open the file for READ | WRITE, but we do not
want the Open_File to create it. So check to see if it exists before
the Open_File */
// fh = Open_File(filename, READ); // Open the source file for READ
// Close_File(fh);
//fh = Open_File(filename, READ | WRITE); // Open the source file again
fh = Open_File(filename, READ); // Open the source file again
// Validate that it is a FORM type.
Read_File(fh, &type, 4L);
if (type == ID_FORM) {
// The file is valid (so far). Position the read so that the actual
// IFF file type code can be read.
Seek_File(fh, 4L, SEEK_CUR); // Skip the filesize bytes.
} else {
// This is NOT an IFF file. Close the source file and return with
// the error code.
Close_File(fh);
fh = ERROR;
}
return fh;
}
/***************************************************************************
* CLOSE_IFF_FILE -- Closes an IFF file handle. *
* *
* The routine will close the file that was opened with the *
* Open_Iff_File() function. *
* *
* INPUT: fh - File handle that was returned from Open_Iff_File(). *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/16/1991 JLB : Created. *
* 04/19/1994 SKB : Update to 32 bit library. *
*=========================================================================*/
VOID cdecl Close_Iff_File(WORD fh)
{
if (fh != ERROR) Close_File(fh);
}
/***************************************************************************
* GET_IFF_CHUNK_SIZE -- Get the size of the given IFF chunk. *
* *
* INPUT: WORD file handle to open IFF file, LONG id to get size of *
* *
* OUTPUT: LONG size of the chunk or 0L if it was not found *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 06/03/1991 CY : Created. *
* 04/19/1994 SKB : Update to 32 bit library. *
*=========================================================================*/
ULONG cdecl Get_Iff_Chunk_Size(WORD fh, LONG id)
{
LONG form; // Chunk iff form name.
LONG chunksize; // Size of the chunk.
BYTE first_iteration; // Check once the current chunk name
first_iteration = TRUE;
for (;;) {
if (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;
if (Read_File(fh, (BYTE *) &chunksize, 4L) != 4L && !first_iteration) break;
#if(IBM)
chunksize = Reverse_LONG(chunksize);
#endif
if (id == form) {
Seek_File(fh, -8L, SEEK_CUR); // Seek back to the start of
return(chunksize); // the chunk & return size
} else {
if (first_iteration) {
Seek_File(fh, 12L, SEEK_SET); // Start at beginning of file.
first_iteration = FALSE; // Don't do this again
} else {
/* Otherwise, go to the next chunk in the file */
chunksize = (chunksize + 1) & 0xFFFFFFFEL;
Seek_File(fh, chunksize, SEEK_CUR);
}
}
}
return(0L);
}
/***************************************************************************
* READ_IFF_CHUNK -- Reads a chunk from an IFF file. *
* *
* Once an IFF file is opened, various chunks must be read from it. *
* This routine will search through the IFF file and load in the *
* specified chunk. It will scan through the entire file when *
* searching for the chunk. It will load the FIRST chunk of the given *
* type. *
* *
* INPUT: fh - File handle of IFF file. *
* *
* id - Chunk ID code. *
* *
* buffer - Pointer to buffer to load the chunk. *
* *
* maxsize - Maximum data bytes to read. *
* *
* OUTPUT: Returns with the number of bytes read from the chunk. *
* If 0 is returned, this indicates that the chunk wasn't *
* found. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/16/1991 JLB : Created. *
* 04/19/1994 SKB : Update to 32 bit library. *
*=========================================================================*/
ULONG cdecl Read_Iff_Chunk(WORD fh, LONG id, VOID *buffer, ULONG maxsize)
{
LONG form; // Chunk iff form name.
ULONG chunksize; // Size of the chunk.
BYTE first_iteration; // Check once the current chunk name
first_iteration = TRUE;
for (;;) {
if (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;
if (Read_File(fh, (BYTE *) &chunksize, 4L) != 4L && !first_iteration) break;
#if(IBM)
chunksize = Reverse_LONG(chunksize);
#endif
if (id == form) {
maxsize = MIN(maxsize, chunksize);
Read_File(fh, buffer, maxsize); // Read the buffer.
chunksize = (chunksize + 1) & 0xFFFFFFFEL;
if (maxsize < chunksize) {
Seek_File(fh, chunksize - maxsize, SEEK_CUR);
}
return(maxsize);
} else {
if (first_iteration) {
Seek_File(fh, 12L, SEEK_SET); // Start at beginning of file.
first_iteration = FALSE; // Don't do this again
} else {
/* Otherwise, go to the next chunk in the file */
chunksize = (chunksize + 1) & 0xFFFFFFFEL;
Seek_File(fh, chunksize, SEEK_CUR);
}
}
}
return(0L);
}
/***************************************************************************
* WRITE_IFF_CHUNK -- Writes an IFF chuck out. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/19/1994 SKB : Created. *
*=========================================================================*/
VOID cdecl Write_Iff_Chunk(WORD file, LONG id, VOID *buffer, LONG length)
{
LONG pos; // Current position in the IFF file.
LONG oldpos; // Record of start of chunk offset.
LONG endpos; // end of file offset before we write our data
LONG value;
BOOL odd; // Is length odd?
BYTE pad = 0; // Optional padding byte for even sized chunks.
/*
** Get the current end of file (before we write more data to the file)
*/
pos = Seek_File (file, 0L, SEEK_CUR);
endpos = Seek_File (file, 0L, SEEK_END);
Seek_File (file, pos, SEEK_SET);
if (length) {
value = id;
odd = (WORD)length & 0x01;
Write_File(file, &value, 4L);
oldpos = Seek_File(file, 0L, SEEK_CUR);
Write_File(file, &value, 4L);
Write_File(file, buffer, length);
pos = Seek_File(file, 0L, SEEK_CUR);
if (odd) {
Write_File(file, &pad, 1L);
}
/*
** Update the chunk size LONG.
*/
Seek_File(file, oldpos, SEEK_SET);
value = IFFize_LONG((pos - oldpos)-4);
Write_File(file, &value, 4L);
/*
** Update the file size LONG. if we are not just overwriting existing data
*/
// (MCC)
if ( endpos < pos ) {
Seek_File(file, 4L, SEEK_SET);
value = IFFize_LONG((pos+odd) - 8);
Write_File(file, &value, 4L);
}
/*
** Return to end of file.
*/
Seek_File(file, 0L, SEEK_END);
}
}

168
WWFLAT32/IFF/IFF.H Normal file
View File

@@ -0,0 +1,168 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
***************************************************************************
* *
* Project Name : Part of the FILEIO Library *
* *
* File Name : IFF.H *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : April 20, 1994 *
* *
* Last Update : April 20, 1994 [SKB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef IFF_H
#define IFF_H
#ifndef MISC_H
#include <misc.h> // This is needed fro Reverse_WORD and _LONG
#endif
#ifndef MEMFLAGS_H
#include <memflag.h> // This is needed for MemoryFlagType.
#endif
#ifndef GBUFFER_H
#include <gbuffer.h>
#endif
#define LZW_SUPPORTED FALSE
/*=========================================================================*/
/* Iff and Load Picture system defines and enumerations */
/*=========================================================================*/
#define MAKE_ID(a,b,c,d) ((LONG) ((LONG) d << 24) | ((LONG) c << 16) | ((LONG) b << 8) | (LONG)(a))
#define IFFize_WORD(a) Reverse_WORD(a)
#define IFFize_LONG(a) Reverse_LONG(a)
//lint -strong(AJX,PicturePlaneType)
typedef enum {
BM_AMIGA, // Bit plane format (8K per bitplane).
BM_MCGA, // Byte per pixel format (64K).
BM_DEFAULT=BM_MCGA // Default picture format.
} PicturePlaneType;
/*
** This is the compression type code. This value is used in the compressed
** file header to indicate the method of compression used. Note that the
** LZW method may not be supported.
*/
//lint -strong(AJX,CompressionType)
typedef enum {
NOCOMPRESS, // No compression (raw data).
LZW12, // LZW 12 bit codes.
LZW14, // LZW 14 bit codes.
HORIZONTAL, // Run length encoding (RLE).
LCW // Westwood proprietary compression.
} CompressionType;
/*
** Compressed blocks of data must start with this header structure.
** Note that disk based compressed files have an additional two
** leading bytes that indicate the size of the entire file.
*/
//lint -strong(AJX,CompHeaderType)
typedef struct {
BYTE Method; // Compression method (CompressionType).
BYTE pad; // Reserved pad byte (always 0).
LONG Size; // Size of the uncompressed data.
WORD Skip; // Number of bytes to skip before data.
} CompHeaderType;
/*=========================================================================*/
/* The following prototypes are for the file: IFF.CPP */
/*=========================================================================*/
WORD cdecl Open_Iff_File(BYTE const *filename);
VOID cdecl Close_Iff_File(WORD fh);
ULONG cdecl Get_Iff_Chunk_Size(WORD fh, LONG id);
ULONG cdecl Read_Iff_Chunk(WORD fh, LONG id, VOID *buffer, ULONG maxsize);
VOID cdecl Write_Iff_Chunk(WORD file, LONG id, VOID *buffer, LONG length);
/*=========================================================================*/
/* The following prototypes are for the file: LOADPICT.CPP */
/*=========================================================================*/
//WORD cdecl Load_Picture(BYTE const *filename, BufferClass& scratchbuf, BufferClass& destbuf, UBYTE *palette=NULL, PicturePlaneType format=BM_DEFAULT);
/*=========================================================================*/
/* The following prototypes are for the file: LOAD.CPP */
/*=========================================================================*/
ULONG cdecl Load_Data(BYTE const *name, VOID *ptr, ULONG size);
ULONG cdecl Write_Data(BYTE const *name, VOID *ptr, ULONG size);
VOID * cdecl Load_Alloc_Data(BYTE const *name, MemoryFlagType flags);
//ULONG cdecl Load_Uncompress(BYTE const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, VOID *reserved_data=NULL);
ULONG cdecl Uncompress_Data(VOID const *src, VOID *dst);
VOID cdecl Set_Uncomp_Buffer(WORD buffer_segment, UWORD size_of_buffer);
/*=========================================================================*/
/* The following prototypes are for the file: WRITELBM.CPP */
/*=========================================================================*/
PUBLIC BOOL Write_LBM_File(WORD lbmhandle, BufferClass& buff, WORD bitplanes, UBYTE *palette);
/*========================= Assembly Functions ============================*/
#ifdef __cplusplus
extern "C" {
#endif
/*=========================================================================*/
/* The following prototypes are for the file: PACK2PLN.ASM */
/*=========================================================================*/
extern VOID Pack_2_Plane(VOID *buffer, VOID * pageptr, WORD planebit);
/*=========================================================================*/
/* The following prototypes are for the file: LCWCOMP.ASM */
/*=========================================================================*/
extern ULONG LCW_Compress(VOID *source, VOID *dest, ULONG length);
/*=========================================================================*/
/* The following prototypes are for the file: LCWUNCMP.ASM */
/*=========================================================================*/
extern ULONG LCW_Uncompress(VOID *source, VOID *dest, ULONG length);
#ifdef __cplusplus
}
#endif
/*=========================================================================*/
#endif //IFF_H


286
WWFLAT32/IFF/LCWCOMP.ASM Normal file
View File

@@ -0,0 +1,286 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
; $Header: g:/library/wwlib32/misc/rcs/lcwcomp.asm 1.1 1994/04/11 15:31:10 jeff_wilson Exp $
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Library routine *
;* *
;* File Name : COMPRESS.ASM *
;* *
;* Programmer : Louis Castle *
;* *
;* Last Update : 20 August, 1990 [CY] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* *
; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length); *
;* *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL LCW_Compress :NEAR
CODESEG
; ----------------------------------------------------------------
;
; Here are prototypes for the routines defined within this module:
;
; ULONG LCW_Compress(BYTE *source,BYTE *dest, ULONG length);
;
; ----------------------------------------------------------------
;***********************************************************
;
; ULONG LCW_Compress(BYTE *source, BYTE *dest, ULONG length)
;
; returns the size of the compressed data in bytes
;
;*
PROC LCW_Compress C near
USES ebx,ecx,edx,edi,esi
ARG source:DWORD
ARG dest:DWORD
ARG datasize:DWORD
LOCAL inlen:DWORD
LOCAL a1stdest:DWORD
LOCAL a1stsrc:DWORD
LOCAL lenoff:DWORD
LOCAL ndest:DWORD
LOCAL count:DWORD
LOCAL matchoff:DWORD
LOCAL end_of_data:DWORD
cld
mov edi,[dest]
mov esi,[source]
mov edx,[datasize] ; get length of data to compress
; mov ax,ds
; mov es,ax
;
; compress data to the following codes in the format b = byte, w = word
; n = byte code pulled from compressed data
; Bit field of n command description
; n=0xxxyyyy,yyyyyyyy short run back y bytes and run x+3
; n=10xxxxxx,n1,n2,...,nx+1 med length copy the next x+1 bytes
; n=11xxxxxx,w1 med run run x+3 bytes from offset w1
; n=11111111,w1,w2 long run run w1 bytes from offset w2
; n=10000000 end end of data reached
;
cld ; make sure all string commands are forward
mov ebx,esi
add ebx,edx
mov [end_of_data],ebx
mov [inlen],1 ; set the in-length flag
mov [a1stdest],edi ; save original dest offset for size calc
mov [a1stsrc],esi ; save offset of first byte of data
mov [lenoff],edi ; save the offset of the legth of this len
sub eax,eax
mov al,081h ; the first byte is always a len
stosb ; write out a len of 1
lodsb ; get the byte
stosb ; save it
??loop:
mov [ndest],edi ; save offset of compressed data
mov edi,[a1stsrc] ; get the offset to the first byte of data
mov [count],1 ; set the count of run to 0
??searchloop:
sub eax,eax
mov al,[esi] ; get the current byte of data
cmp al,[esi+64]
jne short ??notrunlength
mov ebx,edi
mov edi,esi
mov ecx,[end_of_data]
sub ecx,edi
repe scasb
dec edi
mov ecx,edi
sub ecx,esi
cmp ecx,65
jb short ??notlongenough
mov [DWORD PTR inlen],0 ; clear the in-length flag
mov esi,edi
mov edi,[ndest] ; get the offset of our compressed data
mov ah,al
mov al,0FEh
stosb
xchg ecx,eax
stosw
mov al,ch
stosb
mov [ndest],edi ; save offset of compressed data
mov edi,ebx
jmp ??searchloop
??notlongenough:
mov edi,ebx
??notrunlength:
??oploop:
mov ecx,esi ; get the address of the last byte +1
sub ecx,edi ; get the total number of bytes left to comp
jz short ??searchdone
repne scasb ; look for a match
jne short ??searchdone ; if we don't find one we're done
mov ebx,[count]
mov ah,[esi+ebx-1]
cmp ah,[edi+ebx-2]
jne ??oploop
mov edx,esi ; save this spot for the next search
mov ebx,edi ; save this spot for the length calc
dec edi ; back up one for compare
mov ecx,[end_of_data] ; get the end of data
sub ecx,esi ; sub current source for max len
repe cmpsb ; see how many bytes match
; start of change MH 9-24-91
jne short ??notend ; if found mismatch then di - bx = match count
inc edi ; else cx = 0 and di + 1 - bx = match count
??notend:
; end of change MH 9-24-91
mov esi,edx ; restore si
mov eax,edi ; get the dest
sub eax,ebx ; sub the start for total bytes that match
mov edi,ebx ; restore dest
cmp eax,[count] ; see if its better than before
jb ??searchloop ; if not keep looking
mov [count],eax ; if so keep the count
dec ebx ; back it up for the actual match offset
mov [matchoff],ebx ; save the offset for later
jmp ??searchloop ; loop until we searched it all
??searchdone:
mov ecx,[count] ; get the count of the longest run
mov edi,[ndest] ; get the offset of our compressed data
cmp ecx,2 ; see if its not enough run to matter
jbe short ??lenin ; if its 0,1, or 2 its too small
cmp ecx,10 ; if not, see if it would fit in a short
ja short ??medrun ; if not, see if its a medium run
mov eax,esi ; if its short get the current address
sub eax,[matchoff] ; sub the offset of the match
cmp eax,0FFFh ; if its less than 12 bits its a short
ja short ??medrun ; if its not, its a medium
??shortrun:
sub ebx,ebx
mov bl,cl ; get the length (3-10)
sub bl,3 ; sub 3 for a 3 bit number 0-7
shl bl,4 ; shift it left 4
add ah,bl ; add in the length for the high nibble
xchg ah,al ; reverse the bytes for a word store
jmp short ??srunnxt ; do the run fixup code
??medrun:
cmp ecx,64 ; see if its a short run
ja short ??longrun ; if not, oh well at least its long
sub cl,3 ; back down 3 to keep it in 6 bits
or cl,0C0h ; the highest bits are always on
mov al,cl ; put it in al for the stosb
stosb ; store it
jmp short ??medrunnxt ; do the run fixup code
??lenin:
cmp [DWORD PTR inlen],0 ; is it doing a length?
jnz short ??len ; if so, skip code
??lenin1:
mov [lenoff],edi ; save the length code offset
mov al,80h ; set the length to 0
stosb ; save it
??len:
mov ebx,[lenoff] ; get the offset of the length code
cmp [BYTE PTR ebx],0BFh ; see if its maxed out
je ??lenin1 ; if so put out a new len code
??stolen:
inc [BYTE PTR ebx] ; inc the count code
lodsb ; get the byte
stosb ; store it
mov [DWORD PTR inlen],1 ; we are now in a length so save it
jmp short ??nxt ; do the next code
??longrun:
mov al,0ffh ; its a long so set a code of FF
stosb ; store it
mov eax,[count] ; send out the count
stosw ; store it
??medrunnxt:
mov eax,[matchoff] ; get the offset
sub eax,[a1stsrc] ; make it relative tot he start of data
??srunnxt:
stosw ; store it
; this code common to all runs
add esi,[count] ; add in the length of the run to the source
mov [DWORD PTR inlen],0 ; set the in leght flag to false
;=======================================================================
??nxt:
cmp esi,[end_of_data] ; see if we did the whole pic
jae short ??out ; if so, cool! were done
jmp ??loop
??out:
mov ax,080h ; remember to send an end of data code
stosb ; store it
mov eax,edi ; get the last compressed address
sub eax,[a1stdest] ; sub the first for the compressed size
ret
ENDP LCW_Compress
END


221
WWFLAT32/IFF/LCWUNCMP.ASM Normal file
View 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/>.
;
; $Header: g:/library/wwlib32/misc/rcs/lcwuncmp.asm 1.1 1994/04/11 15:31:21 jeff_wilson Exp $
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Library routine *
;* *
;* File Name : UNCOMP.ASM *
;* *
;* Programmer : Christopher Yates *
;* *
;* Last Update : 20 August, 1990 [CY] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* *
; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length); *
;* *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
GLOBAL LCW_Uncompress :NEAR
CODESEG
; ----------------------------------------------------------------
;
; Here are prototypes for the routines defined within this module:
;
; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);
;
; ----------------------------------------------------------------
PROC LCW_Uncompress C near
USES ebx,ecx,edx,edi,esi
ARG source:DWORD
ARG dest:DWORD
ARG length:DWORD
;LOCALS
LOCAL a1stdest:DWORD
LOCAL maxlen:DWORD
LOCAL lastbyte:DWORD
LOCAL lastcom:DWORD
LOCAL lastcom1:DWORD
mov edi,[dest]
mov esi,[source]
mov edx,[length]
;
;
; uncompress data to the following codes in the format b = byte, w = word
; n = byte code pulled from compressed data
; Bit field of n command description
; n=0xxxyyyy,yyyyyyyy short run back y bytes and run x+3
; n=10xxxxxx,n1,n2,...,nx+1 med length copy the next x+1 bytes
; n=11xxxxxx,w1 med run run x+3 bytes from offset w1
; n=11111111,w1,w2 long copy copy w1 bytes from offset w2
; n=11111110,w1,b1 long run run byte b1 for w1 bytes
; n=10000000 end end of data reached
;
mov [a1stdest],edi
add edx,edi
mov [lastbyte],edx
cld ; make sure all lod and sto are forward
mov ebx,esi ; save the source offset
??loop:
mov eax,[lastbyte]
sub eax,edi ; get the remaining byte to uncomp
jz short ??out ; were done
mov [maxlen],eax ; save for string commands
mov esi,ebx ; mov in the source index
sub eax,eax
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 cl,al ; put count nibble in ch
shr cl,4 ; get run -3
add ecx,3 ; get actual run length
cmp ecx,[maxlen] ; is it too big to fit?
jbe short ??rsok ; if not, its ok
mov ecx,[maxlen] ; if so, max it out so it dosen't overrun
??rsok:
lodsb ; get rel offset low byte
mov ebx,esi ; save the source offset
mov esi,edi ; get the current dest
sub esi,eax ; get relative offset
rep movsb
jmp ??loop
??notshort:
test al,40h ; is it a length?
jne short ??notlength ; if not it could be med or long run
cmp al,80h ; is it the end?
je short ??out ; if so its over
mov cl,al ; put the byte in count register
and ecx,3Fh ; and off the extra bits
cmp ecx,[maxlen] ; is it too big to fit?
jbe short ??lenok ; if not, its ok
mov ecx,[maxlen] ; if so, max it out so it dosen't overrun
??lenok:
rep movsb
mov ebx,esi ; save the source offset
jmp ??loop
??out:
mov eax,edi
sub eax,[a1stdest]
jmp short ??exit
??notlength:
mov cl,al ; get the entire code
and ecx,3Fh ; and off all but the size -3
add ecx,3 ; add 3 for byte count
cmp al,0FEh
jne short ??notrunlength
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
ret
ENDP LCW_Uncompress
;***********************************************************
END


443
WWFLAT32/IFF/LOAD.BAK Normal file
View File

@@ -0,0 +1,443 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* $Header: g:/library/wwlib32/file/rcs/load.cpp 1.4 1994/04/22 12:42:21 scott_bowen Exp $ */
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
***************************************************************************
* *
* Project Name : LIBRARY *
* *
* File Name : LOAD.C *
* *
* Programmer : Christopher Yates *
* *
* Last Update : September 17, 1993 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Load_Uncompress -- Load and uncompress the given file. *
* Uncompress_Data -- Uncompress standard CPS buffer. *
* Load_Data -- Loads a data file from disk. *
* Load_Alloc_Data -- Loads and allocates buffer for a file. *
* Write_Data -- Writes a block of data as a file to disk. *
* Uncompress_Data -- Uncompresses data from one buffer to another. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <wwstd.h>
#include "file.h"
#include "iff.h"
#include <misc.h>
#include <dos.h>
#include <wwmem.h>
#if(LZW_SUPPORTED)
/* These are our local pointer and size variables for the LZW table. They
are set through the Set_Uncomp_Buffer routine. */
PRIVATE int LZW_Table = 0; /* No current paragraph */
PRIVATE unsigned int LZW_Table_Size = 0; /* No current size */
#endif
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* LOAD_DATA -- Loads a data file from disk. *
* *
* This routine will load a data file from disk. It does no translation*
* on the data. *
* *
* INPUT: name -- Pointer to ASCII filename of the data file. *
* *
* ptr -- Buffer to load the data file into. *
* *
* size -- Maximum size of the buffer (in bytes). *
* *
* OUTPUT: Returns with the number of bytes read. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 06/24/1991 JLB : Created. *
*=========================================================================*/
unsigned long cdecl Load_Data(char const *name, VOID *ptr, unsigned long size)
{
int fd;
fd = Open_File(name, READ);
size = Read_File(fd, ptr, size);
Close_File(fd);
return(size);
}
/***************************************************************************
* WRITE_DATA -- Writes a block of data as a file to disk. *
* *
* This routine will write a block of data as a file to the disk. It *
* is the compliment of Load_Data. *
* *
* INPUT: name -- Name of the file to create. *
* *
* ptr -- Pointer to the block of data to write. *
* *
* size -- Size of the data block to be written. *
* *
* OUTPUT: Returns with the number of bytes actually written. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/05/1992 JLB : Created. *
*=========================================================================*/
unsigned long cdecl Write_Data(char const *name, VOID *ptr, unsigned long size)
{
int fd;
fd = Open_File(name, WRITE);
size = Write_File(fd, ptr, size);
Close_File(fd);
return(size);
}
/***************************************************************************
* LOAD_ALLOC_DATA -- Loads and allocates buffer for a file. *
* *
* The routine will allocate a buffer and load the specified file into *
* it. The kind of memory used for the buffer is determined by the *
* memory allocation flags passed in. *
* *
* INPUT: name -- Name of the file to load. *
* *
* flags -- Memory allocation flags to use when allocating. *
* *
* OUTPUT: Returns with a pointer to the buffer that contains the file's *
* data. *
* *
* WARNINGS: A memory error could occur if regular memory flags are *
* specified. If XMS memory is specified, then this routine *
* could likely return NULL. *
* *
* HISTORY: *
* 05/28/1992 JLB : Created. *
*=========================================================================*/
VOID * cdecl Load_Alloc_Data(char const *name, MemoryFlagType flags)
{
int fd; // Working file handle.
unsigned long size; // Size of the file to load.
VOID *buffer; // Buffer to hold the file.
fd = Open_File(name, READ);
size = File_Size(fd);
buffer = Alloc(size, flags);
if (buffer) {
Read_File(fd, buffer, size);
}
Close_File(fd);
return(buffer);
}
/***************************************************************************
* LOAD_UNCOMPRESS -- Load and uncompress the given file. *
* *
* INPUT: BYTE * - file name to uncompress *
* GraphicBufferClass& - to load the source data into *
* GraphicBufferClass& - for the picture *
* VOID * - ptr for header uncompressed data *
* *
* OUTPUT: unsigned long size of uncompressed data *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/28/1991 CY : Created. *
* 06/26/1991 JLB : Handles load & uncompress to same buffer. *
*=========================================================================*/
unsigned long cdecl Load_Uncompress(char const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, VOID *reserved_data)
{
int fd; // Source file handle.
unsigned int isize; // Size of the file.
unsigned int skipsize; // Size of the skip data bytes.
VOID *uncomp_ptr; // Source buffer pointer.
char *newuncomp_ptr; // Adjusted source pointer.
uncomp_ptr = uncomp_buff.Get_Buffer(); // get a pointer to buffer
/*======================================================================*/
/* Read the file into the uncompression buffer. */
/*======================================================================*/
fd = Open_File(file, READ); // Open up the file to read from
Read_File(fd, (char *) &isize, 2L); // Read the file size
Read_File(fd, uncomp_ptr, 8L); // Read the header bytes in.
isize -= 8; // Remaining data in file.
/*======================================================================*/
/* Check for and read in the skip data block. */
/*======================================================================*/
skipsize = *(((int*)uncomp_ptr) + 3);
if (reserved_data && skipsize) {
Read_File(fd, reserved_data, (unsigned long) skipsize);
} else {
Seek_File(fd, skipsize, SEEK_CUR);
}
*( ((int*)uncomp_ptr+3) ) = 0; // K/O any skip value.
isize -= skipsize;
/*======================================================================*/
/* If the source and dest buffer are the same, we adjust the pointer so */
/* that the compressed data is loaded into the end of the buffer. In */
/* this way the uncompress code can write to the same buffer. */
/*======================================================================*/
newuncomp_ptr = (char *)Add_Long_To_Pointer(uncomp_buff.Get_Buffer(), uncomp_buff.Get_Size() - (isize+8L));
/*======================================================================*/
/* Duplicate the header bytes. */
/*======================================================================*/
Mem_Copy(uncomp_ptr,newuncomp_ptr,8);
/*======================================================================*/
/* Read in the main compressed part of the file. */
/*======================================================================*/
Read_File(fd, newuncomp_ptr + 8, (unsigned long)isize);
Close_File(fd);
/*======================================================================*/
/* Uncompress the file into the destination buffer (which may very well */
/* be the source buffer). */
/*======================================================================*/
return(Uncompress_Data(newuncomp_ptr, dest_buff.Get_Buffer()));
}
#if(0)
/***************************************************************************
* LOAD_UNCOMPRESS -- Load and uncompress the given file. *
* *
* INPUT: BYTE *file name to uncompress, BuffType uncomp_buff to load *
* the source data into, BuffType dest_buff for the picture, *
* VOID *reserved_data pointer for header uncompressed data *
* *
* OUTPUT: unsigned long size of uncompressed data *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/28/1991 CY : Created. *
* 06/26/1991 JLB : Handles load & uncompress to same buffer. *
*=========================================================================*/
unsigned long cdecl Load_Uncompress(char const *file, BuffType uncomp_buff, BuffType dest_buff, VOID *reserved_data)
{
int fd; // Source file handle.
unsigned int isize; // Size of the file.
unsigned int skipsize; // Size of the skip data bytes.
VOID *uncomp_ptr; // Source buffer pointer.
char *newuncomp_ptr; // Adjusted source pointer.
uncomp_ptr = Get_Buff(uncomp_buff); /* Get pointer to uncomp buffer */
/* Read the file into the uncomp_buff */
fd = Open_File(file, READ);
Read_File(fd, (char *) &isize, 2L); /* Read the file size */
#if(AMIGA)
isize = Reverse_WORD(isize);
#endif
Read_File(fd, uncomp_ptr, 8L); // Read the header bytes in.
isize -= 8; // Remaining data in file.
/*
** Check for and read in the skip data block.
*/
skipsize = *(((int*)uncomp_ptr) + 3);
#if(AMIGA)
skipsize = Reverse_WORD(skipsize);
#endif
if (reserved_data && skipsize) {
Read_File(fd, reserved_data, (unsigned long) skipsize);
} else {
Seek_File(fd, skipsize, SEEK_CUR);
}
*( ((int*)uncomp_ptr+3) ) = 0; // K/O any skip value.
isize -= skipsize;
/*
** If the source and dest buffer are the same, we
** adjust the pointer so that the compressed data is
** loaded into the end of the buffer. In this way the
** uncompress code can write to the same buffer.
*/
#if(IBM)
newuncomp_ptr = (char *)Add_Long_To_Pointer(Get_Buff(uncomp_buff), PageArraySize[uncomp_buff] - (isize+8L));
//newuncomp_ptr = (char*)MK_FP(PageArray[uncomp_buff],0);
//newuncomp_ptr += (unsigned int)(PageArraySize[uncomp_buff] - (isize+8));
//newuncomp_ptr = Normalize_Pointer(newuncomp_ptr);
//newuncomp_ptr = MK_FP(FP_SEG(newuncomp_ptr),0);
#else
newuncomp_ptr = Get_Buff(uncomp_buff);
newuncomp_ptr += PageArraySize[uncomp_buff] - ((isize+10) & 0xFFFE);
#endif
/*
** Duplicate the header bytes.
*/
Mem_Copy(uncomp_ptr,newuncomp_ptr,8);
/*
** Read in the main compressed part of the file.
*/
Read_File(fd, newuncomp_ptr + 8, (unsigned long)isize);
Close_File(fd);
return(Uncompress_Data(newuncomp_ptr, Get_Buff(dest_buff)));
}
#endif
/***************************************************************************
* Uncompress_Data -- Uncompresses data from one buffer to another. *
* *
* This routine takes data from a compressed file (sans the first two *
* size bytes) and uncompresses it to a destination buffer. The source *
* data MUST have the CompHeaderType at its start. *
* *
* INPUT: src -- Source compressed data pointer. *
* *
* dst -- Destination (paragraph aligned) pointer. *
* *
* OUTPUT: Returns with the size of the uncompressed data. *
* *
* WARNINGS: If LCW compression is used, the destination buffer must *
* be paragraph aligned. *
* *
* HISTORY: *
* 09/17/1993 JLB : Created. *
*=========================================================================*/
unsigned long cdecl Uncompress_Data(VOID const *src, VOID *dst)
{
unsigned int skip; // Number of leading data to skip.
CompressionType method; // Compression method used.
unsigned long uncomp_size=NULL;
#if(LZW_SUPPORTED)
VOID *table_buffer;
#endif
if (!src || !dst) return(NULL);
/*
** Interpret the data block header structure to determine
** compression method, size, and skip data amount.
*/
uncomp_size = ((CompHeaderType*)src)->Size;
#if(AMIGA)
uncomp_size = Reverse_LONG(uncomp_size);
#endif
skip = ((CompHeaderType*)src)->Skip;
#if(AMIGA)
skip = Reverse_WORD(skip);
#endif
method = (CompressionType) ((CompHeaderType*)src)->Method;
src = Add_Long_To_Pointer((VOID *)src, (long)sizeof(CompHeaderType) + (long)skip);
switch (method) {
default:
case NOCOMPRESS:
Mem_Copy((VOID *) src, dst, uncomp_size);
break;
case HORIZONTAL:
#if LIB_EXTERNS_RESOLVED
RLE_Uncompress((VOID *) src, dst, uncomp_size);
#endif
break;
case LCW:
LCW_Uncompress((VOID *) src, (VOID *) dst, (unsigned long) uncomp_size);
break;
#if(LZW_SUPPORTED)
case LZW12:
/* If the current buffer isn't big enough, try to
allocate one that is */
if (LZW_Table_Size < LZW12BUFFERSIZE) {
table_buffer = Alloc((long) LZW12BUFFERSIZE, MEM_PARA);
LZW12_Uncompress(FP_SEG(src), FP_SEG(dst),
FP_SEG(table_buffer));
Free(table_buffer);
}
else {
LZW12_Uncompress(FP_SEG(src), FP_SEG(dst), LZW_Table);
}
break;
case LZW14:
/* If the current buffer isn't big enough, try to
allocate one that is */
if (LZW_Table_Size < LZW14BUFFERSIZE) {
table_buffer = Alloc((long) LZW14BUFFERSIZE, MEM_PARA);
LZW14_Uncompress(FP_SEG(src), FP_SEG(dst),
FP_SEG(table_buffer));
Free(table_buffer);
}
else {
LZW14_Uncompress(FP_SEG(src), FP_SEG(dst), LZW_Table);
}
break;
#endif
}
return(uncomp_size);
}
#if(LZW_SUPPORTED)
/* ARGSUSED */
#pragma argsused
VOID cdecl Set_Uncomp_Buffer(int buffer_segment, unsigned int size_of_buffer)
{
if ((LZW_Table = buffer_segment) == NULL) {
/* ERROR HERE */
}
if ((LZW_Table_Size = size_of_buffer) == 0U) {
/* ERROR HERE */
}
}
#endif


444
WWFLAT32/IFF/LOAD.CPP Normal file
View File

@@ -0,0 +1,444 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* $Header: g:/library/wwlib32/file/rcs/load.cpp 1.4 1994/04/22 12:42:21 scott_bowen Exp $ */
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
***************************************************************************
* *
* Project Name : LIBRARY *
* *
* File Name : LOAD.C *
* *
* Programmer : Christopher Yates *
* *
* Last Update : September 17, 1993 [JLB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Load_Uncompress -- Load and uncompress the given file. *
* Uncompress_Data -- Uncompress standard CPS buffer. *
* Load_Data -- Loads a data file from disk. *
* Load_Alloc_Data -- Loads and allocates buffer for a file. *
* Write_Data -- Writes a block of data as a file to disk. *
* Uncompress_Data -- Uncompresses data from one buffer to another. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <wwstd.h>
#include "file.h"
#include "iff.h"
#include <misc.h>
#include <dos.h>
#include <wwmem.h>
#if(LZW_SUPPORTED)
/* These are our local pointer and size variables for the LZW table. They
are set through the Set_Uncomp_Buffer routine. */
PRIVATE int LZW_Table = 0; /* No current paragraph */
PRIVATE unsigned int LZW_Table_Size = 0; /* No current size */
#endif
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* LOAD_DATA -- Loads a data file from disk. *
* *
* This routine will load a data file from disk. It does no translation*
* on the data. *
* *
* INPUT: name -- Pointer to ASCII filename of the data file. *
* *
* ptr -- Buffer to load the data file into. *
* *
* size -- Maximum size of the buffer (in bytes). *
* *
* OUTPUT: Returns with the number of bytes read. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 06/24/1991 JLB : Created. *
*=========================================================================*/
unsigned long cdecl Load_Data(char const *name, VOID *ptr, unsigned long size)
{
int fd;
fd = Open_File(name, READ);
size = Read_File(fd, ptr, size);
Close_File(fd);
return(size);
}
/***************************************************************************
* WRITE_DATA -- Writes a block of data as a file to disk. *
* *
* This routine will write a block of data as a file to the disk. It *
* is the compliment of Load_Data. *
* *
* INPUT: name -- Name of the file to create. *
* *
* ptr -- Pointer to the block of data to write. *
* *
* size -- Size of the data block to be written. *
* *
* OUTPUT: Returns with the number of bytes actually written. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 07/05/1992 JLB : Created. *
*=========================================================================*/
unsigned long cdecl Write_Data(char const *name, VOID *ptr, unsigned long size)
{
int fd;
fd = Open_File(name, WRITE);
size = Write_File(fd, ptr, size);
Close_File(fd);
return(size);
}
#ifdef NEVER
/***************************************************************************
* LOAD_ALLOC_DATA -- Loads and allocates buffer for a file. *
* *
* The routine will allocate a buffer and load the specified file into *
* it. The kind of memory used for the buffer is determined by the *
* memory allocation flags passed in. *
* *
* INPUT: name -- Name of the file to load. *
* *
* flags -- Memory allocation flags to use when allocating. *
* *
* OUTPUT: Returns with a pointer to the buffer that contains the file's *
* data. *
* *
* WARNINGS: A memory error could occur if regular memory flags are *
* specified. If XMS memory is specified, then this routine *
* could likely return NULL. *
* *
* HISTORY: *
* 05/28/1992 JLB : Created. *
*=========================================================================*/
VOID * cdecl Load_Alloc_Data(char const *name, MemoryFlagType flags)
{
int fd; // Working file handle.
unsigned long size; // Size of the file to load.
VOID *buffer; // Buffer to hold the file.
fd = Open_File(name, READ);
size = File_Size(fd);
buffer = Alloc(size, flags);
if (buffer) {
Read_File(fd, buffer, size);
}
Close_File(fd);
return(buffer);
}
#endif
/***************************************************************************
* LOAD_UNCOMPRESS -- Load and uncompress the given file. *
* *
* INPUT: BYTE * - file name to uncompress *
* GraphicBufferClass& - to load the source data into *
* GraphicBufferClass& - for the picture *
* VOID * - ptr for header uncompressed data *
* *
* OUTPUT: unsigned long size of uncompressed data *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/28/1991 CY : Created. *
* 06/26/1991 JLB : Handles load & uncompress to same buffer. *
*=========================================================================*/
unsigned long cdecl Load_Uncompress(char const *file, BufferClass& uncomp_buff, BufferClass& dest_buff, VOID *reserved_data)
{
int fd; // Source file handle.
unsigned int isize; // Size of the file.
unsigned int skipsize; // Size of the skip data bytes.
VOID *uncomp_ptr; // Source buffer pointer.
char *newuncomp_ptr; // Adjusted source pointer.
uncomp_ptr = uncomp_buff.Get_Buffer(); // get a pointer to buffer
/*======================================================================*/
/* Read the file into the uncompression buffer. */
/*======================================================================*/
fd = Open_File(file, READ); // Open up the file to read from
Read_File(fd, (char *) &isize, 2L); // Read the file size
Read_File(fd, uncomp_ptr, 8L); // Read the header bytes in.
isize -= 8; // Remaining data in file.
/*======================================================================*/
/* Check for and read in the skip data block. */
/*======================================================================*/
skipsize = *(((int*)uncomp_ptr) + 3);
if (reserved_data && skipsize) {
Read_File(fd, reserved_data, (unsigned long) skipsize);
} else {
Seek_File(fd, skipsize, SEEK_CUR);
}
*( ((int*)uncomp_ptr+3) ) = 0; // K/O any skip value.
isize -= skipsize;
/*======================================================================*/
/* If the source and dest buffer are the same, we adjust the pointer so */
/* that the compressed data is loaded into the end of the buffer. In */
/* this way the uncompress code can write to the same buffer. */
/*======================================================================*/
newuncomp_ptr = (char *)Add_Long_To_Pointer(uncomp_buff.Get_Buffer(), uncomp_buff.Get_Size() - (isize+8L));
/*======================================================================*/
/* Duplicate the header bytes. */
/*======================================================================*/
Mem_Copy(uncomp_ptr,newuncomp_ptr,8);
/*======================================================================*/
/* Read in the main compressed part of the file. */
/*======================================================================*/
Read_File(fd, newuncomp_ptr + 8, (unsigned long)isize);
Close_File(fd);
/*======================================================================*/
/* Uncompress the file into the destination buffer (which may very well */
/* be the source buffer). */
/*======================================================================*/
return(Uncompress_Data(newuncomp_ptr, dest_buff.Get_Buffer()));
}
#if(0)
/***************************************************************************
* LOAD_UNCOMPRESS -- Load and uncompress the given file. *
* *
* INPUT: BYTE *file name to uncompress, BuffType uncomp_buff to load *
* the source data into, BuffType dest_buff for the picture, *
* VOID *reserved_data pointer for header uncompressed data *
* *
* OUTPUT: unsigned long size of uncompressed data *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 05/28/1991 CY : Created. *
* 06/26/1991 JLB : Handles load & uncompress to same buffer. *
*=========================================================================*/
unsigned long cdecl Load_Uncompress(char const *file, BuffType uncomp_buff, BuffType dest_buff, VOID *reserved_data)
{
int fd; // Source file handle.
unsigned int isize; // Size of the file.
unsigned int skipsize; // Size of the skip data bytes.
VOID *uncomp_ptr; // Source buffer pointer.
char *newuncomp_ptr; // Adjusted source pointer.
uncomp_ptr = Get_Buff(uncomp_buff); /* Get pointer to uncomp buffer */
/* Read the file into the uncomp_buff */
fd = Open_File(file, READ);
Read_File(fd, (char *) &isize, 2L); /* Read the file size */
#if(AMIGA)
isize = Reverse_WORD(isize);
#endif
Read_File(fd, uncomp_ptr, 8L); // Read the header bytes in.
isize -= 8; // Remaining data in file.
/*
** Check for and read in the skip data block.
*/
skipsize = *(((int*)uncomp_ptr) + 3);
#if(AMIGA)
skipsize = Reverse_WORD(skipsize);
#endif
if (reserved_data && skipsize) {
Read_File(fd, reserved_data, (unsigned long) skipsize);
} else {
Seek_File(fd, skipsize, SEEK_CUR);
}
*( ((int*)uncomp_ptr+3) ) = 0; // K/O any skip value.
isize -= skipsize;
/*
** If the source and dest buffer are the same, we
** adjust the pointer so that the compressed data is
** loaded into the end of the buffer. In this way the
** uncompress code can write to the same buffer.
*/
#if(IBM)
newuncomp_ptr = (char *)Add_Long_To_Pointer(Get_Buff(uncomp_buff), PageArraySize[uncomp_buff] - (isize+8L));
//newuncomp_ptr = (char*)MK_FP(PageArray[uncomp_buff],0);
//newuncomp_ptr += (unsigned int)(PageArraySize[uncomp_buff] - (isize+8));
//newuncomp_ptr = Normalize_Pointer(newuncomp_ptr);
//newuncomp_ptr = MK_FP(FP_SEG(newuncomp_ptr),0);
#else
newuncomp_ptr = Get_Buff(uncomp_buff);
newuncomp_ptr += PageArraySize[uncomp_buff] - ((isize+10) & 0xFFFE);
#endif
/*
** Duplicate the header bytes.
*/
Mem_Copy(uncomp_ptr,newuncomp_ptr,8);
/*
** Read in the main compressed part of the file.
*/
Read_File(fd, newuncomp_ptr + 8, (unsigned long)isize);
Close_File(fd);
return(Uncompress_Data(newuncomp_ptr, Get_Buff(dest_buff)));
}
#endif
/***************************************************************************
* Uncompress_Data -- Uncompresses data from one buffer to another. *
* *
* This routine takes data from a compressed file (sans the first two *
* size bytes) and uncompresses it to a destination buffer. The source *
* data MUST have the CompHeaderType at its start. *
* *
* INPUT: src -- Source compressed data pointer. *
* *
* dst -- Destination (paragraph aligned) pointer. *
* *
* OUTPUT: Returns with the size of the uncompressed data. *
* *
* WARNINGS: If LCW compression is used, the destination buffer must *
* be paragraph aligned. *
* *
* HISTORY: *
* 09/17/1993 JLB : Created. *
*=========================================================================*/
unsigned long cdecl Uncompress_Data(VOID const *src, VOID *dst)
{
unsigned int skip; // Number of leading data to skip.
CompressionType method; // Compression method used.
unsigned long uncomp_size=NULL;
#if(LZW_SUPPORTED)
VOID *table_buffer;
#endif
if (!src || !dst) return(NULL);
/*
** Interpret the data block header structure to determine
** compression method, size, and skip data amount.
*/
uncomp_size = ((CompHeaderType*)src)->Size;
#if(AMIGA)
uncomp_size = Reverse_LONG(uncomp_size);
#endif
skip = ((CompHeaderType*)src)->Skip;
#if(AMIGA)
skip = Reverse_WORD(skip);
#endif
method = (CompressionType) ((CompHeaderType*)src)->Method;
src = Add_Long_To_Pointer((VOID *)src, (long)sizeof(CompHeaderType) + (long)skip);
switch (method) {
default:
case NOCOMPRESS:
Mem_Copy((VOID *) src, dst, uncomp_size);
break;
case HORIZONTAL:
#if LIB_EXTERNS_RESOLVED
RLE_Uncompress((VOID *) src, dst, uncomp_size);
#endif
break;
case LCW:
LCW_Uncompress((VOID *) src, (VOID *) dst, (unsigned long) uncomp_size);
break;
#if(LZW_SUPPORTED)
case LZW12:
/* If the current buffer isn't big enough, try to
allocate one that is */
if (LZW_Table_Size < LZW12BUFFERSIZE) {
table_buffer = Alloc((long) LZW12BUFFERSIZE, MEM_PARA);
LZW12_Uncompress(FP_SEG(src), FP_SEG(dst),
FP_SEG(table_buffer));
Free(table_buffer);
}
else {
LZW12_Uncompress(FP_SEG(src), FP_SEG(dst), LZW_Table);
}
break;
case LZW14:
/* If the current buffer isn't big enough, try to
allocate one that is */
if (LZW_Table_Size < LZW14BUFFERSIZE) {
table_buffer = Alloc((long) LZW14BUFFERSIZE, MEM_PARA);
LZW14_Uncompress(FP_SEG(src), FP_SEG(dst),
FP_SEG(table_buffer));
Free(table_buffer);
}
else {
LZW14_Uncompress(FP_SEG(src), FP_SEG(dst), LZW_Table);
}
break;
#endif
}
return(uncomp_size);
}
#if(LZW_SUPPORTED)
/* ARGSUSED */
#pragma argsused
VOID cdecl Set_Uncomp_Buffer(int buffer_segment, unsigned int size_of_buffer)
{
if ((LZW_Table = buffer_segment) == NULL) {
/* ERROR HERE */
}
if ((LZW_Table_Size = size_of_buffer) == 0U) {
/* ERROR HERE */
}
}
#endif


187
WWFLAT32/IFF/LOADPCX.CPP Normal file
View File

@@ -0,0 +1,187 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
***************************************************************************
* *
* Project Name : IFF *
* *
* File Name : LOADPCX.CPP *
* *
* Programmer : Julio R. Jerez *
* *
* Start Date : May 2, 1995 *
* *
* Last Update : May 3, 1995 [JRJ] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* GraphicBufferClass* Read_PCX_File (char* name, void *Buff, long size ); *
* int Get_PCX_Palette (char * name, void& palette ) *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <wwlib32.h>
#include "filepcx.h"
/***************************************************************************
* READ_PCX_FILE -- read a pcx file into a Graphic Buffer *
* *
* GraphicBufferClass* Read_PCX_File (char* name, char* palette ,void *Buff, long size ); *
* *
* *
* INPUT: name is a NULL terminated string of the fromat [xxxx.pcx] *
* palette is optional, if palette != NULL the the color palette of *
* the pcx file will be place in the memory block pointed *
* by palette. *
* Buff is optinal, if Buff == NULL a new memory Buffer *
* will be allocated, otherwise the file will be placed *
* at location pointd by Buffer; *
* Size is the size in bytes of the memory block pointed by Buff *
* is also optional;
* *
* OUTPUT: on succes a pointer to a GraphicBufferClass cointaining the *
* pcx file, NULL othewise. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/03/1995 JRJ : Created. *
*=========================================================================*/
#define POOL_SIZE 2048
#define READ_CHAR() * file_ptr ++ ; \
if ( file_ptr >= & pool [ POOL_SIZE ] ) { \
Read_File ( file_handle, pool , POOL_SIZE ) ; \
file_ptr = pool ; \
}
GraphicBufferClass* Read_PCX_File (char* name, BYTE* Palette,void *Buff, long Size)
{
unsigned i , j ;
unsigned rle ;
unsigned color ;
unsigned scan_pos ;
unsigned file_size ;
char * file_ptr ;
int width ;
int height ;
int file_handle ;
char * buffer ;
PCX_HEADER header ;
RGB * pal ;
char pool [ POOL_SIZE ] ;
GraphicBufferClass * pic ;
// Open file name
file_handle = Open_File ( name , READ ) ;
if ( file_handle == ERROR ) return NULL ;
Read_File ( file_handle, & header , sizeof (PCX_HEADER)) ;
if ( header.id != 10 && header.version != 5 &&
header.pixelsize != 8 ) return NULL ;
width = header.width - header.x + 1 ;
height = header.height - header.y + 1 ;
if ( Buff ) {
buffer = ( char * ) Buff;
i = Size / width;
height = MIN ( i - 1, height);
pic = new GraphicBufferClass( Size, width, height, buffer);
if ( !(pic && pic->Get_Buffer()))return NULL ;
} else {
pic = new GraphicBufferClass(width*(height+4), width, height);
if ( !(pic && pic->Get_Buffer()))return NULL ;
}
buffer = (char *) pic->Get_Buffer() ;
file_ptr = pool ;
Read_File ( file_handle, pool , POOL_SIZE ) ;
if ( header.byte_per_line != width )
for ( scan_pos = j = 0 ; j < height ; j ++, scan_pos += width ) {
for ( i = 0 ; i < width ; ) {
rle = READ_CHAR ();
if ( rle > 192 ) {
rle -= 192 ;
color = READ_CHAR (); ;
memset ( buffer + scan_pos + i , color , rle ) ;
i += rle ;
} else * ( buffer + scan_pos + i ++ ) = rle ;
}
if ( i == width )
rle = READ_CHAR () ;
// if ( rle > 192 ) rle = READ_CHAR ();
}
else for ( i = 0 ; i < width * height ; ) {
rle = READ_CHAR ();
if ( rle > 192 ) {
rle -= 192 ;
color = READ_CHAR ();
memset ( buffer + i , color , rle ) ;
i += rle ;
} else * ( buffer + i ++ ) = rle ;
}
if ( Palette ) {
Seek_File ( file_handle , - 256 * sizeof ( RGB ) , SEEK_END ) ;
Read_File ( file_handle, Palette , 256 * sizeof ( RGB )) ;
pal = ( RGB * ) Palette ;
for ( i = 0 ; i < 256 ; i ++ ) {
pal -> red >>= 2 ;
pal -> green >>= 2 ;
pal -> blue >>= 2 ;
pal ++ ;
}
}
Close_File (file_handle) ;
return pic ;
}
/***************************************************************************
* READ_PCX_FILE -- read a pcx file into a Graphic Buffer *
* *
* GraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff, *
* char* palette) * *
* *
* *
* INPUT: name is a NULL terminated string of the fromat [xxxx.pcx] *
* Buff is a pointer to a BufferClass the will hold the pcx file *
* at location pointd by Buffer; *
* palette is optional, if palette != NULL the the color palette of *
* the pcx file will be place in the memory block pointed *
* by palette. *
* *
* OUTPUT: on succes a pointer to a GraphicBufferClass cointaining the *
* pcx file, NULL othewise. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/03/1995 JRJ : Created. *
*=========================================================================*/
GraphicBufferClass* Read_PCX_File (char* name, BufferClass& Buff,char* palette)
{
return Read_PCX_File(name, palette, (void*)Buff.Get_Buffer(), Buff.Get_Size());
}

571
WWFLAT32/IFF/LOADPICT.BAK Normal file
View File

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

574
WWFLAT32/IFF/LOADPICT.CPP Normal file
View File

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

189
WWFLAT32/IFF/MAKEFILE Normal file
View File

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

132
WWFLAT32/IFF/PACK2PLN.ASM Normal file
View File

@@ -0,0 +1,132 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
; $Header: g:/library/wwlib32/file/rcs/pack2pln.asm 1.1 1994/04/22 18:07:46 scott_bowen Exp $
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Library *
;* *
;* File Name : PACK2PLN.ASM *
;* *
;* Programmer : Scott K. Bowen *
;* *
;* Start Date : November 20, 1991 *
;* *
;* Last Update : April 22, 1994 [SKB] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
;******************************************************************************
; External declares so these functions can be called
;
GLOBAL Pack_2_Plane:NEAR
CODESEG
;***************************************************************************
;* PACK_2_PLANE -- packed to planar scanline conversion *
;* *
;* INPUT: BYTE *buffer (far) -- pointer to planar output buffer *
;* BYTE *pageptr (far) -- pointer to current row in packed page *
;* WORD planebit -- current bit used in plane -- use only low byte *
;* *
;* OUTPUT: *
;* Return result in buffer. *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 11/20/1991 SB : Created. *
;* 04/22/1994 SKB : Converted to 32 bit library. *
;*=========================================================================*
; *
; This is the original function that is converted to asm
;
;PRIVATE VOID Pack_2_Plane(UBYTE * buffer, BYTE * pageptr, BYTE planebit)
;{
; WORD currbit=0x80; // current bit to be written to
; WORD pixel; // current pixel in row used as a counter;
;
; buffer--; // will be incremented at the start
; for (currbit = 0, pixel = 0; pixel < 320; pixel++) {
; if (!currbit) {
; currbit = 0x80; // reset bit 7
; buffer++; // go to next byte in buffer
; *buffer = 0; // clear byte so we only need to set bits needed
; }
; if (planebit & *pageptr++)
; *buffer |= currbit; // set bit in destination if plane was set is source
;
; currbit >>= 1; // shift destination bit one right
; }
;}
PROC Pack_2_Plane C NEAR
USES ebx,ecx,esi,edi
ARG buffer:DWORD
ARG page:DWORD
ARG planebit:WORD
mov edi,[buffer]
mov esi,[page]
mov ax,[planebit] ; move bit set for current plane (planebit) to ax
; the low byte will only be used
mov ecx,320d ; set counter to 320 columns (320x200 picture)
mov ah,80h ; set bit 7 of current_bit
dec edi ; this will get incremented at the start
??top_loop: ; while (columns left)
cmp ah,80h ; if current_bit is bit 7
jnz short ??same_dest
; Then
inc edi ; buffer++ increment pointer
mov [BYTE PTR edi],0 ; *buffer = 0
??same_dest: ; EndIf
mov bl,al
and bl,[esi] ; if (planebit & *pageptr)
jz short ??no_set_bit
or [BYTE PTR edi],ah ; Then *buffer |= current_bit
??no_set_bit:
inc esi ; pageptr++ goto next in source byte
ror ah,1 ; rotate current_bit right one
dec ecx ;
jnz ??top_loop
ret
ENDP Pack_2_Plane
END


422
WWFLAT32/IFF/WRITELBM.CPP Normal file
View File

@@ -0,0 +1,422 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* $Header: g:/library/wwlib32/file/rcs/writelbm.cpp 1.1 1994/04/20 14:38:57 scott_bowen Exp $ */
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
***************************************************************************
* *
* Project Name : Write LBM File *
* *
* File Name : writelbm.c *
* *
* Programmer : Scott Bowen *
* *
* Start Date : November 18, 1991 *
* *
* Last Update : November 19, 1991 [SB] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Get_Line -- convert one plane of one row to a packed plane *
* Write_BMHD -- writes out the bit map header (LocalHeader) *
* Write_Body -- writes out compressed data in an LBM file *
* Write_CMAP -- Writes out CMAP (palette) information *
* Write_LBM_File -- Writes out a file in LBM format *
* Write_Row -- compresses and writes a row plane to .lbm file *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
// At the end of this file there is an IFF definition for a .LBM file.
#include <wwstd.h>
#include "iff.h"
#include "file.h"
#include <stdio.h>
#include <string.h>
// A BitMapHeader is stored in a BMHD chunk. This structure MUST be an even size
typedef struct {
UWORD w, h; // raster width & height in pixels
UWORD x, y; // position for this image
UBYTE planes; // # source bitplanes
UBYTE masking; // masking technique
UBYTE compression; // compression algoithm
UBYTE pad1; // UNUSED. For consistency, put 0 here.
UWORD transcolor; // transparent "color number"
UBYTE xaspect, yaspect; // aspect ratio, a rational number x/y
UWORD pagewidth, pageheight; // source "page" size in pixels
} BitMapHeaderType;
// All values in LocalHeader are always the same except planes. This is set in Write_BMHD
// the WORD values must be in low-high order for compatibility.
PRIVATE BitMapHeaderType LocalHeader = {
0x4001, 0xc800, 0, 0, 0, 0, // width, height, x, y, planes, mask
1, 0, 0xFF00, 5, 6, // compress, pad1, transcolor, xasptect, yaspect
0x4001, 0xC800 }; // pagewidth, pageheight
// Used to verify that the write of the header was valid
#define BM_HEADER_SIZE (((sizeof(BitMapHeaderType) + 1) & 0xFFFE) + 8L)
/*=========================================================================*/
/* The following PRIVATE functions are in this file: */
/*=========================================================================*/
PRIVATE LONG Write_BMHD(WORD lbmhandle, WORD bitplanes);
PRIVATE LONG Write_CMAP(WORD lbmhandle, UBYTE * palette, WORD bitplanes);
PRIVATE LONG Write_BODY(WORD lbmhandle, BufferClass& buff, WORD bitplanes);
PRIVATE LONG Write_Row(WORD lbmhandle, UBYTE *buffer);
/*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
/***************************************************************************
* WRITE_LBM_FILE -- Writes out a file in LBM format *
* *
* INPUT: WORD lbmhandle -- lbm file handle already opened by caller *
* BufferClass buff -- buff where MCGA picture is *
* WORD bitplane -- number of bitplanes to convert to *
* BYTE *palette -- pointer to palette for buff *
* *
* OUTPUT: Returns BOOL -- successfull or not *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/18/1991 SB : Created. *
*=========================================================================*/
PUBLIC BOOL Write_LBM_File(WORD lbmhandle, BufferClass& buff, WORD bitplanes, UBYTE *palette)
{
LONG filesize;
Seek_File(lbmhandle, 0L, SEEK_SET); // goto beginning of file
Write_File(lbmhandle, "FORM????ILBM", 12L); // First 12 bytes of all .lbm files
// size is unkown so write ????
filesize = 12L; // 4 bytes for "ILBM"
filesize += Write_BMHD(lbmhandle, bitplanes); // write out BMHD (fixed size)
filesize += Write_CMAP(lbmhandle, palette, bitplanes); // write out CMAP
// Write out the body, or compressed picture image. This size will depend
// on the compression, but the value passed back is what the compressor
// assumed was written to file
filesize += Write_BODY(lbmhandle, buff, bitplanes);
// Verify that we were able to write out the file without running out of space
if (Seek_File(lbmhandle, 0L, SEEK_END) != filesize) {
return(FALSE);
}
Seek_File(lbmhandle, 4L, SEEK_SET); // goto beginning of file
filesize = Reverse_LONG(filesize - 8L); // - 8 because of "FORM" + WORD (size)
Write_File(lbmhandle, (BYTE *) &filesize, 4L); // patch in filesize
return(TRUE);
}
/***************************************************************************
* WRITE_BMHD -- writes out the bit map header (LocalHeader) *
* *
* INPUT: WORD lbmhandle -- file handle for lbm file *
* WORD pitplanes -- number of bitplanes to write out *
* *
* OUTPUT: LONG number of bytes hopefully written out to .LBM file *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/19/1991 SB : Created. *
*=========================================================================*/
PRIVATE LONG Write_BMHD(WORD lbmhandle, WORD bitplanes)
{
LONG size;
Write_File(lbmhandle, "BMHD", 4L); // write out chunk title
size = Reverse_LONG(sizeof(LocalHeader)); // write out size of LocalHeader chunk
Write_File(lbmhandle, (BYTE *) &size, 4L);
LocalHeader.planes = bitplanes; // only nonconstant value in LocalHeader
// Make sure size is even. Return 8 = "BMHD" + size of the bitmap header structure
return(Write_File(lbmhandle, (BYTE *) &LocalHeader,
(sizeof(LocalHeader) + 1) & 0xFFFE) + 8L);
}
/***************************************************************************
* WRITE_CMAP -- Writes out CMAP (palette) information *
* *
* *
* INPUT: WORD lbmhandle -- file handle of lbm file *
* BYTE * palette -- pointer to paletter information *
* WORD bitplanes -- used to figure out size of palette *
* *
* OUTPUT: LONG number of bytes that should have been written out to .LBM. *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/19/1991 SB : Created. *
*=========================================================================*/
PRIVATE LONG Write_CMAP(WORD lbmhandle, UBYTE * palette, WORD bitplanes)
{
WORD color, r, g, b, colors;
LONG size;
UBYTE *pal_ptr;
BYTE rgb[3];
Write_File(lbmhandle, "CMAP", 4L); // write out palette info
colors = 1 << bitplanes; // colors = 2 to the bitplanes
size = Reverse_LONG(colors * 3L); // size = colors * 3 guns
Write_File(lbmhandle, (BYTE *) &size, 4L);
for (pal_ptr = palette, color = 0; color < colors; color++) { // for each color
if ((r = *pal_ptr++) != 0) { // DPaint changes allows 0 - 100 for gun values
r = (r << 2) | 0x03; // this must be converted to 0 - 256 for LBM
} // so LBM_val = (DP_val * 4) | 3 if DP_val != 0
if ((g = *pal_ptr++) != 0) {
g = (g << 2) | 0x03;
}
if ((b = *pal_ptr++) != 0) {
b = (b << 2) | 0x03;
}
rgb[0] = r; // assign gun values to an array to write out
rgb[1] = g;
rgb[2] = b;
Write_File(lbmhandle, rgb, 3L);
}
// size = colors * 3
return(((colors << 1) + colors) + 8L); // total size of CMAP 8 = "CMAP" + WORD (size)
}
/***************************************************************************
* WRITE_BODY -- writes out compressed data in an LBM file *
* *
* INPUT: WORD lbmhandle -- file handle of lbm file *
* *
* OUTPUT: LONG - number of byte written *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/19/1991 SB : Created. *
*=========================================================================*/
PRIVATE LONG Write_BODY(WORD lbmhandle, BufferClass& buff, WORD bitplanes)
{
LONG bodysize = 0;
LONG actualsize;
LONG size;
WORD planebit;
WORD line, plane;
UBYTE buffer[40];
UBYTE *buffptr;
Write_File(lbmhandle, "BODY????", 8L); // BODY chunk ID, ???? reserved for chuncksize
buffptr = (UBYTE *) buff.Get_Buffer(); // point to beginning of buff
for (line = 0; line < 200; line++) {
planebit = 1; // start with bit 1 set
for (plane = 0; plane < bitplanes; plane++) {
Pack_2_Plane(buffer, buffptr, planebit); // convert to planar
bodysize += Write_Row(lbmhandle, buffer); // write to to the BODY in the LBM
planebit <<= 1; // set next bit
}
buffptr += 320; // row size is 320
}
actualsize = bodysize + (bodysize&0x01);
if (actualsize != bodysize) {
Write_File(lbmhandle, buffer, 1); // Padd the block.
}
Seek_File(lbmhandle, -(actualsize + 4L), SEEK_CUR); // Patch in chunksize
size = Reverse_LONG(bodysize);
Write_File(lbmhandle, (BYTE *) &size ,4L);
return(actualsize + 8L); // total size of BODY, "BODY????" = 8 bytes
}
/***************************************************************************
* WRITE_ROW -- compresses and writes a row plane to .lbm file *
* *
* INPUT: WORD lbmhandle -- lbm file handle *
* UBYTE *buffer -- pointer to buffer to be written out *
* *
* OUTPUT: LONG size of chunk that should have been written out *
* *
* WARNINGS: *
* *
* HISTORY: *
* 11/19/1991 SB : Created. *
*=========================================================================*/
// this algorithm was taken from WILBM.c written by EA that was in the
// 1985 yearbook. This is the compression method that DP.EXE uses.
// Change only if DP.EXE changes.
PRIVATE LONG Write_Row(WORD lbmhandle, UBYTE *buffer)
{
WORD i;
WORD chunksize = 0;
WORD dataLength = 40; // 320 rows / 8 ( 1 plane per row)
UBYTE repCode, current, curr_plus_2;
UBYTE *buffptr;
while (dataLength) {
// If at least 2 more bytes and they are equal, then replicate
if ((dataLength >= 2) && (buffer[0] == buffer[1])) {
buffptr = buffer;
for (i = 0; (i <= 128) && (i < (dataLength - 1)); i++) {
if (*buffptr != buffptr[1]) {
break;
}
buffptr++;
}
i++;
repCode = -i + 1;
Write_File(lbmhandle, &repCode, 1L); // Write count as -count+1
Write_File(lbmhandle, buffer, 1L); // Write byte to replicate
buffer += i;
dataLength -= i;
chunksize += 2;
}
else { // Copy literally till 3 byte run or two 2 byte runs found
for (i = 0; (i <= 128) && (i < dataLength); i++) {
current = buffer[i];
curr_plus_2 = buffer[i + 2];
if (i == dataLength - 1)
continue;
if (current != buffer[i + 1])
continue;
if (i == dataLength - 2)
continue;
if (current == curr_plus_2)
break;
if (i == dataLength - 3)
continue;
if (curr_plus_2 == buffer[i + 3])
break;
}
repCode = i - 1;
Write_File(lbmhandle, &repCode, 1L); // Write count as count-1
Write_File(lbmhandle, buffer, (LONG) i); // Write 'count' bytes
buffer += i;
dataLength -= i;
chunksize += i + 1;
}
} // end while
return(chunksize);
}
#if(FALSE)
This is a definition of a DPII .LBM file.
Below this definition are differences in DPIIe .LMB files.
Created by : Scott K. Bowen Nov 18, 1991
Start with .LBM to read definition :
.LBM -> "FORM" + FILESIZE + "ILMB" + CHUNKS
BITPLANES -> (word) // number of bit planes used
BLUE -> (byte) // blue color gun value
BMHD -> "BMHD" + CHUNKSIZE + CONTEXT
BODY ->
CHUNKS -> BMHD | BODY | CMAP | DPPV | CRNG | ????
CHUNKSIZE -> (long) // size of chunk not including header or size.
CMAP -> "CMAP" + CHUNKSIZE + PALETTE_INFO
COMPRESS_METHOD -> (byte) // compression method used
CONTEXT -> WIDTH + HEIGHT + POSX + POSY + #_BITPLANES + MASKING +
COMPRESS_METHOD + PAD + TRANS_COL + XASPECT + YASPECT +
PAGEWIDTH + PAGEHEIGHT
CRNG -> // we do not use
DPPV -> // we do not use
FILESIZE -> (long) //size of file minus (sizeof(FORM) + sizeof(FILESIZE)
GREEN -> (byte) // green color gun value
HEIGHT -> (word) // of picture
MASKING -> (byte) // masking type ?
NUM_COLORS -> //number of colors used depending on format
PAGE_WIDTH -> (word) // width of page
PAGE_HEIGHT -> (word) // height of page
PALETTE_INFO-> (RED+GREEN+BLUE) @ NUM_COLORS
PAD -> (byte) // not used. used as a padding
POSX -> (word) // staring position
POSY -> (word) // staring position
RED -> (byte) // red color gun value
TRANS_COL -> (word) // transparrent color
WIDTH -> (word) // of picture
XASPECT -> (byte) // x aspect ratio
YASPECT -> (byte) // y aspect ratio
???? -> // other possibilities
Differences in DPII enhance version
.LBM -> "FORM" + FILESIZE + "PBM " + CHUNKS
DPPV -> DPPS // uses dpps instead of dppv
CHUNKS -> + TINY // add these to old definition
#endif


175
WWFLAT32/IFF/WRITEPCX.CPP Normal file
View File

@@ -0,0 +1,175 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
***************************************************************************
* *
* Project Name : iff *
* *
* File Name : WRITEPCX.CPP *
* *
* Programmer : Julio R. Jerez *
* *
* Start Date : May 2, 1995 *
* *
* Last Update : May 2, 1995 [JRJ] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* int Save_PCX_File (char* name, GraphicViewPortClass& pic, char* palette)*
*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
#include <wwlib32.h>
#include "filepcx.h"
static void Write_Pcx_ScanLine ( int file_handle , int scansize , char * ptr );
/***************************************************************************
* WRITE_PCX_FILE -- Write the data in ViewPort to a pcx file *
* *
* *
* *
* INPUT: name is a NULL terminated string of the fromat [xxxx.pcx] *
* pic is a pointer to a GraphicViewPortClass or to a *
* GraphicBufferClass holding the picture. *
* palette is a pointer the the memry block holding the color * *
* palette of the picture. *
* *
* OUTPUT: FALSE if the function fails zero otherwise *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/04/1995 JRJ : Created. *
*=========================================================================*/
int Write_PCX_File (char* name, GraphicViewPortClass& pic, BYTE* palette )
{
unsigned i ;
unsigned width ;
int file_handle ;
int VP_Scan_Line ;
char * ptr ;
RGB * pal ;
GraphicBufferClass * Graphic_Buffer ;
PCX_HEADER header = { 10 , 5 , 1 , 8 , 0 , 0 , 319 , 199 ,
320 , 200 , { 0 } , 0 , 1 , 320 , 1 , {0} } ;
// Open file name
file_handle = Open_File ( name , WRITE ) ;
if ( file_handle == ERROR ) return FALSE ;
header.width = pic.Get_Width() - 1 ;
header.height = pic.Get_Height() - 1 ;
header.byte_per_line = pic.Get_Width() ;
Write_File ( file_handle, & header , sizeof (PCX_HEADER)) ;
VP_Scan_Line = pic.Get_Width() + pic.Get_XAdd();
Graphic_Buffer = pic.Get_Graphic_Buffer() ;
ptr = ( char * ) Graphic_Buffer->Get_Buffer() ;
ptr += ( (pic.Get_YPos() * VP_Scan_Line) + pic.Get_XPos() );
for ( i = 0 ; i < header.height + 1 ; i ++ )
Write_Pcx_ScanLine ( file_handle , header.byte_per_line, ptr + i *VP_Scan_Line ) ;
pal = ( RGB * ) palette ;
for ( i = 0 ; i < 256 ; i ++ ) {
pal -> red <<= 2 ;
pal -> green <<= 2 ;
pal -> blue <<= 2 ;
pal ++ ;
}
i = 0x0c ;
Write_File ( file_handle, & i , 1 ) ;
Write_File ( file_handle, palette , 256 * sizeof (RGB) ) ;
Close_File (file_handle) ;
return 0 ;
}
/***************************************************************************
* WRITE_PCX_SCANLINE -- function to write a single pcx scanline to a file *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 05/04/1995 JRJ : Created. *
*=========================================================================*/
#define POOL_SIZE 2048
#define WRITE_CHAR(x) { \
* file_ptr ++ = x ; \
if ( file_ptr >= & pool [ POOL_SIZE ] ) { \
Write_File ( file_handle, pool , POOL_SIZE ) ; \
file_ptr = pool ; \
} }
void Write_Pcx_ScanLine ( int file_handle , int scansize , char * ptr )
{
unsigned i ;
unsigned rle ;
unsigned color ;
unsigned last ;
char * file_ptr ;
char pool [ POOL_SIZE ] ;
file_ptr = pool ;
last = * ptr ;
rle = 1 ;
for ( i = 1 ; i < scansize ; i ++ ) {
color = 0xff & * ++ ptr ;
if ( color == last ) {
rle ++ ;
if ( rle == 63 ) {
WRITE_CHAR ( 255 ) ;
WRITE_CHAR ( color ) ;
rle = 0 ;
}
} else if ( rle ) {
if ( rle == 1 && ( 192 != ( 192 & last ))) {
WRITE_CHAR ( last ) ;
} else {
WRITE_CHAR ( rle + 192 ) ;
WRITE_CHAR ( last ) ;
}
last = color ;
rle = 1 ;
}
}
if ( rle ) {
if ( rle == 1 && ( 192 != ( 192 & last ))) {
WRITE_CHAR ( last ) ;
} else {
WRITE_CHAR ( rle + 192 ) ;
WRITE_CHAR ( last) ;
}
}
Write_File ( file_handle, pool , ( int ) file_ptr - ( int ) pool ) ;
}