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

📄 overlay_console.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: overlay_ddraw.c 276 2005-08-23 14:47:32Z picard $
 *
 * The Core Pocket Media Player
 * Copyright (c) 2004-2005 Gabor Kovacs
 *
 ****************************************************************************/

#include "../common.h"

#if defined(TARGET_WIN32)

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

#if defined(TARGET_WINCE)
#define TWIN(a) L ## a
#else
#define TWIN(a) a
#endif

typedef struct palitem
{
	char ch;
	uint8_t col;
	uint8_t y[4];
	uint8_t u;
	uint8_t v;
	uint8_t rgb[4][3];

} palitem;

#define MAPCOUNT	29
//#define MAPCOUNT	14

typedef struct console
{
	overlay Overlay;
	planes Planes;
	planes Dither;
	HANDLE Handle;
	HANDLE Buffer;
	HMODULE Kernel;
	CHAR_INFO *Char;
	int16_t Width,Height;
	bool_t Own;
	HWND (WINAPI* GetConsoleWindow)();
	BOOL (WINAPI* SetConsoleOutputCP)(UINT);
	palitem** Map;
	palitem Pal[256*MAPCOUNT];

} console;

#define SAT(Value) (Value < 0 ? 0: (Value > 255 ? 255: Value))
#define SATY(Value) (Value < 16 ? 16: (Value > 255 ? 255: Value))

static const uint8_t Pal[16*4] = 
{
	0,0,0,0,
	0,0,128,0,
	0,128,0,0,
	0,128,128,0,
	128,0,0,0,
	128,0,128,0,
	128,128,0,0,
	192,192,192,0,
	128,128,128,0,
	0,0,255,0,
	0,255,0,0,
	0,255,255,0,
	255,0,0,0,
	255,0,255,0,
	255,255,0,0,
	255,255,255,0,
};

static const char Map[MAPCOUNT*5] = 
{
	' ',0,0,0,0,
	'.',0,0,3,3,
	',',0,0,4,4,
	':',3,3,3,3,
	';',3,3,4,4,
	'=',5,5,5,5,
	'~',5,5,0,0,
	'/',0,10,10,0,
	'\\',10,0,0,10,
	')',6,2,6,2,
	'(',2,6,2,6,
	'#',12,12,12,12,
	'\262',15,15,15,15,
	'\261',9,9,9,9,
	'\260',2,2,2,2,
	't',5,5,3,5,
	'f',5,3,5,5,
	'%',4,6,4,6,
	'$',8,8,8,8,
	'&',8,8,8,10,
	'K',11,9,11,9,
	'S',10,10,10,10,
	'Z',8,10,10,8,
	'W',8,8,10,10,
	'M',10,10,8,8,
	'X',11,11,11,11,
	'Y',11,11,6,6,
	'G',10,10,10,12,
	'8',11,11,11,11,
};

static INLINE void ToRGB(uint8_t* p,int y,int u,int v)
{
	int r,g,b;
	y -= 16;
	u -= 128;
	v -= 128;
	r = (y*0x2568             + 0x3343*v) /0x2000;
	g = (y*0x2568 - 0x0c92*u  - 0x1a1e*v) /0x2000;
	b = (y*0x2568 + 0x40cf*u)             /0x2000;
	p[0] = (uint8_t)(SAT(r));
	p[1] = (uint8_t)(SAT(g));
	p[2] = (uint8_t)(SAT(b));
}

