| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** 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 "iff.h"
- #include "file.h"
- #include <wwstd.h>
- #include <stdio.h>
- #include <string.h>
- // A BitMapHeader is stored in a BMHD chunk. This structure MUST be an even size
- typedef struct {
- unsigned short w, h; // raster width & height in pixels
- unsigned short x, y; // position for this image
- unsigned char planes; // # source bitplanes
- unsigned char masking; // masking technique
- unsigned char compression; // compression algoithm
- unsigned char pad1; // UNUSED. For consistency, put 0 here.
- unsigned short transcolor; // transparent "color number"
- unsigned char xaspect, yaspect; // aspect ratio, a rational number x/y
- unsigned short 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 short 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(int lbmhandle, int bitplanes);
- PRIVATE long Write_CMAP(int lbmhandle, unsigned char * palette, int bitplanes);
- PRIVATE long Write_BODY(int lbmhandle, BufferClass& buff, int bitplanes);
- PRIVATE long Write_Row(int lbmhandle, unsigned char *buffer);
- /*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
- /***************************************************************************
- * WRITE_LBM_FILE -- Writes out a file in LBM format *
- * *
- * INPUT: int lbmhandle -- lbm file handle already opened by caller *
- * BufferClass buff -- buff where MCGA picture is *
- * int bitplane -- number of bitplanes to convert to *
- * char *palette -- pointer to palette for buff *
- * *
- * OUTPUT: Returns BOOL -- successfull or not *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/18/1991 SB : Created. *
- *=========================================================================*/
- PUBLIC BOOL Write_LBM_File(int lbmhandle, BufferClass& buff, int bitplanes, unsigned char *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, (char *) &filesize, 4L); // patch in filesize
- return(TRUE);
- }
- /***************************************************************************
- * WRITE_BMHD -- writes out the bit map header (LocalHeader) *
- * *
- * INPUT: int lbmhandle -- file handle for lbm file *
- * int 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(int lbmhandle, int 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, (char *) &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, (char *) &LocalHeader,
- (sizeof(LocalHeader) + 1) & 0xFFFE) + 8L);
- }
- /***************************************************************************
- * WRITE_CMAP -- Writes out CMAP (palette) information *
- * *
- * *
- * INPUT: int lbmhandle -- file handle of lbm file *
- * char * palette -- pointer to paletter information *
- * int 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(int lbmhandle, unsigned char * palette, int bitplanes)
- {
- int color, r, g, b, colors;
- long size;
- unsigned char *pal_ptr;
- char 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, (char *) &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: int lbmhandle -- file handle of lbm file *
- * *
- * OUTPUT: long - number of byte written *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 11/19/1991 SB : Created. *
- *=========================================================================*/
- PRIVATE long Write_BODY(int lbmhandle, BufferClass& buff, int bitplanes)
- {
- long bodysize = 0;
- long actualsize;
- long size;
- int planebit;
- int line, plane;
- unsigned char buffer[40];
- unsigned char *buffptr;
- Write_File(lbmhandle, "BODY????", 8L); // BODY chunk ID, ???? reserved for chuncksize
- buffptr = (unsigned char *) 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, (char *) &size ,4L);
- return(actualsize + 8L); // total size of BODY, "BODY????" = 8 bytes
- }
- /***************************************************************************
- * WRITE_ROW -- compresses and writes a row plane to .lbm file *
- * *
- * INPUT: int lbmhandle -- lbm file handle *
- * unsigned char *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(int lbmhandle, unsigned char *buffer)
- {
- int i;
- int chunksize = 0;
- int dataLength = 40; // 320 rows / 8 ( 1 plane per row)
- unsigned char repCode, current, curr_plus_2;
- unsigned char *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
|