Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.
This commit is contained in:
parent
2e338c00cb
commit
3d0ee53a05
6072 changed files with 2283311 additions and 0 deletions
29
GeneralsMD/Code/Libraries/Source/debug/_pch.cpp
Normal file
29
GeneralsMD/Code/Libraries/Source/debug/_pch.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/_pch.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Precompiled header (module internal)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
46
GeneralsMD/Code/Libraries/Source/debug/_pch.h
Normal file
46
GeneralsMD/Code/Libraries/Source/debug/_pch.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/_pch.h $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Precompiled header (module internal)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
#ifndef _PCH_H // Include guard
|
||||
#define _PCH_H
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
// we need windows.h at too many places...
|
||||
#define STRICT
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "internal_io.h"
|
||||
#include "internal_except.h"
|
||||
|
||||
#endif // _PCH_H
|
26
GeneralsMD/Code/Libraries/Source/debug/compile_doxygen.bat
Normal file
26
GeneralsMD/Code/Libraries/Source/debug/compile_doxygen.bat
Normal file
|
@ -0,0 +1,26 @@
|
|||
@echo off
|
||||
|
||||
rem
|
||||
rem This batch file generates DoxyGen info and compiles the separate
|
||||
rem HTML files into CHMs.
|
||||
rem
|
||||
rem Assumptions:
|
||||
rem ------------
|
||||
rem - doxygen installed and in path
|
||||
rem - hhc (HTML Help Compiler) installed and in path
|
||||
rem - dot (Graphviz package) installed and in path
|
||||
rem
|
||||
rem Both generated CHM files are then copied over to the
|
||||
rem common DOC area.
|
||||
|
||||
doxygen debug.dox
|
||||
doxygen debug_priv.dox
|
||||
cd doc\html
|
||||
hhc index.hhp
|
||||
copy index.chm ..\..\debug.chm
|
||||
cd ..\html_priv
|
||||
hhc index.hhp
|
||||
copy index.chm ..\..\debug_priv.chm
|
||||
cd ..\..
|
||||
|
||||
copy debug.chm ..\..\docs
|
29
GeneralsMD/Code/Libraries/Source/debug/debug.cpp
Normal file
29
GeneralsMD/Code/Libraries/Source/debug/debug.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug module main code
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
208
GeneralsMD/Code/Libraries/Source/debug/debug.dox
Normal file
208
GeneralsMD/Code/Libraries/Source/debug/debug.dox
Normal file
|
@ -0,0 +1,208 @@
|
|||
# Doxyfile 1.3.1
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# General configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = "EA/Debug module"
|
||||
PROJECT_NUMBER =
|
||||
OUTPUT_DIRECTORY = doc/
|
||||
OUTPUT_LANGUAGE = English
|
||||
USE_WINDOWS_ENCODING = YES
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
HIDE_FRIEND_COMPOUNDS = YES
|
||||
HIDE_IN_BODY_DOCS = YES
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = YES
|
||||
FULL_PATH_NAMES = NO
|
||||
STRIP_FROM_PATH =
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
SHORT_NAMES = NO
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
DETAILS_AT_TOP = NO
|
||||
INHERIT_DOCS = YES
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
TAB_SIZE = 8
|
||||
GENERATE_TODOLIST = NO
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ALIASES = "todo_opt=\todo"
|
||||
ALIASES += "todo_urgent=\todo"
|
||||
ALIASES += "todo_feature=\todo"
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
SHOW_USED_FILES = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = ./
|
||||
FILE_PATTERNS = debug*.h
|
||||
RECURSIVE = NO
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = YES
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = YES
|
||||
TREEVIEW_WIDTH = 250
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = NO
|
||||
USE_PDFLATEX = NO
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = YES
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED = _DEBUG \
|
||||
DOXYGEN
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::addtions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = NO
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::addtions related to the search engine
|
||||
#---------------------------------------------------------------------------
|
||||
SEARCHENGINE = NO
|
||||
CGI_NAME = search.cgi
|
||||
CGI_URL =
|
||||
DOC_URL =
|
||||
DOC_ABSPATH =
|
||||
BIN_ABSPATH = /usr/local/bin/
|
||||
EXT_DOC_PATHS =
|
320
GeneralsMD/Code/Libraries/Source/debug/debug.dsp
Normal file
320
GeneralsMD/Code/Libraries/Source/debug/debug.dsp
Normal file
|
@ -0,0 +1,320 @@
|
|||
# Microsoft Developer Studio Project File - Name="debug" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=debug - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "debug.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "debug.mak" CFG="debug - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "debug - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "debug - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "debug - Win32 Internal" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "debug - Win32 Profile" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "debug"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "debug - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /G6 /MD /W3 /WX /Zi /Ot /Og /Oi /Oy /Ob2 /Gy /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /Yu"_pch.h" /FD /GF /Gs /c
|
||||
# SUBTRACT CPP /Oa
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=copying
|
||||
PostBuild_Cmds=copy release\debug.lib ..\..\lib
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "debug - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /G6 /MDd /W3 /WX /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /Yu"_pch.h" /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"Debug\debugdebug.lib"
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=copying
|
||||
PostBuild_Cmds=copy debug\debugdebug.lib ..\..\lib
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "debug - Win32 Internal"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Internal"
|
||||
# PROP BASE Intermediate_Dir "Internal"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Internal"
|
||||
# PROP Intermediate_Dir "Internal"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G6 /MD /W3 /WX /Zi /Ot /Oa /Og /Oi /Oy /Ob2 /Gy /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /Yu"_pch.h" /FD /GF /Gs /c
|
||||
# ADD CPP /nologo /G6 /MD /W3 /WX /Zi /Ot /Og /Oi /Oy /Ob2 /Gy /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "_INTERNAL" /Yu"_pch.h" /FD /GF /Gs /c
|
||||
# SUBTRACT CPP /Oa
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"Internal\debuginternal.lib"
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=copying
|
||||
PostBuild_Cmds=copy internal\debuginternal.lib ..\..\lib
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "debug - Win32 Profile"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Profile"
|
||||
# PROP BASE Intermediate_Dir "Profile"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Profile"
|
||||
# PROP Intermediate_Dir "Profile"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G6 /MD /W3 /WX /Zi /Ot /Oa /Og /Oi /Oy /Ob2 /Gy /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /Yu"_pch.h" /FD /GF /Gs /c
|
||||
# ADD CPP /nologo /G6 /MD /W3 /WX /Zi /Ot /Og /Oi /Oy /Ob2 /Gy /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "_PROFILE" /Yu"_pch.h" /FD /GF /Gs /c
|
||||
# SUBTRACT CPP /Oa
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"Profile\debugprofile.lib"
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=copying
|
||||
PostBuild_Cmds=copy profile\debugprofile.lib ..\..\lib
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "debug - Win32 Release"
|
||||
# Name "debug - Win32 Debug"
|
||||
# Name "debug - Win32 Internal"
|
||||
# Name "debug - Win32 Profile"
|
||||
# Begin Group "Precompiled header"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\_pch.cpp
|
||||
# ADD CPP /Yc"_pch.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\_pch.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Doxygen"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\compile_doxygen.bat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug.dox
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_priv.dox
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "IO Classes"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_io.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_io_con.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_io_flat.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_io_net.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_io_ods.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\internal_io.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Exception handler"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_except.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\internal_except.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rc_exception.inl
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Stack walk"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_stack.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_stack.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_stack.inl
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Command interface"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_cmd.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_cmd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_getdefaultcommands.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Proxy header"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Include\rts\debug.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug.cpp
|
||||
# ADD CPP /FAcs
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_debug.cpp
|
||||
|
||||
!IF "$(CFG)" == "debug - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "debug - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "debug - Win32 Internal"
|
||||
|
||||
# ADD CPP /FAcs
|
||||
|
||||
!ELSEIF "$(CFG)" == "debug - Win32 Profile"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_debug.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_doc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_internal.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_macro.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_purecall.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\internal.h
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
179
GeneralsMD/Code/Libraries/Source/debug/debug.dsw
Normal file
179
GeneralsMD/Code/Libraries/Source/debug/debug.dsw
Normal file
|
@ -0,0 +1,179 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "debug"=.\debug.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
debug
|
||||
.
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "debug_dlg"=.\debug_dlg\debug_dlg.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
debug_dlg
|
||||
.\debug_dlg
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "netserv"=.\netserv\netserv.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
netserv
|
||||
.\netserv
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "test1"=.\test1\test1.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
test1
|
||||
.\test1
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name debug
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "test2"=.\test2\test2.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
test2
|
||||
.\test2
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name debug
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "test3"=.\test3\test3.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
test3
|
||||
.\test3
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name debug
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "test4"=.\test4\test4.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
test4
|
||||
.\test4
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name debug
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "test5"=.\test5\test5.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
test5
|
||||
.\test5
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name debug
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "test6"=.\test6\test6.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
test6
|
||||
.\test6
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name debug
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
120
GeneralsMD/Code/Libraries/Source/debug/debug.h
Normal file
120
GeneralsMD/Code/Libraries/Source/debug/debug.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug.h $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debugging module
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
#ifndef DEBUG_H // Include guard
|
||||
#define DEBUG_H
|
||||
|
||||
/**
|
||||
\page lib_var Library variants
|
||||
|
||||
Generally speaking there are four different library variants:
|
||||
- Internal: all asserts/checks/logs, full optimizations (_INTERNAL macro defined)
|
||||
- %Debug: all asserts/checks/logs, no optimizations (_DEBUG macro defined)
|
||||
- Profile: all asserts/checks/logs, full optimizations, profiling active (_PROFILE macro defined)
|
||||
- Release: no asserts/checks/logs, full optimizations
|
||||
|
||||
These variants will be broken down into separate features which
|
||||
can be queried for by #ifdef(HAS_FEATURE):
|
||||
|
||||
<table><tr>
|
||||
<td><b>Variant</b></td>
|
||||
<td><b>HAS_ASSERTS</b></td>
|
||||
<td><b>HAS_LOGS</b></td>
|
||||
<td><b>HAS_OPT</b></td>
|
||||
<td><b>HAS_PROFILE</b></td>
|
||||
</tr><tr>
|
||||
<td>Internal</td>
|
||||
<td><center>Y</center></td>
|
||||
<td><center>Y</center></td>
|
||||
<td><center>Y</center></td>
|
||||
<td><center></center></td>
|
||||
</tr><tr>
|
||||
<td>%Debug</td>
|
||||
<td><center>Y</center></td>
|
||||
<td><center>Y</center></td>
|
||||
<td><center></center></td>
|
||||
<td><center></center></td>
|
||||
</tr><tr>
|
||||
<td>Profile</td>
|
||||
<td><center>Y</center></td>
|
||||
<td><center>Y</center></td>
|
||||
<td><center>Y</center></td>
|
||||
<td><center>Y</center></td>
|
||||
</tr><tr>
|
||||
<td>Release</td>
|
||||
<td><center></center></td>
|
||||
<td><center></center></td>
|
||||
<td><center>Y</center></td>
|
||||
<td><center></center></td>
|
||||
</tr></table>
|
||||
|
||||
Library files have a suffix appended that depends on the
|
||||
library variant:
|
||||
- Internal: XXXInternal.lib
|
||||
- %Debug: XXXDebug.lib
|
||||
- Profile: XXXProfile.lib
|
||||
- Release: XXX.lib
|
||||
*/
|
||||
|
||||
#if defined(_DEBUG) && defined(_INTERNAL)
|
||||
#error "Only either _DEBUG or _INTERNAL should ever be defined"
|
||||
#endif
|
||||
|
||||
// Define which libraries to use.
|
||||
#if defined(_INTERNAL)
|
||||
# pragma comment (lib,"debuginternal.lib")
|
||||
# define HAS_ASSERTS
|
||||
# define HAS_LOGS
|
||||
# define HAS_OPT
|
||||
#elif defined(_DEBUG)
|
||||
# pragma comment (lib,"debugdebug.lib")
|
||||
# define HAS_ASSERTS
|
||||
# define HAS_LOGS
|
||||
#elif defined(_PROFILE)
|
||||
# pragma comment (lib,"debugprofile.lib")
|
||||
# define HAS_ASSERTS
|
||||
# define HAS_LOGS
|
||||
# define HAS_OPT
|
||||
# define HAS_PROFILE
|
||||
#else
|
||||
# pragma comment (lib,"debug.lib")
|
||||
# define HAS_OPT
|
||||
#endif
|
||||
|
||||
// include all our public header files (use double quotes here)
|
||||
#include "debug_doc.h"
|
||||
#include "debug_macro.h"
|
||||
#include "debug_io.h"
|
||||
#include "debug_cmd.h"
|
||||
#include "debug_stack.h"
|
||||
#include "debug_debug.h"
|
||||
|
||||
#endif // DEBUG_H
|
405
GeneralsMD/Code/Libraries/Source/debug/debug_cmd.cpp
Normal file
405
GeneralsMD/Code/Libraries/Source/debug/debug_cmd.cpp
Normal file
|
@ -0,0 +1,405 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_cmd.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug command group 'debug'
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
||||
#include <process.h>
|
||||
|
||||
bool DebugCmdInterfaceDebug::Execute(class Debug& dbg, const char *cmd,
|
||||
CommandMode cmdmode, unsigned argn,
|
||||
const char * const * argv)
|
||||
{
|
||||
// just for convenience...
|
||||
bool normalMode=cmdmode==CommandMode::Normal;
|
||||
|
||||
if (!strcmp(cmd,"help"))
|
||||
{
|
||||
if (!normalMode)
|
||||
return true;
|
||||
|
||||
if (!argn)
|
||||
{
|
||||
dbg << "debug group help:\n"
|
||||
" list, io, alwaysflush, timestamp, exit, clear, add, view\n";
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(argv[0],"list"))
|
||||
{
|
||||
dbg << "list (g|l|d|a|c) [ <pattern> ]\n"
|
||||
"\n"
|
||||
"Shows some or all items of a specific type.\n"
|
||||
"\n"
|
||||
"The following items are supported:\n"
|
||||
"- g: command groups\n"
|
||||
"- l: log groups (only those encountered yet)\n"
|
||||
"- d: log groups with descriptions (only those that have descriptions)\n"
|
||||
"- a: asserts/crashes (only those hit yet)\n"
|
||||
"- c: checks (only those failed yet)\n"
|
||||
"\n"
|
||||
"If a pattern is specified only items matching\n"
|
||||
"that pattern are shown. A pattern can contain\n"
|
||||
"any character, letter, or a wildcard '*'.\n"
|
||||
"\n"
|
||||
"Please note that assert, crashes, and check items have\n"
|
||||
"their line number appended to the current file name,\n"
|
||||
"e.g. debug.cpp(13).\n";
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(argv[0],"io"))
|
||||
{
|
||||
dbg << "io <I/O Class> <cmd> { <param> }]\n"
|
||||
"\n"
|
||||
"Issues a I/O class command. I/O class commands are used\n"
|
||||
"for determining where all log output should be sent. \n"
|
||||
"Please check the list of \ref debug_ioclasses for a list\n"
|
||||
"of existing I/O classes.\n"
|
||||
"\n"
|
||||
"Each existing I/O class must accept at least the\n"
|
||||
"following two commands: 'add' and 'remove'. Usually\n"
|
||||
"after a class has been added it reacts to the 'help'\n"
|
||||
"command as well.\n"
|
||||
"\n"
|
||||
"If the command is entered without any parameters a list\n"
|
||||
"of active I/O classes is shown. Typing 'io ?' retrieves\n"
|
||||
"a list of possible I/O classes.\n";
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(argv[0],"alwaysflush"))
|
||||
{
|
||||
dbg << "alwaysflush [ (+|-) ]\n\n"
|
||||
"Enables/disables flushing after each new entry in\n"
|
||||
"the log file (default: off).\n";
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(argv[0],"timestamp"))
|
||||
{
|
||||
dbg << "timestamp [ (+|-) ]\n\n"
|
||||
"Enables/disables timestamping each log entry\n"
|
||||
"(default: off).\n";
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(argv[0],"exit"))
|
||||
{
|
||||
dbg << "exit\n\nExits program immediately.\n";
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(argv[0],"clear"))
|
||||
{
|
||||
dbg << "clear (l|a|c)\n\n"
|
||||
"Clears the given inclusion/exclusion list\n"
|
||||
"(l=logs, a=asserts/crashes, c=checks).\n";
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(argv[0],"add"))
|
||||
{
|
||||
dbg << "add (l|a|c) (+|-) <pattern>\n"
|
||||
"\n"
|
||||
"Adds a pattern to the given list (l=logs, \n"
|
||||
"a=asserts/crashes, c=checks). By default all\n"
|
||||
"asserts, crashes, and checks are active, all logs\n"
|
||||
"inactive. Each item is then checked \n"
|
||||
"against all pattern in the respective\n"
|
||||
"list. If a match is found the active/inactive\n"
|
||||
"state is modified accordingly (+ for active,\n"
|
||||
"- for inactive). The final state is always\n"
|
||||
"the last match.";
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(argv[0],"view"))
|
||||
{
|
||||
dbg << "view [ (l|a|c) ]\n\n"
|
||||
"Shows the active pattern for the given list\n"
|
||||
"(l=logs, a=asserts/crashes, c=checks).\n";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!strcmp(cmd,"list"))
|
||||
{
|
||||
const char *pattern=argn>=2?argv[1]:"*";
|
||||
|
||||
switch(argn?*argv[0]:0)
|
||||
{
|
||||
case 'g':
|
||||
{
|
||||
if (normalMode)
|
||||
dbg << "Command groups:\n";
|
||||
for (Debug::CmdInterfaceListEntry *cur=dbg.firstCmdGroup;cur;cur=cur->next)
|
||||
if (Debug::SimpleMatch(cur->group,pattern))
|
||||
dbg << cur->group << "\n";
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
case 'd':
|
||||
{
|
||||
if (normalMode)
|
||||
dbg << "Logs:\n";
|
||||
for (Debug::KnownLogGroupList *cur=dbg.firstLogGroup;cur;cur=cur->next)
|
||||
if (Debug::SimpleMatch(cur->nameGroup,pattern)&&
|
||||
(*argv[0]=='l'||cur->descr))
|
||||
{
|
||||
dbg << cur->nameGroup;
|
||||
if (cur->descr)
|
||||
dbg << " (" << cur->descr << ")";
|
||||
dbg << "\n";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
case 'c':
|
||||
{
|
||||
if (normalMode)
|
||||
dbg << (*argv[0]=='a'?"Asserts/Crashes:\n":"Checks:\n");
|
||||
unsigned mask=*argv[0]=='a'?Debug::FrameTypeAssert:Debug::FrameTypeCheck;
|
||||
for (unsigned k=0;k<Debug::FRAME_HASH_SIZE;k++)
|
||||
{
|
||||
for (Debug::FrameHashEntry *cur=dbg.frameHash[k];cur;cur=cur->next)
|
||||
{
|
||||
if (!(cur->frameType&mask))
|
||||
continue;
|
||||
|
||||
char help[256];
|
||||
wsprintf(help,"%s(%i)",cur->fileOrGroup,cur->line);
|
||||
if (Debug::SimpleMatch(help,pattern))
|
||||
{
|
||||
dbg << help << " (" << cur->hits << " hits)";
|
||||
if (cur->status==Debug::Skip)
|
||||
dbg << " [off]";
|
||||
dbg << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dbg << "Unknown item type, see help.";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(cmd,"io"))
|
||||
{
|
||||
// cmd: io
|
||||
if (!argn||!strcmp(argv[0],"?"))
|
||||
{
|
||||
// show active/all I/O classes
|
||||
if (normalMode)
|
||||
dbg << (argn?"Possible:\n":"Active:\n");
|
||||
|
||||
bool hadItem=false;
|
||||
for (Debug::IOFactoryListEntry *cur=dbg.firstIOFactory;cur;cur=cur->next)
|
||||
{
|
||||
if (!argn&&!cur->io)
|
||||
continue;
|
||||
|
||||
hadItem=true;
|
||||
dbg << cur->ioID << " (" << cur->descr << ")\n";
|
||||
}
|
||||
if (normalMode&&!hadItem)
|
||||
dbg << "(none)\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// regular I/O command
|
||||
|
||||
// find I/O class
|
||||
for (Debug::IOFactoryListEntry *cur=dbg.firstIOFactory;cur;cur=cur->next)
|
||||
if (!strcmp(argv[0],cur->ioID))
|
||||
break;
|
||||
if (!cur)
|
||||
{
|
||||
dbg << "Unknown I/O class " << argv[0];
|
||||
return true; // still return true because we knew the command
|
||||
}
|
||||
|
||||
if (argn>1)
|
||||
{
|
||||
// 'add' command?
|
||||
if (!strcmp(argv[1],"add"))
|
||||
{
|
||||
if (cur->io)
|
||||
{
|
||||
dbg << "I/O class already added";
|
||||
return true;
|
||||
}
|
||||
cur->io=cur->factory();
|
||||
if (!cur->io)
|
||||
{
|
||||
dbg << "I/O class factory failed";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 'remove' command?
|
||||
if (!strcmp(argv[1],"remove"))
|
||||
{
|
||||
if (cur->io)
|
||||
{
|
||||
cur->io->Delete();
|
||||
cur->io=NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// now pass along I/O command
|
||||
if (!cur->io)
|
||||
{
|
||||
dbg << "Add I/O class first";
|
||||
return true;
|
||||
}
|
||||
|
||||
cur->io->Execute(dbg,argn>1?argv[1]:NULL,!normalMode,argn>1?argn-2:0,argv+2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(cmd,"alwaysflush"))
|
||||
{
|
||||
if (argn)
|
||||
{
|
||||
if (*argv[0]=='+')
|
||||
dbg.alwaysFlush=true;
|
||||
if (*argv[0]=='-')
|
||||
dbg.alwaysFlush=false;
|
||||
}
|
||||
if (normalMode)
|
||||
dbg << "Always flush: " << (dbg.alwaysFlush?"on":"off");
|
||||
else
|
||||
dbg << (dbg.alwaysFlush?"1":"0");
|
||||
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(cmd,"timestamp"))
|
||||
{
|
||||
if (argn)
|
||||
{
|
||||
if (*argv[0]=='+')
|
||||
dbg.timeStamp=true;
|
||||
if (*argv[0]=='-')
|
||||
dbg.timeStamp=false;
|
||||
}
|
||||
if (normalMode)
|
||||
dbg << "Timestamp: " << (dbg.timeStamp?"on":"off");
|
||||
else
|
||||
dbg << (dbg.timeStamp?"1":"0");
|
||||
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(cmd,"exit"))
|
||||
{
|
||||
exit(1);
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(cmd,"clear")||
|
||||
!strcmp(cmd,"add")||
|
||||
!strcmp(cmd,"view"))
|
||||
{
|
||||
unsigned mask=0;
|
||||
if (argn)
|
||||
{
|
||||
for (const char *p=argv[0];*p;p++)
|
||||
{
|
||||
switch(*p)
|
||||
{
|
||||
case 'l': mask|=Debug::FrameTypeLog; break;
|
||||
case 'a': mask|=Debug::FrameTypeAssert; break;
|
||||
case 'c': mask|=Debug::FrameTypeCheck; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mask)
|
||||
mask=0xffffffff;
|
||||
|
||||
bool modified=false;
|
||||
if (!strcmp(cmd,"clear"))
|
||||
{
|
||||
// remove some (or all) pattern
|
||||
const char *pattern=argn<2?"*":argv[1];
|
||||
for (Debug::PatternListEntry **entryPtr=&dbg.firstPatternEntry;*entryPtr;)
|
||||
{
|
||||
if ( (((*entryPtr)->frameTypes&mask)!=0)
|
||||
&& Debug::SimpleMatch((*entryPtr)->pattern,pattern) )
|
||||
{
|
||||
// remove this entry
|
||||
modified=true;
|
||||
Debug::PatternListEntry *cur=*entryPtr;
|
||||
*entryPtr=cur->next;
|
||||
DebugFreeMemory(cur->pattern);
|
||||
DebugFreeMemory(cur);
|
||||
}
|
||||
else
|
||||
entryPtr=&((*entryPtr)->next);
|
||||
}
|
||||
|
||||
// must fixup lastPatternEntry now
|
||||
if (dbg.firstPatternEntry)
|
||||
{
|
||||
for (Debug::PatternListEntry *cur=dbg.firstPatternEntry;cur->next;cur=cur->next);
|
||||
dbg.lastPatternEntry=cur;
|
||||
}
|
||||
else
|
||||
dbg.lastPatternEntry=NULL;
|
||||
}
|
||||
if (!strcmp(cmd,"add"))
|
||||
{
|
||||
// add a pattern
|
||||
if (argn<3)
|
||||
dbg << "Please specify mode and pattern";
|
||||
else
|
||||
{
|
||||
dbg.AddPatternEntry(mask,*argv[1]=='+',argv[2]);
|
||||
modified=true;
|
||||
}
|
||||
}
|
||||
if (!strcmp(cmd,"view"))
|
||||
{
|
||||
// show list of defined patterns
|
||||
for (Debug::PatternListEntry *cur=dbg.firstPatternEntry;cur;cur=cur->next)
|
||||
{
|
||||
if (!(cur->frameTypes&mask))
|
||||
continue;
|
||||
|
||||
if (cur->frameTypes&Debug::FrameTypeLog) dbg << "l";
|
||||
if (cur->frameTypes&Debug::FrameTypeAssert) dbg << "a";
|
||||
if (cur->frameTypes&Debug::FrameTypeCheck) dbg << "c";
|
||||
|
||||
dbg << (cur->isActive?" + ":" - ") << cur->pattern << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (modified)
|
||||
{
|
||||
// pattern list was modified, set all frame entries statuses to Unknown
|
||||
for (unsigned k=0;k<Debug::FRAME_HASH_SIZE;k++)
|
||||
for (Debug::FrameHashEntry *cur=dbg.frameHash[k];cur;cur=cur->next)
|
||||
cur->status=Debug::Unknown;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// unknown command
|
||||
return false;
|
||||
}
|
131
GeneralsMD/Code/Libraries/Source/debug/debug_cmd.h
Normal file
131
GeneralsMD/Code/Libraries/Source/debug/debug_cmd.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_cmd.h $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug command interface
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
#ifndef DEBUG_CMD_H // Include guard
|
||||
#define DEBUG_CMD_H
|
||||
|
||||
/**
|
||||
\interface DebugCmdInterface debug.h <rts/debug.h>
|
||||
|
||||
\brief Debug command group interface.
|
||||
|
||||
A debug command group interface implementation defines a new
|
||||
command group and the commands implemented for this group.
|
||||
|
||||
A Debug command group interface instance must register itself
|
||||
using Debug::AddCommands. Ownership is then transfered to
|
||||
the Debug module unless the object is manually removed
|
||||
by calling Debug::RemoveCommands.
|
||||
|
||||
For convenience the macro \ref DEBUG_CREATE_COMMAND_GROUP
|
||||
can be used as well.
|
||||
*/
|
||||
class DebugCmdInterface
|
||||
{
|
||||
// no copy/assign op
|
||||
DebugCmdInterface(const &DebugCmdInterface);
|
||||
DebugCmdInterface& operator=(const DebugCmdInterface&);
|
||||
|
||||
protected:
|
||||
// nobody can call this destructor (except child classes)
|
||||
virtual ~DebugCmdInterface() {}
|
||||
|
||||
public:
|
||||
// interface only so no functionality here
|
||||
explicit DebugCmdInterface(void) {}
|
||||
|
||||
/// possible command modes
|
||||
enum CommandMode
|
||||
{
|
||||
/// normal command mode
|
||||
Normal,
|
||||
|
||||
/// structured command mode
|
||||
Structured,
|
||||
|
||||
MAX
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Execute the given command.
|
||||
|
||||
This function is called whenever a command has been issued for
|
||||
the command group the interface implements.
|
||||
|
||||
\param dbg debug instance
|
||||
\param cmd command issued
|
||||
\param cmdmode command mode
|
||||
\param argn number of additional arguments passed in
|
||||
\param argv argument list
|
||||
\return true if command was known, false if not
|
||||
*/
|
||||
virtual bool Execute(class Debug& dbg, const char *cmd, CommandMode cmdmode,
|
||||
unsigned argn, const char * const * argv)=0;
|
||||
|
||||
/**
|
||||
\brief Destroys the current command interface.
|
||||
|
||||
Use this function instead of just delete'ing the instance.
|
||||
*/
|
||||
virtual void Delete(void)=0;
|
||||
};
|
||||
|
||||
/**
|
||||
\addtogroup debug_cmd_macros Debug command interface helper macros
|
||||
|
||||
These macros can be used if a command interface instance should
|
||||
be available right after starting the program (which is usually
|
||||
the case).
|
||||
*/
|
||||
///@{
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
/**
|
||||
\brief Helper macro for creating and registering a command interface
|
||||
instance the Debug module.
|
||||
|
||||
\param groupname name of command group this class if for
|
||||
(without quotes)
|
||||
\param type type name of class we're implementing
|
||||
*/
|
||||
#define DEBUG_CREATE_COMMAND_GROUP(groupname,type)
|
||||
|
||||
#else
|
||||
|
||||
#define DEBUG_CREATE_COMMAND_GROUP(groupname,type) \
|
||||
static bool __RegisterDebugCmdGroup_##type=Debug::AddCommands(#groupname,new type);
|
||||
|
||||
#endif
|
||||
|
||||
///@}
|
||||
|
||||
#endif // DEBUG_CMD_H
|
1625
GeneralsMD/Code/Libraries/Source/debug/debug_debug.cpp
Normal file
1625
GeneralsMD/Code/Libraries/Source/debug/debug_debug.cpp
Normal file
File diff suppressed because it is too large
Load diff
1236
GeneralsMD/Code/Libraries/Source/debug/debug_debug.h
Normal file
1236
GeneralsMD/Code/Libraries/Source/debug/debug_debug.h
Normal file
File diff suppressed because it is too large
Load diff
209
GeneralsMD/Code/Libraries/Source/debug/debug_dlg/debug_dlg.cpp
Normal file
209
GeneralsMD/Code/Libraries/Source/debug/debug_dlg/debug_dlg.cpp
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_dlg/debug_dlg.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug exception dialog test program
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#define STRICT
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Pardon my coding here but this is for testing only...
|
||||
|
||||
#pragma comment (lib,"comctl32")
|
||||
|
||||
BOOL CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
SendDlgItemMessage(hWnd,100,WM_SETTEXT,0,(LPARAM)"EXCEPTION_TYPE");
|
||||
SendDlgItemMessage(hWnd,101,WM_SETTEXT,0,(LPARAM)"Explains exception type further here...\n"
|
||||
"123456789012345678901234567890123456789012345678901234567890");
|
||||
SendDlgItemMessage(hWnd,102,WM_SETTEXT,0,(LPARAM)"Module/File/Line, Address");
|
||||
SendDlgItemMessage(hWnd,103,WM_SETTEXT,0,(LPARAM)"File version, build type");
|
||||
|
||||
HWND list;
|
||||
list=GetDlgItem(hWnd,104);
|
||||
|
||||
LVCOLUMN c;
|
||||
c.mask=LVCF_TEXT|LVCF_WIDTH;
|
||||
c.pszText="";
|
||||
c.cx=0;
|
||||
ListView_InsertColumn(list,0,&c);
|
||||
|
||||
c.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_FMT;
|
||||
c.pszText="Address";
|
||||
c.cx=60;
|
||||
c.fmt=LVCFMT_RIGHT;
|
||||
ListView_InsertColumn(list,1,&c);
|
||||
|
||||
c.mask=LVCF_TEXT|LVCF_WIDTH;
|
||||
c.pszText="Module";
|
||||
c.cx=120;
|
||||
ListView_InsertColumn(list,2,&c);
|
||||
|
||||
c.pszText="Symbol";
|
||||
c.cx=300;
|
||||
ListView_InsertColumn(list,3,&c);
|
||||
|
||||
c.pszText="File";
|
||||
c.cx=130;
|
||||
ListView_InsertColumn(list,4,&c);
|
||||
|
||||
c.pszText="Line";
|
||||
c.cx=80;
|
||||
ListView_InsertColumn(list,5,&c);
|
||||
|
||||
LVITEM item;
|
||||
item.iItem=0;
|
||||
item.iSubItem=0;
|
||||
item.mask=0;
|
||||
|
||||
item.iItem=ListView_InsertItem(list,&item);
|
||||
item.mask=LVIF_TEXT;
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText="01234567";
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText="MSVCRTD.dll+0xad38";
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText="mainCRTStartupSuperLongSymbolOYeahThisIsCool+0xd23e0";
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText="reallyreallyverylongfilename.cpp";
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText="5748+0xad38";
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
for (int k=1;k<30;k++)
|
||||
{
|
||||
item.iItem=k;
|
||||
item.iSubItem=0;
|
||||
item.iItem=ListView_InsertItem(list,&item);
|
||||
item.mask=LVIF_TEXT;
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText="88888888";
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText="MSVCRTD.dll+0xad38";
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText="Debug::DebugException::Symbol+0xd23e0";
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText="regularfilename.cpp";
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText="5748+0x38";
|
||||
ListView_SetItem(list,&item);
|
||||
}
|
||||
|
||||
HFONT hf;
|
||||
hf=CreateFont(13,0,0,0,FW_NORMAL,
|
||||
FALSE,FALSE,FALSE,ANSI_CHARSET,
|
||||
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
|
||||
DEFAULT_QUALITY,FIXED_PITCH|FF_MODERN,NULL);
|
||||
SendDlgItemMessage(hWnd,105,WM_SETFONT,(WPARAM)hf,MAKELPARAM(TRUE,0));
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"EAX:0x00000666 EBX:0x7ffdf000 ECX:0x00000000");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"EDX:0x00422208 ESI:0x02100210 EDI:0x0012fec4");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"EIP:0x0040103d ESP:0x0012fe78 EBP:0x0012fec4");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"Flags:%00000000000000010000001000000110");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"CS:0x001b DS:0x0023 SS:0x0023");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"ES:0x0023 FS:0x0038 GS:0x0000");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"CW:%0000001001111111");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"SW:%0000000000000000");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"TW:%1111111111111111");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"ErrOfs: 0x00000000 ErrSel: 0x03020000");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"DataOfs: 0x00000000 DataSel: 0xffff0000");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"Cr0NpxState: 0x00000000");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"ST(0) 10020203100210021002 -1.#IND00");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"ST(1) 01031002010320020103 -1.#IND00");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"ST(2) 10021002100210021002 -1.#IND00");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"ST(3) 02031002020320020203 -1.#IND00");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"ST(4) 10021002100210021002 -1.#IND00");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"ST(5) 12031002100210021002 -1.#IND00");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"ST(6) 14021402100212031002 -1.#IND00");
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)"ST(7) 12031002100210021002 -1.#IND00");
|
||||
}
|
||||
return TRUE;
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDOK:
|
||||
EndDialog(hWnd,IDOK);
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int CALLBACK WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
|
||||
{
|
||||
// show dialog box first
|
||||
InitCommonControls();
|
||||
DialogBox(hInst,MAKEINTRESOURCE(100),NULL,DialogProc);
|
||||
|
||||
// write out resource data (if possible)
|
||||
FILE *f=fopen("..\\rc_exception.inl","wt");
|
||||
if (f)
|
||||
{
|
||||
fprintf(f,"static unsigned char rcException[]={ // program generated, do not edit\n");
|
||||
|
||||
HRSRC h=FindResource(hInst,MAKEINTRESOURCE(100),RT_DIALOG);
|
||||
DWORD size=SizeofResource(hInst,h);
|
||||
|
||||
unsigned char *data=(unsigned char *)LockResource(LoadResource(hInst,h));
|
||||
for (unsigned k=0;k<size;k+=8)
|
||||
{
|
||||
for (unsigned i=0;i<8;i++)
|
||||
fprintf(f,"0x%02x,",k+i<size?data[k+i]:0);
|
||||
fprintf(f,"\n");
|
||||
}
|
||||
|
||||
fprintf(f,"0 };\n");
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
# Microsoft Developer Studio Project File - Name="debug_dlg" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||
|
||||
CFG=debug_dlg - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "debug_dlg.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "debug_dlg.mak" CFG="debug_dlg - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "debug_dlg - Win32 Release" (based on "Win32 (x86) Application")
|
||||
!MESSAGE "debug_dlg - Win32 Debug" (based on "Win32 (x86) Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "debug_dlg"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "debug_dlg - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "debug_dlg - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "debug_dlg - Win32 Release"
|
||||
# Name "debug_dlg - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_dlg.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\debug_dlg.rc
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
110
GeneralsMD/Code/Libraries/Source/debug/debug_dlg/debug_dlg.rc
Normal file
110
GeneralsMD/Code/Libraries/Source/debug/debug_dlg/debug_dlg.rc
Normal file
|
@ -0,0 +1,110 @@
|
|||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_EXCEPTION DIALOGEX 0, 0, 479, 245
|
||||
STYLE DS_SYSMODAL | DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP |
|
||||
WS_VISIBLE | WS_CAPTION
|
||||
EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
|
||||
CAPTION "Exception"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,422,224,50,14
|
||||
CTEXT "ExType",100,7,7,265,9,SS_NOPREFIX
|
||||
LTEXT "ExMsg",101,7,19,265,28,SS_NOPREFIX | SS_SUNKEN
|
||||
CTEXT "ExAddr",102,7,59,265,19,SS_NOPREFIX | SS_CENTERIMAGE |
|
||||
SS_SUNKEN
|
||||
LTEXT "Location:",IDC_STATIC,7,50,30,8
|
||||
LTEXT "Stack trace:",IDC_STATIC,7,103,40,8
|
||||
CONTROL "List2",104,"SysListView32",LVS_REPORT |
|
||||
LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,115,465,106
|
||||
CTEXT "Ver",103,7,86,265,10,SS_NOPREFIX | SS_SUNKEN
|
||||
LISTBOX 105,280,7,192,103,LBS_NOINTEGRALHEIGHT | LBS_NOSEL |
|
||||
WS_VSCROLL | WS_TABSTOP
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO DISCARDABLE
|
||||
BEGIN
|
||||
IDD_EXCEPTION, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 472
|
||||
VERTGUIDE, 272
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 238
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
35
GeneralsMD/Code/Libraries/Source/debug/debug_dlg/resource.h
Normal file
35
GeneralsMD/Code/Libraries/Source/debug/debug_dlg/resource.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by debug_dlg.rc
|
||||
//
|
||||
#define IDD_EXCEPTION 100
|
||||
#define IDC_STATIC -1
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1003
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
709
GeneralsMD/Code/Libraries/Source/debug/debug_doc.h
Normal file
709
GeneralsMD/Code/Libraries/Source/debug/debug_doc.h
Normal file
|
@ -0,0 +1,709 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_doc.h $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// additional Doxygen module documentation
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
#ifndef DEBUG_DOC_H // Include guard
|
||||
#define DEBUG_DOC_H
|
||||
|
||||
// This generates a small main page for Doxygen if a module only
|
||||
// documentation is built.
|
||||
#ifndef DOXYGEN_GLOBAL_DOC
|
||||
/**
|
||||
\mainpage %Debug module
|
||||
|
||||
The following pages contain the most useful information:
|
||||
- \ref module_debug
|
||||
- \ref debug_macros
|
||||
- \ref debug_stream
|
||||
- \ref debug_cmd
|
||||
|
||||
\internal This is the internal module documentation meant only for
|
||||
programmers who are working on the module internals.
|
||||
*/
|
||||
#endif
|
||||
|
||||
/**
|
||||
\page module_debug Debug module overview
|
||||
|
||||
\section overview Overview
|
||||
|
||||
The Debug module contains all functions necessary to perform debugging related tasks,
|
||||
e.g. checking assertions or logging.
|
||||
|
||||
\section logging Logging
|
||||
|
||||
Logging can be sent to a number of different locations:
|
||||
- a flat log file
|
||||
- a console window
|
||||
- a debugger via OutputDebugString
|
||||
- to a remote program (via a named pipe)
|
||||
- to a number of separated log files
|
||||
|
||||
By default logging is enabled to the flat log file.
|
||||
|
||||
\section cmd Commands
|
||||
|
||||
The debug module is controlled via extendable commands. Commands are
|
||||
typically put into logical groups. A command can then be executed
|
||||
in a number of ways:
|
||||
- group.command \<param\> (explicitly specifies which group to use)
|
||||
- command \<param\> (assumes that the command resides in the same group
|
||||
as the previous one)
|
||||
- group. (switches the current group)
|
||||
|
||||
Every group has to respond to the command 'help'.
|
||||
|
||||
See also: \ref debug_cmd
|
||||
|
||||
\section dbgcmd .dbgcmd file
|
||||
|
||||
On startup the debug module tries to open a file called \<exe\>.dbgcmd -
|
||||
if found then all lines in this module are directly interpreted as commands.
|
||||
If the file is not found then default.dbgcmd is tried instead.
|
||||
This allows for setting up a default environment.
|
||||
*/
|
||||
|
||||
/**
|
||||
\page debug_cmd Debug commands
|
||||
|
||||
Notation used:
|
||||
- [ abc ] means that 'abc' may or may not be specified
|
||||
- { abc } means that 'abc' may be specified any number of times (or not at all)
|
||||
- (a|b|c) means that either 'a', 'b' or 'c' must be specified once
|
||||
|
||||
The following commands are already build in (group: debug):
|
||||
|
||||
<table><tr>
|
||||
<td><b>Command</b></td>
|
||||
<td><b>Parameters</b></td>
|
||||
<td><b>Description</b></td>
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>list</td>
|
||||
<td valign=top>(g|l|d|a|c) [ \<pattern\> ]</td>
|
||||
<td>
|
||||
Shows some or all items of a specific type.
|
||||
|
||||
The following items are supported:
|
||||
- g: command groups
|
||||
- l: log groups (only those encountered yet)
|
||||
- d: log groups with descriptions (only those that have descriptions)
|
||||
- a: asserts/crashes (only those hit yet)
|
||||
- c: checks (only those failed yet)
|
||||
|
||||
If a pattern is specified only items matching
|
||||
that pattern are shown. A pattern can contain
|
||||
any character, letter, or a wildcard '*'.
|
||||
|
||||
Please note that assert, crashes, and check items have
|
||||
their line number appended to the current file name,
|
||||
e.g. debug.cpp(13).
|
||||
|
||||
Example:
|
||||
\code
|
||||
> list g
|
||||
debug
|
||||
> list l test*
|
||||
test
|
||||
test_log2
|
||||
> list d test*
|
||||
test_log2: test log group w/ description
|
||||
\endcode
|
||||
</td>
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>help</td>
|
||||
<td valign=top></td>
|
||||
<td>
|
||||
Shows help regarding debug group commands.
|
||||
|
||||
Example:
|
||||
\code
|
||||
> help
|
||||
Help info debug group:
|
||||
...
|
||||
\endcode
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>io</td>
|
||||
<td valign=top>[ \<I/O Class\> \<cmd\> { \<param\> }] </td>
|
||||
<td>
|
||||
Issues a I/O class command. I/O class commands are used
|
||||
for determining where all log output should be sent.
|
||||
Please check the list of \ref debug_ioclasses for a list
|
||||
of existing I/O classes.
|
||||
|
||||
Each existing I/O class must accept at least the
|
||||
following two commands: 'add' and 'remove'. Parameters
|
||||
for these commands and additional commands are defined
|
||||
on this page: \ref debug_ioclasses
|
||||
|
||||
If the command is entered without any parameters a list
|
||||
of active I/O classes is shown. Typing 'io ?' retrieves
|
||||
a list of possible I/O classes.
|
||||
|
||||
Example:
|
||||
\code
|
||||
> io
|
||||
Active:
|
||||
flat (flat log file)
|
||||
ods (OutputDebugString)
|
||||
> io ods remove
|
||||
> io ?
|
||||
Possible:
|
||||
flat (flat/split log file)
|
||||
con (console window)
|
||||
ods (OutputDebugString)
|
||||
net (Network destination via named pipe)
|
||||
\endcode
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>alwaysflush</td>
|
||||
<td valign=top>[ (+|-) ]</td>
|
||||
<td>
|
||||
Enables/disables flushing after each new entry in
|
||||
the log file (default: off)
|
||||
|
||||
Example:
|
||||
\code
|
||||
> alwaysflush +
|
||||
Flush: on
|
||||
\endcode
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>timestamp</td>
|
||||
<td valign=top>[ (+|-) ]</td>
|
||||
<td>
|
||||
Enables/disables timestamping each log entry
|
||||
(default: off).
|
||||
|
||||
Example:
|
||||
\code
|
||||
> timestamp +
|
||||
Timestamping: on
|
||||
\endcode
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>exit</td>
|
||||
<td valign=top></td>
|
||||
<td>
|
||||
Exits program immediately.
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>clear</td>
|
||||
<td valign=top>(l|a|c)</td>
|
||||
<td>
|
||||
Clears the given inclusion/exclusion list
|
||||
(l=logs, a=asserts/crashes, c=checks).
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>add</td>
|
||||
<td valign=top>(l|a|c) (+|-) \<pattern\></td>
|
||||
<td>
|
||||
Adds a pattern to the given list (l=logs,
|
||||
a=asserts/crashes, c=checks). By default all
|
||||
asserts, crashes, and checks are active, all logs
|
||||
inactive. Each item is then checked
|
||||
against all pattern in the respective
|
||||
list. If a match is found the active/inactive
|
||||
state is modified accordingly (+ for active, -
|
||||
for inactive). The final state is always
|
||||
the last match.
|
||||
|
||||
Example:
|
||||
\code
|
||||
> clear l
|
||||
> add l + test*
|
||||
> add l - *45*
|
||||
\endcode
|
||||
|
||||
This would now enable logging on all log groups
|
||||
that start with 'test' but don't have '45' in
|
||||
the group name.
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>view</td>
|
||||
<td valign=top>[ (l|a|c) ]</td>
|
||||
<td>
|
||||
Shows the active pattern for the given list
|
||||
(l=logs, a=asserts/crashes, c=checks).
|
||||
</td>
|
||||
|
||||
<!-- keep this as template for new commands -->
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top></td>
|
||||
<td valign=top></td>
|
||||
<td>
|
||||
</td>
|
||||
|
||||
</tr></table>
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
\addtogroup debug_stream Debug and Logging stream
|
||||
|
||||
The Debug class can act as an output stream for debugging and logging purposes.
|
||||
This is used e.g. for displaying custom messages in a failed DASSERT_MSG statement
|
||||
or for logging data.
|
||||
|
||||
There are a number of reasons why this module implements this in a stream-like
|
||||
fashion instead of the 'usual' printf method:
|
||||
- type safety: using a streams-like approach makes logging statements
|
||||
type safe. No more crashes in an ASSERT or log statement because the
|
||||
parameter specifiers in the printf format string didn't match with
|
||||
the values actually given.
|
||||
- extensibility: new stream operators can be implemented outside of the debug
|
||||
module
|
||||
|
||||
Syntactically the Debug class acts almost like a ostream class:
|
||||
\code
|
||||
int n=1;
|
||||
float f=4;
|
||||
DLOG( "This is a static string and some other stuff: "
|
||||
<< n << " " << f << "\n" );
|
||||
\endcode
|
||||
|
||||
New types can be added easily, e.g.:
|
||||
\code
|
||||
struct Point2D { int x,y; };
|
||||
|
||||
inline Debug& operator<<(Debug& debug, const Point2D &pt)
|
||||
{
|
||||
debug << "(" << pt.x << ";" << pt.y << ")";
|
||||
return debug;
|
||||
}
|
||||
|
||||
void test(const Point2D &val)
|
||||
{
|
||||
DLOG( "Current point value is " << val << "\n" );
|
||||
DASSERT_MSG( val.x>=0 && val.y>=0, val << " is invalid");
|
||||
}
|
||||
\endcode
|
||||
Please note that all these operators should not be cluttered with any #ifdef _DEBUG
|
||||
or similar conditional compile statements. It is not necessary to remove these
|
||||
operators from the code in release builds (just don't forget to add 'inline' before
|
||||
the operator though).
|
||||
|
||||
In addition there are a number of helper classes declared inside of Debug:
|
||||
- Debug::MemDump provides functions for inserting a raw memory dump into the Debug stream
|
||||
- Debug::HResult dumps out a HRESULT value plus additionally calling custom translator functions
|
||||
*/
|
||||
|
||||
/**
|
||||
\page debug_ioclasses Debug I/O classes
|
||||
|
||||
The %Debug module defines a number of pre-existing I/O classes. New classes can
|
||||
be developed and added.
|
||||
|
||||
An I/O class can have additional commands and parameters. This section lists
|
||||
the existing I/O classes and their additional commands and parameters. The
|
||||
initial part of the command ('io \<class\>') is omitted here.
|
||||
|
||||
\section debug_ioc_flat flat (flat or split log file)
|
||||
|
||||
By default all data is written into a single flag log file. Optionally the
|
||||
size of this log file may be limited (implemented by using a memory based
|
||||
ring buffer).
|
||||
|
||||
<table><tr>
|
||||
<td><b>I/O Command</b></td>
|
||||
<td><b>Parameters</b></td>
|
||||
<td><b>Description</b></td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>add</td>
|
||||
<td valign=top>[ \<filename\> [ \<size in kb\> ] ]</td>
|
||||
<td>
|
||||
Adds the flat I/O class. If a filename is
|
||||
specified all output is written to that file.
|
||||
Otherwise the filename \<exe\>-\<machinename\>.log
|
||||
(resp. \<exe\>-\<machinename\>-\<splitname\>.log)
|
||||
is automatically used. Any existing files with
|
||||
that name are overwritten.
|
||||
|
||||
Instead of a real file name a 'magic' file name
|
||||
can be used by starting the file name with a '*'
|
||||
followed by any number of special characters:
|
||||
- 'e': inserts EXE name
|
||||
- 'm': inserts machine name
|
||||
- 'u': inserts username
|
||||
- 't': inserts timestamp
|
||||
- 'n': inserts split name (empty if main log file)
|
||||
- '-': inserts '-'
|
||||
- 'E', 'M', 'U', 'T', 'N': same as above but with '-'
|
||||
in front (for 'N': empty if main log file)
|
||||
.log is automatically appended if using magic
|
||||
file names.
|
||||
|
||||
So basically 'add' and 'and *eMN' are identical.
|
||||
|
||||
If a size is specified then all data is internally written
|
||||
to a fixed size memory based ring buffer. This data is
|
||||
flushed out once the program exits.
|
||||
|
||||
If no size is given then the size of the log file
|
||||
is not limited and any log data is written out
|
||||
immediately.
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>copy</td>
|
||||
<td valign=top>\<directory\></td>
|
||||
<td>
|
||||
Copies generated log file(s) into the given
|
||||
directory if the program exists or crashes.
|
||||
If there is already a log file with the same
|
||||
name a unique number is appended to the
|
||||
current log files' name.
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>splitadd</td>
|
||||
<td valign=top>\<types\> \<filter\> \<name\> [ \<size in kb\> ]</td>
|
||||
<td>
|
||||
Splits off part of the log data. Multiple
|
||||
splits can be defined. They are written out
|
||||
to the first matching split file.
|
||||
|
||||
'types' defines one or more
|
||||
string types which should be split off:
|
||||
- a: asserts/crashes
|
||||
- c: checks
|
||||
- l: logs
|
||||
- h: crash
|
||||
- x: exceptions
|
||||
- r: replies from commands
|
||||
- o: other messages
|
||||
|
||||
Next a filter is specified that determines
|
||||
which items are to be filtered (only for string
|
||||
types a, c and l). Items can be listed with
|
||||
then 'list' command. The filter is exactly specified
|
||||
as in that command.
|
||||
|
||||
The third parameter defines a name for this
|
||||
split. If there is already a split with the same name
|
||||
then both will write to the same destination file.
|
||||
|
||||
Note: If splits are used and the filename given
|
||||
for 'add' is static then the split name is automatically
|
||||
appended to the log file name (before the extension).
|
||||
|
||||
If a size is specified then all data is internally written
|
||||
to a fixed size memory based ring buffer. This data is
|
||||
flushed out once the program exits.
|
||||
|
||||
If no size is given then the size of the log file
|
||||
is not limited and any log data is written out
|
||||
immediately.
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>splitview</td>
|
||||
<td valign=top></td>
|
||||
<td>
|
||||
Shows all existing splits in the order they are
|
||||
evaluated.
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>splitremove</td>
|
||||
<td valign=top>\<namepattern\></td>
|
||||
<td>
|
||||
Removes all active splits matching the given
|
||||
name pattern.
|
||||
</td>
|
||||
|
||||
<!-- keep this as template for new commands -->
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top></td>
|
||||
<td valign=top></td>
|
||||
<td>
|
||||
</td>
|
||||
|
||||
</tr></table>
|
||||
|
||||
\section debug_ioc_con con (console window)
|
||||
|
||||
<table><tr>
|
||||
<td><b>I/O Command</b></td>
|
||||
<td><b>Parameters</b></td>
|
||||
<td><b>Description</b></td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>add</td>
|
||||
<td valign=top>%</td>
|
||||
<td>
|
||||
Adds the console window as log output. A new
|
||||
console window is created (if it doesn't
|
||||
exist already).
|
||||
</td>
|
||||
|
||||
<!-- keep this as template for new commands -->
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top></td>
|
||||
<td valign=top></td>
|
||||
<td>
|
||||
</td>
|
||||
|
||||
</tr></table>
|
||||
|
||||
\section debug_ioc_ods ods (OutputDebugString, for use in debugger)
|
||||
|
||||
<table><tr>
|
||||
<td><b>I/O Command</b></td>
|
||||
<td><b>Parameters</b></td>
|
||||
<td><b>Description</b></td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>add</td>
|
||||
<td valign=top>%</td>
|
||||
<td>
|
||||
%Debug output is sent via OutputDebugString.
|
||||
</td>
|
||||
|
||||
<!-- keep this as template for new commands -->
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top></td>
|
||||
<td valign=top></td>
|
||||
<td>
|
||||
</td>
|
||||
|
||||
</tr></table>
|
||||
|
||||
\section debug_ioc_net net (Network destination via named pipe)
|
||||
|
||||
<table><tr>
|
||||
<td><b>I/O Command</b></td>
|
||||
<td><b>Parameters</b></td>
|
||||
<td><b>Description</b></td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>add</td>
|
||||
<td valign=top>\<name\></td>
|
||||
<td>
|
||||
Tells system which computer to connect to for
|
||||
remote logging. By default this is the local
|
||||
machine. The debug module tries to connect
|
||||
to a named pipe \\\\\<name\>\\pipe\\ea_debug_v1.
|
||||
|
||||
<!-- sorry about all these backslashes but they're used for escaping... -->
|
||||
</td>
|
||||
|
||||
<!-- keep this as template for new commands -->
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top></td>
|
||||
<td valign=top></td>
|
||||
<td>
|
||||
</td>
|
||||
|
||||
</tr></table>
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
\page debug_structcmd Structured command reply
|
||||
|
||||
\section debug_structcmd_overview Overview
|
||||
|
||||
All commands are capable of returning replies in two differnt forms: A regular
|
||||
reply or a structured reply.
|
||||
A structured reply is basically like the regular reply but with three differences:
|
||||
- Structured reply string type \ref DebugIOInterface::StructuredCmdReply
|
||||
- There is a 1:1 mapping between command and result i.e. no matter how long a command
|
||||
result is there will always be only one call to the \ref DebugIOInterface::Write method
|
||||
for that result.
|
||||
- The result format is fixed for any given command i.e. it must not change.
|
||||
|
||||
A structured reply is given if the command is invoked with a '!' as first character.
|
||||
|
||||
The motivation behind having structured command replies is to make it possible
|
||||
to hide some of the debug command complexity behind a UI.
|
||||
|
||||
\section debug_structcmd_list List of structured command replies for debug command group
|
||||
|
||||
The reply for a structured command always consists of first repeating the
|
||||
given command, a CR and then additional optional reply data.
|
||||
|
||||
<table><tr>
|
||||
<td valign=top><b>Command</b></td>
|
||||
<td><b>Reply</b></td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>list</td>
|
||||
<td>
|
||||
\<item 1\> CR<br>
|
||||
...<br>
|
||||
\<item N\> CR
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>help</td>
|
||||
<td>
|
||||
regular reply format (unstructured)
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>io, io ?</td>
|
||||
<td>
|
||||
\<item 1\> CR<br>
|
||||
...<br>
|
||||
\<item N\> CR
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>io \<any parameters\></td>
|
||||
<td>
|
||||
'1' CR (if command ok) <br>
|
||||
'0' \<error msg\> CR (if command failed)
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>alwaysflush</td>
|
||||
<td>
|
||||
'1' CR (if flush on) <br>
|
||||
'0' CR (if flush off)
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>timestamp</td>
|
||||
<td>
|
||||
'1' CR (if timestamp on) <br>
|
||||
'0' CR (if timestamp off)
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>exit</td>
|
||||
<td>
|
||||
none
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>clear</td>
|
||||
<td>
|
||||
none
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>add</td>
|
||||
<td>
|
||||
none
|
||||
</td>
|
||||
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top>view</td>
|
||||
<td>
|
||||
\<item 1\> CR<br>
|
||||
...<br>
|
||||
\<item N\> CR
|
||||
</td>
|
||||
|
||||
<!-- keep this as template for new commands -->
|
||||
</tr><tr>
|
||||
|
||||
<!---------------------------------->
|
||||
<td valign=top></td>
|
||||
<td>
|
||||
</td>
|
||||
|
||||
</tr></table>
|
||||
*/
|
||||
|
||||
#endif // DEBUG_DOC_H
|
409
GeneralsMD/Code/Libraries/Source/debug/debug_except.cpp
Normal file
409
GeneralsMD/Code/Libraries/Source/debug/debug_except.cpp
Normal file
|
@ -0,0 +1,409 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_except.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Unhandled exception handler
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
||||
#include <commctrl.h>
|
||||
|
||||
#pragma comment (lib,"comctl32")
|
||||
|
||||
DebugExceptionhandler::DebugExceptionhandler(void)
|
||||
{
|
||||
// don't do anything here!
|
||||
}
|
||||
|
||||
const char *DebugExceptionhandler::GetExceptionType(struct _EXCEPTION_POINTERS *exptr, char *explanation)
|
||||
{
|
||||
#define EX(code,text) \
|
||||
case EXCEPTION_##code: strcpy(explanation,text); return "EXCEPTION_" #code;
|
||||
|
||||
switch(exptr->ExceptionRecord->ExceptionCode)
|
||||
{
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
wsprintf(explanation,
|
||||
"The thread tried to read from or write to a virtual\n"
|
||||
"address for which it does not have the appropriate access.\n"
|
||||
"Access address 0x%08x was %s.",
|
||||
exptr->ExceptionRecord->ExceptionInformation[1],
|
||||
exptr->ExceptionRecord->ExceptionInformation[0]?"written to":"read from");
|
||||
return "EXCEPTION_ACCESS_VIOLATION";
|
||||
EX(ARRAY_BOUNDS_EXCEEDED,"The thread tried to access an array element that\n"
|
||||
"is out of bounds and the underlying hardware\n"
|
||||
"supports bounds checking.")
|
||||
EX(BREAKPOINT,"A breakpoint was encountered.")
|
||||
EX(DATATYPE_MISALIGNMENT,"The thread tried to read or write data that is\n"
|
||||
"misaligned on hardware that does not provide alignment.\n"
|
||||
"For example, 16-bit values must be aligned on\n"
|
||||
"2-byte boundaries; 32-bit values on 4-byte\n"
|
||||
"boundaries, and so on.")
|
||||
EX(FLT_DENORMAL_OPERAND,"One of the operands in a floating-point operation is\n"
|
||||
"denormal. A denormal value is one that is too small\n"
|
||||
"to represent as a standard floating-point value.")
|
||||
EX(FLT_DIVIDE_BY_ZERO,"The thread tried to divide a floating-point\n"
|
||||
"value by a floating-point divisor of zero.")
|
||||
EX(FLT_INEXACT_RESULT,"The result of a floating-point operation\n"
|
||||
"cannot be represented exactly as a decimal fraction.")
|
||||
EX(FLT_INVALID_OPERATION,"Some strange unknown floating point operation was attempted.")
|
||||
EX(FLT_OVERFLOW,"The exponent of a floating-point operation is greater\n"
|
||||
"than the magnitude allowed by the corresponding type.")
|
||||
EX(FLT_STACK_CHECK,"The stack overflowed or underflowed as the result\n"
|
||||
"of a floating-point operation.")
|
||||
EX(FLT_UNDERFLOW,"The exponent of a floating-point operation is less\n"
|
||||
"than the magnitude allowed by the corresponding type.")
|
||||
EX(GUARD_PAGE,"A guard page was accessed.")
|
||||
EX(ILLEGAL_INSTRUCTION,"The thread tried to execute an invalid instruction.")
|
||||
EX(IN_PAGE_ERROR,"The thread tried to access a page that was not\n"
|
||||
"present, and the system was unable to load the page.\n"
|
||||
"For example, this exception might occur if a network "
|
||||
"connection is lost while running a program over the network.")
|
||||
EX(INT_DIVIDE_BY_ZERO,"The thread tried to divide an integer value by\n"
|
||||
"an integer divisor of zero.")
|
||||
EX(INT_OVERFLOW,"The result of an integer operation caused a carry\n"
|
||||
"out of the most significant bit of the result.")
|
||||
EX(INVALID_DISPOSITION,"An exception handler returned an invalid disposition\n"
|
||||
"to the exception dispatcher. Programmers using a\n"
|
||||
"high-level language such as C should never encounter\n"
|
||||
"this exception.")
|
||||
EX(INVALID_HANDLE,"An invalid Windows handle was used.")
|
||||
EX(NONCONTINUABLE_EXCEPTION,"The thread tried to continue execution after\n"
|
||||
"a noncontinuable exception occurred.")
|
||||
EX(PRIV_INSTRUCTION,"The thread tried to execute an instruction whose\n"
|
||||
"operation is not allowed in the current machine mode.")
|
||||
EX(SINGLE_STEP,"A trace trap or other single-instruction mechanism\n"
|
||||
"signaled that one instruction has been executed.")
|
||||
EX(STACK_OVERFLOW,"The thread used up its stack.")
|
||||
case 0xE06D7363: strcpy(explanation,"Microsoft C++ Exception"); return "EXCEPTION_MS";
|
||||
default:
|
||||
wsprintf(explanation,"Unknown exception code 0x%08x",exptr->ExceptionRecord->ExceptionCode);
|
||||
return "EXCEPTION_UNKNOWN";
|
||||
}
|
||||
|
||||
#undef EX
|
||||
}
|
||||
|
||||
void DebugExceptionhandler::LogExceptionLocation(Debug &dbg, struct _EXCEPTION_POINTERS *exptr)
|
||||
{
|
||||
struct _CONTEXT &ctx=*exptr->ContextRecord;
|
||||
|
||||
char buf[512];
|
||||
DebugStackwalk::Signature::GetSymbol(ctx.Eip,buf,sizeof(buf));
|
||||
dbg << "Exception occured at\n" << buf << ".";
|
||||
}
|
||||
|
||||
void DebugExceptionhandler::LogRegisters(Debug &dbg, struct _EXCEPTION_POINTERS *exptr)
|
||||
{
|
||||
struct _CONTEXT &ctx=*exptr->ContextRecord;
|
||||
|
||||
dbg << Debug::FillChar('0')
|
||||
<< Debug::Hex()
|
||||
<< "EAX:" << Debug::Width(8) << ctx.Eax
|
||||
<< " EBX:" << Debug::Width(8) << ctx.Ebx
|
||||
<< " ECX:" << Debug::Width(8) << ctx.Ecx << "\n"
|
||||
<< "EDX:" << Debug::Width(8) << ctx.Edx
|
||||
<< " ESI:" << Debug::Width(8) << ctx.Esi
|
||||
<< " EDI:" << Debug::Width(8) << ctx.Edi << "\n"
|
||||
<< "EIP:" << Debug::Width(8) << ctx.Eip
|
||||
<< " ESP:" << Debug::Width(8) << ctx.Esp
|
||||
<< " EBP:" << Debug::Width(8) << ctx.Ebp << "\n"
|
||||
<< "Flags:" << Debug::Bin() << Debug::Width(32) << ctx.EFlags << Debug::Hex() << "\n"
|
||||
<< "CS:" << Debug::Width(4) << ctx.SegCs
|
||||
<< " DS:" << Debug::Width(4) << ctx.SegDs
|
||||
<< " SS:" << Debug::Width(4) << ctx.SegSs
|
||||
<< "\nES:" << Debug::Width(4) << ctx.SegEs
|
||||
<< " FS:" << Debug::Width(4) << ctx.SegFs
|
||||
<< " GS:" << Debug::Width(4) << ctx.SegGs << "\n" << Debug::FillChar() << Debug::Dec();
|
||||
}
|
||||
|
||||
void DebugExceptionhandler::LogFPURegisters(Debug &dbg, struct _EXCEPTION_POINTERS *exptr)
|
||||
{
|
||||
struct _CONTEXT &ctx=*exptr->ContextRecord;
|
||||
|
||||
if (!(ctx.ContextFlags&CONTEXT_FLOATING_POINT))
|
||||
{
|
||||
dbg << "FP registers not available\n";
|
||||
return;
|
||||
}
|
||||
|
||||
FLOATING_SAVE_AREA &flt=ctx.FloatSave;
|
||||
dbg << Debug::Bin() << Debug::FillChar('0')
|
||||
<< "CW:" << Debug::Width(16) << (flt.ControlWord&0xffff) << "\n"
|
||||
<< "SW:" << Debug::Width(16) << (flt.StatusWord&0xffff) << "\n"
|
||||
<< "TW:" << Debug::Width(16) << (flt.TagWord&0xffff) << "\n"
|
||||
<< Debug::Hex()
|
||||
<< "ErrOfs: " << Debug::Width(8) << flt.ErrorOffset
|
||||
<< " ErrSel: " << Debug::Width(8) << flt.ErrorSelector << "\n"
|
||||
<< "DataOfs: " << Debug::Width(8) << flt.DataOffset
|
||||
<< " DataSel: " << Debug::Width(8) << flt.DataSelector << "\n"
|
||||
<< "Cr0NpxState: " << Debug::Width(8) << flt.Cr0NpxState << "\n";
|
||||
|
||||
for (unsigned k=0;k<SIZE_OF_80387_REGISTERS/10;++k)
|
||||
{
|
||||
dbg << Debug::Dec() << "ST(" << k << ") ";
|
||||
dbg.SetPrefixAndRadix("",16);
|
||||
|
||||
BYTE *value=flt.RegisterArea+k*10;
|
||||
for (unsigned i=0;i<10;i++)
|
||||
dbg << Debug::Width(2) << value[i];
|
||||
|
||||
double fpVal;
|
||||
|
||||
// convert from temporary real (10 byte) to double
|
||||
_asm
|
||||
{
|
||||
mov eax,value
|
||||
fld tbyte ptr [eax]
|
||||
fstp qword ptr [fpVal]
|
||||
}
|
||||
|
||||
dbg << " " << fpVal << "\n";
|
||||
}
|
||||
dbg << Debug::FillChar() << Debug::Dec();
|
||||
}
|
||||
|
||||
// include exception dialog box
|
||||
#include "rc_exception.inl"
|
||||
|
||||
// stupid dialog box function needs this
|
||||
static struct _EXCEPTION_POINTERS *exPtrs;
|
||||
|
||||
// and this saves us from re-generating register/version info again...
|
||||
static char regInfo[1024],verInfo[256];
|
||||
|
||||
// and this saves us from doing a stack walk twice
|
||||
static DebugStackwalk::Signature sig;
|
||||
|
||||
static BOOL CALLBACK ExceptionDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
if (LOWORD(wParam)==IDOK)
|
||||
EndDialog(hWnd,IDOK);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// init dialog box
|
||||
|
||||
// version
|
||||
SendDlgItemMessage(hWnd,103,WM_SETTEXT,0,(LPARAM)verInfo);
|
||||
|
||||
// registers
|
||||
char *p=regInfo;
|
||||
for (char *q=p;;q++)
|
||||
{
|
||||
if (!*q||*q=='\n')
|
||||
{
|
||||
bool quit=!*q; *q=0;
|
||||
SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)p);
|
||||
if (quit)
|
||||
break;
|
||||
p=q+1;
|
||||
}
|
||||
}
|
||||
|
||||
// yes, this generates a GDI leak but we're crashing anyway
|
||||
SendDlgItemMessage(hWnd,105,WM_SETFONT,(WPARAM)CreateFont(13,0,0,0,FW_NORMAL,
|
||||
FALSE,FALSE,FALSE,ANSI_CHARSET,
|
||||
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
|
||||
DEFAULT_QUALITY,FIXED_PITCH|FF_MODERN,NULL),MAKELPARAM(TRUE,0));
|
||||
|
||||
// exception type
|
||||
SendDlgItemMessage(hWnd,100,WM_SETTEXT,0,(LPARAM)
|
||||
DebugExceptionhandler::GetExceptionType(exPtrs,regInfo));
|
||||
SendDlgItemMessage(hWnd,101,WM_SETTEXT,0,(LPARAM)regInfo);
|
||||
|
||||
// address
|
||||
struct _CONTEXT &ctx=*exPtrs->ContextRecord;
|
||||
DebugStackwalk::Signature::GetSymbol(ctx.Eip,regInfo,sizeof(regInfo));
|
||||
SendDlgItemMessage(hWnd,102,WM_SETTEXT,0,(LPARAM)regInfo);
|
||||
|
||||
// stack
|
||||
// (this code is a little messy because we're dealing with a raw list control)
|
||||
HWND list;
|
||||
list=GetDlgItem(hWnd,104);
|
||||
if (!sig.Size())
|
||||
{
|
||||
LVCOLUMN c;
|
||||
c.mask=LVCF_TEXT|LVCF_WIDTH;
|
||||
c.pszText="";
|
||||
c.cx=690;
|
||||
ListView_InsertColumn(list,0,&c);
|
||||
|
||||
LVITEM item;
|
||||
item.iItem=0;
|
||||
item.iSubItem=0;
|
||||
item.mask=LVIF_TEXT;
|
||||
item.pszText="No stack data available - check for dbghelp.dll";
|
||||
|
||||
item.iItem=ListView_InsertItem(list,&item);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add columns first
|
||||
LVCOLUMN c;
|
||||
c.mask=LVCF_TEXT|LVCF_WIDTH;
|
||||
c.pszText="";
|
||||
c.cx=0; // first column is empty (can't right-align 1st column)
|
||||
ListView_InsertColumn(list,0,&c);
|
||||
|
||||
c.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_FMT;
|
||||
c.pszText="Address";
|
||||
c.cx=60;
|
||||
c.fmt=LVCFMT_RIGHT;
|
||||
ListView_InsertColumn(list,1,&c);
|
||||
|
||||
c.mask=LVCF_TEXT|LVCF_WIDTH;
|
||||
c.pszText="Module";
|
||||
c.cx=120;
|
||||
ListView_InsertColumn(list,2,&c);
|
||||
|
||||
c.pszText="Symbol";
|
||||
c.cx=300;
|
||||
ListView_InsertColumn(list,3,&c);
|
||||
|
||||
c.pszText="File";
|
||||
c.cx=130;
|
||||
ListView_InsertColumn(list,4,&c);
|
||||
|
||||
c.pszText="Line";
|
||||
c.cx=80;
|
||||
ListView_InsertColumn(list,5,&c);
|
||||
|
||||
// now add stack walk lines
|
||||
for (unsigned k=0;k<sig.Size();k++)
|
||||
{
|
||||
DebugStackwalk::Signature::GetSymbol(sig.GetAddress(k),regInfo,sizeof(regInfo));
|
||||
|
||||
LVITEM item;
|
||||
item.iItem=k;
|
||||
item.iSubItem=0;
|
||||
item.mask=0;
|
||||
item.iItem=ListView_InsertItem(list,&item);
|
||||
item.mask=LVIF_TEXT;
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText=strtok(regInfo," ");
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText=strtok(NULL,",");
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText=strtok(NULL,",");
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText=strtok(NULL,":");
|
||||
ListView_SetItem(list,&item);
|
||||
|
||||
item.iSubItem++;
|
||||
item.pszText=strtok(NULL,"");
|
||||
ListView_SetItem(list,&item);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
LONG __stdcall DebugExceptionhandler::ExceptionFilter(struct _EXCEPTION_POINTERS* pExPtrs)
|
||||
{
|
||||
// we should not be calling ourselves!
|
||||
static bool inExceptionFilter;
|
||||
if (inExceptionFilter)
|
||||
{
|
||||
MessageBox(NULL,"Exception in exception handler","Fatal error",MB_OK);
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
inExceptionFilter=true;
|
||||
|
||||
if (pExPtrs->ExceptionRecord->ExceptionCode==EXCEPTION_STACK_OVERFLOW)
|
||||
{
|
||||
// almost everything we are about to do will generate a second
|
||||
// stack overflow... double fault... so give at least a little warning
|
||||
OutputDebugString("EA/DEBUG: EXCEPTION_STACK_OVERFLOW\n");
|
||||
}
|
||||
|
||||
// Let's log some info
|
||||
Debug &dbg=Debug::Instance;
|
||||
|
||||
// we're logging an exception
|
||||
++dbg.disableAssertsEtc;
|
||||
if (dbg.curType!=DebugIOInterface::StringType::MAX)
|
||||
dbg.FlushOutput();
|
||||
dbg.StartOutput(DebugIOInterface::StringType::Exception,"");
|
||||
|
||||
// start off with the exception type & location
|
||||
dbg << "\n" << Debug::RepeatChar('=',80) << "\n";
|
||||
dbg << GetExceptionType(pExPtrs,regInfo) << ":\n" << regInfo << "\n\n";
|
||||
LogExceptionLocation(dbg,pExPtrs); dbg << "\n\n";
|
||||
|
||||
// build info must be saved off for dialog...
|
||||
unsigned curOfs=dbg.ioBuffer[DebugIOInterface::Exception].used;
|
||||
dbg.WriteBuildInfo();
|
||||
unsigned len=dbg.ioBuffer[DebugIOInterface::Exception].used-curOfs;
|
||||
if (len>=sizeof(verInfo))
|
||||
len=sizeof(verInfo)-1;
|
||||
memcpy(verInfo,dbg.ioBuffer[DebugIOInterface::Exception].buffer+curOfs,len);
|
||||
verInfo[len]=0;
|
||||
dbg << "\n\n";
|
||||
|
||||
// save off register info as well...
|
||||
curOfs=dbg.ioBuffer[DebugIOInterface::Exception].used;
|
||||
LogRegisters(dbg,pExPtrs); dbg << "\n";
|
||||
LogFPURegisters(dbg,pExPtrs); dbg << "\n";
|
||||
len=dbg.ioBuffer[DebugIOInterface::Exception].used-curOfs;
|
||||
if (len>=sizeof(regInfo))
|
||||
len=sizeof(regInfo)-1;
|
||||
memcpy(regInfo,dbg.ioBuffer[DebugIOInterface::Exception].buffer+curOfs,len);
|
||||
regInfo[len]=0;
|
||||
|
||||
// now finally add stack & EIP dump
|
||||
dbg.m_stackWalk.StackWalk(sig,pExPtrs->ContextRecord);
|
||||
dbg << sig << "\n";
|
||||
|
||||
dbg << "Bytes around EIP:" << Debug::MemDump::Char(((char *)(pExPtrs->ContextRecord->Eip))-32,80);
|
||||
|
||||
dbg.FlushOutput();
|
||||
|
||||
// shut down real Debug module now
|
||||
// (atexit code never gets called in exception case)
|
||||
Debug::StaticExit();
|
||||
|
||||
// Show a dialog box
|
||||
InitCommonControls();
|
||||
exPtrs=pExPtrs;
|
||||
DialogBoxIndirect(NULL,(LPDLGTEMPLATE)rcException,NULL,ExceptionDlgProc);
|
||||
|
||||
// Now die
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_getdefaultcommands.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// DebugGetDefaultCommands function
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
||||
|
||||
// this function has its own file so that it can be 'overridden'
|
||||
// by another program using the Debug module
|
||||
const char *DebugGetDefaultCommands(void)
|
||||
{
|
||||
return "!debug.io flat add";
|
||||
}
|
86
GeneralsMD/Code/Libraries/Source/debug/debug_internal.cpp
Normal file
86
GeneralsMD/Code/Libraries/Source/debug/debug_internal.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_internal.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Implementation of internal code
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
||||
|
||||
void DebugInternalAssert(const char *file, int line, const char *expr)
|
||||
{
|
||||
// dangerous as well but since this function is used in this
|
||||
// module only we know how long stuff can get
|
||||
char buf[512];
|
||||
wsprintf(buf,"File %s, line %i:\n%s",file,line,expr);
|
||||
MessageBox(NULL,buf,"Internal assert failed",
|
||||
MB_OK|MB_ICONSTOP|MB_TASKMODAL|MB_SETFOREGROUND);
|
||||
|
||||
// stop right now!
|
||||
TerminateProcess(GetCurrentProcess(),666);
|
||||
}
|
||||
|
||||
void *DebugAllocMemory(unsigned numBytes)
|
||||
{
|
||||
HGLOBAL h=GlobalAlloc(GMEM_FIXED,numBytes);
|
||||
if (!h)
|
||||
DCRASH_RELEASE("Debug mem alloc failed");
|
||||
return (void *)h;
|
||||
}
|
||||
|
||||
void *DebugReAllocMemory(void *oldPtr, unsigned newSize)
|
||||
{
|
||||
// Windows doesn't like ReAlloc with NULL handle/ptr...
|
||||
if (!oldPtr)
|
||||
return newSize?DebugAllocMemory(newSize):0;
|
||||
|
||||
// Shrinking to 0 size is basically freeing memory
|
||||
if (!newSize)
|
||||
{
|
||||
GlobalFree((HGLOBAL)oldPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// now try GlobalReAlloc first
|
||||
HGLOBAL h=GlobalReAlloc((HGLOBAL)oldPtr,newSize,0);
|
||||
if (!h)
|
||||
{
|
||||
// this failed (Windows doesn't like ReAlloc'ing larger
|
||||
// fixed memory blocks) - go with Alloc/Free instead
|
||||
h=GlobalAlloc(GMEM_FIXED,newSize);
|
||||
if (!h)
|
||||
DCRASH_RELEASE("Debug mem realloc failed");
|
||||
unsigned oldSize=GlobalSize((HGLOBAL)oldPtr);
|
||||
memcpy((void *)h,oldPtr,oldSize<newSize?oldSize:newSize);
|
||||
GlobalFree((HGLOBAL)oldPtr);
|
||||
}
|
||||
|
||||
return (void *)h;
|
||||
}
|
||||
|
||||
void DebugFreeMemory(void *ptr)
|
||||
{
|
||||
if (ptr)
|
||||
GlobalFree((HGLOBAL)ptr);
|
||||
}
|
202
GeneralsMD/Code/Libraries/Source/debug/debug_io.h
Normal file
202
GeneralsMD/Code/Libraries/Source/debug/debug_io.h
Normal file
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_io.h $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug I/O interface
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
#ifndef DEBUG_IO_H // Include guard
|
||||
#define DEBUG_IO_H
|
||||
|
||||
/**
|
||||
\interface DebugIOInterface debug.h <rts/debug.h>
|
||||
|
||||
\brief Debug I/O interface.
|
||||
|
||||
A Debug I/O interface implementation must register itself
|
||||
using Debug::AddIOFactory. Typically this is done
|
||||
by using the \ref DEBUG_DECLARE_IO_INTERFACE and
|
||||
\ref DEBUG_IMPLEMENT_IO_INTERFACE macros (recommended, but
|
||||
not mandatory.)
|
||||
*/
|
||||
class DebugIOInterface
|
||||
{
|
||||
// no copy/assign op
|
||||
DebugIOInterface(const &DebugIOInterface);
|
||||
DebugIOInterface& operator=(const DebugIOInterface&);
|
||||
|
||||
protected:
|
||||
/**
|
||||
\brief I/O class destructor.
|
||||
|
||||
The destructor must always be protected. Destruction is
|
||||
done by calling the Delete member function.
|
||||
*/
|
||||
virtual ~DebugIOInterface() {}
|
||||
|
||||
public:
|
||||
// interface only so no functionality here
|
||||
explicit DebugIOInterface(void) {}
|
||||
|
||||
/// List of possible log string types
|
||||
enum StringType
|
||||
{
|
||||
/// DASSERT etc
|
||||
Assert = 0,
|
||||
|
||||
/// DCHECK etc
|
||||
Check,
|
||||
|
||||
/// DLOG etc
|
||||
Log,
|
||||
|
||||
/// DCRASH etc
|
||||
Crash,
|
||||
|
||||
/// Exception
|
||||
Exception,
|
||||
|
||||
/// Regular command reply
|
||||
CmdReply,
|
||||
|
||||
/// Structured command reply, see \ref debug_structcmd
|
||||
StructuredCmdReply,
|
||||
|
||||
/// some other message
|
||||
Other,
|
||||
|
||||
MAX
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Retrieves up to the given number of characters from a command input source.
|
||||
|
||||
This source can be e.g. keyboard or a network pipe. This function must
|
||||
not block.
|
||||
|
||||
\param buf buffer to place read characters in
|
||||
\param maxchar maximum number of characters to return
|
||||
\return numbers of characters written to buffer
|
||||
\note There is no terminating NUL char written to the buffer
|
||||
*/
|
||||
virtual int Read(char *buf, int maxchar)=0;
|
||||
|
||||
/**
|
||||
\brief Write out some characters differentiated by the log string type.
|
||||
|
||||
\param type possible string type
|
||||
\param src string source, may be NULL, content depends on type:
|
||||
<table><tr>
|
||||
<td><b>type</b></td><td><b>src</b></td></tr><tr>
|
||||
<td>Assert</td><td>file(line)</td></tr><tr>
|
||||
<td>Check</td><td>file(line)</td></tr><tr>
|
||||
<td>Log</td><td>log group</td></tr><tr>
|
||||
<td>Crash</td><td>file(line)</td></tr><tr>
|
||||
<td>Exception</td><td>NULL</td></tr><tr>
|
||||
<td>CmdReply</td><td>group.command</td></tr><tr>
|
||||
<td>StructuredCmdReply</td><td>group.command</td></tr><tr>
|
||||
<td>Other</td><td>NULL</td>
|
||||
</tr></table>
|
||||
\param str string to output, NUL delimited, if NULL then simply flush
|
||||
output (if applicable)
|
||||
*/
|
||||
virtual void Write(StringType type, const char *src, const char *str)=0;
|
||||
|
||||
/**
|
||||
\brief Emergency shutdown function.
|
||||
|
||||
This function gets called during an exception and should perform the
|
||||
absolute bare minimum (e.g. just flushing and closing the output file).
|
||||
*/
|
||||
virtual void EmergencyFlush(void)=0;
|
||||
|
||||
/**
|
||||
\brief I/O class specific command.
|
||||
|
||||
All io \<class\> commands are passed into this function, with the
|
||||
exception of remove which results in simply calling the class
|
||||
destructor.
|
||||
|
||||
\param dbg debug instance
|
||||
\param cmd command issued
|
||||
\param structuredCmd true if structured command reply, false if not
|
||||
\param argn number of additional arguments passed in
|
||||
\param argv argument list
|
||||
*/
|
||||
virtual void Execute(class Debug& dbg, const char *cmd, bool structuredCmd,
|
||||
unsigned argn, const char * const * argv)=0;
|
||||
|
||||
/**
|
||||
\brief Destroys the current I/O class instance.
|
||||
|
||||
Use this function instead of just delete'ing the instance.
|
||||
*/
|
||||
virtual void Delete(void)=0;
|
||||
};
|
||||
|
||||
/**
|
||||
\addtogroup debug_io_macros Debug I/O interface helper macros
|
||||
*/
|
||||
///@{
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
/**
|
||||
\brief Helper macro used in I/O class declaration to declare
|
||||
a factory function.
|
||||
|
||||
\param type type name of class we're implementing
|
||||
\note This macro changes the access method to private.
|
||||
*/
|
||||
#define DEBUG_DECLARE_IO_INTERFACE(type)
|
||||
|
||||
/**
|
||||
\brief Helper macro for registering I/O class factory with
|
||||
the Debug module.
|
||||
|
||||
\param io_id name of I/O class as it should be registered with Debug module
|
||||
(without quotes)
|
||||
\param descr short I/O class description
|
||||
\param type type name of class we're implementing
|
||||
*/
|
||||
#define DEBUG_IMPLEMENT_IO_INTERFACE(io_id,descr,type)
|
||||
|
||||
#else
|
||||
|
||||
#define DEBUG_DECLARE_IO_INTERFACE(type) \
|
||||
public: \
|
||||
static bool __RegisterClassFactory; \
|
||||
static DebugIOInterface *__ClassFactory(void) { return new type; }
|
||||
|
||||
#define DEBUG_IMPLEMENT_IO_INTERFACE(io_id,descr,type) \
|
||||
static bool type::__RegisterClassFactory=Debug::AddIOFactory(#io_id,descr,type::__ClassFactory);
|
||||
|
||||
#endif
|
||||
|
||||
///@}
|
||||
|
||||
#endif // DEBUG_IO_H
|
230
GeneralsMD/Code/Libraries/Source/debug/debug_io_con.cpp
Normal file
230
GeneralsMD/Code/Libraries/Source/debug/debug_io_con.cpp
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_io_con.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug I/O class con (console window)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
||||
#include <stdlib.h>
|
||||
#include <new> // needed for placement new prototype
|
||||
|
||||
DebugIOCon::DebugIOCon(void):
|
||||
m_inputUsed(0), m_inputRead(0)
|
||||
{
|
||||
// check: is there already a console window open?
|
||||
m_allocatedConsole=AllocConsole()!=0;
|
||||
if (m_allocatedConsole)
|
||||
{
|
||||
HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
|
||||
SetConsoleMode(h,0);
|
||||
|
||||
// make screen buffer same size as currently displayed area
|
||||
// (prevents that our input line gets scrolled out of view)
|
||||
h=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
GetConsoleScreenBufferInfo(h,&info);
|
||||
|
||||
COORD newSize;
|
||||
newSize.X=info.srWindow.Right+1;
|
||||
newSize.Y=info.srWindow.Bottom+1;
|
||||
SetConsoleScreenBufferSize(h,newSize);
|
||||
|
||||
// hide cursor
|
||||
CONSOLE_CURSOR_INFO ci;
|
||||
ci.dwSize=1;
|
||||
ci.bVisible=FALSE;
|
||||
SetConsoleCursorInfo(h,&ci);
|
||||
|
||||
Write(StringType::Other,NULL,"\n\nEA/Debug console open\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
DebugIOCon::~DebugIOCon()
|
||||
{
|
||||
// close console if we allocated it
|
||||
if (m_allocatedConsole)
|
||||
FreeConsole();
|
||||
}
|
||||
|
||||
int DebugIOCon::Read(char *buf, int maxchar)
|
||||
{
|
||||
// We are not supporting reading from the console
|
||||
// unless we allocated that console ourselves.
|
||||
// The reason for that is that if we didn't allocate
|
||||
// the console ourselves we're running as a console
|
||||
// process and if we'd be reading data from the console
|
||||
// we would probably be snatching away keyboard data
|
||||
// for the process that is using that console.
|
||||
if (!m_allocatedConsole)
|
||||
return 0;
|
||||
|
||||
// are we doing a continuous read?
|
||||
if (m_inputRead)
|
||||
{
|
||||
int numRead;
|
||||
if (maxchar>m_inputUsed-m_inputRead)
|
||||
{
|
||||
// return all
|
||||
numRead=m_inputUsed-m_inputRead;
|
||||
memcpy(buf,m_input+m_inputRead,numRead);
|
||||
m_inputRead=m_inputUsed=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// return partially
|
||||
numRead=maxchar;
|
||||
memcpy(buf,m_input+m_inputRead,numRead);
|
||||
m_inputRead+=maxchar;
|
||||
}
|
||||
return numRead;
|
||||
}
|
||||
|
||||
// update our input buffer
|
||||
HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
|
||||
bool returnChars=false;
|
||||
for (;;)
|
||||
{
|
||||
DWORD dwRecords;
|
||||
if (!GetNumberOfConsoleInputEvents(h,&dwRecords))
|
||||
break;
|
||||
if (!dwRecords)
|
||||
break;
|
||||
|
||||
INPUT_RECORD record;
|
||||
ReadConsoleInput(h,&record,1,&dwRecords);
|
||||
if (record.EventType!=KEY_EVENT)
|
||||
continue;
|
||||
|
||||
KEY_EVENT_RECORD &key=record.Event.KeyEvent;
|
||||
if (!key.bKeyDown||!key.uChar.AsciiChar)
|
||||
continue;
|
||||
|
||||
if (key.uChar.AsciiChar=='\r'||
|
||||
key.uChar.AsciiChar=='\n')
|
||||
{
|
||||
m_input[m_inputUsed++]='\n';
|
||||
returnChars=true;
|
||||
break;
|
||||
}
|
||||
|
||||
/// @todo_opt if somebody wants this can be improved by adding support for cursor keys, history, etc
|
||||
|
||||
if (key.uChar.AsciiChar=='\b')
|
||||
{
|
||||
if (m_inputUsed)
|
||||
m_inputUsed--;
|
||||
}
|
||||
else if (((unsigned char)key.uChar.AsciiChar)>=' ')
|
||||
{
|
||||
if (m_inputUsed<sizeof(m_input)-1)
|
||||
m_input[m_inputUsed++]=key.uChar.AsciiChar;
|
||||
}
|
||||
}
|
||||
|
||||
// update screen
|
||||
h=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
GetConsoleScreenBufferInfo(h,&info);
|
||||
CHAR_INFO ci[sizeof(m_input)+1];
|
||||
for (unsigned k=0;k<=sizeof(m_input);k++)
|
||||
{
|
||||
ci[k].Char.AsciiChar=k<m_inputUsed?m_input[k]:' ';
|
||||
ci[k].Attributes=BACKGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_GREEN
|
||||
|FOREGROUND_RED|FOREGROUND_INTENSITY;
|
||||
}
|
||||
|
||||
// fake another cursor
|
||||
if (GetTickCount()&512)
|
||||
ci[m_inputUsed].Attributes=BACKGROUND_BLUE|BACKGROUND_GREEN
|
||||
|BACKGROUND_RED|BACKGROUND_INTENSITY|FOREGROUND_GREEN;
|
||||
|
||||
COORD srcSize,srcCoord;
|
||||
srcSize.X=sizeof(m_input); srcSize.Y=1;
|
||||
srcCoord.X=srcCoord.Y=0;
|
||||
|
||||
SMALL_RECT r;
|
||||
r.Left=r.Top=r.Bottom=0; r.Right=info.dwSize.X-1;
|
||||
WriteConsoleOutput(h,ci+(m_inputUsed<=info.dwSize.X?0:m_inputUsed-info.dwSize.X),
|
||||
srcSize,srcCoord,&r);
|
||||
|
||||
// return data now?
|
||||
if (returnChars&&m_inputUsed>1)
|
||||
{
|
||||
*buf=*m_input;
|
||||
m_inputRead=1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DebugIOCon::Write(StringType type, const char *src, const char *str)
|
||||
{
|
||||
if (type==StringType::StructuredCmdReply||!str)
|
||||
return;
|
||||
|
||||
DWORD dwDummy;
|
||||
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),str,strlen(str),&dwDummy,NULL);
|
||||
}
|
||||
|
||||
void DebugIOCon::Execute(class Debug& dbg, const char *cmd, bool structuredCmd,
|
||||
unsigned argn, const char * const * argv)
|
||||
{
|
||||
if (!cmd||!strcmp(cmd,"help"))
|
||||
{
|
||||
dbg << "con I/O help:\n"
|
||||
" add [ <width> [ <height> ] ]\n"
|
||||
" create con I/O (optionally specifying the window size)\n";
|
||||
}
|
||||
else if (!strcmp(cmd,"add"))
|
||||
{
|
||||
if (argn>0&&m_allocatedConsole)
|
||||
{
|
||||
// resize our console area
|
||||
HANDLE h=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
COORD newSize;
|
||||
newSize.X=atoi(argv[0]);
|
||||
newSize.Y=argn>1?atoi(argv[1]):25;
|
||||
SMALL_RECT sr;
|
||||
sr.Left=sr.Top=0;
|
||||
sr.Right=newSize.X-1;
|
||||
sr.Bottom=newSize.Y-1;
|
||||
SetConsoleWindowInfo(h,TRUE,&sr);
|
||||
SetConsoleScreenBufferSize(h,newSize);
|
||||
SetConsoleWindowInfo(h,TRUE,&sr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DebugIOInterface *DebugIOCon::Create(void)
|
||||
{
|
||||
return new (DebugAllocMemory(sizeof(DebugIOCon))) DebugIOCon();
|
||||
}
|
||||
|
||||
void DebugIOCon::Delete(void)
|
||||
{
|
||||
this->~DebugIOCon();
|
||||
DebugFreeMemory(this);
|
||||
}
|
546
GeneralsMD/Code/Libraries/Source/debug/debug_io_flat.cpp
Normal file
546
GeneralsMD/Code/Libraries/Source/debug/debug_io_flat.cpp
Normal file
|
@ -0,0 +1,546 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_io_flat.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug I/O class flat (flat or split log file)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
||||
#include <stdlib.h>
|
||||
#include <new> // needed for placement new prototype
|
||||
|
||||
DebugIOFlat::OutputStream::OutputStream(const char *filename, unsigned maxSize):
|
||||
m_bufferUsed(0), m_nextChar(0)
|
||||
{
|
||||
m_fileName=(char *)DebugAllocMemory(strlen(filename)+1);
|
||||
strcpy(m_fileName,filename);
|
||||
|
||||
m_limitedFileSize=maxSize>0;
|
||||
m_bufferSize=m_limitedFileSize?maxSize:0x10000;
|
||||
m_buffer=(char *)DebugAllocMemory(m_bufferSize);
|
||||
|
||||
if (!m_limitedFileSize)
|
||||
m_fileHandle=CreateFile(m_fileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH,
|
||||
NULL);
|
||||
}
|
||||
|
||||
DebugIOFlat::OutputStream::~OutputStream()
|
||||
{
|
||||
}
|
||||
|
||||
DebugIOFlat::OutputStream *DebugIOFlat::OutputStream::Create(const char *filename, unsigned maxSize)
|
||||
{
|
||||
return new (DebugAllocMemory(sizeof(OutputStream))) OutputStream(filename,maxSize);
|
||||
}
|
||||
|
||||
void DebugIOFlat::OutputStream::Delete(const char *path)
|
||||
{
|
||||
Flush();
|
||||
if (!m_limitedFileSize)
|
||||
CloseHandle(m_fileHandle);
|
||||
|
||||
if (path&&*path)
|
||||
{
|
||||
// copy file to given path
|
||||
int run=-1;
|
||||
char *ext=strrchr(m_fileName,'.');
|
||||
if (!ext)
|
||||
ext=m_fileName+strlen(m_fileName);
|
||||
char *fileNameOnly=strrchr(m_fileName,'\\');
|
||||
fileNameOnly=fileNameOnly?fileNameOnly+1:m_fileName;
|
||||
|
||||
unsigned pathLen=strlen(path);
|
||||
for (;;)
|
||||
{
|
||||
// absolute path?
|
||||
char help[512];
|
||||
if (path[0]&&(path[1]==':'||(path[0]=='\\'&&path[1]=='\\')))
|
||||
{
|
||||
strcpy(help,path);
|
||||
strcpy(help+pathLen,fileNameOnly);
|
||||
help[ext-fileNameOnly+pathLen]=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no, relative path given
|
||||
strcpy(help,m_fileName);
|
||||
strcpy(help+(fileNameOnly-m_fileName),path);
|
||||
strcpy(help+(fileNameOnly-m_fileName)+pathLen,fileNameOnly);
|
||||
help[ext-fileNameOnly+pathLen+(fileNameOnly-m_fileName)]=0;
|
||||
}
|
||||
if (++run)
|
||||
wsprintf(help+strlen(help),"(%i)%s",run,ext);
|
||||
else
|
||||
strcat(help,ext);
|
||||
if (CopyFile(m_fileName,help,TRUE))
|
||||
break;
|
||||
if (GetLastError()!=ERROR_FILE_EXISTS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DebugFreeMemory(m_buffer);
|
||||
DebugFreeMemory(m_fileName);
|
||||
|
||||
this->~OutputStream();
|
||||
DebugFreeMemory(this);
|
||||
}
|
||||
|
||||
void DebugIOFlat::OutputStream::Write(const char *src)
|
||||
{
|
||||
if (!src)
|
||||
{
|
||||
// flush request, flush only if unlimited file size
|
||||
if (!m_limitedFileSize)
|
||||
Flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned len=strlen(src);
|
||||
|
||||
while (len>m_bufferSize)
|
||||
{
|
||||
InternalWrite(src,m_bufferSize);
|
||||
src+=m_bufferSize;
|
||||
len-=m_bufferSize;
|
||||
}
|
||||
InternalWrite(src,len);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugIOFlat::OutputStream::InternalWrite(const char *src, unsigned len)
|
||||
{
|
||||
__ASSERT(len<=m_bufferSize);
|
||||
|
||||
// unlimited log file length?
|
||||
if (!m_limitedFileSize)
|
||||
{
|
||||
if (m_bufferUsed+len>m_bufferSize)
|
||||
Flush();
|
||||
memcpy(m_buffer+m_bufferUsed,src,len);
|
||||
m_bufferUsed+=len;
|
||||
}
|
||||
else
|
||||
{
|
||||
// just write to ring buffer
|
||||
if ((m_bufferUsed+=len)>m_bufferSize)
|
||||
m_bufferUsed=m_bufferSize;
|
||||
|
||||
while (len)
|
||||
{
|
||||
unsigned toWrite;
|
||||
if (m_nextChar+len>m_bufferSize)
|
||||
toWrite=m_bufferSize-m_nextChar;
|
||||
else
|
||||
toWrite=len;
|
||||
memcpy(m_buffer+m_nextChar,src,toWrite);
|
||||
if ((m_nextChar+=toWrite)>=m_bufferSize)
|
||||
m_nextChar=0;
|
||||
src+=toWrite;
|
||||
len-=toWrite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebugIOFlat::OutputStream::Flush(void)
|
||||
{
|
||||
if (!m_limitedFileSize)
|
||||
{
|
||||
// simple flush to file
|
||||
DWORD written;
|
||||
WriteFile(m_fileHandle,m_buffer,m_bufferUsed,&written,NULL);
|
||||
m_bufferUsed=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// create file, write ring buffer
|
||||
m_fileHandle=CreateFile(m_fileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH,
|
||||
NULL);
|
||||
DWORD written;
|
||||
if (m_bufferUsed<m_bufferSize)
|
||||
WriteFile(m_fileHandle,m_buffer,m_bufferUsed,&written,NULL);
|
||||
else
|
||||
{
|
||||
WriteFile(m_fileHandle,m_buffer+m_nextChar,m_bufferUsed-m_nextChar,&written,NULL);
|
||||
WriteFile(m_fileHandle,m_buffer,m_nextChar,&written,NULL);
|
||||
}
|
||||
CloseHandle(m_fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DebugIOFlat::ExpandMagic(const char *src, const char *splitName, char *buf)
|
||||
{
|
||||
// barf if too long
|
||||
if (strlen(src)>250)
|
||||
src="*eMN";
|
||||
|
||||
// non-magic name?
|
||||
if (*src!='*')
|
||||
{
|
||||
// just return input name
|
||||
if (splitName)
|
||||
{
|
||||
// must jam in split name before extension
|
||||
const char *p=strrchr(src,'.');
|
||||
if (!p)
|
||||
p=src+strlen(src);
|
||||
strncpy(buf,src,p-src);
|
||||
buf[p-src]='-';
|
||||
strcpy(buf+(p-src)+1,splitName);
|
||||
strcat(buf,p);
|
||||
}
|
||||
else
|
||||
strcpy(buf,src);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// translate magic name
|
||||
src++;
|
||||
char *dst=buf;
|
||||
while (*src)
|
||||
{
|
||||
if (dst-buf>250)
|
||||
break;
|
||||
|
||||
if (*src>='A'&&*src<='Z'&&(*src!='N'||splitName))
|
||||
*dst++='-';
|
||||
|
||||
char help[256];
|
||||
DWORD size=sizeof(help);
|
||||
*help=0;
|
||||
|
||||
switch(*src++)
|
||||
{
|
||||
case 'e':
|
||||
case 'E':
|
||||
GetModuleFileName(NULL,help,sizeof(help));
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
GetComputerName(help,&size);
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
GetUserName(help,&size);
|
||||
break;
|
||||
case 't':
|
||||
case 'T':
|
||||
{
|
||||
SYSTEMTIME systime;
|
||||
GetLocalTime(&systime);
|
||||
|
||||
wsprintf(help,"%04i%02i%02i-%02i%02i-%02i",
|
||||
systime.wYear,systime.wMonth,systime.wDay,
|
||||
systime.wHour,systime.wMinute,systime.wSecond);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
case 'N':
|
||||
if (splitName&&strlen(splitName)<250)
|
||||
strcpy(help,splitName);
|
||||
break;
|
||||
default:
|
||||
*dst++=src[-1];
|
||||
}
|
||||
|
||||
unsigned len=strlen(help);
|
||||
if (dst-buf+len>250)
|
||||
break;
|
||||
strcpy(dst,help);
|
||||
dst+=len;
|
||||
}
|
||||
strcpy(dst,".log");
|
||||
}
|
||||
|
||||
DebugIOFlat::DebugIOFlat(void):
|
||||
m_firstStream(NULL), m_firstSplit(NULL),
|
||||
m_lastStreamPtr(&m_firstStream), m_lastSplitPtr(&m_firstSplit)
|
||||
{
|
||||
*m_copyDir=0;
|
||||
}
|
||||
|
||||
DebugIOFlat::~DebugIOFlat()
|
||||
{
|
||||
for (SplitListEntry *cur=m_firstSplit;cur;)
|
||||
{
|
||||
SplitListEntry *kill=cur;
|
||||
cur=cur->next;
|
||||
DebugFreeMemory(kill);
|
||||
}
|
||||
m_firstSplit=NULL;
|
||||
|
||||
for (StreamListEntry *stream=m_firstStream;stream;)
|
||||
{
|
||||
StreamListEntry *kill=stream;
|
||||
stream=stream->next;
|
||||
kill->stream->Delete(m_copyDir);
|
||||
DebugFreeMemory(kill);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugIOFlat::Write(StringType type, const char *src, const char *str)
|
||||
{
|
||||
for (SplitListEntry *cur=m_firstSplit;cur;cur=cur->next)
|
||||
{
|
||||
if (!(cur->stringTypes&(1<<type)))
|
||||
continue;
|
||||
if (src&&*src&&!Debug::SimpleMatch(src,cur->items))
|
||||
continue;
|
||||
cur->stream->Write(str);
|
||||
break;
|
||||
}
|
||||
if (!cur)
|
||||
m_firstStream->stream->Write(str);
|
||||
}
|
||||
|
||||
void DebugIOFlat::EmergencyFlush(void)
|
||||
{
|
||||
for (StreamListEntry *cur=m_firstStream;cur;cur=cur->next)
|
||||
cur->stream->Flush();
|
||||
}
|
||||
|
||||
void DebugIOFlat::Execute(class Debug& dbg, const char *cmd, bool structuredCmd,
|
||||
unsigned argn, const char * const * argv)
|
||||
{
|
||||
if (!cmd||!strcmp(cmd,"help"))
|
||||
{
|
||||
if (!argn)
|
||||
dbg << "flat I/O help:\n"
|
||||
"The following I/O commands are defined:\n"
|
||||
" add, copy, splitadd, splitview, splitremove\n"
|
||||
"Type in debug.io flat help <cmd> for a detailed command help.\n";
|
||||
else if (!strcmp(argv[0],"add"))
|
||||
dbg <<
|
||||
"add [ <filename> [ <size in kb> ] ]\n\n"
|
||||
"Create flat file I/O (optionally specifying file name and file size).\n"
|
||||
"If a filename is specified all output is written to that file. Otherwise\n"
|
||||
"the magic filename '*eMN' is automatically used. Any existing files with\n"
|
||||
"that name are overwritten.\n"
|
||||
"\n"
|
||||
"Instead of a real file name a 'magic' file name can be used by starting\n"
|
||||
"the file name with a '*' followed by any number of special characters:\n"
|
||||
"- 'e': inserts EXE name\n"
|
||||
"- 'm': inserts machine name\n"
|
||||
"- 'u': inserts username\n"
|
||||
"- 't': inserts timestamp\n"
|
||||
"- 'n': inserts split name (empty if main log file)\n"
|
||||
"- '-': inserts '-'\n"
|
||||
"- 'E', 'M', 'U', 'T', 'N': same as above but with '-' in front \n"
|
||||
" (for 'N': empty if main log file)\n"
|
||||
".log is automatically appended if using magic file names.\n"
|
||||
"\n"
|
||||
"If a size is specified then all data is internally written to a fixed \n"
|
||||
"size memory based ring buffer. This data is flushed out once the \n"
|
||||
"program exits. If no size is given then the size of the log file is not \n"
|
||||
"limited and any log data is written out immediately.\n";
|
||||
else if (!strcmp(argv[0],"copy"))
|
||||
dbg <<
|
||||
"copy <directory>\n\n"
|
||||
"Copies generated log file(s) into the given directory if the program\n"
|
||||
"exists or crashes. If there is already a log file with the same\n"
|
||||
"name a unique number is appended to the current log files' name.\n";
|
||||
else if (!strcmp(argv[0],"splitadd"))
|
||||
dbg <<
|
||||
"splitadd <types> <filter> <name> [ <size in kb> ]\n\n"
|
||||
"Splits off part of the log data. Multiple splits can be defined. They \n"
|
||||
"are written out to the first matching split file.\n"
|
||||
"\n"
|
||||
"'types' defines one or more string types which should be split off:\n"
|
||||
"- a: asserts\n"
|
||||
"- c: checks\n"
|
||||
"- l: logs\n"
|
||||
"- h: crash\n"
|
||||
"- x: exceptions\n"
|
||||
"- r: replies from commands\n"
|
||||
"- o: other messages \n"
|
||||
"\n"
|
||||
"Next a filter is specified that determines which items are to be \n"
|
||||
"filtered (only for string types a, c and l). Items can be listed with\n"
|
||||
"then 'list' command. The filter is exactly specified as in that command.\n"
|
||||
"\n"
|
||||
"The third parameter defines a name for this split. If there is \n"
|
||||
"already a split with the same name then both will write to the same \n"
|
||||
"destination file.\n"
|
||||
"\n"
|
||||
"Note: If splits are used and the filename given for 'add' is static \n"
|
||||
"or does not contain 'n' or 'N' then the split name is automatically \n"
|
||||
"appended to the log file name (before the extension).\n"
|
||||
"\n"
|
||||
"If a size is specified then all data is internally written to a \n"
|
||||
"fixed size memory based ring buffer. This data is flushed out once \n"
|
||||
"the program exits.\n"
|
||||
"\n"
|
||||
"If no size is given then the size of the log file is not limited and \n"
|
||||
"any log data is written out immediately.\n";
|
||||
else if (!strcmp(argv[0],"splitview"))
|
||||
dbg << "splitview\n\n"
|
||||
"Shows all existing splits in the order they are evaluated.";
|
||||
else if (!strcmp(argv[0],"splitremove"))
|
||||
dbg << "splitremove <namepattern>\n\n"
|
||||
"Removes all active splits matching the given name pattern.";
|
||||
else
|
||||
dbg << "Unknown flat I/O command";
|
||||
}
|
||||
else if (!strcmp(cmd,"add"))
|
||||
{
|
||||
// add [ <filename> [ <size in kb> ] ]
|
||||
__ASSERT(m_firstStream==NULL);
|
||||
|
||||
strcpy(m_baseFilename,argn?argv[0]:"*eMN");
|
||||
|
||||
char fn[256];
|
||||
ExpandMagic(m_baseFilename,NULL,fn);
|
||||
|
||||
m_firstStream=(StreamListEntry *)DebugAllocMemory(sizeof(StreamListEntry));
|
||||
m_firstStream->next=NULL;
|
||||
m_firstStream->stream=OutputStream::Create(fn,argn>1?atoi(argv[1])*1024:0);
|
||||
m_lastStreamPtr=&m_firstStream->next;
|
||||
}
|
||||
else if (!strcmp(cmd,"copy"))
|
||||
{
|
||||
// copy <directory>
|
||||
if (argn)
|
||||
{
|
||||
strncpy(m_copyDir,argv[0],sizeof(m_copyDir)-1);
|
||||
m_copyDir[sizeof(m_copyDir)-1]=0;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(cmd,"splitadd"))
|
||||
{
|
||||
// splitadd <types> <filter> <name> [ <size in kb> ]
|
||||
if (argn>=3)
|
||||
{
|
||||
// add entry
|
||||
SplitListEntry *cur=(SplitListEntry *)DebugAllocMemory(sizeof(SplitListEntry));
|
||||
cur->next=*m_lastSplitPtr;
|
||||
m_lastSplitPtr=&cur->next;
|
||||
if (!m_firstSplit)
|
||||
m_firstSplit=cur;
|
||||
cur->stringTypes=0;
|
||||
for (const char *p=argv[0];*p;++p)
|
||||
{
|
||||
switch(*p)
|
||||
{
|
||||
case 'a': cur->stringTypes|=1<<Assert; break;
|
||||
case 'c': cur->stringTypes|=1<<Check; break;
|
||||
case 'l': cur->stringTypes|=1<<Log; break;
|
||||
case 'h': cur->stringTypes|=1<<Crash; break;
|
||||
case 'x': cur->stringTypes|=1<<Exception; break;
|
||||
case 'r': cur->stringTypes|=1<<CmdReply; break;
|
||||
case 'o': cur->stringTypes|=1<<Other; break;
|
||||
}
|
||||
}
|
||||
if (!cur->stringTypes)
|
||||
cur->stringTypes=0xffffffff;
|
||||
|
||||
strncpy(cur->items,argv[1],sizeof(cur->items)-1);
|
||||
cur->items[sizeof(cur->items)-1]=0;
|
||||
|
||||
strncpy(cur->name,argv[2],sizeof(cur->name)-1);
|
||||
cur->name[sizeof(cur->name)-1]=0;
|
||||
|
||||
// create our filename, search for stream with same filename
|
||||
char fn[256];
|
||||
ExpandMagic(m_baseFilename,cur->name,fn);
|
||||
for (StreamListEntry *stream=m_firstStream;stream;stream=stream->next)
|
||||
if (!strcmp(stream->stream->GetFilename(),fn))
|
||||
break;
|
||||
if (!stream)
|
||||
{
|
||||
// must create new stream
|
||||
stream=(StreamListEntry *)DebugAllocMemory(sizeof(StreamListEntry));
|
||||
stream->next=NULL;
|
||||
*m_lastStreamPtr=stream;
|
||||
m_lastStreamPtr=&stream->next;
|
||||
stream->stream=OutputStream::Create(fn,argn>3?atoi(argv[3])*1024:0);
|
||||
}
|
||||
cur->stream=stream->stream;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(cmd,"splitview"))
|
||||
{
|
||||
// splitview
|
||||
for (SplitListEntry *cur=m_firstSplit;cur;cur=cur->next)
|
||||
{
|
||||
for (StringType t=Assert;t<MAX;t=(StringType)(t+1))
|
||||
{
|
||||
if (t==StructuredCmdReply||!(cur->stringTypes&(1<<t)))
|
||||
continue;
|
||||
switch(t)
|
||||
{
|
||||
case Assert: dbg << "a"; break;
|
||||
case Check: dbg << "c"; break;
|
||||
case Log: dbg << "l"; break;
|
||||
case Crash: dbg << "h"; break;
|
||||
case Exception: dbg << "x"; break;
|
||||
case CmdReply: dbg << "r"; break;
|
||||
case Other: dbg << "o"; break;
|
||||
}
|
||||
}
|
||||
dbg << " " << cur->items << " " << cur->name << "\n";
|
||||
}
|
||||
}
|
||||
else if (!strcmp(cmd,"splitremove"))
|
||||
{
|
||||
// splitremove <namepattern>
|
||||
const char *pattern=argn<1?"*":argv[0];
|
||||
for (SplitListEntry **entryPtr=&m_firstSplit;*entryPtr;)
|
||||
{
|
||||
if ( Debug::SimpleMatch((*entryPtr)->name,pattern) )
|
||||
{
|
||||
// remove this entry
|
||||
SplitListEntry *cur=*entryPtr;
|
||||
*entryPtr=cur->next;
|
||||
DebugFreeMemory(cur);
|
||||
}
|
||||
else
|
||||
entryPtr=&((*entryPtr)->next);
|
||||
}
|
||||
|
||||
// must fixup m_lastSplitPtr now
|
||||
if (m_firstSplit)
|
||||
{
|
||||
for (SplitListEntry *cur=m_firstSplit;cur->next;cur=cur->next);
|
||||
m_firstSplit=cur;
|
||||
}
|
||||
else
|
||||
m_firstSplit=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DebugIOInterface *DebugIOFlat::Create(void)
|
||||
{
|
||||
return new (DebugAllocMemory(sizeof(DebugIOFlat))) DebugIOFlat();
|
||||
}
|
||||
|
||||
void DebugIOFlat::Delete(void)
|
||||
{
|
||||
this->~DebugIOFlat();
|
||||
DebugFreeMemory(this);
|
||||
}
|
128
GeneralsMD/Code/Libraries/Source/debug/debug_io_net.cpp
Normal file
128
GeneralsMD/Code/Libraries/Source/debug/debug_io_net.cpp
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_io_net.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug I/O class net (Network destination via named pipe)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
||||
#include <new> // needed for placement new prototype
|
||||
|
||||
DebugIONet::DebugIONet(void)
|
||||
{
|
||||
}
|
||||
|
||||
DebugIONet::~DebugIONet()
|
||||
{
|
||||
if (m_pipe!=INVALID_HANDLE_VALUE)
|
||||
CloseHandle(m_pipe);
|
||||
}
|
||||
|
||||
int DebugIONet::Read(char *buf, int maxchar)
|
||||
{
|
||||
if (m_pipe==INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
DWORD mode=PIPE_READMODE_MESSAGE|PIPE_NOWAIT;
|
||||
SetNamedPipeHandleState(m_pipe,&mode,NULL,NULL);
|
||||
|
||||
DWORD read;
|
||||
if (!ReadFile(m_pipe,buf,maxchar-1,&read,NULL))
|
||||
read=0;
|
||||
mode=PIPE_READMODE_MESSAGE|PIPE_WAIT;
|
||||
SetNamedPipeHandleState(m_pipe,&mode,NULL,NULL);
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
void DebugIONet::Write(StringType type, const char *src, const char *str)
|
||||
{
|
||||
if (m_pipe==INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
DWORD dummy;
|
||||
WriteFile(m_pipe,&type,1,&dummy,NULL);
|
||||
|
||||
unsigned len;
|
||||
len=src?strlen(src):0;
|
||||
WriteFile(m_pipe,&len,4,&dummy,NULL);
|
||||
if (len)
|
||||
WriteFile(m_pipe,src,len,&dummy,NULL);
|
||||
|
||||
len=strlen(str);
|
||||
WriteFile(m_pipe,&len,4,&dummy,NULL);
|
||||
if (len)
|
||||
WriteFile(m_pipe,str,len,&dummy,NULL);
|
||||
}
|
||||
|
||||
void DebugIONet::EmergencyFlush(void)
|
||||
{
|
||||
}
|
||||
|
||||
void DebugIONet::Execute(class Debug& dbg, const char *cmd, bool structuredCmd,
|
||||
unsigned argn, const char * const * argv)
|
||||
{
|
||||
if (!cmd||!strcmp(cmd,"help"))
|
||||
{
|
||||
dbg << "net I/O help:\n"
|
||||
" add [ <machine> ]\n"
|
||||
" create net I/O (optionally specifying the machine to connect to)\n";
|
||||
}
|
||||
else if (!strcmp(cmd,"add"))
|
||||
{
|
||||
const char *machine=argn?argv[0]:".";
|
||||
|
||||
char buf[256];
|
||||
wsprintf(buf,"\\\\%s\\pipe\\ea_debug_v1",machine);
|
||||
m_pipe=CreateFile(buf,GENERIC_READ|GENERIC_WRITE,
|
||||
0,NULL,OPEN_EXISTING,0,NULL);
|
||||
if (m_pipe==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
dbg << "Could not connect to given machine.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// we're reading messages
|
||||
DWORD mode=PIPE_READMODE_MESSAGE;
|
||||
SetNamedPipeHandleState(m_pipe,&mode,NULL,NULL);
|
||||
|
||||
// write welcome message
|
||||
char comp[128];
|
||||
mode=sizeof(comp);
|
||||
GetComputerName(comp,&mode);
|
||||
wsprintf(buf,"Client at %s\n",comp);
|
||||
Write(Other,NULL,buf);
|
||||
}
|
||||
}
|
||||
|
||||
DebugIOInterface *DebugIONet::Create(void)
|
||||
{
|
||||
return new (DebugAllocMemory(sizeof(DebugIONet))) DebugIONet();
|
||||
}
|
||||
|
||||
void DebugIONet::Delete(void)
|
||||
{
|
||||
this->~DebugIONet();
|
||||
DebugFreeMemory(this);
|
||||
}
|
47
GeneralsMD/Code/Libraries/Source/debug/debug_io_ods.cpp
Normal file
47
GeneralsMD/Code/Libraries/Source/debug/debug_io_ods.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_io_ods.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug I/O class ods (OutputDebugString, for use in debugger)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
||||
#include <new> // needed for placement new prototype
|
||||
|
||||
void DebugIOOds::Write(StringType type, const char *src, const char *str)
|
||||
{
|
||||
if (type!=StringType::StructuredCmdReply&&str)
|
||||
OutputDebugString(str);
|
||||
}
|
||||
|
||||
DebugIOInterface *DebugIOOds::Create(void)
|
||||
{
|
||||
return new (DebugAllocMemory(sizeof(DebugIOOds))) DebugIOOds();
|
||||
}
|
||||
|
||||
void DebugIOOds::Delete(void)
|
||||
{
|
||||
this->~DebugIOOds();
|
||||
DebugFreeMemory(this);
|
||||
}
|
394
GeneralsMD/Code/Libraries/Source/debug/debug_macro.h
Normal file
394
GeneralsMD/Code/Libraries/Source/debug/debug_macro.h
Normal file
|
@ -0,0 +1,394 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_macro.h $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #2 $
|
||||
// $DateTime: 2003/07/09 10:57:23 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debugging macros
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
#ifndef DEBUG_MACRO_H // Include guard
|
||||
#define DEBUG_MACRO_H
|
||||
|
||||
// I'm putting the documentation for the following macros
|
||||
// here because Doxygen otherwise includes the values of each macro
|
||||
// in the documentation. I don't want that (it would expose some
|
||||
// internals) so I'm putting all comments for the following macros
|
||||
// here...
|
||||
#ifdef DOXYGEN // defined if Doxygen is running
|
||||
|
||||
/**
|
||||
\addtogroup debug_macros Debugging and logging macros
|
||||
|
||||
This module defines a number of macros. Usually only these macros should be
|
||||
used to access any debug functionality.
|
||||
|
||||
All these macros are defined if either _DEBUG or _INTERNAL is defined. Otherwise
|
||||
all of them (with the exception of DCHECK and DCHECK_MSG) will be removed.
|
||||
*/
|
||||
///@{
|
||||
|
||||
/**
|
||||
\brief Regular assert macro.
|
||||
|
||||
This macro will generate an error message on screen if the evaluated expression
|
||||
returns false. The user will then have the choice of aborting the program,
|
||||
continuing once or continuing with completely ignoring that specific assertion.
|
||||
|
||||
Assertions are completely removed if neither _DEBUG nor _INTERNAL are defined.
|
||||
|
||||
\param expr expression, trigger assert window if false
|
||||
*/
|
||||
#define DASSERT(expr)
|
||||
|
||||
/**
|
||||
\brief Assert macro with custom message.
|
||||
|
||||
Like \ref DASSERT but a custom message will be given in addition to the expression.
|
||||
The message can be specified in a stream-like notation, e.g.
|
||||
\code
|
||||
DASSERT_MSG( n>=0 && n<MAX_N, "n:" << n << ", max " << MAX_N);
|
||||
\endcode
|
||||
For more information see the \ref debug_stream page.
|
||||
|
||||
Assertions are completely removed if neither _DEBUG nor _INTERNAL are defined.
|
||||
|
||||
\param expr expression, trigger assert window if false
|
||||
\param msg custom message stream, see \ref debug_stream
|
||||
|
||||
*/
|
||||
#define DASSERT_MSG(expr,msg)
|
||||
|
||||
/**
|
||||
\brief Compile time assertion.
|
||||
|
||||
This assertion will fail during compile time. It can be used anywhere and will
|
||||
(of course) remain in release compiles as well. No code is generated in any case.
|
||||
|
||||
If a compile time assertion fails the compiler will give an error message like
|
||||
this:
|
||||
\code
|
||||
debug.cpp(14) : error C2027: use of undefined type 'StaticAssertionFailed<0>'
|
||||
\endcode
|
||||
|
||||
If the expression given can't be evaluated at compile time the error message
|
||||
looks like this:
|
||||
\code
|
||||
debug.cpp(15) : error C2027: use of undefined type 'StaticAssertionFailed< ?? >'
|
||||
\endcode
|
||||
|
||||
\param expr expression which can be evaluated at compile time
|
||||
*/
|
||||
#define DCTASSERT(expr)
|
||||
|
||||
/**
|
||||
\brief Function macro, checks if the given expression is true, returns false if not.
|
||||
|
||||
Additionally a message is written to the log file. This macro is usually used
|
||||
like this:
|
||||
\code
|
||||
if ( !DCHECK( n>=0 && n<MAX_N ) ) return;
|
||||
\endcode
|
||||
|
||||
\note Checks will remain in place even in release builds!
|
||||
|
||||
\param expr expression which will always be checked
|
||||
*/
|
||||
#define DCHECK(expr)
|
||||
|
||||
/**
|
||||
\brief Function macro, \ref DCHECK with additional message on failure.
|
||||
|
||||
For more information see the \ref debug_stream page.
|
||||
|
||||
\note Even though the expression check will remain in place in release builds the
|
||||
\a msg part is completely removed.
|
||||
|
||||
\param expr expression which will always be checked
|
||||
\param msg custom message stream, see \ref debug_stream
|
||||
*/
|
||||
#define DCHECK_MSG(expr,msg)
|
||||
|
||||
/**
|
||||
\brief Macro for precondition-checks.
|
||||
|
||||
Internally expands to
|
||||
\code
|
||||
if (!DCHECK(!(cond)))
|
||||
\endcode
|
||||
so it can be used e.g. like this:
|
||||
\code
|
||||
DFAIL_IF(!ptrval) return;
|
||||
\endcode
|
||||
|
||||
\param cond condition which is checked for failure
|
||||
*/
|
||||
#define DFAIL_IF(cond)
|
||||
|
||||
/**
|
||||
\brief Convenience macro, \ref DFAIL_IF with additional message on failure.
|
||||
|
||||
Internally expands to
|
||||
\code
|
||||
if (!DCHECK_MSG(!(cond),msg))
|
||||
\endcode
|
||||
so it can be used e.g. like this:
|
||||
\code
|
||||
DFAIL_IF_MSG(!ptrval,"pointer must not be NULL") return;
|
||||
\endcode
|
||||
|
||||
\param cond condition which is checked for failure
|
||||
\param msg custom message stream, see \ref debug_stream
|
||||
*/
|
||||
#define DFAIL_IF_MSG(cond,msg)
|
||||
|
||||
/**
|
||||
\brief Writes a message to the log file.
|
||||
|
||||
It also generates a logging group with the name of the current file (but without
|
||||
path or extension), e.g. if DLOG("hello world") is written in here a logging group
|
||||
called 'debug' would be created.
|
||||
|
||||
Logs can be turned on and off based on individual logging groups.
|
||||
|
||||
\param what message, see \ref debug_stream
|
||||
*/
|
||||
#define DLOG(what)
|
||||
|
||||
/**
|
||||
\brief Adds a description for the current file if used for logging.
|
||||
|
||||
\note This macro must be used in a CPP file in file scope only.
|
||||
\param descr a short static description of what gets logged in the current file
|
||||
*/
|
||||
#define DLOG_DESCR(descr)
|
||||
|
||||
/**
|
||||
\brief Writes a message to the log file using a custom log group.
|
||||
|
||||
Works just like \ref DLOG but instead of using the current file as a logging group
|
||||
the logging group is explicitly specified.
|
||||
|
||||
\note Specifiy the group directly without quotes, e.g.
|
||||
\code
|
||||
DLOG_GROUP(my_log_group,"hello world")
|
||||
\endcode
|
||||
|
||||
\param group logging group, without quotes
|
||||
\param what message, see \ref debug_stream
|
||||
*/
|
||||
#define DLOG_GROUP(group,what)
|
||||
|
||||
/**
|
||||
\brief Adds a description for a custom log group
|
||||
|
||||
\note This macro must be used in a CPP file in file scope only.
|
||||
\param group logging group, without quotes
|
||||
\param descr a short static description of what gets logged in the specified log group
|
||||
*/
|
||||
#define DLOG_GROUP_DESCR(group,descr)
|
||||
|
||||
/**
|
||||
\brief Unconditionally aborts the program in debug/internal builds.
|
||||
|
||||
A DCRASH can not be disabled by the user.
|
||||
|
||||
\param msg custom message stream, see \ref debug_stream
|
||||
*/
|
||||
#define DCRASH(msg)
|
||||
|
||||
/**
|
||||
\brief Unconditional program exit that is active in release builds as well.
|
||||
|
||||
\note In a release build the crash message will not include the file name or
|
||||
line number where the DCRASH_RELEASE was specified.
|
||||
|
||||
\param msg custom message stream, see \ref debug_stream
|
||||
*/
|
||||
#define DCRASH_RELEASE(msg)
|
||||
|
||||
/**
|
||||
\brief Unconditional assert.
|
||||
|
||||
Basically makes sense only as default clause in switch statements to make
|
||||
sure that no case is missed, e.g.
|
||||
\code
|
||||
switch(n)
|
||||
{
|
||||
case MY_DEF_VAL_A:
|
||||
// ...
|
||||
break;
|
||||
case MY_DEF_VAL_B:
|
||||
// ...
|
||||
break;
|
||||
default:
|
||||
DFAIL();
|
||||
}
|
||||
\endcode
|
||||
Gets removed in release builds.
|
||||
*/
|
||||
#define DFAIL()
|
||||
|
||||
/**
|
||||
\brief Function macro, determines if logging is active for current file or not.
|
||||
|
||||
This function macro can be safely used without any #ifdefs:
|
||||
\code
|
||||
if (D_ISLOG())
|
||||
{
|
||||
// do some computationally expensive logging here...
|
||||
}
|
||||
\endcode
|
||||
|
||||
In release builds this macro expands to \a false effectively removing
|
||||
the whole section.
|
||||
|
||||
\return true if logging is active, false if not
|
||||
*/
|
||||
#define D_ISLOG()
|
||||
|
||||
/**
|
||||
\brief Function macro, determines if logging is active for the specified log group or not.
|
||||
|
||||
Works just like \ref D_ISLOG but instead of using the current file as a logging group
|
||||
the logging group is explicitly specified.
|
||||
|
||||
\param group logging group, without quotes
|
||||
\return true if logging is active, false if not
|
||||
*/
|
||||
#define D_ISLOG_GROUP(group)
|
||||
|
||||
///@}
|
||||
|
||||
#elif defined(_DEBUG) || defined(_INTERNAL)
|
||||
|
||||
#define DASSERT(expr) \
|
||||
((void)( Debug::SkipNext() || \
|
||||
(expr) || \
|
||||
Debug::AssertBegin(__FILE__,__LINE__,#expr).AssertDone() ))
|
||||
|
||||
#define DASSERT_MSG(expr,msg) \
|
||||
((void)( Debug::SkipNext() || \
|
||||
(expr) || \
|
||||
( Debug::AssertBegin(__FILE__,__LINE__,#expr) << ": " << msg ).AssertDone() ))
|
||||
|
||||
#define DCHECK(expr) \
|
||||
( (expr) || \
|
||||
Debug::SkipNext() || \
|
||||
Debug::CheckBegin(__FILE__,__LINE__,#expr).CheckDone() )
|
||||
|
||||
#define DCHECK_MSG(expr,msg) \
|
||||
( (expr) || \
|
||||
Debug::SkipNext() || \
|
||||
( Debug::CheckBegin(__FILE__,__LINE__,#expr) << ": " << msg ).CheckDone() )
|
||||
|
||||
#define DFAIL_IF(cond) \
|
||||
if (!DCHECK(!(cond)))
|
||||
|
||||
#define DFAIL_IF_MSG(cond,msg) \
|
||||
if (!DCHECK_MSG(!(cond),msg))
|
||||
|
||||
#define DLOG(what) \
|
||||
((void)( Debug::SkipNext() || \
|
||||
( Debug::LogBegin(__FILE__) << what ).LogDone() ))
|
||||
|
||||
#define DLOG_DESCR(descr) \
|
||||
static Debug::LogDescription _LogDescr_FILE(__FILE__,descr);
|
||||
|
||||
#define DLOG_GROUP(group,what) \
|
||||
((void)( Debug::SkipNext() || \
|
||||
( Debug::LogBegin(#group) << what ).LogDone() ))
|
||||
|
||||
#define DLOG_GROUP_DESCR(group,descr) \
|
||||
static Debug::LogDescription(#group,descr) _LogDescr_Grp_##group
|
||||
|
||||
#define DCRASH(msg) \
|
||||
(Debug::SkipNext() || (Debug::CrashBegin(__FILE__,__LINE__) << msg).CrashDone(false))
|
||||
|
||||
#define DCRASH_RELEASE(msg) \
|
||||
(Debug::SkipNext(),(Debug::CrashBegin(__FILE__,__LINE__) << msg).CrashDone(true))
|
||||
|
||||
#define DFAIL() \
|
||||
Debug::AssertBegin(__FILE__,__LINE__,NULL).AssertDone()
|
||||
|
||||
#define D_ISLOG() \
|
||||
Debug::IsLogEnabled(__FILE__)
|
||||
|
||||
#define D_ISLOG_GROUP(group) \
|
||||
Debug::IsLogEnabled(#group)
|
||||
|
||||
#else
|
||||
|
||||
#define DASSERT(expr) ((void)0)
|
||||
#define DASSERT_MSG(expr,msg) ((void)0)
|
||||
#define DCHECK(expr) (expr)
|
||||
#define DCHECK_MSG(expr,msg) (expr)
|
||||
#define DFAIL_IF(cond) if (cond)
|
||||
#define DFAIL_IF_MSG(cond,msg) if (cond)
|
||||
#define DLOG(what) ((void)0)
|
||||
#define DLOG_DESCR(descr)
|
||||
#define DLOG_GROUP(group,what) ((void)0)
|
||||
#define DLOG_GROUP_DESCR(g,d)
|
||||
#define DCRASH(msg) ((void)0)
|
||||
#define DCRASH_RELEASE(msg) (Debug::SkipNext(),(Debug::CrashBegin(NULL,0) << msg).CrashDone(true))
|
||||
#define DFAIL() ((void)0)
|
||||
#define D_ISLOG() false
|
||||
#define D_ISLOG_GROUP(group) false
|
||||
|
||||
#endif
|
||||
|
||||
// put these helper templates in a namespace...
|
||||
namespace _Debug
|
||||
{
|
||||
template<bool> struct StaticAssertionFailed;
|
||||
template<> struct StaticAssertionFailed<true> {};
|
||||
template<int x> struct StaticAssertionTest {};
|
||||
|
||||
#define DCTASSERT(expr) typedef ::_Debug::StaticAssertionTest< \
|
||||
sizeof(::_Debug::StaticAssertionFailed< (bool)(expr) >) \
|
||||
> DebugStaticAssertTypedef__;
|
||||
};
|
||||
|
||||
// These are stolen from the WW3D Debug file. REALLY useful. :-)
|
||||
#define STRING_IT(a) #a
|
||||
#define TOKEN_IT(a) STRING_IT(,##a)
|
||||
|
||||
/**
|
||||
The macro MESSAGE allows user to put:
|
||||
\code
|
||||
#pragma MESSAGE("Hello world")
|
||||
\endcode
|
||||
anywhere in a source file. The message:
|
||||
\code
|
||||
sourcefname.cpp (123) : Hello world
|
||||
\endcode
|
||||
would be printed if put in sourcefname.cpp on line 123 in compile window like an error.
|
||||
You can then use next/prev error hot keys to see where comment is. It is not an error and
|
||||
will be printed everytime it is compiled. Very useful to put comments in code that cannot
|
||||
be forgotten.
|
||||
*/
|
||||
#define MESSAGE(a) message (__FILE__ "(" TOKEN_IT(__LINE__) ") : " a)
|
||||
|
||||
#endif // DEBUG_MACRO_H
|
36
GeneralsMD/Code/Libraries/Source/debug/debug_purecall.cpp
Normal file
36
GeneralsMD/Code/Libraries/Source/debug/debug_purecall.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_purecall.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Replacement for MSVCRT _purecall
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
||||
|
||||
// Pure virtual function called
|
||||
int __cdecl _purecall(void)
|
||||
{
|
||||
DCRASH_RELEASE("Pure virtual function called.");
|
||||
return 0;
|
||||
}
|
391
GeneralsMD/Code/Libraries/Source/debug/debug_stack.cpp
Normal file
391
GeneralsMD/Code/Libraries/Source/debug/debug_stack.cpp
Normal file
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_stack.cpp $
|
||||
// $Author: KMorness $
|
||||
// $Revision: #2 $
|
||||
// $DateTime: 2005/01/19 15:02:33 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Stack walker
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "_pch.h"
|
||||
#include "dbghelp.h"
|
||||
|
||||
// Definitions to allow run-time linking to the dbghelp.dll functions.
|
||||
|
||||
#define DBGHELP(name,ret,par) typedef ret (WINAPI *name##Type) par;
|
||||
#include "debug_stack.inl"
|
||||
#undef DBGHELP
|
||||
|
||||
#define DBGHELP(name,ret,par) name##Type _##name;
|
||||
static union
|
||||
{
|
||||
struct
|
||||
{
|
||||
#include "debug_stack.inl"
|
||||
};
|
||||
unsigned funcPtr[1];
|
||||
} gDbg;
|
||||
#undef DBGHELP
|
||||
|
||||
#define DBGHELP(name,ret,par) #name,
|
||||
static char const *DebughelpFunctionNames[] =
|
||||
{
|
||||
#include "debug_stack.inl"
|
||||
NULL
|
||||
};
|
||||
#undef DBGHELP
|
||||
|
||||
// local dbghelp.dll module handle
|
||||
static HMODULE g_dbghelp;
|
||||
|
||||
// local flag that is true if we're using an old dbghelp.dll version
|
||||
static bool g_oldDbghelp;
|
||||
|
||||
static void InitDbghelp(void)
|
||||
{
|
||||
// already called?
|
||||
if (g_dbghelp)
|
||||
return;
|
||||
|
||||
// firstly check for dbghelp.dll in the EXE directory
|
||||
char dbgHelpPath[256];
|
||||
if (GetModuleFileName(NULL,dbgHelpPath,sizeof(dbgHelpPath)))
|
||||
{
|
||||
char *slash=strrchr(dbgHelpPath,'\\');
|
||||
if (slash)
|
||||
{
|
||||
strcpy(slash+1,"DBGHELP.DLL");
|
||||
g_dbghelp=::LoadLibrary(dbgHelpPath);
|
||||
}
|
||||
}
|
||||
if (!g_dbghelp)
|
||||
// load any version we can
|
||||
g_dbghelp=::LoadLibrary("DBGHELP.DLL");
|
||||
|
||||
if (!g_dbghelp)
|
||||
return;
|
||||
|
||||
// Get function addresses
|
||||
unsigned *funcptr=gDbg.funcPtr;
|
||||
for (unsigned k=0;DebughelpFunctionNames[k];++k,++funcptr)
|
||||
{
|
||||
*funcptr=(unsigned)GetProcAddress(g_dbghelp,DebughelpFunctionNames[k]);
|
||||
if (!*funcptr)
|
||||
break;
|
||||
}
|
||||
if (DebughelpFunctionNames[k])
|
||||
{
|
||||
// not all functions found -> clear them all
|
||||
while (funcptr!=gDbg.funcPtr)
|
||||
*--funcptr=NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set options
|
||||
gDbg._SymSetOptions(gDbg._SymGetOptions()|SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES);
|
||||
|
||||
// Init module
|
||||
gDbg._SymInitialize((HANDLE)GetCurrentProcessId(),NULL,TRUE);
|
||||
|
||||
// Check: are we using a newer version of dbghelp.dll?
|
||||
// (older versions have some serious issues.. err... bugs)
|
||||
if (!GetProcAddress(g_dbghelp,"SymEnumSymbolsForAddr"))
|
||||
g_oldDbghelp=true;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DebugStackwalk::Signature::Signature(const Signature &src)
|
||||
{
|
||||
*this=src;
|
||||
}
|
||||
|
||||
DebugStackwalk::Signature& DebugStackwalk::Signature::operator=(const Signature& src)
|
||||
{
|
||||
if (&src!=this)
|
||||
{
|
||||
m_numAddr=src.m_numAddr;
|
||||
memcpy(m_addr,src.m_addr,m_numAddr*sizeof(*m_addr));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned DebugStackwalk::Signature::GetAddress(int n) const
|
||||
{
|
||||
DFAIL_IF_MSG(n<0||n>=MAX_ADDR,n << "/" << MAX_ADDR) return 0;
|
||||
return m_addr[n];
|
||||
}
|
||||
|
||||
void DebugStackwalk::Signature::GetSymbol(unsigned addr, char *buf, unsigned bufSize)
|
||||
{
|
||||
DFAIL_IF(!buf) return;
|
||||
DFAIL_IF(bufSize<64||bufSize>=0x80000000) return;
|
||||
|
||||
InitDbghelp();
|
||||
|
||||
char *bufEnd=buf+bufSize;
|
||||
*buf=0;
|
||||
buf+=wsprintf(buf,"%08x",addr);
|
||||
|
||||
// determine module
|
||||
unsigned modBase=gDbg._SymGetModuleBase((HANDLE)GetCurrentProcessId(),addr);
|
||||
if (!modBase)
|
||||
{
|
||||
strcpy(buf," (unknown module)");
|
||||
return;
|
||||
}
|
||||
|
||||
// illegal code ptr?
|
||||
if (IsBadReadPtr((void *)addr,4)||IsBadCodePtr((FARPROC)addr))
|
||||
{
|
||||
strcpy(buf," (invalid code addr)");
|
||||
return;
|
||||
}
|
||||
|
||||
char symbolBuffer[512];
|
||||
GetModuleFileName((HMODULE)modBase,symbolBuffer,sizeof(symbolBuffer));
|
||||
|
||||
char *p=strrchr(symbolBuffer,'\\'); // use filename only, strip off path
|
||||
p=p?p+1:symbolBuffer;
|
||||
*buf++=' ';
|
||||
strcpy(buf,p);
|
||||
buf+=strlen(buf);
|
||||
if (bufEnd-buf<32)
|
||||
return;
|
||||
buf+=wsprintf(buf,"+0x%x",addr-modBase);
|
||||
|
||||
// determine symbol
|
||||
PIMAGEHLP_SYMBOL symPtr=(PIMAGEHLP_SYMBOL)symbolBuffer;
|
||||
memset(symPtr,0,sizeof(symbolBuffer));
|
||||
symPtr->SizeOfStruct=sizeof(IMAGEHLP_SYMBOL);
|
||||
symPtr->MaxNameLength=sizeof(symbolBuffer)-sizeof(IMAGEHLP_SYMBOL);
|
||||
DWORD displacement;
|
||||
if (!gDbg._SymGetSymFromAddr((HANDLE)GetCurrentProcessId(),addr,&displacement,symPtr))
|
||||
return;
|
||||
if ((unsigned int)(bufEnd-buf)<strlen(symPtr->Name)+16)
|
||||
return;
|
||||
buf+=wsprintf(buf,", %s+0x%x",symPtr->Name,displacement);
|
||||
|
||||
// and line number
|
||||
IMAGEHLP_LINE line;
|
||||
memset(&line,0,sizeof(line));
|
||||
line.SizeOfStruct=sizeof(line);
|
||||
if (!gDbg._SymGetLineFromAddr((HANDLE)GetCurrentProcessId(),addr,&displacement,&line))
|
||||
return;
|
||||
|
||||
p=strrchr(line.FileName,'\\'); // use filename only, strip off path
|
||||
p=p?p+1:line.FileName;
|
||||
|
||||
if ((unsigned int)(bufEnd-buf)<strlen(p)+16)
|
||||
return;
|
||||
buf+=wsprintf(buf,", %s:%i+0x%x",p,line.LineNumber,displacement);
|
||||
}
|
||||
|
||||
void DebugStackwalk::Signature::GetSymbol(unsigned addr,
|
||||
char *bufMod, unsigned sizeMod, unsigned *relMod,
|
||||
char *bufSym, unsigned sizeSym, unsigned *relSym,
|
||||
char *bufFile, unsigned sizeFile, unsigned *linePtr, unsigned *relLine)
|
||||
{
|
||||
InitDbghelp();
|
||||
|
||||
if (bufMod) *bufMod=0;
|
||||
if (relMod) *relMod=0;
|
||||
if (bufSym) *bufSym=0;
|
||||
if (relSym) *relSym=0;
|
||||
|
||||
if (bufFile) *bufFile=0;
|
||||
if (linePtr) *linePtr=0;
|
||||
if (relLine) *relLine=0;
|
||||
|
||||
DFAIL_IF(bufMod&&sizeMod<16) return;
|
||||
DFAIL_IF(bufSym&&sizeSym<16) return;
|
||||
DFAIL_IF(bufFile&&sizeFile<16) return;
|
||||
|
||||
// determine module
|
||||
unsigned modBase=gDbg._SymGetModuleBase((HANDLE)GetCurrentProcessId(),addr);
|
||||
if (!modBase)
|
||||
{
|
||||
if (bufMod)
|
||||
strcpy(bufMod,"(unknown mod)");
|
||||
if (bufSym)
|
||||
strcpy(bufSym,"(unknown)");
|
||||
return;
|
||||
}
|
||||
|
||||
// illegal code ptr?
|
||||
if (IsBadReadPtr((void *)addr,4)||IsBadCodePtr((FARPROC)addr))
|
||||
{
|
||||
if (bufMod)
|
||||
strcpy(bufMod,"(inv code addr)");
|
||||
if (bufSym)
|
||||
strcpy(bufSym,"(unknown)");
|
||||
return;
|
||||
}
|
||||
|
||||
char symbolBuffer[512];
|
||||
if (bufMod)
|
||||
{
|
||||
GetModuleFileName((HMODULE)modBase,symbolBuffer,sizeof(symbolBuffer));
|
||||
|
||||
char *p=strrchr(symbolBuffer,'\\'); // use filename only, strip off path
|
||||
p=p?p+1:symbolBuffer;
|
||||
strncpy(bufMod,p,sizeMod);
|
||||
bufMod[sizeMod-1]=0;
|
||||
}
|
||||
if (relMod)
|
||||
*relMod=addr-modBase;
|
||||
|
||||
// determine symbol
|
||||
if (bufSym)
|
||||
{
|
||||
PIMAGEHLP_SYMBOL symPtr=(PIMAGEHLP_SYMBOL)symbolBuffer;
|
||||
memset(symPtr,0,sizeof(symbolBuffer));
|
||||
symPtr->SizeOfStruct=sizeof(IMAGEHLP_SYMBOL);
|
||||
symPtr->MaxNameLength=sizeof(symbolBuffer)-sizeof(IMAGEHLP_SYMBOL);
|
||||
DWORD displacement;
|
||||
if (gDbg._SymGetSymFromAddr((HANDLE)GetCurrentProcessId(),addr,&displacement,symPtr))
|
||||
{
|
||||
strncpy(bufSym,symPtr->Name,sizeSym);
|
||||
bufSym[sizeSym-1]=0;
|
||||
if (relSym)
|
||||
*relSym=displacement;
|
||||
}
|
||||
else
|
||||
strcpy(bufSym,"(unknown)");
|
||||
}
|
||||
|
||||
// and line number
|
||||
if (bufFile)
|
||||
{
|
||||
IMAGEHLP_LINE line;
|
||||
memset(&line,0,sizeof(line));
|
||||
line.SizeOfStruct=sizeof(line);
|
||||
DWORD displacement;
|
||||
if (!gDbg._SymGetLineFromAddr((HANDLE)GetCurrentProcessId(),addr,&displacement,&line))
|
||||
strcpy(bufFile,"(unknown)");
|
||||
else
|
||||
{
|
||||
char *p=strrchr(line.FileName,'\\'); // use filename only, strip off path
|
||||
p=p?p+1:line.FileName;
|
||||
strncpy(bufFile,p,sizeFile);
|
||||
bufFile[sizeFile-1]=0;
|
||||
if (linePtr)
|
||||
*linePtr=line.LineNumber;
|
||||
if (relLine)
|
||||
*relLine=displacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug& operator<<(Debug &dbg, const DebugStackwalk::Signature &sig)
|
||||
{
|
||||
dbg << sig.Size() << " addresses:\n";
|
||||
|
||||
for (unsigned k=0;k<sig.Size();k++)
|
||||
{
|
||||
char buf[512];
|
||||
sig.GetSymbol(sig.GetAddress(k),buf,sizeof(buf));
|
||||
dbg << buf << "\n";
|
||||
}
|
||||
|
||||
return dbg;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DebugStackwalk::DebugStackwalk(void)
|
||||
{
|
||||
// it doesn't harm to do this here
|
||||
InitDbghelp();
|
||||
}
|
||||
|
||||
DebugStackwalk::~DebugStackwalk()
|
||||
{
|
||||
}
|
||||
|
||||
void *DebugStackwalk::GetDbghelpHandle(void)
|
||||
{
|
||||
return g_dbghelp;
|
||||
}
|
||||
|
||||
bool DebugStackwalk::IsOldDbghelp(void)
|
||||
{
|
||||
return g_oldDbghelp;
|
||||
}
|
||||
|
||||
int DebugStackwalk::StackWalk(Signature &sig, struct _CONTEXT *ctx)
|
||||
{
|
||||
InitDbghelp();
|
||||
|
||||
sig.m_numAddr=0;
|
||||
|
||||
// bail out if no stack walk available
|
||||
if (!gDbg._StackWalk)
|
||||
return 0;
|
||||
|
||||
// Set up the stack frame structure for the start point of the stack walk (i.e. here).
|
||||
STACKFRAME stackFrame;
|
||||
memset(&stackFrame,0,sizeof(stackFrame));
|
||||
|
||||
stackFrame.AddrPC.Mode = AddrModeFlat;
|
||||
stackFrame.AddrStack.Mode = AddrModeFlat;
|
||||
stackFrame.AddrFrame.Mode = AddrModeFlat;
|
||||
|
||||
// Use the context struct if it was provided.
|
||||
if (ctx)
|
||||
{
|
||||
stackFrame.AddrPC.Offset = ctx->Eip;
|
||||
stackFrame.AddrStack.Offset = ctx->Esp;
|
||||
stackFrame.AddrFrame.Offset = ctx->Ebp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// walk stack back using current call chain
|
||||
unsigned long reg_eip, reg_ebp, reg_esp;
|
||||
__asm
|
||||
{
|
||||
here:
|
||||
lea eax,here
|
||||
mov reg_eip,eax
|
||||
mov reg_ebp,ebp
|
||||
mov reg_esp,esp
|
||||
};
|
||||
stackFrame.AddrPC.Offset = reg_eip;
|
||||
stackFrame.AddrStack.Offset = reg_esp;
|
||||
stackFrame.AddrFrame.Offset = reg_ebp;
|
||||
}
|
||||
|
||||
// Walk the stack by the requested number of return address iterations.
|
||||
bool skipFirst=!ctx;
|
||||
while (sig.m_numAddr<Signature::MAX_ADDR&&
|
||||
gDbg._StackWalk(IMAGE_FILE_MACHINE_I386,GetCurrentProcess(),GetCurrentThread(),
|
||||
&stackFrame,NULL,NULL,gDbg._SymFunctionTableAccess,gDbg._SymGetModuleBase,NULL))
|
||||
{
|
||||
if (skipFirst)
|
||||
skipFirst=false;
|
||||
else
|
||||
sig.m_addr[sig.m_numAddr++]=stackFrame.AddrPC.Offset;
|
||||
}
|
||||
|
||||
return sig.m_numAddr;
|
||||
}
|
172
GeneralsMD/Code/Libraries/Source/debug/debug_stack.h
Normal file
172
GeneralsMD/Code/Libraries/Source/debug/debug_stack.h
Normal file
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_stack.h $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Stack walker
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
#ifndef DEBUG_STACK_H // Include guard
|
||||
#define DEBUG_STACK_H
|
||||
|
||||
/// \brief stack walker class (singleton)
|
||||
class DebugStackwalk
|
||||
{
|
||||
friend class Debug;
|
||||
|
||||
DebugStackwalk(const DebugStackwalk&);
|
||||
DebugStackwalk& operator=(DebugStackwalk&);
|
||||
|
||||
// private so that only Debug can create and destroy us
|
||||
DebugStackwalk(void);
|
||||
~DebugStackwalk();
|
||||
|
||||
public:
|
||||
|
||||
/// \brief a stack trace signature
|
||||
class Signature
|
||||
{
|
||||
// makes life easier :)
|
||||
friend class DebugStackwalk;
|
||||
|
||||
/// max # of possible addresses
|
||||
enum { MAX_ADDR = 256 };
|
||||
|
||||
/// number of addresses
|
||||
unsigned m_numAddr;
|
||||
|
||||
/// addresses
|
||||
unsigned m_addr[MAX_ADDR];
|
||||
|
||||
public:
|
||||
explicit Signature(void): m_numAddr(0) {}
|
||||
Signature(const Signature &src);
|
||||
Signature& operator=(const Signature& src);
|
||||
|
||||
/**
|
||||
\brief Determine the number of addresses in this signature.
|
||||
|
||||
\return number of addresses in this signature
|
||||
*/
|
||||
unsigned Size(void) const { return m_numAddr; }
|
||||
|
||||
/**
|
||||
\brief Get a single address from the signature.
|
||||
|
||||
The address at index 0 is always on top of the stack.
|
||||
|
||||
\param n index, 0..Size()-1
|
||||
\return signature address
|
||||
*/
|
||||
unsigned GetAddress(int n) const;
|
||||
|
||||
/**
|
||||
\brief Strong ordering operator.
|
||||
|
||||
Signatures are ordered by looking at the bottom of the stack
|
||||
first. Implemented inline so that STL algorithms using this
|
||||
operator can be compiled more efficiently.
|
||||
*/
|
||||
bool operator<(const Signature &other) const
|
||||
{
|
||||
unsigned m=m_numAddr<other.m_numAddr?m_numAddr:other.m_numAddr;
|
||||
for (unsigned k=0;k<m;k++)
|
||||
{
|
||||
if (m_addr[m_numAddr-k-1]<other.m_addr[other.m_numAddr-k-1])
|
||||
return true;
|
||||
if (m_addr[m_numAddr-k-1]>other.m_addr[other.m_numAddr-k-1])
|
||||
return false;
|
||||
}
|
||||
return m_numAddr<other.m_numAddr;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Determines symbol for given address.
|
||||
|
||||
The data is returned in the form
|
||||
\<addr\> \<module\>+NN, \<sym\>+NN, \<file\>:\<line\>+NN
|
||||
|
||||
\param addr function address
|
||||
\param buf return buffer
|
||||
\param bufSize size of return buffer, minimum is 64 bytes (256 recommended)
|
||||
*/
|
||||
static void GetSymbol(unsigned addr, char *buf, unsigned bufSize);
|
||||
|
||||
/**
|
||||
\brief Determines symbol for given address.
|
||||
|
||||
\param addr function address
|
||||
\param bufMod module buffer, may be NULL
|
||||
\param sizeMod size of buffer, including NUL, minimum 16 if given
|
||||
\param relMod relative address within module, may be NULL
|
||||
\param bufSym symbol buffer, may be NULL
|
||||
\param sizeSym size of buffer, including NUL
|
||||
\param relSym relative address within symbol, may be NULL
|
||||
\param bufFile file name buffer, may be NULL
|
||||
\param sizeFile size of buffer, including NUL
|
||||
\param line line number, may be NULL
|
||||
\param relLine relative address within line, may be NULL
|
||||
*/
|
||||
static void GetSymbol(unsigned addr,
|
||||
char *bufMod, unsigned sizeMod, unsigned *relMod,
|
||||
char *bufSym, unsigned sizeSym, unsigned *relSym,
|
||||
char *bufFile, unsigned sizeFile, unsigned *line, unsigned *relLine);
|
||||
};
|
||||
|
||||
/** \internal
|
||||
\brief Returns dbghelp.dll DLL handle.
|
||||
|
||||
\return dbghelp.dll DLL handle
|
||||
*/
|
||||
static void *GetDbghelpHandle(void);
|
||||
|
||||
/** \internal
|
||||
\brief Checks if dbghelp.dll version is old.
|
||||
|
||||
\return true if old version, false if not
|
||||
*/
|
||||
static bool IsOldDbghelp(void);
|
||||
|
||||
/**
|
||||
\brief Walks the stack from the given address.
|
||||
|
||||
\param sig stack signature to return
|
||||
\param ctx processor context, if NULL then use current address
|
||||
\return number of addresses found
|
||||
*/
|
||||
static int StackWalk(Signature &sig, struct _CONTEXT *ctx=0);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Dumps a complete signature with symbols.
|
||||
|
||||
\param dbg debug instance
|
||||
\param sig signature
|
||||
\return debug instance
|
||||
*/
|
||||
Debug& operator<<(Debug &dbg, const DebugStackwalk::Signature &sig);
|
||||
|
||||
#endif // DEBUG_STACK_H
|
63
GeneralsMD/Code/Libraries/Source/debug/debug_stack.inl
Normal file
63
GeneralsMD/Code/Libraries/Source/debug/debug_stack.inl
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Used for dynamically linking to dbghelp.dll functions.
|
||||
|
||||
// keep this always as first entry
|
||||
DBGHELP(SymInitialize,
|
||||
BOOL,
|
||||
(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess))
|
||||
|
||||
DBGHELP(SymGetOptions,
|
||||
DWORD,
|
||||
(void))
|
||||
|
||||
DBGHELP(SymSetOptions,
|
||||
DWORD,
|
||||
(DWORD SymOptions))
|
||||
|
||||
DBGHELP(StackWalk,
|
||||
BOOL,
|
||||
(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME StackFrame,
|
||||
LPVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
|
||||
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
|
||||
PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
|
||||
PTRANSLATE_ADDRESS_ROUTINE TranslateAddress))
|
||||
|
||||
DBGHELP(SymFunctionTableAccess,
|
||||
LPVOID,
|
||||
(HANDLE hProcess, DWORD AddrBase))
|
||||
|
||||
DBGHELP(SymGetModuleBase,
|
||||
DWORD,
|
||||
(HANDLE hProcess, DWORD dwAddr))
|
||||
|
||||
DBGHELP(SymGetSymFromAddr,
|
||||
BOOL,
|
||||
(HANDLE hProcess, DWORD Address, LPDWORD Displacement,
|
||||
PIMAGEHLP_SYMBOL Symbol))
|
||||
|
||||
DBGHELP(SymGetLineFromAddr,
|
||||
BOOL,
|
||||
(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement,
|
||||
PIMAGEHLP_LINE Line))
|
||||
|
||||
// keep this always as last entry
|
||||
DBGHELP(SymCleanup,
|
||||
BOOL,
|
||||
(HANDLE hProcess))
|
101
GeneralsMD/Code/Libraries/Source/debug/internal.h
Normal file
101
GeneralsMD/Code/Libraries/Source/debug/internal.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/internal.h $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Internal header
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
#ifndef INTERNAL_H // Include guard
|
||||
#define INTERNAL_H
|
||||
|
||||
// make sure we're not omitting the frame pointer
|
||||
#pragma optimize("y",off)
|
||||
|
||||
// We're doing our own little internal asserts for full debug
|
||||
// builds (until this library is proven & stable)
|
||||
#ifdef _DEBUG
|
||||
# define __ASSERT(x) do { if (!(x)) DebugInternalAssert(__FILE__,__LINE__,#x); } while (0)
|
||||
#else
|
||||
# define __ASSERT(x) do { } while(0)
|
||||
#endif
|
||||
|
||||
/** \internal
|
||||
|
||||
Internal assert function for module internal assertions.
|
||||
|
||||
\param file file name
|
||||
\param line line number
|
||||
\param expr expression which failed
|
||||
*/
|
||||
void DebugInternalAssert(const char *file, int line, const char *expr);
|
||||
|
||||
/** \internal
|
||||
|
||||
Allocate the given number of bytes from the Windows heap.
|
||||
This function performs a controlled crash on failure.
|
||||
|
||||
\param numBytes number of bytes to allocate
|
||||
\return pointer to allocated memory
|
||||
*/
|
||||
void *DebugAllocMemory(unsigned numBytes);
|
||||
|
||||
/** \internal
|
||||
|
||||
Allocates/reallocates the given memory block to the new
|
||||
given size.
|
||||
This function performs a controlled crash on failure.
|
||||
|
||||
\param oldPtr pointer to old memory block, may be NULL
|
||||
\param newSize new size of block
|
||||
\return pointer to reallocated memory
|
||||
*/
|
||||
void *DebugReAllocMemory(void *oldPtr, unsigned newSize);
|
||||
|
||||
/** \internal
|
||||
|
||||
Frees the allocated memory block.
|
||||
This function never fails.
|
||||
|
||||
\param ptr memory block to free
|
||||
*/
|
||||
void DebugFreeMemory(void *ptr);
|
||||
|
||||
/// \internal Command group: 'debug'
|
||||
class DebugCmdInterfaceDebug: public DebugCmdInterface
|
||||
{
|
||||
public:
|
||||
virtual bool Execute(class Debug& dbg, const char *cmd, CommandMode cmdmode,
|
||||
unsigned argn, const char * const * argv);
|
||||
|
||||
virtual void Delete(void)
|
||||
{
|
||||
this->~DebugCmdInterfaceDebug();
|
||||
DebugFreeMemory(this);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // INTERNAL_H
|
90
GeneralsMD/Code/Libraries/Source/debug/internal_except.h
Normal file
90
GeneralsMD/Code/Libraries/Source/debug/internal_except.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/internal_except.h $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Unhandled exception handler
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
#ifndef INTERNAL_EXCEPT_H // Include guard
|
||||
#define INTERNAL_EXCEPT_H
|
||||
|
||||
/// \internal exception handler
|
||||
class DebugExceptionhandler
|
||||
{
|
||||
DebugExceptionhandler(const DebugExceptionhandler&);
|
||||
DebugExceptionhandler& operator=(const DebugExceptionhandler&);
|
||||
|
||||
// nobody can instantiate us
|
||||
DebugExceptionhandler(void);
|
||||
|
||||
/** \internal
|
||||
|
||||
\brief Log exception location.
|
||||
|
||||
\param dbg debug instance
|
||||
\param exptr exception pointers
|
||||
*/
|
||||
static void LogExceptionLocation(Debug &dbg, struct _EXCEPTION_POINTERS *exptr);
|
||||
|
||||
/** \internal
|
||||
|
||||
\brief Log regular registers.
|
||||
|
||||
\param dbg debug instance
|
||||
\param exptr exception pointers
|
||||
*/
|
||||
static void LogRegisters(Debug &dbg, struct _EXCEPTION_POINTERS *exptr);
|
||||
|
||||
/** \internal
|
||||
|
||||
\brief Log FPU registers.
|
||||
|
||||
\param dbg debug instance
|
||||
\param exptr exception pointers
|
||||
*/
|
||||
static void LogFPURegisters(Debug &dbg, struct _EXCEPTION_POINTERS *exptr);
|
||||
|
||||
public:
|
||||
|
||||
/** \internal
|
||||
|
||||
\brief Determine exception type.
|
||||
|
||||
\param exptr exception pointers
|
||||
\param explanation exception explanation, buffer must be 512 chars
|
||||
\return exception type as string
|
||||
*/
|
||||
static const char *GetExceptionType(struct _EXCEPTION_POINTERS *exptr, char *explanation);
|
||||
|
||||
/** \internal
|
||||
|
||||
\brief System exception filter
|
||||
*/
|
||||
static long __stdcall ExceptionFilter(struct _EXCEPTION_POINTERS* pExPtrs);
|
||||
};
|
||||
|
||||
#endif // INTERNAL_EXCEPT_H
|
256
GeneralsMD/Code/Libraries/Source/debug/internal_io.h
Normal file
256
GeneralsMD/Code/Libraries/Source/debug/internal_io.h
Normal file
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/internal_io.h $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Internal header: I/O classes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
#ifndef INTERNAL_IO_H // Include guard
|
||||
#define INTERNAL_IO_H
|
||||
|
||||
/// \internal \brief con debug I/O class
|
||||
class DebugIOCon: public DebugIOInterface
|
||||
{
|
||||
/**
|
||||
true if we allocated the console, false if there has already
|
||||
been a console
|
||||
*/
|
||||
bool m_allocatedConsole;
|
||||
|
||||
/**
|
||||
internal input buffer
|
||||
*/
|
||||
char m_input[256];
|
||||
|
||||
/**
|
||||
number of bytes in input buffer
|
||||
*/
|
||||
unsigned m_inputUsed;
|
||||
|
||||
/**
|
||||
Current read position. This variable is 0 while data is
|
||||
composed into m_input and >0 while multiple Read calls are
|
||||
received.
|
||||
*/
|
||||
unsigned m_inputRead;
|
||||
|
||||
public:
|
||||
explicit DebugIOCon(void);
|
||||
virtual ~DebugIOCon();
|
||||
virtual int Read(char *buf, int maxchar);
|
||||
virtual void Write(StringType type, const char *src, const char *str);
|
||||
virtual void EmergencyFlush(void) {}
|
||||
virtual void Execute(class Debug& dbg, const char *cmd, bool structuredCmd,
|
||||
unsigned argn, const char * const * argv);
|
||||
static DebugIOInterface *Create(void);
|
||||
virtual void Delete(void);
|
||||
};
|
||||
|
||||
/// \internal \brief con flat I/O class
|
||||
class DebugIOFlat: public DebugIOInterface
|
||||
{
|
||||
/// \brief single output stream
|
||||
class OutputStream
|
||||
{
|
||||
OutputStream(const OutputStream&);
|
||||
OutputStream& operator=(const OutputStream&);
|
||||
|
||||
/// output file name (dynamically allocated)
|
||||
char *m_fileName;
|
||||
|
||||
/// output file handle (only if unlimited output buffer size)
|
||||
HANDLE m_fileHandle;
|
||||
|
||||
/// file size limited?
|
||||
bool m_limitedFileSize;
|
||||
|
||||
/// output buffer
|
||||
char *m_buffer;
|
||||
|
||||
/// number of bytes in buffer
|
||||
unsigned m_bufferUsed;
|
||||
|
||||
/// size of buffer (if m_limitedFileSize then m_bufferSize==m_maxSize)
|
||||
unsigned m_bufferSize;
|
||||
|
||||
/// position of next free char in ring buffer (used if m_limitedFileSize)
|
||||
unsigned m_nextChar;
|
||||
|
||||
// these are private so that we are forced to use Create/Destroy
|
||||
OutputStream(const char *filename, unsigned maxSize);
|
||||
~OutputStream();
|
||||
|
||||
/**
|
||||
\brief Writes some data to output stream.
|
||||
|
||||
\param src string to write
|
||||
\param len number of bytes to write
|
||||
*/
|
||||
void InternalWrite(const char *src, unsigned len);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
\brief Creates a new output stream instance.
|
||||
|
||||
\param filename name of output file (will be overwritten if it exists)
|
||||
\param maxSize maximum size of output file, unlimited if 0
|
||||
*/
|
||||
static OutputStream *Create(const char *filename, unsigned maxSize);
|
||||
|
||||
/**
|
||||
\brief Destroys this object.
|
||||
|
||||
If a path is given the file is copied to that path as well. If there
|
||||
is already a file with that name in the destination directory the
|
||||
current file is copied under a new unique name.
|
||||
|
||||
\param path optional path to a destination directory
|
||||
*/
|
||||
void Delete(const char *path=NULL);
|
||||
|
||||
/**
|
||||
\brief Determines name of output stream.
|
||||
|
||||
\return name of output stream
|
||||
*/
|
||||
const char *GetFilename(void) { return m_fileName; }
|
||||
|
||||
/**
|
||||
\brief Writes data to the output stream.
|
||||
|
||||
\param src NUL delimited string to write
|
||||
*/
|
||||
void Write(const char *src);
|
||||
|
||||
/**
|
||||
\brief Flushes all buffered data.
|
||||
*/
|
||||
void Flush(void);
|
||||
};
|
||||
|
||||
/// \brief a single split structure
|
||||
struct SplitListEntry
|
||||
{
|
||||
/// next split
|
||||
SplitListEntry *next;
|
||||
|
||||
/// for which string types?
|
||||
unsigned stringTypes;
|
||||
|
||||
/// for which items?
|
||||
char items[256];
|
||||
|
||||
/// split name
|
||||
char name[256];
|
||||
|
||||
/// into which stream? (note: pointer not owned by this!)
|
||||
OutputStream *stream;
|
||||
};
|
||||
|
||||
/// \brief List of output streams
|
||||
struct StreamListEntry
|
||||
{
|
||||
/// next entry
|
||||
StreamListEntry *next;
|
||||
|
||||
/// which stream?
|
||||
OutputStream *stream;
|
||||
};
|
||||
|
||||
/// first split
|
||||
SplitListEntry *m_firstSplit;
|
||||
|
||||
/// end of split list pointer
|
||||
SplitListEntry **m_lastSplitPtr;
|
||||
|
||||
/// first output stream (first is always the default output stream)
|
||||
StreamListEntry *m_firstStream;
|
||||
|
||||
/// end of stream list pointer
|
||||
StreamListEntry **m_lastStreamPtr;
|
||||
|
||||
/// base filename
|
||||
char m_baseFilename[256];
|
||||
|
||||
/// copy location
|
||||
char m_copyDir[256];
|
||||
|
||||
/**
|
||||
\brief Expands a magic filename into a real filename.
|
||||
|
||||
\param src magic filename or real filename
|
||||
\param splitName split name, NULL for default stream
|
||||
\param buf output buffer, must have a size of at least 256 char's
|
||||
*/
|
||||
static void ExpandMagic(const char *src, const char *splitName, char *buf);
|
||||
|
||||
public:
|
||||
explicit DebugIOFlat(void);
|
||||
virtual ~DebugIOFlat();
|
||||
virtual int Read(char *buf, int maxchar) { return 0; }
|
||||
virtual void Write(StringType type, const char *src, const char *str);
|
||||
virtual void EmergencyFlush(void);
|
||||
virtual void Execute(class Debug& dbg, const char *cmd, bool structuredCmd,
|
||||
unsigned argn, const char * const * argv);
|
||||
static DebugIOInterface *Create(void);
|
||||
virtual void Delete(void);
|
||||
};
|
||||
|
||||
/// \internal \brief net debug I/O class
|
||||
class DebugIONet: public DebugIOInterface
|
||||
{
|
||||
/// our pipe handle
|
||||
HANDLE m_pipe;
|
||||
|
||||
public:
|
||||
explicit DebugIONet(void);
|
||||
virtual ~DebugIONet();
|
||||
virtual int Read(char *buf, int maxchar);
|
||||
virtual void Write(StringType type, const char *src, const char *str);
|
||||
virtual void EmergencyFlush(void);
|
||||
virtual void Execute(class Debug& dbg, const char *cmd, bool structuredCmd,
|
||||
unsigned argn, const char * const * argv);
|
||||
static DebugIOInterface *Create(void);
|
||||
virtual void Delete(void);
|
||||
};
|
||||
|
||||
/// \internal \brief ods debug I/O class
|
||||
class DebugIOOds: public DebugIOInterface
|
||||
{
|
||||
public:
|
||||
explicit DebugIOOds(void) {}
|
||||
virtual int Read(char *buf, int maxchar) { return 0; }
|
||||
virtual void Write(StringType type, const char *src, const char *str);
|
||||
virtual void EmergencyFlush(void) {}
|
||||
virtual void Execute(class Debug& dbg, const char *cmd, bool structuredCmd,
|
||||
unsigned argn, const char * const * argv) {}
|
||||
static DebugIOInterface *Create(void);
|
||||
virtual void Delete(void);
|
||||
};
|
||||
|
||||
#endif // INTERNAL_IO_H
|
328
GeneralsMD/Code/Libraries/Source/debug/netserv/netserv.cpp
Normal file
328
GeneralsMD/Code/Libraries/Source/debug/netserv/netserv.cpp
Normal file
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/netserv/netserv.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Simple console based server for NET I/O connections
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#define STRICT
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <malloc.h>
|
||||
|
||||
// Note: This implementation is quick'n'ugly. I've developed this
|
||||
// program basically just for testing the net I/O class.
|
||||
|
||||
static char m_input[256];
|
||||
static unsigned m_inputUsed;
|
||||
|
||||
static void InitConsole(void)
|
||||
{
|
||||
AllocConsole();
|
||||
|
||||
HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
|
||||
SetConsoleMode(h,0);
|
||||
|
||||
// make screen buffer same size as currently displayed area
|
||||
// (prevents that our input line gets scrolled out of view)
|
||||
h=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
GetConsoleScreenBufferInfo(h,&info);
|
||||
|
||||
COORD newSize;
|
||||
newSize.X=info.srWindow.Right+1;
|
||||
newSize.Y=info.srWindow.Bottom+1;
|
||||
SetConsoleScreenBufferSize(h,newSize);
|
||||
|
||||
// hide cursor
|
||||
CONSOLE_CURSOR_INFO ci;
|
||||
ci.dwSize=1;
|
||||
ci.bVisible=FALSE;
|
||||
SetConsoleCursorInfo(h,&ci);
|
||||
}
|
||||
|
||||
static char *InputConsole(void)
|
||||
{
|
||||
// update our input buffer
|
||||
HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
|
||||
bool returnChars=false;
|
||||
for (;;)
|
||||
{
|
||||
DWORD dwRecords;
|
||||
if (!GetNumberOfConsoleInputEvents(h,&dwRecords))
|
||||
break;
|
||||
if (!dwRecords)
|
||||
break;
|
||||
|
||||
INPUT_RECORD record;
|
||||
ReadConsoleInput(h,&record,1,&dwRecords);
|
||||
if (record.EventType!=KEY_EVENT)
|
||||
continue;
|
||||
|
||||
KEY_EVENT_RECORD &key=record.Event.KeyEvent;
|
||||
if (!key.bKeyDown||!key.uChar.AsciiChar)
|
||||
continue;
|
||||
|
||||
if (key.uChar.AsciiChar=='\r'||
|
||||
key.uChar.AsciiChar=='\n')
|
||||
{
|
||||
m_input[m_inputUsed++]='\n';
|
||||
returnChars=true;
|
||||
break;
|
||||
}
|
||||
|
||||
/// @todo_opt if somebody wants this can be improved by adding support for cursor keys, history, etc
|
||||
|
||||
if (key.uChar.AsciiChar=='\b')
|
||||
{
|
||||
if (m_inputUsed)
|
||||
m_inputUsed--;
|
||||
}
|
||||
else if (((unsigned char)key.uChar.AsciiChar)>=' ')
|
||||
{
|
||||
if (m_inputUsed<sizeof(m_input)-1)
|
||||
m_input[m_inputUsed++]=key.uChar.AsciiChar;
|
||||
}
|
||||
}
|
||||
|
||||
// update screen
|
||||
h=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
GetConsoleScreenBufferInfo(h,&info);
|
||||
CHAR_INFO ci[sizeof(m_input)+1];
|
||||
for (unsigned k=0;k<=sizeof(m_input);k++)
|
||||
{
|
||||
ci[k].Char.AsciiChar=k<m_inputUsed?m_input[k]:' ';
|
||||
ci[k].Attributes=BACKGROUND_BLUE|FOREGROUND_BLUE|FOREGROUND_GREEN
|
||||
|FOREGROUND_RED|FOREGROUND_INTENSITY;
|
||||
}
|
||||
|
||||
// fake another cursor
|
||||
if (GetTickCount()&512)
|
||||
ci[m_inputUsed].Attributes=BACKGROUND_BLUE|BACKGROUND_GREEN
|
||||
|BACKGROUND_RED|BACKGROUND_INTENSITY|FOREGROUND_BLUE;
|
||||
|
||||
COORD srcSize,srcCoord;
|
||||
srcSize.X=sizeof(m_input); srcSize.Y=1;
|
||||
srcCoord.X=srcCoord.Y=0;
|
||||
|
||||
SMALL_RECT r;
|
||||
r.Left=r.Top=r.Bottom=0; r.Right=info.dwSize.X-1;
|
||||
WriteConsoleOutput(h,ci+(m_inputUsed<=info.dwSize.X?0:m_inputUsed-info.dwSize.X),
|
||||
srcSize,srcCoord,&r);
|
||||
|
||||
// return data now?
|
||||
if (returnChars&&m_inputUsed>1)
|
||||
{
|
||||
m_input[--m_inputUsed]=0;
|
||||
m_inputUsed=0;
|
||||
return m_input;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
class Pipe
|
||||
{
|
||||
Pipe(const Pipe&);
|
||||
Pipe& operator=(const Pipe&);
|
||||
|
||||
HANDLE m_pipe;
|
||||
bool m_connected;
|
||||
int m_state;
|
||||
int m_stringType;
|
||||
int m_len;
|
||||
char *m_src;
|
||||
char *m_str;
|
||||
|
||||
public:
|
||||
Pipe(void):
|
||||
m_pipe(INVALID_HANDLE_VALUE),
|
||||
m_src(NULL), m_str(NULL), m_stringType(0)
|
||||
{
|
||||
}
|
||||
|
||||
~Pipe()
|
||||
{
|
||||
if (m_pipe!=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DisconnectNamedPipe(m_pipe);
|
||||
CloseHandle(m_pipe);
|
||||
free(m_src);
|
||||
free(m_str);
|
||||
}
|
||||
}
|
||||
|
||||
bool Create(const char *name)
|
||||
{
|
||||
m_pipe=CreateNamedPipe(name,
|
||||
PIPE_ACCESS_DUPLEX,
|
||||
PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_NOWAIT,
|
||||
PIPE_UNLIMITED_INSTANCES,1024,1024,0,NULL);
|
||||
m_connected=false;
|
||||
return m_pipe!=INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
bool Connected(void)
|
||||
{
|
||||
if (!m_connected)
|
||||
{
|
||||
ConnectNamedPipe(m_pipe,NULL);
|
||||
if (GetLastError()==ERROR_PIPE_CONNECTED)
|
||||
{
|
||||
DWORD dwDummy;
|
||||
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),"\n<connect>\n",11,&dwDummy,NULL);
|
||||
m_connected=true;
|
||||
m_state=0;
|
||||
}
|
||||
}
|
||||
return m_connected;
|
||||
}
|
||||
|
||||
void Write(char msg)
|
||||
{
|
||||
DWORD dummy;
|
||||
if (!WriteFile(m_pipe,&msg,1,&dummy,NULL)||!dummy)
|
||||
{
|
||||
char sp[30];
|
||||
wsprintf(sp,"%c:%i/%i\n",msg,dummy,GetLastError());
|
||||
|
||||
DWORD dwDummy;
|
||||
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),sp,strlen(sp),&dwDummy,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
const char *Read(void)
|
||||
{
|
||||
DWORD read;
|
||||
switch(m_state)
|
||||
{
|
||||
case 0:
|
||||
if (!ReadFile(m_pipe,&m_stringType,1,&read,NULL))
|
||||
break;
|
||||
if (read==1)
|
||||
m_state++;
|
||||
return NULL;
|
||||
case 1:
|
||||
case 3:
|
||||
if (!ReadFile(m_pipe,&m_len,4,&read,NULL))
|
||||
break;
|
||||
if (read==4)
|
||||
{
|
||||
if (m_state==1)
|
||||
m_src=(char *)realloc(m_src,m_len+1);
|
||||
else
|
||||
m_str=(char *)realloc(m_str,m_len+1);
|
||||
m_state++;
|
||||
}
|
||||
return NULL;
|
||||
case 2:
|
||||
if (!ReadFile(m_pipe,m_src,m_len,&read,NULL))
|
||||
break;
|
||||
if (read==m_len)
|
||||
{
|
||||
m_src[m_len]=0;
|
||||
m_state++;
|
||||
}
|
||||
return NULL;
|
||||
case 4:
|
||||
if (!ReadFile(m_pipe,m_str,m_len,&read,NULL))
|
||||
break;
|
||||
if (read==m_len)
|
||||
{
|
||||
m_str[m_len]=0;
|
||||
m_state=0;
|
||||
return m_str;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (GetLastError()==ERROR_BROKEN_PIPE)
|
||||
{
|
||||
DisconnectNamedPipe(m_pipe);
|
||||
|
||||
DWORD dwDummy;
|
||||
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),"\n<disconnect>\n",14,&dwDummy,NULL);
|
||||
m_connected=false;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
int CALLBACK WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
|
||||
{
|
||||
InitConsole();
|
||||
|
||||
char buf1[200],buf2[400];
|
||||
DWORD dwDummy=sizeof(buf1);
|
||||
GetComputerName(buf1,&dwDummy);
|
||||
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),buf2,
|
||||
wsprintf(buf2,"\n\nSimple debug.net Server ready. Enter 'quit' to exit.\n\nLocal machine: %s\n\n",buf1),
|
||||
&dwDummy,NULL);
|
||||
|
||||
Pipe p[10];
|
||||
for (int k=0;k<10;k++)
|
||||
if (!p[k].Create("\\\\.\\pipe\\ea_debug_v1"))
|
||||
{
|
||||
char msg[200];
|
||||
wsprintf(msg,"Can't create named pipe (Code %i).",GetLastError());
|
||||
MessageBox(NULL,msg,"Error",MB_OK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char *input=InputConsole();
|
||||
if (input)
|
||||
{
|
||||
if (!strcmp(input,"quit"))
|
||||
break;
|
||||
}
|
||||
|
||||
for (int k=0;k<10;k++)
|
||||
{
|
||||
if (!p[k].Connected())
|
||||
continue;
|
||||
|
||||
const char *msg=p[k].Read();
|
||||
if (msg)
|
||||
{
|
||||
DWORD dwDummy;
|
||||
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),msg,strlen(msg),&dwDummy,NULL);
|
||||
}
|
||||
|
||||
if (input)
|
||||
{
|
||||
for (unsigned i=0;input[i];i++)
|
||||
p[k].Write(input[i]);
|
||||
p[k].Write('\n');
|
||||
}
|
||||
}
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
93
GeneralsMD/Code/Libraries/Source/debug/netserv/netserv.dsp
Normal file
93
GeneralsMD/Code/Libraries/Source/debug/netserv/netserv.dsp
Normal file
|
@ -0,0 +1,93 @@
|
|||
# Microsoft Developer Studio Project File - Name="netserv" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||
|
||||
CFG=netserv - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "netserv.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "netserv.mak" CFG="netserv - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "netserv - Win32 Release" (based on "Win32 (x86) Application")
|
||||
!MESSAGE "netserv - Win32 Debug" (based on "Win32 (x86) Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "netserv"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "netserv - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "netserv - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "netserv - Win32 Release"
|
||||
# Name "netserv - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\netserv.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
83
GeneralsMD/Code/Libraries/Source/debug/rc_exception.inl
Normal file
83
GeneralsMD/Code/Libraries/Source/debug/rc_exception.inl
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
static unsigned char rcException[]={ // program generated, do not edit
|
||||
0x01,0x00,0xff,0xff,0x00,0x00,0x00,0x00,
|
||||
0x80,0x02,0x00,0x00,0xc2,0x0a,0xc0,0x90,
|
||||
0x09,0x00,0x00,0x00,0x00,0x00,0xdf,0x01,
|
||||
0xf5,0x00,0x00,0x00,0x00,0x00,0x45,0x00,
|
||||
0x78,0x00,0x63,0x00,0x65,0x00,0x70,0x00,
|
||||
0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,
|
||||
0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x01,
|
||||
0x4d,0x00,0x53,0x00,0x20,0x00,0x53,0x00,
|
||||
0x61,0x00,0x6e,0x00,0x73,0x00,0x20,0x00,
|
||||
0x53,0x00,0x65,0x00,0x72,0x00,0x69,0x00,
|
||||
0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x50,
|
||||
0xa6,0x01,0xe0,0x00,0x32,0x00,0x0e,0x00,
|
||||
0x01,0x00,0x00,0x00,0xff,0xff,0x80,0x00,
|
||||
0x4f,0x00,0x4b,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x81,0x00,0x02,0x50,0x07,0x00,0x07,0x00,
|
||||
0x09,0x01,0x09,0x00,0x64,0x00,0x00,0x00,
|
||||
0xff,0xff,0x82,0x00,0x45,0x00,0x78,0x00,
|
||||
0x54,0x00,0x79,0x00,0x70,0x00,0x65,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x80,0x10,0x02,0x50,
|
||||
0x07,0x00,0x13,0x00,0x09,0x01,0x1c,0x00,
|
||||
0x65,0x00,0x00,0x00,0xff,0xff,0x82,0x00,
|
||||
0x45,0x00,0x78,0x00,0x4d,0x00,0x73,0x00,
|
||||
0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x81,0x12,0x02,0x50,0x07,0x00,0x3b,0x00,
|
||||
0x09,0x01,0x13,0x00,0x66,0x00,0x00,0x00,
|
||||
0xff,0xff,0x82,0x00,0x45,0x00,0x78,0x00,
|
||||
0x41,0x00,0x64,0x00,0x64,0x00,0x72,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x50,
|
||||
0x07,0x00,0x32,0x00,0x1e,0x00,0x08,0x00,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0x82,0x00,
|
||||
0x4c,0x00,0x6f,0x00,0x63,0x00,0x61,0x00,
|
||||
0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,
|
||||
0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x02,0x50,0x07,0x00,0x67,0x00,
|
||||
0x28,0x00,0x08,0x00,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0x82,0x00,0x53,0x00,0x74,0x00,
|
||||
0x61,0x00,0x63,0x00,0x6b,0x00,0x20,0x00,
|
||||
0x74,0x00,0x72,0x00,0x61,0x00,0x63,0x00,
|
||||
0x65,0x00,0x3a,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x01,0x80,0x81,0x50,0x07,0x00,0x73,0x00,
|
||||
0xd1,0x01,0x6a,0x00,0x68,0x00,0x00,0x00,
|
||||
0x53,0x00,0x79,0x00,0x73,0x00,0x4c,0x00,
|
||||
0x69,0x00,0x73,0x00,0x74,0x00,0x56,0x00,
|
||||
0x69,0x00,0x65,0x00,0x77,0x00,0x33,0x00,
|
||||
0x32,0x00,0x00,0x00,0x4c,0x00,0x69,0x00,
|
||||
0x73,0x00,0x74,0x00,0x32,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x81,0x10,0x02,0x50,
|
||||
0x07,0x00,0x56,0x00,0x09,0x01,0x0a,0x00,
|
||||
0x67,0x00,0x00,0x00,0xff,0xff,0x82,0x00,
|
||||
0x56,0x00,0x65,0x00,0x72,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x01,0x41,0xa1,0x50,
|
||||
0x18,0x01,0x07,0x00,0xc0,0x00,0x67,0x00,
|
||||
0x69,0x00,0x00,0x00,0xff,0xff,0x83,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0 };
|
49
GeneralsMD/Code/Libraries/Source/debug/test1/test1.cpp
Normal file
49
GeneralsMD/Code/Libraries/Source/debug/test1/test1.cpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/test1/test1.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug module - Test 1 (Checking early exceptions)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "../debug.h"
|
||||
|
||||
const char *DebugGetDefaultCommands(void)
|
||||
{
|
||||
return "!debug.io con add";
|
||||
}
|
||||
|
||||
int divByNull;
|
||||
unsigned *invalidPtr=(unsigned *)0x666;
|
||||
|
||||
bool crash(void)
|
||||
{
|
||||
*invalidPtr/=divByNull;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool thisWillCrash=crash();
|
||||
|
||||
void main(void)
|
||||
{
|
||||
}
|
89
GeneralsMD/Code/Libraries/Source/debug/test1/test1.dsp
Normal file
89
GeneralsMD/Code/Libraries/Source/debug/test1/test1.dsp
Normal file
|
@ -0,0 +1,89 @@
|
|||
# Microsoft Developer Studio Project File - Name="test1" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=test1 - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test1.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test1.mak" CFG="test1 - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "test1 - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "test1 - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "test1"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "test1 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "test1 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "test1 - Win32 Release"
|
||||
# Name "test1 - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\test1.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
26
GeneralsMD/Code/Libraries/Source/debug/test2/StdAfx.cpp
Normal file
26
GeneralsMD/Code/Libraries/Source/debug/test2/StdAfx.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// test2.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
50
GeneralsMD/Code/Libraries/Source/debug/test2/StdAfx.h
Normal file
50
GeneralsMD/Code/Libraries/Source/debug/test2/StdAfx.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
|
||||
#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
|
||||
// C RunTime Header Files
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <memory.h>
|
||||
#include <tchar.h>
|
||||
|
||||
// Local Header Files
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
|
|
@ -0,0 +1,3 @@
|
|||
; test dbgcmd file
|
||||
|
||||
debug.io con add ; send output to CON I/O window
|
45
GeneralsMD/Code/Libraries/Source/debug/test2/resource.h
Normal file
45
GeneralsMD/Code/Libraries/Source/debug/test2/resource.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by TEST2.RC
|
||||
//
|
||||
#define IDR_MAINFRAME 128
|
||||
#define IDD_TEST2_DIALOG 102
|
||||
#define IDD_ABOUTBOX 103
|
||||
#define IDS_APP_TITLE 103
|
||||
#define IDM_ABOUT 104
|
||||
#define IDM_EXIT 105
|
||||
#define IDS_HELLO 106
|
||||
#define IDI_TEST2 107
|
||||
#define IDI_SMALL 108
|
||||
#define IDC_TEST2 109
|
||||
#define IDC_MYICON 2
|
||||
#define IDC_STATIC -1
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
#define _APS_NEXT_RESOURCE_VALUE 129
|
||||
#define _APS_NEXT_COMMAND_VALUE 32771
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 110
|
||||
#endif
|
||||
#endif
|
246
GeneralsMD/Code/Libraries/Source/debug/test2/test2.cpp
Normal file
246
GeneralsMD/Code/Libraries/Source/debug/test2/test2.cpp
Normal file
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/test2/test2.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug module - Test 2 (Checking commands, CON I/O, cmddbg file)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "resource.h"
|
||||
#include "..\debug.h"
|
||||
|
||||
#define MAX_LOADSTRING 100
|
||||
|
||||
// Global Variables:
|
||||
HINSTANCE hInst; // current instance
|
||||
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
|
||||
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
|
||||
|
||||
// Foward declarations of functions included in this code module:
|
||||
ATOM MyRegisterClass(HINSTANCE hInstance);
|
||||
BOOL InitInstance(HINSTANCE, int);
|
||||
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
class TestCmdInterface: public DebugCmdInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual bool Execute(class Debug& dbg, const char *cmd, CommandMode cmdmode,
|
||||
unsigned argn, const char * const * argv)
|
||||
{
|
||||
if (strcmp(cmd,"box"))
|
||||
return false;
|
||||
|
||||
MessageBox(NULL,"Hello world!","Command",MB_OK);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void Delete(void) { delete this; }
|
||||
};
|
||||
|
||||
DEBUG_CREATE_COMMAND_GROUP(test,TestCmdInterface)
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPSTR lpCmdLine,
|
||||
int nCmdShow)
|
||||
{
|
||||
// TODO: Place code here.
|
||||
MSG msg;
|
||||
HACCEL hAccelTable;
|
||||
|
||||
// Initialize global strings
|
||||
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
|
||||
LoadString(hInstance, IDC_TEST2, szWindowClass, MAX_LOADSTRING);
|
||||
MyRegisterClass(hInstance);
|
||||
|
||||
// Perform application initialization:
|
||||
if (!InitInstance (hInstance, nCmdShow))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TEST2);
|
||||
|
||||
// Send a command to Debug interface
|
||||
Debug::Command("debug.io ; send via EXE, try test.box!");
|
||||
|
||||
// Main message loop:
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
return msg.wParam;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// FUNCTION: MyRegisterClass()
|
||||
//
|
||||
// PURPOSE: Registers the window class.
|
||||
//
|
||||
// COMMENTS:
|
||||
//
|
||||
// This function and its usage is only necessary if you want this code
|
||||
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
|
||||
// function that was added to Windows 95. It is important to call this function
|
||||
// so that the application will get 'well formed' small icons associated
|
||||
// with it.
|
||||
//
|
||||
ATOM MyRegisterClass(HINSTANCE hInstance)
|
||||
{
|
||||
WNDCLASSEX wcex;
|
||||
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wcex.lpfnWndProc = (WNDPROC)WndProc;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = 0;
|
||||
wcex.hInstance = hInstance;
|
||||
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TEST2);
|
||||
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
||||
wcex.lpszMenuName = (LPCSTR)IDC_TEST2;
|
||||
wcex.lpszClassName = szWindowClass;
|
||||
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
|
||||
|
||||
return RegisterClassEx(&wcex);
|
||||
}
|
||||
|
||||
//
|
||||
// FUNCTION: InitInstance(HANDLE, int)
|
||||
//
|
||||
// PURPOSE: Saves instance handle and creates main window
|
||||
//
|
||||
// COMMENTS:
|
||||
//
|
||||
// In this function, we save the instance handle in a global variable and
|
||||
// create and display the main program window.
|
||||
//
|
||||
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
|
||||
{
|
||||
HWND hWnd;
|
||||
|
||||
hInst = hInstance; // Store instance handle in our global variable
|
||||
|
||||
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
|
||||
|
||||
if (!hWnd)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// create a timer for calling Debug::Update
|
||||
SetTimer(hWnd,1,100,NULL);
|
||||
|
||||
ShowWindow(hWnd, nCmdShow);
|
||||
UpdateWindow(hWnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
|
||||
//
|
||||
// PURPOSE: Processes messages for the main window.
|
||||
//
|
||||
// WM_COMMAND - process the application menu
|
||||
// WM_PAINT - Paint the main window
|
||||
// WM_DESTROY - post a quit message and return
|
||||
//
|
||||
//
|
||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int wmId, wmEvent;
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc;
|
||||
TCHAR szHello[MAX_LOADSTRING];
|
||||
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
switch (wmId)
|
||||
{
|
||||
case IDM_ABOUT:
|
||||
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
|
||||
break;
|
||||
case IDM_EXIT:
|
||||
DestroyWindow(hWnd);
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
case WM_PAINT:
|
||||
hdc = BeginPaint(hWnd, &ps);
|
||||
// TODO: Add any drawing code here...
|
||||
RECT rt;
|
||||
GetClientRect(hWnd, &rt);
|
||||
DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
|
||||
EndPaint(hWnd, &ps);
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
case WM_TIMER:
|
||||
Debug::Update();
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Mesage handler for about box.
|
||||
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
|
||||
{
|
||||
EndDialog(hDlg, LOWORD(wParam));
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
118
GeneralsMD/Code/Libraries/Source/debug/test2/test2.dsp
Normal file
118
GeneralsMD/Code/Libraries/Source/debug/test2/test2.dsp
Normal file
|
@ -0,0 +1,118 @@
|
|||
# Microsoft Developer Studio Project File - Name="test2" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||
|
||||
CFG=test2 - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test2.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test2.mak" CFG="test2 - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "test2 - Win32 Release" (based on "Win32 (x86) Application")
|
||||
!MESSAGE "test2 - Win32 Debug" (based on "Win32 (x86) Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "test2"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "test2 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "test2 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "test2 - Win32 Release"
|
||||
# Name "test2 - Win32 Debug"
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.cpp
|
||||
# ADD CPP /Yc"stdafx.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\test2.rc
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\default.dbgcmd
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\test2.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
132
GeneralsMD/Code/Libraries/Source/debug/test2/test2.rc
Normal file
132
GeneralsMD/Code/Libraries/Source/debug/test2/test2.rc
Normal file
|
@ -0,0 +1,132 @@
|
|||
//Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "windows.h"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE 9, 1
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
//
|
||||
|
||||
IDC_TEST2 MENU DISCARDABLE
|
||||
BEGIN
|
||||
POPUP "&File"
|
||||
BEGIN
|
||||
MENUITEM "E&xit", IDM_EXIT
|
||||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&About ...", IDM_ABOUT
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Accelerator
|
||||
//
|
||||
|
||||
IDC_TEST2 ACCELERATORS MOVEABLE PURE
|
||||
BEGIN
|
||||
"?", IDM_ABOUT, ASCII, ALT
|
||||
"/", IDM_ABOUT, ASCII, ALT
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 230, 75
|
||||
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "About"
|
||||
FONT 8, "System"
|
||||
BEGIN
|
||||
ICON IDI_TEST2,IDC_MYICON,14,9,16,16
|
||||
LTEXT "test2 Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
|
||||
LTEXT "Copyright (C) 2003",IDC_STATIC,49,20,119,8
|
||||
DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""resource.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDC_TEST2 "TEST2"
|
||||
IDS_APP_TITLE "test2"
|
||||
IDS_HELLO "Hello World!"
|
||||
END
|
||||
|
||||
#endif
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
65
GeneralsMD/Code/Libraries/Source/debug/test3/test3.cpp
Normal file
65
GeneralsMD/Code/Libraries/Source/debug/test3/test3.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/test3/test3.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug module - Test 3 (Checking FLAT I/O, logging)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef NDEBUG
|
||||
# define _INTERNAL
|
||||
# pragma comment(linker,"/nodefaultlib:debuginternal.lib")
|
||||
#endif
|
||||
#include "../debug.h"
|
||||
|
||||
unsigned divByNull;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
// switch to debug group
|
||||
Debug::Command("debug.");
|
||||
|
||||
Debug::Command("alwaysflush +");
|
||||
|
||||
// we want our files copied
|
||||
Debug::Command("io flat copy ..\\");
|
||||
|
||||
// split 'split_me' log group to separate file (with size limit)
|
||||
Debug::Command("io flat splitadd l split_me splitted 1");
|
||||
|
||||
// turn all logs on
|
||||
Debug::Command("add l + *");
|
||||
|
||||
// disable no_log log
|
||||
Debug::Command("add l - no_log");
|
||||
|
||||
// now log something...
|
||||
DLOG("This should be visible.\n");
|
||||
DLOG_GROUP(no_log,"This should *NOT* be visible.\n");
|
||||
for (int k=0;k<200;k++)
|
||||
DLOG_GROUP(split_me,"Log line " << k << "\n");
|
||||
DLOG_GROUP(split_me,"Final line in separate log file.\n");
|
||||
|
||||
// and now let's crash!
|
||||
divByNull/=divByNull;
|
||||
}
|
88
GeneralsMD/Code/Libraries/Source/debug/test3/test3.dsp
Normal file
88
GeneralsMD/Code/Libraries/Source/debug/test3/test3.dsp
Normal file
|
@ -0,0 +1,88 @@
|
|||
# Microsoft Developer Studio Project File - Name="test3" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=test3 - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test3.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test3.mak" CFG="test3 - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "test3 - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "test3 - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "test3"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "test3 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "test3 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "test3 - Win32 Release"
|
||||
# Name "test3 - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\test3.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
42
GeneralsMD/Code/Libraries/Source/debug/test4/test4.cpp
Normal file
42
GeneralsMD/Code/Libraries/Source/debug/test4/test4.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/test4/test4.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug module - Test 4 (Multiple DASSERTs, high-count DCHECKs)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "../debug.h"
|
||||
|
||||
void main(void)
|
||||
{
|
||||
for (int i=0;i<30;i++)
|
||||
DCHECK_MSG(i>100,"run#" << i);
|
||||
Debug::Command("list c");
|
||||
for (int k=0;k<3;k++)
|
||||
{
|
||||
DASSERT(k>4);
|
||||
DASSERT_MSG(k<1,"k must be less than 1...");
|
||||
Debug::Command("list a");
|
||||
}
|
||||
}
|
88
GeneralsMD/Code/Libraries/Source/debug/test4/test4.dsp
Normal file
88
GeneralsMD/Code/Libraries/Source/debug/test4/test4.dsp
Normal file
|
@ -0,0 +1,88 @@
|
|||
# Microsoft Developer Studio Project File - Name="test4" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=test4 - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test4.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test4.mak" CFG="test4 - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "test4 - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "test4 - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "test4"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "test4 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "test4 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "test4 - Win32 Release"
|
||||
# Name "test4 - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\test4.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
43
GeneralsMD/Code/Libraries/Source/debug/test5/test5.cpp
Normal file
43
GeneralsMD/Code/Libraries/Source/debug/test5/test5.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/test5/test5.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug module - Test 5 (printf style formatting)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "../debug.h"
|
||||
|
||||
const char *DebugGetDefaultCommands(void)
|
||||
{
|
||||
return "!debug.io con add";
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
// turn on all logs
|
||||
Debug::Command("add l + *");
|
||||
|
||||
for (int k=0;k<16;k++)
|
||||
DLOG("Testing: " << Debug::Format("0x%04x (%c)",k,'A'+k) << "\n");
|
||||
}
|
88
GeneralsMD/Code/Libraries/Source/debug/test5/test5.dsp
Normal file
88
GeneralsMD/Code/Libraries/Source/debug/test5/test5.dsp
Normal file
|
@ -0,0 +1,88 @@
|
|||
# Microsoft Developer Studio Project File - Name="test5" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=test5 - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test5.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test5.mak" CFG="test5 - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "test5 - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "test5 - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "test5"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "test5 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "test5 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "test5 - Win32 Release"
|
||||
# Name "test5 - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\test5.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
59
GeneralsMD/Code/Libraries/Source/debug/test6/test6.cpp
Normal file
59
GeneralsMD/Code/Libraries/Source/debug/test6/test6.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////EA-V1
|
||||
// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/test6/test6.cpp $
|
||||
// $Author: mhoffe $
|
||||
// $Revision: #1 $
|
||||
// $DateTime: 2003/07/03 11:55:26 $
|
||||
//
|
||||
// ©2003 Electronic Arts
|
||||
//
|
||||
// Debug module - Test 6 (SEH, FPO test)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "../debug.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int test,divByZero;
|
||||
|
||||
void func1(void)
|
||||
{
|
||||
test/=divByZero;
|
||||
}
|
||||
|
||||
void func2(void)
|
||||
{
|
||||
func1();
|
||||
}
|
||||
|
||||
void func3(void)
|
||||
{
|
||||
func2();
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
func3();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("This catch clause should not be executed.\n");
|
||||
}
|
||||
}
|
89
GeneralsMD/Code/Libraries/Source/debug/test6/test6.dsp
Normal file
89
GeneralsMD/Code/Libraries/Source/debug/test6/test6.dsp
Normal file
|
@ -0,0 +1,89 @@
|
|||
# Microsoft Developer Studio Project File - Name="test6" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=test6 - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test6.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test6.mak" CFG="test6 - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "test6 - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "test6 - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "test6"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "test6 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "test6 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "test6 - Win32 Release"
|
||||
# Name "test6 - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\test6.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
Reference in a new issue