📄 mmonemu.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(®ister_table, &mode, PANEL, m_nScreenBpp, clock);
//programMode(®ister_table);
setModeRegisters(®ister_table, &mode, CRT, m_nScreenBpp, clock);
programMode(®ister_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 + -