Initial commit of Command & Conquer Red Alert source code.
This commit is contained in:
77
WWFLAT32/IFF/FILEPCX.H
Normal file
77
WWFLAT32/IFF/FILEPCX.H
Normal 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
168
WWFLAT32/IFF/IFF.BAK
Normal 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
325
WWFLAT32/IFF/IFF.CPP
Normal 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
168
WWFLAT32/IFF/IFF.H
Normal 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
286
WWFLAT32/IFF/LCWCOMP.ASM
Normal 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
221
WWFLAT32/IFF/LCWUNCMP.ASM
Normal file
@@ -0,0 +1,221 @@
|
||||
;
|
||||
; Command & Conquer Red Alert(tm)
|
||||
; Copyright 2025 Electronic Arts Inc.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
;
|
||||
|
||||
; $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
443
WWFLAT32/IFF/LOAD.BAK
Normal 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
444
WWFLAT32/IFF/LOAD.CPP
Normal 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
187
WWFLAT32/IFF/LOADPCX.CPP
Normal 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
571
WWFLAT32/IFF/LOADPICT.BAK
Normal 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
574
WWFLAT32/IFF/LOADPICT.CPP
Normal 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
189
WWFLAT32/IFF/MAKEFILE
Normal 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
132
WWFLAT32/IFF/PACK2PLN.ASM
Normal 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
422
WWFLAT32/IFF/WRITELBM.CPP
Normal 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
175
WWFLAT32/IFF/WRITEPCX.CPP
Normal 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 ) ;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user