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

📄 lcd.cpp

📁 ARM_显示器_键盘_源代码
💻 CPP
字号:

// ARM Ltd
// Copyright 1998 All Rights reserved

// David Earlam 22.9.1998
// Updated by David Roberts 8.8.2001

// Virtual LCD.

// First hack set individual pixels in an offscreen memory DC and bitblatted the memory to the screen.
// This worked -slowly- and was not very succesful if the screen was resized (StretchBlt).

// But why call GDI for every pixel with lots of bit manipulations and stacking of parameters.
// Second hack uses a Device Independent Bitmap and converts from an in memory frame buffer
// simulating the frame buffer of an actual LCD and converts the bits therein 
// to a DIB compatible format, then blats this to the screen.
// The conversion from frame buffer to DIB format is done by a dynamically constructed
// lookup table improving screen refresh rates about 80,000 times for a 480x240x2 LCD
// over the 'First hack'. 
// Screen resizing is ever so nice too.
//
// A refreshTimer controls how frequently the framebuffer is inspected to deduce the minimum that must
// be repainted. 
  

#include <afxwin.h>
#include <io.h>

#include "CPixelDepthChanger.h"

#include "CIntervalTimer.h"

#include "resource.h"

#include "..\console.h"
#include "..\console_rpc.h"

unsigned lcd_width, lcd_height;

// Define the application class
class CApp : public CWinApp
{
public:
	BOOL bArmulator;
	void CloseRPC(void);
	void SetupRPC();
	virtual BOOL InitInstance();
	virtual int ExitInstance( );

	COLORREF lcdcolor[256]; 

	unsigned char* pszStringBinding;
	RPC_STATUS status;	
};

CApp App;  



// Define the window class
class CWindow : public CFrameWnd
{ 
	CDC memDC;
	CBitmap *oldMemDCBitmap, *newMemDCBitmap;
public:
	LPVOID lpMemFile;
	CWindow(DWORD _threadID);
	~CWindow();
	afx_msg void OnPaint();
	afx_msg void OnChar( UINT nChar, UINT nRepCnt, UINT nFlags );

	void RePaint();
	void DoPaint();

	virtual BOOL PreCreateWindow( CREATESTRUCT& cs );

	void DoAbout( void );
	void DoChangeRefresh1( void );
	void DoChangeRefresh2( void );
	void DoChangeRefresh5( void );
	void DoChangeRefresh10( void );
	void CheckMenu( int id );

	CDib *pdisplayDib;
	int displayDibBitsperpixel;

	CPixelDepthChanger *pdisplayPixelDepthChanger;

	int srcBitsperpixel;

	CIntervalTimer refreshTimer;

	CDib realbitmap;

	DWORD threadID;

	DECLARE_MESSAGE_MAP()
};

