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

📄 mem_palmos.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
字号:
/*****************************************************************************
 *
 * 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_palmos.c 543 2006-01-07 22:06:24Z picard $
 *
 * The Core Pocket Media Player
 * Copyright (c) 2004-2005 Gabor Kovacs
 *
 ****************************************************************************/

#include "../common.h"

//#define TRACKMEMORY

#if defined(TARGET_PALMOS)

#define MIN_DYNAMIC_LIMIT	32768
#define TRY_DYNAMIC			3*1024*1024
#define FTRID_MIN			4096
#define FTRID_MAX			16384
#define MAX_CACHE			32768

#include "pace.h"

extern SysAppInfoPtr SysGetAppInfo(SysAppInfoPtr *uiAppPP, SysAppInfoPtr* actionCodeAppPP);

#ifdef HAVE_PALMONE_SDK
#include <68K/System/PmPalmOSNVFS.h>
#endif

static block FlushCache = {NULL};
static int OutOfMemory = 0;
static UInt16 StorageId = 1;

void free(void *p)
{
	if (p)
	{
#ifdef TRACKMEMORY
		int q = AvailMemory();
#endif
		MemPtrFree(p);
#ifdef TRACKMEMORY
		DebugMessage("%08x free:%d %d",p,AvailMemory(),q-AvailMemory());
#endif
	}
}

void EnableOutOfMemory()
{
	OutOfMemory--;
}

void DisableOutOfMemory()
{
	OutOfMemory++;
}

void ShowOutOfMemory()
{
	if (OutOfMemory<=0)
	{
		RectangleType r;
		Coord Width;
		Coord Height;
		const tchar_t* s = LangStr(ERR_ID,ERR_OUT_OF_MEMORY);
		WinHandle Old = WinSetDrawWindow(WinGetDisplayWindow());
		WinGetDisplayExtent(&Width, &Height);

		if (Width<60)
			Width=60;
		r.topLeft.x = (Coord)(Width-80);
		r.topLeft.y = 16;
		r.extent.x = 79;
		r.extent.y = 15; 

		WinEraseRectangle(&r, 0);
		WinDrawChars(s, (Int16)strlen(s), (Coord)(r.topLeft.x+1), (Coord)(r.topLeft.y+1));

		if (Old)
			WinSetDrawWindow(Old);
	}
}

void* malloc(size_t n)
{
#ifdef TRACKMEMORY
	int q = AvailMemory();
#endif
	void *p = NULL;
	if (n)
	{
		do
		{
			if ((size_t)AvailMemory()>MIN_DYNAMIC_LIMIT+n)
				p = MemGluePtrNew(n);
		} while (!p && NodeHibernate());

		if (!p)
		{
			//DebugMessage("malloc %d %d",n,AvailMemory());
			ShowOutOfMemory();
		}
	}

#ifdef TRACKMEMORY
	DebugMessage("%08x malloc:%d %d %d",p,n,q,q-AvailMemory());
	if (n>1024)
		ThreadSleep(300);
#endif
	return p;
}

void* realloc(void* p,size_t n)
{
#ifdef TRACKMEMORY
	int q = AvailMemory();
#endif
	if (!p)
		return malloc(n);
	else
	if (!n)
	{
		MemPtrFree(p);
#ifdef TRACKMEMORY
		DebugMessage("%08x free:%d %d",p,AvailMemory(),q-AvailMemory());
#endif
		return NULL;
	}
	else
	if (MemPtrResize(p,n)!=errNone)
	{
		void *q = NULL;
		do
		{
			if ((size_t)AvailMemory()>MIN_DYNAMIC_LIMIT+n)
				q = MemGluePtrNew(n);
		} while (!q && NodeHibernate());
		if (q) 
		{
			memcpy(q,p,MemPtrSize(p));
			MemPtrFree(p);
		}
		else
			ShowOutOfMemory();
		p = q;
    }
#ifdef TRACKMEMORY
	DebugMessage("%08x realloc:%d %d %d",p,n,q,q-AvailMemory());
	if (n>1024)
		ThreadSleep(300);
#endif
	return p;
}

void* CodeAlloc(int Size) {	return malloc(Size); }
void CodeFree(void* Code,int Size) { free(Code); }
void CodeLock(void* Code,int Size) {}

void CodeUnlock(void* Code,int Size) 
{
	// instruction cache flush needed
#ifdef ARM
	if (FlushCache.Ptr)
		((void(*)())FlushCache.Ptr)();
#endif
}

