4
* This file is part of FreeRCT.
5
* FreeRCT 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, version 2.
6
* FreeRCT 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.
7
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FreeRCT. If not, see <http://www.gnu.org/licenses/>.
10
/** @file file_writing.cpp File write code. */
12
#include "../../src/stdafx.h"
13
#include "file_writing.h"
16
FileBlock::FileBlock()
22
FileBlock::~FileBlock()
28
* Setup storing of data to the file block.
29
* Supply name of the block, version number, and expected data length (without the 12 byte header).
30
* After setup, use #SaveUInt8, #SaveUInt16, #SaveUInt32, and #SaveBytes to store the data in the block.
31
* Afterwards, use #CheckEndSave to verify the amount of actually written data matches with the expected length.
32
* @param blk_name Name of the block (a 4 character text string).
33
* @param version Version of the block.
34
* @param data_length Length of the data part (that is, excluding the header).
36
void FileBlock::StartSave(const char *blk_name, int version, int data_length)
38
this->length = data_length + 12; // Add length of the header.
40
this->data = (uint8 *)malloc(this->length);
43
assert(strlen(blk_name) == 4);
44
this->SaveBytes((uint8 *)blk_name, 4);
45
this->SaveUInt32(version);
46
this->SaveUInt32(data_length);
50
* Save a 8 bit unsigned value into the file block.
51
* @param d Value to write.
53
void FileBlock::SaveUInt8(uint8 d)
55
assert(this->save_index < this->length);
56
this->data[this->save_index] = d;
61
* Save a 8 bit signed value into the file block.
62
* @param d Value to write.
64
void FileBlock::SaveInt8(int8 d)
70
* Save a 16 bit unsigned value into the file block.
71
* @param d Value to write.
73
void FileBlock::SaveUInt16(uint16 d)
76
this->SaveUInt8(d >> 8);
79
* Save a 16 bit signed value into the file block.
80
* @param d Value to write.
82
void FileBlock::SaveInt16(uint16 d)
85
this->SaveUInt8(d >> 8);
89
* Save a 32 bit unsigned value into the file block.
90
* @param d Value to write.
92
void FileBlock::SaveUInt32(uint32 d)
95
this->SaveUInt16(d >> 16);
99
* Save a sequence of bytes in the file block.
100
* @param data Start address of the data.
101
* @param size Length of the data.
103
void FileBlock::SaveBytes(uint8 *data, int size)
106
this->SaveUInt8(*data);
112
/** Check that all data has been written. */
113
void FileBlock::CheckEndSave()
115
assert(this->save_index == this->length);
119
* Write the file block to the output.
120
* @param fp File handle to write to.
122
void FileBlock::Write(FILE *fp)
124
if (this->length == 0) return;
126
if ((int)fwrite(this->data, 1, this->length, fp) != this->length) {
127
fprintf(stderr, "Failed to write RCD block\n");
133
* Check whether two file blocks are identical.
134
* @param fb1 First block to compare.
135
* @param fb2 Second block to compare.
136
* @return Whether both blocks are the same.
138
bool operator==(const FileBlock &fb1, const FileBlock &fb2)
140
if (fb1.length != fb2.length) return false;
141
if (fb1.length == 0) return true;
142
return memcmp(fb1.data, fb2.data, fb1.length) == 0;
145
FileWriter::FileWriter()
149
FileWriter::~FileWriter()
151
for (FileBlockPtrList::iterator iter = this->blocks.begin(); iter != this->blocks.end(); iter++) {
157
* Add a block to the file.
158
* @param blk Block to add.
159
* @return Block index number where the block is stored in the file.
161
int FileWriter::AddBlock(FileBlock *blk)
164
FileBlockPtrList::iterator iter = this->blocks.begin();
165
while (iter != this->blocks.end()) {
166
if (*(*iter) == *blk) { // Block already added, just return the old block number.
173
this->blocks.push_back(blk);
178
* Write all blocks of the RCD file to the file.
179
* @param fname Filename to create.
181
void FileWriter::WriteFile(const char *fname)
183
FILE *fp = fopen(fname, "wb");
185
fprintf(stderr, "Failed to open \"%s\" for writing.", fname);
189
static const uint8 file_header[8] = {'R', 'C', 'D', 'F', 1, 0, 0, 0};
190
if (fwrite(file_header, 1, 8, fp) != 8) {
191
fprintf(stderr, "Failed to write the RCD file header of \"%s\".", fname);
195
for (FileBlockPtrList::iterator iter = this->blocks.begin(); iter != this->blocks.end(); iter++) {