/*****************************************************************************/

/*
 *      osdFunc.c -- REALmagic Celeste Application
 *
 *      Copyright (C) 1999-2000 Sigma Designs
 *
 *      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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*****************************************************************************/

#include "remote.h"
#include "bitmaps/palette.h"
#include "bitmaps/back.h"
#include "bitmaps/next.h"
#include "bitmaps/pause.h"
#include "bitmaps/play.h"
//#include "bitmaps/reading.h"
#include "bitmaps/reverse.h"
#include "bitmaps/skip.h"
//#include "bitmaps/still.h"
#include "bitmaps/stop.h"
#include "bitmaps/close.h"
#include "bitmaps/open.h"
#include "bitmaps/stepff.h"
#include "bitmaps/steprw.h"
#include "bitmaps/slowff.h"
#include "bitmaps/slowrw.h"
#include "bitmaps/loading.h"
#ifdef PRINCETON
#include "bitmaps/Image6.h"
#endif

BOOL checkPassword(INFO *pInfo);

unsigned char *pictArr[15] = { NULL,
                               play_osd,
                               pause_osd,
                               stop_osd,
                               open_osd,
                               close_osd,
                               reverse_osd,
                               next_osd,
                               back_osd,
                               skip_osd,
                               stepff_osd,
                               steprw_osd,
                               slowrw_osd,
                               slowff_osd,
                               loading_osd };

extern HDTV_PARAMS Hdtv_Params[];
extern RMAFONT _RMA_12x24;
extern RMAFONT _RMA_7x14;
extern int osdtID;
extern float g_sw;
extern float g_sh;
extern DWORD g_OutputMode;

#define MAX_HEIGHT    360
#define MAX_WIDTH     720
#define RIGHT_INDENT  72
#define TOP_INDENT    60
#define BOTTOM_INDENT 60
#define FF_SLOW_LEFT_INDENT  8
#define FF_SLOW_RIGHT_INDENT 42
#define FF_SLOW_TOP_INDENT   5
#define OSD_PICTS_FONT _RMA_12x24


ULONG textToBitmap(IRma *pIRma,
                   unsigned char **bmp,
                   char *string,
                   RMAYUVENTRY *palette,
                   PRMAFONT font) {
	RMAYUVENTRY *pPalette;
	RMARECT rect;
	RMAALIGNMENT al;
	RMASIZE textsize;
	ULONG size1;
	PBYTE tmp;

	pPalette = (RMAYUVENTRY *)palette;

////////////////////////////////////////////////////////////////////

	RmaGetTextSize(string, &textsize, font, 0);
	IRma_CreateDC(pIRma, COLORDEPTH_EIGHT_BPP, (WORD) (textsize.width + 4), (WORD) (textsize.height + 4), 255);
	IRma_SetPalette(pIRma, (HRMABITMAP) NULL, pPalette, 0, 256);
	IRma_SetPen(pIRma, RMAPEN_SOLID, 0x2a, 1);
	IRma_SetTextStyle(pIRma, RMAOPAQUE);
	IRma_SetTextColor(pIRma, 0x2a);
	IRma_SetTextBackground(pIRma, 0x01);
	IRma_SetFont(pIRma, font);

	rect.left = 0;
	rect.right = textsize.width + 4;
	rect.top = 0;
	rect.bottom = textsize.height + 4;

	al = ALIGNMIDDLE|ALIGNCENTER;

	IRma_RMADrawText(pIRma, string, rect, al, 0);
	IRma_LockRmaOSD(pIRma, (HRMABITMAP) NULL, (PBYTE *)(&tmp), &size1);

	if((*bmp = (unsigned char *)OSCelMalloc(size1)))
		memcpy((void *)(*bmp), (void *)tmp, size1);
	else
		size1 = 0;
	IRma_DestroyDC(pIRma);
	return size1;
}

ULONG addPict(IRma *pIRma,
              unsigned char *pict,
              unsigned char *p1,
              unsigned char *p2) {

	ULONG size;
	DWORD width, height, Width;
	RMAYUVENTRY *pPalette, onePE[1];
	RMAPOINT pos1;
	PBYTE tmp;
	RMARECT rect;

	if(!pict)
		return 0;

	if(p1 && p2) {
	
		onePE[0].Alpha = 0;
		onePE[0].yuvY = 0x0;
		onePE[0].yuvCr = 0x0;
		onePE[0].yuvCb = 0x0;

		width = (((DWORD)(p1[4])) << 8) | p1[5];
		Width = ((DWORD)p2[4] << 8) | (DWORD)p2[5];
		if(Width < width)
			Width = width;

		IRma_CreateDC(pIRma, COLORDEPTH_EIGHT_BPP, (WORD) Width, (WORD) MAX_HEIGHT, 255);
		IRma_GetPaletteFromBitmap(pIRma,
		                          (HRMABITMAP)p1,
		                          (PBYTE *)(&pPalette), (LONG *)(&size));
		IRma_SetPalette(pIRma, (HRMABITMAP)NULL, pPalette, 0, 255);
		IRma_SetPalette(pIRma, (HRMABITMAP)NULL, onePE, 255, 1);

		height = (((DWORD)(p1[6])) << 8) | p1[7];
		pos1.x = Width - width;
		pos1.y = 0;
		tmp = p1;
		IRma_LockRmaOSD(pIRma, (HRMABITMAP)tmp, &tmp, &size);
		rect.left = 0;
		rect.right = width - 1;
		rect.top = 0;
		rect.bottom = height - 1;
		RmaBitBlt(NULL, pIRma, (HRMABITMAP)tmp, (HRMABITMAP)NULL, pos1, rect, RMASRCCOPY, 0);
		IRma_UnLockRmaOSD(pIRma, (HRMABITMAP)tmp, &tmp, &size);

		width = (((DWORD)(p2[4])) << 8) | p2[5];
		height = (((DWORD)(p2[6])) << 8) | p2[7];
		pos1.x = Width - width;
		pos1.y = MAX_HEIGHT - height;
		tmp = p2;
		IRma_LockRmaOSD(pIRma, (HRMABITMAP)tmp, &tmp, &size);
		rect.left = 0;
		rect.right = width - 1;
		rect.top = 0;
		rect.bottom = height - 1;
		RmaBitBlt(NULL, pIRma, (HRMABITMAP)tmp, (HRMABITMAP)NULL, pos1, rect, RMASRCCOPY, 0);
		IRma_UnLockRmaOSD(pIRma, (HRMABITMAP)tmp, &tmp, &size);

		IRma_LockRmaOSD(pIRma, (HRMABITMAP)NULL, &tmp, &size);
		memcpy((void *)pict, (void *)tmp, size);
		IRma_DestroyDC(pIRma);
	}
	else if(!p1 && !p2) {
		pict[0] = 0;
		size = 0;
	}
	else {
		if(p1) tmp = p1;
		else tmp = p2;

		width = (((DWORD)(tmp[4])) << 8) | tmp[5];
		height = (((DWORD)(tmp[6])) << 8) | tmp[7];
		size = width * height + 1032;
		memcpy((void *)pict, (void *)tmp, size);
	}
	return size;
}

