overlay_console.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:13k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: overlay_ddraw.c 276 2005-08-23 14:47:32Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common.h"
  24. #if defined(TARGET_WIN32)
  25. #define WIN32_LEAN_AND_MEAN
  26. #ifndef STRICT
  27. #define STRICT
  28. #endif
  29. #include <windows.h>
  30. #if defined(TARGET_WINCE)
  31. #define TWIN(a) L ## a
  32. #else
  33. #define TWIN(a) a
  34. #endif
  35. typedef struct palitem
  36. {
  37. char ch;
  38. uint8_t col;
  39. uint8_t y[4];
  40. uint8_t u;
  41. uint8_t v;
  42. uint8_t rgb[4][3];
  43. } palitem;
  44. #define MAPCOUNT 29
  45. //#define MAPCOUNT 14
  46. typedef struct console
  47. {
  48. overlay Overlay;
  49. planes Planes;
  50. planes Dither;
  51. HANDLE Handle;
  52. HANDLE Buffer;
  53. HMODULE Kernel;
  54. CHAR_INFO *Char;
  55. int16_t Width,Height;
  56. bool_t Own;
  57. HWND (WINAPI* GetConsoleWindow)();
  58. BOOL (WINAPI* SetConsoleOutputCP)(UINT);
  59. palitem** Map;
  60. palitem Pal[256*MAPCOUNT];
  61. } console;
  62. #define SAT(Value) (Value < 0 ? 0: (Value > 255 ? 255: Value))
  63. #define SATY(Value) (Value < 16 ? 16: (Value > 255 ? 255: Value))
  64. static const uint8_t Pal[16*4] = 
  65. {
  66. 0,0,0,0,
  67. 0,0,128,0,
  68. 0,128,0,0,
  69. 0,128,128,0,
  70. 128,0,0,0,
  71. 128,0,128,0,
  72. 128,128,0,0,
  73. 192,192,192,0,
  74. 128,128,128,0,
  75. 0,0,255,0,
  76. 0,255,0,0,
  77. 0,255,255,0,
  78. 255,0,0,0,
  79. 255,0,255,0,
  80. 255,255,0,0,
  81. 255,255,255,0,
  82. };
  83. static const char Map[MAPCOUNT*5] = 
  84. {
  85. ' ',0,0,0,0,
  86. '.',0,0,3,3,
  87. ',',0,0,4,4,
  88. ':',3,3,3,3,
  89. ';',3,3,4,4,
  90. '=',5,5,5,5,
  91. '~',5,5,0,0,
  92. '/',0,10,10,0,
  93. '\',10,0,0,10,
  94. ')',6,2,6,2,
  95. '(',2,6,2,6,
  96. '#',12,12,12,12,
  97. '262',15,15,15,15,
  98. '261',9,9,9,9,
  99. '260',2,2,2,2,
  100. 't',5,5,3,5,
  101. 'f',5,3,5,5,
  102. '%',4,6,4,6,
  103. '$',8,8,8,8,
  104. '&',8,8,8,10,
  105. 'K',11,9,11,9,
  106. 'S',10,10,10,10,
  107. 'Z',8,10,10,8,
  108. 'W',8,8,10,10,
  109. 'M',10,10,8,8,
  110. 'X',11,11,11,11,
  111. 'Y',11,11,6,6,
  112. 'G',10,10,10,12,
  113. '8',11,11,11,11,
  114. };
  115. static INLINE void ToRGB(uint8_t* p,int y,int u,int v)
  116. {
  117. int r,g,b;
  118. y -= 16;
  119. u -= 128;
  120. v -= 128;
  121. r = (y*0x2568             + 0x3343*v) /0x2000;
  122. g = (y*0x2568 - 0x0c92*u  - 0x1a1e*v) /0x2000;
  123. b = (y*0x2568 + 0x40cf*u)             /0x2000;
  124. p[0] = (uint8_t)(SAT(r));
  125. p[1] = (uint8_t)(SAT(g));
  126. p[2] = (uint8_t)(SAT(b));
  127. }
  128. static palitem* GetMap(console* p,int y0,int y1,int y2,int y3,int u,int v)
  129. {
  130. palitem** q;
  131. q = &p->Map[(y0>>5)*8*8*8*16*16+
  132.      (y1>>5)*8*8*16*16+
  133.      (y2>>5)*8*16*16+
  134.      (y3>>5)*16*16+
  135.      (u>>4)*16+(v>>4)];
  136. if (*q==NULL)
  137. {
  138. //find best
  139. palitem* Best = NULL;
  140. int BestDiff = MAX_INT;
  141. palitem* Pal = p->Pal;
  142. uint8_t RGB[4][3];
  143. int i;
  144. y0 &= ~31;
  145. y1 &= ~31;
  146. y2 &= ~31;
  147. y3 &= ~31;
  148. u &= ~15;
  149. v &= ~15;
  150. ToRGB(RGB[0],y0,u,v);
  151. ToRGB(RGB[1],y1,u,v);
  152. ToRGB(RGB[2],y2,u,v);
  153. ToRGB(RGB[3],y3,u,v);
  154. for (i=0;i<MAPCOUNT*256;++i,++Pal)
  155. {
  156. int Diff;
  157. #if defined(_MSC_VER) && defined(_M_IX86)
  158. uint16_t Diff2[2];
  159. __asm
  160. {
  161. mov eax,Pal
  162. pxor mm0,mm0
  163. movq mm2,[RGB]
  164. movd mm4,[RGB+8]
  165. movq mm3,mm2
  166. punpcklbw mm2,mm0
  167. punpckhbw mm3,mm0
  168. punpcklbw mm4,mm0
  169. movq mm5,[eax+8]
  170. movd mm7,[eax+8+8]
  171. movq mm6,mm5
  172. punpcklbw mm5,mm0
  173. punpckhbw mm6,mm0
  174. punpcklbw mm7,mm0
  175. psubw mm2,mm5
  176. psubw mm3,mm6
  177. psubw mm4,mm7
  178. pxor mm5,mm5
  179. pxor mm6,mm6
  180. pxor mm7,mm7
  181. pcmpgtw mm5,mm2
  182. pcmpgtw mm6,mm3
  183. pcmpgtw mm7,mm4
  184. pxor mm2,mm5
  185. pxor mm3,mm6
  186. pxor mm4,mm7
  187. paddw mm2,mm5
  188. paddw mm3,mm6
  189. paddw mm4,mm7
  190. paddw mm2,mm3
  191. paddw mm2,mm4
  192. movq mm0,mm2
  193. psrl mm0,32
  194. paddw mm0,mm2
  195. movd Diff2,mm0
  196. };
  197. Diff = Diff2[0] + Diff2[1];
  198. #else
  199. Diff = 
  200. abs(RGB[0][0] - Pal->rgb[0][0]) + 
  201. abs(RGB[0][1] - Pal->rgb[0][1]) + 
  202. abs(RGB[0][2] - Pal->rgb[0][2]);
  203. if (Diff >= BestDiff) continue;
  204. Diff +=
  205. abs(RGB[1][0] - Pal->rgb[1][0]) + 
  206. abs(RGB[1][1] - Pal->rgb[1][1]) + 
  207. abs(RGB[1][2] - Pal->rgb[1][2]);
  208. if (Diff >= BestDiff) continue;
  209. Diff +=
  210. abs(RGB[2][0] - Pal->rgb[2][0]) + 
  211. abs(RGB[2][1] - Pal->rgb[2][1]) + 
  212. abs(RGB[2][2] - Pal->rgb[2][2]);
  213. if (Diff >= BestDiff) continue;
  214. Diff +=
  215. abs(RGB[3][0] - Pal->rgb[3][0]) + 
  216. abs(RGB[3][1] - Pal->rgb[3][1]) + 
  217. abs(RGB[3][2] - Pal->rgb[3][1]);
  218. #endif
  219. if (Diff < BestDiff)
  220. {
  221. BestDiff = Diff;
  222. Best = Pal;
  223. }
  224. }
  225. #if defined(_MSC_VER) && defined(_M_IX86)
  226. __asm { emms };
  227. #endif
  228. *q = Best;
  229. }
  230. return *q;
  231. }
  232. static int Init(console* p)
  233. {
  234. int i,j,k,l;
  235. palitem* w;
  236. if (!p->Map)
  237. {
  238. p->Map = (palitem**) malloc(8*8*8*8*16*16*sizeof(palitem*));
  239. if (!p->Map)
  240. return ERR_OUT_OF_MEMORY;
  241. memset(p->Map,0,8*8*8*8*16*16*sizeof(palitem*));
  242. }
  243. if (SurfaceAlloc(p->Planes,&p->Overlay.Output.Format.Video)!=ERR_NONE)
  244. return ERR_OUT_OF_MEMORY;
  245. if (SurfaceAlloc(p->Dither,&p->Overlay.Output.Format.Video)!=ERR_NONE)
  246. return ERR_OUT_OF_MEMORY;
  247. memset(p->Planes[0],0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height);
  248. memset(p->Planes[1],128,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);
  249. memset(p->Planes[2],128,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);
  250. memset(p->Dither[0],0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height);
  251. memset(p->Dither[1],0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);
  252. memset(p->Dither[2],0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);
  253. p->Kernel = LoadLibrary(T("kernel32.dll"));
  254. *(FARPROC*)&p->GetConsoleWindow = GetProcAddress(p->Kernel,TWIN("GetConsoleWindow"));
  255. *(FARPROC*)&p->SetConsoleOutputCP = GetProcAddress(p->Kernel,TWIN("SetConsoleOutputCP"));
  256. p->Handle = INVALID_HANDLE_VALUE;
  257. p->Width = (int16_t)(p->Overlay.Output.Format.Video.Width/2);
  258. p->Height = (int16_t)(p->Overlay.Output.Format.Video.Height/2);
  259. p->Char = malloc(sizeof(CHAR_INFO)*p->Width*p->Height);
  260. if (!p->Char)
  261. return ERR_OUT_OF_MEMORY;
  262. w = p->Pal;
  263. for (i=0;i<16;++i)
  264. for (j=0;j<16;++j)
  265. for (k=0;k<MAPCOUNT;++k,++w)
  266. {
  267. int r,g,b,t;
  268. const char* ch = &Map[k*5];
  269. w->ch = ch[0];
  270. w->col = (uint8_t)(i*16+j);
  271. ++ch;
  272. for (l=0;l<4;++l,++ch)
  273. {
  274. w->rgb[l][0] = (uint8_t)((Pal[i*4+0]*(32-ch[0])+Pal[j*4+0]*ch[0])>>5);
  275. w->rgb[l][1] = (uint8_t)((Pal[i*4+1]*(32-ch[0])+Pal[j*4+1]*ch[0])>>5);
  276. w->rgb[l][2] = (uint8_t)((Pal[i*4+2]*(32-ch[0])+Pal[j*4+2]*ch[0])>>5);
  277. }
  278. r = (w->rgb[0][0]+w->rgb[1][0]+w->rgb[2][0]+w->rgb[3][0])/4;
  279. g = (w->rgb[0][1]+w->rgb[1][1]+w->rgb[2][1]+w->rgb[3][1])/4;
  280. b = (w->rgb[0][2]+w->rgb[1][2]+w->rgb[2][2]+w->rgb[3][2])/4;
  281. t = (-(1212 * r) - (2384 * g) + (3596 * b))/0x2000 + 128;
  282. w->u = (uint8_t)(SAT(t));
  283. t = ((3596 * r) - (3015 * g) - (582 * b))/0x2000 + 128;
  284. w->v = (uint8_t)(SAT(t));
  285. t = ((2105 * w->rgb[0][0]) + (4128 * w->rgb[0][1]) + (802 * w->rgb[0][2]))/0x2000 + 16;
  286. w->y[0] = (uint8_t)(SATY(t));
  287. t = ((2105 * w->rgb[1][0]) + (4128 * w->rgb[1][1]) + (802 * w->rgb[1][2]))/0x2000 + 16;
  288. w->y[1] = (uint8_t)(SATY(t));
  289. t = ((2105 * w->rgb[2][0]) + (4128 * w->rgb[2][1]) + (802 * w->rgb[2][2]))/0x2000 + 16;
  290. w->y[2] = (uint8_t)(SATY(t));
  291. t = ((2105 * w->rgb[3][0]) + (4128 * w->rgb[3][1]) + (802 * w->rgb[3][2]))/0x2000 + 16;
  292. w->y[3] = (uint8_t)(SATY(t));
  293. }
  294. p->Overlay.ClearFX = BLITFX_ONLYDIFF;
  295. return ERR_NONE;
  296. }
  297. static void Done(console* p)
  298. {
  299. SurfaceFree(p->Planes); 
  300. SurfaceFree(p->Dither);
  301. FreeLibrary(p->Kernel);
  302. free(p->Char);
  303. p->Char = NULL;
  304. }
  305. static void Delete(console* p)
  306. {
  307. free(p->Map);
  308. p->Map = NULL;
  309. }
  310. static int UpdateShow(console* p)
  311. {
  312. CONSOLE_CURSOR_INFO Info;
  313. if (p->Overlay.Show)
  314. {
  315. COORD Size;
  316. p->Own = AllocConsole() != FALSE;
  317.         p->Handle = CreateFile(T("CONOUT$"), GENERIC_READ | GENERIC_WRITE,
  318.                                 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  319.                                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  320. if (p->Handle == INVALID_HANDLE_VALUE)
  321. return ERR_NOT_SUPPORTED;
  322. p->Buffer = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,0,NULL,CONSOLE_TEXTMODE_BUFFER,NULL);
  323. if (p->Buffer == INVALID_HANDLE_VALUE)
  324. return ERR_NOT_SUPPORTED;
  325. Size.X = p->Width;
  326. Size.Y = p->Height;
  327. SetConsoleScreenBufferSize(p->Buffer,Size);
  328. GetConsoleCursorInfo(p->Buffer, &Info);
  329. Info.bVisible = FALSE;
  330. SetConsoleCursorInfo(p->Buffer, &Info);
  331. SetConsoleMode(p->Buffer, 0);
  332. SetConsoleActiveScreenBuffer(p->Buffer);
  333. if (p->SetConsoleOutputCP)
  334. p->SetConsoleOutputCP(850);
  335. if (p->GetConsoleWindow)
  336. SetWindowPos(p->GetConsoleWindow(),HWND_TOP,0,0,1024,1024,SWP_NOMOVE|SWP_SHOWWINDOW);
  337. }
  338. else
  339. {
  340. if (p->Handle != INVALID_HANDLE_VALUE)
  341. {
  342. SetConsoleActiveScreenBuffer(p->Handle);
  343. CloseHandle(p->Buffer);
  344. CloseHandle(p->Handle);
  345. if (p->Own)
  346. FreeConsole();
  347. }
  348. }
  349. return ERR_NONE;
  350. }
  351. static int Lock(console* p, planes Planes, bool_t OnlyAligned )
  352. {
  353. Planes[0] = p->Planes[0];
  354. return ERR_NONE;
  355. }
  356. static int Unlock(console* p )
  357. {
  358. return ERR_NONE;
  359. }
  360. static int Blit(console* p, const constplanes Data, const constplanes DataLast )
  361. {
  362. if (p->Handle != INVALID_HANDLE_VALUE)
  363. {
  364. COORD Pos,Size;
  365. SMALL_RECT Rect;
  366. int n,Row;
  367. CHAR_INFO *Char;
  368. uint8_t *y,*u,*v;
  369. int8_t *y2,*u2,*v2;
  370. int dy[4],du,dv,PalY;
  371. BlitImage(p->Overlay.Soft,p->Planes,Data,DataLast,-1,-1);
  372. y = p->Planes[0];
  373. u = p->Planes[1];
  374. v = p->Planes[2];
  375. y2 = p->Dither[0];
  376. u2 = p->Dither[1];
  377. v2 = p->Dither[2];
  378. if (p->Overlay.Dirty)
  379. {
  380. memset(y2,0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height);
  381. memset(u2,0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);
  382. memset(v2,0,p->Overlay.Output.Format.Video.Pitch*p->Overlay.Output.Format.Video.Height/4);
  383. }
  384. Char = p->Char;
  385. Row = 0;
  386. dy[0] = dy[1] = dy[2] = dy[3] = du = dv = 0;
  387. for (n = p->Width*p->Height;--n>=0;++Char)
  388. {
  389. int Pitch = p->Overlay.Output.Format.Video.Pitch;
  390. palitem* Pal;
  391. dy[0] += y[0] + y2[0];
  392. dy[1] += y[1] + y2[1];
  393. dy[2] += y[Pitch+0] + y2[Pitch+0];
  394. dy[3] += y[Pitch+1] + y2[Pitch+1];
  395. du += u[0] + u2[0];
  396. dv += v[0] + v2[0];
  397. dy[0] = SATY(dy[0]);
  398. dy[1] = SATY(dy[1]);
  399. dy[2] = SATY(dy[2]);
  400. dy[3] = SATY(dy[3]);
  401. du = SAT(du);
  402. dv = SAT(dv);
  403. Pal = GetMap(p,dy[0],dy[1],dy[2],dy[3],du,dv);
  404. y2[0] = (int8_t)((dy[0]-Pal->y[0])>>1);
  405. y2[1] = (int8_t)((dy[1]-Pal->y[1])>>1);
  406. y2[Pitch+0] = (int8_t)((dy[2]-Pal->y[2])>>1);
  407. y2[Pitch+1] = (int8_t)((dy[3]-Pal->y[3])>>1);
  408. PalY = Pal->y[0]+Pal->y[1]+Pal->y[2]+Pal->y[3];
  409. dy[0] = dy[1] = dy[2] = dy[3] = (dy[0]+dy[1]+dy[2]+dy[3]-PalY)/8;
  410. du = (du - Pal->u) >> 1;
  411. dv = (dv - Pal->v) >> 1;
  412. if (PalY < 48*4)
  413. {
  414. du /= 2;
  415. dv /= 2;
  416. if (PalY < 32*4)
  417. {
  418. du /= 4;
  419. dv /= 4;
  420. }
  421. }
  422. u2[0] = (int8_t)du;
  423. v2[0] = (int8_t)dv;
  424. Char->Attributes = Pal->col;
  425. Char->Char.AsciiChar = Pal->ch;
  426. y += 2;
  427. ++u;
  428. ++v;
  429. y2 += 2;
  430. ++u2;
  431. ++v2;
  432. if (++Row == p->Width)
  433. {
  434. Row = 0;
  435. y += p->Overlay.Output.Format.Video.Pitch;
  436. y2 += p->Overlay.Output.Format.Video.Pitch;
  437. }
  438. }
  439. Size.X = p->Width;
  440. Size.Y = p->Height;
  441. Pos.X = 0;
  442. Pos.Y = 0;
  443. Rect.Left = 0;
  444. Rect.Top = 0;
  445. Rect.Right = (int16_t)(p->Width-1);
  446. Rect.Bottom = (int16_t)(p->Height-1);
  447. WriteConsoleOutput(p->Buffer, p->Char, Size, Pos, &Rect);
  448. }
  449. return ERR_NONE;
  450. }
  451. static int Create(console* p)
  452. {
  453. p->Overlay.Primary = 0;
  454. p->Overlay.Output.Format.Video.Width = 80*2;
  455. p->Overlay.Output.Format.Video.Height = 50*2;
  456. p->Overlay.Output.Format.Video.Direction = 0;
  457. p->Overlay.Output.Format.Video.Aspect = ASPECT_ONE;
  458. p->Overlay.Output.Format.Video.Pitch = p->Overlay.Output.Format.Video.Width;
  459. p->Overlay.Output.Format.Video.Pixel.Flags = PF_YUV420|PF_16ALIGNED;
  460. FillInfo(&p->Overlay.Output.Format.Video.Pixel);
  461. p->Overlay.Init = Init;
  462. p->Overlay.Done = Done;
  463. p->Overlay.Blit = Blit;
  464. p->Overlay.UpdateShow = UpdateShow;
  465. p->Overlay.Lock = Lock;
  466. p->Overlay.Unlock = Unlock;
  467. return ERR_NONE;
  468. }
  469. static const nodedef Console = 
  470. {
  471. sizeof(console)|CF_GLOBAL,
  472. CONSOLE_ID,
  473. OVERLAY_CLASS,
  474. PRI_DEFAULT-15,
  475. (nodecreate)Create,
  476. (nodedelete)Delete,
  477. };
  478. void OverlayConsole_Init() 
  479. NodeRegisterClass(&Console);
  480. }
  481. void OverlayConsole_Done()
  482. {
  483. NodeUnRegisterClass(CONSOLE_ID);
  484. }
  485. #endif