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

📄 mmonemu.cpp

📁 SM501基于ARMV4/ARMV4I平台
💻 CPP
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1997-2000 Microsoft and/or its suppliers. All rights reserved.
Copyright (c) 2002 Silicon Motion, Inc.

Module Name:    mmonemu.cpp

Abstract:       Special MultiMon Emulation Feature

Notes:

--*/

#include "precomp.h"
#include "palette.h"

#ifdef MULTIMONEMU_ENABLE

#include "mmonemu.h"

#ifdef ENABLE_DIRECT3D
extern SMI*	ppdev;
extern _SMDMA   gblSMDMA;		//_SMDMA defined in smdma.h

#endif // ENABLE_DIRECT3D

SMIVGXEmu::SMIVGXEmu(SMISETTINGS *pss, SMI *pSMI) 
	: SMI()
{
	m_pSMI = pSMI;
	Init(pss);

#ifdef DD_ENABLE
	m_pVideoMemoryHeap = (SurfaceHeap *) 0xFFFFFFFF;
#else	// ! DD_ENABLE
	m_p2DVideoMemory = (Node2D *) 0xFFFFFFFF;
#endif	// DD_ENABLE

}

BYTE SMIVGXEmu::GetPanelID(void)
{
	return m_pSMI->GetPanelID();
}

void SMIVGXEmu::InitCard(void)
{
	// Setup hardware pointer
	m_pLAW = m_SMISettings.m_pLAW;
	m_nLAWPhysical = m_SMISettings.m_nLAWPhysical;
	m_pREG = m_SMISettings.m_pREG;
	m_nREGPhysical = m_SMISettings.m_nREGPhysical;

	m_pDPR = m_pREG + DE_SOURCE;
	m_pMMIO = m_pREG + DE_DATAPORT;

}

void SMIVGXEmu::AdjustDefaultMode() 
{
	SMI::AdjustDefaultMode();
	// Panning not supported
	m_SMISettings.m_dwCxScreen = m_SMISettings.m_dwCxPanel;
	m_SMISettings.m_dwCyScreen = m_SMISettings.m_dwCyPanel;
}

int SMIVGXEmu::GetRotateModeFromReg()
{
    return 0;
}

LONG SMIVGXEmu::DynRotate(int angle)
{
	return FALSE;
}

extern mode_table_t mode_table[];
void SMIVGXEmu::SetModeHardware(int modeId)
{

	mode_table_t *vesaMode, mode;
	reg_table_t register_table;
	long clock = 0;
	unsigned long value;

	if (rev() == 0xA0)
	{
		if (m_SMISettings.m_nTestClock == 0) 
			m_SMISettings.m_nTestClock = 133000000L;
	}

	clock = (long) m_SMISettings.m_nTestClock;

	// m_pMode->frequency = 75;
	vesaMode = findMode(mode_table,	m_SMISettings.m_dwCxPanel, m_SMISettings.m_dwCyPanel,
					m_pMode->frequency);
	if (vesaMode == NULL)
	{
		RETAILMSG (1, (_T("SMIVGX - Mode not found (modeId = %d, %dx%d@%d)\r\n"), 
			modeId, m_SMISettings.m_dwCxPanel, m_SMISettings.m_dwCyPanel,
					m_SMISettings.m_nFrequency));
		return;
	}

	// Set mode on panel and CRT.
	adjustMode(vesaMode, &mode, CRT, clock);
	//setModeRegisters(&register_table, &mode, PANEL, m_nScreenBpp, clock);
	//programMode(&register_table);
	setModeRegisters(&register_table, &mode, CRT, m_nScreenBpp, clock);
	programMode(&register_table);

	// Let CRT display panel data.
	value = peekRegisterDWord(CRT_DISPLAY_CTRL);
	value = FIELD_SET(value, CRT_DISPLAY_CTRL, SELECT, CRT);
	value = FIELD_SET(value, CRT_DISPLAY_CTRL, PLANE, ENABLE);
	value = FIELD_SET(value, CRT_DISPLAY_CTRL, TIMING, ENABLE);
	pokeRegisterDWord(CRT_DISPLAY_CTRL, value);

	// Reset panel frame buffer address to 0.
	pokeRegisterDWord(CRT_FB_ADDRESS,
					  FIELD_SET(0, CRT_FB_ADDRESS, STATUS, PENDING) |
					  FIELD_SET(0, CRT_FB_ADDRESS, EXT, LOCAL) |
					  FIELD_VALUE(0, CRT_FB_ADDRESS, ADDRESS, 0));

	// Setup Panning
	m_nPanningX = m_SMISettings.m_dwPanningX;
	m_nPanningY = m_SMISettings.m_dwPanningY;

}

