The canvas was capped at 100%, so a bigger monitor got a 1920x1080 cockpit in the corner of the screen and maximising did nothing - the layout only ran once at startup. Now the fit is one uniform scale with no ceiling, recomputed whenever the window changes size (maximise, restore, drag), and the canvas is centred in whatever client area it gets. Uniform scale is what locks the aspect: a wider-than-16:9 desktop letterboxes with even black bars instead of stretching the cockpit. Panes gained Resize() so the glass and its button banks re-scale with the canvas; the pixel buffers keep their native source resolution. Scaling up is free quality on the MFDs - their glass is a downscale of a native 640x480 channel until about 200%. Verified on the 3440x1392 ultrawide: opens at 125% (2400x1350) instead of 100%, maximises to 126% centred with even bars, a 1884x661 window fits 61% letterboxed left/right, 1084x961 fits 56% letterboxed top/ bottom, and a 2584x1461 client scales up to 134%. The 3D still renders at -res and D3D stretches it to the canvas, so raise -res to match a large screen for 1:1 pixels; start-windowed.bat and the README say so. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
557 lines
9.7 KiB
C++
557 lines
9.7 KiB
C++
#pragma once
|
|
|
|
#include "..\munga\graph2d.h"
|
|
#include "..\munga\time.h"
|
|
#include <D3DX9.h>
|
|
#include <D3DX9math.h>
|
|
|
|
|
|
class L4graphicsPort;
|
|
class MFDSplitView;
|
|
|
|
//########################################################################
|
|
//######################### Video16BitBuffered ###########################
|
|
//########################################################################
|
|
//
|
|
// X/Y values passed to these routines are assumed to be in
|
|
// the VIDEO DISPLAY COORDINATE SYSTEM, with (0,0) at the top left.
|
|
//
|
|
class Video16BitBuffered :
|
|
public GraphicsDisplay
|
|
{
|
|
public:
|
|
Video16BitBuffered(int x, int y);
|
|
|
|
~Video16BitBuffered();
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
void
|
|
ShowInstance(char *indent);
|
|
|
|
void
|
|
DrawPoint(
|
|
int color,
|
|
int bitmask,
|
|
Enumeration operation,
|
|
int x, int y
|
|
);
|
|
|
|
void
|
|
DrawLine(
|
|
int color,
|
|
int bitmask,
|
|
Enumeration operation,
|
|
int x1, int y1,
|
|
int x2, int y2,
|
|
Logical include_last_pixel
|
|
);
|
|
|
|
void
|
|
DrawFilledRectangle(
|
|
int color,
|
|
int bitmask,
|
|
Enumeration operation,
|
|
int x1, int y1,
|
|
int x2, int y2
|
|
);
|
|
|
|
void
|
|
DrawText(
|
|
int color,
|
|
int bitmask,
|
|
Enumeration operation,
|
|
Logical opaque,
|
|
int rotation,
|
|
Enumeration fontNumber,
|
|
Logical vertical,
|
|
GraphicsDisplay::Justification justification,
|
|
Rectangle2D *clippingRectanglePtr,
|
|
char *stringPointer
|
|
);
|
|
|
|
void
|
|
DrawBitMap(
|
|
int color,
|
|
int bitmask,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
BitMap *bitmap,
|
|
int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates
|
|
);
|
|
|
|
void
|
|
DrawBitMapOpaque(
|
|
int color,
|
|
int background,
|
|
int bitmask,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
BitMap *bitmap,
|
|
int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates
|
|
);
|
|
|
|
void
|
|
DrawPixelMap8(
|
|
int *translation_table,
|
|
int bitmask,
|
|
Enumeration operation,
|
|
Logical opaque,
|
|
int rotation,
|
|
int x, int y,
|
|
PixelMap8 *pixelmap,
|
|
int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates
|
|
);
|
|
|
|
void
|
|
DrawPixelMap8SingleColor(
|
|
int color,
|
|
int bitmask,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
PixelMap8 *pixelmap,
|
|
int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates
|
|
);
|
|
|
|
protected:
|
|
void
|
|
MarkChangedLines(int screenTop, int screenBottom);
|
|
|
|
void
|
|
buildDestPointer(
|
|
int x, int y,
|
|
Word **pixelPointer,
|
|
LWord **changed_bit_pointer,
|
|
LWord *changed_bit
|
|
);
|
|
|
|
Logical
|
|
valid;
|
|
int
|
|
width,
|
|
changedBitWidth,
|
|
height,
|
|
maximumX,
|
|
maximumY;
|
|
|
|
PixelMap16
|
|
pixelBuffer;
|
|
Byte
|
|
*changedLine;
|
|
LWord
|
|
*changedBit;
|
|
};
|
|
|
|
|
|
//########################################################################
|
|
//################################ SVGA16 ################################
|
|
//########################################################################
|
|
struct SVGA16Palette
|
|
{
|
|
Word
|
|
hardwarePort;
|
|
Logical
|
|
modified;
|
|
Palette8
|
|
paletteData;
|
|
Scalar
|
|
flashAccumulator,
|
|
flashRate;
|
|
|
|
enum PaletteID
|
|
{
|
|
maskStates=4
|
|
};
|
|
unsigned char
|
|
mask[maskStates];
|
|
int
|
|
previousMaskState;
|
|
};
|
|
|
|
|
|
class SVGA16 :
|
|
public Video16BitBuffered
|
|
{
|
|
friend class L4GraphicsPort; // for palette access
|
|
|
|
public:
|
|
enum PaletteID {
|
|
NativePalette=0,
|
|
SecondaryPalette,
|
|
AuxiliaryPalette1,
|
|
AuxiliaryPalette2,
|
|
PaletteCount
|
|
};
|
|
|
|
SVGA16(
|
|
int mode,
|
|
int width,
|
|
int height,
|
|
int page_size,
|
|
int mem_granularity,
|
|
int bytes_per_line,
|
|
int page_function_pointer,
|
|
int special_interface,
|
|
bool windowed,
|
|
int *secondaryIndex,
|
|
int *aux1Index,
|
|
int *aux2Index
|
|
);
|
|
|
|
~SVGA16();
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
void
|
|
ShowInstance(char *indent);
|
|
|
|
Logical
|
|
Update(Logical forceall);
|
|
void
|
|
Refresh();
|
|
void
|
|
UpdatePalette();
|
|
|
|
void
|
|
FadeToPalettes(Scalar fade_time);
|
|
void
|
|
FadeToWhite(Scalar fade_time);
|
|
void
|
|
FlashPalette(
|
|
int palette_number,
|
|
Scalar rate,
|
|
unsigned char *stateList
|
|
);
|
|
void
|
|
UnflashPalette(int palette_number);
|
|
|
|
void
|
|
FunkyVideo(Logical on_off);
|
|
|
|
protected:
|
|
|
|
void BuildWindows(unsigned int width, unsigned int height, bool windowed, int *secondaryIndex, int *aux1Gauge, int *aux2Gauge);
|
|
|
|
|
|
void
|
|
ResetUpdatePosition();
|
|
|
|
int
|
|
pageSize,
|
|
pageDelta,
|
|
widthInBytes,
|
|
pageFcnPtr,
|
|
specialInterface;
|
|
|
|
int
|
|
currentPageNumber,
|
|
nextPageNumber,
|
|
lineNumber;
|
|
long
|
|
destOffset;
|
|
Byte
|
|
*changedLinePointer;
|
|
Word
|
|
*sourcePointer;
|
|
LWord
|
|
*changedBitPointer;
|
|
|
|
enum PaletteFadeState
|
|
{
|
|
staticPalette,
|
|
fadeToWhite,
|
|
whitePalette,
|
|
fadeToColor
|
|
};
|
|
|
|
PaletteFadeState
|
|
paletteFadeState;
|
|
Scalar
|
|
fadeAlpha,
|
|
fadeUnitsPerSecond;
|
|
Time
|
|
previousFadeTime;
|
|
|
|
// This array is closely linked to the PaletteID enumeration, above
|
|
SVGA16Palette
|
|
palette[PaletteCount];
|
|
|
|
private:
|
|
int NUMGAUGEWINDOWS;
|
|
HWND *gaugeWindows;
|
|
LPDIRECT3DDEVICE9 *mDevice;
|
|
D3DPRESENT_PARAMETERS *mPresentParams;
|
|
LPDIRECT3DVERTEXBUFFER9 *mVertBuffers;
|
|
LPDIRECT3DTEXTURE9 *mSurfaces;
|
|
DWORD *mLockFlags;
|
|
RECT *mSurfaceRects;
|
|
|
|
int mDisplayToUpdate;
|
|
|
|
//------------------------------------------------------------------
|
|
// Split-view mode (L4MFDSPLIT=1): the five channel-packed MFDs and
|
|
// the rotated map render as their own desktop windows; the packed
|
|
// D3D gauge windows stay hidden. See L4MFDVIEW.h.
|
|
//------------------------------------------------------------------
|
|
enum SplitViewID {
|
|
SplitMFDUpperLeft = 0,
|
|
SplitMFDUpperCenter,
|
|
SplitMFDUpperRight,
|
|
SplitMFDLowerLeft,
|
|
SplitMFDLowerRight,
|
|
SplitMap,
|
|
SplitViewCount
|
|
};
|
|
|
|
void
|
|
FillSplitMFD(
|
|
SplitViewID view,
|
|
DWORD mask16,
|
|
int shift
|
|
);
|
|
|
|
public:
|
|
//------------------------------------------------------------------
|
|
// Fit the cockpit into a client area: one uniform scale keeps the
|
|
// 1920x1080 canvas at its own aspect (so an ultrawide letterboxes
|
|
// rather than stretching), centred in whatever space it is given.
|
|
// Re-run whenever the cockpit window is resized.
|
|
//------------------------------------------------------------------
|
|
void
|
|
LayoutCockpit(int client_w, int client_h);
|
|
|
|
static SVGA16 *
|
|
GetCockpit()
|
|
{ return activeCockpit; }
|
|
|
|
protected:
|
|
Logical
|
|
splitViews;
|
|
MFDSplitView
|
|
*splitView[SplitViewCount];
|
|
HWND
|
|
cockpitViewscreen; // child pane the 3D scene presents into
|
|
|
|
static SVGA16
|
|
*activeCockpit; // the instance owning the cockpit window
|
|
};
|
|
|
|
//########################################################################
|
|
//########################## L4GraphicsPort ##############################
|
|
//########################################################################
|
|
//
|
|
// X/Y values passed to these routines are assumed to be in
|
|
// the GRAPHICS COORDINATE SYSTEM, with (0,0) at the bottom left.
|
|
//
|
|
class L4GraphicsPort :
|
|
public GraphicsPort
|
|
{
|
|
public:
|
|
enum ChannelEnableID {
|
|
RedChannel,
|
|
GreenChannel,
|
|
BlueChannel,
|
|
AllChannels,
|
|
|
|
DirectColor,
|
|
BlankColor,
|
|
|
|
RedChannelTransparentZero=0x80,
|
|
GreenChannelTransparentZero,
|
|
BlueChannelTransparentZero,
|
|
AllChannelsTransparentZero
|
|
};
|
|
|
|
L4GraphicsPort(
|
|
Video16BitBuffered *graphics_display,
|
|
const char *name,
|
|
int rotation,
|
|
int bit_mask,
|
|
SVGA16::PaletteID palette_ID,
|
|
L4GraphicsPort::ChannelEnableID channel_enable
|
|
);
|
|
|
|
~L4GraphicsPort();
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
void
|
|
ShowInstance(char *indent);
|
|
|
|
void
|
|
SetSecondaryPalette(
|
|
Palette8 *source_palette
|
|
);
|
|
|
|
void
|
|
SetAuxiliaryPalette();
|
|
|
|
void
|
|
SetColor(
|
|
PaletteTriplet *source_color,
|
|
int color_index
|
|
);
|
|
|
|
void
|
|
DrawPoint(
|
|
int color,
|
|
Enumeration operation,
|
|
int x, int y
|
|
);
|
|
|
|
void
|
|
DrawLine(
|
|
int color,
|
|
Enumeration operation,
|
|
int x1, int y1,
|
|
int x2, int y2,
|
|
Logical include_last_pixel
|
|
);
|
|
|
|
void
|
|
DrawFilledRectangle(
|
|
int color,
|
|
Enumeration operation,
|
|
int x1, int y1,
|
|
int x2, int y2
|
|
);
|
|
|
|
void
|
|
DrawText(
|
|
int color,
|
|
Enumeration operation,
|
|
Logical opaque,
|
|
int rotation,
|
|
Enumeration fontNumber,
|
|
Logical vertical,
|
|
GraphicsDisplay::Justification justification,
|
|
Rectangle2D *clippingRectanglePtr,
|
|
char *stringPointer
|
|
);
|
|
|
|
void
|
|
DrawBitMap(
|
|
int color,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
BitMap *bitmap,
|
|
int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates
|
|
);
|
|
|
|
void
|
|
DrawBitMapOpaque(
|
|
int color,
|
|
int background,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
BitMap *bitmap,
|
|
int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates
|
|
);
|
|
|
|
void
|
|
DrawPixelMap8(
|
|
Enumeration operation,
|
|
Logical opaque,
|
|
int rotation,
|
|
int x, int y,
|
|
PixelMap8 *pixelmap,
|
|
int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates
|
|
);
|
|
|
|
void
|
|
DrawPixelMap8SingleColor(
|
|
int color,
|
|
Enumeration operation,
|
|
int rotation,
|
|
int x, int y,
|
|
PixelMap8 *pixelmap,
|
|
int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates
|
|
);
|
|
|
|
void
|
|
SetPaletteID(SVGA16::PaletteID palette_ID)
|
|
{
|
|
Check(this);
|
|
paletteID = palette_ID;
|
|
}
|
|
|
|
void
|
|
SetEnableID(L4GraphicsPort::ChannelEnableID channel_enable)
|
|
{
|
|
Check(this);
|
|
channelEnable = channel_enable;
|
|
}
|
|
|
|
int
|
|
GetBitMask()
|
|
{
|
|
Check(this);
|
|
return bitMask;
|
|
}
|
|
SVGA16::PaletteID
|
|
paletteID;
|
|
|
|
protected:
|
|
void
|
|
convertPortPair(
|
|
int *xp,
|
|
int *yp,
|
|
int x,
|
|
int y
|
|
);
|
|
|
|
void
|
|
BuildDirectTranslation(
|
|
Palette8 *source_palette
|
|
);
|
|
|
|
void
|
|
BuildSecondaryPalette(
|
|
Palette8 *source_palette
|
|
);
|
|
|
|
void
|
|
BuildAuxiliaryPalette();
|
|
|
|
void
|
|
BuildSecondaryTranslation();
|
|
|
|
void
|
|
BuildAuxiliaryTranslation();
|
|
|
|
void
|
|
BlankPalette();
|
|
|
|
void
|
|
BuildSecondaryColor(
|
|
PaletteTriplet *source_triplet,
|
|
int color_number
|
|
);
|
|
//------------------------------------------------------------
|
|
// Protected data
|
|
//------------------------------------------------------------
|
|
int
|
|
translationTable[256];
|
|
unsigned char
|
|
myColor[256];
|
|
|
|
int
|
|
baseRotation,
|
|
bitMask,
|
|
numberOfBits,
|
|
maximumX,
|
|
maximumY;
|
|
|
|
|
|
L4GraphicsPort::ChannelEnableID
|
|
channelEnable;
|
|
};
|