⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mem_win32.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 *
 * 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * $Id: mem_win32.c 430 2005-12-28 14:50:08Z picard $
 *
 * The Core Pocket Media Player
 * Copyright (c) 2004-2005 Gabor Kovacs
 *
 ****************************************************************************/

#include "../common.h"

#if defined(TARGET_WIN32) || defined(TARGET_WINCE)

//#define FIND		0xCF9390
//#define SAFEGUARD	32

#define BLOCKGROUP	8

#ifndef STRICT
#define STRICT
#endif
#include <windows.h>

#if defined(_MSC_VER) && !defined(TARGET_WINCE)
#include <crtdbg.h>
#endif

#if defined(TARGET_WINCE)

#define MAXPHY		16

#define CACHE_SYNC_INSTRUCTIONS		2
#define LOCKFLAG_WRITE				1
#define TBL_CACHE	0x08
#define TBL_BUFFER	0x04

typedef struct phymem
{
	char* Virt;
	uint32_t Phy; 
	uint32_t Length;
	uint32_t RefCount;
	phymemblock* Blocks;
	int BlockCount;

} phymem;

static phymem PhyMem[MAXPHY] = { 0 };

static BOOL (WINAPI* FuncVirtualSetAttributes)(LPVOID lpvAddress, DWORD cbSize, DWORD dwNewFlags, DWORD dwMask, LPDWORD lpdwOldFlags) = NULL;
static BOOL (WINAPI* FuncFreePhysMem)(LPVOID) = NULL;
static BOOL (WINAPI* FuncLockPages)(LPVOID lpvAddress,DWORD cbSize,PDWORD pPFNs,int fOptions) = NULL;
static BOOL (WINAPI* FuncUnlockPages)(LPVOID lpvAddress,DWORD cbSize) = NULL;
static LPVOID (WINAPI* FuncAllocPhysMem)(DWORD cbSize, DWORD fdwProtect, DWORD dwAlignmentMask, DWORD dwFlags, PULONG pPhysicalAddress) = NULL;
static void (WINAPI* FuncCacheSync)(DWORD) = NULL;
static BOOL (WINAPI* FuncVirtualCopy)(LPVOID, LPVOID, DWORD, DWORD) = NULL;

static HMODULE CoreDLL = NULL;

#endif

typedef struct blockgroup
{
	block Block;
	int Mask;
	int Unused; //align to 16bytes

} blockgroup;

static int PageSize = 4096;
static array BlockGroup = { NULL };

#ifndef NDEBUG
static int BlockAllocated = 0;
#endif