void SMIVGXEmu::GetPhysicalVideoMemory(PULONG pPhysicalMemoryBase, PULONG pVideoMemorySize)
{
	m_pSMI->GetPhysicalVideoMemory(pPhysicalMemoryBase, pVideoMemorySize);
}

SCODE SMIVGXEmu::SetPalette(const PALETTEENTRY *src,unsigned short firstEntry,unsigned short numEntries )
{
	int i;

	DEBUGMSG(GPE_ZONE_ENTER, (TEXT("GPEVGA::SetPallette()\r\n")));

	if (firstEntry < 0 || firstEntry + numEntries > 256)
		return(E_INVALIDARG);

	for (i=firstEntry; i< numEntries; i++)
	{
		POKE_32(CRT_PALETTE_RAM+i*4, src[i].peRed<<16 | src[i].peGreen<<8 | src[i].peBlue);
	}

	return S_OK;
}

void SMIVGXEmu::WaitForNotBusy(void)
{
	//m_pSMI->WaitForNotBusy();
}

int SMIVGXEmu::IsBusy(void)
{
	//return m_pSMI->IsBusy();
	return FALSE; 
}

void SMIVGXEmu::WaitForVBlank()
{
	//m_pSMI->WaitForVBlank();

}

int SMIVGXEmu::InVBlank()
{
	// return m_pSMI->InVBlank();
	return TRUE; 
}

void SMIVGXEmu::SetupVideoMemory()
{
	m_nVideoMemorySize = 0;
	m_nVideoMemoryAvail = 0;

}

extern unsigned char mask_table[];
SCODE SMIVGXEmu::SetPointerShape(GPESurf *pMask, GPESurf *pColorSurf, int xHot, int yHot, int cx, int cy)
{
	PUCHAR pByte;
	PUCHAR pBuf;
	int i, row, col_byte, stride;
	UCHAR and_mask, xor_mask;

	DEBUGMSG(GPE_ZONE_CURSOR, (TEXT("SMIVGXEmu::SetPointerShape()\r\n")));

	SetCursorColors(0x00ffffff, 0x00000000);	// Set colors to black & white

	pByte = m_pLAW + m_nCursorMemory;
	DEBUGMSG(GPE_ZONE_CURSOR, (TEXT("pByte = %08X, m_nCursorMemory = %08X\r\n"),
			pByte, m_nCursorMemory));

	// Not sure if this hide cursor is necessary, please verify
	DisableCursor();

	if (!pMask)
	{
		DEBUGMSG(GPE_ZONE_CURSOR, (TEXT("+SMIVGXEmu Turning off cursor\r\n")));

		for (i = 0; i < 64*64/8*2; i++)	// Turn off cursor by setting mask to clear
			pByte[i] = 0;
	}
	else
	{
		// A cursor shape has been entered, draw it.
		DEBUGMSG(GPE_ZONE_CURSOR, (TEXT("+SMIVGXEmu Setting pointer shape\r\n")));

		// Setup freq addressed information into local variables.
		stride = pMask->Stride();
		pBuf = (PUCHAR) pMask->Buffer();

		// initialize entire 32 x 32 shape to be ANDs=0xFF and XORs = 0x00
		// (i.e. transparent)
		m_nXHot = xHot;
		m_nYHot = yHot;	// we rely on MovePointer being called after this
		
		// Clear Cursor Mem to transparent.
		// 1/2/2003. Clear additional 1KB to 0 to patch Hw RevA cursor bottom garbage 
		// when cursor at bottom of screen.
		memset((PUCHAR) m_pLAW+m_nCursorMemory, 0, CURSUR_IMAGE_SIZE);

		for (row = 0, i=0; row < cy; row++)
		{
			i = row * 64/8 * 2;
			for (col_byte = 0; col_byte < cx/8; col_byte++)
			{
				and_mask = mask_table[(~pBuf[row * stride+col_byte ] & 0xF0)>>4];
				xor_mask = mask_table[(pBuf[(cy + row) * stride + col_byte] & 0xF0)>>4]/2;
				pByte[i++] = and_mask | xor_mask;

				and_mask = mask_table[(~pBuf[row * stride+col_byte] & 0x0F)];
				xor_mask = mask_table[(pBuf[(cy + row) * stride + col_byte] & 0x0F)]/2;
				pByte[i++] = and_mask | xor_mask;
			}
		}
	}


	RotateCursorShape(m_iRotate);

	SetCursorAddress(m_nCursorMemory);
	
	DEBUGMSG(GPE_ZONE_CURSOR, (TEXT("+SMIVGXEmu Cursor shape set done\r\n")));

	return (S_OK);
}

