Archival snapshot of the Virtual World Entertainment Tesla cockpit software, 1994-1996: MUNGA engine and L4 pod layer source (Borland C++ 5.0), BT/RP game code, and game content (models, audio, maps, gauges, Division renderer data). Includes third-party libraries: Division dVS/DPL graphics, HMI SOS audio, WATTCP networking. Files are preserved byte-for-byte (.gitattributes disables all line-ending conversion). README.md documents the layout, target hardware, and toolchain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
334 lines
8.1 KiB
C++
334 lines
8.1 KiB
C++
//===========================================================================//
|
|
// File: L4plasma.cpp //
|
|
// Project: MUNGA Brick: Applications-specific controls module //
|
|
// Contents: Interface specification for plasma display //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- -----------------------------------------------------------//
|
|
// 02/08/95 CPB Initial coding. //
|
|
// 06/15/95 CPB Changed to Video8BitBuffered, added transmission. //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved //
|
|
// PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include <mungal4.hpp>
|
|
#pragma hdrstop
|
|
|
|
#if !defined(L4PLASMA_HPP)
|
|
# include <l4plasma.hpp>
|
|
#endif
|
|
|
|
#if !defined(TIME_HPP)
|
|
# include <time.hpp>
|
|
#endif
|
|
|
|
//########################################################################
|
|
//############################# PlasmaDisplay ############################
|
|
//########################################################################
|
|
PlasmaDisplay::PlasmaDisplay(
|
|
Word port,
|
|
Word int_num
|
|
):
|
|
Video8BitBuffered(plasmaWidth, plasmaHeight)
|
|
{
|
|
//------------------------------------
|
|
// Create serial interface
|
|
//------------------------------------
|
|
pc_serial = new PCSerial(PCS_9600, PCS_N81, port, int_num);
|
|
if (pc_serial != NULL)
|
|
{
|
|
Register_Object(pc_serial);
|
|
pc_serial->FlowControlEnable(False);
|
|
//------------------------------------
|
|
// Turn off the cursor
|
|
//------------------------------------
|
|
static char
|
|
cursorOffString[] = { 27 /*ESC*/, 'G', (char) 0x00 };
|
|
|
|
pc_serial->SendString(cursorOffString, 3);
|
|
}
|
|
//------------------------------------
|
|
// Clear update flag array
|
|
//------------------------------------
|
|
currentTransferLine = 0;
|
|
updateInProgress = False;
|
|
|
|
for(int i=0; i<plasmaHeight; ++i)
|
|
{
|
|
updateFlag[i] = 0;
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
PlasmaDisplay::~PlasmaDisplay()
|
|
{
|
|
if (pc_serial != NULL)
|
|
{
|
|
//---------------------------------------------------------------------
|
|
// Flush data to plasma display
|
|
//---------------------------------------------------------------------
|
|
WaitForUpdate();
|
|
|
|
// This odd sequence of allocation, setting, and adding is necessary:
|
|
// if you try to combine them, the compiler gets confused as to which
|
|
// method to invoke for 'Now()'.
|
|
Time
|
|
then;
|
|
then = Now();
|
|
then += 5.0;
|
|
while (Now() < then)
|
|
{
|
|
//---------------------------------------------------
|
|
// Drop out of loop when ALL data has been sent
|
|
//---------------------------------------------------
|
|
if (pc_serial->TransmitCharCount() <= 0)
|
|
{
|
|
if (!pc_serial->IsActive())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------
|
|
// Delete the serial interface
|
|
//---------------------------------------------------------------------
|
|
Unregister_Object(pc_serial);
|
|
delete pc_serial;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
PlasmaDisplay::TestInstance() const
|
|
{
|
|
return Video8BitBuffered::TestInstance();
|
|
}
|
|
|
|
void
|
|
PlasmaDisplay::ShowInstance(char *indent)
|
|
{
|
|
cout << indent << "Plasma:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
Video8BitBuffered::ShowInstance(temp);
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
void
|
|
sendLine(
|
|
PCSerial *pc_serial,
|
|
int line_number,
|
|
Byte *source_pointer,
|
|
int source_width
|
|
)
|
|
{
|
|
char
|
|
graphics[32]; // We only need 16...the extra is just in case.
|
|
int
|
|
x,
|
|
index;
|
|
Byte
|
|
byte,
|
|
byte_bit;
|
|
//--------------------------------------------
|
|
// Send header
|
|
//--------------------------------------------
|
|
graphics[0] = (char) 27; // ascii ESC
|
|
graphics[1] = 'P'; // graphics command
|
|
graphics[2] = (char) 0; // screen number
|
|
graphics[3] = (char) line_number; // Y position
|
|
graphics[4] = (char) 0; // X BYTE position
|
|
graphics[5] = (char) ((source_width+7)>>3); // width in bytes
|
|
graphics[6] = (char) 1;
|
|
|
|
pc_serial->SendString(graphics, 7);
|
|
//--------------------------------------------
|
|
// Send data
|
|
//--------------------------------------------
|
|
byte = 0;
|
|
byte_bit = 0x80;
|
|
index = 0;
|
|
for(x=0; x<source_width; ++x)
|
|
{
|
|
//
|
|
// Add bit to byte
|
|
//
|
|
if (*source_pointer++)
|
|
{
|
|
byte |= byte_bit;
|
|
}
|
|
//
|
|
// Update bit position
|
|
//
|
|
byte_bit >>= 1;
|
|
//
|
|
// If entire byte collected, send it
|
|
//
|
|
if (byte_bit == 0)
|
|
{
|
|
Verify(index < sizeof(graphics));
|
|
graphics[index++] = byte;
|
|
byte = 0;
|
|
byte_bit = 0x80;
|
|
}
|
|
}
|
|
//
|
|
// End of source line: send remaining bits
|
|
//
|
|
if (byte_bit != 0x80)
|
|
{
|
|
graphics[index++] = byte;
|
|
}
|
|
//
|
|
// Send graphics data
|
|
//
|
|
pc_serial->SendString(graphics, index);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
PlasmaDisplay::Scan(Logical forceAll)
|
|
{
|
|
Word
|
|
changed_line = (Word) forceAll,
|
|
*changed_line_pointer = changedLine;
|
|
char
|
|
*update_pointer=updateFlag;
|
|
int
|
|
y;
|
|
|
|
for(y=0; y<plasmaHeight; ++y,++update_pointer)
|
|
{
|
|
//---------------------------------------------------------
|
|
// Scan for changed lines
|
|
//---------------------------------------------------------
|
|
changed_line += *changed_line_pointer;
|
|
*changed_line_pointer++ = 0;
|
|
|
|
if (changed_line)
|
|
{
|
|
*update_pointer = 1;
|
|
|
|
updateInProgress = True;
|
|
}
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
PlasmaDisplay::Update(Logical force_all)
|
|
{
|
|
int
|
|
transfer_count,
|
|
total_count;
|
|
Logical
|
|
result = True; // True == 'more to send, not done'
|
|
|
|
if (pc_serial != NULL)
|
|
{
|
|
//-----------------------------------------
|
|
// Accumulate changed lines
|
|
//-----------------------------------------
|
|
forceAll |= force_all;
|
|
|
|
if (currentTransferLine == 0)
|
|
{
|
|
Scan(forceAll);
|
|
forceAll = False;
|
|
}
|
|
//-----------------------------------------
|
|
// Send only if the buffer is empty
|
|
//-----------------------------------------
|
|
if (pc_serial->TransmitCharCount() == 0)
|
|
{
|
|
total_count = plasmaHeight;
|
|
transfer_count = 4;
|
|
while(transfer_count>0)
|
|
{
|
|
//-----------------------------------------
|
|
// Transfer a line if it's ready
|
|
//-----------------------------------------
|
|
if (updateFlag[currentTransferLine])
|
|
{
|
|
//-----------------------------------------
|
|
// Decrement the 'transfer count'
|
|
//-----------------------------------------
|
|
--transfer_count;
|
|
//-----------------------------------------
|
|
// Clear the 'update' flag
|
|
//-----------------------------------------
|
|
updateFlag[currentTransferLine] = 0;
|
|
//-----------------------------------------
|
|
// Send the line data to the display
|
|
//-----------------------------------------
|
|
sendLine(
|
|
pc_serial,
|
|
currentTransferLine,
|
|
pixelBuffer->Data.MapPointer +
|
|
(pixelBuffer->Data.Size.x * currentTransferLine),
|
|
pixelBuffer->Data.Size.x
|
|
);
|
|
}
|
|
//-----------------------------------------
|
|
// Increment currentTransferLine
|
|
//-----------------------------------------
|
|
if (++currentTransferLine >= plasmaHeight)
|
|
{
|
|
currentTransferLine = 0;
|
|
}
|
|
//-----------------------------------------
|
|
// Reset to top if all lines scanned
|
|
//-----------------------------------------
|
|
if (--total_count < 0)
|
|
{
|
|
currentTransferLine = 0; // reset to top line
|
|
updateInProgress = False;
|
|
result = False; // False == 'all data sent'
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
return result;
|
|
}
|
|
|
|
void
|
|
PlasmaDisplay::WaitForUpdate()
|
|
{
|
|
Time
|
|
end_time;
|
|
|
|
end_time = Now();
|
|
end_time += 5.0; // We'll wait this many seconds to update the display-
|
|
|
|
while (updateInProgress)
|
|
{
|
|
Update(False);
|
|
|
|
if (Now() >= end_time)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|