Files
TeslaRel410/restoration/source410/MUNGA/APPTASK.CPP
T
CydandClaude Fable 5 0e763fda1f BT410 5.3.113: the displays lag because the loop is slow, and the loop was slow because the flags were wrong -- authentic OPT.MAK optimizer set adopted
The operator's 'many seconds between display updates', run to ground:

MECHANISM (verified in source AND the shipped exe bytes): main passes
GetTicksPerSecond() as ApplicationManager's frame RATE, so frameDuration
is microscopic and RunMissions runs flat-out -- exactly ONE background
slot per loop frame, shipped and ours alike (ctor constant @0044f2d8 ==
1.0f, read straight out of BTL4OPT.EXE). That slot feeds a 7-task ring;
the gauge renderer gets 1/7th of slots, one ACTIVE gauge per slot, and
the screen blits once per completed wheel pass. The wheel is 136 gauges
-- and the BT_GAUGE_LOG roster dump shows all 136 are real cockpit
instruments (26 armor colormappers, leak gauges, cooling loops, weapon
clusters...): a Tesla pod shows everything at once, so the roster is
AUTHENTIC and must not be trimmed. Per-instrument latency is therefore
7 x 146 / loop_fps -- the loop rate is the only lever.

THE DEFECT: build410.sh compiled -O2 alone. The authentic release tier
(CODE/BT/OPT.MAK) is -O2 -Ot -Oc -Og -O -Ol -Z -Ob -Oe -Oi -Om -Op -Ov.
Adopting it (all 234 TUs clean, no BC4.52 optimizer ICEs) doubled the
loop: 16.7 -> ~30 fps wall on the rig. Shipped fifo throughput is still
~2x ours (11.8KB/s vs 6.4KB/s, governor-conflated) -- residual gap is an
open question pinned in GAUGE-CADENCE-NOTES.md with the operator A/B ask.

Instrumentation kept, cheap and gated: slot/wheel counters on the
[stack] line (BT_STACK_LOG), one-shot roster dump (BT_GAUGE_LOG),
tick-delta timers compile-gated BT_TICK_PROBES (OFF -- guest tick sums
proved to be trap-burst artifacts in the emulator, not costs; wall rates
are the only trustworthy measure). New: MUNGA/APPTASK.CPP shadow,
fifofps.py (true board fps from a fifodump), pod_render_bgprobe.conf.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 01:42:08 -05:00

276 lines
6.7 KiB
C++