SCODE SMIVGXEmu::MovePointer(int x, int y)
{
	DEBUGMSG(GPE_ZONE_CURSOR, (TEXT("SMIVGXEmu::MovePointer(%d, %d)\r\n"), x, y));

#ifndef ROTATION_ENABLE
	int newX = x - m_nXHot;	// Hot spot is currently 32,32
	int newY = y - m_nYHot;
	int nHideCursor = -1;
	
	//Fix hw cursor X,Y out of screen range. 11/01/02
	if (newX >= m_nScreenWidth)
		newX = m_nScreenWidth-1;

	if (newY >= m_nScreenHeight)
		newY = m_nScreenHeight-1;

#else // ! ROTATION_ENABLE
	int newX,newY;	// Hot spot is currently 32,32
	int nHideCursor = -33;

	switch (m_iRotate)
	{
		case DMDO_270:
			newX = m_nScreenHeight - y - m_nXHot - 1;	// Hot spot is currently 32,32
			newY = x - m_nYHot;
			break;
		case DMDO_180:
			newX = m_nScreenWidth - x - m_nXHot - 1;
			newY = m_nScreenHeight - y - m_nYHot - 1;
			break;
		case DMDO_90:
			newX = y - m_nXHot;
			newY = m_nScreenWidth - x - m_nYHot - 1;
			break;
		default:
			newX = x - m_nXHot;
			newY = y - m_nYHot;
			break;
	}
#endif // ROTATION_ENABLE

	if (x == nHideCursor)
		DisableCursor();

	ULONG dwVal = PEEK_32(CRT_HWC_LOCATION);

	if (newX >= 0)
	{
		dwVal = FIELD_VALUE(dwVal, CRT_HWC_LOCATION, X, newX); 
		dwVal = FIELD_SET(dwVal, CRT_HWC_LOCATION, LEFT, INSIDE);
	}
	else
	{
		dwVal = FIELD_VALUE(dwVal, CRT_HWC_LOCATION, X, -newX); 
		dwVal = FIELD_SET(dwVal, CRT_HWC_LOCATION, LEFT, OUTSIDE); 
	}

	if (newY >= 0)
	{
		dwVal = FIELD_VALUE(dwVal, CRT_HWC_LOCATION, Y, newY); 
		dwVal = FIELD_SET(dwVal, CRT_HWC_LOCATION, TOP, INSIDE); 
	}
	else
	{
		dwVal = FIELD_VALUE(dwVal, CRT_HWC_LOCATION, Y, -newY); 
		dwVal = FIELD_SET(dwVal, CRT_HWC_LOCATION, TOP, OUTSIDE); 
	}

	POKE_32(CRT_HWC_LOCATION, dwVal);

	if (x != nHideCursor)
		EnableCursor();

 	return (S_OK);
}

void SMIVGXEmu::SetCursorColors(ULONG foreground, ULONG background)
{
	ULONG color3=0x0000; //for invert color, assume it is Black at this time.

	DEBUGMSG(GPE_ZONE_CURSOR, (TEXT("SMI::SetCursorColors(0x%x, 0x%x)\r\n"),
			foreground, background));

	POKE_32(CRT_HWC_COLOR_01, background<<16 | color3 );
	
	POKE_32(CRT_HWC_COLOR_2, foreground	  ); 
}

