Files
arcattackandClaude Opus 4.8 7b7d465e5e Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.

Layout:
  engine/   MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
            work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
            models) + image codec; the minimal rp/ headers the audio HAL needs
  game/     reconstructed BT logic + surviving-original BT source + fwd shims
            + WinMain launcher
  content/  full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
  docs/     format specs + reconstruction ledgers
  reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
  tools/    MP console emulator + map/resource scanners

One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 21:03:40 -05:00

293 lines
8.9 KiB
C++

//===========================================================================//
// File: PCSPAK.hh //
// Project: MUNGA Brick: Platform-specific IO //
// Contents: PC serial packet interface class //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 01/16/95 CPB Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved //
// PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#pragma once
//Win32 Serial support: ADB 01/15/07
#include <windows.h>
#include <assert.h>
#include "..\munga\style.h"
#include "L4SERIAL.H"
class PCSerialPacket;
class PCSerialPacketScanner;
//Win32 Serial support: ADB 02/13/07
#define DIE_ON_ERROR 1
#define DIE_ON_OVERFLOW 1
#define WATCH_IRQ 1
#define THE_WAY_IT_WAS 0
//===========================================================================
// Equates
//===========================================================================
#ifdef DIE_ON_ERROR
#define DISABLE_AND_DIE(errorString) throw errorString
#else
#define DISABLE_AND_DIE
#endif
//Win32 Serial support: ADB 02/10/07
//TX
#define TX_IDLE_STATE 0
#define TX_RESTART_STATE 1
#define TX_BODY_STATE 2
#define TX_WAIT_STATE 3
//RX
#define RX_IDLE_STATE 0
#define RX_ACTIVE_STATE 1
//
// Lower eight bits reserved for UART status
//
#define ERR_INIT 0x0100
#define TX_EARLY_ERR 0x0200
#define TX_ABANDON 0x0400
#define TX_RESTART 0x0800
#define TX_NAK 0x1000
#define RX_SEQ_ERR 0x2000
#define RX_BAD_CHECKSUM 0x4000
#define RX_COM_ERR 0x8000
#define TXMAXRESET 3
#define TXMAXERROR 3
#define TXMAXIDLE 4
#define MAX_COMMAND_CHAR 0xFB //largest command code allowed
#define ACK_CHAR 0xFC
#define NAK_CHAR 0xFD
#define RESTART_CHAR 0xFE
#define IDLE_CHAR 0xFF
#define RX_ACK_BIT 0x0001
#define RX_NAK_BIT 0x0002
enum
{
//Win32 Serial support: ADB 02/10/07
//PCSPAKInitErrDPMI = -2,
//PCSPAKInitErrAlloc = -1,
PCSPAKWin32Err = -1,
PCSPAKInitOk = 0
};
//Win32 Serial support: ADB 01/15/07
DWORD WINAPI RxThreadProc(LPVOID lpParameter);
//Win32 Serial support: ADB 02/13/07
#define COMBUFSIZE 2048
// This is for INTERNAL USE only (reflects structure in .ASM file)
struct PCSerPackBuf
{
Word head, tail, tempHead, tempTail, count, tempIn, tempOut;
//Win32 Serial support: ADB 02/13/07
BYTE data[COMBUFSIZE]; // was 256 before 7-13-95 cpb
// WARNING: make ABSOLUTELY SURE this matches pcspak.asm
};
class PCSerialPacket
{
friend class PCSerialPacketScanner;
friend DWORD WINAPI RxThreadProc(LPVOID lpParameter);
private:
//Win32 Serial support: ADB 02/10/07
//------------------------------------------------
// COM_INIT macro
// Initializes COMBUF structure
//------------------------------------------------
void COM_INIT(PCSerPackBuf* buffer);
//Win32 Serial support: ADB 02/13/07
//------------------------------------------------
// COM_PUT_AL macro
// 'Temporarily' puts character in AL into COMBUF
//------------------------------------------------
void COM_PUT_AL(PCSerPackBuf* buffer, BYTE al);
//Win32 Serial support: ADB 02/13/07
//------------------------------------------------
// COM_RESTORE_IN macro
// Discards characters 'temporarily' placed in COMBUF
//------------------------------------------------
void COM_RESTORE_IN(PCSerPackBuf* buffer);
//Win32 Serial support: ADB 02/13/07
//------------------------------------------------
// COM_ACCEPT_IN macro
// Accepts characters 'temporarily' placed in COMBUF
//------------------------------------------------
void COM_ACCEPT_IN(PCSerPackBuf* buffer);
//Win32 Serial support: ADB 02/13/07
//------------------------------------------------
// COM_GET_AL macro
// 'Temporarily' gets character into AL from COMBUF
//------------------------------------------------
int COM_GET_AL(PCSerPackBuf* buffer);
//Win32 Serial support: ADB 02/13/07
//------------------------------------------------
// COM_RESTORE_OUT macro
// Restores characters 'temporarily' removed from COMBUF
//------------------------------------------------
void COM_RESTORE_OUT(PCSerPackBuf* buffer);
//Win32 Serial support: ADB 02/13/07
//------------------------------------------------
// COM_ACCEPT_OUT macro
// Discards characters 'temporarily' removed from COMBUF
//------------------------------------------------
void COM_ACCEPT_OUT(PCSerPackBuf* buffer);
//Win32 Serial support: ADB 02/13/07
//------------------------------------------------
// COM_EAT_PACKET macro
// Discards entire buffer item from COMBUF
//------------------------------------------------
void COM_EAT_PACKET(PCSerPackBuf* buffer);
//Win32 Serial support: ADB 02/13/07
//------------------------------------------------
// COM_SPACE_IN macro
// Returns input bytes available in COMBUF
//------------------------------------------------
int COM_SPACE_IN(PCSerPackBuf* buffer);
//Win32 Serial support: ADB 02/13/07
//------------------------------------------------
// COM_SPACE_OUT macro
// Returns output bytes available in COMBUF
//------------------------------------------------
int COM_SPACE_OUT(PCSerPackBuf* buffer);
public:
//Win32 Serial support: ADB 06/23/07
PCSerialPacket();
void ShutdownRxThread();
~PCSerialPacket();
//Win32 Serial support: ADB 01/15/07
// Only call Initialize(...) ONCE during the lifetime of the object!
int Initialize(WORD rate, WORD format, const char* port, BYTE* rxLengths, BYTE rxCount, BYTE* txLengths, BYTE txCount);
//Win32 Serial support: ADB 01/15/07
Logical TestInstance();
//Win32 Serial support: ADB 02/10/07
//-------------------------------------------------------------------------
// PCSPAKReceive()
// Returns packet if available
//-------------------------------------------------------------------------
// Enter:
// BYTE *destPtr = pointer to 128-byte destination buffer
//-------------------------------------------------------------------------
// Returns:
// int packetSize (or zero if no packet available)
//-------------------------------------------------------------------------
int ReceivePacket(BYTE *destPtr);
//Win32 Serial Support
//-------------------------------------------------------------------------
// PCSPAKSend()
// Transmits packet
//-------------------------------------------------------------------------
// Enter:
// BYTE *sp_src = pointer to (up to) 128-byte source buffer
//-------------------------------------------------------------------------
// Returns:
// void
//-------------------------------------------------------------------------
void SendPacket(BYTE *srcPtr);
// error bits returned by PCSerialPacket::Errors()
enum ErrorBits {
overrunError=0x0002,
parityError=0x0004,
framingError=0x0008,
breakDetect=0x0010,
initError=0x0100,
txEarlyReply=0x0200,
txAbandonPacket=0x0400,
txRestart=0x0800,
txNakReply=0x1000,
rxSequenceError=0x2000,
rxChecksumError=0x4000,
rxCommandError=0x8000
};
//Win32 Serial support: ADB 01/15/07
int ReceiveQueueCount();
//Win32 Serial support: ADB 01/15/07
int TransmitQueueCount();
//Win32 Serial Support: ADB 02/25/2007
void SetDTR(Logical on);
//Win32 Serial support: ADB 01/15/2007
//-------------------------------------------------------------------------
// PCSPAKActive()
// Returns transmitter 'active' state (=0 when all transmission is done).
//-------------------------------------------------------------------------
// This function is now deprecated.
int IsActive();
//Win32 Serial support: ADB 01/15/07
Word Errors();// returns error value, clears it
protected:
//Win32 Serial support: ADB 01/15/07
//Word portBase;
HANDLE hComm;
WORD Error; //error word
//Win32 Serial support: ADB 02/10/07
WORD historyIndex;
BYTE enabled;
BYTE txHoldOff;
BYTE txReply; //reply char
BYTE txState; //status
BYTE txCount; //maximum dialect transmit index
BYTE txResetCount; //counts down each time a NAK is recieved until 0
BYTE txErrorCount; //counts down each time the RIO errors out
BYTE txIdleCount;
BYTE txChecksum;
BYTE txMaximum;
BYTE rxFlags; //receive flags (ack/nak)
BYTE rxState;
BYTE rxCount; //maximum dialect receive index
BYTE rxChecksum;
BYTE rxMaximum;
BYTE* txLengthPtr; //dialect transmit table pointer
BYTE* rxLengthPtr; //dialect receive table pointer
LWord intDataPtr; //pointer to current working packet
// LWord hackCount; //WGR previously missing: seen in pcspak.asm
PCSerPackBuf txBuf;
PCSerPackBuf rxBuf;
//Win32 Serial support: ADB 06/23/07
HANDLE hMutex;
HANDLE hRxThread;
HANDLE hRxAbortEvent;
BOOL bThreadAbort;
OVERLAPPED overlapSend;
};