static palitem* GetMap(console* p,int y0,int y1,int y2,int y3,int u,int v)
{
	palitem** q;
	q = &p->Map[(y0>>5)*8*8*8*16*16+
					     (y1>>5)*8*8*16*16+
					     (y2>>5)*8*16*16+
					     (y3>>5)*16*16+
					     (u>>4)*16+(v>>4)];

	if (*q==NULL)
	{
		//find best
		palitem* Best = NULL;
		int BestDiff = MAX_INT;
		palitem* Pal = p->Pal;
		uint8_t RGB[4][3];
		int i;

		y0 &= ~31;
		y1 &= ~31;
		y2 &= ~31;
		y3 &= ~31;
		u &= ~15;
		v &= ~15;

		ToRGB(RGB[0],y0,u,v);
		ToRGB(RGB[1],y1,u,v);
		ToRGB(RGB[2],y2,u,v);
		ToRGB(RGB[3],y3,u,v);

		for (i=0;i<MAPCOUNT*256;++i,++Pal)
		{
			int Diff;
#if defined(_MSC_VER) && defined(_M_IX86)
			uint16_t Diff2[2];
			__asm
			{
				mov eax,Pal
				pxor mm0,mm0

				movq mm2,[RGB]
				movd mm4,[RGB+8]
				movq mm3,mm2
				punpcklbw mm2,mm0		
				punpckhbw mm3,mm0		
				punpcklbw mm4,mm0		

				movq mm5,[eax+8]
				movd mm7,[eax+8+8]
				movq mm6,mm5
				punpcklbw mm5,mm0		
				punpckhbw mm6,mm0		
				punpcklbw mm7,mm0

				psubw mm2,mm5
				psubw mm3,mm6
				psubw mm4,mm7
				pxor mm5,mm5
				pxor mm6,mm6
				pxor mm7,mm7
				pcmpgtw	mm5,mm2
				pcmpgtw	mm6,mm3
				pcmpgtw	mm7,mm4
				pxor mm2,mm5
				pxor mm3,mm6
				pxor mm4,mm7
				paddw mm2,mm5
				paddw mm3,mm6
				paddw mm4,mm7

				paddw mm2,mm3
				paddw mm2,mm4
				movq mm0,mm2
				psrl mm0,32
				paddw mm0,mm2
				movd Diff2,mm0
			};
			Diff = Diff2[0] + Diff2[1];
#else			
			Diff = 
				abs(RGB[0][0] - Pal->rgb[0][0]) + 
				abs(RGB[0][1] - Pal->rgb[0][1]) + 
				abs(RGB[0][2] - Pal->rgb[0][2]);

			if (Diff >= BestDiff) continue;
			Diff +=
				abs(RGB[1][0] - Pal->rgb[1][0]) + 
				abs(RGB[1][1] - Pal->rgb[1][1]) + 
				abs(RGB[1][2] - Pal->rgb[1][2]);

			if (Diff >= BestDiff) continue;
			Diff +=
				abs(RGB[2][0] - Pal->rgb[2][0]) + 
				abs(RGB[2][1] - Pal->rgb[2][1]) + 
				abs(RGB[2][2] - Pal->rgb[2][2]);

			if (Diff >= BestDiff) continue;
			Diff +=
				abs(RGB[3][0] - Pal->rgb[3][0]) + 
				abs(RGB[3][1] - Pal->rgb[3][1]) + 
				abs(RGB[3][2] - Pal->rgb[3][1]);
#endif

			if (Diff < BestDiff)
			{
				BestDiff = Diff;
				Best = Pal;
			}
		}

#if defined(_MSC_VER) && defined(_M_IX86)
		__asm { emms };
#endif
		*q = Best;
	}
	return *q;
}

static int Init(console* p)
{
	int i,j,k,l;
	palitem* w;

	if (!p->Map)
	{
		p->Map = (palitem**) malloc(8*8*8*8*16*16*sizeof(palitem*));
		if (!p->Map)
			return ERR_OUT_OF_MEMORY;
		memset(p->Map,0,8*8*8*8*16*16*sizeof(palitem*));
	}

	if (SurfaceAlloc(p->Planes,&p->Overlay.Output.Format.Video)!=ERR_NONE)
		return ERR_OUT_OF_MEMORY;

	if (SurfaceAlloc(p->Dither,&p->Overlay.Output.Format.Video)!=ERR_NONE)
		return ERR_OUT_OF_MEMORY;

	memset(p->Planes[0],0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height);
	memset(p->Planes[1],128,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);
	memset(p->Planes[2],128,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);

	memset(p->Dither[0],0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height);
	memset(p->Dither[1],0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);
	memset(p->Dither[2],0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);

	p->Kernel = LoadLibrary(T("kernel32.dll"));
	*(FARPROC*)&p->GetConsoleWindow = GetProcAddress(p->Kernel,TWIN("GetConsoleWindow"));
	*(FARPROC*)&p->SetConsoleOutputCP = GetProcAddress(p->Kernel,TWIN("SetConsoleOutputCP"));

	p->Handle = INVALID_HANDLE_VALUE;
	p->Width = (int16_t)(p->Overlay.Output.Format.Video.Width/2);
	p->Height = (int16_t)(p->Overlay.Output.Format.Video.Height/2);
	p->Char = malloc(sizeof(CHAR_INFO)*p->Width*p->Height);
	if (!p->Char)
		return ERR_OUT_OF_MEMORY;

	w = p->Pal;
	for (i=0;i<16;++i)
		for (j=0;j<16;++j)
			for (k=0;k<MAPCOUNT;++k,++w)
			{
				int r,g,b,t;
				const char* ch = &Map[k*5];

				w->ch = ch[0];
				w->col = (uint8_t)(i*16+j);

				++ch;
				for (l=0;l<4;++l,++ch)
				{
					w->rgb[l][0] = (uint8_t)((Pal[i*4+0]*(32-ch[0])+Pal[j*4+0]*ch[0])>>5);
					w->rgb[l][1] = (uint8_t)((Pal[i*4+1]*(32-ch[0])+Pal[j*4+1]*ch[0])>>5);
					w->rgb[l][2] = (uint8_t)((Pal[i*4+2]*(32-ch[0])+Pal[j*4+2]*ch[0])>>5);
				}

				r = (w->rgb[0][0]+w->rgb[1][0]+w->rgb[2][0]+w->rgb[3][0])/4;
				g = (w->rgb[0][1]+w->rgb[1][1]+w->rgb[2][1]+w->rgb[3][1])/4;
				b = (w->rgb[0][2]+w->rgb[1][2]+w->rgb[2][2]+w->rgb[3][2])/4;

				t = (-(1212 * r) - (2384 * g) + (3596 * b))/0x2000 + 128;
				w->u = (uint8_t)(SAT(t));

				t = ((3596 * r) - (3015 * g) - (582 * b))/0x2000 + 128;
				w->v = (uint8_t)(SAT(t));

				t = ((2105 * w->rgb[0][0]) + (4128 * w->rgb[0][1]) + (802 * w->rgb[0][2]))/0x2000 + 16;
				w->y[0] = (uint8_t)(SATY(t));

				t = ((2105 * w->rgb[1][0]) + (4128 * w->rgb[1][1]) + (802 * w->rgb[1][2]))/0x2000 + 16;
				w->y[1] = (uint8_t)(SATY(t));

				t = ((2105 * w->rgb[2][0]) + (4128 * w->rgb[2][1]) + (802 * w->rgb[2][2]))/0x2000 + 16;
				w->y[2] = (uint8_t)(SATY(t));

				t = ((2105 * w->rgb[3][0]) + (4128 * w->rgb[3][1]) + (802 * w->rgb[3][2]))/0x2000 + 16;
				w->y[3] = (uint8_t)(SATY(t));
			}

	p->Overlay.ClearFX = BLITFX_ONLYDIFF;
	return ERR_NONE;
}