//===========================================================================//
// File: apptask.cpp //
// Project: MUNGA Brick: Application //
// Contents: Interface specification for Application //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/24/94 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(APPTASK_HPP)
# include <apptask.hpp>
#endif
#if !defined(RENDERER_HPP)
# include <renderer.hpp>
#endif
#if !defined(AUDREND_HPP)
# include <audrend.hpp>
#endif
#if !defined(APP_HPP)
# include <app.hpp>
#endif
#if !defined(NTTMGR_HPP)
# include <nttmgr.hpp>
#endif
#if !defined(GAUGEREND_HPP)
# include <gaugrend.hpp>
#endif
#if defined(TRACE_COMPLETE_CYCLES)
BitTrace Complete_Cycles("Complete Cycles");
#endif
#if defined(TRACE_DEATH_ROW)
BitTrace Death_Row("Death Row");
#endif
//#############################################################################
//########################### ApplicationTask ###########################
//#############################################################################
ApplicationTask::ApplicationTask(ClassID class_ID):
Component(class_ID)
{
}
ApplicationTask::~ApplicationTask()
{
}
//#############################################################################
//########################### BackgroundTasks ###########################
//#############################################################################
BackgroundTasks::BackgroundTasks():
taskSocket(NULL)
{
taskIterator = new SChainIteratorOf<ApplicationTask*>(&taskSocket);
Register_Object(taskIterator);
}
BackgroundTasks::~BackgroundTasks()
{
Check(taskIterator);
taskIterator->DeletePlugs();
Unregister_Object(taskIterator);
delete taskIterator;
}
Logical
BackgroundTasks::TestInstance() const
{
Component::TestInstance();
Check(&taskSocket);
Check(taskIterator);
return True;
}
void
BackgroundTasks::AddTask(ApplicationTask *task)
{
Check(this);
Check(task);
taskSocket.Add(task);
}
void
BackgroundTasks::Execute()
{
Check(this);
Check(taskIterator);
if (taskIterator->GetCurrent() == NULL)
{
taskIterator->First();
}
ApplicationTask *task = taskIterator->GetCurrent();
Check(task);
task->Execute();
taskIterator->Next();
}
//
// RING-TASK TICK SUMS (gauge-starvation probe; counters defined in app.cpp,
// printed on the [stack] line). The single background slot per frame eats
// ~8 unaccounted ticks -- these say which task's Execute holds the clock.
//
extern long taskRouteTicks;
extern long taskEventTicks;
extern long taskAudioTicks;
extern long taskGaugeTicks;
extern long taskNetTicks;
extern long taskCyclesTicks;
extern long taskFryTicks;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkManagerTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
NetworkManagerTask::Execute()
{
Check(this);
Check(application);
Check(application->GetNetworkManager());
{
#if defined(BT_TICK_PROBES)
Time probe_t0 = Now();
application->GetNetworkManager()->ExecuteBackground();
taskNetTicks += (long)(Now().ticks - probe_t0.ticks);
#else
application->GetNetworkManager()->ExecuteBackground();
#endif
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RoutePacketTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
RoutePacketTask::Execute()
{
Check(this);
Check(application);
Check(application->GetNetworkManager());
{
#if defined(BT_TICK_PROBES)
Time probe_t0 = Now();
application->GetNetworkManager()->RoutePacket();
taskRouteTicks += (long)(Now().ticks - probe_t0.ticks);
#else
application->GetNetworkManager()->RoutePacket();
#endif
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ProcessEventTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
ProcessEventTask::Execute()
{
Check(this);
Check(application);
{
#if defined(BT_TICK_PROBES)
Time probe_t0 = Now();
application->ProcessOneEvent();
taskEventTicks += (long)(Now().ticks - probe_t0.ticks);
#else
application->ProcessOneEvent();
#endif
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
AudioRendererTask::Execute()
{
Check(this);
Check(application);
if (application->GetAudioRenderer() != NULL)
{
Check(application->GetAudioRenderer());
{
#if defined(BT_TICK_PROBES)
Time probe_t0 = Now();
application->GetAudioRenderer()->ExecuteBackground();
taskAudioTicks += (long)(Now().ticks - probe_t0.ticks);
#else
application->GetAudioRenderer()->ExecuteBackground();
#endif
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GaugeRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
GaugeRendererTask::Execute()
{
Check(this);
Check(application);
if (application->GetGaugeRenderer() != NULL)
{
Check(application->GetGaugeRenderer());
{
#if defined(BT_TICK_PROBES)
Time probe_t0 = Now();
application->GetGaugeRenderer()->ExecuteBackground();
taskGaugeTicks += (long)(Now().ticks - probe_t0.ticks);
#else
application->GetGaugeRenderer()->ExecuteBackground();
#endif
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompleteCyclesTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
CompleteCyclesTask::Execute()
{
SET_COMPLETE_CYCLES();
Check(this);
Check(application);
Check(application->GetRendererManager());
{
#if defined(BT_TICK_PROBES)
Time probe_t0 = Now();
application->GetRendererManager()->CompleteCycles();
taskCyclesTicks += (long)(Now().ticks - probe_t0.ticks);
#else
application->GetRendererManager()->CompleteCycles();
#endif
}
CLEAR_COMPLETE_CYCLES();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FryDeathRowTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
FryDeathRowTask::Execute()
{
SET_DEATH_ROW();
Check(this);
Check(application);
Check(application->GetEntityManager());
{
#if defined(BT_TICK_PROBES)
Time probe_t0 = Now();
application->GetEntityManager()->FryDeathRow();
taskFryTicks += (long)(Now().ticks - probe_t0.ticks);
#else
application->GetEntityManager()->FryDeathRow();
#endif
}
CLEAR_DEATH_ROW();
}