void WriteBlock(block* Block,int Ofs,const void* Src,int Length)
{
	if (IsHeapStorage(Block))
		DmWrite((void*)Block->Ptr,Ofs,Src,Length);
	else
		memcpy((char*)Block->Ptr+Ofs,Src,Length);
}

void FreeBlock(block* Block)
{
	if (Block)
	{
		context* p = Context();
		if (IsHeapStorage(Block))
		{
			int FtrId = Block->Id;
			if (p->FtrId > FtrId)
				p->FtrId = FtrId;
			FtrPtrFree(p->ProgramId,(UInt16)FtrId);
		}
		else
			free((char*)Block->Ptr);
		Block->Id = 0;
		Block->Ptr = NULL;
	}
}

bool_t SetHeapBlock(int n,block* Block,int Heap)
{
	block New;
	if (!Block->Id && (Heap & HEAP_DYNAMIC))
		return 0;
	if (IsHeapStorage(Block) && (Heap & HEAP_STORAGE))
		return 0;
	if (!AllocBlock(n,&New,1,Heap))
		return 0;
	WriteBlock(&New,0,Block->Ptr,n);
	FreeBlock(Block);
	*Block = New;
	return 1;
}

#ifdef ARM
static NOINLINE void FlushData(volatile const void* ptr)
{
	const int zero = 0;
	asm volatile ("mcr p15, 0, %0, c7, c14, 1" : : "r" (ptr));  // clean+invalidate D entry
	asm volatile ("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero)); // drain write buffer
}

static NOINLINE void FlushTLB()
{
	const int zero = 0;
	asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero)); // invalidate I and D TLB
}
#endif

static NOINLINE int GetFtrId(context* p)
{
	UInt32 v;
	int FtrId = max(p->FtrId,FTRID_MIN);
	for (;FtrId<FTRID_MAX;++FtrId)
		if (FtrGet(p->ProgramId,(UInt16)FtrId,&v)==ftrErrNoSuchFeature)
			return FtrId;
	return -1;
}

bool_t AllocBlock(size_t n,block* Block,bool_t Optional,int Heap)
{
	context* p = Context();
	uint32_t Storage,Max;
	void* Ptr = NULL;

	if (!n)
	{
		Block->Id = 0;
		Block->Ptr = NULL;
		return 1;
	}

	if (Heap == HEAP_ANY && !p->TryDynamic)
		Heap = HEAP_STORAGE;

	if ((Heap & HEAP_STORAGEWR) && (n<16384 || !QueryAdvanced(ADVANCED_MEMORYOVERRIDE)))
		Heap &= ~HEAP_STORAGEWR;

	if (Optional)
	{
		if ((Heap & (HEAP_STORAGE|HEAP_STORAGEWR)) && MemHeapFreeBytes(StorageId,&Storage,&Max)==errNone && (int)Storage<128*1024+n)
			Heap &= ~(HEAP_STORAGE|HEAP_STORAGEWR);

		if ((Heap & HEAP_DYNAMIC) && AvailMemory()<((Heap & HEAP_STORAGE)?2048:512)*1024+n)
			Heap &= ~HEAP_DYNAMIC;
	}

	if (Heap & HEAP_STORAGEWR)
	{
		int FtrId = GetFtrId(p);
		if (FtrId>=0)
		{
			do
			{
				if (FtrPtrNew(p->ProgramId,(UInt16)FtrId,n,&Ptr)==errNone)
					break;
			} while (NodeHibernate());

			if (Ptr)
			{
				uint32_t Phy = MemVirtToPhy(Ptr);
				void* PtrWr = MemAsWritable(Phy);

				if (!PtrWr || memcmp(Ptr,PtrWr,n)!=0)
				{
					//ShowMessage("","Memory tweak failed for address virt:%08x phy:%08x tmp:%08x\nPlease report to developer!",Ptr,Phy,PtrWr);
					PtrWr = NULL;
				}

				if (PtrWr)
				{
					p->FtrId = FtrId+1;
					Block->Id = FtrId;
					Block->Ptr = PtrWr;
					return 1;
				}

				FtrPtrFree(p->ProgramId,(UInt16)FtrId);
				Ptr = NULL;
			}
		}
	}

	if (Heap & HEAP_DYNAMIC)
	{
		Ptr = malloc(n);
		if (Ptr)
		{
			Block->Ptr = Ptr;
			Block->Id = 0;
			return 1;
		}
	}

	if (Heap & HEAP_STORAGE)
	{
		int FtrId = GetFtrId(p);
		if (FtrId>=0)
		{
			do
			{
				if (MemHeapFreeBytes(StorageId,&Storage,&Max)==errNone && (int)Max<n+8192)
					continue;
				if (FtrPtrNew(p->ProgramId,(UInt16)FtrId,n,&Ptr)==errNone)
					break;
			} while (!Optional && NodeHibernate());

			if (Ptr)
			{
				p->FtrId = FtrId+1;
				Block->Id = FtrId;
				Block->Ptr = Ptr;
				return 1;
			}
		}
	}

	if (!Optional)
		ShowOutOfMemory();
	return 0;
}

