mirror of
				https://github.com/dolphin-emu/dolphin.git
				synced 2025-10-25 17:39:09 +00:00 
			
		
		
		
	still experimental, not totally optimized but must bring a nice speed up please test for regressions an error. an please Linux people fix scons :) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6149 8ced0084-cf51-0410-be5f-012b33b47a6e
		
			
				
	
	
		
			172 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (C) 2003 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 "LinearDiskCache.h"
 | |
| 
 | |
| static const char ID[4] = {'D', 'C', 'A', 'C'};
 | |
| 
 | |
| // Update this to the current SVN revision every time you change shader generation code.
 | |
| // We don't automatically get this from SVN_REV because that would mean regenerating the
 | |
| // shader cache for every revision, graphics-related or not, which is simply annoying.
 | |
| const int version = 6148;
 | |
| 
 | |
| LinearDiskCache::LinearDiskCache() 
 | |
| 	: file_(NULL), num_entries_(0) {
 | |
| }
 | |
| 
 | |
| void LinearDiskCache::WriteHeader() {
 | |
| 	fwrite(ID, 4, 1, file_);
 | |
| 	fwrite(&version, 4, 1, file_);
 | |
| }
 | |
| 
 | |
| bool LinearDiskCache::ValidateHeader() {
 | |
| 	char header_id[4];
 | |
| 	int header_version;
 | |
| 	fread(&header_id, 4, 1, file_);
 | |
| 	fread(&header_version, 4, 1, file_);
 | |
| 	if (memcmp(header_id, ID, 4) != 0)
 | |
| 		return false;
 | |
| 	if (header_version != version)
 | |
| 		return false;
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| int LinearDiskCache::OpenAndRead(const char *filename, LinearDiskCacheReader *reader) {
 | |
| 	if (file_)
 | |
| 	{
 | |
| 		ERROR_LOG(VIDEO, "LinearDiskCache trying to open an alredy opened cache");
 | |
| 		return 0;
 | |
| 	}
 | |
| 	int items_read_count = 0;
 | |
| 	file_ = fopen(filename, "rb");
 | |
| 	int file_size = 0;
 | |
| 	if (file_) {
 | |
| 		fseek(file_, 0, SEEK_END);
 | |
| 		file_size = (int)ftell(file_);
 | |
| 	}
 | |
| 
 | |
| 	bool file_corrupt = false;
 | |
| 	if (file_size == 0) {
 | |
| 		if (file_)
 | |
| 			fclose(file_);
 | |
| 		// Reopen for writing.
 | |
| 		file_ = fopen(filename, "wb");
 | |
| 		// Cache empty, let's initialize a header.
 | |
| 		WriteHeader();
 | |
| 		num_entries_ = 0;
 | |
| 	} else {
 | |
| 		// file_ must be != 0 here.
 | |
| 		// Back to the start we go.
 | |
| 		fseek(file_, 0, SEEK_SET);
 | |
| 		// Check that the file is valid
 | |
| 		if (!ValidateHeader()) {
 | |
| 			// Not valid - delete the file and start over.
 | |
| 			fclose(file_);
 | |
| 			unlink(filename);
 | |
| 
 | |
| 			// PanicAlert("LinearDiskCache file header broken.");
 | |
| 
 | |
| 			file_ = fopen(filename, "wb");
 | |
| 			WriteHeader();
 | |
| 			num_entries_ = 0;
 | |
| 		} else {
 | |
| 			// Valid - blow through it.
 | |
| 			// We're past the header already thanks to ValidateHeader.
 | |
| 			while (!feof(file_)) {
 | |
| 				int key_size, value_size;
 | |
| 				size_t key_size_size = fread(&key_size, 1, sizeof(key_size), file_);
 | |
| 				size_t value_size_size = fread(&value_size, 1, sizeof(value_size), file_);
 | |
| 				if (key_size_size == 0 && value_size_size == 0) {
 | |
| 					// I guess feof isn't doing it's job - we're at the end.
 | |
| 					break;
 | |
| 				}
 | |
| 				if (key_size <= 0 || value_size < 0 || key_size_size != 4 || value_size_size != 4) {
 | |
| 					// PanicAlert("Disk cache file %s corrupted/truncated! ks: %i vs %i kss %i vss %i", filename,
 | |
| 					//	key_size, value_size, key_size_size, value_size_size);
 | |
| 					file_corrupt = true;
 | |
| 					break;
 | |
| 				}
 | |
| 				u8 *key = new u8[key_size];
 | |
| 				u8 *value = new u8[value_size];
 | |
| 				int actual_key_size = (int)fread(key, 1, key_size, file_);
 | |
| 				int actual_value_size = (int)fread(value, 1, value_size, file_);
 | |
| 				if (actual_key_size != key_size || actual_value_size != value_size) {
 | |
| 					// PanicAlert("Disk cache file %s corrupted/truncated! ks: %i  actual ks: %i   vs: %i  actual vs: %i", filename,
 | |
| 					// 	key_size, actual_key_size, value_size, actual_value_size);
 | |
| 					file_corrupt = true;
 | |
| 				} else {
 | |
| 					reader->Read(key, key_size, value, value_size);
 | |
| 					items_read_count++;
 | |
| 				}
 | |
| 				delete [] key;
 | |
| 				delete [] value;
 | |
| 			}
 | |
| 			fclose(file_);
 | |
| 			// Done reading.
 | |
| 
 | |
| 			// Reopen file for append.
 | |
| 			// At this point, ftell() will be at the end of the file,
 | |
| 			// which happens to be exactly what we want.
 | |
| 			file_ = fopen(filename, "ab");
 | |
| 			fseek(file_, 0, SEEK_END);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (file_corrupt) {
 | |
| 		// Restore sanity, start over.
 | |
| 		fclose(file_);
 | |
| 		unlink(filename);
 | |
| 
 | |
| 		file_ = fopen(filename, "wb+");
 | |
| 		WriteHeader();
 | |
| 	}
 | |
| 
 | |
| 	return items_read_count;
 | |
| }
 | |
| 
 | |
| void LinearDiskCache::Append(
 | |
| 	const u8 *key, int key_size, const u8 *value, int value_size) {
 | |
| 	// Should do a check that we don't already have "key"?
 | |
| 	fwrite(&key_size, 1, sizeof(key_size), file_);
 | |
| 	fwrite(&value_size, 1, sizeof(value_size), file_);
 | |
| 	fwrite(key, 1, key_size, file_);
 | |
| 	fwrite(value, 1, value_size, file_);
 | |
| }
 | |
| 
 | |
| void LinearDiskCache::Sync() {
 | |
| 	if (file_)
 | |
| 	{
 | |
| 		fflush(file_);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		ERROR_LOG(VIDEO, "LinearDiskCache trying to sync closed cache");
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void LinearDiskCache::Close() {
 | |
| 	if (file_)
 | |
| 	{
 | |
| 		fclose(file_);
 | |
| 		file_ = 0;
 | |
| 		num_entries_ = 0;
 | |
| 	}
 | |
| 	else 
 | |
| 	{
 | |
| 		ERROR_LOG(VIDEO, "LinearDiskCache trying to close an alredy closed cache");
 | |
| 	}
 | |
| }
 |