// The constructor for the window
CWindow::CWindow(DWORD _threadID) : threadID(_threadID)
{ 
// Should use GetSystemMetrics for 'correction factor' of 4 below
// GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER)
// but still doesn't give correct adjustment???
	CApp* theApp = (CApp*)AfxGetApp();

	if( theApp->bArmulator == TRUE ) {
		lcd_width = getPixelsX();
		lcd_height = getPixelsY();
	} else {
		lcd_width = 480;
		lcd_height = 240;
	}

	CRect myrect = CRect(CPoint(50,50), CSize(
		lcd_width+8,
		lcd_height+46));

	Create(NULL, "ARM Virtual LCD", WS_OVERLAPPEDWINDOW, myrect, NULL,
		MAKEINTRESOURCE(IDR_MENU_MAIN));

	CSize sizeDib(lcd_width,lcd_height);
	displayDibBitsperpixel = 8;

	pdisplayDib = new CDib(sizeDib,displayDibBitsperpixel);

	if (_threadID == 0) {
	// need to get a pointer to shared memory contating the source frame buffer here

		//LPBYTE psrcBits = new BYTE[WIDTH * HEIGHT / srcBitsperpixel];
		srcBitsperpixel = BITS_PER_PIXEL;
		BOOL result = realbitmap.AttachMapFile("logo_back.bmp",TRUE);

		// DR added - make sure that the display dib and loaded dib have same palette!!
		// Copy palette from source DIB to new DIB
		pdisplayDib->SetColorTable( (RGBQUAD*)realbitmap.m_lpvColorTable, realbitmap.m_nColorTableEntries );

		pdisplayPixelDepthChanger = new CPixelDepthChanger(lcd_width,lcd_height,realbitmap.m_lpBMIH->biBitCount,(void*) realbitmap.m_lpImage, *pdisplayDib);
	} else {
		WORD srcBitsperpixel = BITS_PER_PIXEL;

		HANDLE hMap = ::OpenFileMapping(FILE_MAP_READ, FALSE, "wince");
#if 0
		char buf[100];
		DWORD dwErr = ::GetLastError();
		sprintf(buf, "hmap = %d, dwerr = %d\n", hMap, dwErr);
		MessageBox(buf, "2", MB_OK);
#endif
		if(hMap == NULL) {
			AfxMessageBox("Cannot open file mapping to 'wince' memory");
		}
		LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); // map whole file

		
		BOOL result;
		
		switch( BITS_PER_PIXEL ) {
		case 8:
			result = realbitmap.AttachMapFile("palette8.bmp",TRUE);
			pdisplayDib->SetColorTable( (RGBQUAD*)realbitmap.m_lpvColorTable, realbitmap.m_nColorTableEntries );
			break;

		case 2:
			// design a palette
			int i;
			for( i = 0; i < 4; i++ )
				theApp->lcdcolor[i] = RGB( i * 85, i * 85, i * 85 );

			pdisplayDib->SetColorTable( (RGBQUAD*)theApp->lcdcolor, 4 );
			break;

		default:
			// not supported
			AfxMessageBox("Unsupported colour depth!");
		}

		pdisplayPixelDepthChanger = new CPixelDepthChanger(lcd_width,lcd_height,srcBitsperpixel,lpvFile, *pdisplayDib);
	}

	DoChangeRefresh5();
}

extern "C"
{
	void CALLBACK yourMMTimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1,
    DWORD dw2)
	{
		CWindow* pThis = (CWindow*) dwUser;
		pThis->RePaint();
	}

}
CWindow::~CWindow()
{
#if FIRSTHACK
	memDC.SelectObject(oldMemDCBitmap);
	delete newMemDCBitmap;
#endif

	delete pdisplayDib;
	delete pdisplayPixelDepthChanger;
}

// The message map
BEGIN_MESSAGE_MAP( CWindow, CFrameWnd )
	ON_WM_PAINT()
	ON_WM_CHAR()
	
	ON_COMMAND( IDM_ABOUT, DoAbout )
	ON_COMMAND( ID_HZ_1, DoChangeRefresh1 )
	ON_COMMAND( ID_HZ_2, DoChangeRefresh2 )
	ON_COMMAND( ID_HZ_5, DoChangeRefresh5 )
	ON_COMMAND( ID_HZ_10, DoChangeRefresh10 )
END_MESSAGE_MAP()


// Handle exposure events
void CWindow::OnPaint()
{

	DoPaint();
	
		
#if FIRSTHACK	
	CRect borderrect(0,0,WIDTH,HEIGHT);
	
	// Paint into the memory DC pixel by pixel ... sloooow even with SetPixelV which is claimed faster than SetPixel  
	{
	int x;
	int y;

	for (x=0;
      x< WIDTH ;
	  ++x)
	  {
		  for (y=0;
      y < HEIGHT;
	   ++y)
	  {
		memDC.SetPixelV(x,y,((CApp*)AfxGetApp())->lcdcolor[x%4]);
	  }
	  }
	}

	// Transfer the memory DC to the screen
	 //use this if fixed size window
	 dc.BitBlt(0,0,borderrect.Width(),borderrect.Height(),&memDC,0,0,SRCCOPY);

	 //use this if allow resize
     //dc.StretchBlt(0, 0, clirect.Width(),clirect.Height(), &memDC, 0,0,borderrect.Width(),borderrect.Height(), SRCCOPY );

#endif
 
}