void* PhyMemAlloc(int Length,phymemblock* Blocks,int* BlockCount) { return NULL; }
void PhyMemFree(void* p,phymemblock* Blocks,int BlockCount) {}
void* PhyMemBeginEx(phymemblock* Blocks,int BlockCount,bool_t Cached) { return NULL; }
void* PhyMemBegin(uint32_t Phy,uint32_t Length,bool_t Cached) { return NULL; }
void PhyMemEnd(void* Virt) {}

void CheckHeap() 
{
	assert(MemHeapCheck(MemHeapID(0,0))==0);
}
 
size_t AvailMemory()
{
	uint32_t Max = 0;
	uint32_t Free = 0;
	MemHeapFreeBytes(MemHeapID(0,0),&Free,&Max);
	return Free;
}

void CodeFindPages(void* Ptr,uint8_t** PMin,uint8_t** PMax,size_t* PPageSize)
{
	if (PMin)
		*PMin = (uint8_t*)Ptr;
	if (PMax)
		*PMax = (uint8_t*)Ptr;
	if (PPageSize)
		*PPageSize = 4096;
}

bool_t MemGetInfo(memoryinfo* Info)
{
#ifdef ARM
	int Model = QueryPlatform(PLATFORM_MODEL);
	if (Model == MODEL_TUNGSTEN_T || Model == MODEL_TUNGSTEN_T2)
	{
		if (Info)
		{
			memset(Info,0,sizeof(memoryinfo));
			Info->TLB = (uint32_t*)0x20010000;
			Info->MemBase[0] = 0x10100000;
			Info->MemSize[0] = 14;
			Info->UnusedArea[0] = 0xB0200000;
			Info->MemBase[1] = 0x11000000;
			Info->MemSize[1] = 16;
			Info->UnusedArea[1] = 0xB1000000;
		}
		return 1;
	}
#endif
	return 0;
}

void* MemAsWritable(uint32_t Phy)
{
#ifdef ARM
	memoryinfo Info;
	uint32_t v;
	bool_t Changed;
	int n,i,j;

	if (!Phy)
		return NULL;

	if (!MemGetInfo(&Info))
		return NULL;

	for (n=0;n<2;++n)
		if (Phy >= Info.MemBase[n] && Phy < Info.MemBase[n]+(Info.MemSize[n]<<20))
		{
			Phy = Phy - Info.MemBase[n] + Info.UnusedArea[n];

			Changed = 0;
			for (n=0;n<2;++n)
			{
				j = Info.UnusedArea[n]>>20;
				v = Info.MemBase[n] | 0xC4E;
				for (i=0;i<Info.MemSize[n];i++,v+=1024*1024,++j)
					if (Info.TLB[j] != v)
					{
						Info.TLB[j] = v;
						FlushData(Info.TLB+j);
						Changed = 1;
					}
			}

			if (Changed)
				FlushTLB();
			return (void*)Phy;
		}

#endif
	return NULL;
}

void* MemPhyToVirt(uint32_t Phy)
{
#ifdef ARM
	int Model = QueryPlatform(PLATFORM_MODEL);
	switch (Model)
	{
	case MODEL_TUNGSTEN_T3:
	case MODEL_TUNGSTEN_T5:
	case MODEL_ZIRE_72:
	case MODEL_LIFEDRIVE:
	case MODEL_PALM_TX:
	case MODEL_TREO_650:
		if (Phy >= 0x44000000 && Phy < 0x44100000) // XScale LCD
			return (void*)(Phy+0x94000000-0x44000000);
		break;
	case MODEL_TUNGSTEN_C:
	case MODEL_TUNGSTEN_E2:
		if (Phy >= 0x44000000 && Phy < 0x44100000) // XScale LCD
			return (void*)(Phy+0x92000000-0x44000000);
		break;
	//case MODEL_TUNGSTEN_T: //(borderless mode not supported)
	case MODEL_ZIRE_71:
	case MODEL_TUNGSTEN_E:
	case MODEL_TUNGSTEN_T2:
		if (Phy >= 0xFFF00000) // OMAP
			return (void*)Phy;
		break;
	}
#endif
	return NULL;
}

