summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Src/ChunkFile.cpp
diff options
context:
space:
mode:
authorhrydgard <hrydgard@gmail.com>2008-08-21 23:28:07 +0000
committerhrydgard <hrydgard@gmail.com>2008-08-21 23:28:07 +0000
commit465ee5fd866747fe7030d781f9ddebb11c6a840e (patch)
treefee7a2383bb14bd72e808206fec045872771aeea /Source/Core/Common/Src/ChunkFile.cpp
parent28edd4d31bb521ad350a96f5a14bc31bef27f2bf (diff)
Save states - more boring groundwork. Far from done.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@263 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/Common/Src/ChunkFile.cpp')
-rw-r--r--Source/Core/Common/Src/ChunkFile.cpp175
1 files changed, 175 insertions, 0 deletions
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 <stdio.h>
+
+// 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;
+}