void inputSearch(INFO *pInfo) {
	float scrH, scrW;
	unsigned char *bmp, *bmp1 = NULL, *bmp2 = NULL;
	char str[45], buf[1], count, state, str1[13], *pb, *pe;
	DWORD x, y, value;
	WORD reg_tmp;
	OSD_WND wnd;

	if(!(bmp = (unsigned char *)OSCelMalloc(MAX_WIDTH * MAX_HEIGHT + 1032))) {
		DPRINT(("Not enough memory\n"));
		pInfo->dwSearch = 0;
		buf[0] = SHOW_SEARCH;
		OSPostMessage(pInfo->msgQueue, buf, 1);
		return;
	}

	reg_tmp = (WORD)FMPGet(FMPI_CURRENT_DOMAIN);

	memset(&wnd, 0, sizeof(OSD_WND));
	scrH = (pInfo->IHdtv_c) ? (Hdtv_Params[pInfo->IHdtv_c - 1].VideoHeight / 480.0f) : 1.0f;
	scrW = (pInfo->IHdtv_c) ? (Hdtv_Params[pInfo->IHdtv_c - 1].VideoWidth / 720.0f) : 1.0f;
	memset(str1, '_', 12);
	count = 1;
	pb = str1 + 1; pe = str1 + 3;
	if(pInfo->bSearch == 2)
		state = -1;
	else if(pInfo->bSearch == 3) {
		state = -2;
		count = 4;
		pb = str1; pe = str1 + 5;
	}
	else if(pInfo->bSearch == 1 && (pInfo->bDiscType == FMPC_VCD || pInfo->bDiscType == FMPC_SVCD)) {
		state = 0;
		count = 4;
		pb = str1; pe = str1 + 5;
	}
	else
		state = 0;
	str1[12] = 0;
	if(pInfo->symbol != '_') {
		*pe = pInfo->symbol;
		count--; pb++; pe++;
	}
	do {
		memset(str, 0, 45);
		if(!state) {
			if(pInfo->bDiscType == FMPC_CDDA ||
			   pInfo->bDiscType == FMPC_VCD ||
			   pInfo->bDiscType == FMPC_SVCD)
				sprintf(str, "TRACK SEARCH: ");
			else
				sprintf(str, "TITLE SEARCH: ");
			memcpy(str + 14, pb, 2);
			if(pInfo->bDiscType == FMPC_VCD || pInfo->bDiscType == FMPC_SVCD)
				memcpy(str + 16, pb + 2, 3);
		}
		else if(state == 1) {
			sprintf(str, "CHAPTER SEARCH: ");
			memcpy(str + 16, pb, 3);
		}
		else if(state == 2) {
			sprintf(str, "TIME SEARCH:\n__:__:");
			memcpy(str + 13, pb, 2);
			memcpy(str + 16, pb + 2, 2);
			memcpy(str + 19, pb + 4, 2);
		}
		else if(state < 0) {
			memcpy(str, pb, (-3 * state - 1));
		}
		if(bmp1)
			OSCelFree(bmp1);
		value = (DWORD)textToBitmap(pInfo->pIRma, &bmp1, str, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
		if(pInfo->osdFlag &&
		   reg_tmp != VMGM_DOM && reg_tmp != VTSM_DOM) {
			unsigned char *tmp = (unsigned char *)(&(pInfo->dwTime));
			if(pInfo->bDiscType == FMPC_CDDA ||
			   pInfo->bDiscType == FMPC_VCD ||
			   pInfo->bDiscType == FMPC_SVCD)
				sprintf(str, "Track %6d\nTime %0x:%02x:%02x",
				        (int)FMPGet(FMPI_CURRENT_TRACK),
				        (int)tmp[0], (int)tmp[1], (int)tmp[2]);
			else
				sprintf(str, "Title     %02d\nChapter  %03d\nTime %0x:%02x:%02x",
				        (int)FMPGet(FMPI_CURRENT_TITLE),
				        (int)FMPGet(FMPI_CURRENT_CHAPTER), 
				        (int)tmp[0], (int)tmp[1], (int)tmp[2]);
			value = textToBitmap(pInfo->pIRma, &bmp2, str, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
		}
		else
			bmp2 = NULL;
		value = addPict(pInfo->pIRma, bmp, bmp1, bmp2);
		DISPLAY_OSD(pInfo->pIOsd, bmp, (720 - RIGHT_INDENT), TOP_INDENT, RIGHT_TOP, scrW, scrH);
		if(bmp2) {
			OSCelFree(bmp2);
#ifdef PRINCETON
			if(value = textToBitmap(pInfo->pIRma, &bmp2, str, (RMAYUVENTRY *)Palette, &_RMA_7x14)) {
				unsigned char *lcdP0 = NULL, *lcdP1 = NULL;
				rmaOsd2monoLCD(bmp2, &lcdP0, &lcdP1, 0x2a);
				DrawImage(lcdP0, lcdP1);
				if(lcdP0)
					OSCelFree(lcdP0);
				if(lcdP1)
					OSCelFree(lcdP1);
				OSCelFree(bmp2);
			}
#endif
		}
//		SET_HIGHLIGHT(pInfo->pIOsd, &wnd, scrW, scrH);
		if(OSGetMessage(pInfo->osdMsgQ, buf, 1) == ERROR) {
			DPRINT(("osdManager: error during reading message queue \n"));
			return;
		}
		switch(buf[0]) {
			case ZERO:
			case ONE:
			case TWO:
			case THREE:
			case FOUR:
			case FIVE:
			case SIX:
			case SEVEN:
			case EIGHT:
			case NINE:
				if(count >= 0) {
					*pe = buf[0];
					count--; pb++; pe++;
				}
				break;
			case ENT:
				value = 0;
				for(x = 0; x < 12; x++)
					str1[x] = ((str1[x] - ZERO) > 9) ? 0 : (str1[x] - ZERO);
				if(state == -2 ||
				   (!state && (pInfo->bDiscType == FMPC_SVCD || pInfo->bDiscType == FMPC_VCD))) {
					for (x = 4, y = 1; y < 100000; x--, y *= 10)
						value += y * pb[x];
				}
				else if(state < 2) {
					value = pe[-1] + pe[-2] * 10 + pe[-3] * 100;
				}
				else {
					for(x = 0; x < 6; x += 2)
						value |= ((pb[x] << 4 | pb[x + 1]) << (x << 2));
/*
					DWORD a = pe[-1] + pe[-2] * 10;
					value = a << 16;
					a = pb[3] + pb[2] * 10;
					value |= (a << 8);
					a = pb[1] + pb[0] * 10;
					value |= a;
*/
				}
				if(value) {
					if(state > -1)
						pInfo->dwSearch = (state << 24) | value;
					else
						pInfo->dwSearch = value;
				}
				else
					pInfo->dwSearch = 0;
				if(state < -1) {
					if(pInfo->pIOsd) {
						IOsd_Off(pInfo->pIOsd);
//						IOsd_Flush(pInfo->pIOsd);
					}
				}
				state = 3;
				break;
			case VGA_TV:
				if((state < 1 && count < 1 && state > -2) ||
				   (state == 1 && count < 2) ||
				   (state == 2 && count < 5) ||
				   ((state == -2 || (!state && (pInfo->bDiscType == FMPC_SVCD || pInfo->bDiscType == FMPC_VCD))) && count < 4)) {
					count++; pe--; pb--;
					*pe = '_';
				}
				break;
			case SHOW_SEARCH:
				state++;
				memset(str1, '_', 12);
				if(state == 1) {
					if(pInfo->bDiscType == FMPC_CDDA ||
					   pInfo->bDiscType == FMPC_VCD ||
					   pInfo->bDiscType == FMPC_SVCD)
						state++;
					else {
						count = 2;
						pb = str1; pe = str1 + 3;
					}
				}
				if(state == 2) {
					pb = str1; pe = str1 + 6;
					count = 5;
				}
				else
					pInfo->dwSearch = 0;
				break;		
			default:
				break;
		}
	} while(state < 3);
	if(bmp)
		OSCelFree(bmp);
	if(bmp1)
		OSCelFree(bmp1);
	buf[0] = SHOW_SEARCH;
	OSPostMessage(pInfo->msgQueue, buf, 1);
	return;
}

void changeRes(INFO *pInfo) {

	float scrH, scrW;
	unsigned char *bmp;
	char str[45], buf[1];
	DWORD x, y, size, VideoHeight, VFreq;
	OSD_WND wnd;
#ifdef PRINCETON
	PBYTE p0, p1;
	float arrHSpeed[12], hSpeed = 0;

	p0 = (PBYTE)OSCelMalloc(8 * 64);
	p1 = (PBYTE)OSCelMalloc(8 * 64);
#endif

START:
	memset(&wnd, 0, sizeof(OSD_WND));
	memset(str, 0, 45);
	scrH = (pInfo->IHdtv_c) ? (Hdtv_Params[pInfo->IHdtv_c - 1].VideoHeight / 480.0f) : 1.0f;
	scrW = (pInfo->IHdtv_c) ? (Hdtv_Params[pInfo->IHdtv_c - 1].VideoWidth / 720.0f) : 1.0f;
	if(!pInfo->IHdtv_c || !pInfo->pIHdtv) {
		DWORD tmp = FMPGet(FMPI_VIDEOOUT) &
		            (FMPV_VIDEOOUT_STANDARDTV_MASK | FMPV_VIDEOOUT_TV_AS_SOURCE);
		if(tmp & FMPV_VIDEOOUT_TV_AS_SOURCE)
			sprintf(str, "MULTISYSTEM TV");
		else if((tmp & FMPV_VIDEOOUT_STANDARDTV_MASK) == FMPV_VIDEOOUT_NTSC)
			sprintf(str, "NTSC TV");
		else if((tmp & FMPV_VIDEOOUT_STANDARDTV_MASK) == FMPV_VIDEOOUT_PAL)
			sprintf(str, "PAL TV");
		else
			sprintf(str, "TV OUTPUT");
		pInfo->IHdtv_c = 0;
	}
	else {
		VideoHeight = Hdtv_Params[pInfo->IHdtv_c - 1].VideoHeight;
		VFreq = Hdtv_Params[pInfo->IHdtv_c - 1].VFreq / 100;
		sprintf(str, "Vert resolution %ld\nFPS %ld", VideoHeight, VFreq);
#ifdef PRINCETON
		memset(arrHSpeed, 0, 12 * sizeof(float));
		for(x = 0; x < HDTV_PAR_SIZE; x++)
			arrHSpeed[(Hdtv_Params[x].VideoHeight / 60) + (Hdtv_Params[x].VFreq / 2400) - 10] = Hdtv_Params[x].HFreq / 1000.f;
#endif
	}
	size = (DWORD)textToBitmap(pInfo->pIRma, &bmp, str, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
	x = ((DWORD)bmp[4] << 8) | (DWORD)bmp[5];
	x = (720 - x) >> 1;
	y = ((DWORD)bmp[6] << 8) | (DWORD)bmp[7];
	y = (480 - y) >> 1;
	DISPLAY_OSD(pInfo->pIOsd, bmp, x, y, LEFT_TOP, scrW, scrH);
	SET_HIGHLIGHT(pInfo->pIOsd, &wnd, scrW, scrH);
#ifdef PRINCETON
	if(pInfo->IHdtv_c && pInfo->pIHdtv) {
		sprintf(str, "%dp\n%3dFPS\n%#2.1fKHz", VideoHeight, VFreq, Hdtv_Params[pInfo->IHdtv_c - 1].HFreq / 1000.f);
	}
	size = (DWORD)textToBitmap(pInfo->pIRma, &bmp, str, (RMAYUVENTRY *)Palette, &_RMA_7x14);
	rmaOsd2monoLCD(bmp, &p0, &p1, 0x2a);
	DrawImage(p0, p1);
#endif
	do {
		if(OSGetMessage(pInfo->osdMsgQ, buf, 1) == ERROR) {
			DPRINT(("osdManager: error during reading message queue \n"));
			return;
		}
		if(pInfo->IHdtv_c) {
			switch(buf[0]) {
				case UP:
					if(VideoHeight == 960)
						VideoHeight = 480;
					else
						VideoHeight += 240;
					break;
				case DOWN:
					if(VideoHeight == 480)
						VideoHeight = 960;
					else
						VideoHeight -= 240;
					break;
				case LEFT:
					if(VFreq == 72)
						VFreq = 60;
					else if(VFreq == 60)
						VFreq = 120;
					else
						VFreq -= 24;
					break;
				case RIGHT:
					if(VFreq == 120)
						VFreq = 60;
					else if(VFreq == 60)
						VFreq = 72;
					else
						VFreq += 24;
					break;
				case VGA_TV:
					VideoHeight = Hdtv_Params[pInfo->IHdtv_c - 1].VideoHeight;
					VFreq = Hdtv_Params[pInfo->IHdtv_c - 1].VFreq / 100;
				default:
					break;
			}
			memset(str, 0, 45);
			sprintf(str, "Vert resolution %ld\nFPS %ld", VideoHeight, VFreq);
			size = (DWORD)textToBitmap(pInfo->pIRma, &bmp, str, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
			x = ((DWORD)bmp[4] << 8) | (DWORD)bmp[5];
			x = (720 - x) >> 1;
			y = ((DWORD)bmp[6] << 8) | (DWORD)bmp[7];
			y = (480 - y) >> 1;
			DISPLAY_OSD(pInfo->pIOsd, bmp, x, y, LEFT_TOP, scrW, scrH);
			SET_HIGHLIGHT(pInfo->pIOsd, &wnd, scrW, scrH);
#ifdef PRINCETON
			{
				memset(str, 0, 45);
				sprintf(str, "%dp\n%3dFPS\n", VideoHeight, VFreq);
				hSpeed = arrHSpeed[(VideoHeight / 60 - 8) + (VFreq / 24) - 2];
				if(hSpeed)
					sprintf(str + 12, "%#2.1fKHz", hSpeed);
				else
					sprintf(str + 12, "??.?KHz");
				size = (DWORD)textToBitmap(pInfo->pIRma, &bmp, str, (RMAYUVENTRY *)Palette, &_RMA_7x14);
				rmaOsd2monoLCD(bmp, &p0, &p1, 0x2a);
				DrawImage(p0, p1);
			}
#endif
		}
	} while(buf[0] != SHOW_RES);
	if(pInfo->IHdtv_c &&
	   ((VideoHeight != Hdtv_Params[pInfo->IHdtv_c - 1].VideoHeight) ||
	    ((VFreq * 100) != Hdtv_Params[pInfo->IHdtv_c - 1].VFreq))) {
		y = 0;
		for(x = 0; x < HDTV_PAR_SIZE; x++) {
			if(VideoHeight == Hdtv_Params[x].VideoHeight &&
			   VFreq == Hdtv_Params[x].VFreq / 100) {
				pInfo->IHdtv_c = x + 1;
				y = 1;
				break;
			}
		}
		if(!y) {
			memset(str, 0, 45);
			sprintf(str, "Incorrect settings\nPress MODE");
			size = (DWORD)textToBitmap(pInfo->pIRma, &bmp, str, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
			x = ((DWORD)bmp[4] << 8) | (DWORD)bmp[5];
			x = (720 - x) >> 1;
			y = ((DWORD)bmp[6] << 8) | (DWORD)bmp[7];
			y = (480 - y) >> 1;
			DISPLAY_OSD(pInfo->pIOsd, bmp, x, y, LEFT_TOP, scrW, scrH);
			SET_HIGHLIGHT(pInfo->pIOsd, &wnd, scrW, scrH);
#ifdef PRINCETON
			memset(str, 0, 45);
			sprintf(str, "Incorrect\nsettings");
			size = (DWORD)textToBitmap(pInfo->pIRma, &bmp, str, (RMAYUVENTRY *)Palette, &_RMA_7x14);
			rmaOsd2monoLCD(bmp, &p0, &p1, 0x2a);
			DrawImage(p0, p1);
#endif
			do {
				if(OSGetMessage(pInfo->osdMsgQ, buf, 1) == ERROR) {
					DPRINT(("osdManager: error during reading message queue \n"));
					return;
				}
			} while(buf[0] != SHOW_RES);
			goto START;
		}
		if(pInfo->pIOsd) {
			IOsd_Off(pInfo->pIOsd);
//			IOsd_Flush(pInfo->pIOsd);
		}
		IHdtv_SetMode(pInfo->pIHdtv, &(Hdtv_Params[pInfo->IHdtv_c - 1]), g_OutputMode);
#ifdef PRINCETON
		if(p0) OSCelFree(p0);
		if(p1) OSCelFree(p1);
#endif
		return;
	}
	if(pInfo->pIOsd) {
		IOsd_Off(pInfo->pIOsd);
//		IOsd_Flush(pInfo->pIOsd);
	}
#ifdef PRINCETON
	if(p0) OSCelFree(p0);
	if(p1) OSCelFree(p1);
#endif
	return;
}

void getLanguage(WORD code, char *str) {
	char fl = (((code >> 8) & 0xff) - 32), ll = ((code & 0xff) - 32);
	switch(fl) {
		case 'A':
			switch(ll) {
				case 'A': sprintf(str, "AFAR"); break;
				case 'B': sprintf(str, "ABKHAZIAN"); break;
				case 'F': sprintf(str, "AFRIKAANS"); break;
				case 'M': sprintf(str, "AMHARIC"); break;
				case 'R': sprintf(str, "ARABIC"); break;
				case 'S': sprintf(str, "ASSAMESE"); break;
				case 'Y': sprintf(str, "AYMARA"); break;
				case 'Z': sprintf(str, "AZERBAIJANI"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'B':
			switch(ll) {
				case 'A': sprintf(str, "BASHKIR"); break;
				case 'E': sprintf(str, "BYELORUSSIAN"); break;
				case 'G': sprintf(str, "BULGARIAN"); break;
				case 'H': sprintf(str, "BIHARI"); break;
				case 'I': sprintf(str, "BISLAMA"); break;
				case 'N': sprintf(str, "BENGALI or BANGLA"); break;
				case 'O': sprintf(str, "TIBETAN"); break;
				case 'R': sprintf(str, "BRETON"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'C':
			switch(ll) {
				case 'A': sprintf(str, "CATALAN"); break;
				case 'O': sprintf(str, "CORSICAN"); break;
				case 'S': sprintf(str, "CZECH"); break;
				case 'Y': sprintf(str, "WELSH"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'D':
			switch(ll) {
				case 'A': sprintf(str, "DANISH"); break;
				case 'E': sprintf(str, "GERMAN"); break;
				case 'Z': sprintf(str, "BHUTANI"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'E':
			switch(ll) {
				case 'L': sprintf(str, "GREEK"); break;
				case 'N': sprintf(str, "ENGLISH"); break;
				case 'O': sprintf(str, "ESPERANTO"); break;
				case 'S': sprintf(str, "SPANISH"); break;
				case 'T': sprintf(str, "ESTONIAN"); break;
				case 'U': sprintf(str, "BASQUE"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'F':
			switch(ll) {
				case 'A': sprintf(str, "PERSIAN"); break;
				case 'I': sprintf(str, "FINNISH"); break;
				case 'J': sprintf(str, "FIJI"); break;
				case 'O': sprintf(str, "FAROESE"); break;
				case 'R': sprintf(str, "FRENCH"); break;
				case 'Y': sprintf(str, "FRISIAN"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'G':
			switch(ll) {
				case 'A': sprintf(str, "IRISH"); break;
				case 'D': sprintf(str, "SCOTS GAELIC"); break;
				case 'L': sprintf(str, "GALICIAN"); break;
				case 'N': sprintf(str, "GUARANI"); break;
				case 'U': sprintf(str, "GUJARATI"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'H':
			switch(ll) {
				case 'A': sprintf(str, "HAUSA"); break;
				case 'E': sprintf(str, "HEBREW"); break;
				case 'I': sprintf(str, "HINDI"); break;
				case 'R': sprintf(str, "CROATIAN"); break;
				case 'U': sprintf(str, "HUNGARIAN"); break;
				case 'Y': sprintf(str, "ARMENIAN"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'I':
			switch(ll) {
				case 'A': sprintf(str, "INTERLINGUA"); break;
				case 'D': sprintf(str, "INDONESIAN"); break;
				case 'E': sprintf(str, "INTERLINGUE"); break;
				case 'K': sprintf(str, "INUPIAK"); break;
				case 'S': sprintf(str, "ICELANDIC"); break;
				case 'T': sprintf(str, "ITALIAN"); break;
				case 'U': sprintf(str, "INUKTITUT"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'J':
			switch(ll) {
				case 'A': sprintf(str, "JAPANESE"); break;
				case 'V': sprintf(str, "JAVANESE"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'K':
			switch(ll) {
				case 'A': sprintf(str, "GEORGIAN"); break;
				case 'K': sprintf(str, "KAZAKH"); break;
				case 'L': sprintf(str, "GREENLANDIC"); break;
				case 'M': sprintf(str, "CAMBODIAN"); break;
				case 'N': sprintf(str, "KANNADA"); break;
				case 'O': sprintf(str, "KOREAN"); break;
				case 'S': sprintf(str, "KASHMIRI"); break;
				case 'U': sprintf(str, "KURDISH"); break;
				case 'Y': sprintf(str, "KIRGHIZ"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'L':
			switch(ll) {
				case 'A': sprintf(str, "LATIN"); break;
				case 'N': sprintf(str, "LINGALA"); break;
				case 'O': sprintf(str, "LAOTHIAN"); break;
				case 'T': sprintf(str, "LITHUANIAN"); break;
				case 'V': sprintf(str, "LATVIAN or LETTISH"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'M':
			switch(ll) {
				case 'G': sprintf(str, "MALAGASY"); break;
				case 'I': sprintf(str, "MAORI"); break;
				case 'K': sprintf(str, "MACEDONIAN"); break;
				case 'L': sprintf(str, "MALAYALAM"); break;
				case 'N': sprintf(str, "MONGOLIAN"); break;
				case 'O': sprintf(str, "MOLDAVIAN"); break;
				case 'R': sprintf(str, "MARATHI"); break;
				case 'S': sprintf(str, "MALAY"); break;
				case 'T': sprintf(str, "MALTESE"); break;
				case 'Y': sprintf(str, "BURMESE"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'N':
			switch(ll) {
				case 'A': sprintf(str, "NAURU"); break;
				case 'E': sprintf(str, "NEPALI"); break;
				case 'L': sprintf(str, "DUTCH"); break;
				case 'O': sprintf(str, "NORWEGIAN"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'O':
			switch(ll) {
				case 'C': sprintf(str, "OCCITAN"); break;
				case 'M': sprintf(str, "AFAN"); break;
				case 'R': sprintf(str, "ORIYA"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'P':
			switch(ll) {
				case 'A': sprintf(str, "PUNJABI"); break;
				case 'L': sprintf(str, "POLISH"); break;
				case 'S': sprintf(str, "PASHTO or PUSHTO"); break;
				case 'T': sprintf(str, "PORTUGUESE"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'Q':
			if(ll == 'U')
				sprintf(str, "QUECHUA");
			else
				sprintf(str, "UNKNOWN");
			break;
		case 'R':
			switch(ll) {
				case 'M': sprintf(str, "RHAETO-ROMANCE"); break;
				case 'N': sprintf(str, "KURUNDI"); break;
				case 'O': sprintf(str, "ROMANIAN"); break;
				case 'U': sprintf(str, "RUSSIAN"); break;
				case 'W': sprintf(str, "KINYARWANDA"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'S':
			switch(ll) {
				case 'A': sprintf(str, "SANSKRIT"); break;
				case 'D': sprintf(str, "SINDHI"); break;
				case 'G': sprintf(str, "SANGHO"); break;
				case 'H': sprintf(str, "SERBO-CROATIAN"); break;
				case 'I': sprintf(str, "SINGHALESE"); break;
				case 'K': sprintf(str, "SLOVAK"); break;
				case 'L': sprintf(str, "SLOVENIAN"); break;
				case 'M': sprintf(str, "SAMOAN"); break;
				case 'N': sprintf(str, "SHONA"); break;
				case 'O': sprintf(str, "SOMALI"); break;
				case 'Q': sprintf(str, "ALBANIAN"); break;
				case 'R': sprintf(str, "SERBIAN"); break;
				case 'S': sprintf(str, "SISWATI"); break;
				case 'T': sprintf(str, "SESOTHO"); break;
				case 'U': sprintf(str, "SUNDANESE"); break;
				case 'V': sprintf(str, "SWEDISH"); break;
				case 'W': sprintf(str, "SWAHILI"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'T':
			switch(ll) {
				case 'A': sprintf(str, "TAMIL"); break;
				case 'E': sprintf(str, "TELUGU"); break;
				case 'G': sprintf(str, "TAJIK"); break;
				case 'H': sprintf(str, "THAI"); break;
				case 'I': sprintf(str, "TIGRINYA"); break;
				case 'K': sprintf(str, "TURKMEN"); break;
				case 'L': sprintf(str, "TAGALOG"); break;
				case 'N': sprintf(str, "SETSWANA"); break;
				case 'O': sprintf(str, "TONGA"); break;
				case 'R': sprintf(str, "TURKISH"); break;
				case 'S': sprintf(str, "TSONGA"); break;
				case 'T': sprintf(str, "TATAR"); break;
				case 'W': sprintf(str, "TWI"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'U':
			switch(ll) {
				case 'G': sprintf(str, "UIGUR"); break;
				case 'K': sprintf(str, "UKRAINIAN"); break;
				case 'R': sprintf(str, "URDU"); break;
				case 'Z': sprintf(str, "UZBEK"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'V':
			switch(ll) {
				case 'I': sprintf(str, "VIETNAMESE"); break;
				case 'O': sprintf(str, "VOLAPUK"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'W':
			if(ll == 'O')
				sprintf(str, "WOLOF");
			else
				sprintf(str, "UNKNOWN");
			break;
		case 'X':
			if(ll == 'H')
				sprintf(str, "XHOSA");
			else
				sprintf(str, "UNKNOWN");
			break;
		case 'Y':
			switch(ll) {
				case 'I': sprintf(str, "YIDDISH"); break;
				case 'O': sprintf(str, "YORUBA"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		case 'Z':
			switch(ll) {
				case 'A': sprintf(str, "ZHUANG"); break;
				case 'H': sprintf(str, "CHINESE"); break;
				case 'U': sprintf(str, "ZULU"); break;
				default: sprintf(str, "UNKNOWN"); break;
			}
			break;
		default:
			sprintf(str, "UNKNOWN");
			break;
	}
}

void formString(char *tmp, char stPictFlag) {

	char *p;
	DWORD sp;

	memset(tmp, 0, sizeof(tmp));

	if(stPictFlag == 20) {
		sp = FMPGet(FMPI_SUBPICTURE_ON);
		if(sp) {
			SPST_ATR pSpst_Atr;
			if(!(DVDQueryAttribute(DVDI_SPST_ATR, (DWORD)(&pSpst_Atr)))) {
				sp = FMPGet(FMPI_CURRENT_SUBPICT_STREAM);
				sprintf(tmp, "Subtitles: %2d\n", (int)sp + 1);
				getLanguage(pSpst_Atr.wLanguageCode[sp], (char *)(tmp + 14));
/*
				for(p = tmp + 14; (p < tmp + 100) && (*p); p++)
					;
				switch(pSpst_Atr.wLanguageCodeExtension[sp]) {
					case 0x01: sprintf(p, "\nCaption with normal size character"); break;
					case 0x02: sprintf(p, "\nCaption with bigger size character"); break;
					case 0x03: sprintf(p, "\nCaption for children"); break;
					case 0x05: sprintf(p, "\nClosed caption with normal size character"); break;
					case 0x06: sprintf(p, "\nClosed caption with bigger size character"); break;
					case 0x07: sprintf(p, "\nClosed caption for children"); break;
					case 0x09: sprintf(p, "\nForced caption"); break;
					case 0x0d: sprintf(p, "\nDirector's comments with normal size character"); break;
					case 0x0e: sprintf(p, "\nDirector's comments with bigger size character"); break;
					case 0x0f: sprintf(p, "\nDirector's comments for children"); break;
					default: break;
				}
*/
			}
			else
				sprintf(tmp, "Subtitles: FAILED");
		}
		else
			sprintf(tmp, "Subtitles: OFF");
	}
	else if(stPictFlag == 21) {
		AST_ATR pAst_Atr;
		if(!(DVDQueryAttribute(DVDI_AST_ATR, (DWORD)(&pAst_Atr)))) {
			sp = FMPGet(FMPI_CURRENT_AUDIO_STREAM);
			sprintf(tmp, "Language: %d\n", (int)sp + 1);
			getLanguage(pAst_Atr.wLanguageCode[sp], (char *)(tmp + 12));
			for(p = tmp + 12; (p < tmp + 100) && (*p); p++)
				;
			switch(pAst_Atr.bAudioCodingMode[sp]) {
				case 0: sprintf(p, "\nDolby AC-3"); p += 11; break;
				case 2: sprintf(p, "\nMPEG-1"); p += 7; break;
				case 3: sprintf(p, "\nMPEG-2\nwith extension"); p += 22; break;
				case 4: sprintf(p, "\nLinear PCM audio"); p += 17; break;
				case 6: sprintf(p, "\nDTS"); p += 4; break;
				case 7: sprintf(p, "\nSDDS"); p += 5; break;
				default: break;
			}
			if(pAst_Atr.bNumberOfAudioChannels[sp] < 8) {
				if(pAst_Atr.bNumberOfAudioChannels[sp] == 5) {
					sprintf(p, "\n5.1 channels");
					p += 13;
				}
				else {
					sprintf(p, "\n%d channels", pAst_Atr.bNumberOfAudioChannels[sp] + 1);
					p += 11;
				}
				if(!pAst_Atr.bNumberOfAudioChannels[sp])
					p--;
			}
/*
			switch(pAst_Atr.wLanguageCodeExtension[sp]) {
				case 0x01: sprintf(p, "\nNormal captions"); break;
				case 0x02: sprintf(p, "\nAudio for visually impaired"); break;
				case 0x03: sprintf(p, "\nDirector's comments 1"); break;
				case 0x04: sprintf(p, "\nDirector's comments 2"); break;
				default: break;
			}
*/
		}
		else
			sprintf(tmp, "Language: FAILED");
	}
	else if(stPictFlag == 22) {
		sp = FMPGet(FMPI_CURRENT_ANGLE);
		sprintf(tmp, "Angle %d", (int)sp);
	}
}

void osdManager(INFO *pInfo) {

	char delayFlag, timeFlag = 0, stPictFlag = 0, menuFlag = 0;
	unsigned char *pict1, *pict2, *pict3, *tmpPict = NULL;
	char buf[1], str[40];
	ULONG size1;
	float scrH, scrW;
	int y = 0, al;
	WORD reg_tmp;
#ifdef PRINCETON
	unsigned char *lcdP0 = NULL, *lcdP1 = NULL, lcdFlag;
#endif

	if(pInfo->pIRma == NULL)
		while(1)
			if(OSGetMessage(pInfo->osdMsgQ, buf, 1) == ERROR) {
				DPRINT(("osdManager: error during reading message queue \n"));
				return;
			}

	while(1) {

		int freeFlag = 0;
		delayFlag = 0;
#ifdef PRINCETON
		lcdFlag = 0;
#endif

		if(OSGetMessage(pInfo->osdMsgQ, buf, 1) == ERROR) {
			DPRINT(("osdManager: error during reading message queue \n"));
			return;
		}

		if(pInfo->playing != CLOSED) {
			scrH = (pInfo->IHdtv_c) ? (Hdtv_Params[pInfo->IHdtv_c - 1].VideoHeight / 480.0f) : 1.0f;
			scrW = (pInfo->IHdtv_c) ? (Hdtv_Params[pInfo->IHdtv_c - 1].VideoWidth / 720.0f) : 1.0f;
		}
		else {
			scrH = 1.0f;
			scrW = 1.0f;
		}

		switch(buf[0]) {
			case SHOW_MENU: menuFlag++; stPictFlag = 0; break;
			case SHOW_TIME: timeFlag = !timeFlag; break;
			case SHOW_PLAY: stPictFlag = 1; delayFlag = 1; break;
			case SHOW_PAUSE: stPictFlag = 2; /*delayFlag = 1; */break;
			case SHOW_STOP2: timeFlag = 0; delayFlag = 1;
			case SHOW_STOP: stPictFlag = 3; break;
			case SHOW_OPEN: stPictFlag = 4; delayFlag = 1; timeFlag = 0; break;
			case SHOW_CLOSE: stPictFlag = 5; delayFlag = 1; break;
			case SHOW_REVERSE: stPictFlag = 6; break;
			case SHOW_NEXT: stPictFlag = 7; break;
			case SHOW_BACK: stPictFlag = 8; delayFlag = 1; break;
			case SHOW_SKIP: stPictFlag = 9; delayFlag = 1; break;
			case SHOW_STEPFF: stPictFlag = 10; delayFlag = 1; break;
			case SHOW_STEPRW: stPictFlag = 11; delayFlag = 1; break;
			case SHOW_SLOWRW: stPictFlag = 12; break;
			case SHOW_SLOWFF: stPictFlag = 13; break;
			case SHOW_LOADING: stPictFlag = 14; break;
			case SHOW_SUBTITLE: stPictFlag = 20; delayFlag = 1; break;
			case SHOW_LANGUAGE: stPictFlag = 21; delayFlag = 1; break;
			case SHOW_ANGLE: stPictFlag = 22; delayFlag = 1; break;
			case SHOW_AB_REPEAT: stPictFlag = 23; break;
			case SHOW_REPEAT: stPictFlag = 24; delayFlag = 1; break;
			case SHOW_CHECK_PASSWORD:
			{
				pInfo->blk = 1;
				g_sw = scrW; g_sh = scrH;
				if(checkPassword(pInfo))
					pInfo->test = 0x1;
				else
					pInfo->test = 0xff;
				OSPurgeMQ(pInfo->osdMsgQ);
				pInfo->blk = 0;
				goto scroff_case;
			}
			case SHOW_RES: changeRes(pInfo);
scroff_case:
			case SCR_OFF:
				stPictFlag = 0;
				if(pInfo->bABRepeat == 1)
					stPictFlag = 23;
				else if(pInfo->playing == TRICK_MODE) {
					LONG sp = (LONG)FMPGet(FMPI_CURRENT_SPEED);
					if(pInfo->bFast)
						if(sp < 0)
							stPictFlag = 6;
						else
							stPictFlag = 7; 
					else
						if(sp < 0)
							stPictFlag = 12;
						else
							stPictFlag = 13; 
				}
				else if(pInfo->playing == STOP_FOR_RESUME)
					stPictFlag = 3;
				else if(pInfo->playing == PAUSED)
					stPictFlag = 2;
				break;
			case SHOW_ERROR: stPictFlag = 25; delayFlag = 1; break;
			case SHOW_SVCD_WAITING: stPictFlag = 26; break;
			case SHOW_SEARCH: inputSearch(pInfo); stPictFlag = (pInfo->bABRepeat == 1) ? 23 : 0;
			default: break;
		}

		if(menuFlag) {
			menuFlag = onScreenMenus(pInfo);
			continue;
		}

		tmpPict = (unsigned char *)OSCelMalloc(MAX_WIDTH * MAX_HEIGHT + 1032);

		if(!timeFlag && !stPictFlag) tmpPict[0] = 0;
		else {
			if(stPictFlag < 20) {
				pict1 = pictArr[(int)stPictFlag];
#ifdef PRINCETON
				if(stPictFlag)
					lcdFlag = 1;
#endif
			}
			else if(stPictFlag < 23) {
				char tmp[100];
				pict1 = NULL;
				formString(tmp, stPictFlag);
				size1 = textToBitmap(pInfo->pIRma, &pict1, tmp, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
				if(pict1)
					freeFlag = 1;
			}
			else if(stPictFlag == 23) {
				char tmp[25];
				memset(tmp, 0, 25);
				pict1 = 0;
				if(!pInfo->bABRepeat) {
					sprintf(tmp, "A-B repeat mode\ncleared");
					size1 = textToBitmap(pInfo->pIRma, &pict1, tmp, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
					if(pict1) {
						delayFlag = 1;
						freeFlag = 1;
					}
				}
				else if(pInfo->bABRepeat == 1) {
					unsigned char *p;
					sprintf(tmp, "A-B\nrepeat");
					size1 = textToBitmap(pInfo->pIRma, &pict1, tmp, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
					sprintf(tmp, "B");
					size1 = textToBitmap(pInfo->pIRma, &pict3, tmp, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
					if(pict1) {
						if(pict3) {
							RMAPOINT pos;
							RMARECT rect;
							DWORD W3 = ((DWORD)pict3[4] << 8) | ((DWORD)pict3[5] - 4),
							      H3 = ((DWORD)pict3[6] << 8) | ((DWORD)pict3[7] - 4);
							for(p = pict3 + 1032; p < pict3 + size1; p++)
								if(*p == 0x2a)
									*p = 0x56;
							pos.x = (((((DWORD)pict1[4] << 8) | (DWORD)pict1[5])) + W3) >> 1; pos.y = 2;
							rect.left = 2; rect.right = W3 + rect.left;
							rect.top = 2; rect.bottom = H3 + rect.top - 2;
							IRma_LockRmaOSD(pInfo->pIRma, (HRMABITMAP)pict3, (PBYTE *)(&pict3), &size1);
							IRma_LockRmaOSD(pInfo->pIRma, (HRMABITMAP)pict1, (PBYTE *)(&pict1), &size1);
							RmaBitBlt(NULL, NULL, (HRMABITMAP)pict3, (HRMABITMAP)pict1, pos, rect, RMASRCCOPY, 0);
							IRma_UnLockRmaOSD(pInfo->pIRma, (HRMABITMAP)pict1, (PBYTE *)(&pict1), &size1);
							OSCelFree(pict3);
							pict3 = NULL;
						}
						freeFlag = 1;
					}
				}
				else {
					sprintf(tmp, "A-B repeat mode\nset");
					size1 = textToBitmap(pInfo->pIRma, &pict1, tmp, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
					if(pict1) {
						freeFlag = 1;
						delayFlag = 1;
					}
				}
			}
			else if(stPictFlag == 24) {
				char tmp[25];
				memset(tmp, 0, 25);
				pict1 = NULL;
				sprintf(tmp, "Repeat");
				switch(pInfo->bRepeat) {
					case 0: sprintf(tmp + 6, " mode\ncleared"); break;
					case 1:
						if(pInfo->bDiscType == FMPC_CDDA)
							sprintf(tmp + 6, "\ndisk");
						else
							sprintf(tmp + 6, "\ntitle");
						break;
					case 2:
						if(pInfo->bDiscType == FMPC_DVD_VIDEO)
							sprintf(tmp + 6, "\nchapter");
						else
							sprintf(tmp + 6, "\ntrack");
						break;
					default: memset(tmp, 0, 25); break;
				}
				if(tmp[0])
					size1 = textToBitmap(pInfo->pIRma, &pict1, tmp, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
				if(pict1) {
					freeFlag = 1;
				}
			}
			else if(stPictFlag == 25) {
				memset(str, 0, 40);
				if(pInfo->maddie == 1)
					sprintf(str, "INVALID\nDISK\nREGION");
				else if(pInfo->maddie == 2)
					sprintf(str, "PARENTAL\nCONTROL\nVIOLATION");
				else
					sprintf(str, "UNAUTHORIZED\nCOMMAND");
				size1 = textToBitmap(pInfo->pIRma, &pict1, str, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
				if(pict1) {
					freeFlag = 1;
					delayFlag = 1;
#ifdef PRINCETON
					lcdFlag = 1;
#endif
				}
			}
			else if(stPictFlag == 26) {
				memset(str, 0, 40);
				sprintf(str, "PLEASE, INSERT\nTHE NEXT DISK");
				size1 = textToBitmap(pInfo->pIRma, &pict1, str, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
				if(pict1) {
					freeFlag = 1;
#ifdef PRINCETON
					lcdFlag = 1;
#endif
				}
			}
			if(stPictFlag == 6 || stPictFlag == 7 ||
			   stPictFlag == 12 || stPictFlag == 13) {
				LONG sp = (LONG)FMPGet(FMPI_CURRENT_SPEED);
				if(!sp) {
					pict1 = play_osd;
					delayFlag = 1;
				}
				else {
					RMAPOINT pos;
					RMARECT rect;
					char speed[5];
					if(sp < 0) sp = -sp;
					if(pInfo->bABRepeat == 1)
						delayFlag = 1;
					memset(speed, 0, 5);
					if(stPictFlag > 10)
						sprintf(speed, "1/%dX", (int)sp);
					else
						sprintf(speed, "%dX", (int)sp);
					size1 = textToBitmap(pInfo->pIRma, &pict3, speed, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
					rect.left = 0; rect.top = 0;
					rect.right = (((DWORD)pict3[4] << 8) | (DWORD)pict3[5]) - 4;
					rect.bottom = (((DWORD)pict3[6] << 8) | (DWORD)pict3[7]) - 4;
					if(stPictFlag == 7 || stPictFlag == 13)
						pos.x = FF_SLOW_LEFT_INDENT;
					else
						pos.x = FF_SLOW_RIGHT_INDENT;
					pos.y = FF_SLOW_TOP_INDENT;
					IRma_LockRmaOSD(pInfo->pIRma, (HRMABITMAP)pict3, (PBYTE *)(&pict3), &size1);
					IRma_LockRmaOSD(pInfo->pIRma, (HRMABITMAP)pict1, (PBYTE *)(&pict1), &size1);
					RmaBitBlt(NULL, NULL, (HRMABITMAP)pict3, (HRMABITMAP)pict1, pos, rect, RMASRCCOPY, 0);
					IRma_UnLockRmaOSD(pInfo->pIRma, (HRMABITMAP)pict1, (PBYTE *)(&pict1), &size1);
					OSCelFree(pict3);
					pict3 = NULL;
				}
			}
			reg_tmp = (WORD)FMPGet(FMPI_CURRENT_DOMAIN);
			if(timeFlag && pInfo->playing != CLOSED &&
			   reg_tmp != VMGM_DOM && reg_tmp != VTSM_DOM) {
				unsigned char *tmp = (unsigned char *)(&(pInfo->dwTime));
				if(pInfo->bDiscType == FMPC_CDDA ||
				   pInfo->bDiscType == FMPC_VCD ||
				   pInfo->bDiscType == FMPC_SVCD) {
					sprintf(str, "Track %6d\nTime %0x:%02x:%02x",
					        (int)FMPGet(FMPI_CURRENT_TRACK),
					        (int)tmp[0], (int)tmp[1], (int)tmp[2]);
				}
				else {
					sprintf(str, "Title     %02d\nChapter  %03d\nTime %0x:%02x:%02x",
					        (int)FMPGet(FMPI_CURRENT_TITLE),
					        (int)FMPGet(FMPI_CURRENT_CHAPTER), 
					        (int)tmp[0], (int)tmp[1], (int)tmp[2]);
				}
				size1 = textToBitmap(pInfo->pIRma, &pict2, str, (RMAYUVENTRY *)Palette, &OSD_PICTS_FONT);
				y = 480 - BOTTOM_INDENT; al = RIGHT_BOTTOM;
			}
			else {
				pict2 = NULL;
				y = TOP_INDENT; al = RIGHT_TOP;
			}
			size1 = addPict(pInfo->pIRma, tmpPict, pict1, pict2);
			if(pict2) {
				OSCelFree(pict2);
				pict2 = NULL;
			}
		}

		if(tmpPict[0]) {
			OSD_WND wnd;
			memset(&wnd, 0, sizeof(OSD_WND));
			DISPLAY_OSD(pInfo->pIOsd,tmpPict,(720-RIGHT_INDENT),y,al,scrW,scrH);
			SET_HIGHLIGHT(pInfo->pIOsd, &wnd, scrW, scrH);
			if(delayFlag) {
				OSThreadDelete(osdtID);
				osdtID = OSInitPolling("osd_delay", (FUNCPTR)osdDelay, (DWORD)(pInfo));
			}
#ifdef PRINCETON
			if(lcdFlag) {
				if(stPictFlag == 25) {
					OSCelFree(pict1);
					pict1 = NULL;
					memset(str, 0, 40);
					if(pInfo->maddie == 1)
						sprintf(str, "INVALID\nDISK\nREGION");
					else if(pInfo->maddie == 2)
						sprintf(str, "PARENTAL\nCONTROL\nVIOLATION");
					else
						sprintf(str, "UNAUTHORIZED\nCOMMAND");
					size1 = textToBitmap(pInfo->pIRma, &pict1, str, (RMAYUVENTRY *)Palette, &_RMA_7x14);
				}
				else if(stPictFlag == 26) {
					OSCelFree(pict1);
					pict1 = NULL;
					memset(str, 0, 40);
					sprintf(str, "PLEASE, INSERT\nTHE NEXT DISK");
					size1 = textToBitmap(pInfo->pIRma, &pict1, str, (RMAYUVENTRY *)Palette, &_RMA_7x14);
				}
				rmaOsd2monoLCD(pict1, &lcdP0, &lcdP1, 0x2a);
				DrawImage(lcdP0, lcdP1);
			}
			else if(timeFlag && pInfo->playing != CLOSED &&
			        reg_tmp != VMGM_DOM && reg_tmp != VTSM_DOM) {
				unsigned char *tmp = (unsigned char *)(&(pInfo->dwTime));
				if(pInfo->bDiscType == FMPC_CDDA ||
				   pInfo->bDiscType == FMPC_VCD ||
				   pInfo->bDiscType == FMPC_SVCD) {
					sprintf(str, "Track %6d\nTime %0x:%02x:%02x",
					        FMPGet(FMPI_CURRENT_TRACK),
					        tmp[0], tmp[1], tmp[2]);
				}
				else {
					sprintf(str, "Title     %02d\nChapter  %03d\nTime %0x:%02x:%02x",
					        FMPGet(FMPI_CURRENT_TITLE),
					        FMPGet(FMPI_CURRENT_CHAPTER), 
					        tmp[0], tmp[1], tmp[2]);
				}
				size1 = textToBitmap(pInfo->pIRma, &pict2, str, (RMAYUVENTRY *)Palette, &_RMA_7x14);
				rmaOsd2monoLCD(pict2, &lcdP0, &lcdP1, 0x2a);
				DrawImage(lcdP0, lcdP1);
				if(pict2) {
					OSCelFree(pict2);
					pict2 = NULL;
				}
				if(lcdP0) {
					OSCelFree(lcdP0);
					lcdP0 = NULL;
				}
				if(lcdP1) {
					OSCelFree(lcdP1);
					lcdP1 = NULL;
				}
			}
#endif
			if(pict1 && freeFlag) {
				OSCelFree(pict1);
				pict1 = NULL;
			}
		}
		else {
			if(pInfo->pIOsd) {
				IOsd_Off(pInfo->pIOsd);
//				IOsd_Flush(pInfo->pIOsd);
			}
#ifdef PRINCETON
//			LCDRAM2();
			DrawImage(Image6_0, Image6_1);
			if(lcdP0) {
				OSCelFree(lcdP0);
				lcdP0 = NULL;
			}
			if(lcdP1) {
				OSCelFree(lcdP1);
				lcdP1 = NULL;
			}
#endif
		}
		if(tmpPict) {
			OSCelFree(tmpPict);
			tmpPict = NULL;
		}
	}
}

void osdDelay(INFO *ms) {
	char msg = SCR_OFF;
	if(ms->maddie)
		OSSleep_s(3);
	if(ms->maddie == 3) {
		OSSleep_s(6);
		ms->maddie = 0;
	}
	OSSleep_s(1);
	OSPostMessage(ms->osdMsgQ, &msg, 1);
	osdtID = 0;
}



#ifdef PRINCETON

BYTE flipB(BYTE a) {
	BYTE c;
	c = (a << 4) | (a >> 4);
	c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
	c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
	return c;	
}

void rotateBl(BYTE *bl) {
	BYTE p[8], i, j;

	memset(p, 0, 8);

	for(i = 0; i < 8; i++)
		for(j = 0; j < 8; j++)
			p[i] |= (((bl[7 - j] >> (7 - i)) & 1) << (7 - j));

	memcpy(bl, p, 8);
	return;
}

void rotateP(BYTE *m) {
	BYTE p[8], tmp[8 * 64], i, j, k;

	for(i = 0; i < 8; i++) {
		for(j = 0; j < 8; j++) {
			for(k = 0; k < 8; k++)
				p[k] = m[64 * (7 - j) + k * 8 + i];
			rotateBl(p);
			for(k = 0; k < 8; k++)
				tmp[64 * i + k * 8 + j] = p[k];
		}
	}
	memcpy(m, tmp, 8 * 64);
	return;
}

BYTE rmaOsd2monoLCD(PBYTE bmp, PBYTE *pict0, PBYTE *pict1, BYTE color) {

	DWORD width, height, tmp;
	PBYTE p;
	int ii, jj, kk;
	unsigned char *p1, *p0;

	if(!bmp) {
		DPRINT(("NULL source bitmap"));
		return 0xff;
	}

	width = (DWORD)(bmp[4] << 8) | (DWORD)(bmp[5]);
	height = (DWORD)(bmp[6] << 8) | (DWORD)(bmp[7]);

	if(width > 128 || height > 64) {
		DPRINT(("Wrong size of the source bitmap\n"));
		return 0xff;
	}

	if(!(p = (PBYTE)OSCelMalloc(128 * 64))) {
		DPRINT(("Not enough memory"));
		return 0xff;
	}
	if(!(*pict0))
		if(!(*pict0 = (PBYTE)OSCelMalloc(8 * 64))) {
			DPRINT(("Not enough memory"));
			return 0xff;
		}
	if(!(*pict1))
		if(!(*pict1 = (PBYTE)OSCelMalloc(8 * 64))) {
			DPRINT(("Not enough memory"));
			return 0xff;
		}

	memset(p, ~color, 128 * 64);
	tmp = ((64 - height) >> 1) * 128 + ((128 - width) >> 1);
	for(ii = 0; ii < height; ii++)
		memcpy(p + tmp + ii * 128, bmp + 1032 + (height - 1 - ii) * width, width);
	for(ii = 0; ii < 128 * 64; ii++)
		p[ii] = (p[ii] == color) ? 1 : 0;

	for(ii = 0; ii < 64; ii++) {
		BYTE a;
		for(jj = 0; jj < 128; jj+=8) {
			a = 0;
			for(kk = 0; kk < 8; kk++)
				a |= p[jj + kk + ii * 128] << (7 - kk);
			p[(jj >> 3) + ii * 16] = a;
		}
	}

	memset(*pict0, 0, 8 * 64);
	memset(*pict1, 0, 8 * 64);
	p1 = *pict1; p0 = *pict0;
	for(ii = 0; ii < 64; ii++, p0 += 8, p1 += 8) {
		memcpy(p0, p + ii * 16, 8);
		memcpy(p1, p + ii * 16 + 8, 8);
	}

	OSCelFree(p);

	rotateP(*pict0);
	rotateP(*pict1);
	for(ii = 0; ii < 64 * 8; ii++) {
		(*pict0)[ii] = (flipB((*pict0)[ii]));
		(*pict1)[ii] = (flipB((*pict1)[ii]));
	}

//printing for the test
/*
	{
		int fd = open("tmp.h", O_CREAT | O_WRONLY, 0644);
		for(ii = 0; ii < 64; ii++) {
			for(jj = 0; jj < 64; jj++) {
				BYTE sss = ((*pict0)[jj * 8 + ii / 8] >> (ii % 8)) & 1;
				if(sss)
					write(fd, "*", 1);
				else
					write(fd, " ", 1);
			}
			if(wid2)
				for(jj = 0; jj < 64; jj++) {
					BYTE sss = ((*pict1)[jj * 8 + ii / 8] >> (ii % 8)) & 1;
					if(sss)
						write(fd, "*", 1);
					else
						write(fd, " ", 1);
				}
			write(fd, "\n", 1);
		}
		close(fd);
	}
*/
	return 0;				
}

/*
void test() {
	PBYTE p0 = NULL, p1 = NULL;
	int i;
	MPEGDriverEntry(0);
	for(i = 1; i < 12; i++) {
		if(rmaOsd2monoLCD(pictArr[i], &p0, &p1, 0x2a));
//			printf("\n");
			LCDOn();
		DrawImage(p0, p1);
		while(getchar() != 'b');
		LCDOff();
	}
	if(p0) OSfree(p0);
	if(p1) OSfree(p1);
	MPEGDriverUnload();
}
*/
#endif
