#include "munga.h" #pragma hdrstop #include "controls.h" #include "gaugrend.h" //#include "windows.h" #if defined(__BCPLUSPLUS__) // //############################################################################# //############################################################################# // #if DEBUG_LEVEL>0 int _matherr(struct exception *a) { switch (a->type) { case DOMAIN: DEBUG_STREAM << "Domain" << std::flush; break; case SING: DEBUG_STREAM << "Singularity" << std::flush; break; case UNDERFLOW: DEBUG_STREAM << "Underflow" << std::flush; break; case OVERFLOW: DEBUG_STREAM << "Overflow" << std::flush; break; case TLOSS: DEBUG_STREAM << "Loss of Precision" << std::flush; break; } DEBUG_STREAM << " error occurred in " << a->name << endl << std::flush; DEBUG_STREAM << "arg1 = " << a->arg1 << endl << std::flush; DEBUG_STREAM << "arg2 = " << a->arg2 << endl << std::flush; DEBUG_STREAM << "retval = " << a->retval << endl << std::flush << std::flush; return 0; } #else int _matherr(struct exception *) { _fpreset(); return 1; } #endif extern "C" void _pure_error_() { Fail("Pure virtual function called"); } #endif // //############################################################################# // Fpu_Ok // // returns True if fpu has no errors, False if errors found //############################################################################# // int Fpu_Ok() { unsigned int s = _status87() & ( SW_INVALID | // SW_DENORMAL | SW_ZERODIVIDE | SW_OVERFLOW // SW_UNDERFLOW | //VERIFY: SW_STACKFAULT ); if (s) { DEBUG_STREAM << "ERROR: FPU status=" << std::flush; if (s & SW_INVALID) { DEBUG_STREAM << "invalid " << std::flush; } if (s & SW_DENORMAL) { DEBUG_STREAM << "denormalized " << std::flush; } if (s & SW_ZERODIVIDE) { DEBUG_STREAM << "zeroDivide " << std::flush; } if (s & SW_OVERFLOW) { DEBUG_STREAM << "overflow " << std::flush; } if (s & SW_UNDERFLOW) { DEBUG_STREAM << "underflow " << std::flush; } /*if (s & SW_STACKFAULT) { DEBUG_STREAM << "stackFault" << std::flush; }*/ DEBUG_STREAM << "\n" << std::flush << std::flush; return False; } else { return True; } } // //############################################################################# //############################################################################# // static Logical AlreadyFailed=False; void Verify_Failed(char *Message, char *File, int Line) { if (!AlreadyFailed) { AlreadyFailed = True; DEBUG_STREAM << File << "(" << Line << "): Failed " << Message << "\n" << std::flush; #if defined(USE_PROFILE_ANALYSIS) Analysis_Named_Status(); #endif DEBUG_STREAM << "Failing to debugger\n" << std::flush << std::flush; SystemClock::timer.Shutdown(); ControlsManager::Shutdown(); GaugeRenderer::EmergencyShutdown(); *(int*)(0xFFFFFFFF) = 0; } } // //############################################################################# //############################################################################# // // // The release build's Fail. Says what went wrong before it goes. // // Terminates exactly as the old bare abort() did - same call, same // 0xC0000409 - so no caller, script or crash handler sees a change. The // only difference is the line in the log naming the check that failed and // where it lives. // // The emergency shutdowns are worth doing before the process ends even // though it is ending: the gauge renderer and the controls manager both // hold hardware, and a display left mid-mode is a nuisance to whoever has // to pick the machine up afterwards - which in a pod bay is not the // person who was playing. // void Fail_With_Message(const char *Message, const char *File, int Line) { if (!AlreadyFailed) { AlreadyFailed = True; DEBUG_STREAM << "FAIL " << File << "(" << Line << "): " << Message << "\n" << std::flush; // // And again, somewhere that cannot be lost. // // rpl4.log is std::cout with its streambuf swapped for an ofstream's // (see WinMain), and the text written above did NOT survive to disk // across the exit - flushed as far as the stream and no further. // Rather than guess at where it stops, write the one line that // matters to its own file and close it: fclose is a promise the // bytes are on the disk, and a file opened and closed inside this // function cannot be left dangling by whatever happens next. // // Its own file rather than an append to rpl4.log because that one is // already open for writing and Windows will not share it. // FILE *record = fopen("rpl4-fail.log", "w"); if (record != NULL) { fprintf(record, "FAIL %s(%d): %s\n", File, Line, Message); fclose(record); } // // Hardware last, and after the record is safely written: the gauge // renderer and the controls manager both hold devices, and a display // left mid-mode is a nuisance for whoever picks the machine up - in // a pod bay, not the person who was playing. If one of these faults // on the way down, the failure has already been recorded. // SystemClock::timer.Shutdown(); ControlsManager::Shutdown(); GaugeRenderer::EmergencyShutdown(); } abort(); } // //############################################################################# //############################################################################# // void Fail_To_Debugger(char *Message, char *File, int Line) { if (!AlreadyFailed) { AlreadyFailed = True; DEBUG_STREAM << File << "(" << Line << "): " << Message << "\n" << std::flush; #if defined(USE_PROFILE_ANALYSIS) Analysis_Named_Status(); #endif DEBUG_STREAM << "Failing to debugger\n" << std::flush << std::flush; SystemClock::timer.Shutdown(); ControlsManager::Shutdown(); GaugeRenderer::EmergencyShutdown(); *(int*)(0xFFFFFFFF) = 0; } } // //############################################################################# //############################################################################# // #if defined(USE_SIGNATURE) Signature::Signature() { #if DEBUG_LEVEL>0 mark = magic; #endif } Signature::~Signature() { #if DEBUG_LEVEL>0 mark = noMagic; #endif } int Is_Signature_Bad(const volatile Signature *p) { #if DEBUG_LEVEL>0 if (p->mark == Signature::magic) { return Signature::ok; } else if (p->mark == Signature::noMagic) { return Signature::destroyed; } else { return Signature::corrupted; } #else return False; #endif } #endif