From 7c3d089d9c39febcc484dea9ea2253f22d2966e3 Mon Sep 17 00:00:00 2001 From: Cyd Date: Wed, 29 Jul 2026 22:12:06 -0500 Subject: [PATCH] BT410 5.3.83: MFD-bleed hardening -- the uninitialised half of the 6-bit colour head's translation table Operator report: "artifacts bleeding over from the radar display into the MFDs, I have noticed this in the BT411 builds as well, but does not happen in the original." MECHANISM (proven from the archive source, not inferred): The ten cockpit heads are not ten framebuffers -- L4GAUGE.CFG gives each port a BIT MASK into ONE 16-bit buffer. The colour head is six bits (sec, 0x003F); the MFDs are bits 8-15 of the same words. A colour-head defect can therefore only ever surface as MFD garbage, which is exactly the reported shape. The two translation-table builders in L4VB16.CPP are asymmetric: BuildSecondaryTranslation (:5419) writes ONLY the active-bit combinations -- 1< BuildSecondaryTranslation refills 0..63 over the top without disturbing the zeroed tail. WHAT IS AND IS NOT PROVEN -- the honest scoreboard: PROVEN non-regressive. Gauge A/B, three boots: unfixed x2 and fixed x1 score identically on every head (Mfd1 132/0, Mfd2 37/7, Mfd3 23/0, Eng1/2/3 and Comm exact), against a ~6px across-boot noise floor established by re-booting the same binary. NOT PROVEN to cure the symptom. The A/B rig captures the boot/attract cockpit, where the MFD heads already show ZERO extra pixels -- there is no bleed there to remove. The operator's report is in-mission with the radar live. This is a hardening change against a real uninitialised read that matches the symptom exactly; the cure needs a mission-state capture to confirm. METHOD NOTE: the first "fixed" capture appeared to regress the MFDs by ~2700px and nearly got the change reverted. It was a bad grab caught mid-draw -- rebuild-and-rerun matched the unfixed numbers exactly. The two-agreeing-runs rule earned its keep; a single run would have thrown away a correct change. Worth noting the noise floor that mattered was ACROSS boots, not the within-boot floor measured first. Co-Authored-By: Claude Fable 5 --- restoration/source410/MUNGA_L4/L4GREND.CPP | 958 +++++++++++++++++++++ 1 file changed, 958 insertions(+) create mode 100644 restoration/source410/MUNGA_L4/L4GREND.CPP diff --git a/restoration/source410/MUNGA_L4/L4GREND.CPP b/restoration/source410/MUNGA_L4/L4GREND.CPP new file mode 100644 index 00000000..f6c4e732 --- /dev/null +++ b/restoration/source410/MUNGA_L4/L4GREND.CPP @@ -0,0 +1,958 @@ +//===========================================================================// +// File: l4grend.cc // +// Project: MUNGA Brick: LBE4 Gauge Renderer // +// Contents: // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 02/10/95 CPB Initial coding. // +// 04/12/95 CPB Moved BuildGraphicsPorts in from RP/BTL4GRND.CPP. // +//---------------------------------------------------------------------------// +// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved // +// PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#include +#pragma hdrstop + +#if !defined(L4APP_HPP) +# include +#endif + +#if !defined(TIME_HPP) +# include // for profiling +#endif + +#if !defined(L4GREND_HPP) +# include +#endif + +#if !defined(L4GAUGE_HPP) +# include +#endif + +#if !defined(MISSION_HPP) +# include +#endif + +#if !defined(L4PLASMA_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) cout << n +#else +# define Test_Tell(n) +#endif + +// +//############################################################################# +// L4MethodDescription list +//############################################################################# +// +MethodDescription + ChainToPrevious = METHOD_DESCRIPTION_CHAIN(NULL); // Null:end of chain + +MethodDescription + *L4MethodDescription[] = + { + &MakeConfigMethodDescription, + &MakeExternConfigMethodDescription, + &BackgroundReconfig::methodDescription, + &BackgroundLine::methodDescription, + &BackgroundRect::methodDescription, + &BackgroundFilledRect::methodDescription, + &BackgroundPixelmap::methodDescription, + &BackgroundBitmap::methodDescription, + &NumericDisplayScalar::methodDescription, + &NumericDisplaySpeed::methodDescription, + &NumericDisplayInteger::methodDescription, + &DigitalClock::methodDescription, + &RankAndScore::methodDescription, + &BarGraphSolidScalar::methodDescription, + &BarGraphPixelMapScalar::methodDescription, + &ColorState::methodDescription, + &TwoState::methodDescription, + &SegmentArcNormalized::methodDescription, + &ChainToPrevious + }; + +// +//############################################################################# +// L4GaugeRenderer +//############################################################################# +// +L4GaugeRenderer::L4GaugeRenderer(): + GaugeRenderer() +{ + // + //--------------------------------------------------------------------- + // Ensure that graphicsDisplay is NULL + //--------------------------------------------------------------------- + // + graphicsDisplay = NULL; + externalDisplay = NULL; + + palettesAreActive = True; + scrambleVideoFlag = False; + + char + *mode_string = getenv("L4GAUGE"); + // + //--------------------------------------------------------------------- + // NOTE that L4Application::Initialize() searches for the environment + // variable "L4GAUGE" to determine whether or not to create + // a gauge renderer. + //--------------------------------------------------------------------- + // + if (mode_string != NULL) + { + // + //--------------------------------------------------------------------- + // Attempt to initialize external display + //--------------------------------------------------------------------- + // + char + *plasma_string = getenv("L4PLASMA"); + + if (plasma_string != NULL) + { + if (strnicmp(plasma_string, "COM2", 4) == 0) + { + Tell("Plasma display created on COM2\n"); + externalDisplay = new PlasmaDisplay(PCS_COM2); + } + else + { + Tell("Plasma display created on COM1\n"); + externalDisplay = new PlasmaDisplay(PCS_COM1); + } + + if (externalDisplay != NULL) + { + Register_Object(externalDisplay); + } + } + // + //--------------------------------------------------------------------- + // Attempt to initialize main display + //--------------------------------------------------------------------- + //------------------------------------------------- + // Search notation file for specified resolution + //------------------------------------------------- + // + NotationFile + notation_file("GAUGE\\L4GAUGE.INI"); + + if (!notation_file.PageExists(mode_string)) + { + Tell("L4GaugeRenderer::L4GaugeRenderer - '" << + mode_string << + "' not found in L4GAUGE.INI!\n" + ); + } + else + { + // + //------------------------------------------------- + // Requested resolution exists, read parameters + //------------------------------------------------- + // + int + mode(0), + width(640), + height(480), + page_size(64), + gran(64), + bpl(640*2), + pfp(0), + special(0), + q(0); + + q += notation_file.GetEntry(mode_string, "mode", &mode); + q += notation_file.GetEntry(mode_string, "width", &width); + q += notation_file.GetEntry(mode_string, "height", &height); + q += notation_file.GetEntry(mode_string, "sizeInKB", &page_size); + q += notation_file.GetEntry(mode_string, "granularityInKB", &gran); + q += notation_file.GetEntry(mode_string, "bytesPerLine", &bpl); + q += notation_file.GetEntry(mode_string, "pageFcnPtr", &pfp); + q += notation_file.GetEntry(mode_string, "special", &special); + + if (q == 8) + { + graphicsDisplay = new + SVGA16( + mode, + width, + height, + page_size, + gran, + bpl, + pfp, + special + ); + if (graphicsDisplay != NULL) + { + Register_Object(graphicsDisplay); + } + } + } + } + Check_Fpu(); +} + +// +//############################################################################# +// ~L4GaugeRenderer +//############################################################################# +// +L4GaugeRenderer::~L4GaugeRenderer() +{ +# if defined (LOCAL_TEST) + Tell("L4GaugeRenderer::~L4GaugeRenderer()\n"); +# endif + Check(this); + + int i; + + //---------------------------------------------------- + // Make sure all gauges removed first + //---------------------------------------------------- + Remove(0); + //---------------------------------------------------- + // Delete the graphics ports + //---------------------------------------------------- + for(i=0; iUpdatePalette(); + } + + Check_Fpu(); +} + +// +//############################################################################# +// ExecuteImplementation +//############################################################################# +// +Logical + L4GaugeRenderer::ExecuteBackgroundDisplayUpdate() +{ + Check(this); + + Logical + result = False; // False == 'all done' + + //-------------------------------------------------------- + // Update external annunciator + // + // Allow the plasma display to continue if there's + // more background time available. + // + // This method is still called if taskmode is set to + // 'foreground'. If it's called in 'foreground' mode, + // it really means that we're still waiting for foreground + // to begin processing, so we might as well update the + // external display (if needed). + //-------------------------------------------------------- + if (externalDisplay != NULL) + { + Check(externalDisplay); + result = externalDisplay->Update(False); // returns 'False' if done + } + //------------------------------------------------------- + // Update display ONLY in 'copy' mode + //-------------------------------------------------------- + if (taskMode == copy) + { + if (graphicsDisplay != NULL) + { + Check(graphicsDisplay); + + if (graphicsDisplay->Update(False) == False) + { + //-------------------------------------------------------- + // Tell executionImplementation that we're basically done. + //-------------------------------------------------------- + taskMode = foreground; + } + else + { + result = True; // We're not done yet! + } + } + } + return result; +} + +// +//############################################################################# +// NotifyOfNewInterestingEntity +//############################################################################# +// +void + L4GaugeRenderer::NotifyOfNewInterestingEntity( + Entity *interesting_entity + ) +{ + SET_GAUGE_RENDERER(); + Check(this); + Check(interesting_entity); + //---------------------------------------------- + // Make sure gaugeImage exists for entity + //---------------------------------------------- + Check(warehousePointer); + + ((L4Warehouse*)warehousePointer)->gaugeImageBin.Get( + interesting_entity->GetResourceID() + ); + //---------------------------------------------- + // Update gaugeRenderer + //---------------------------------------------- + GaugeRenderer::NotifyOfNewInterestingEntity(interesting_entity); + Check_Fpu(); + CLEAR_GAUGE_RENDERER(); +} + +// +//############################################################################# +// NotifyOfBecomingUninterestingEntity +//############################################################################# +// +void + L4GaugeRenderer::NotifyOfBecomingUninterestingEntity( + Entity *uninteresting_entity + ) +{ + SET_GAUGE_RENDERER(); + Check(this); + Check(uninteresting_entity); + //---------------------------------------------- + // Remove gaugeImage if no longer used + //---------------------------------------------- + Check(warehousePointer); + + ((L4Warehouse*)warehousePointer)->gaugeImageBin.Release( + uninteresting_entity->GetResourceID() + ); + //---------------------------------------------- + // Update gaugeRenderer + //---------------------------------------------- + GaugeRenderer::NotifyOfBecomingUninterestingEntity(uninteresting_entity); + Check_Fpu(); + CLEAR_GAUGE_RENDERER(); +} + +// +//############################################################################# +// BuildGraphicsPort +//############################################################################# + +//===========================================================================// +// RECONSTRUCTION SHADOW (source410 overrides CODE per build410.sh srcfor). +// +// Verbatim copy of CODE/RP/MUNGA_L4/L4GREND.CPP with ONE change: the port +// construction below builds a BTL4GraphicsPort instead of an L4GraphicsPort, +// to close the MFD-bleed artifact. Everything else is the archive's. +// +// THE ARTIFACT (operator report 2026-07-29: "artifacts bleeding over from the +// radar display into the MFDs ... I have noticed this in the BT411 builds as +// well, but does not happen in the original"): +// +// * The colour head is SIX BITS (L4GAUGE.CFG:4395, sec mask 0x003F) and the +// MFDs are bits 8-15 of the SAME 16-bit words -- one plane-packed +// framebuffer, so a colour-head defect can only surface as MFD garbage. +// * L4GraphicsPort::BuildSecondaryTranslation (L4VB16.CPP:5419) enumerates +// only the ACTIVE-bit combinations, filling 1<= 0); + Test_Tell("...port_number= " << port_number << "\n"); + // + //--------------------------------------------------------- + // If it already exists, delete it + //--------------------------------------------------------- + // + L4GraphicsPort + *graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + if (graphics_port != NULL) + { + Test_Tell("...deleting existing port\n"); + Check(graphics_port); + Unregister_Object(graphics_port); + delete graphics_port; + } + // + //--------------------------------------------------------- + // Attempt to create it + //--------------------------------------------------------- + // + graphicsPort[port_number] = new BTL4GraphicsPort( + (Video16BitBuffered *) graphicsDisplay, + name, + rotation, + bitAllocation, + palette_ID, + enable_ID + ); + + graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + Test_Tell("...new port at " << graphics_port << "\n"); + // + //--------------------------------------------------------- + // If created, register it and build the palette + //--------------------------------------------------------- + // + if (graphics_port != NULL) + { + Check(graphics_port); + Register_Object(graphics_port); + // + // Set the palette for the port + // (Note: secondary uses lowest 8 bits) + // + if ((bitAllocation > 0) && (bitAllocation < 0x0100)) + { + Test_Tell("...secondary\n"); + graphics_port->SetSecondaryPalette(palette); + } + else + { + Test_Tell("...auxiliary\n"); + graphics_port->SetAuxiliaryPalette(); + } + } + } + Check_Fpu(); +} + +// +//############################################################################# +// RemapGraphicsPort +//############################################################################# +// +void + L4GaugeRenderer::RemapGraphicsPort( + int port_number, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID enable_ID, + Palette8 *palette + ) +{ + Check(this); + Test_Tell("L4GaugeRenderer::RemapGraphicsPort\n"); + + if (graphicsDisplay != NULL) + { + Test_Tell("...non-NULL display\n"); + Verify(port_number < maximumGraphicsPorts); + Verify(port_number >= 0); + Test_Tell("...port_number= " << port_number << "\n"); + //--------------------------------------------------------- + // If it exists, change the palette ID and set the palette + //--------------------------------------------------------- + L4GraphicsPort + *graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + if (graphics_port != NULL) + { + Check(graphics_port); + // + // Set the palette ID + // + graphics_port->SetPaletteID(palette_ID); + graphics_port->SetEnableID(enable_ID); + + // + // Set the palette for the port + // (Note: secondary uses lowest 8 bits) + // + + int + bit_mask = graphics_port->GetBitMask(); + + if (bit_mask & 0x00FF) // must be secondary + { + Test_Tell("...secondary\n"); + Verify(palette != NULL); + graphics_port->SetSecondaryPalette(palette); + } + else + { + Test_Tell("...auxiliary\n"); + graphics_port->SetAuxiliaryPalette(); + } + } + } + Check_Fpu(); +} + +// +//############################################################################# +// BuildExternalGraphicsPort +//############################################################################# +// +void + L4GaugeRenderer::BuildExternalGraphicsPort( + int port_number, + const char *name, + int /*bitAllocation*/ + ) +{ + Check(this); + Test_Tell( + "L4GaugeRenderer::BuildExternalGraphicsPort(" << port_number << ")\n" + ); + + if (externalDisplay != NULL) + { + Test_Tell("...non-NULL display\n"); + Verify(port_number < maximumGraphicsPorts); + Verify(port_number >= 0); + Test_Tell("...port_number= " << port_number << "\n"); + // + //--------------------------------------------------------- + // If it already exists, delete it + //--------------------------------------------------------- + // + L4GraphicsPort + *graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + if (graphics_port != NULL) + { + Test_Tell("...deleting existing port\n"); + Check(graphics_port); + Unregister_Object(graphics_port); + delete graphics_port; + } + // + //--------------------------------------------------------- + // Attempt to create it + //--------------------------------------------------------- + // + graphicsPort[port_number] = new L4BytePort( + (Video8BitBuffered *) externalDisplay, + name, + 0 // rotation + ); + + graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + Test_Tell("...new port at " << graphics_port << "\n"); + // + //--------------------------------------------------------- + // If created, register it + //--------------------------------------------------------- + // + if (graphics_port != NULL) + { + Check(graphics_port); + Register_Object(graphics_port); + } + } + Check_Fpu(); +} + +// +//############################################################################# +// FadeToWhite, FadeToGame +//############################################################################# +// +void + L4GaugeRenderer::FadeToWhite(Scalar number_of_seconds) +{ + Check(this); + Verify(number_of_seconds >= 0.0); // zero is allowed (instant change) + +// cout << "L4GaugeRenderer::FadeToWhite(" << number_of_seconds << ")\n"; + + if (graphicsDisplay != NULL) + { + Check(graphicsDisplay); + ((SVGA16 *)graphicsDisplay)->FadeToWhite(number_of_seconds); + } + Check_Fpu(); +} + +void + L4GaugeRenderer::FadeToNormal(Scalar number_of_seconds) +{ + Check(this); + Verify(number_of_seconds >= 0.0); // zero is allowed (instant change) + +// cout << "L4GaugeRenderer::FadeToNormal(" << number_of_seconds << ")\n"; + + if (graphicsDisplay != NULL) + { + Check(graphicsDisplay); + ((SVGA16 *)graphicsDisplay)->FadeToPalettes(number_of_seconds); + } + Check_Fpu(); +} + +// +//############################################################################# +// Configure +//############################################################################# +// +void + L4GaugeRenderer::ConfigureForModel( + const char *configuration_name, + Entity *entity + ) +{ + Check(this); + Check_Pointer(configuration_name); + + Test_Tell( + "L4GaugeRenderer::ConfigureForModel(" << + configuration_name << ", " << + entity << ")\n" + ); + + Check(application); + Check(entity); + + Mission + *mission = application->GetCurrentMission(); + Check(mission); + + const char + *model_name = mission->GetGameModel(); + Check_Pointer(model_name); + + char + full_name[64]; + + Str_Copy(full_name, model_name, sizeof(full_name)); + Str_Cat(full_name, configuration_name, sizeof(full_name)); + + Test_Tell( + "L4GaugeRenderer::ConfigureForModel, full_name=" << full_name << + ")\n" + ); + + Configure(full_name, entity); + Check_Fpu(); +} + +// +//############################################################################# +// SpecialEffect +//############################################################################# +// +void + L4GaugeRenderer::SpecialEffect( + VideoEffectType type, + Scalar duration + ) +{ + Check(this); + + switch (type) + { + case scrambleVideo: + if (graphicsDisplay != NULL) + { + scrambleVideoFlag = True; + scrambleVideoTimeout = ((Scalar)Now()) + duration; + + Check(graphicsDisplay); + ((SVGA16*) graphicsDisplay)->FunkyVideo(True); + } + break; + + // other modes go here + + } + Check_Fpu(); +} + +void + L4GaugeRenderer::ProcessVideoEffects() +{ + Check(this); + Check(graphicsDisplay); + + Time + now = Now(); + + if (scrambleVideoFlag) + { + if (now >= scrambleVideoTimeout) + { + scrambleVideoFlag = False; + ((SVGA16*) graphicsDisplay)->FunkyVideo(False); + } + } + + Check_Fpu(); +} + +//-------------------------------------------------------------------- +// Profiling support +//-------------------------------------------------------------------- +Scalar + L4GaugeRenderer::GetCurrentFramePercentage() +{ + Check(this); + return Get_Frame_Percent_Used(); +} + + + +