netlib.narod.ru | < Назад | Оглавление | Далее > |
Говорят, некоторым программистам нравится отлаживать свои программы — я не отношусь к их числу. Приятно узнать, почему ваша программа постоянно «зависает» или почему спрайт неправильно выводится на экран — но я охотно поменял бы это чувство удовлетворения на те напрасно потраченные часы и дни, когда я скрежетал зубами, заново компилировал свои программы и в сотый раз перезагружал компьютер.
Конечно, наша рабочая среда не идеальна, а инструменты еще не прошли всего пути развития. Всю программную отрасль постоянно лихорадит от ошибок в программах. Они приводят к задержкам, сворачиванию и отмене крупных и мелких проектов. На искоренение особо зловредных ошибок истрачены многие миллионы долларов.
Но, работая над проектом, содержащим множество багов, вы теряете не только деньги — вы теряете чувство уверенности. Программирование — дело непростое, и не стоит усложнять его попытками внести новые возможности в еще не отлаженную программу. Мы, программисты, видели достаточно ошибок и привыкли к ним, но такое положение дел никак нельзя считать нормальным.
Иногда ошибки возникают по вине Windows, иногда — по вине DirectX или какой-нибудь библиотеки классов, но подавляющее большинство ошибок лежит на совести прикладных программистов. Если вы нашли ошибку в программе, лучше бросить все дела и заняться ее искоренением. Не стоит усложнять ситуацию и продолжать работу, зная, что в вашей программе прячутся ошибки.
Об ошибках и способах отладки написаны многие тома. Особенно ценной я считаю книгу «Writing Solid Code» Стива Магуайра (Steve Maguire) (Microsoft Press, ISBN 1-55615-551-4). Если вы не читали ее ранее, обязательно прочтите. В этом приложении мы ограничимся проблемами и способами отладки, которые относятся к полноэкранным приложениям DirectDraw.
Отладить полноэкранное приложение намного сложнее, чем любое другое, и для этого есть несколько причин. Самая очевидная из них — раз приложение занимает весь экран, вы не сможете изменить точки прерывания, просмотреть код программы или значения переменных. Дело усложняется переключением страниц. Если программа должна вывести проверочное сообщение или отладочное окно, нельзя гарантировать, что оно действительно появится на экране, потому что Windows может вывести информацию во вторичном буфере. И даже если вам повезет и вы сможете увидеть это окно (при использовании буферизации ваши шансы — 50 на 50), вероятно, его все равно не удастся толком разглядеть из-за различий между текущей и системной палитрой.
Следовательно, многие традиционные механизмы и методики отладки не работают для DirectDraw. Интегрированный отладчик Visual C++ практически бесполезен, а пользоваться стандартными отладочными макросами типа ASSERT() или VERIFY() оказывается рискованно.
Первый шаг в великой битве с ошибками — переход на Windows NT (если вы еще не успели этого сделать). Разумеется, вам не придется отказываться от поддержки Windows 95, но для разработки NT подходит лучше, а приложения DirectX переносятся из NT в 95 без перекомпиляции. Просто Windows NT работает более устойчиво, чем Windows 95. NT редко (очень редко) требует перезагрузки, тогда как в 95 это вполне обычное явление.
Оборотная сторона заключается в том, что по возможностям DirectX NT часто отстает от 95. Поскольку в Windows NT нельзя установить стандартную runtime-часть DirectX, на поддержку новых возможностей у Microsoft уходит больше времени. Следовательно, если вам необходимы новейшие возможности DirectX, то для разработки неизбежно придется использовать Windows 95. Для DirectDraw это не вызывает особых проблем, потому что в последних версиях эта библиотека практически не изменялась. А вот другие DirectX API, напротив, заметно изменились в DirectX 5 (особенно это относится к DirectInput и DirectPlay).
Профессиональные разработчики для DirectX отдают явное предпочтение NT. Более того, некоторые будущие бета-версии DirectX могут предназначаться только для NT.
Visual C++ (как и многие другие среды разработки) содержит макросы, предназначенные специально для отладки. Например, макросы TRACE(), ASSERT() и VERIFY() приносят огромную пользу в процессе разработки. Они предназначены для разных целей, но у всех трех макросов есть нечто общее — они не отягощают итоговый выполняемый файл. При построении отладочных версий вашей программы макросы ведут себя так, как им положено. Однако в «окончательной» версии они удаляются из программы (вместе с теми возможностями, которые ими обеспечивались).
Макрос TRACE() посылает диагностические сообщения в окно отладчика. Правильно составленные сообщения образуют протокол событий, который можно просмотреть после выполнения программы (а средства удаленной отладки, о которой мы вскоре поговорим, позволяют сделать это даже во время работы программы). Макросы TRACE(), содержащие коды возврата и описания ошибок, помогают отыскать источники ошибок в ваших программах. Макрос TRACE() в отличие от двух других нормально работает в полноэкранных приложениях DirectDraw, так что вы можете свободно пользоваться им (этот макрос регулярно встречается в программах на CD-ROM).
Макросы ASSERT() и VERIFY() очень похожи друг на друга, что часто приводит к недоразумениям. На самом деле между ними существует очень важное различие. В отладочных версиях макросы ASSERT() и VERIFY() работают одинаково. Оба макроса вычисляют выражение, переданное им в качестве аргумента, и прекращают работу программы с выводом сообщения в том случае, если это выражение оказывается равным нулю. Отличие заключается в том, что в окончательной версии макрос ASSERT() вместе с вычисляемым выражением полностью удаляется из кода. С другой стороны, выражение макроса VERIFY() остается в программе. Макрос ASSERT() предназначен для проверки состояния переменных, а VERIFY() — для проверки функций. Выражение макроса ASSERT() относится только к состоянию переменных и не является обязательной частью программы, поэтому его можно удалить из окончательной версии.
Использование макросов ASSERT() и VERIFY() в полноэкранных приложениях DirectDraw осложняется тем, что при неудачной проверке выводится диалоговое окно. Несовместимость палитры может привести к искажению окна, а из-за переключения страниц окно может и вовсе не появиться на экране.
При таких затруднениях у вас есть два варианта: отказаться от ASSERT() и VERIFY() или предоставить нестандартные версии, работающие в DirectDraw. Второй вариант предпочтительнее, и, как выясняется, он реализуется достаточно просто.
Если покопаться в заголовочных файлах MFC, вы увидите, что в отладочном режиме макрос ASSERT() определяется так:
#define ASSERT(f) \ do \ { \ if (!(f) && AfxAssertFailedLine(THIS_FILE, __LINE__)) \ AfxDebugBreak(); \ } while (0) \
Выглядит довольно странно. Но вместо того, чтобы пытаться расшифровать логику его работы, мы согласимся с тем, что макрос работает, и попытаемся изменить его так, чтобы он правильно работал в приложениях DirectDraw. Однако перед этим следует заметить, что вывод диалогового окна и завершение приложения выполняются с помощью вызова AfxAssertFailedLine(). Следовательно, любой код, добавленный в этот условный оператор (что на первый взгляд кажется логичным), выполняться не будет.
Теперь давайте подумаем, что нужно сделать для нормального отображения диалогового окна. Можно вызвать функцию DirectDraw FlipToGDISurface() и обеспечить вывод диалогового окна на первичной поверхности, но проблема с палитрой при этом остается, к тому же окно может быть выведено в неверном видеорежиме. Вместо этого мы воспользуемся функцией RestoreDisplayMode() — это гарантирует вывод диалогового окна, активизацию стандартной палитры Windows и возврат к исходному видеорежиму Windows. Видоизмененный код выглядит так:
#define ASSERT(f) \ do \ { \ if (!(f)) \ { \ if (GetDDWin()) \ { \ GetDDWin()->GetDDraw()->RestoreDisplayMode(); \ GetDDWin()->GetDDraw()->Release(); \ } \ AfxAssertFailedLine(THIS_FILE, __LINE__); \ AfxDebugBreak(); \ } \ } while (0) \
Для работы с объектом DirectDraw применяются функции GetDDWin() и GetDDraw() (которые соответственно возвращают указатели на объект DirectDrawWin и интерфейс DirectDraw). Помимо вызова функции RestoreDisplayMode() мы для приличия освобождаем объект DirectDraw. Также обратите внимание на перестановку, в результате которой наш код будет выполняться перед вызовом функции AfxAssertFailedLine().
Перейдем к макросу VERIFY(). Возвращаясь к заголовочным файлам MFC, мы находим, что в отладочной версии VERIFY() реализуется с помощью макроса ASSERT():
#define VERIFY(f) ASSERT(f)
Вспомните — в отладочной версии ASSERT() и VERIFY() ведут себя одинаково. Раз ASSERT() и VERIFY() реализуются одним макросом, VERIFY() можно оставить без изменений. Сказанное относится и к окончательным версиям макросов ASSERT() и VERIFY(), потому что нам не потребуется изменять их поведение. При компиляции окончательной версии ASSERT() и VERIFY() определяются так:
#define ASSERT(f) ((void)0) #define VERIFY(f) ((void)(f))
Как было сказано выше, выражение, передаваемое макросу ASSERT(), удаляется из окончательной версии (в действительности оно заменяется выражением ((void)0), которое игнорируется компилятором). Выражения, передаваемые VERIFY(), остаются в коде программы, однако их значение больше не проверяется.
Нам остается лишь переопределить стандартный вариант ASSERT() из MFC своим нестандартным вариантом. Для этого необходимо сначала отменить определение макроса из MFC. Кроме того, нужно позаботиться о том, чтобы подстановка осуществлялась только в отладочной версии. Окончательный код выглядит так:
#ifdef _DEBUG #undef ASSERT #define ASSERT(f) \ do \ { \ if (!(f)) \ { \ if (GetDDWin()) \ { \ GetDDWin()->GetDDraw()->RestoreDisplayMode(); \ GetDDWin()->GetDDraw()->Release(); \ } \ AfxAssertFailedLine(THIS_FILE, __LINE__); \ AfxDebugBreak(); \ } \ } while (0) \ #endif _DEBUG
Модифицированный макрос находится на CD-ROM и готов к работе, поэтому если вы захотите внести изменения в какую-нибудь программу, то можете свободно пользоваться макросами TRACE(), ASSERT() и VERIFY(). Кроме того, этот код автоматически генерируется и включается в проекты, создаваемые DirectDraw AppWizard.
Процесс отладки упрощается, если вам повезло и в вашем распоряжении оказались два компьютера, объединенных в локальную сеть. В этом случае возможна удаленная отладка, при которой на одном компьютере работает отлаживаемая программа, а на другом — отладчик Visual C++. При удаленной отладке исчезают все проблемы, связанные с переключением страниц, палитрами и отображением отладчика. Отладчик всегда присутствует на экране и с ним можно работать, потому что отладчик и приложение работают на разных компьютерах. Даже если ваша программа «сломается», ее состояние можно будет просмотреть в отладчике. Поскольку удаленная отладка обладает такими преимуществами (и при этом так плохо документирована), мы поговорим о том, как происходит ее настройка. Если эта тема вас не интересует, можете пропустить этот раздел.
Для выполнения удаленной отладки вам понадобятся два компьютера, объединенных в локальную сеть. Конкретные параметры сети (количество узлов, тип кабеля, сетевые адаптеры и т.д.) не имеют значения; главное — чтобы на обоих компьютерах был установлен сетевой протокол TCP/IP. Кроме того, необходимо установить на обоих компьютерах Visual C++.
Затем вы должны выбрать, на каком компьютере будет работать отладчик Visual C++, а на каком — приложение. Мы будем называть компьютер, на котором работает Visual C++, хостом, а компьютер с отлаживаемым приложением — удаленным компьютером. Обычно хостом назначают более мощный из двух компьютеров.
Вам необходимо узнать адреса TCP/IP для обоих компьютеров. Проще всего получить этот адрес с помощью утилиты Winipcfg (WINIPCFG.EXE). Для Winipcfg не существует ярлыка или команды меню Start (Пуск), поэтому придется либо создать ярлык или команду (утилита находится в каталоге Windows), либо запустить Winipcfg из окна DOS или диалогового окна Run (Выполнить) меню Start (Пуск). Окно утилиты Winipcfg изображено на рис. А.1. В поле IP Address приведено значение адреса TCP/IP. В нашем примере удаленный компьютер имеет адрес 128.128.128.1 (а хост будет иметь адрес 128.128.128.2).
Рис. A.1. Утилита Winipcfg
Также вам понадобится сетевое имя удаленного компьютера. Сетевое имя представляет собой неформальную строку, которая облегчает идентификацию сетевых компьютеров (при этом вам не придется запоминать адреса TCP/IP для всех компьютеров сети). Чтобы узнать сетевое имя компьютера, можно щелкнуть правой кнопкой мыши на значке Network Neighborhood (Сетевое окружение) (он находится на рабочем столе) и выбрать из контекстного меню команду Properties (Свойства); откроется диалоговое окно Network (Сеть). Перейдите на вкладку Identification (Сетевая идентификация). На рис. А.2 показано, как выглядит эта вкладка. В данном примере имя удаленного компьютера — remotemachine. Вероятно, вам не стоит менять сетевое имя, если только вы не являетесь сетевым администратором — просто воспользуйтесь именем, которое было назначено компьютеру при исходной настройке.
Рис. A.2. Диалоговое окно Network Identification
Затем вам понадобится каталог на удаленном компьютере, где будет храниться и работать ваше приложение. Вы можете присвоить ему любое имя и разместить в любом месте жесткого диска, но на практике оказывается удобнее разместить этот каталог поближе к корневому. Вам не придется копировать выполняемый файл приложения (это будет сделано автоматически), однако следует перенести все файлы данных, необходимые для его работы. Собственно, выполняемый файл можно перенести хотя бы с целью тестирования. Чтобы отладка прошла нормально, запущенное приложение должно найти все свои файлы данных (не считая случаев, когда вы отлаживаете поведение программы при отсутствующих файлах данных).
После того как вы создадите каталог для приложения и убедитесь в том, что оно может выполняться на удаленном компьютере, запустите отладочный монитор Visual C++ (MSVCMON.EXE). Для этой программы, как и для утилиты Winipcfg, не существует ярлыка, поэтому вам придется создать его самостоятельно. Отладочный монитор находится в каталоге bin Visual C++. Если вы собираетесь плотно заняться удаленной отладкой, вероятно, ярлык отладочного монитора следует поместить в удобное место. Окно отладочного монитора Visual C++ изображено на рис. А.3.
Рис. A.3. Диалоговое окно Visual C++ Debug Monitor
Теперь нужно указать адрес хоста. Убедитесь, что в отладочном мониторе выбрано соединение TCP/IP, и нажмите кнопку Settings — откроется диалоговое окно Win32 Network (TCP/IP) Settings. Введите адрес хоста в первом поле. На рис. А.4 показано, как выглядит диалоговое окно с введенным адресом.
Рис. A.4. Диалоговое окно Network Settings
Вводить пароль необязательно — я рекомендую оставить это поле пустым. После ввода адреса хоста нажмите кнопку OK. Вы возвратитесь к диалоговому окну Debug Monitor. Нажмите кнопку Connect. Появится маленькое окно, которое показывает, что отладочный монитор готов начать сеанс отладки. Теперь удаленный компьютер настроен для проведения отладки.
Теперь займемся настройкой хоста. Запустите Visual C++ и загрузите проект, который вы собираетесь отлаживать. В нашем примере используется проект с именем Sample. Выполните команду Project|Settings и перейдите на вкладку General. На ней задается каталог, в котором генерируется итоговый выполняемый файл. Для упрощения отладки мы будем генерировать его прямо на удаленном компьютере — это избавит нас от необходимости заново копировать выполняемый файл на удаленный компьютер после очередной компиляции. В поле Output files введите имя каталога, созданного ранее на удаленном компьютере. Имя начинается с условного обозначения сетевого файла (\\). На рис. А.5 показано, как выглядит поле Output files с указанным каталогом.
Рис. A.5. Поле Output files подготовлено для генерации выполняемого файла на удаленном компьютере
Задаваемая строка начинается с имени удаленного компьютера (remotemachine), за которым следует имя диска (в нашем примере каталог удаленной отладки находится на диске C) и имя каталога. Перейдите на вкладку Debug; здесь необходимо изменить все три поля. Вы должны задать местонахождение целевого выполняемого файла и рабочий каталог. На рис. А.6 показано, как заполняются поля вкладки Debug в нашем примере. Как и на рис. А.5, путь к выполняемому файлу включает имя удаленного компьютера.
Рис. A.6. Изменения на вкладке Debug
Перед тем как приступать к удаленной отладке, остается сделать лишь один шаг. Выполните команду Debugger Remote Connection из меню Build. Эта команда открывает окно (похожее на окно отладочного монитора), предназначенное для активизации и настройки сеанса удаленной отладки. По умолчанию в списке Connection выбирается строка Local. Чтобы перейти к удаленной отладке, выберите строку Network (TCP/IP), как показано на рис. А.7.
Рис. A.7. Окно Remote Connection
Нажмите кнопку Settings — появится окно, изображенное на рис. А.4. Задайте в нем адрес TCP/IP удаленного компьютера. Поле Debug monitor password оставьте пустым, если только вы не задали пароль при настройке отладочного монитора на удаленном компьютере.
Теперь можно запускать отладчик. К сожалению, настройка еще не закончена, потому что отладчик потребует задать местонахождение всех DLL, используемых удаленным приложением. К счастью, это необходимо проделать лишь один раз.
Запустите отладчик. Если все параметры были настроены правильно, окно Debug Monitor на удаленном компьютере исчезнет — это говорит о том, что соединение установлено.
Удаленный компьютер попытается запустить программу, и вам будет предложено (на хостовом компьютере) указать местонахождение необходимых DLL. Для каждой DLL открывается окно Find Local Module. Вы должны ввести имя файла, включая сетевое имя компьютера. Окно Find Local Module изображено на рис. А.8 (в нем предлагается задать местонахождение файла WINMM.DLL). Часть введенной строки не поместилась на рисунке, но вы должны помнить о том, что кроме пути необходимо указать имя файла.
Рис. A.8. Окно Find Local Module
После того как вы укажете местонахождение всех DLL (как правило, они располагаются в каталоге windows\system), программа запускается на удаленном компьютере, однако ее отладочный вывод направляется в окно отладчика на хосте. Теперь вы можете отлаживать свою программу. Мы настроили Visual C++ так, что при каждой компиляции новый выполняемый файл будет автоматически копироваться на удаленный компьютер. Удаленная отладка почти ничем не отличается от обычной, разве что программа выполняется не на хосте, а на другом компьютере.
Напоследок я скажу еще несколько слов об удаленной отладке. Во-первых, как ее отключить? Хороший вопрос. Выполните команду Build|Debugger Remote Connection в Visual C++ (на хосте), затем выберите строку Local в списке Connection и нажмите кнопку OK.
Удаленная отладка обладает многими достоинствами, но она не идеальна. Прежде всего, точки прерывания в ней работают ненадежно, а то и вовсе не работают. Другая проблема заключается в том, что после настройки удаленной отладки и выбора местонахождения DLL, необходимых для вашей программы, Visual C++ будет настаивать на загрузке DLL даже после возврата в режим локальной отладки. Следовательно, в конце раздела, посвященного удаленной отладке, мне следует рассказать о том, как вернуться к нормальной загрузке DLL.
Выполните команду Project|Settings и перейдите на вкладку Debug. Выберите из списка Category строку Additional DLL. Открывается список DLL, которые Visual C++ пытается загрузить при отладке вашей программы (независимо от того, включена удаленная отладка или нет). Чтобы отказаться от переназначения DLL (для нормальной отладки вам не потребуется ни один из элементов этого списка), выделите соответствующую строку и снимите флажок в левом верхнем углу. Список Additional DLL с некоторыми DLL, необходимыми для типичных приложений MFC, изображен на рис. А.9.
Рис. A.9. Окно Additional DLL
Вероятно, вы уже заметили, что при запуске приложений DirectX в окне вывода отладчика Visual C++ появляются диагностические сообщения. По умолчанию отладочные версии компонентов DirectX сообщают таким образом о важных внутренних событиях — например, об ошибках. Типичное окно вывода для приложения DirectDraw изображено на рис. А.10.
Рис. A.10. Типичное окно вывода в отладчике
СОВЕТ |
Прислушивайтесь к крикам DirectX. При установке runtime-части DirectX на рабочий компьютер возникает искушение установить окончательные версии DLL вместо отладочных (во время инсталляции вам предлагается выбрать нужный вариант). Не поддавайтесь соблазну и не устанавливайте окончательные версии! Да, они действительно работают чуть быстрее, и именно с ними будут работать пользователи вашего приложения, но при этом вы лишитесь отладочного вывода. Если во время работы над программой возникнут проблемы, вы так и не узнаете, что же DirectX пытается вам сказать. |
Возможно, вы не знаете, что детальность этих сообщений тоже можно изменять. В каждой из библиотек DirectDraw, Direct3D и DirectSound можно выбрать пять разных уровней отладочных сообщений. Чтобы настроить уровень отладочных сообщений, выберите значок DirectX в окне Control Panel (Панель управления) и перейдите на вкладку нужного компонента DirectX. Диалоговое окно DirectX Properties с выбранной вкладкой DirectDraw изображено на рис. А.11.
Рис. A.11. Окно DirectX Properties (запускается из Control Panel)
Для библиотеки DirectDraw нажмите кнопку Advanced Settings — откроется окно DirectDraw Advanced Settings. Нужный уровень отладочных сообщений устанавливается с помощью ползунка Debug Level. Окно DirectDraw Advanced Settings изображено на рис. А.12.
Рис. A.12. Окно DirectDraw Advanced Settings
При максимальном уровне отладки каждое приложение DirectDraw, запущенное в отладчике, выдает весьма обширный и подробный протокол. Вывод протокола снижает быстродействие программы, так что максимальный уровень не стоит держать включенным постоянно. С другой стороны, он сильно помогает в затяжной борьбе с DirectDraw. Чтобы показать, насколько подробная информация выдается при максимальном уровне отладки, я приведу отладочный протокол для небольшого полноэкранного приложения DirectDraw. Обратите внимание на то, что листинг раскрывает некоторые внутренние тонкости работы DirectDraw. Подробный отладочный протокол приведен в листинге А.1.
Листинг A.1. Подробный отладочный протокол DirectDraw |
DDraw:====> ENTER: DLLMAIN(baaa12c0): Process Attach: fff00c89, tid=fff04bf1 DDraw:Thunk connects DDraw:Signalling DDHELP that a new process has connected DDraw:====> EXIT: DLLMAIN(baaa12c0): Process Attach: fff00c89 DDraw:createDC(R3D) DDraw:Enumerating GUID aba52f41-f744-11cf-b4-52-00-00-1d-1b-41-26 DDraw: Driver Name = R3D DDraw: Description = Righteous 3D DirectX II Driver DDraw:DeleteDC 0x179e DDraw:createDC(mm3dfx) DDraw:Enumerating GUID 3a0cfd01-9320-11cf-ac-a1-00-a0-24-13-c2-e2 DDraw: Driver Name = mm3dfx DDraw: Description = 3Dfx Interactive DirectX Driver DDraw:DeleteDC 0x179e DDraw:Only one Display device in the current system. DDraw:DirectDrawCreate entered DDraw: GUID *:00000000, LPLPDD:0064f870, pUnkOuter:00000000 DDraw:Registry already scanned, not doing it again DDraw:full name = C:\SAMPLE\DEBUG\SAMPLE.EXE DDraw:name = SAMPLE.EXE DDraw:DirectDrawCreate: pid = fff00c89 DDraw:Reading Registry DDraw: ModeXOnly: 0 DDraw: EmulationOnly: 0 DDraw: ShowFrameRate: 0 DDraw: EnablePrintScreen: 0 DDraw: DisableMMX: 0 DDraw: DisableWiderSurfaces:0 DDraw: DisableNoSysLock:0 DDraw: ForceNoSysLock:0 DDraw:Signalling DDHELP to create a new DC DDraw:createDC(display) DDraw:DIRECTDRAW driver is wrong version, got 0x5250, expected 0x0100 DDraw:getDisplayMode: DDraw: bpp=8, refresh=0 DDraw: dwHeight=600, dwWidth=800 DDraw: lStride=0 DDraw:Driver says nummodes=9 DDraw:Enum Display Settings says nummodes=9 DDraw:dwModeIndex = 1 DDraw:Masks for current mode are: 00000000 00000000 00000000 DDraw:DirectDrawObjectCreate: oldpdd == 00000000, reset=0 DDraw:DIRECTDRAW object passed in = 00000000 DDraw:oldpdd == 00000000, reset=0 DDraw:Driver Object: 2256 base bytes DDraw:dwReserved3 of DDrawGbl is set to 0x0 DDraw:oldpdd == NULL || reset DDraw:Driver can't blt DDraw:pddd->lp16DD = 40cf0000 DDraw:Adding ModeX mode 320x200x8 (standard VGA flag is 0) DDraw:Adding ModeX mode 320x240x8 (standard VGA flag is 0) DDraw:Adding ModeX mode 320x200x8 (standard VGA flag is 1) DDraw:All video memory heaps have been disabled. OS has no AGP support DDraw:Current and Original Mode = 1 DDraw:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ MODE INDEX = 1 DDraw:DDHALInfo contains D3D pointers: 00000000 00000000 DDraw:createDC(display) DDraw:NOT Setting DDCAPS_BANKSWITCHED DDraw:DeleteDC 0x179e DDraw:Taking the Win16 lock may not be necessary for VRAM locks DDraw:DirectDrawObjectCreate: Returning global object 82dc11f8 DDraw:createDC(display) DDraw:createDC(display) DDraw:DeleteDC 0x175e DDraw:DeleteDC 0x179e DDraw:Primary's rect is 0, 0, 800, 600 DDraw:HELInit for DISPLAY Driver: Reference Count = 1 DDraw:createDC(display) DDraw:DeleteDC 0x179e DDraw:createDC(display) DDraw:createDC(display) DDraw:DeleteDC 0x175e DDraw:DeleteDC 0x179e DDraw:***New local allocated 82dc1b1c for global pdrv 82dc11f8 DDraw:New driver object created, interface ptr = 82dc1b84 DDraw: DirectDrawCreate succeeds, and returns ddraw pointer 82dc1b84 DDraw:New driver interface created, 82dc1bb0 DDraw:DD_AddRef, pid=fff00c89, obj=82dc1bb0 DDraw:DD_AddRef, Reference Count: Global = 2 Local = 2 Int = 1 DDraw:DD_Release, pid=fff00c89, obj=82dc1b84 DDraw:DD_Release, Ref Count: Global = 1 Local = 1 Interface = 0 DDraw:*********** ALLOWING MODE X AND VGA MODES DDraw:DD_GetDeviceRect: display [0 0 800 600] DDraw:Subclassing window 00000aac DDraw:StartExclusiveMode DDraw:******** invalidating all surfaces DDraw:Enumerating mode 0. 640x480 DDraw:Enumerating mode 1. 800x600 DDraw:Enumerating mode 2. 1024x768 DDraw:Enumerating mode 3. 1280x1024 DDraw:Enumerating mode 4. 640x480 DDraw:Enumerating mode 5. 800x600 DDraw:Enumerating mode 6. 1024x768 DDraw:Enumerating mode 7. 640x480 DDraw:Enumerating mode 8. 800x600 DDraw:Enumerating mode 9. 320x200 DDraw:Enumerating mode 10. 320x240 DDraw:Enumerating mode 11. 320x200 DDraw:Looking for 640x480x8 DDraw:Found 640x480x8x (flags = 1) DDraw:Found 800x600x8x (flags = 1) DDraw:Found 1024x768x8x (flags = 1) DDraw:Found 1280x1024x8x (flags = 1) DDraw:Found 640x480x16x (flags = 0) DDraw:Found 800x600x16x (flags = 0) DDraw:Found 1024x768x16x (flags = 0) DDraw:Found 640x480x32x (flags = 0) DDraw:Found 800x600x32x (flags = 0) DDraw:Found 320x200x8x (flags = 3) DDraw:Found 320x240x8x (flags = 3) DDraw:Found 320x200x8x (flags = 11) DDraw:Calling HEL SetMode DDraw:width = 640 DDraw:height = 480 DDraw:bpp = 8 DDraw:WM_DISPLAYCHANGE: 640x480x8 DDraw:DD_GetDeviceRect: display [0 0 640 480] DDraw:WM_SIZE hWnd=AAC wp=0000, lp=01E00280 DDraw:WM_SIZE: Window restored, NOT sending WM_ACTIVATEAPP DDraw:createDC(display) DDraw:DeleteDC 0x1712 DDraw:createDC(display) DDraw:createDC(display) DDraw:DeleteDC 0x179e DDraw:DeleteDC 0x1712 DDraw:createDC(display) DDraw:getDisplayMode: DDraw: bpp=8, refresh=0 DDraw: dwHeight=480, dwWidth=640 DDraw: lStride=0 DDraw:Driver says nummodes=9 DDraw:Enum Display Settings says nummodes=9 DDraw:dwModeIndex = 0 DDraw:Masks for current mode are: 00000000 00000000 00000000 DDraw:DirectDrawObjectCreate: oldpdd == 82dc11f8, reset=1 DDraw:DIRECTDRAW object passed in = 82dc11f8 DDraw:oldpdd == 82dc11f8, reset=1 DDraw:Driver Object: 2256 base bytes DDraw:dwReserved3 of DDrawGbl is set to 0x0 DDraw:oldpdd == NULL || reset DDraw:Driver can't blt DDraw:******** invalidating all surfaces DDraw:All video memory heaps have been disabled. OS has no AGP support DDraw:Current and Original Mode = 0 DDraw:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ MODE INDEX = 0 DDraw:DDHALInfo contains D3D pointers: 00000000 00000000 DDraw:createDC(display) DDraw:NOT Setting DDCAPS_BANKSWITCHED DDraw:DeleteDC 0x179e DDraw:Taking the Win16 lock may not be necessary for VRAM locks DDraw:DirectDrawObjectCreate: Returning global object 82dc11f8 DDraw:createDC(display) DDraw:createDC(display) DDraw:DeleteDC 0x1776 DDraw:DeleteDC 0x179e DDraw:Primary's rect is 0, 0, 640, 480 DDraw:DeleteDC 0x1712 DDraw:Looking for 640x480x16 DDraw:Found 640x480x8x (flags = 1) DDraw:Found 800x600x8x (flags = 1) DDraw:Found 1024x768x8x (flags = 1) DDraw:Found 1280x1024x8x (flags = 1) DDraw:Found 640x480x16x (flags = 0) DDraw:Found 800x600x16x (flags = 0) DDraw:Found 1024x768x16x (flags = 0) DDraw:Found 640x480x32x (flags = 0) DDraw:Found 800x600x32x (flags = 0) DDraw:Found 320x200x8x (flags = 3) DDraw:Found 320x240x8x (flags = 3) DDraw:Found 320x200x8x (flags = 11) DDraw:Calling HEL SetMode DDraw:width = 640 DDraw:height = 480 DDraw:bpp = 16 DDraw:Window 00000ac4 is on top of us!! DDraw:Window 00000ac4 is on top of us!! DDraw:Window 00000ac4 is on top of us!! DDraw:WM_DISPLAYCHANGE: 640x480x16 DDraw:DD_GetDeviceRect: display [0 0 640 480] DDraw:createDC(display) DDraw:DeleteDC 0x172a DDraw:createDC(display) DDraw:createDC(display) DDraw:DeleteDC 0xc96 DDraw:DeleteDC 0x172a DDraw:createDC(display) DDraw:getDisplayMode: DDraw: bpp=16, refresh=0 DDraw: dwHeight=480, dwWidth=640 DDraw: lStride=0 DDraw:Driver says nummodes=9 DDraw:Enum Display Settings says nummodes=9 DDraw:dwModeIndex = 4 DDraw:Masks for current mode are: 00007c00 000003e0 0000001f DDraw:DirectDrawObjectCreate: oldpdd == 82dc11f8, reset=1 DDraw:DIRECTDRAW object passed in = 82dc11f8 DDraw:oldpdd == 82dc11f8, reset=1 DDraw:Driver Object: 2256 base bytes DDraw:dwReserved3 of DDrawGbl is set to 0x0 DDraw:oldpdd == NULL || reset DDraw:Driver can't blt DDraw:******** invalidating all surfaces DDraw:All video memory heaps have been disabled. OS has no AGP support DDraw:Current and Original Mode = 4 DDraw:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ MODE INDEX = 4 DDraw:DDHALInfo contains D3D pointers: 00000000 00000000 DDraw:createDC(display) DDraw:NOT Setting DDCAPS_BANKSWITCHED DDraw:DeleteDC 0xc96 DDraw:Taking the Win16 lock may not be necessary for VRAM locks DDraw:DirectDrawObjectCreate: Returning global object 82dc11f8 DDraw:createDC(display) DDraw:createDC(display) DDraw:DeleteDC 0x179e DDraw:DeleteDC 0xc96 DDraw:Primary's rect is 0, 0, 640, 480 DDraw:DeleteDC 0x172a DDraw:82dc1bb0->CreateSurface DDraw: DDSURFACEDESC->dwBackBufferCount = 1 DDraw: DDSURFACEDESC->lpSurface = 00000000 DDraw: DDSCAPS_COMPLEX DDraw: DDSCAPS_FLIP DDraw: DDSCAPS_PRIMARYSURFACE DDraw:******** invalidating all primary surfaces DDraw:#### Using GDI screen bpp = 16 DDraw:*** allocating primary surface DDraw:createDC(display) DDraw:createDC(display) DDraw:DeleteDC 0x179e DDraw:DeleteDC 0xc96 DDraw:#### Using GDI screen bpp = 16 DDraw:*** allocating a backbuffer DDraw:HEL:About to allocate 614400 bytes for the surface DDraw:DD_Surface_AddRef, Reference Count: Global = 1 Local = 1 Int = 1 DDraw:DD_Surface_AddRef, Reference Count: Global = 1 Local = 1 Int = 1 DDraw: CreateSurface returns 00000000 (0) DDraw:DD_Surface_AddRef, Reference Count: Global = 2 Local = 2 Int = 2 DDraw:82dc1bb0->CreateSurface DDraw: DDSURFACEDESC->dwHeight = 240 DDraw: DDSURFACEDESC->dwWidth = 320 DDraw: DDSURFACEDESC->lpSurface = 00000000 DDraw: DDSCAPS_OFFSCREENPLAIN DDraw: DDSCAPS_VIDEOMEMORY DDraw:No hardware support DDraw: CreateSurface returns 88760233 (563) DDraw:82dc1bb0->CreateSurface DDraw: DDSURFACEDESC->dwHeight = 240 DDraw: DDSURFACEDESC->dwWidth = 320 DDraw: DDSURFACEDESC->lpSurface = 00000000 DDraw: DDSCAPS_OFFSCREENPLAIN DDraw: DDSCAPS_SYSTEMMEMORY DDraw:Forcing pixel format for explicit system memory surface DDraw:#### Got surface pixel format bpp = 16 DDraw:*** allocating a surface 320x240x16 DDraw:HEL: About to allocate 153600 bytes for the surface of 640x240 with alignemnt 8 DDraw:DD_Surface_AddRef, Reference Count: Global = 1 Local = 1 Int = 1 DDraw: CreateSurface returns 00000000 (0) DDraw:82dc1f74->Lock DDraw: DDSURFACEDESC->dwHeight = 240 DDraw: DDSURFACEDESC->dwWidth = 320 DDraw: DDSURFACEDESC->lPitch = 640 DDraw: DDSURFACEDESC->lpSurface = 004b7118 DDraw:Flags: DDraw: DDPF_RGB DDraw: BitCount:16 DDraw: Bitmasks: R/Y:00007c00, G/U:000003e0, B/V:0000001f, Alpha/Z:00000000 DDraw: DDSCAPS_OFFSCREENPLAIN DDraw: DDSCAPS_SYSTEMMEMORY DDraw:WM_SIZE hWnd=AAC wp=0000, lp=01E00280 DDraw:WM_SIZE: Window restored, sending WM_ACTIVATEAPP DDraw:WM_ACTIVATEAPP: BEGIN Activating app pid=fff00c89, tid=fff04bf1 DDraw:*** Already activated DDraw:WM_ACTIVATEAPP: DONE Activating app pid=fff00c89, tid=fff04bf1 DDraw:Bringing window to top DDraw:WM_ACTIVATEAPP: BEGIN Deactivating app pid=fff00c89, tid=fff04bf1 DDraw:*** Active state changing DDraw:******** invalidating all surfaces DDraw:INACTIVE: fff00c89: Restoring original mode (1) DDraw:In RestoreDisplayMode DDraw:Turning off DCI in mySetMode DDraw:WM_DISPLAYCHANGE: 800x600x8 DDraw:DD_GetDeviceRect: display [0 0 800 600] DDraw:WM_SIZE hWnd=AAC wp=0000, lp=02580320 DDraw:WM_SIZE: Window restored, NOT sending WM_ACTIVATEAPP DDraw:WM_ACTIVATEAPP: BEGIN Deactivating app pid=fff00c89, tid=fff04bf1 DDraw:*** Already deactivated DDraw:WM_ACTIVATEAPP: DONE Deactivating app pid=fff00c89, tid=fff04bf1 DDraw:createDC(display) DDraw:createDC(display) DDraw:DeleteDC 0x159a DDraw:DeleteDC 0xa4a DDraw:RestoreDisplayMode: Process fff00c89 Mode = 4 DDraw:createDC(display) DDraw:getDisplayMode: DDraw: bpp=8, refresh=0 DDraw: dwHeight=600, dwWidth=800 DDraw: lStride=0 DDraw:Driver says nummodes=9 DDraw:Enum Display Settings says nummodes=9 DDraw:dwModeIndex = 1 DDraw:Masks for current mode are: 00000000 00000000 00000000 DDraw:DirectDrawObjectCreate: oldpdd == 82dc11f8, reset=1 DDraw:DIRECTDRAW object passed in = 82dc11f8 DDraw:oldpdd == 82dc11f8, reset=1 DDraw:Driver Object: 2256 base bytes DDraw:dwReserved3 of DDrawGbl is set to 0x0 DDraw:oldpdd == NULL || reset DDraw:Driver can't blt DDraw:******** invalidating all surfaces DDraw:All video memory heaps have been disabled. OS has no AGP support DDraw:Current and Original Mode = 1 DDraw:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ MODE INDEX = 1 DDraw:DDHALInfo contains D3D pointers: 00000000 00000000 DDraw:createDC(display) DDraw:NOT Setting DDCAPS_BANKSWITCHED DDraw:DeleteDC 0x170a DDraw:Taking the Win16 lock may not be necessary for VRAM locks DDraw:DirectDrawObjectCreate: Returning global object 82dc11f8 DDraw:createDC(display) DDraw:createDC(display) DDraw:DeleteDC 0xaa2 DDraw:DeleteDC 0x170a DDraw:Primary's rect is 0, 0, 800, 600 DDraw:DeleteDC 0x13ba DDraw:Redrawing all windows DDraw:DoneExclusiveMode DDraw:Enabling error mode, hotkeys DDraw:Mode was never changed by this app DDraw:WM_ACTIVATEAPP: DONE Deactivating app pid=fff00c89, tid=fff04bf1 DDraw:DD_Surface_Release, Reference Count: Global = 0 Local = 0 Int = 0 DDraw:Deleting attachment from 82dc1e98 to 82dc1b84 (implicit = 1) DDraw:DeleteOneAttachment: 82dc1b84,82dc1e98 DDraw:DD_Surface_AddRef, Reference Count: Global = 3 Local = 3 Int = 3 DDraw:Leaving AddRef early to prevent recursion DDraw:DeleteOneLink: 82dc1e98,82dc1b84 DDraw:DeleteOneLink: 82dc1b84,82dc1e98 DDraw:DD_Surface_Release, Reference Count: Global = 2 Local = 2 Int = 2 DDraw:Leaving Release early to prevent recursion DDraw:DD_Surface_Release, Reference Count: Global = 1 Local = 1 Int = 1 DDraw:DD_Surface_Release, Reference Count: Global = 0 Local = 0 Int = 0 DDraw:Freeing pointer 0042110c DDraw:DD_Release, pid=fff00c89, obj=82dc1bb0 DDraw:DD_Release, Ref Count: Global = 0 Local = 0 Interface = 0 DDraw:Unsubclassing window 00000aac DDraw:ProcessSurfaceCleanup DDraw:Process fff00c89 had 1 accesses to surface 82dc1f74 DDraw:DD_Surface_Release, Reference Count: Global = 0 Local = 0 Int = 0 DDraw:Freeing pointer 004b7118 DDraw:Leaving ProcessSurfaceCleanup DDraw:ProcessPaletteCleanup, ppal=00000000 DDraw:ProcessClipperCleanup DDraw:Cleaning up clippers owned by driver object 0x82dc11f8 DDraw:Not cleaning up clippers not owned by a driver object DDraw:ProcessVideoPortCleanup DDraw:Leaving ProcessVideoPortCleanup DDraw:Mode was never changed by this app DDraw:FREEING DRIVER OBJECT DDraw:Calling HEL DestroyDriver DDraw:HEL DestroyDriver: dwHELRefCnt=0 DDraw:3 surfaces allocated - 768000 bytes total DDraw:*********** DDHEL TIMING INFO ************ DDraw:myFlip: 30 calls, 1.365 sec (0.045) DDraw:myLock: 1 calls, 0.000 sec (0.000) DDraw:myUnlock: 1 calls, 0.000 sec (0.000) DDraw:****************************************** DDraw:Frequency(cycles/second)(0) 1193180 DDraw:Blt16_SrcCopy(32): SUM = 264860 DDraw:Blt16_SrcCopy(32): COUNT = 30 DDraw:Blt16_SrcCopy(32): AVG = 8828 DDraw:Blt16_SrcCopy(32): MIN = 8572 DDraw:Blt16_SrcCopy(32): MAX = 9964 DDraw:Blt16_SrcCopy(32): Dst MB/sec = 17 DDraw:Blt16_ColorFill(47): SUM = 716435 DDraw:Blt16_ColorFill(47): COUNT = 32 DDraw:Blt16_ColorFill(47): AVG = 22388 DDraw:Blt16_ColorFill(47): MIN = 15855 DDraw:Blt16_ColorFill(47): MAX = 55858 DDraw:Blt16_ColorFill(47): Dst MB/sec = 27 DDraw:P6SrcCopy(Bypass Blt16_SrcCopy)(88): SUM = 263495 DDraw:P6SrcCopy(Bypass Blt16_SrcCopy)(88): COUNT = 30 DDraw:P6SrcCopy(Bypass Blt16_SrcCopy)(88): AVG = 8783 DDraw:P6SrcCopy(Bypass Blt16_SrcCopy)(88): MIN = 8528 DDraw:P6SrcCopy(Bypass Blt16_SrcCopy)(88): MAX = 9917 DDraw:P6SrcCopy(Bypass Blt16_SrcCopy)(88): Dst MB/sec = 17 DDraw:Driver is now FREE DDraw:====> ENTER: DLLMAIN(baaa12c0): Process Detach fff00c89, tid=fff04bf1 DDraw:MemState DDraw:Memory still allocated! Alloc count = 11 DDraw:Current Process (pid) = fff00c89 DDraw:82dc100c: dwSize=00000008, lpAddr=baaa1bbc (pid=fff1b349) DDraw:82dc1054: dwSize=0000001d, lpAddr=baae5093 (pid=fff18e61) DDraw:82dc1090: dwSize=00000019, lpAddr=baae5093 (pid=fff18e61) DDraw:82dc10c8: dwSize=00000019, lpAddr=baae5093 (pid=fff18e61) DDraw:82dc1100: dwSize=0000001d, lpAddr=baae5093 (pid=fff18e61) DDraw:82dc113c: dwSize=00000018, lpAddr=baae5093 (pid=fff18e61) DDraw:82dc1170: dwSize=00000019, lpAddr=baae5093 (pid=fff18e61) DDraw:82dc11a8: dwSize=0000001c, lpAddr=baae52c8 (pid=fff18e61) DDraw:82dc1030: dwSize=00000008, lpAddr=baaa1bbc (pid=fff04a0d) DDraw:82dc1fc0: dwSize=00000008, lpAddr=baaa1bbc (pid=fff04a0d) DDraw:82dc1c3c: dwSize=00000008, lpAddr=baaa1bbc (pid=fff00c89) DDraw:Total Memory Unfreed From Current Process = 8 bytes DDraw:====> EXIT: DLLMAIN(baaa12c0): Process Detach fff00c89 |
netlib.narod.ru | < Назад | Оглавление | Далее > |