Files
BT411/engine/MUNGA_L4/L4VB16.h
T
arcattackandClaude Fable 5 6783619069 Gitea #9: the upper-MFD PRESET pages (3 MFDs x 5) live -- SetPresetMode
table re-decoded to the ModeMFD bits + desktop J/K/L page cycle

The preset system was unwired by ONE defect in the message layer: the
SetPresetMode @004d1b24 table @0051dbf0 had been transcribed from the
section dump as BIG-endian dwords ({0x1e,0x01000000} instead of
{0x1e,0x01}), so a preset press set a garbage high bit -- and for group 1
items 3-4 / group 2 items 0-2 stomped the LIVE NonMapping / Intercom /
ModeSecondary* bits -- while the real page bits never moved.  Ground
truth (section_dump.txt:72901-72908, little-endian + BTL4MODE.HPP [T0]):
set = ModeMFD{1,2,3}{Quad,Eng1-4} = 1<<(group*5+item), bits 0-14, fully
disjoint from the #6 secondary trio (bits 18-20); group 2 is MFD3, NOT a
duplicate of the secondary views.

What the 15 presets show (l4gauge.cfg): group = the MFD (Mfd1 lower left
/ Mfd2 upper center / Mfd3 lower right), item 0 = the btquad.pcx Quad
overview (up to 4 vehicleSubSystems cluster panels), items 1-4 = the
full-screen engineering-detail pages (bteng.pcx + prepEngr screens
group*4+1..4 + the cluster eng children: GENERATOR SELECT A-D, POWER
graph, COOLING loop, DAMAGE, ammo).  Empty screens are authored per mech
(Blackhawk: 3/11/12 empty).

Authentic dispatch (streamed "L4" .CTL EventMappings, BT_CTRLMAP_LOG
dump): each MFD owns the 8-button RIO bank around it, MODE-MASK-gated --
Mfd1 = 0x08-0x0F, Mfd2 = 0x20-0x27, Mfd3 = 0x00-0x07.  Quad page ->
direct-select buttons for the POPULATED eng pages (mapper msgs
Aux1Eng1-4 0x4-0x7 / Aux2* 0x9-0xC / Aux3* 0xE-0x11); eng page -> one
back-to-Quad button (0x3/0x8/0xD) + per-subsystem controls.  These
records already install and fire on desktop (btinput passes the live
manager mask), so the NUMPAD profile's 0x20-0x27 keys page MFD2
authentically.

Port wiring (the #6 pattern): keys J/K/L -> actions Mfd1/2/3Cycle ->
gBTPresetCycle -> L4MechControlsMapper::CyclePresetModeNow(group) -- a
documented desktop shim (24 mode-dependent pod buttons don't fit a
keyboard) that cycles Quad -> populated Eng pages -> Quad, visiting
exactly the pod-reachable set; the body is the authentic SetPresetMode.

Dev-composite: BTDrawGaugeSurfaces now draws the Eng1-3 planes at their
sibling cells and skips any mono plane whose channel is BlankColor,
honoring the mode-driven reconfigure (RemapGraphicsPort) -- each dev
cell shows the ACTIVE page like the pod monitor.  This supersedes and
removes the 2026-07-12 GAUGREND "frozen-dial" scaffold (forced all 15
page bits active under BT_DEV_GAUGES; it pinned the shared Eng plane on
the highest screen and ate the page flips).

Pixel-verified (BT_PRESET_TEST + BT_DEV_GAUGES_DOCK + BT_SHOT,
Blackhawk): all three MFDs page Quad -> SYSTEM NN eng details -> back to
Quad in lockstep with the [mode] preset mask log; group 0 skips the
authored-empty screen 3, group 2 skips 11/12.  Un-regressed: N display
cycle (0x450421->0x490421->0x510421, page bits intact), M control mode,
CONTROLS.MAP 52 bindings parse clean.

Diags: BT_MODE_LOG ([mode] preset), BT_PRESET_TEST=<frame>.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 17:30:35 -05:00

533 lines
9.6 KiB
C++

#pragma once
#include "..\munga\graph2d.h"
#include "..\munga\time.h"
#include <D3DX9.h>
#include <D3DX9math.h>
class L4graphicsPort;
//########################################################################
//######################### 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;
LPDIRECT3DTEXTURE9 mDevSurfaceTex[10]; // DEV-COMPOSITE: one texture per gauge surface
// (sec/radar + the 5 MFD bit-planes + the Eng1-3
// preset-page planes, Gitea #9), on the MAIN device.
public:
// DEV-COMPOSITE: extract ONE gauge surface from the shared pixelBuffer into
// mDevSurfaceTex[slot] on the given (main) device + draw it as a quad at (dstX,dstY,
// dstW,dstH). monoTint < 0 -> palette-expand (sec/radar, case-0 LUT); monoTint >= 0
// -> mono bit-plane expand ((word & mask) ? tint : 0) for an MFD plane. See
// BTDrawGaugeSurfaces (L4VB16.cpp).
// rotateCCW: 0 = as-is; 1/3 = display the texture turned 90 degrees (the
// pod's portrait-mounted secondary CRT; the dev panel unrotates it).
void DrawDevSurface(LPDIRECT3DDEVICE9 device, int slot, int mask, int paletteID,
int monoTint, float dstX, float dstY, float dstW, float dstH,
int rotateCCW = 0);
};
//########################################################################
//########################## 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;
}
// DEV-COMPOSITE (Gitea #9): the dock honors the live reconfigure state --
// a plane whose channel is currently BlankColor contributes nothing on the
// pod's shared-word palette LUT, so the dev panel skips drawing it.
L4GraphicsPort::ChannelEnableID
GetEnableID()
{
Check(this);
return channelEnable;
}
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;
};