#ifndef RELEASE #include "Debug.h" #include "pstring.h" #include "networking.h" #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #include #include #include #include extern bool Debug_NT; extern bool Debug_print_block = false; /////////////////////////////////////////////////////////////////////////////// // NT MONO DRIVER SPECS // // Define the various device type values. Note that values used by Microsoft // Corporation are in the range 0-32767, and 32768-65535 are reserved for use // by customers. // #define FILE_DEVICE_MONO 0x00008100 // // Macro definition for defining IOCTL and FSCTL function control codes. Note // that function codes 0-2047 are reserved for Microsoft Corporation, and // 2048-4095 are reserved for customers. // #define MONO_IOCTL_INDEX 0x810 // // The MONO device driver IOCTLs // #define IOCTL_MONO_PRINT CTL_CODE(FILE_DEVICE_MONO, MONO_IOCTL_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_MONO_CLEAR_SCREEN CTL_CODE(FILE_DEVICE_MONO, MONO_IOCTL_INDEX + 1, METHOD_BUFFERED, FILE_ANY_ACCESS) // --------------------------------------------------------------------------- // console debugging functions #define MAX_NUM_WINDOWS 4 #define MAX_NUM_VWINDOWS 8 typedef struct mono_element { unsigned char character; unsigned char attribute; } mono_element; typedef struct { short first_row; short height; short first_col; short width; short cursor_row; short cursor_col; short open; struct mono_element save_buf[25][80]; struct mono_element text[25][80]; } WINDOW; static bool Mono_initialized = 0; static mono_element (*Mono_screen)[25][80]; static char Dbgstr_format[512]; static WINDOW Window[MAX_NUM_WINDOWS]; static ubyte Mono_virtual_window_list[MAX_NUM_VWINDOWS]; #ifndef RELEASE #define MAX_MONO_LENGTH 2048 #else #define MAX_MONO_LENGTH 256 #endif static char Mono_buffer[MAX_MONO_LENGTH]; static HANDLE hNTMonoDriver = NULL; static int Debug_logfile = -1; #define ROW Window[n].first_row #define HEIGHT Window[n].height #define COL Window[n].first_col #define WIDTH Window[n].width #define CROW Window[n].cursor_row #define CCOL Window[n].cursor_col #define OPEN Window[n].open #define CHAR(r, c) (*Mono_screen)[ROW + (r)][COL + (c)].character #define ATTR(r, c) (*Mono_screen)[ROW + (r)][COL + (c)].attribute #define XCHAR(r, c) Window[n].text[ROW + (r)][COL + (c)].character #define XATTR(r, c) Window[n].text[ROW + (r)][COL + (c)].attribute void con_scroll(int n); void con_drawbox(int n); void con_clear(int n); void con_setcursor(int r, int c); void con_mputc(int n, char ch); #define MAX_TCPLOG_LEN 2000 SOCKET tcp_log_sock; SOCKADDR_IN tcp_log_addr; char tcp_log_buffer[MAX_TCPLOG_LEN]; void nw_InitTCPLogging(char *ip, unsigned short port) { unsigned long argp = 1; int addrlen = sizeof(SOCKADDR_IN); tcp_log_sock = socket(AF_INET, SOCK_STREAM, 0); if (INVALID_SOCKET == tcp_log_sock) { return; } memset(&tcp_log_addr, 0, sizeof(SOCKADDR_IN)); tcp_log_addr.sin_family = AF_INET; tcp_log_addr.sin_addr.s_addr = INADDR_ANY; tcp_log_addr.sin_port = 0; if (SOCKET_ERROR == bind(tcp_log_sock, (SOCKADDR *)&tcp_log_addr, sizeof(sockaddr))) { return; } ioctlsocket(tcp_log_sock, FIONBIO, &argp); tcp_log_addr.sin_addr.s_addr = inet_addr(ip); tcp_log_addr.sin_port = htons(port); connect(tcp_log_sock, (SOCKADDR *)&tcp_log_addr, addrlen); } void nw_TCPPrintf(int n, char *format, ...) { va_list args; if (tcp_log_sock == INVALID_SOCKET) return; // filter out messages for other windows if (n != 0) return; va_start(args, format); Pvsprintf(tcp_log_buffer, MAX_TCPLOG_LEN, format, args); fd_set read_fds; timeval tv = {0, 0}; FD_ZERO(&read_fds); FD_SET(tcp_log_sock, &read_fds); if (select(0, NULL, &read_fds, 0, &tv)) { send(tcp_log_sock, tcp_log_buffer, strlen(tcp_log_buffer), 0); } else { // Int3(); } } void Debug_ConsoleExit() { if (hNTMonoDriver) CloseHandle(hNTMonoDriver); } bool Debug_ConsoleInit() { int n = 0; if (Mono_initialized) return 1; // Only use monochrome if D3_MONO environment var is set atexit(Debug_ConsoleExit); if (Debug_NT == true) { hNTMonoDriver = CreateFile("\\\\.\\MONO", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hNTMonoDriver != (HANDLE)(-1)) Mono_initialized = 1; else Mono_initialized = 0; } #ifdef OLD else { _outp(0x3b4, 0x0f); _outp(0x3b4 + 1, 0x55); if (_inp(0x3b4 + 1) != 0x55) { if (getenv("D3_MONO")) Mono_initialized = 1; else Mono_initialized = 0; } else { _outp(0x3b4 + 1, 0); Mono_initialized = 1; } Mono_screen = (mono_element(*)[25][80])0xB0000; } #endif if (Mono_initialized) OPEN = 1; else OPEN = 0; ROW = 2; COL = 0; WIDTH = 80; HEIGHT = 24; CCOL = 0; CROW = 0; con_clear(0); for (n = 1; n < MAX_NUM_WINDOWS; n++) { OPEN = 0; ROW = 2; COL = 1; WIDTH = 78; HEIGHT = 23; CROW = 0; CCOL = 0; } // map 0 always to itself. Mono_virtual_window_list[0] = 0; for (n = 1; n < MAX_NUM_VWINDOWS; n++) { Mono_virtual_window_list[n] = -1; } return 1; } void Debug_ConsoleRedirectMessages(int virtual_window, int physical_window) { int i, n; if (virtual_window < 1 || virtual_window >= MAX_NUM_VWINDOWS) { return; } if (physical_window < 1 || physical_window >= MAX_NUM_WINDOWS) { return; } n = physical_window; if (!OPEN) return; // clear out any bindings and map virtual window to physical window. for (i = 0; i < MAX_NUM_VWINDOWS; i++) { if (Mono_virtual_window_list[i] == physical_window) { Mono_virtual_window_list[i] = -1; } } Mono_virtual_window_list[virtual_window] = physical_window; con_clear(physical_window); } void Debug_LogClose(); bool Debug_Logfile(const char *filename) { if (Debug_logfile == -1) { Debug_logfile = _open(filename, _O_CREAT | _O_WRONLY | _O_TEXT, _S_IREAD | _S_IWRITE); if (Debug_logfile == -1) { Debug_MessageBox(OSMBOX_OK, "Debug", "FYI Logfile couldn't be created."); return false; } atexit(Debug_LogClose); } Debug_LogWrite("BEGINNING LOG\n\n"); return true; } void Debug_LogWrite(const char *str) { if (Debug_logfile > -1) _write(Debug_logfile, str, strlen(str)); } void Debug_LogClose() { if (Debug_logfile > -1) { Debug_LogWrite("\nEND LOG"); _close(Debug_logfile); Debug_logfile = -1; } } void Debug_ConsoleOpen(int n, int row, int col, int width, int height, char *title) { if (!Mono_initialized) return; // error! no mono card if (n >= MAX_NUM_WINDOWS) return; if (OPEN) Debug_ConsoleClose(n); OPEN = 1; ROW = row; COL = col; WIDTH = width; HEIGHT = height; Mono_virtual_window_list[n] = n; if (Debug_NT) { } else { for (row = -1; row < HEIGHT + 1; row++) for (col = -1; col < WIDTH + 1; col++) { CHAR(row, col) = 32; ATTR(row, col) = 7; XCHAR(row, col) = 32; XATTR(row, col) = 7; } con_drawbox(n); CROW = -1; CCOL = 0; Debug_ConsolePrintf(n, title); CROW = 0; CCOL = 0; con_setcursor(ROW + CROW, COL + CCOL); } } void Debug_ConsoleClose(int n) { int row, col; if (!OPEN) return; if (n >= MAX_NUM_WINDOWS) return; if (Debug_NT) { } else { for (row = -1; row < HEIGHT + 1; row++) for (col = -1; col < WIDTH + 1; col++) { CHAR(row, col) = 32; ATTR(row, col) = 7; } } OPEN = 0; CCOL = 0; CROW = 0; con_setcursor(0, 0); Mono_virtual_window_list[n] = -1; } void Debug_ConsolePrintf(int n, char *format, ...) { static bool newline = false; char *ptr = Mono_buffer; va_list args; if (n >= MAX_NUM_VWINDOWS) return; if (n > 0) { n = Mono_virtual_window_list[n]; } // filter out messages if (n > MAX_NUM_WINDOWS || n < 0) return; // if (!OPEN) return; va_start(args, format); Pvsprintf(ptr, MAX_MONO_LENGTH, format, args); if (strlen(ptr) >= MAX_MONO_LENGTH) { return; } if (OPEN) { if (Debug_NT) { DWORD cbReturned; DeviceIoControl(hNTMonoDriver, (DWORD)IOCTL_MONO_PRINT, ptr, strlen(ptr) + 1, NULL, 0, &cbReturned, 0); } else { while (*ptr) con_mputc(n, *ptr++); } } Debug_LogWrite(Mono_buffer); if (n == 0) { OutputDebugString(Mono_buffer); nw_TCPPrintf(n, Mono_buffer); } } void Debug_ConsolePrintf(int n, int row, int col, char *format, ...) { char *ptr = Mono_buffer; int r, c; va_list args; if (Debug_NT) return; if (n >= MAX_NUM_VWINDOWS) return; if (n > 0) { n = Mono_virtual_window_list[n]; } if (n > MAX_NUM_WINDOWS || n < 0) return; va_start(args, format); Pvsprintf(ptr, MAX_MONO_LENGTH, format, args); // if (n==MAX_NUM_WINDOWS) // OutputDebugString (Mono_buffer); if (!OPEN) return; r = CROW; c = CCOL; CROW = row; CCOL = col; while (*ptr) con_mputc(n, *ptr++); CROW = r; CCOL = c; if (n == 0) OutputDebugString(Mono_buffer); } void con_mputc(int n, char c) { if (!OPEN) return; if (Debug_NT) { return; } switch (c) { case 8: if (CCOL > 0) CCOL--; break; case 9: CHAR(CROW, CCOL) = ' '; ATTR(CROW, CCOL) = XATTR(CROW, CCOL); XCHAR(CROW, CCOL) = ' '; CCOL++; while (CCOL % 4) { CHAR(CROW, CCOL) = ' '; ATTR(CROW, CCOL) = XATTR(CROW, CCOL); XCHAR(CROW, CCOL) = ' '; CCOL++; } break; case 10: case 13: CCOL = 0; CROW++; break; default: CHAR(CROW, CCOL) = c; ATTR(CROW, CCOL) = XATTR(CROW, CCOL); XCHAR(CROW, CCOL) = c; CCOL++; } if (CCOL >= WIDTH) { CCOL = 0; CROW++; } if (CROW >= HEIGHT) { CROW--; con_scroll(n); } con_setcursor(ROW + CROW, COL + CCOL); } void copy_row(int nwords, short *src, short *dest1, short *dest2) { __asm { mov ecx,nwords mov esi,src mov ebx,dest1 mov edx,dest2 shr ecx, 1 jnc even_num mov ax, [esi] add esi, 2 mov [ebx], ax add ebx, 2 mov [edx], ax add edx, 2 even_num: cmp ecx, 0 je done rowloop: mov eax, [esi] add esi, 4 mov [edx], eax add edx, 4 mov [ebx], eax add ebx, 4 loop rowloop done: } } void con_scroll(int n) { register int row, col; if (!OPEN) return; if (Debug_NT) return; col = 0; for (row = 0; row < (HEIGHT - 1); row++) copy_row(WIDTH, (short *)&XCHAR(row + 1, col), (short *)&CHAR(row, col), (short *)&XCHAR(row, col)); // for ( col = 0; col < WIDTH; col++ ) // { // CHAR( row, col ) = XCHAR( row+1, col ); // ATTR( row, col ) = XATTR( row+1, col ); // XCHAR( row, col ) = XCHAR( row+1, col ); // XATTR( row, col ) = XATTR( row+1, col ); // } for (col = 0; col < WIDTH; col++) { CHAR(HEIGHT - 1, col) = ' '; ATTR(HEIGHT - 1, col) = XATTR(HEIGHT - 1, col); XCHAR(HEIGHT - 1, col) = ' '; } } void con_setcursor(int row, int col) { int pos = row * 80 + col; if (Debug_NT) { return; } #ifdef OLD _outp(0x3b4, 15); _outp(0x3b5, pos & 0xFF); _outp(0x3b4, 14); _outp(0x3b5, (pos >> 8) & 0xff); #endif } void con_drawbox(int n) { short row, col; if (!OPEN) return; if (Debug_NT) { return; } for (row = 0; row < HEIGHT; row++) { CHAR(row, -1) = 179; CHAR(row, WIDTH) = 179; XCHAR(row, -1) = 179; XCHAR(row, WIDTH) = 179; } for (col = 0; col < WIDTH; col++) { CHAR(-1, col) = 196; CHAR(HEIGHT, col) = 196; XCHAR(-1, col) = 196; XCHAR(HEIGHT, col) = 196; } CHAR(-1, -1) = 218; CHAR(-1, WIDTH) = 191; CHAR(HEIGHT, -1) = 192; CHAR(HEIGHT, WIDTH) = 217; XCHAR(-1, -1) = 218; XCHAR(-1, WIDTH) = 191; XCHAR(HEIGHT, -1) = 192; XCHAR(HEIGHT, WIDTH) = 217; } void con_clear(int n) { short row, col; if (!OPEN) return; if (Debug_NT) { DWORD cbReturned; DeviceIoControl(hNTMonoDriver, (DWORD)IOCTL_MONO_CLEAR_SCREEN, NULL, 0, NULL, 0, &cbReturned, 0); return; } for (row = 0; row < HEIGHT; row++) for (col = 0; col < WIDTH; col++) { CHAR(row, col) = 32; ATTR(row, col) = 7; XCHAR(row, col) = 32; XATTR(row, col) = 7; } CCOL = 0; CROW = 0; } #endif