static void Done(console* p)
{
	SurfaceFree(p->Planes); 
	SurfaceFree(p->Dither);
	FreeLibrary(p->Kernel);
	free(p->Char);
	p->Char = NULL;
}

static void Delete(console* p)
{
	free(p->Map);
	p->Map = NULL;
}

static int UpdateShow(console* p)
{
	CONSOLE_CURSOR_INFO Info;

	if (p->Overlay.Show)
	{
		COORD Size;
		p->Own = AllocConsole() != FALSE;

        p->Handle = CreateFile(T("CONOUT$"), GENERIC_READ | GENERIC_WRITE,
                                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                                OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		if (p->Handle == INVALID_HANDLE_VALUE)
			return ERR_NOT_SUPPORTED;

		p->Buffer = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,0,NULL,CONSOLE_TEXTMODE_BUFFER,NULL);
		if (p->Buffer == INVALID_HANDLE_VALUE)
			return ERR_NOT_SUPPORTED;

		Size.X = p->Width;
		Size.Y = p->Height;
		SetConsoleScreenBufferSize(p->Buffer,Size);

		GetConsoleCursorInfo(p->Buffer, &Info);
		Info.bVisible = FALSE;
		SetConsoleCursorInfo(p->Buffer, &Info);

		SetConsoleMode(p->Buffer, 0);
		SetConsoleActiveScreenBuffer(p->Buffer);

		if (p->SetConsoleOutputCP)
			p->SetConsoleOutputCP(850);

		if (p->GetConsoleWindow)
			SetWindowPos(p->GetConsoleWindow(),HWND_TOP,0,0,1024,1024,SWP_NOMOVE|SWP_SHOWWINDOW);
	}
	else
	{
		if (p->Handle != INVALID_HANDLE_VALUE)
		{
			SetConsoleActiveScreenBuffer(p->Handle);

			CloseHandle(p->Buffer);
			CloseHandle(p->Handle);

			if (p->Own)
				FreeConsole();
		}
	}
	return ERR_NONE;
}

static int Lock(console* p, planes Planes, bool_t OnlyAligned )
{
	Planes[0] = p->Planes[0];
	return ERR_NONE;
}

static int Unlock(console* p )
{
	return ERR_NONE;
}

