Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
364 lines
8.3 KiB
C++
364 lines
8.3 KiB
C++
#include "mungal4.h"
|
|
#pragma hdrstop
|
|
|
|
#include "l4plasma.h"
|
|
#include "..\munga\time.h"
|
|
|
|
//########################################################################
|
|
//############################# PlasmaDisplay ############################
|
|
//########################################################################
|
|
PlasmaDisplay::PlasmaDisplay(
|
|
//Win32 Serial Support: ADB 02/24/2007
|
|
//Word port,
|
|
const char* port
|
|
//Word int_num
|
|
):
|
|
Video8BitBuffered(plasmaWidth, plasmaHeight),
|
|
forceAll(False)
|
|
{
|
|
//------------------------------------
|
|
// Create serial interface
|
|
//------------------------------------
|
|
//Win32 Serial Support: ADB 02/24/2007
|
|
//pc_serial = new PCSerial(PCS_9600, PCS_N81, port, int_num);
|
|
pc_serial = new PCSerial(PCS_9600, PCS_N81, port);
|
|
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;
|
|
}
|
|
|
|
this->DrawFilledRectangle(0, 0xFF, GraphicsDisplay::Replace, 0, 0, this->width - 1, this->height - 1);
|
|
this->Update(True);
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
PlasmaDisplay::~PlasmaDisplay()
|
|
{
|
|
if (pc_serial != NULL)
|
|
{
|
|
//---------------------------------------------------------------------
|
|
// Flush data to plasma display
|
|
//---------------------------------------------------------------------
|
|
this->DrawFilledRectangle(0, 0xFF, GraphicsDisplay::Replace, 0, 0, this->width - 1, this->height - 1);
|
|
this->Update(True);
|
|
|
|
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.0f;
|
|
while (Now() < then)
|
|
{
|
|
//---------------------------------------------------
|
|
// Drop out of loop when ALL data has been sent
|
|
//---------------------------------------------------
|
|
if (pc_serial->CanDraw() <= 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)
|
|
{
|
|
std::cout << indent << "Plasma:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
Video8BitBuffered::ShowInstance(temp);
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
int
|
|
sendLine(
|
|
char *transfer_pointer,
|
|
int line_number,
|
|
Byte *source_pointer,
|
|
int source_width
|
|
)
|
|
{
|
|
int
|
|
x,
|
|
index;
|
|
Byte
|
|
byte,
|
|
byte_bit;
|
|
//--------------------------------------------
|
|
// Send header
|
|
//--------------------------------------------
|
|
transfer_pointer[0] = (char) 27; // ascii ESC
|
|
transfer_pointer[1] = 'P'; // graphics command
|
|
transfer_pointer[2] = (char) 0; // screen number
|
|
transfer_pointer[3] = (char) line_number; // Y position
|
|
transfer_pointer[4] = (char) 0; // X BYTE position
|
|
transfer_pointer[5] = (char) ((source_width+7)>>3); // width in bytes
|
|
transfer_pointer[6] = (char) 1;
|
|
|
|
transfer_pointer += 7;
|
|
|
|
//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));
|
|
*transfer_pointer = byte;
|
|
transfer_pointer++;
|
|
index++;
|
|
byte = 0;
|
|
byte_bit = 0x80;
|
|
}
|
|
}
|
|
//
|
|
// End of source line: send remaining bits
|
|
//
|
|
if (byte_bit != 0x80)
|
|
{
|
|
transfer_pointer[index++] = byte;
|
|
}
|
|
//
|
|
// Send graphics data
|
|
//
|
|
//pc_serial->SendString(graphics, index);
|
|
Check_Fpu();
|
|
|
|
return index + 7;
|
|
}
|
|
|
|
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)
|
|
{
|
|
Time startSendLine,endSendLine,startWhile,endWhile,dataSendStart,dataSendEnd;
|
|
Time start = Now();
|
|
int __totalTransferLength;
|
|
|
|
Time allStarts[100], allEnds[100];
|
|
|
|
int
|
|
transfer_count,
|
|
total_count;
|
|
Logical
|
|
result = True; // True == 'more to send, not done'
|
|
|
|
if (pc_serial != NULL && pc_serial->CanDraw())
|
|
{
|
|
//-----------------------------------------
|
|
// Accumulate changed lines
|
|
//-----------------------------------------
|
|
forceAll |= force_all;
|
|
|
|
if (currentTransferLine == 0)
|
|
{
|
|
Scan(forceAll);
|
|
forceAll = False;
|
|
}
|
|
//-----------------------------------------
|
|
// Send only if the buffer is empty
|
|
//-----------------------------------------
|
|
total_count = plasmaHeight;
|
|
transfer_count = 7;
|
|
int transfer_length = 32 * transfer_count;
|
|
char *transfer_data = new char[transfer_length];
|
|
char *transfer_pointer = transfer_data;
|
|
int total_transfer_count = transfer_count;
|
|
int total_transfer_length = 0;
|
|
|
|
startWhile = Now();
|
|
|
|
int i = 0;
|
|
|
|
while(transfer_count>0)
|
|
{
|
|
//-----------------------------------------
|
|
// Transfer a line if it's ready
|
|
//-----------------------------------------
|
|
allStarts[i] = Now();
|
|
if (updateFlag[currentTransferLine])
|
|
{
|
|
//-----------------------------------------
|
|
// Decrement the 'transfer count'
|
|
//-----------------------------------------
|
|
--transfer_count;
|
|
//-----------------------------------------
|
|
// Clear the 'update' flag
|
|
//-----------------------------------------
|
|
updateFlag[currentTransferLine] = 0;
|
|
//-----------------------------------------
|
|
// Send the line data to the display
|
|
//-----------------------------------------
|
|
startSendLine = Now();
|
|
int length = sendLine(transfer_pointer, currentTransferLine,
|
|
pixelBuffer->Data.MapPointer +
|
|
(pixelBuffer->Data.Size.x * currentTransferLine),
|
|
pixelBuffer->Data.Size.x
|
|
);
|
|
endSendLine = Now();
|
|
|
|
transfer_pointer += length;
|
|
total_transfer_length += length;
|
|
}
|
|
|
|
|
|
allEnds[i] = Now();
|
|
//-----------------------------------------
|
|
// 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;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
endWhile = Now();
|
|
|
|
dataSendStart = Now();
|
|
if (total_transfer_length > 0)
|
|
{
|
|
this->pc_serial->SendString(transfer_data, total_transfer_length);
|
|
}
|
|
dataSendEnd = Now();
|
|
|
|
__totalTransferLength = total_transfer_length;
|
|
|
|
delete [] transfer_data;
|
|
}
|
|
Check_Fpu();
|
|
|
|
Time end = Now();
|
|
|
|
if (end.ticks - start.ticks > 100)
|
|
{
|
|
start = end;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
PlasmaDisplay::WaitForUpdate()
|
|
{
|
|
Time
|
|
end_time;
|
|
|
|
end_time = Now();
|
|
end_time += 5.0f; // We'll wait this many seconds to update the display-
|
|
|
|
while (updateInProgress)
|
|
{
|
|
Update(False);
|
|
|
|
if (Now() >= end_time)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|