/* Copyright (C) 1994-1995 Apogee Software, Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include "rt_def.h" #include "rt_str.h" #include "rt_error.h" #include "rt_menu.h" #include "isr.h" #include "w_wad.h" #include "z_zone.h" #include "rt_vid.h" #include "rt_util.h" #include "modexlib.h" //MED #include "memcheck.h" //***************************************************************************** // // HARD ERROR ROUTINES // //**************************************************************************** #define WINDOWUX 7 #define WINDOWUY 76 #define WINDOWLX 138 #define WINDOWLY 158 #define MESSAGEBOXCOLOR 166 #define DISKERROR 0x4000 // bit 15 (of deverr) #define IGNOREAVAILABLE 0x1000 // bit 13 (bit 14 isn't used) #define RETRYAVAILABLE 0x800 // bit 12 #define FAILAVAILABLE 0x400 // bit 11 #define LOCATION 0x300 // bit 10 and 9 #define READWRITEERROR 0x80 // bit 8 #define DRIVEOFERROR 0x0F // low-order byte #define DIVISIONINT 0x00 // Globals boolean DivisionError = false; // Statics static char ErrorCodes[13][25] = { "Write-protected disk\0", "Unknown unit\0", "Drive not ready\0", "Unknown command\0", "CRC error in data\0", "Bad drive struct length\0", "Seek error\0", "Unknown media type\0", "Sector not found\0", "Printer out of paper\0", "Write fault\0", "Read fault\0", "General failure\0" }; static char Drives[7][3] = { "A\0", "B\0", "C\0", "D\0", "E\0", "F\0", "G\0" }; static char Locations[4][11] = { "MS-DOS\0", "FAT\0", "Directory\0", "Data area\0" }; static char ReadWrite[2][6] = { "Read\0", "Write\0" }; static boolean ErrorHandlerStarted=false; void (__interrupt __far *olddivisr) () = NULL; //****************************************************************************** // // UL_UserMessage () // //****************************************************************************** void UL_UserMessage (int x, int y, char *str, ...) __attribute__((format(printf,3,4))) { va_list strptr; char buf[128]; int width, height; memset (&buf[0], 0, sizeof (buf)); va_start (strptr, str); vsprintf (&buf[0], str, strptr); va_end (strptr); if ( *(byte *)0x449 == 0x13) { CurrentFont = tinyfont; WindowW=160; WindowH=100; WindowX=80; WindowY=50; US_MeasureStr (&width, &height, &buf[0]); width += (CurrentFont->width[1] << 1); height += (CurrentFont->height << 1); VL_Bar (x, y, WindowW-2, WindowH, MESSAGEBOXCOLOR); PrintX = x+CurrentFont->width[1]; PrintY = y+CurrentFont->height; US_CPrint (&buf[0]); displayofs=bufferofs; OUTP(CRTC_INDEX, CRTC_STARTHIGH); OUTP(CRTC_DATA,((displayofs&0x0000ffff)>>8)); bufferofs += screensize; if (bufferofs > page3start) bufferofs = page1start; } else printf("%s\n",&buf[0]); } //**************************************************************************** // // UL_GeneralError () // //**************************************************************************** int UL_GeneralError (int code) { boolean done = false; int retval = 0; UL_UserMessage (80, 50, "Device Error!\n%s.\n \n(A)bort (R)etry\n", ErrorCodes[code]); if (KeyboardStarted==true) { while (!done) { if (Keyboard[sc_A]) { retval = 1; done = true; while (Keyboard[sc_A]) ; } else if (Keyboard[sc_R]) { retval = 0; done = true; while (Keyboard[sc_R]) ; } } } else { while (!done) { if (kbhit()) { char ch; ch=toupper(getch()); if (ch=='A') { retval = 1; done = true; } else if (ch=='R') { retval = 0; done = true; } } } } return (retval); } //**************************************************************************** // // UL_DriveError () // //**************************************************************************** int UL_DriveError (int code, int location, int rwerror, int whichdrive) { boolean done = false; int retval = 0; UL_UserMessage (80, 50, "Drive Error!\n%s.\nOn drive %s.\nLocation: %s.\n%s error.\n(A)bort (R)etry\n", ErrorCodes[code], Drives[whichdrive], Locations[location], ReadWrite[rwerror]); if (KeyboardStarted==true) { while (!done) { if (Keyboard[sc_A]) { retval = 1; done = true; while (Keyboard[sc_A]) ; } else if (Keyboard[sc_R]) { retval = 0; done = true; while (Keyboard[sc_R]) ; } } } else { while (!done) { if (kbhit()) { char ch; ch=toupper(getch()); if (ch=='A') { retval = 1; done = true; } else if (ch=='R') { retval = 0; done = true; } } } } return (retval); } //**************************************************************************** // // UL_harderr () // //**************************************************************************** int __far UL_harderr (unsigned deverr, unsigned errcode, unsigned far *devhdr) { int DiskError = 0; // Indicates if it was a disk error int IgnoreAvail = 0; // if "ignore" response is available int RetryAvail = 0; // if "retry" response is available int FailAvail = 0; // if "fail" response is available byte ErrorLocation = 0; // Location of error byte RWerror = 0; // Read/Write error (0 == read, 1 == write) byte whichDrive = 0; // Drive the error is on (0 == A, 1 == B, ...) int action; unsigned temp; temp = *devhdr; // Check errors DiskError = (deverr & DISKERROR); IgnoreAvail = (deverr & IGNOREAVAILABLE); RetryAvail = (deverr & RETRYAVAILABLE); FailAvail = (deverr & FAILAVAILABLE); ErrorLocation = ((deverr & LOCATION) >> 8); RWerror = (deverr & READWRITEERROR); if (DiskError == 0) action = UL_GeneralError (errcode); else action = UL_DriveError (errcode, ErrorLocation, RWerror, whichDrive); if (action) Error ("USER BREAK : ROTT aborted.\n"); return (_HARDERR_RETRY); } //**************************************************************************** // // UL_DivisionISR () // //**************************************************************************** extern byte * colormap; void __interrupt __far UL_DivisionISR ( void ) { // acknowledge the interrupt SetBorderColor (*(colormap+(((100-10)>>2)<<8)+160)); DivisionError = true; OUTP (0x20, 0x20); } //**************************************************************************** // // UL_ErrorStartup () // //**************************************************************************** void UL_ErrorStartup ( void ) { if (ErrorHandlerStarted==true) return; ErrorHandlerStarted=true; _harderr (UL_harderr); // Install hard error handler UL_StartupDivisionByZero(); } //**************************************************************************** // // UL_ErrorShutdown () // //**************************************************************************** void UL_ErrorShutdown ( void ) { if (ErrorHandlerStarted==false) return; ErrorHandlerStarted=false; UL_ShutdownDivisionByZero(); } /* =============== = = UL_StartupDivisionByZero = =============== */ void UL_StartupDivisionByZero ( void ) { olddivisr = _dos_getvect(DIVISIONINT); _dos_setvect (DIVISIONINT, UL_DivisionISR); } /* =============== = = UL_ShutdownDivisionByZero = =============== */ void UL_ShutdownDivisionByZero ( void ) { _dos_setvect (DIVISIONINT, olddivisr); }