void SMIVGXEmu::SetCursorAddress(ULONG dwAddress)
{
	ULONG dwAdd = PEEK_32(CRT_HWC_ADDRESS);
	dwAdd = FIELD_VALUE(dwAdd, CRT_HWC_ADDRESS, ADDRESS, dwAddress);
	dwAdd = FIELD_SET(dwAdd, CRT_HWC_ADDRESS, EXT, LOCAL);
	POKE_32(CRT_HWC_ADDRESS, dwAdd);
}

void SMIVGXEmu::DisableCursor(void)
{
	// Disable cursor
	ULONG dwAdd = PEEK_32(CRT_HWC_ADDRESS);
	dwAdd = FIELD_SET(dwAdd, CRT_HWC_ADDRESS, ENABLE, DISABLE);
	POKE_32(CRT_HWC_ADDRESS, dwAdd);
}

void SMIVGXEmu::EnableCursor(void)
{
	// Enable cursor
	ULONG dwAdd = PEEK_32(CRT_HWC_ADDRESS);
	dwAdd = FIELD_SET(dwAdd, CRT_HWC_ADDRESS, ENABLE, ENABLE);
	POKE_32(CRT_HWC_ADDRESS, dwAdd);
}

void SMIVGXEmu::SetupCursor(void)
{
    m_pSMI->m_nVideoMemoryAvail = m_pSMI->m_nVideoMemoryAvail - CURSUR_IMAGE_SIZE;

    m_nCursorMemory = m_pSMI->m_nVideoMemoryAvail;
	DisableCursor();
	
	SetCursorAddress(m_nCursorMemory);
}

SCODE SMIVGXEmu::AllocSurface(GPESurf **ppSurf, int width, int height, EGPEFormat format, int surfaceFlags)
{
	return m_pSMI->AllocSurface(ppSurf, width, height, format, surfaceFlags);
}

#ifdef	DD_ENABLE
SCODE SMIVGXEmu::AllocSurface(DDGPESurf **ppSurf, int width, int height, EGPEFormat format, EDDGPEPixelFormat pixelFormat, int surfaceFlags)
{
	return m_pSMI->AllocSurface(ppSurf, width, height, format, pixelFormat, surfaceFlags);
}
#endif	// DD_ENABLE

#ifdef DD_ENABLE
void SMIVGXEmu::SetVisibleSurface(GPESurf *pSurf, BOOL bWaitForVBlank)
#else
void SMIVGXEmu::SetVisibleSurface(GPESurf *pSurf)
#endif
{
#ifndef DD_ENABLE
	BOOL bWaitForVBlank = FALSE;
#endif

	WaitForNotBusy();

	POKE_32(CRT_FB_ADDRESS,
		FIELD_VALUE(0, CRT_FB_ADDRESS, STATUS, bWaitForVBlank) |
		FIELD_VALUE(0, CRT_FB_ADDRESS, EXT, m_SMISettings.m_bUMA) |
		FIELD_VALUE(0, CRT_FB_ADDRESS, ADDRESS, VgxSurfAddr(pSurf->OffsetInVideoMemory())) |
		0);

}


SCODE SMIVGXEmu::Line(GPELineParms *pLineParms, EGPEPhase phase)
{

	 return m_pSMI->Line(pLineParms, phase);
/*
	if (phase == gpeSingle || phase == gpePrepare)
	{
		pLineParms->pLine = EmulatedLine;
	}
	else if (phase == gpeComplete)
	{
		// Complete
	}

	return S_OK;
*/
}

SCODE SMIVGXEmu::BltPrepare(GPEBltParms *pBltParms)
{
	return m_pSMI->BltPrepare(pBltParms);
/*
	pBltParms->pBlt = EmulatedBlt; // catch all
	return S_OK;
*/
}

SCODE SMIVGXEmu::BltComplete(GPEBltParms *pBltParms)
{
	return m_pSMI->BltComplete(pBltParms);

	//return S_OK;

}

ULONG SMIVGXEmu::DrvEscape(SURFOBJ *pso, ULONG iEsc, ULONG cjIn, PVOID pvIn, 
					 ULONG cjOut, PVOID pvOut)
{
	int	RetVal = 0;	// Default not supported

	return (ULONG) RetVal;
}
#endif	// MULTIMONEMU_ENABLE







⌨️ 快捷键说明

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