В этой главе.
Каждая программа должна обеспечивать пользователя справочной информацией. Существует два способа отображения справочной информации: классический (рис. 8.1, левый) и современный, в «интернет-стиле» (рис. 8.1, правый). Классический способ отображения справочной информации применяется большинством приложений, в том числе и C++ Builder. Отображение справочной информации в интернет-стиле используется в программных продуктах Microsoft и, в последнее время, в продуктах других разработчиков программного обеспечения.
Классическая справочная система представляет собой набор файлов, используя которые программа Winhelp, являющаяся составной частью Windows, выводит справочную информацию. Основой такой справочной системы являются hip-файлы.
Основой современной справочной системы являются chm-файлы. Chm-файл представляет собой компилированный HTML-документ, полученный путем компиляции (объединения) файлов, составляющих HTML-документ, в том числе и файлов иллюстраций.
Создать hip-файл можно при помощи утилиты Microsoft Help Workshop, которая входит в комплект C++ Builder (файл утилиты hce.exe находится в каталоге \CBuilder\Help\Tools). Chm-файл можно создать при помощи утилиты Microsoft HTML Help Workshop, которая, к сожалению, в состав C++ Builder не включена.
Рассмотрим процесс создания справочной системы, сначала классической, а затем — современной.
Четвертый borland с и его окружение d
Вы выбрали книгу «Четвертый Borland С++ и его окружение. Вахтеров М.». Вы можете совершенно бесплатно скачать эту книгу, но только для ознакомления и личного, не коммерческого использования. Ссылка на скачивание расположена ниже на странице.
Возможно, что у автора Вахтеров М. есть и другие книги в нашей электронной библиотеке. Если это так, то Вы можете их видеть в списке снизу данной страницы.
Для начала скачивания выберите сервер и нажмите ссылку «скачать»
Все книги запакованы архиватором RAR. Чем распаковать читайте тут. Внутри архива Вы найдёте файл(ы) книги, как открыть и просмотреть файл книги читайте здесь.
Все права на книги принадлежат их авторам. В случае если мы нарушаем авторские права, свяжитесь с нами через контакты
Четвертый borland с и его окружение d
Ниже представлена информация, которая будет полезной при разработке 16-разрядных приложений для работы в DOS.
Управление памятью в DOS
Нехватка памяти при выполнении
Borland С++ при компиляции не генерирует на диске никаких промежуточных структур данных (записывая на диск только файлы .OBJ). Вместо этого для хранения промежуточных структур данных между проходами используется оперативная память. Поэтому при недостаточном объеме оперативной памяти вам может выводиться сообщение о нехватке памяти. Чтобы решить эту проблему, уменьшите размер функций или разбейте файл с крупными функциями на несколько частей.
Модели памяти
В Borland С++ используется 6 моделей памяти, каждая из которых служит для различных размеров программ и кода. Регистры процессора
Ниже представлены некоторые регистры процессоров 80х86. Эти процессора имеют и другие регистры, но непосредственно к ним обращаться нельзя, поэтому они здесь не показаны.
Регистры общего назначения
Аккумулятор (математические операции) | ||
---|---|---|
AX | AH | AL |
Базовый регистр (индексирование) | ||
BX | BH | BL |
Счетчик (индексирование) | ||
CX | CH | CL |
Регистр данных | ||
DX | DH | DL |
Сегментные адресные регистры
CS | Сегментный регистр кода |
DS | Сегментный регистр данных |
SS | Указатель сегмента стека |
ES | Дополнительный регистр сегмента |
Регистры общего назначения
SP | Указатель стека |
BP | Указатель базы |
SI | Индекс источника |
DI | Индекс приемника |
Общие регистры чаще всего используются для работы с данными. Каждый из них выполняет некоторые специальные функции, которые доступны только ему, например, некоторые математические операции могут использовать только регистр AX, регистр BX может служить базовым регистром, CX применяется инструкцией LOOP и некоторыми строковыми инструкциями, а DX используется некоторыми математическими операциями неявно. Однако во многих операциях можно использовать все эти регистры и заменять один из них на другой.
Сегментные регистры содержат начальный адрес каждого из 4 сегментов. Как описывается ниже, 16-разрядное значение в сегментном регистре для получения 20-разрядного адреса сегмента сдвигается влево на 4 (умножается на 16).
Процессоры 80х86 имеют также некоторые специальные регистры:
- Регистры SI и DI могут выполнять многие функции общих регистров, но могут также использоваться в качестве индексных регистров. Они используются и в регистровых переменных Borland С++.
- Регистр SP указывает на текущую вершину стека и представляет смещение в сегменте стека.
- Регистр BP — это вспомогательный указатель стека, применяемый для индексирования в стеке с целью извлечения аргументов или локальных динамических переменных.
Функции Borland С++ используют регистр базы (BP) в качестве базового регистра для аргументов и переменных. Параметры имеют положительные смещения от BP, зависящие от модели памяти. При наличии кадра стека BP указывает на сохраненное предыдущее значение BP. Если параметр Standard Stack Frame выключен (Off), то функции без аргументов не используют и не сохраняют BP.
16-разрядный регистр флагов содержит все необходимую информацию о состоянии процессора 80х86 и результатах последних инструкций.
Например, если вы хотите знать, получен ли при вычитании нулевой результат, непосредственно после этой инструкции вам следует проверить флаг нуля (бит Z в регистре флагов). Если он установлен (то есть имеет ненулевое значение), это будет говорить о том, что результат нулевой. Другие флаги, такие, как флаги переноса и переполнения аналогичным образом сообщают о результатах арифметических и логических операций.
Прочие флаги управляют режимом операций процессора 80х86. Флаг направления управляет направлением, в котором строковые инструкции выполняют перемещение, а флаг прерывания управляет тем, будет ли разрешено внешним аппаратным средствам, таким, например, как клавиатура или модем, временно приостанавливать текущий код для выполнения функций, требующих немедленного обслуживания. Флаг перехвата используется только программным обеспечением, которое служит для отладки другого программного обеспечения (отладчики).
Регистр флагов не считывается и не модифицируется непосредственно. Вместо этого регистр флагов управляется в общем случае с помощью специальных инструкций (таких, как CLD, STI и CMC), а также с помощью арифметических и логических инструкций, модифицирующих отдельные флаги. И наоборот, содержимое отдельных разрядов регистра флагов влияет на выполнение инструкций (например, JZ, RCR и MOVSB). Регистр флагов не используется на самом деле, как ячейка памяти, вместо этого он служит для контроля за состоянием и управления процессором 8086.
Сегментация памяти
Память микропроцессора Intel 80×86 имеет сегментированную архитектуру. Непосредственно можно адресоваться к 64К памяти сегменту. Процессор 80×86 отслеживает 4 различных сегмента: сегмент кода, сегмент данных, сегмент стека и дополнительный сегмент. В сегменте кода находятся машинные инструкции, а в дополнительном сегменте — дополнительные данные. Процессор 80×86 имеет 4 16-разрядных сегмента (по одному на сегмент) — CS, DS, SS и ES, которые указывают на сегмент кода, данных, стека и дополнительный сегмент соответственно. Сегмент может находиться в любом месте памяти, но начинаться должен по адресу, кратному 10. Сегменты могут перекрываться. Например, все четыре сегмента могут начинаться с одного адреса.
Стандартная запись адреса имеет форму «сегмент:смещение», например, 2F84:0546. Начальный адрес сегмента всегда представляет собой 20-битовое число, но так как сегментный регистр содержит только 16 бит, нижние 4 бита полагаются равными 0. Это значит, что сегменты могут начинаться только с тех адресов, у которых последние 4 бита равны 0.
Указатели
Хотя указатель или функция могут иметь конкретный тип независимо от используемой модели, вы можете выбрать заданный по умолчанию тип указателя, используемый для кода и данных. Существует 4 типа указателей: near (16 бит), far (32 бита), huge (32 бита) и segment (16 бит).
В указателях near (ближние указатели) для вычисления адреса используется один сегментный регистр, например, 16-битовое значение указателя функции складывается со сдвинутым влево содержимым регистра кода CS. С такими указателями легко работать.
Указатели far (дальние указатели) содержат не только смещение в сегменте, но и адрес сегмента (другое 16-битовое значение). Такие указатели позволяют иметь несколько сегментов кода и программы, превышающие по размеру 64К. Здесь нужно учитывать, что в операциях == и != используются 32-битовые значения unsigned long, а не полный адрес памяти. В операциях сравнения =, используется только смещение.
При прибавлении к указателю значения изменяется только смещение. Если смещение превышает FFFF (максимально возможное значение), то указатель возвращается к началу сегмента. При сравнении указателей лучше использовать ближние указатели или указатели huge.
Указатели huge также занимают 32 бита. Аналогично указателям far, они содержат и адрес сегмента и смещение. Однако, чтобы избежать проблем с указателями, такие указатели нормализуются. Нормализованный указатель — это 32-битовый указатель с максимально возможным значением в сегментном адресе. Так как сегмент может начинаться с каждых 16 байт, это означает, что данное смещение будет иметь значение от 0 до 15. Для нормализации указателя он конвертируется в 20-битовый адрес, а затем используются правые 4 бита смещения и левые 16 бит адреса сегмента. Например, 2F84:0532 преобразуется в абсолютный адрес 2FD72, который нормализуется в 2FD7:0002. Нормализация важна по следующими причинам:
- Каждому сегментному адресу соответствует при этом только одна возможная адресная пара «сегмент:смещение». Это означает, что операции == и != возвращают корректный ответ.
- В операциях сравнения =, используется при этом полные 32-битовые значения. Нормализация обеспечивает корректность результатов.
- Благодаря нормализации смещение в указателях huge автоматически циклически возвращаются каждые 16 байт, но настраивается также и сегмент. Например, при инкрементации 811B:000F результатом будет 811C:0000. Это обеспечивает, что, например, при наличии массива структур типа huge > 64К индексирование массива и выбор поля struct будет работать для структур любого размера.
Однако работа с указателями huge связана с дополнительными издержками. Из-за этого арифметические операции с указателями huge выполняются намного медленнее, чем с указателями far.
Модели памяти
В 16-разрядных программах Borland С++ вы можете использовать 6 моделей памяти: крохотную, малую, среднюю, компактную, большую и огромную.
- Tiny (крохотная). Эта модель памяти используется в тех случаях, когда абсолютным критерием достоинства программы является размер ее загрузочного кода. Это минимальная из моделей памяти. Все четыре сегментных регистра (CS, DS, SS и ES) устанавливаются на один и тот же адрес, что дает общий размер кода, данных и стека, равный 64К. Используются исключительно ближние указатели. Программы со сверхмалой моделью памяти можно преобразовать к формату .COM (при компоновке с параметром /t).
- Small (малая). Эта модель хорошо подходит для небольших прикладных программ. Сегменты кода и данных расположены отдельно друг от друга и не перекрываются, что позволяет иметь 64К кода программы и 64К данных и стека. Используются только указатели near.
- Medium (средняя). Эта модель годится для больших программ, для которых не требуется держать в памяти большой объем данных. Для кода, но не для данных используются указатели far. В результате данные плюс стек ограничены размером 64К, а код может занимать до 1М.
- Compact (компактная). Лучше всего использовать эту модель в тех случаях, когда размер кода невелик, но требуется адресация большого объема данных. Указатели far используются для данных, но не для кода. Следовательно, код здесь ограничен 64К, а предельный размер данных — 1 Мб.
- Large (большая). Модели large и huge применяются только в очень больших программах. Дальние указатели используются как для кода, так и для данных, что дает предельный размер 1 Мб для обоих.
- Huge (огромная). Дальние указатели используются как для кода, так и для данных. Borland C++ обычно ограничивает размер статических данных 64К; модель памяти huge отменяет это ограничение, позволяя статическим данным занимать более 64К.
Для выбора любой из этих моделей памяти вы должны либо воспользоваться соответствующим параметром меню интегрированной среды, либо ввести параметр при запуске компилятора, работающего в режиме командной строки.
Следующие иллюстрации показывают, как выполняется распределение памяти для всех шести моделей памяти Borland C++.
Сегментация для модели памяти tiny
Сегментация для модели памяти small
Сегментация для модели памяти medium
Сегментация для модели памяти compact
Сегментация для модели памяти large
Сегментация для модели памяти Huge
В следующей таблице сведены различные модели и их сравнение друг с другом. Модели часто группируются по модели кода или данных на малые (64К) и большие (16М); эти группы соответственно отражены в столбцах и строках таблицы.
Модели tiny, small и compact относятся к малым моделям кода, поскольку по умолчанию указатели кода являются ближними (near). Аналогичным образом, модели compact, large huge относятся к большим моделями данных, поскольку по умолчанию указатели на данные являются дальними (far).
Модели памяти
При компиляции модуля (некоторый исходный файл с несколькими подпрограммами), результирующий код для этого модуля не может превышать 64К, поскольку весь файл должен компилироваться в один кодовый сегмент. Это верно и в том случае, когда вы используете одну из больших моделей памяти (medium, large или huge). Если ваш модуль слишком велик и не помещается в одном кодовом сегменте (64К), вы должны разбить его на несколько файлов исходного кода, скомпилировать каждый из них по отдельности и затем скомпоновать их в одну программу. Аналогичным образом, хотя модель huge и позволяет иметь размер статических данных больше чем 64К, в каждом отдельном модуле статические данные не должны превышать 64К.
Программирование со смешанными моделями и модификаторы адресации
Borland C ++ вводит восемь новых ключевых слов, отсутствующих в языке Си стандарта ANSI (near, far, huge, _cs, _ds, _es, _ss и _seg), которые с некоторыми ограничениями и предупреждениями могут использоваться в качестве модификаторов для указателей (и в некоторых случаях, для функций).
В Borland C++ при помощи ключевых слов near, far или huge вы можете модифицировать объявления функций и указателей. Указатели данных near, far и huge рассматривались в выше. Объекты far объявляются при помощи ключевого слова far. Функции near запускаются при помощи ближних вызовов (near), а выход из них происходит с использованием ближних команд возврата. Аналогичным образом, функции far вызываются дальними вызовами (far) и выполняют дальний (far) возврат. Функции huge похожи на функции far, за исключением того, что функции huge устанавливают регистр DS в новое значение, тогда как функции far не изменяют значения этого регистра.
Существует также четыре специальных ближних (near) указателя данных: __cs, __ds, __es и __ss. Имеются 16-битовые указатели, конкретно связанные с соответствующими сегментными регистрами. Например, если вы объявите указатель следующим образом: то p будет содержать 16-битовое смещение в сегмент стека.
Функции и указатели в данной программе по умолчанию бывают ближними или дальними, в зависимости от выбранной модели памяти. Если функция или указатель являются ближними, то они автоматически связываются с регистром CS или DS.
В следующей таблице показано, как это происходит. Отметим, что размер указателя соответствует предельному размеру памяти, равному 64К (ближний, в пределах сегмента) или 1 Мб (дальний, содержит собственный адрес сегмента).
Типы указателей
Модель памяти | Указатели функции | Указатели данных |
---|---|---|
Tiny | near, _cs | near, _ds |
Small | near, _cs | near, _ds |
Medium | far | near, _ds |
Compact | near, _cs | far |
Large | far | far |
Huge | far | far |
Указатели сегментов
В объявлениях типа указателя сегмента используется __seg. В результате получаются 16-битовые указатели сегментов. Синтаксис __seg следующий: Например,
Любое обращение по ссылке через «идентификатор» предполагает смещение 0. В арифметических операциях с указателями выполняются следующие правила:
- Нельзя использовать с указателями сегментов операции ++, —, +- или -=.
- Нельзя вычитать один указатель сегмента из другого.
- При сложении сегментного указателя с ближним (near) указателем результатом будет дальний (far) указатель, который формируется из сегмента, задаваемого сегментным указателем, и смещения из ближнего указателя. Эта операция разрешена только в том случае, если два указателя указывают на один и тот же тип, либо если один из указателей указывает на тип vo > Borland С++ позволяет объявлять дальние (far) объекты. Например:
Компилятор Borland C++ создает для каждого дальнего объекта отдельный сегмент. Параметры компилятора командной строки -zE, -zF и -zH (которые могут также задаваться директивой #pragma option) влияют на имя, класс и группу дальнего сегмента, соответственно. Изменяя эти значения при помощи указания #pragma option, вы тем самым распространяете новые установки на все объявления дальних объектов. Таким образом, для создания в конкретном сегменте дальнего объекта, можно использовать следующую последовательность:
Тем самым x будет помещен в сегмент MYSEGMENT с классом ‘MY > И x, и y окажутся в сегменте COMBINED ‘MY > В некоторых случаях вам может потребоваться переопределить заданное по умолчание значение типа функции для модели памяти. Например, вы используете модель памяти large, и в программе имеется рекурсивная функция:
Каждый раз, когда функция power вызывает сама себя, она должна выполнить дальний вызов, причем используется дополнительное пространства стека и число тактовых циклов. Объявив power как near, можно ускорить выполнение ее благодаря тому, что вызовы этой функции будут ближними:
Это гарантирует, что функция power может вызываться только из того кодового сегмента, в котором она компилировалась, и что все обращения к ней будут ближними.
Это означает, что при использовании большой модели памяти (medium, large или huge) функцию power можно вызывать только из того модуля, в котором она определена. Прочие модули имеют свои собственные кодовые сегменты и не могут вызывать функции near из других модулей. Более того, ближняя функция до первого к ней обращения должна быть либо определена, либо объявлена, иначе компилятор не знает о необходимости генерировать ближний вызов.
И наоборот, объявление функции как дальней означает генерацию дальнего возврата. В малых моделях кодовой памяти дальняя функция должна быть объявлена или определена до первого к ней обращения, что обеспечит дальний вызов.
Вернемся к примеру функции power. Хорошо также объявить power как static, поскольку предусматривается вызывать ее только из текущего модуля. Если функция будет объявлена как static, то имя ее не будет доступно ни одной функции вне данного модуля.
Объявление указателей near, far или huge
Только что были рассмотрены случаи, в которых может понадобиться объявить функцию с другой моделью памяти, нежели остальная часть программы. Зачем то же самое может понадобиться для указателей? По тем же причинам, что и для функций: либо для улучшения характеристик быстродействия (объявив __near там, где по умолчанию было бы __far), либо для ссылки за пределы сегмента по умолчанию (объявив __far или __huge там, где по умолчанию бывает __near).
Разумеется, при объявлении функций или указателей с другим типом, нежели используемый по умолчанию, потенциально появляется возможность ошибок. Предположим, имеется следующий пример программы с моделью small:
Эта программа работает удовлетворительно, хотя объявление mystr как __near избыточно, поскольку все указатели, как кода, так и данных, будут ближними (near) по умолчанию.
Однако, что произойдет, если перекомпилировать эту программу с моделью памяти compact (либо large или huge)? Указатель mystr в функции main останется ближним (16-битовым). Однако, указатель s в функции myputs теперь будет дальним (far), поскольку по умолчанию теперь используется far. Это означает, что попытка создания дальнего указателя приведет к извлечению из стека двух слов, и полученный таким образом адрес, безусловно, не будет являться адресом функции mystr.
Как избежать этой проблемы? Решение состоит в том, чтобы определить myputs в современном стиле Си:
Теперь при компиляции вашей программы Borland C++ знает, что myputs ожидает указатель на char. Поскольку компиляция выполняется с моделью large, то известно, что указатель должен быть __far. Вследствие этого Borland C++ поместит в стек регистр сегмента данных (DS) и 16-битовое значение mystr, образуя тем самым дальний указатель.
Если вы собираетесь явно объявлять указатели как far или near, не забывайте использовать прототипы тех функций, которые могут работать с этими указателями.
Как быть в обратном случае: когда аргументы myputs объявлены как __far, а компиляция выполняется с моделью памяти small? И в этом случае без прототипа функции у вас возникнут проблемы, поскольку функция main будет помещать в стек и смещение, и адрес сегмента, тогда как myputs будет ожидать приема только одного смещения. При наличии определений функций в прототипах main будет помещать в стек только смещение.
Создание указателя данного адреса «сегмент:смещение»
Как создать дальний указатель на конкретный адрес памяти (конкретный адрес «сегмент:смещение»)? Для этого можно воспользоваться встроенной библиотечной подпрограммой MK_FP, которая в качестве аргумента воспринимает сегмент и смещение, и возвращает дальний указатель. Например:
Имея дальний указатель fp, вы можете получить значение сегмента полного адреса с помощью FP_SEG(fp) и значение смещения с помощью FP_OFF(fp). Более полную информацию об этих трех библиотечных функциях Borland C++ можно найти в справочнике по библиотеке.
Использование библиотечных файлов
Borland C++ предлагает для каждой из шести моделей памяти собственную версию библиотеки стандартных подпрограмм. Компилятор Borland C++ при этом проявляет достаточно «интеллекта», чтобы при последующей компоновке брать нужные библиотеки и в нужной последовательности, в зависимости от выбранной вами модели памяти. Однако, при непосредственном использовании компоновщика Borland C++ TLINK (как автономного компоновщика) вы должны явно указывать используемые библиотеки.
Компоновка смешанных модулей
Что произойдет, если вы компилируете один модуль с использованием модели памяти small (малая), второй — модели large (большая), и затем хотите скомпоновать их? Что при этом произойдет?
Файлы скомпонуются удовлетворительно, но при этом вы столкнетесь с проблемами. Если функция модуля с моделью small вызывает функцию в модуле с моделью large, она будет использовать при этом ближний вызов, что даст абсолютно неверные результаты. Кроме того, у вас возникнут проблемы с указателями, описанные в разделе «Объявление указателей как near, far или huge», поскольку функция в модуле small ожидает, что принимаемые и передаваемые ей указатели будут __near, тогда как функция в модуле large ожидает работу с указателями __far.
И снова решение заключается в использовании прототипов функций. Предположим, что вы поместили myputs в отдельный модуль и скомпилировали его с моделью памяти large. Затем вы создаете файл заголовка myputs.h (либо с любым другим именем и расширением .h), который содержит следующий прототип функции:
Теперь, если поместить функцию main в отдельный модуль (MYMAIN.C) и выполнить следующие установки:
то при компиляции данной программы Borland C++ считает прототип функции из файла MYPUTS.H и увидит, что это функция __far, ожидающая указатель __far. В результате этого даже при модели памяти small при компиляции будет сгенерирован правильный вызывающий код.
Как быть, если помимо этого вам требуется компоновка с библиотечными подпрограммами? Лучший подход здесь заключается в том, чтобы выбрать одну из библиотек с моделью large и объявить все как far. Для этого сделайте копии всех файлов заголовка, которые вы обычно включаете (таких, как stdio.h) и переименуйте эти копии (например, fstdio.h).
Затем отредактируйте копии прототипов функций таким образом, чтобы там было явно указано far, например:
Тем самым, не только вызовы подпрограмм будут дальними, но и передаваемые указатели также будут дальними. Модифицируйте вашу программу таким образом, чтобы она включала новый файл заголовка:
Четвертый borland с и его окружение d
Четвертый BORLAND С++ и его окружение
Настоящий «мгновенный» курс C++ в сжатой и всеобъемлющей форме представляет программирование на С++, прежде всего, для программистов, владеющих основами традиционного Си, и дает возможность совершить быстрый переход к С++.
При отсутствии опыта работы с Cи и С++, возможно, по-началу, могут показаться трудными новые концепции, обсуждаемые здесь, но разбор (и эксперименты) с примерами помогут прояснить картину. Прежде, чем начать работу, окружите себя уже имеющимися у Вас учебными пособиями и руководствами по С++. Возможно одно из них пригодится для более детального изучения С++.
Несмотря на то, что каждая тема с помощью примеров и подробных разъяснений раскрывает основные идеи языка, для желающих стать настоящими хакерами рекомендуется дополнительно проработать книги Страуструпа.
Компилируем, как будто на дворе 1992 год
Я изучал ванильный исходный код игры Wolfenstein 3D 1992 года. Несмотря на то, что ей уже 25 лет, и она совершенно устарела для современных платформ, её всё равно можно скомпилировать, если воссоздать окружение.
Для этого требуется всего лишь:
- Исходный код Wolfenstein 3D.
- DosBox.
- Компилятор Borland C++ 3.1.
- Wolfenstein 3D shareware (чтобы позаимствовать ресурсы).
Настройка файловой системы
Откроем командную строку и создадим две папки, по одной для каждого из необходимых дисков DOS:
Скачиваем файлы
- Скачиваем Borland 3.1 в system/a .
- Скачиваем исходный код Wolfenstein 3D в system/c
- Скачиваем файлы VGA в system/c (в конце статьи я объясню, зачем это нужно).
Теперь все файлы находятся в файловой системе. Просто чтобы проверить, введём:
У вас должно получиться следующее:
Распаковываем всё
DosBox
Скачаем и запустим DosBox:
Монтируем
Смонтируем файловую систему, по одной папке для каждого из дисков:
Устанавливаем компилятор
Настало время установить Borland C++ 3.1:
Нажмите «ввод» при выборе исходного диска (должен быть выбран диск A)
Оставим все параметры по умолчанию и выберем «Start Installation»:
Уведомления предупреждают, что не удаётся найти папку Microsoft Windows, но она нам не нужна, просто нажмём «ввод».
Устанавливаем исходный код Wolfenstein 3D
Система работает и в ней есть компилятор: настало время распаковывать (снова) исходный код.
Оставим путь по умолчанию: \WOLFSRC
Подтвердим («Y») создание директории.
Компилируем
Запускаем Borland C++ 3.1:
После нажатия на OK, используем мышь или горячие клавиши, чтобы выбрать Project → Open Project ..\..\WOLFSRC\WOLF3D.PRJ :
Выберем Options → Directories и изменим значение следующим образом:
Попробуем скомпилировать: Compile -> Build All
Мы получим ошибку: «Cannot find executable TASM»
Выйдем из Borland C++, нужно настроить PATH:
Снова попробуем скомпилировать (Compile -> Build All):
Компилирование выполнилось, но возникла ошибка компоновки: «Unable to find OBJ file», потому что путь к SIGNON.OBJ и GAMEPAL.OBJ в проекте указан неверно.
Они отмечены в C:\SOURCE\WOLF\ :
Удаляем их из проекта (Выберем Projext → Delete item). Добавим их снова через PROJECT → Add Item…. Добавляем WOLFSRC\OBJ\SIGNON.OBJ и WOLFSRC\OBJ\GAMEPAL.OBJ
Попробуем скомпилировать снова (Compile → Build All)
Сработало! Но запустится ли игра?
Достаём ресурсы
Скачайте shareware-версию, или даже лучше: купите как полную версию Wolfenstein 3D.
Вернёмся в DosBox и установим игру в C:\WOLF3D .
После установки игры скопируем только что скомпилированный файл .EXE в папку игры,
Запускаем игру
Хм, выглядит странно…
Не припомню, чтобы игра была такой…
Так, где-то возникла ошибка!
Что случилось?
Дело в конвейере производства игры и в том, как он использовался движком. Когда Адриан Кармак и Кевин Клауд заканчивали работу над всеми графическими файлами, они использовали инструмент IGRABed для их упаковки. В результате получалось 3+2 файла.
- VGAHEAD.WL1
- VGAGRAPH.WL1
- VGADICT.WL1
Файл VGAHEAD — это индекс, содержащий указатели на VGAGRAPH, в котором хранятся данные, сжатые алгоритмом Хаффмана. VGADICT содержит словари Хаффмана для распаковки данных.
Два других созданных файла:
- GRE.H
- GRE.EQU
компилируются в движок, как показано на рисунке ниже:
Для чего нужны файлы .H и .EQU ? Если вкратце, то они позволяют получать доступ по имени. Когда IGRABed собирает все файлы, он также создаёт перечисление (enum) с соответствующими индексами:
Таким образом, когда движок запрашивает нужный ресурс, он может использовать логическое имя (L_GUYPIC), а не «магическое число» (2).
Это значит, что движок выпускался с жёстко заданными индексами изображений в файлах VGA. Поскольку ресурсы и база кода эволюционировали после выпуска wolf3D shareware (в Spear of Destiny), новые скомпилированные индексы игры не совпадают с расположением исходных файлов ресурсов.
Запускаем игру (снова)
К счастью, у этой проблемы есть простое решение: кто-то сгенерировал ресурсы VGA заново, чтобы они совпадали с индексами в файлах .H и .EQU, выпущенных с исходным кодом. Просто скопируем эти файлы (если вы используете ресурсы из shareware-версии, то нужно будет изменить расширение файлов с .WL6 на .WL1).
Но мы всё ещё не закончили!
Буфер кадров VGA и соотношение сторон экрана
Это может быть неочевидно для людей, никогда не видевших оригинальную игру, но представленная выше картинка из DosBox не совсем совпадает с тем, что видели игроки в 1992 году. Буфер кадров VGA имел размер 320×200, но у ЭЛТ-мониторов соотношение сторон равно 4:3. Это значит, что буфер кадров при отправке на монитор вертикально растягивался. В DosBox есть опция для компенсации этого:
Поменяем значение aspect на true.
Borland C++
Borland C++ | |||||||||||
Описание | Среда разработки от Borland на языке C++ | Раздел: C/C++ Скриншоты Операционная система: — Требования: — Автор: Borland Издатель: — |
|||||||||
Доступные файлы — сортировка по имени и версии, времени добавления Файлов: 21.
|
1992 | Английский | SR | ||||||||
Portable. Works from directory C:\BC\ | |||||||||||
|
3.1 | SR 2009.06.21 |
|||||||||
|
1991 | Английский | Login 2011.11.03 |
||||||||
|
1992 | Английский | Login 2011.11.03 |
||||||||
2297 |
2011.11.03
2011.11.03
Некоторые считают, что их должно было быть 27.
SokilOff пишет:
27-я дискета действительно была — там находился Microsoft Win32s 1.20
Borland C++ Compiler | |
5383 |
2012.01.11
Borland C++ | |
4048 |
2012.05.27
Borland C++ | |
2833 |
2012.06.28
Borland C++ & Application Frameworks | |
1299 |
2012.08.26
Borland C++ | |
1259 |
2012.08.26
Borland C++ | |
2792 |
2012.10.14
Borland C++ | |
997 |
2012.11.04
Borland C++ | |
2518 |
2012.11.16
2014.09.30
2014.09.30
Библиотека системного программиста, том 12
(C) Фролов А.В., Фролов Г.В., 1994 ДИСКЕТА С ПРИМЕРАМИ ПРОГРАММ На этой дискете записаны исходные тексты приложений, приведенных в книге
в качестве примеров. В каждом каталоге имеется prj-файл для транслятора
Borland Turbo C++ 3.1 и готовые загрузочные модули. Все программы, записанные на дискете, могут свободно копироваться
и распространяться, но только все вместе и в неизменном виде. Вы можете разместить их в бесплатных BBS.
Платное распространение возможно только с письменного согласия авторов. Вы можете прислать свои замечания и предложения относительно содержания
книг серии «Библиотека системного программиста» через электронную почту: frolov@glas.apc.org. Ваши замечания будут обязательно учтены при подготовке новых книг серии.
Заранее благодарны всем, приславшим отклики. Фролов А.В., Фролов Г.В.
2015.05.08
Проверенная рабочая версия.
2015.05.08
Borland C++ & Application Frameworks | |
778 |
2015.09.27
Borland C++ 3.1 & Application Frameworks | |
709 |
2020.08.23
Borland C++ | |
394 |
2020.08.05
Комментарии | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Ближайшие планы развития средств разработки и СУБДЕсли принять во внимание оглашенные на семинаре и последующей пресс-конференции планы развития средств разработки и СУБД, то достаточно сложно представить себе закрытие подобного направления. Эти планы включают создание новых версий Delphi, предназначенных для .NET Framework 2.0, Windows Vista, 64-разрядных версий Windows, версии JBuilder 2007, основанной на платформе Eclipse, а также для ряда новых версий СУБД Interbase. Borland Developer StudioГоворя о планах развития Borland Developer Studio (включающего Delphi, C++Builder и C#Builder), в первую очередь стоит отметить, что компания Borland считает одним из важнейших стратегических направлений развития средств разработки для Windows поддержку платформы Win32 (для которой, собственно, и написаны российскими разработчиками вышеупомянутые миллионы строк кода) и дальнейшего развития библиотеки VCL (Visual Component Library) с целью создания ее версий для различных платформ. В планах компании — бесшовная миграция библиотеки VCL с платформы Win32 на Windows Vista (после выхода последней), поддержка библиотекой VCL платформ .NET Framework 2.0 и .NET Compact Framework, а также создание версий Delphi и C++Builder для 64-разрядных версий Windows. Кроме того, следует ожидать и дальнейшего развития такого перспективного направления, как разработка приложений на основе UML-моделей, включая поддержку выполнения приложений в соответствии с диаграммами состояний и поддержку реализации ECO-приложений с помощью библиотеки VCL для .NET. Отметим также, что применение технологии ECO (Enterprise Core Objects) вскоре будет доступно пользователям всех редакций Delphi и C++Builder (рис. 1). Рис. 1. Ближайшие планы развития Borland Developer Studio JBuilderJBuilder довольно давно занимает лидирующие позиции на рынке средств разработки Java-приложений, и этому не помешал даже все тот же вышеупомянутый пресс-релиз. Так, согласно проведенному в начале этого года исследовательской компанией Evans Data Corp опросу почти 800 разработчиков, Borland JBuilder был признан обладающим лучшими и самыми высокопроизводительными компилятором, отладчиком и оптимизатором, что дало повод авторам отчета высказаться в пользу приобретения инструментов разработки Borland корпорацией Oracle, чьи собственные инструменты оказались в аутсайдерах опроса. В планах дальнейшего развития JBuilder — выпуск обновлений имеющейся версии, в том числе и для свободно доступной для загрузки редакции JBuilder Foundation, а также создание новой версии JBuilder на основе набирающей популярность платформы Eclipse (рис. 2). Рис. 2. Ближайшие планы развития Borland JBuilder Опытные пользователи JBuilder, возможно, помнят, что первая среда разработки JBuilder была создана с помощью Delphi, а вскоре была разработана среда, написанная полностью на языке Java и считавшаяся одним из лучших продуктов, написанных на этом языке (рис. 3). Так для чего же понадобилось в очередной раз менять платформу, на которой основан JBuilder? Рис. 3. Эволюция сред разработки JBuilder Проект Eclipse был начат в 1998 году корпорацией IBM, поставившей перед собой цель создать интегрированную среду Java-разработки нового поколения и предоставившей сообществу Open Source часть исходного кода своего средства разработки Java-приложений Websphere Studio Workbench. Сегодня, по прошествии пяти лет с момента создания, платформа Eclipse стала настолько популярной, что начала вытеснять с рынка широко применявшиеся коммерческие инструменты. Основные причины популярности Eclipse состоят не только в относительно невысокой стоимости инструментов, основанных на данной платформе, но и в широком выборе модулей расширения для нее, равно как и коммерческих продуктов на ее основе. На данный момент проект Eclipse является одним из лидирующих направлений развития рынка средств разработки, при этом компания Borland имеет статус стратегического разработчика организации Eclipse Foundation. Отметим, однако, что перенос JBuilder на платформу Eclipse обусловлен не только и не столько желанием компании Borland следовать современным тенденциям и продолжать оказывать заметное влияние на их формирование, сколько неоспоримыми преимуществами, которые в этом случае получат пользователи продукта. Так, наличие огромного количества инструментов для Eclipse (как коммерческих, так и с открытым кодом) для поддержки коллективной разработки, тестирования, моделирования, бизнес-анализа и создания отчетов, визуального создания Web-служб и компонентов Enterprise Java Beans позволит каждому разработчику организовать максимально удобную среду разработки приложений, содержащую всю функциональность, требующуюся для решения конкретных задач. InterbaseВ планах развития СУБД InterBase — создание в ближайшее время 8-й версии, поддерживающей двухбайтные строковые данные и позволяющей осуществлять резервное копирование путем обновления предыдущей копии (incremental backup), а затем — версии 8.5 с поддержкой создания серверного кода на языке Java и средствами, упрощающими использование этой СУБД в качестве составной части решений независимых разработчиков. В 2007 году ожидается выпуск 9-й версии, отличающейся поддержкой написания кода на .NET-совместимых языках и расширенными средствами поддержки защиты данных (рис. 4). Рис. 4. Ближайшие планы развития Borland Interbase Вместо заключенияИтак, слухи о скорой кончине Delphi, C++Builder и Interbase оказались, мягко говоря, преувеличенными, а февральская новость от Borland, к счастью, была не столь пугающей, как это могло показаться на первый взгляд. Возможно, все это даже к лучшему: отделение IDE-подразделения от большой компании, ориентированной на крупных заказчиков и гигантские проекты, позволит ему сосредоточиться на задачах и потребностях разработчиков, а не многочисленных менеджеров, пытающихся управлять их работой. Впрочем, поживем — увидим. Borland C++ Builder 6 для начинающих (статья четвертая)Borland C++ Builder 6 для начинающих (статья четвертая) При разработке программ, особенно в первое время, возможны синтаксические и логические ошибки. Чем сложнее программа, тем труднее их обнаружить. Для облегчения обнаружения и устранения ошибок в среде разработки Borland C++ Builder 6 существует встроенный отладчик программ. Он позволяет выполнять программу по шагам, устанавливать точки останова, просматривать переменные и производить другие операции. ОТЛАДКА ПРОГРАММ Теперь замените свойство Caption всех объектов приложения в инспекторе объектов на заголовки Программа 2, Кнопка 1, Выход и пустую строку соответственно. В результате у вас должно получиться окно, приведенное на рис. 2. Обратите внимание, что элемента Labell, располагающегося выше кнопок, не видно, поскольку мы заменили его свойство Caption на пустую строку, т. е. очистили это свойство. Щелкните дважды левой кнопкой мыши по созданной кнопке Выход и в открывшемся окне инспектора кодов впишите между фигурными скобками заготовки обработчика события команду закрытия приложения CloseQ;. Вернитесь к окну формы и щелкните дважды левой кнопкой мыши по кнопке с названием Кнопка 1. В отрывшемся окне инспектора кодов впишите между фигурными скобками строку команд: Label1->Caption=»Кнопка 1 нажата » + IntToStr(++i) +» раз»; В этой строке команд выполняется присвоение (знак равенства) свойству Caption элемента надписи Label 1 текстовой строчки, состоящей из трех слагаемых частей. Поскольку свойство Caption элемента надписи Labell предназначено для отображения текста, мы должны присваивать этому свойству только текстовые (строковые) значения. В языке C++ такие строковые значения заключаются в кавычки. Первая и последняя части присваиваемого значения таковыми и являются. Счетчиком числа нажатий на кнопку в программе будет служить переменная i, которая должна автоматически увеличиваться на единичку перед выводом. Для этой цели перед ней записаны два знака плюс. Данная операция в языке C++ называется автоинкрементом. Для превращения числовой переменной i в строковую используется встроенная функция C++ преобразования целых чисел в строки IntToStrQ. Итак, в одной строке команд мы осуществили целый ряд операций. Разве это не изящный язык программирования?! В верхней строке этого окна отображается путь размещения и имя проекта программы. В следующей строке вначале отображается процесс компиляции, сменяющийся записью о завершении данной операции Done и сообщением об обнаруженных ошибках There are errors (здесь есть ошибки). Ниже отображается номер текущей строки программы Current line и общее количество арок программы Total line. В нижней строке отображается обнаруженное на данный момент число замечаний Hints, предупреждений Warnings и ошибок Errors. Как видим, в программе есть одна ошибка. Нажмите кнопку ОК в окне, и перед вами окажется окно инспектора кода с выделенной строкой, имеющей ошибку, и сообщением о типе ошибки внизу окна (рис. 4). Сообщение «[C++ Error] Ubutct.cpp(25): E2451 Undefined symbol ‘i’» говорит о том, что компилятор C++ обнаружил ошибку в 21-й строке модуля Ubutct.cpp. Код ошибки Е2451 означает, что обнаружен необъявленный символ. В нашем случае это переменная с именем i. Действительно, мы не объявили ее в программе, хотя и сделали это намеренно, с целью получения сообщения об ошибке в качестве примера. В языке C++, как впрочем и в других языках программирования, все переменные, используемые в программе, необходимо объявлять. Это делается для того, чтобы компилятор знал, сколько ячеек памяти необходимо резервировать в памяти компьютера для ее хранения. Поскольку различные типы переменных требуют для своего хранения различное количество ячеек памяти (байт), рационально резервировать для них лишь необходимый объем памяти. В нашем случае переменная i является целой, т. е. принимающей только целочисленные значения. Для ее объявления необходимо использовать директиву int (от integer — целый). Можно сделать такое объявление непосредственно в тексте программы обработчика событий, но тогда эта переменная будет недоступна в Других функциях обработчика. Поэтому мы объявим ее в блоке public (общедоступный) файла описания заголовков Ubutct.h. Для этого необходимо щелкнуть левой кнопкой мыши по закладке Ubutct.h инспектора кодов и вписать строку объявления переменной с комментариями сразу же после строчки public. Ниже приведена эта запись полностью. Теперь снова выполним компиляцию и обнаружим, что ошибок нет. Но не спешите радоваться. Дело в том, что мы не присвоили переменной i начального значения. Компилятор не обращает на это внимания и не выдает никаких сообщений по этому поводу. Однако в программе это может привести к недоразумениям. Поэтому выполним присвоение начального значения переменой i, сделав запись i=0; в тексте программы обработчика создания формы (ведь при запуске программы Кнопка 1 не была нажата ни разу). Для этого щелкните дважды левой кнопкой мыши по форме приложения и в открывшемся окне инспектора кода впишите между фигурными скобками текста программы строку Выполним компоновку проекта с помощью команды Make из группы Project главного меню или просто нажав «горячую» комбинацию клавиш для компоновки программы Ctrl+F9. В результате мы должны получить безошибочную компоновку приложения. Теперь приложение можно сохранить и запустить на выполнение с помощью команды Run или воспользоваться «горячей» кнопкой запуска программы F9. СТРУКТУРА ФАЙЛОВ В этих нескольких строчках содержатся директивы и команды, с помощью которых формируется программа. Строчки, начинающиеся с символов //, являются строками комментариев для разделения или снабжения текстовым описанием частей программы. В языке С допускается также заключать комментарии между символами I* и */. В этом случае комментарии могут состоять из нескольких строк, заключенных между этими символами. Строка #include является строкой препроцессора, т. е. программы, которая будет подключать к нашим модулям дополнительные файлы библиотек и описаний. В данном случае строка #include говорит препроцессору о том, что ему необходимо подключить к нашей программе заголовочный файл vclh, в котором содержатся описания визуальных компонентов Borland C++ Builder. Директива #pragma hdrstop завершает список файлов заголовка для препроцессора. Строка макрокоманды USEFORMC^’Ubutct.cpp», Forml); подключает к проекту модуль Ubutctcpp и форму Forml. Далее следует заголовок программы главной функции проекта WINAPI WinMain(HINSTANCE, H1NSTANCE, LPSTR, int). Перед названием главной функции находится дескриптор W1NAPI, который позволяет использовать множество полезных готовых функций Windows в нашем приложении. В скобках заключены параметры главной функции, необходимые для опознания нашего приложения среди множества других работающих приложений, передачи параметров в программу в командной строке и для определения конфигурации окна нашего приложения. После заголовка главной функции следует блок кода, в котором может произойти исключение — аварийная ситуация (останов, ошибка программы и пр.). Такой блок должен начинаться с ключевого слова try. В этом блоке заключены операторы инициализации компонентов приложения Application->Initialize();, создания формы приложения Application Большинство строк этого файла нам уже известно из предыдущего описания и самого примера программы. Рассмотрим лишь неизвестные строки. Строка #pragma package(smart_init) определяет последовательность инициализации составных частей программы. Строка #pragma resource «*.dfm» сообщает препроцессору о том, что для формы необходимо использовать файл *.dfrn с именем данного файла. В строке TForml *Forml; объявляется класс TForml для формы Forml. Далее следуют подпрограммы создания формы приложения и обработчики событий, рассмотренные выше. #ifndef UbutctH История BorlandКомпания Borland International была основана в 1983 г . Филиппом Каном, являвшимся на тот момент ее единственным сотрудником. Два ее главных продукта середины 80-х — Turbo Pascal и Turbo Basic, а их основные конкуренты — аналогичные инструменты Microsoft. Затем появились Turbo Assembler и Turbo Debugger. В 1989 г . в результате неявного мирового соглашения Borland отказалась от поддержки Basic, а Microsoft — от Pascal. Примерно в эти же годы Borland выпускает TurboVision — один из первых прообразов нынешних визуальных сред разработки, но тогда еще в DOS-исполнении. В начале 90-х Borland пытается создать свой офисный пакет на основе довольно популярных в то время электронных таблиц QuattroPro собственной разработки и приобретенного в 1993 г . текстового процессора WordPerfect. Однако уже в 1994-м эти приложения были проданы Novell, которая еще два года спустя перепродала их Corel. В тот период в течение нескольких лет Borland занималась продвижением своих баз данных — сначала dBase, затем Visual dBase, а также семейства Paradox. В 1994 г . была выпущена первая версия самого популярного продукта компании всех последних лет — Delphi. В апреле 1998 г . Borland приняла решение о смене названия на Inprise (Integration the Enterprise — интеграция предприятий), что должно было подчеркнуть новый стратегический курс на корпоративных клиентов. Это внесло смятение в ряды пользователей ее инструментов (неясно было, в каком направлении пойдет развитие этих средств), которое усиливалось нестабильностью финансовых результатов Borland на протяжении предыдущих пяти лет. В феврале 2000 г . было объявлено о слиянии Inprise и Corel, однако уже в мае это соглашение было разорвано. В ноябре 2000-го корпорация вернула себе название Borland Software. Летом того же года ее президентом и CEO был избран Дейл Фуллер, с именем которого связана выработка нового курса компании. В апреле 2003 г . была официально представлена стратегия Borland на создание полномасштабной ALM-платформы. Реализация этой идеи должна была осуществляться в соответствии с корпоративным лозунгом «Двигаться в будущее, не отказываясь от прошлого», подразумевавшим, что для построения такой системы будут использоваться имеющиеся в арсенале компании продукты. К этому моменту Borland обладала представительным набором средств разработки: Delphi, C++Builder, Kylix (разработка программ на Linux в стиле Delphi), JBuilder (RAD-средство для технологии Java 2 Enterprise Edition) — и еще рядом решений, в том числе сервером приложений AppServer (сочетание технологий J2EE и VisiBroker CORBA) и СУБД InterBase. Кроме того, компания быстро пополняла свой арсенал инструментами, покрывающими весь процесс создания ПО — от выработки требований до сопровождения, причем делала это в основном путем приобретения соответствующих специализированных фирм (за один 2002-й год — шесть сделок!). Так, Borland получила в свое распоряжение продукты CaliberRM (согласование требований), Together (проектирование программ с помощью UML), OptimizeIt Profiler (профилирование программ), StarTeam (управление конфигурацией и изменениями). Тогда, в 2003-м, на рынке предлагалось довольно много продуктов по поддержке различных этапов ALM, но на представление более-менее полной платформы могла претендовать только одна компания — Rational. Пойти по тому же пути — создания своей ALM-системы — решила и Borland, хотя как раз в этот момент обозначился еще один потенциальный участник этого сегмента рынка — Microsoft, приступившая к построению собственной ALM-платформы на базе Visual Studio (создание первого варианта этой платформы Microsoft закончила как раз сейчас в виде Visual Studio 2005 Team System). Но тогда же Rational вошла в состав IBM, и стало очевидно, что развитие ее средств будет идти в основном в направлении Java/Eclipse. В этой ситуации Borland cделала особый акцент на то, что она осталась единственным независимым поставщиком комплексной ALM-системы, активно сотрудничающим с обоими противоборствующими лагерями — Java/Eclipse и .NET/Visual Studio. Что же касается поддержки Windows, то тут Borland выпустила собственный инструмент C#Builder (сам компилятор был лицензирован у Microsoft), одновременно продолжив поддержку разработки для классического Win32 (от чего Microsoft уже фактически отказалась). В феврале 2006 года Borland Software Corporation, дала знать о своих грядущих планах полностью бросить все свои ресурсы на разработки и поддержку средств управления жизненным циклом приложения – ALM. Для осуществления задуманного Borland купила поставщика ALM – решений Segue Software Inc. После этого Borland объявила о том, что ищет покупателя на часть бизнеса компании, а именно ту часть которая связана с созданием средств разработки приложений, включая линейки Borland Developer Studio (Delphi, C++Builder, C#Builder) и JBuilder. На тот момент покупатель не нашелся, и было сделано решение выделить направление интегрированных средств разработки — Integrated Development Environment, IDE в отдельное подразделение под названием CodeGear. В мае 2008 года стало известно о том, что CodeGear будет продано фирме Embarcadero Technologies за 23 млн. долл. Что и было сделано в последствии. В 2009 году, году мирового кризиса 6 мая компания Borland прекратила свое существование. Продав все свои права компании Micro Focus. |