From 465ee5fd866747fe7030d781f9ddebb11c6a840e Mon Sep 17 00:00:00 2001 From: hrydgard Date: Thu, 21 Aug 2008 23:28:07 +0000 Subject: Save states - more boring groundwork. Far from done. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@263 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Src/ChunkFile.cpp | 175 +++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 Source/Core/Common/Src/ChunkFile.cpp (limited to 'Source/Core/Common/Src/ChunkFile.cpp') diff --git a/Source/Core/Common/Src/ChunkFile.cpp b/Source/Core/Common/Src/ChunkFile.cpp new file mode 100644 index 0000000000..48f4498fef --- /dev/null +++ b/Source/Core/Common/Src/ChunkFile.cpp @@ -0,0 +1,175 @@ +// Copyright (C) 2003-2008 Dolphin Project. + +// 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, version 2.0. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "ChunkFile.h" + +#include + +// Not using file mapping, just bog standard fopen and friends. We trust them to be fast +// enough to not be the bottleneck. + +ChunkFile::ChunkFile(const char *filename, ChunkFileMode _mode) +{ + mode = _mode; + data = 0; + + didFail = false; + f = fopen(filename, mode == MODE_WRITE ? "wb" : "rb"); + if (!f) { + didFail = true; + return; + } + + fseek(f, 0, SEEK_END); + size = ftell(f); + eof = size; + + stack_ptr = 0; +} + +ChunkFile::~ChunkFile() +{ + if (f) + fclose(f); +} + +int ChunkFile::ReadInt() +{ + int x; + fread(&x, 4, 1, f); + return x; +} + +void ChunkFile::WriteInt(int x) +{ + fwrite(&x, 4, 1, f); +} + +bool ChunkFile::Do(void *ptr, int size) +{ + int sz; + switch (mode) { + case MODE_READ: + sz = ReadInt(); + if (sz != size) + return false; + fread(ptr, size, 1, f); + fseek(f, ((size + 3) & ~3) - size, SEEK_CUR); + break; + case MODE_WRITE: + WriteInt(size); + fwrite(ptr, size, 1, f); + fseek(f, ((size + 3) & ~3) - size, SEEK_CUR); + break; + case MODE_VERIFY: + sz = ReadInt(); + if (sz != size) + return false; + fseek(f, (size + 3) & ~3, SEEK_CUR); + break; + } + return true; +} + +//let's get into the business +bool ChunkFile::Descend(const char *cid) +{ + int id = *((int*)cid); + if (mode == MODE_READ) + { + bool found = false; + int startPos = ftell(f); + ChunkInfo temp = stack[stack_ptr]; + + //save information to restore after the next Ascend + stack[stack_ptr].parentStartLocation = startPos; + stack[stack_ptr].parentEOF = eof; + + int firstID = 0; + //let's search through children.. + while (ftell(f) < eof) + { + stack[stack_ptr].ID = ReadInt(); + if (firstID == 0) + firstID = stack[stack_ptr].ID|1; + stack[stack_ptr].length = ReadInt(); + stack[stack_ptr].startLocation = ftell(f); + if (stack[stack_ptr].ID == id) + { + found = true; + break; + } + else + { + fseek(f, stack[stack_ptr].length, SEEK_CUR); //try next block + } + } + + //if we found nothing, return false so the caller can skip this + if (!found) + { + stack[stack_ptr] = temp; + fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET); + return false; + } + + //descend into it + //pos was set inside the loop above + eof = stack[stack_ptr].startLocation + stack[stack_ptr].length; + stack_ptr++; + return true; + } + else + { + //write a chunk id, and prepare for filling in length later + WriteInt(id); + WriteInt(0); //will be filled in by Ascend + stack[stack_ptr].startLocation = ftell(f); + stack_ptr++; + return true; + } +} + +//let's ascend out +void ChunkFile::Ascend() +{ + if (mode == MODE_READ) + { + //ascend, and restore information + stack_ptr--; + fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET); + eof = stack[stack_ptr].parentEOF; + } + else + { + stack_ptr--; + //now fill in the written length automatically + int posNow = ftell(f); + fseek(f, stack[stack_ptr].startLocation - 4, SEEK_SET); + WriteInt(posNow - stack[stack_ptr].startLocation); + fseek(f, posNow, SEEK_SET); + } +} + +int ChunkFile::GetCurrentChunkSize() +{ + if (stack_ptr) + return stack[stack_ptr - 1].length; + else + return 0; +} -- cgit v1.2.3