static int Blit(console* p, const constplanes Data, const constplanes DataLast )
{
	if (p->Handle != INVALID_HANDLE_VALUE)
	{
		COORD Pos,Size;
		SMALL_RECT Rect;
		int n,Row;
		CHAR_INFO *Char;
		uint8_t *y,*u,*v;
		int8_t *y2,*u2,*v2;
		int dy[4],du,dv,PalY;

		BlitImage(p->Overlay.Soft,p->Planes,Data,DataLast,-1,-1);

		y = p->Planes[0];
		u = p->Planes[1];
		v = p->Planes[2];

		y2 = p->Dither[0];
		u2 = p->Dither[1];
		v2 = p->Dither[2];

		if (p->Overlay.Dirty)
		{
			memset(y2,0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height);
			memset(u2,0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);
			memset(v2,0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);
		}

		Char = p->Char;
		Row = 0;
		dy[0] = dy[1] = dy[2] = dy[3] = du = dv = 0;

		for (n = p->Width*p->Height;--n>=0;++Char)
		{
			int Pitch = p->Overlay.Output.Format.Video.Pitch;
			palitem* Pal;

			dy[0] += y[0] + y2[0];
			dy[1] += y[1] + y2[1];
			dy[2] += y[Pitch+0] + y2[Pitch+0];
			dy[3] += y[Pitch+1] + y2[Pitch+1];
			du += u[0] + u2[0];
			dv += v[0] + v2[0];

			dy[0] = SATY(dy[0]);
			dy[1] = SATY(dy[1]);
			dy[2] = SATY(dy[2]);
			dy[3] = SATY(dy[3]);
			du = SAT(du);
			dv = SAT(dv);

			Pal = GetMap(p,dy[0],dy[1],dy[2],dy[3],du,dv);

			y2[0] = (int8_t)((dy[0]-Pal->y[0])>>1);
			y2[1] = (int8_t)((dy[1]-Pal->y[1])>>1);
			y2[Pitch+0] = (int8_t)((dy[2]-Pal->y[2])>>1);
			y2[Pitch+1] = (int8_t)((dy[3]-Pal->y[3])>>1);

			PalY = Pal->y[0]+Pal->y[1]+Pal->y[2]+Pal->y[3];
			dy[0] = dy[1] = dy[2] = dy[3] = (dy[0]+dy[1]+dy[2]+dy[3]-PalY)/8;
			du = (du - Pal->u) >> 1;
			dv = (dv - Pal->v) >> 1;
			if (PalY < 48*4)
			{
				du /= 2;
				dv /= 2;

				if (PalY < 32*4)
				{
					du /= 4;
					dv /= 4;
				}
			}

			u2[0] = (int8_t)du;
			v2[0] = (int8_t)dv;

			Char->Attributes = Pal->col;
			Char->Char.AsciiChar = Pal->ch;

			y += 2;
			++u;
			++v;

			y2 += 2;
			++u2;
			++v2;

			if (++Row == p->Width)
			{
				Row = 0;
				y += p->Overlay.Output.Format.Video.Pitch;
				y2 += p->Overlay.Output.Format.Video.Pitch;
			}
		}

		Size.X = p->Width;
		Size.Y = p->Height;
		Pos.X = 0;
		Pos.Y = 0;
		Rect.Left = 0;
		Rect.Top = 0;
		Rect.Right = (int16_t)(p->Width-1);
		Rect.Bottom = (int16_t)(p->Height-1);
		WriteConsoleOutput(p->Buffer, p->Char, Size, Pos, &Rect);
	}
	return ERR_NONE;
}

static int Create(console* p)
{
	p->Overlay.Primary = 0;
	p->Overlay.Output.Format.Video.Width = 80*2;
	p->Overlay.Output.Format.Video.Height = 50*2;
	p->Overlay.Output.Format.Video.Direction = 0;
	p->Overlay.Output.Format.Video.Aspect = ASPECT_ONE;
	p->Overlay.Output.Format.Video.Pitch = p->Overlay.Output.Format.Video.Width;
	p->Overlay.Output.Format.Video.Pixel.Flags = PF_YUV420|PF_16ALIGNED;
	FillInfo(&p->Overlay.Output.Format.Video.Pixel);
	p->Overlay.Init = Init;
	p->Overlay.Done = Done;
	p->Overlay.Blit = Blit;
	p->Overlay.UpdateShow = UpdateShow;
	p->Overlay.Lock = Lock;
	p->Overlay.Unlock = Unlock;
	return ERR_NONE;
}

static const nodedef Console = 
{
	sizeof(console)|CF_GLOBAL,
	CONSOLE_ID,
	OVERLAY_CLASS,
	PRI_DEFAULT-15,
	(nodecreate)Create,
	(nodedelete)Delete,
};

void OverlayConsole_Init() 
{ 
	NodeRegisterClass(&Console);
}

void OverlayConsole_Done()
{
	NodeUnRegisterClass(CONSOLE_ID);
}

#endif

⌨️ 快捷键说明

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