Added tmdfs mode 4 for 2x 640x480 monitors

This commit is contained in:
2026-07-16 11:14:50 -05:00
parent 4cb3ab8ea8
commit 92a94d0ad6
7 changed files with 194 additions and 6 deletions
+13
View File
@@ -0,0 +1,13 @@
{
// Legacy source files use CP949 (Korean Windows encoding, superset of EUC-KR).
// VS Code defaults to UTF-8, which silently corrupts the Korean comment bytes
// on save. Setting encoding to cp949 here preserves them exactly.
"files.encoding": "cp949",
// Let VS Code try to detect encoding per-file, falling back to cp949 above.
"files.autoGuessEncoding": true,
// Preserve the original Windows CRLF line endings (Git's * -text in
// .gitattributes also prevents conversion, but this keeps VS Code consistent).
"files.eol": "\r\n"
}
@@ -46,6 +46,8 @@ videoDevices BufferedDevices[8];
int g_nDualHead = -1; // jcem
int g_nDualHead2 = -1; // jcem
int g_nNonDualHead = -1; // jcem
int g_nMFD1 = -1; // mode 4: left 640x480 MFD monitor
int g_nMFD2 = -1; // mode 4: right 640x480 MFD monitor
// MSL 5.03 Mechview
int g_nMechViewType; // jcem : 0 - no mechview, 1 - on radar screen, 2 - on main screen
@@ -380,6 +382,20 @@ void FindVideoCards()
}
}
}
// Mode 4 (split dual 640x480): find two extra D3D devices beyond
// FullScreenDevice and g_nNonDualHead. These need no special resolution.
{
int found = 0;
for (int t0 = 0; t0 < NumDevices && found < 2; t0++) {
if (t0 == Environment.FullScreenDevice) continue;
if (t0 == g_nNonDualHead) continue;
if (DeviceArray[t0].D3DCaps.dwDevCaps & D3DDEVCAPS_HWRASTERIZATION) {
if (found == 0) g_nMFD1 = t0;
else g_nMFD2 = t0;
found++;
}
}
}
// jcem
//
// Check any known video cards have up to date drivers (Only on Windows9x)
@@ -940,6 +940,13 @@ void gos_UpdateDisplay( bool Everything )
radar_device.BeginScene();
}
break;
case 4:
// Same 7-step cadence as mode 1: clear both MFD devices at step 0.
if(sh_step==0){
radar_device.BeginScene();
mfd_device.BeginScene(); // also clears mfd_device_right internally
}
break;
}
}else if(hsh_mrdev_initialized){
mr_device.BeginScene();
@@ -1106,6 +1113,21 @@ void gos_UpdateDisplay( bool Everything )
break;
case 3:
break;
case 4:
// Same 7-step cadence as mode 1. Flip all three: radar, left MFD,
// right MFD. mfd_device_right.pDDSFront is NULL if not initialised
// (e.g. g_nMFD2 = -1), so guard the flip.
sh_step++;
sh_step%=7;
if(sh_step==0) {
radar_device.EndScene();
radar_device.pDDSFront->Flip(0,DDFLIP_DONOTWAIT|DDFLIP_NOVSYNC);
mfd_device.EndScene();
mfd_device.pDDSFront->Flip(0,DDFLIP_DONOTWAIT|DDFLIP_NOVSYNC);
if (mfd_device_right.pDDSFront)
mfd_device_right.pDDSFront->Flip(0,DDFLIP_DONOTWAIT|DDFLIP_NOVSYNC);
}
break;
}
}else if(hsh_mrdev_initialized){
mr_device.EndScene();
@@ -945,6 +945,8 @@ void CHSH_Device::DrawTexture(float pt[4][2],DWORD dwColor,float tx1,float ty1,f
extern int g_nDualHead;
extern int g_nNonDualHead;
extern int g_nMFD1; // mode 4: left 640x480 MFD monitor
extern int g_nMFD2; // mode 4: right 640x480 MFD monitor
// MSL 5.03 Mechview
extern int g_nMechViewType; // jcem : 0 - no mechview, 1 - on radar screen, 2 - on main screen
@@ -1066,6 +1068,23 @@ bool CMR_Device::LoadMRTargetTexture(const char *mechtexturename)
CMR_Device mr_device;
// Mode 4: the right-hand 640x480 MFD device. Shares VRAM with mfd_device
// (same GPU), so mfd_device's pDDSTarget texture can be passed to this
// device's pD3DDevice->SetTexture without a copy.
CMFDRight_Device mfd_device_right;
bool CMFDRight_Device::InitFirst()
{
// Take over g_nMFD2 monitor at 640x480 fullscreen.
return CHSH_Device::InitFirst(g_nMFD2, 640, 480);
}
bool CMFDRight_Device::InitSecond()
{
// Create flip chain, D3D device and a render-target slot (1024x512).
return CHSH_Device::InitSecond(1024, 512);
}
/////////////////////////////////// CRadar_Device ///////////////////////////////////
const char g_szRadarShutdown[] = "SHUT\nDOWN";
const char g_szRadarStartup[] = "START\nUP";
@@ -1349,7 +1368,7 @@ static DWORD channel_color[6]={
CMFD_Device::CMFD_Device()
: ch((DWORD)-1)
: ch((DWORD)-1), m_pRightDevice(NULL)
{
}
@@ -1359,6 +1378,15 @@ CMFD_Device::~CMFD_Device()
bool CMFD_Device::InitFirst()
{
// Mode 4: use g_nMFD1 (640x480) for left panel; also start up the right
// device here so both displays are ready before InitSecond runs.
if (g_nTypeOfMFDs == 4) {
m_pRightDevice = &mfd_device_right;
CHSH_Device::InitFirst(g_nMFD1, 640, 480); // left device
mfd_device_right.InitFirst(); // right device display mode
return true;
}
m_pRightDevice = NULL;
return CHSH_Device::InitFirst(g_nDualHead,1280,480);
}
@@ -1409,6 +1437,11 @@ bool CMFD_Device::InitSecond()
pD3DDevice->SetMaterial( &mtrl );
pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, 0xffffffff );
// Mode 4: create flip chain + D3D device for the right 640x480 monitor.
if (g_nTypeOfMFDs == 4 && m_pRightDevice) {
mfd_device_right.InitSecond();
}
return true;
}
@@ -1450,6 +1483,11 @@ bool CMFD_Device::BeginChannel(DWORD channel)
return false;
}
break;
case 4:
// Same 7-step timing as mode 1: channels 0-4 map to sh_step 2-6.
if (sh_step != (int)(channel + 2))
return false;
break;
}
ch=channel;
@@ -1475,8 +1513,42 @@ bool CMFD_Device::EndChannel()
gCaptureScreen = 0;
}
SetRenderTargetBackbuffer();
pD3DDevice->BeginScene();
// Mode 4: route this channel's blit to the correct physical monitor.
// Handled here, before the modes 1-3 SetRenderTargetBackbuffer/BeginScene
// block, so each path has exactly one matched Begin/EndScene pair.
// Channels 0-2 go to the LEFT device (this, g_nMFD1).
// Channels 3-4 go to the RIGHT device (m_pRightDevice, g_nMFD2).
// pDDSTarget was created by this device's pDD; both devices are on the
// same GPU so VRAM textures are mutually accessible.
if (g_nTypeOfMFDs == 4 && m_pRightDevice) {
CHSH_Device* target = (ch >= 3) ? m_pRightDevice : static_cast<CHSH_Device*>(this);
target->SetRenderTargetBackbuffer();
target->pD3DDevice->BeginScene();
target->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,TRUE);
target->pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND,D3DBLEND_ONE);
target->pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND,D3DBLEND_ONE);
target->pD3DDevice->SetTexture(0, pDDSTarget);
DWORD color4 = channel_color[ch];
float w4 = (float)target->size_back.cx; // 640
float h4 = (float)target->size_back.cy; // 480
float w2_4 = (float)size_target.cx; // 1024
float h2_4 = (float)size_target.cy; // 512
D3DTLVERTEX V4[4];
V4[0]=D3DTLVERTEX(D3DVECTOR( -0.5f,h4-0.5f,0.9f),1.0f,color4,0, 0/w2_4,h4/h2_4);
V4[1]=D3DTLVERTEX(D3DVECTOR( -0.5f, -0.5f,0.9f),1.0f,color4,0, 0/w2_4, 0/h2_4);
V4[2]=D3DTLVERTEX(D3DVECTOR(w4-0.5f,h4-0.5f,0.9f),1.0f,color4,0,w4/w2_4,h4/h2_4);
V4[3]=D3DTLVERTEX(D3DVECTOR(w4-0.5f, -0.5f,0.9f),1.0f,color4,0,w4/w2_4, 0/h2_4);
target->pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DFVF_TLVERTEX,V4,4,NULL);
target->pD3DDevice->EndScene();
ch = (DWORD)-1;
} else {
// Modes 1-3: blit to half of the single 1280-wide (or 640-wide) backbuffer.
SetRenderTargetBackbuffer();
pD3DDevice->BeginScene();
pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,TRUE);
pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND,D3DBLEND_ONE);
@@ -1504,8 +1576,9 @@ bool CMFD_Device::EndChannel()
pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX , Vertices, 4, NULL );
pD3DDevice->EndScene();
ch = (DWORD)-1;
pD3DDevice->EndScene();
ch = (DWORD)-1;
}
}
return true;
}
@@ -1533,6 +1606,25 @@ bool CMFD_Device::BeginScene()
pD3DDevice->Clear(1,&s_rc2,D3DCLEAR_TARGET ,0,1.0f,0);
//pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET ,0,1.0f,0);
}break;
case 4:
// Clear and draw background grid on the LEFT device.
SetRenderTargetBackbuffer();
pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,1.0f,0);
pD3DDevice->BeginScene();
if(sh_game_started) DrawMFDBackGrid();
pD3DDevice->EndScene();
// Clear and draw background grid on the RIGHT device.
if (m_pRightDevice) {
m_pRightDevice->SetRenderTargetBackbuffer();
m_pRightDevice->pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,1.0f,0);
m_pRightDevice->pD3DDevice->BeginScene();
if(sh_game_started) {
m_pRightDevice->pD3DDevice->SetTexture(0,0);
m_pRightDevice->DrawQuadList(8,rcs640_solo,0xFFFFFFFF);
}
m_pRightDevice->pD3DDevice->EndScene();
}
return true; // skip the common BeginScene/DrawGrid/EndScene below
}
pD3DDevice->BeginScene();
if(sh_game_started) {
@@ -1559,6 +1651,11 @@ bool CMFD_Device::Release()
SAFE_RELEASE(pDDSDamageTexture);
// MSL 5.03 Target Damage Display
SAFE_RELEASE(pDDSTargetTexture);
// Mode 4: release the right device before releasing this (left) device.
if (g_nTypeOfMFDs == 4 && m_pRightDevice) {
m_pRightDevice->Release();
m_pRightDevice = NULL;
}
CHSH_Device::Release();
}
return true;
@@ -1700,6 +1797,19 @@ static RECT rcs640[8]={
{1120-1,440,1120+1,480},
};
// Mode 4: same grid pattern as rcs640 but offset to x=0 for a standalone
// 640x480 surface (left half of rcs1280).
static RECT rcs640_solo[8]={
{0,40,640,42},
{ 160-1,0, 160+1,40},
{ 320-1,0, 320+1,40},
{ 480-1,0, 480+1,40},
{0,480-42,640,480-40},
{ 160-1,440, 160+1,480},
{ 320-1,440, 320+1,480},
{ 480-1,440, 480+1,480},
};
bool CMFD_Device::DrawMFDBackGrid()
{
pD3DDevice->SetTexture(0,0);
@@ -1714,6 +1824,11 @@ bool CMFD_Device::DrawMFDBackGrid()
case 2:
DrawQuadList(8,rcs640,0xFFFFFFFF);
break;
case 4:
// Left device uses the left-half grid (0..640).
// Right device grid is drawn separately in BeginScene.
DrawQuadList(8,rcs640_solo,0xFFFFFFFF);
break;
}
return true;
@@ -2489,6 +2604,9 @@ bool IsMultimonitorAvaliable()
if ((*g_pfnCTCL_GetType)()==_ECTCL_CameraShip)
return false;
}
// Mode 4 uses its own device slots ? g_nDualHead is not required.
if (g_nTypeOfMFDs == 4)
return (g_nMFD1 != -1 && g_nMFD2 != -1);
if (g_nDualHead != -1) {
// 0 - no MFDs, 1 - orginal(5+1=dual & single), 2 - B&W(3 + 1=1 dual), 3 - color(3 + 1=2 dual)
switch(g_nTypeOfMFDs)
@@ -169,6 +169,7 @@ public:
LPDIRECTDRAWSURFACE7 pDDSTargetTexture;//메크 데미지 텍스쳐..
DWORD ch; //current channel....
CHSH_Device* m_pRightDevice; // mode 4: pointer to right 640x480 device (NULL in modes 1-3)
public:
CMFD_Device();
~CMFD_Device();
@@ -189,6 +190,19 @@ public:
bool DrawMFDDefaultBackAux1(int state);
};
// Mode 4 (split dual 640x480): right-side MFD device on its own 640x480 monitor.
// Same GPU as the left device (mfd_device), so VRAM textures are shared.
class CMFDRight_Device : public CHSH_Device
{
public:
CMFDRight_Device() {}
bool InitFirst();
bool InitSecond();
virtual bool BeginScene() { return true; }
virtual bool EndScene() { return true; }
virtual bool Release() { return CHSH_Device::Release(); }
};
class CMR_Device:public CHSH_Device
{
public:
@@ -212,6 +226,7 @@ void HSH_DirectDrawRelease2();
extern CRadar_Device radar_device;
extern CMFD_Device mfd_device;
extern CMFDRight_Device mfd_device_right;
extern CMR_Device mr_device;
extern bool use_shgui;
extern int sh_step;
+4
View File
@@ -14820,6 +14820,10 @@ void __stdcall CTCL_UpdateMechView()
mfd_device.BeginScene();
sh_step = 4;
break;
case 4:
// Same 7-step cadence as mode 1.
sh_step = 6;
break;
}
}
else
@@ -1440,7 +1440,7 @@ int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int n
if (token && token[7])
{
int n = atoi(&token[7]);
if ((0 <= n) && (n <= 3)) // 0 - no MFDs, 1 - orginal(5+1=dual & single), 2 - B&W(3 + 1=1 dual), 3 - color(3 + 1=2 dual)
if ((0 <= n) && (n <= 4)) // 0 - no MFDs, 1 - orginal(5+1=dual & single), 2 - B&W(3 + 1=1 dual), 3 - color(3 + 1=2 dual), 4 - split dual 640x480
g_nTypeOfMFDs = n;
}
token = strstr(all_lower, "-trio ");