// 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/ #ifdef _WIN32 #include #else #include #include #include #include #endif #include "Common.h" #include "MappedFile.h" namespace Common { class CMappedFile : public IMappedFile { public: CMappedFile(void); ~CMappedFile(void); bool Open(const char* _szFilename); bool IsOpen(void); void Close(void); u64 GetSize(void); u8* Lock(u64 _offset, u64 _size); void Unlock(u8* ptr); private: u64 size; typedef std::mapLockmap; Lockmap lockMap; #ifdef _WIN32 HANDLE hFile; HANDLE hFileMapping; #elif POSIX int fd; typedef std::mapSizemap; Sizemap sizeMap; #endif int granularity; }; CMappedFile::CMappedFile() { #ifdef _WIN32 hFile = INVALID_HANDLE_VALUE; SYSTEM_INFO info; GetSystemInfo(&info); granularity = (int)info.dwAllocationGranularity; #elif POSIX fd = -1; granularity = getpagesize(); //sysconf(_SC_PAGE_SIZE); #endif } CMappedFile::~CMappedFile() { Close(); } bool CMappedFile::Open(const char* filename) { Close(); #ifdef _WIN32 hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) { return(false); } hFileMapping = CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, NULL); if (hFileMapping == NULL) { CloseHandle(hFile); hFile = 0; return(false); } u32 high = 0; u32 low = GetFileSize(hFile, (LPDWORD)&high); size = (u64)low | ((u64)high << 32); #elif POSIX fd = open(filename, O_RDONLY); size = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); #endif return(true); } bool CMappedFile::IsOpen() { #ifdef _WIN32 return(hFile != INVALID_HANDLE_VALUE); #elif POSIX return(fd != -1); #endif } u64 CMappedFile::GetSize() { return(size); } void CMappedFile::Close() { #ifdef _WIN32 if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFileMapping); CloseHandle(hFile); lockMap.clear(); hFile = INVALID_HANDLE_VALUE; } #elif POSIX if (fd != -1) { lockMap.clear(); sizeMap.clear(); close(fd); } fd = -1; #endif } u8* CMappedFile::Lock(u64 offset, u64 _size) { #ifdef _WIN32 if (hFile != INVALID_HANDLE_VALUE) #elif POSIX if (fd != -1) #endif { u64 realOffset = offset & ~(granularity - 1); s64 difference = offset - realOffset; u64 fake_size = (difference + _size + granularity - 1) & ~(granularity - 1); #ifdef _WIN32 u8* realPtr = (u8*)MapViewOfFile(hFileMapping, FILE_MAP_READ, (DWORD)(realOffset >> 32), (DWORD)realOffset, (SIZE_T)(_size)); if (realPtr == NULL) { return(NULL); } #elif POSIX // TODO u8* realPtr = (u8*)mmap(0, fake_size, PROT_READ, MAP_PRIVATE, fd, (off_t)realOffset); if (!realPtr) { PanicAlert("Map Failed"); exit(0); } #endif u8* fakePtr = realPtr + difference; //add to map lockMap[fakePtr] = realPtr; #ifndef _WIN32 sizeMap[fakePtr] = _size + difference; #endif return(fakePtr); } else { return(0); } } void CMappedFile::Unlock(u8* ptr) { if (ptr != 0) { Lockmap::iterator iter = lockMap.find(ptr); if (iter != lockMap.end()) { #ifdef _WIN32 UnmapViewOfFile((*iter).second); #else munmap((*iter).second, sizeMap[ptr]); #endif lockMap.erase(iter); } else { PanicAlert("CMappedFile : Unlock failed"); } } } IMappedFile* IMappedFile::CreateMappedFileDEPRECATED(void) { return(new CMappedFile); } } // end of namespace Common