uint32_t MemVirtToPhy(void* p)
{
#ifdef ARM
	int n;
	memoryinfo Info;
	uint32_t Ptr = (uint32_t)p;
	int Model = QueryPlatform(PLATFORM_MODEL);
	switch (Model)
	{
	case MODEL_ZIRE_72:
	case MODEL_TUNGSTEN_C:
	case MODEL_TUNGSTEN_E2:
	case MODEL_TUNGSTEN_T3:
		if (Ptr >= 0x00000000 && Ptr < 0x04000000) //total memory
			return Ptr+0xA0000000;
		break;
	case MODEL_TUNGSTEN_T5:
		if (Ptr >= 0x00200000 && Ptr < 0x00600000) //dynamic
			return Ptr+0xA1C00000-0x00200000;
		// no info about storage yet...
		break;
	case MODEL_TREO_650:
		if (Ptr >= 0x64000000 && Ptr < 0x64500000) //dynamic
			return Ptr+0xA1A00000-0x64000000;
		if (Ptr >= 0x73100000 && Ptr < 0x73c00000) //storage
			return Ptr+0xA0F00000-0x73100000;
		break;
	case MODEL_LIFEDRIVE:
		if (Ptr >= 0x00200000 && Ptr < 0x00800000) //dynamic
			return Ptr+0xA1A00000-0x00200000;
		if (Ptr >= 0x00800000 && Ptr < 0x01430000) //storage
			return Ptr+0xA0DD0000-0x00800000;
		break;
	case MODEL_PALM_TX:
		if (Ptr >= 0x00200000 && Ptr < 0x00800000) //dynamic
			return Ptr+0xA1A00000-0x00200000;
		if (Ptr >= 0x00800000 && Ptr < 0x013D0000) //storage
			return Ptr+0xA0E30000-0x00800000;
		break;
	case MODEL_ZIRE_71:
		if (Ptr >= 0x00100000 && Ptr < 0x00200000) //dynamic
			return Ptr+0x10010000-0x00100000;
		if (Ptr >= 0x00200000 && Ptr < 0x00fe0000) //storage
			return Ptr+0x10120000-0x00200000;
		break;
	case MODEL_TUNGSTEN_E:
		if (Ptr >= 0x00100000 && Ptr < 0x00300000) //dynamic
			return Ptr+0x10020000-0x00100000;
		if (Ptr >= 0x00300000 && Ptr < 0x01fd0000) //storage
			return Ptr+0x10230000-0x00300000;
		break;
	case MODEL_TUNGSTEN_T:
	case MODEL_TUNGSTEN_T2:
		if (Ptr >= 0x00100000 && Ptr < 0x001c9000) //dynamic
			return Ptr+0x10037000-0x00100000;
		if (Ptr >= 0x00200000 && Ptr < 0x01000000) //storage
			return Ptr+0x10100000-0x00200000;
		if (Ptr >= 0x01000000 && Ptr < 0x02000000) //T2 additional storage
			return Ptr+0x11000000-0x01000000;
		break;
	}

	if (MemGetInfo(&Info))
		for (n=0;n<2;++n)
			if (Ptr >= Info.UnusedArea[n] && Ptr < Info.UnusedArea[n]+(Info.MemSize[n]<<20))
				return Ptr-Info.UnusedArea[n]+Info.MemBase[n];

#endif
	return 0;
}

void Mem_Init()
{

	Context()->TryDynamic = Context()->StartUpMemory > TRY_DYNAMIC;
	StorageId = MemHeapID(0,1);

#ifdef HAVE_PALMONE_SDK
	{
		UInt32 Version;
		if (FtrGet(sysFtrCreator,sysFtrNumDmAutoBackup,&Version)==errNone && Version==1)
			StorageId = 1|dbCacheFlag;
	}
#endif

#ifdef ARM
	if (AllocBlock(MAX_CACHE+sizeof(uint32_t),&FlushCache,0,HEAP_ANY))
	{
		uint32_t p[64];
		int i;
		for (i=0;i<64;++i)
			p[i] = 0xE51F0008; //ldr r0,[pc,#-8]
		for (i=0;i<=MAX_CACHE-sizeof(p);i+=sizeof(p))
			WriteBlock(&FlushCache,i,p,sizeof(p));
		p[0] = 0xE1A0F00E; // mov pc,lr
		WriteBlock(&FlushCache,i,p,sizeof(uint32_t));
	}
#endif
}

void Mem_Done()
{
#ifdef ARM
	FreeBlock(&FlushCache);
#endif
}

#endif

⌨️ 快捷键说明

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