473 lines
27 KiB
C++
473 lines
27 KiB
C++
|
//
|
||
|
// Copyright 2020 Electronic Arts Inc.
|
||
|
//
|
||
|
// TiberianDawn.DLL and RedAlert.dll and corresponding source code 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.
|
||
|
|
||
|
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
|
||
|
// in the hope that it will be useful, but with permitted additional restrictions
|
||
|
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
|
||
|
// distributed with this program. You should have received a copy of the
|
||
|
// GNU General Public License along with permitted additional restrictions
|
||
|
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||
|
|
||
|
/* $Header: /CounterStrike/RAMFILE.CPP 1 3/03/97 10:25a Joe_bostic $ */
|
||
|
/***********************************************************************************************
|
||
|
*** 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 : Command & Conquer *
|
||
|
* *
|
||
|
* File Name : RAMFILE.CPP *
|
||
|
* *
|
||
|
* Programmer : Joe L. Bostic *
|
||
|
* *
|
||
|
* Start Date : 06/30/96 *
|
||
|
* *
|
||
|
* Last Update : July 3, 1996 [JLB] *
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* RAMFileClass::Close -- This will 'close' the ram file. *
|
||
|
* RAMFileClass::Create -- Effectively clears the buffer of data. *
|
||
|
* RAMFileClass::Delete -- Effectively clears the buffer of data. *
|
||
|
* RAMFileClass::Is_Available -- Determines if the "file" is available. *
|
||
|
* RAMFileClass::Is_Open -- Is the file open? *
|
||
|
* RAMFileClass::Open -- Opens a RAM based file for read or write. *
|
||
|
* RAMFileClass::Open -- Opens the RAM based file. *
|
||
|
* RAMFileClass::RAMFileClass -- Construct a RAM buffer based "file" object. *
|
||
|
* RAMFileClass::Read -- Read data from the file. *
|
||
|
* RAMFileClass::Seek -- Controls the ram file virtual read position. *
|
||
|
* RAMFileClass::Size -- Returns with the size of the ram file. *
|
||
|
* RAMFileClass::Write -- Copies data to the ram file. *
|
||
|
* RAMFileClass::~RAMFileClass -- Destructor for the RAM file class. *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
#include "FUNCTION.H"
|
||
|
#include "ramfile.h"
|
||
|
#include <string.h>
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::RAMFileClass -- Construct a RAM buffer based "file" object. *
|
||
|
* *
|
||
|
* This routine will construct a "file" object that actually is just a front end processor *
|
||
|
* for a buffer. Access to the buffer will appear as if it was accessing a file. This *
|
||
|
* is different from the caching ability of the buffered file class in that this file *
|
||
|
* class has no real file counterpart. Typical use of this is for algorithms that were *
|
||
|
* originally designed for file processing, but are now desired to work with a buffer. *
|
||
|
* *
|
||
|
* INPUT: buffer -- Pointer to the buffer to use for this file. The buffer will already *
|
||
|
* contain data if the file is opened for READ. It will be considered *
|
||
|
* a scratch buffer if opened for WRITE. If the buffer pointer is NULL *
|
||
|
* but the length parameter is not, then a buffer will be allocated *
|
||
|
* of the specified length. This case is only useful for opening the *
|
||
|
* file for WRITE. *
|
||
|
* *
|
||
|
* length -- The length of the buffer submitted to this routine. *
|
||
|
* *
|
||
|
* OUTPUT: none *
|
||
|
* *
|
||
|
* WARNINGS: none *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
RAMFileClass::RAMFileClass(void * buffer, int len) :
|
||
|
Buffer((char *)buffer),
|
||
|
MaxLength(len),
|
||
|
Length(len),
|
||
|
Offset(0),
|
||
|
Access(READ),
|
||
|
IsOpen(false),
|
||
|
IsAllocated(false)
|
||
|
{
|
||
|
if (buffer == NULL && len > 0) {
|
||
|
Buffer = new char[len];
|
||
|
IsAllocated = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::~RAMFileClass -- Destructor for the RAM file class. *
|
||
|
* *
|
||
|
* The destructor will deallocate any buffer that it allocated. Otherwise it does nothing. *
|
||
|
* *
|
||
|
* INPUT: none *
|
||
|
* *
|
||
|
* OUTPUT: none *
|
||
|
* *
|
||
|
* WARNINGS: none *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
RAMFileClass::~RAMFileClass(void)
|
||
|
{
|
||
|
Close();
|
||
|
if (IsAllocated) {
|
||
|
delete [] Buffer;
|
||
|
Buffer = NULL;
|
||
|
IsAllocated = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::Create -- Effectively clears the buffer of data. *
|
||
|
* *
|
||
|
* This routine "clears" the buffer of data. It only makes the buffer appear empty by *
|
||
|
* resetting the internal length to zero. *
|
||
|
* *
|
||
|
* INPUT: none *
|
||
|
* *
|
||
|
* OUTPUT: Was the file reset in this fashion? *
|
||
|
* *
|
||
|
* WARNINGS: If the file was open, then resetting by this routine is not allowed. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
int RAMFileClass::Create(void)
|
||
|
{
|
||
|
if (!Is_Open()) {
|
||
|
Length = 0;
|
||
|
return(true);
|
||
|
}
|
||
|
return(false);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::Delete -- Effectively clears the buffer of data. *
|
||
|
* *
|
||
|
* This routine "clears" the buffer of data. It only makes the buffer appear empty by *
|
||
|
* resetting the internal length to zero. *
|
||
|
* *
|
||
|
* INPUT: none *
|
||
|
* *
|
||
|
* OUTPUT: Was the file reset in this fashion? *
|
||
|
* *
|
||
|
* WARNINGS: If the file was open, then resetting by this routine is not allowed. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
int RAMFileClass::Delete(void)
|
||
|
{
|
||
|
if (!Is_Open()) {
|
||
|
Length = 0;
|
||
|
return(true);
|
||
|
}
|
||
|
return(false);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::Is_Available -- Determines if the "file" is available. *
|
||
|
* *
|
||
|
* RAM files are always available. *
|
||
|
* *
|
||
|
* INPUT: none *
|
||
|
* *
|
||
|
* OUTPUT: TRUE *
|
||
|
* *
|
||
|
* WARNINGS: none *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
int RAMFileClass::Is_Available(int )
|
||
|
{
|
||
|
return(true);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::Is_Open -- Is the file open? *
|
||
|
* *
|
||
|
* This answers the question whether the file is open or not. *
|
||
|
* *
|
||
|
* INPUT: none *
|
||
|
* *
|
||
|
* OUTPUT: bool; Is the file open? *
|
||
|
* *
|
||
|
* WARNINGS: none *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
int RAMFileClass::Is_Open(void) const
|
||
|
{
|
||
|
return(IsOpen);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::Open -- Opens a RAM based file for read or write. *
|
||
|
* *
|
||
|
* This routine will open the ram file. The name is meaningless so that parameter is *
|
||
|
* ignored. If the access mode is for write, then the pseudo-file can be written until the *
|
||
|
* buffer is full. If the file is opened for read, then the buffer is presumed to be full *
|
||
|
* of the data to be read. *
|
||
|
* *
|
||
|
* INPUT: name -- ignored. *
|
||
|
* *
|
||
|
* access-- The access method to use for the data buffer -- either READ or WRITE. *
|
||
|
* *
|
||
|
* OUTPUT: bool; Was the open successful? *
|
||
|
* *
|
||
|
* WARNINGS: none *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
int RAMFileClass::Open(char const * , int access)
|
||
|
{
|
||
|
return(Open(access));
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::Open -- Opens the RAM based file. *
|
||
|
* *
|
||
|
* This will open the ram based file for read or write. If the file is opened for write, *
|
||
|
* the the 'file' can be written up to the limit of the buffer's size. If the file is *
|
||
|
* opened for read, then the buffer is presumed to hold the data to be read. *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
int RAMFileClass::Open(int access)
|
||
|
{
|
||
|
if (Buffer == NULL || Is_Open()) {
|
||
|
return(false);
|
||
|
}
|
||
|
|
||
|
Offset = 0;
|
||
|
Access = access;
|
||
|
IsOpen = true;
|
||
|
|
||
|
switch (access) {
|
||
|
default:
|
||
|
case READ:
|
||
|
break;
|
||
|
|
||
|
case WRITE:
|
||
|
Length = 0;
|
||
|
break;
|
||
|
|
||
|
case READ|WRITE:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return(Is_Open());
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::Read -- Read data from the file. *
|
||
|
* *
|
||
|
* Use this routine just like a normal file read. It will copy the bytes from the ram *
|
||
|
* buffer to the destination specified. When the ram buffer is exhausted, less bytes than *
|
||
|
* requested will be read. *
|
||
|
* *
|
||
|
* INPUT: buffer -- Pointer to the buffer to store the data to. *
|
||
|
* *
|
||
|
* size -- The number of bytes to 'read' into the specified buffer. *
|
||
|
* *
|
||
|
* OUTPUT: Returns with the number of bytes copied to the destination buffer. If the number *
|
||
|
* of bytes returned is less than requested, then this indicates that the source *
|
||
|
* buffer is exhausted. *
|
||
|
* *
|
||
|
* WARNINGS: The read function only applies to ram 'files' opened for read access. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
long RAMFileClass::Read(void * buffer, long size)
|
||
|
{
|
||
|
if (Buffer == NULL || buffer == NULL || size == 0) {
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
bool hasopened = false;
|
||
|
if (!Is_Open()) {
|
||
|
Open(READ);
|
||
|
hasopened = true;
|
||
|
} else {
|
||
|
if ((Access & READ) == 0) {
|
||
|
return(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int tocopy = (size < (Length-Offset)) ? size : (Length-Offset);
|
||
|
memmove(buffer, &Buffer[Offset], tocopy);
|
||
|
Offset += tocopy;
|
||
|
|
||
|
if (hasopened) {
|
||
|
Close();
|
||
|
}
|
||
|
|
||
|
return(tocopy);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::Seek -- Controls the ram file virtual read position. *
|
||
|
* *
|
||
|
* This routine will move the read/write position of the ram file to the location specified *
|
||
|
* by the offset and direction parameters. It functions similarly to the regular file *
|
||
|
* seek method. *
|
||
|
* *
|
||
|
* INPUT: pos -- The signed offset from the home position specified by the "dir" *
|
||
|
* parameter. *
|
||
|
* *
|
||
|
* dir -- The home position to base the position offset on. This will either be *
|
||
|
* the start of the file, the end of the file, or the current read/write *
|
||
|
* position. *
|
||
|
* *
|
||
|
* OUTPUT: Returns with the new file position. *
|
||
|
* *
|
||
|
* WARNINGS: none *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
long RAMFileClass::Seek(long pos, int dir)
|
||
|
{
|
||
|
if (Buffer == NULL || !Is_Open()) {
|
||
|
return(Offset);
|
||
|
}
|
||
|
|
||
|
int maxoffset = Length;
|
||
|
if ((Access & WRITE) != 0) {
|
||
|
maxoffset = MaxLength;
|
||
|
}
|
||
|
|
||
|
switch (dir) {
|
||
|
case SEEK_CUR:
|
||
|
Offset += pos;
|
||
|
break;
|
||
|
|
||
|
case SEEK_SET:
|
||
|
Offset = 0 + pos;
|
||
|
break;
|
||
|
|
||
|
case SEEK_END:
|
||
|
Offset = maxoffset + pos;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (Offset < 0) Offset = 0;
|
||
|
if (Offset > maxoffset) Offset = maxoffset;
|
||
|
|
||
|
if (Offset > Length) {
|
||
|
Length = Offset;
|
||
|
}
|
||
|
|
||
|
return(Offset);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::Size -- Returns with the size of the ram file. *
|
||
|
* *
|
||
|
* This will return the size of the 'real' data in the ram file. The real data is either *
|
||
|
* the entire buffer, if opened for READ, or just the written data if opened for WRITE. *
|
||
|
* *
|
||
|
* INPUT: none *
|
||
|
* *
|
||
|
* OUTPUT: Returns with the number of bytes that the ram file system considers to be valid *
|
||
|
* data of the 'file'. *
|
||
|
* *
|
||
|
* WARNINGS: none *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
long RAMFileClass::Size(void)
|
||
|
{
|
||
|
return(Length);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::Write -- Copies data to the ram file. *
|
||
|
* *
|
||
|
* This function similarly to the regular write operation supported for files. It copies *
|
||
|
* the data specified to the current write position in the ram file. *
|
||
|
* *
|
||
|
* INPUT: buffer -- Pointer to the data to be written. *
|
||
|
* *
|
||
|
* size -- The number of bytes to write to the file. *
|
||
|
* *
|
||
|
* OUTPUT: Returns with the actual number of bytes written. This will be less than requested *
|
||
|
* if the buffer is exhausted of space prematurely. *
|
||
|
* *
|
||
|
* WARNINGS: none *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
long RAMFileClass::Write(void const * buffer, long size)
|
||
|
{
|
||
|
if (Buffer == NULL || buffer == NULL || size == 0) {
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
bool hasopened = false;
|
||
|
if (!Is_Open()) {
|
||
|
Open(WRITE);
|
||
|
hasopened = true;
|
||
|
} else {
|
||
|
if ((Access & WRITE) == 0) {
|
||
|
return(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int maxwrite = MaxLength - Offset;
|
||
|
int towrite = (size < maxwrite) ? size : maxwrite;
|
||
|
memmove(&Buffer[Offset], buffer, towrite);
|
||
|
Offset += towrite;
|
||
|
|
||
|
if (Offset > Length) {
|
||
|
Length = Offset;
|
||
|
}
|
||
|
|
||
|
if (hasopened) {
|
||
|
Close();
|
||
|
}
|
||
|
|
||
|
return(towrite);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* RAMFileClass::Close -- This will 'close' the ram file. *
|
||
|
* *
|
||
|
* Closing a ram file actually does nothing but record that it is now closed. *
|
||
|
* *
|
||
|
* INPUT: none *
|
||
|
* *
|
||
|
* OUTPUT: none *
|
||
|
* *
|
||
|
* WARNINGS: none *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 07/03/1996 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
void RAMFileClass::Close(void)
|
||
|
{
|
||
|
IsOpen = false;
|
||
|
}
|