extern "C" int _confh;

/*
BOOL CWindow::PreTranslateMessage( MSG* pMsg )
{
	int err; char buf[30];

	switch (pMsg->message)
	{
	case WM_KEYDOWN:
	case WM_KEYUP:
		::PostThreadMessage(threadID, WM_USER, pMsg->wParam, pMsg->lParam);
	}
	return CFrameWnd::PreTranslateMessage(pMsg);
}
*/

void CWindow::DoPaint()
{

	CRect clirect;
    GetClientRect(clirect);

	CPaintDC dc(this);

	pdisplayPixelDepthChanger->Update(); //convert source frame buffer bits to Windows Dib very quickly

	pdisplayDib->Draw( &dc, CPoint(0,0), CSize(clirect.Width(),clirect.Height()));

	// DEBUG
	/*
	char buf[100];
	wsprintf( buf, "Contents of pdisplayDib->m_lpImage[0] = %02x", *pdisplayDib->m_lpImage );
	CRect theRect( 10, 10, 450, 100 );
	dc.DrawText( buf, strlen(buf), theRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
	*/
}


void CWindow::RePaint()
{
	CRect rect;
//	rect = pdisplayPixelDepthChanger->GetInvalidRect(); //what has changed since the last paint

	CClientDC dc(this);
	dc.SetMapMode(MM_ANISOTROPIC);
	//dc.SetWindowExt(pdisplayPixelDepthChanger->GetSrcSize());
	dc.SetWindowExt(pdisplayDib->GetDimensions());

	CRect cliRect;
	GetClientRect(cliRect);
	dc.SetViewportExt(cliRect.right, cliRect.bottom);
	dc.SetViewportOrg(0,0);

//	dc.LPtoDP(rect); // we need to invalidate with device coordinates

	InvalidateRect(&cliRect,FALSE);
//	InvalidateRect(&rect);
//	UpdateWindow(); // don't wait for WM_PAINT to percolate thru the message queue
	
}

void CWindow::OnChar( UINT nChar, UINT nRepCnt, UINT nFlags )
{
	// RPC call
	QueueKey( nChar, nFlags & 0x8000 );
}

BOOL CWindow::PreCreateWindow( CREATESTRUCT& cs ) {
	// Determine the class ID for FindWindow call from the model
	// DEBUG
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;

	CApp* theApp = (CApp*)AfxGetApp();
	if( theApp->bArmulator == TRUE )
		cs.style &= ~WS_SYSMENU;

	cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
	cs.lpszClass = AfxRegisterWndClass(0);

	// DEBUG get the window class name!
	//MessageBox( cs.lpszClass );

	return TRUE;
}

void CWindow::DoAbout( void )
{
	MessageBox( "ARM LCD viewer\n\nCopyright 1998, 2001 ARM Ltd.\nDavid Earlam 22.9.1998\nUpdated by David Roberts 8.8.2001", "About" );
}

void CWindow::CheckMenu( int id )
{
	// clear checks
	CMenu *pMenu = GetMenu();

	pMenu->CheckMenuItem( ID_HZ_1, MF_UNCHECKED );
	pMenu->CheckMenuItem( ID_HZ_2, MF_UNCHECKED );
	pMenu->CheckMenuItem( ID_HZ_5, MF_UNCHECKED );
	pMenu->CheckMenuItem( ID_HZ_10, MF_UNCHECKED );

	// check correct one
	pMenu->CheckMenuItem( id, MF_CHECKED );
}

void CWindow::DoChangeRefresh1()
{
	refreshTimer.StopPeriodicTimer();
	refreshTimer.SetTimerCallback((DWORD)this, 1000, yourMMTimeProc);

	CheckMenu( ID_HZ_1 );
}

void CWindow::DoChangeRefresh2()
{
	refreshTimer.StopPeriodicTimer();
	refreshTimer.SetTimerCallback((DWORD)this, 500, yourMMTimeProc);

	CheckMenu( ID_HZ_2 );
}

