123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2016 RWS Inc, All Rights Reserved
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of version 2 of the GNU General Public License as published by
- // the Free Software Foundation
- //
- // 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, write to the Free Software Foundation, Inc.,
- // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- //
- ///////////////////////////////////////////////////////////////////////////////
- //
- // RAMFLX.CPP
- //
- // History:
- // 08/05/94 MR Started. (10h)
- //
- // 08/07/94 MR Got decompression working (except for SS2) and started
- // on compression. (13h)
- //
- // 08/08/94 MR General cleanup of interfaces, etc. (12h)
- //
- // 08/09/94 MR Finished up basic compression.
- //
- // 08/12/94 MR Added flags to FLX_BUF struct that indicate whether the
- // pixels and/or the colors were modified by a "Read".
- //
- // 08/15/94 MR Fixed bug in ReadFrame() -- if the requested frame was
- // the current frame, it was not copied to the specified buf.
- //
- // Also added a function that returns the last frame that
- // was written.
- //
- // 05/02/95 JW Added functionality for RAM buffer to store flic
- //
- // 05/03/95 JW Added ability to play uncompressed flics without having
- // to seek to the first frame.
- //
- // 11/03/95 JMI Converted to newest CImage and CNFile.
- //
- // 03/04/96 JMI ReadFrame now remembers whether the m_sColorsModified and
- // m_sPixelsModified flags were set at all during a read that
- // required parsing many frames and sets them to TRUE in such
- // a case.
- //
- ///////////////////////////////////////////////////////////////////////////////
- //
- // THIS FILE CONTAINS ONLY THE PUBLIC FUNCTIONS.
- // THE PRIVATE FUNCTIONS ARE IN FLXP.CPP
- //
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Offers a clean and simple interface for reading and writing .FLC files.
- //
- // MEGA WARNING: The memory management being used in this module relies
- // completely on the memory model under which it is compiled. The recommended
- // model is large. However, in large model, flics larger than 320 x 200 are
- // not possible since the image data would exceed 64k! In the 32-bit future,
- // this will no longer be a problem. For now, we're stuck with it.
- // Note that using the huge memory model will not help because many of the
- // math and the indexes are "short" (16 bits), so the results would not be/
- // valid for larger than 320 x 200!
- //
- ///////////////////////////////////////////////////////////////////////////////
- #include <string.h>
- #include <malloc.h>
- #include <SMRTHEAP.HPP>
- #include "common/system.h"
- #include "ramflx/ramflx.h"
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Default constructor. If this is used, then Setup() must be called before
- // any other function can be called.
- //
- ///////////////////////////////////////////////////////////////////////////////
- CRamFlx::CRamFlx(void)
- {
- // Set flags to default states
- m_sOpenForRead = FALSE;
- // Init CImage
- InitBuf(&m_imagePrev);
-
- // Clear file header
- ClearHeader();
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Destructor.
- //
- ///////////////////////////////////////////////////////////////////////////////
- CRamFlx::~CRamFlx()
- {
- // Close in case file was left open
- Close();
-
- // Clear header in case it's illegally accessed after we're destroyed
- ClearHeader();
- // Free any memory that needs freeing
- FreeBuf(&m_imagePrev);
-
- // Clear flags to default values (same reason we cleared header)
- m_sOpenForRead = FALSE;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Open an existing FLC/FLI file for reading. You can optionally get a copy of
- // the file header and can optionally have your buf memory allocated for you.
- // Returns 0 if successfull, non-zero otherwise.
- //
- // 10/20/94, Paul Lin, add code to reset error conditions on the fstream object
- // so that the next time this function is called, it doesn't fail
- //
- ///////////////////////////////////////////////////////////////////////////////
- short CRamFlx::Open(
- char* pszFileName, // Full path and filename of flic file
- FLX_FILE_HDR* pfilehdr, // Copy of header returned here if not NULL
- CImage* pimage) // Memory allocated within struct if not NULL
- {
- short sError = 0;
-
- // Close in case it was left open
- Close();
- // Clear file header. This is done primarily for the older FLI files
- // so that all fields, even those that aren't used by FLI files, will
- // be set to default values.
- ClearHeader();
- CNFile file;
- // Open file (only if it already exists -- do not create new file!)
- if (file.Open(pszFileName, "rb", ENDIAN_LITTLE) == 0)
- {
- // Read the header. Regardless of whether it's a FLC or FLI file,
- // the header is returned as if it was a FLC file.
- if (ReadHeader(&file) == 0)
- {
- // Restart animation
- Restart();
-
- // Default is to read both pixels and color data from flic
- m_sReadPixels = TRUE;
- m_sReadColors = TRUE;
- // Is this a flic with no delta compression?
- if (m_filehdr.sReserveA == FLX_RSP_NODELTA)
- {
- // Create list of pointers to frames in the flic(no delta compression)
- sError = CreateFramePointers();
- // Make sure the memory file pointer resets to the first frame
- Restart();
- // Flic has no delta compression
- m_sNoDelta = TRUE;
- }
- else
- {
- // Flic has delta compression
- m_sNoDelta = FALSE;
- }
- // If user doesn' specify a buffer, then we need to allocate buffers for the
- // previous frame and the previous color palette.
- if (pimage == NULL)
- {
- sError = AllocBuf(&m_imagePrev, (long)m_filehdr.sWidth, (long)m_filehdr.sHeight, 256);
- }
- }
- else
- sError = 1;
-
- // Close the file, the flic is loaded into the buffer
- file.Close();
- }
- else
- sError = 1;
-
- // Final check for file errors
- if ((sError == 0) && m_file.Error() == TRUE)
- sError = 1;
- // If pointer to header not NULL, then return copy of header there
- if ((sError == 0) && (pfilehdr != NULL))
- *pfilehdr = m_filehdr;
-
- // If pointer to buf not NULL, then allocate memory
- if ((sError == 0) && (pimage != NULL))
- sError = CreateBuf(pimage, (long)m_filehdr.sWidth, (long)m_filehdr.sHeight, 256);
-
- // If no errors, then file is finally marked "open for reading"
- if (sError == 0)
- m_sOpenForRead = TRUE;
-
-
- return sError;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Close the currently open file (if any). If a flic was being written to the
- // file, this will NOT properly complete the file. A separate function is
- // supplied for that, and it should be called before this function.
- // Returns 0 if successfull, non-zero otherwise.
- //
- ///////////////////////////////////////////////////////////////////////////////
- short CRamFlx::Close(CImage* pimage)
- {
- short sError = 1;
-
- // If file is open, try to close it.
- if (m_sOpenForRead)
- {
- // Clear flags
- m_sOpenForRead = FALSE;
-
- // Free any memory associated with image buf, flic buf, and frame pointers
- FreeBuf(&m_imagePrev);
- if (m_pucFlxBuf != NULL)
- {
- m_file.Close();
- free(m_pucFlxBuf);
- }
-
- if (m_sNoDelta == TRUE)
- {
- free(m_plFrames);
- }
-
- // Successfull
- sError = 0;
- }
- else
- sError = 0;
-
- // let's free the buffer passed in, if valid
- if (pimage != NULL)
- FreeBuf(pimage);
-
- return sError;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Get copy of flic file header (file must have been opened or created). When
- // creating a new file, certain fields are not valid until the file is closed.
- // Returns 0 if successfull, non-zero otherwise.
- //
- ///////////////////////////////////////////////////////////////////////////////
- short CRamFlx::GetHeader(FLX_FILE_HDR* pFileHdr)
- {
- short sError = 1;
-
- if (m_sOpenForRead)
- {
- // Copy our header struct to user's struct
- *pFileHdr = m_filehdr;
- sError = 0;
- }
-
- return sError;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Get the current frame number. When reading, this is the frame that was
- // last read. When writing, this is the frame that was last written. In both
- // cases, a value of 0 indicates that no frames have been read or written.
- // Otherwise, the number will be from 1 to n.
- //
- ///////////////////////////////////////////////////////////////////////////////
- short CRamFlx::GetFrameNum(void)
- {
- return m_sFrameNum;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Read the specified flic frame (1 to n, anything else is an error). The
- // time it takes to get the frame is proportional to the number of frames
- // between it and the last frame that was read. In simple mode, if the same
- // frame is requested more than once in a row, that frame is simply returned
- // each time. In non-simple mode, requesting the same frame again requires
- // us to restart the animation and work our way up to that frame again.
- // Returns 0 if successfull, non-zero otherwise.
- //
- ///////////////////////////////////////////////////////////////////////////////
- short CRamFlx::ReadFrame(
- short sFrameNum, // Frame number to be read
- CImage* pimageRead) // Buffer for frame being read
- {
- short sError = 0;
-
- if (m_sOpenForRead &&
- (sFrameNum >= 1) &&
- (sFrameNum <= m_filehdr.sNumFrames))
- {
- if (m_sNoDelta == TRUE)
- {
- // Flics with no delta compression
- if (sFrameNum != m_sFrameNum)
- {
- // Set position in buffer for frame
- m_file.Seek(m_plFrames[sFrameNum], SEEK_SET);
- // Decompress packets into image buffer
- sError = ReadNextFrame(pimageRead);
- // Set the frame number to the correct frame currently in image buffer
- m_sFrameNum = sFrameNum;
- }
- }
- else
- {
- if (sFrameNum != m_sFrameNum)
- {
- short sColorsModified = FALSE;
- short sPixelsModified = FALSE;
- // If specified frame is before (or equal to) the current frame,
- // we need to restart the animation.
- if (sFrameNum <= m_sFrameNum)
- {
- Restart();
- // When restarting, we should set these flags for lack
- // of a way of knowing for sure.
- sColorsModified = TRUE;
- sPixelsModified = TRUE;
- }
-
- // Go frame-by-frame to the requested frame
- while ((m_sFrameNum < sFrameNum) && (sError == 0))
- {
- sError = ReadNextFrame(pimageRead);
- // If the colors are modified . . .
- if (m_sColorsModified != FALSE)
- {
- // We need to store this info since the next
- // frame may set m_sColorsModified to FALSE.
- sColorsModified = TRUE;
- }
- // If the pixels are modified . . .
- if (m_sPixelsModified != FALSE)
- {
- // We need to store this info since the next
- // frame may set m_sPixelsModified to FALSE.
- sPixelsModified = TRUE;
- }
- }
- // If flags were set at all during the loop,
- // they need to be set now.
- m_sColorsModified = sColorsModified;
- m_sPixelsModified = sPixelsModified;
- }
- }
- }
- else
- sError = 1;
-
- return sError;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Read the next flic frame (if flic was just opened, this will read frame 1).
- // The "modified" flags are updated in the specified CImage.
- // Returns 0 if successfull, non-zero otherwise.
- //
- ///////////////////////////////////////////////////////////////////////////////
- short CRamFlx::ReadNextFrame(
- CImage* pimageRead) // Buffer for frame being read
- {
- short sError = 0;
- if (m_sOpenForRead)
- {
- if (pimageRead == NULL)
- {
- // Apply delta to our buf
- DoReadFrame(&m_imagePrev);
- }
- else
- {
- // Apply delta directly to user buf
- DoReadFrame(pimageRead);
- }
- }
- else
- sError = 1;
- return sError;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Create a CImage based on the specified width, height, and number of colors.
- // Returns 0 if successfull, non-zero otherwise.
- //
- ///////////////////////////////////////////////////////////////////////////////
- short CRamFlx::CreateBuf(CImage* pimage, long lWidth, long lHeight, short sColors)
- {
- InitBuf(pimage);
- return AllocBuf(pimage, lWidth, lHeight, sColors);
- }
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Destroy a CImage that was previously created using CreateBuf().
- // The CImage must not be used after this call!
- //
- ///////////////////////////////////////////////////////////////////////////////
- void CRamFlx::DestroyBuf(CImage* pimage)
- {
- FreeBuf(pimage);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // EOF
- ///////////////////////////////////////////////////////////////////////////////
|