void* PhyMemAlloc(int Length,phymemblock* Blocks,int* BlockCount)
{
	void* p = NULL;

#if defined(TARGET_WINCE)
	if (*BlockCount>=1)
	{
		int n,Pos;
		int Count = 0;

		Length = (Length + PageSize-1) & ~(PageSize-1);

		if (FuncAllocPhysMem && FuncFreePhysMem && FuncVirtualCopy)
		{
			// try allocate in one continous block
			Blocks[0].Private = FuncAllocPhysMem(Length,PAGE_READWRITE,PageSize-1,0,&Blocks[0].Addr);
			if (Blocks[0].Private)
			{
				Blocks[0].Length = Length;
				Count = 1;
			}

			/* not worth it. allocphysmem is buggy anyway. won't be able to allocate per one pagesize

			if (!Count && *BlockCount>1)
			{
				int Left = Length;
				int BlockMax;
				int BlockSize = (Left+PageSize-1) & ~(PageSize-1);

				// allocate in separate blocks
			
				while (Count < *BlockCount && BlockSize > 0)
				{
					Blocks[Count].Private = FuncAllocPhysMem(BlockSize,PAGE_READWRITE,PageSize-1,0,&Blocks[Count].Addr);
					if (Blocks[Count].Private)
					{
						Blocks[Count].Length = BlockSize;
						++Count;
						Left -= BlockSize;
						BlockMax = (Left+PageSize-1) & ~(PageSize-1);
						if (BlockSize > BlockMax)
							BlockSize = BlockMax;
					}
					else
					if (BlockSize > PageSize*8)
						BlockSize = (BlockSize/2+PageSize-1) & ~(PageSize-1);
					else
						BlockSize -= PageSize;
				}

				if (Left>0)
				{
					for (n=0;n<Count;++n)
						FuncFreePhysMem(Blocks[n].Private);
					Count = 0;
				}
			}
			*/

			if (Count)
			{
				p = VirtualAlloc(NULL,Length,MEM_RESERVE,PAGE_READWRITE);

				if (p)
				{
					Pos = 0;
					for (n=0;n<Count;++n)
					{
						if (!FuncVirtualCopy((char*)p+Pos,(LPVOID)(Blocks[n].Addr >> 8),Blocks[n].Length, PAGE_READWRITE | PAGE_PHYSICAL))
							break;
						Pos += Blocks[n].Length;
					}
				
					if (n!=Count)
					{
						VirtualFree(p,0,MEM_RELEASE);
						p = NULL;
					}
				}

				if (!p)
				{
					for (n=0;n<Count;++n)
						FuncFreePhysMem(Blocks[n].Private);
					Count = 0;
				}
			}
		}
		
		if (!p && FuncLockPages && FuncUnlockPages)
		{
			do
			{
				p = VirtualAlloc(NULL,Length,MEM_COMMIT,PAGE_READWRITE);
			}
			while (!p && Length && NodeHibernate());

			if (p)
			{
				int Pages = Length / PageSize;
				DWORD* PFN = (DWORD*) alloca(sizeof(DWORD)*Pages);

				if (FuncLockPages(p,Length,PFN,LOCKFLAG_WRITE))
				{
					DWORD Last = (DWORD)-1;
					for (n=0;n<Pages;++n)
					{
						if (PFN[n] != Last)
						{
							if (Count >= *BlockCount)
							{
								Count = 0;
								break;
							}

							Blocks[Count].Addr = PFN[n];
							Blocks[Count].Length = PageSize;
							Blocks[Count].Private = NULL;
							++Count;
						}
						else
							Blocks[Count-1].Length += PageSize;

						Last = PFN[n] + PageSize;
					}

					if (!Count)
						FuncUnlockPages(p,Length);
				}
				
				if (!Count)
				{
					VirtualFree(p,0,MEM_RELEASE);
					p = NULL;
				}
			}
		}

#ifdef ARM
		if (p && FuncVirtualSetAttributes && (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_XSCALE))
			FuncVirtualSetAttributes(p,Length,TBL_CACHE|TBL_BUFFER,TBL_CACHE|TBL_BUFFER,NULL);
#endif

		*BlockCount = Count;
	}
#endif

	return p;
}

void PhyMemFree(void* p,phymemblock* Blocks,int BlockCount)
{
#if defined(TARGET_WINCE)
	if (p)
	{
		int n;

		if (FuncLockPages && FuncUnlockPages)
		{
			int Size = 0;
			for (n=0;n<BlockCount;++n)
			{
				if (Blocks[n].Private)
					break;
				Size += Blocks[n].Length;
			}
			if (Size)
				FuncUnlockPages(p,Size);
		}

		VirtualFree(p,0,MEM_RELEASE);

		if (FuncAllocPhysMem && FuncFreePhysMem && FuncVirtualCopy)
			for (n=0;n<BlockCount;++n)
				if (Blocks[n].Private)
					FuncFreePhysMem(Blocks[n].Private);
	}
#endif
}

#if defined(TARGET_WINCE)
static void SafeVirtualFree(PVOID p,DWORD Size)
{
#ifdef ARM
	// O2 Atom destroys video memory and LCD descriptors unless this code... (WM5)
	if (FuncVirtualSetAttributes)
		FuncVirtualSetAttributes(p,Size,0,0xFFFFF000,NULL);
#endif
	VirtualFree(p,0,MEM_RELEASE);
}
#endif