void CWindow::DoChangeRefresh5()
{
	refreshTimer.StopPeriodicTimer();
	refreshTimer.SetTimerCallback((DWORD)this, 200, yourMMTimeProc);

	CheckMenu( ID_HZ_5 );
}

void CWindow::DoChangeRefresh10()
{
	refreshTimer.StopPeriodicTimer();
	refreshTimer.SetTimerCallback((DWORD)this, 100, yourMMTimeProc);

	CheckMenu( ID_HZ_10 );
}

// Init the application
BOOL CApp::InitInstance()
{
	DWORD armulator;  // thread ID passed in in argv[1]
	bArmulator = FALSE;

	lcdcolor[0] = 		RGB (0,0,0);
	lcdcolor[1] = 		RGB (128,128,128);
	lcdcolor[2] = 		RGB (192,192,192);
	lcdcolor[3] = 		RGB (255,255,255);

	CString sCommandLine = m_lpCmdLine; // parse this to get name of shared memory, frame buffer dimensions, depth, refresh rate. lcdcolor mappings

	if (__argc < 2) {
		armulator = 0;  // not invoked from ARMULATE.DLL
		bArmulator = FALSE;
		AfxMessageBox( "Not invoked from ARMULATE.DLL\n\nPlease run this via the ARMulator console model.", MB_OK, NULL );
		//return FALSE;
	}
	else {
		armulator = atoi(__argv[1]);
		bArmulator = TRUE;

		SetupRPC();
	}

	m_pMainWnd = new CWindow(armulator);
	m_pMainWnd->ShowWindow(m_nCmdShow);
	m_pMainWnd->UpdateWindow();

	return TRUE;
}

int CApp::ExitInstance()
{
	CloseRPC();

	return 0;
}

/******************************************************/
/*         MIDL allocate and free                     */
/******************************************************/
 
void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
{
    return(malloc(len));
}
 
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
    free(ptr);
}

void CApp::SetupRPC()
{
	// Set up RPC
    unsigned char * pszUuid             = NULL;

	// If you run windows NT, this can be "ncacn_np" for named pipe
    unsigned char * pszProtocolSequence = (unsigned char*)"ncalrpc";
    unsigned char * pszNetworkAddress   = NULL;
    unsigned char * pszEndpoint    = NULL;
	//unsigned char * pszEndpoint    = (unsigned char*)"console_rdi";
    unsigned char * pszOptions          = NULL;
    pszStringBinding = NULL;
	char buf[150];

    status = RpcStringBindingCompose(pszUuid,
                                     pszProtocolSequence,
                                     pszNetworkAddress,
                                     pszEndpoint,
                                     pszOptions,
                                     &pszStringBinding);
    if (status != RPC_S_OK ) {
		// determine exactly what the error was
		wsprintf( buf, "Invalid client RPC String: status=%d", status );

		switch( status ) {
		case RPC_S_PROTSEQ_NOT_SUPPORTED:
			strcat( buf, "\n Protocol sequence not supported on this host" );
			break;

		case RPC_S_INVALID_RPC_PROTSEQ:
			strcat( buf, "\n Invalid protocol sequence" );
			break;

		case RPC_S_INVALID_ENDPOINT_FORMAT:
			strcat( buf, "\n Invalid endpoint format" );
			break;

		case RPC_S_OUT_OF_MEMORY:
			strcat( buf, "\n Out of memory" );
			break;

		case RPC_S_DUPLICATE_ENDPOINT:
			strcat( buf, "\n Endpoint is duplicate" );
			break;

		case RPC_S_INVALID_SECURITY_DESC:
			strcat( buf, "\n Security descriptor invalid" );
		}

		AfxMessageBox( buf, MB_OK, 0 );
	}

    status = RpcBindingFromStringBinding(pszStringBinding,
                                         &console_rpc_IfHandle);
}

void CApp::CloseRPC()
{
	if( bArmulator == TRUE ) {
		status = RpcStringFree(&pszStringBinding); 
		status = RpcBindingFree(&console_rpc_IfHandle);
	}
}

⌨️ 快捷键说明

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