📄 lcd.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 + -