void* PhyMemBeginEx(phymemblock* Blocks,int BlockCount,bool_t Cached)
{
#if defined(TARGET_WINCE)
	if (FuncVirtualCopy && Blocks && BlockCount)
	{
		int n;
		int Mode;
		phymem* p;
		for (p=PhyMem;p!=PhyMem+MAXPHY;++p)
			if (p->BlockCount == BlockCount && p->Length == Blocks[0].Length && p->Phy == Blocks[0].Addr)
			{
				for (n=1;n<BlockCount;++n)
					if (p->Blocks[n].Addr != Blocks[n].Addr || p->Blocks[n].Length != Blocks[n].Length)
						break;

				if (n==BlockCount)
				{
					++p->RefCount;
					return p->Virt;
				}
			}

		if (BlockCount==1)
			return PhyMemBegin(Blocks[0].Addr,Blocks[0].Length,Cached);

		for (Mode=0;Mode<2;++Mode)
			for (p=PhyMem;p!=PhyMem+MAXPHY;++p)
			{
				if (Mode && !p->RefCount && p->Length)
				{
					free(p->Blocks);
					SafeVirtualFree(p->Virt,p->Length);
					memset(p,0,sizeof(phymem));
				}

				if (!p->Length)
				{
					p->Blocks = (phymemblock*) malloc(sizeof(phymemblock)*BlockCount);
					if (p->Blocks)
					{
						int Size = 0;
						for (n=0;n<BlockCount;++n)
							Size += Blocks[n].Length;

						p->BlockCount = BlockCount;
						p->Virt = (char*) VirtualAlloc(0, Size, MEM_RESERVE, PAGE_NOACCESS);
						if (p->Virt)
						{
							int Mode = PAGE_READWRITE | PAGE_PHYSICAL;
							char* Virt = p->Virt;

							if (!Cached)
								Mode |= PAGE_NOCACHE;

							for (n=0;n<BlockCount;++n)
							{
								if (!FuncVirtualCopy(Virt,(LPVOID)(Blocks[n].Addr >> 8), Blocks[n].Length,Mode))
									break;

								p->Blocks[n].Addr = Blocks[n].Addr;
								p->Blocks[n].Length = Blocks[n].Length;
								Virt += Blocks[n].Length;
							}

							if (n==BlockCount)
							{
								p->RefCount = 1;
								p->Phy = Blocks[0].Addr;
								p->Length = Blocks[0].Length;
								p->BlockCount = BlockCount;

#ifdef ARM
								if (Cached && FuncVirtualSetAttributes && (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_XSCALE))
									FuncVirtualSetAttributes(p->Virt,Size,TBL_CACHE|TBL_BUFFER,TBL_CACHE|TBL_BUFFER,NULL);
#endif
								return p->Virt;
							}

							VirtualFree(p->Virt,0,MEM_RELEASE);
						}
						free(p->Blocks);
					}

					memset(p,0,sizeof(phymem));
					return NULL;
				}
			}
	}	
#endif
	return NULL;
}

void* PhyMemBegin(uint32_t Phy,uint32_t Length,bool_t Cached)
{
#if defined(TARGET_WINCE)
	if (FuncVirtualCopy && Phy && Length)
	{
		int Mode;
		phymem* p;
		for (p=PhyMem;p!=PhyMem+MAXPHY;++p)
			if (p->Phy <= Phy && p->Phy+p->Length >= Phy+Length)
			{
				++p->RefCount;
				return p->Virt + (Phy - p->Phy);
			}

		for (Mode=0;Mode<2;++Mode)
			for (p=PhyMem;p!=PhyMem+MAXPHY;++p)
			{
				if (Mode && !p->RefCount && p->Length)
				{
					free(p->Blocks);
					SafeVirtualFree(p->Virt,p->Length);
					memset(p,0,sizeof(phymem));
				}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -