ZX Review #3-4
22 июля 1997

Читатель-читателю - В.Сироткин. Защита программ (взгляд на проблему).

   ИФК:   представленная    ниже
статья была написана автором до-
вольно давно и поэтому не  отра-
жает самых последних  достижений
в области установки и снятия за-
щит. Однако, как  нам  представ-
ляется, она будет весьма полезна
начинающим  программистам и хак-
керам.
   С  удовольствием  предоставим
место в журнале для описания са-
мых последних достижений в  этой
области.

┌──────────────────────────────┐
│         В. СИРОТКИН.         │
│       ЗАЩИТА ПРОГРАММ        │
│    (взгляд на проблему).     │
└──────────────────────────────┘

   Необходимое отступление...
   Хочу сразу предупредить,  что
автор всегда был и будет  против
всяческих там,  как  програмных,
так и  аппаратных  защит.  Любая
"крутая" защита рано или  поздно
вскрывается, и чем она  "круче",
тем сильнее желание хаккеров  ее
снять.
  Да и вообще, защитить  надежно
и надолго программу для Спектру-
ма практически невозможно.  Мож-
но, конечно, наворотить гору за-
щит, но чем сложней защита,  тем
больше  памяти  она  занимает  в
ущерб головной программе. Но и в
этом случае, взлом защиты -  это
лишь дело времени.
   Да, программам нужна  защита,
но не  программно-аппаратная,  а
ЮРИДИЧЕСКАЯ !

            *  *  *

   Но  так как  программы  защи-
щают и еще долго будут  защищать
именно всяческими программно-ап-
паратными методами, давайте рас-
смотрим, как это можно сделать.
   В основном, все средства  за-
щиты информации делятся на 3 ка-
тегории, которые тесно  перепле-
таются и взаимодействуют друг  с
другом.
   Защитные меры делятся на:
   1. Организационные,  (тут   и
юридические, и экономические,  и
административные).
   2. Программные  (кодирование,
динамически изменяемая  настрой-
ка, скрытые переходы, нестандар-
тное форматирование и т.д.).
   3. Аппаратные    (специальные
платы доступа,  защищенные  мик-
росхемы типа ULA, новейшая  схе-
мотехника).
   Первый способ защиты у нас  в
стране находится еще в  зачаточ-
ном состоянии, хотя на Западе он
является  определяющим  в   деле
програмистского бизнеса.
   Второй и третий пункты нераз-
рывно связаны между собой, и  на
данный момент  являются  домини-
рующими в защите программ  Спек-
трума.
   Остановимся немного на  аппа-
ратной защите.
   Сам компьютер Спектрум  изна-
чально представлял из себя "чер-
ный ящик"  для непосвященных из-
за микросхемы ULA  на плате. Та-
кая защита оказалась  удачной, и
долгое время не могли  полностью
"раскусить"  схемотехнику   этой
секретной микросхемы.
   Сейчас, когда в  стране  "хо-
дит"  не  один  десяток   версий
Спектрума, совместимость с  про-
тотипом, а значит и  с  програм-
мным обеспечением, как раз и оп-
ределяется, насколько  правильно
аппаратно  составлена  схема  из
дискретных элементов, заменяющая
микросхему ULA.
   По этому же пути пошли разра-
ботчики компьютера  "АТМ-ТУРБО",
важные узлы которого собраны  на
микросхемах с заказной  логичес-
кой прошивкой, которую невозмож-
но считать  обычными  способами,
(т.н. микросхемы ПЛИС).
   Такая защита  в  конце концов
вскрывается, но она делает  свое
дело, и определенное время  раз-
работка остается недоступна  для
пиратского копирования и  прино-
сит денежный и  моральный  доход
своему автору.
   Нас же в этой  статье  будет,
прежде всего, интересовать защи-
та программная.
   Механизм защиты  программного
обеспечения можно свести к  сле-
дующим пунктам:
 1. Блок защиты от "раздевания".
 2. Блок защиты от копирования.
 3. Блок  ответной  реакции   на
"раздевание" или незаконное  ко-
пирование.
   1. В блок защиты от "раздева-
ния" входит огромное  количество
методов и способов, которые  ус-
пешно (или безуспешно)  применя-
лись и применяются в  программах
для Спектрума.
   Это и нестандартные загрузчи-
ки с ленты, и шифрация, и приме-
нение  недокументированных   ко-
манд процессора,  и  самогенери-
рующиеся исполняемые команды,  и
работа во ВТОРОМ  прерывании,  и
контроль времени исполнения  от-
дельных кусков  и  многое-многое
другое.
   Весь смысл такой защиты  сво-
дится к тому, чтобы не дать хак-
керу быстренько раскусить  глав-
ный модуль программы, а  запуты-
вать хаккера,  запутывать  и  не
давать возможности  пользоваться
всяческими  там  Мониторами, От-
ладчиками и Трассерами.
   По этому поводу написано  уже
множество статей  и  книг, и  мы
рассмотрим лишь некоторые  прин-
ципы типичных защит, знание  ко-
торых будет  полезно  начинающим
программистам.

            ШИФРАЦИЯ.

   Это, вообще,  тема  для  тол-
стенной  книги.  В  основном,  в
программах  шифрация  идет    по
принципу КСОРКИ (команда XOR).
   Берется  кусок  программы   и
ксорится - или с одинаковым зна-
чением, или со значением из  ре-
гистра  'R',  или  со  значением
числа, получаемого в  результате
арифметико-логических  действий.
В некоторых программах  одна  ее
часть ксорится со второй частью.
   Но  шифрация  может  происхо-
дить не только с  помощью  -XOR-
команды. Закодировать можно и  с
помощью арифметических, логичес-
ких команд сдвига и ротации.
   Типичным  случаем    "крутой"
ксорки является  следующий  при-
мер, взятый из одной программы.
148.
; Дизассемблированный листинг модуля дешифратора.

START   DI             ; запрет прерыванию
        LD A,0         ; обнулим A
        LD HL,DECODE+1 ; загрузим начальный адрес
                       ; зашифрованного модуля
        LD BC,#64      ; длина закодированного
                       ; блока
        LD R,A         ; занести значение в
                       ; регистр 'R'
        LD A,R         ; и сразу вернуть для работы
        IM 2           ; прерывание ДВА
2
(Во-первых, сбивает с толку, во-
вторых, участвует в формировании
регистра 'R', в-третьих  - может
зависнуть  отладчик  при трасси-
ровке и в-четвертых - первая ко-
манда расксоренного блока  может
быть  'EI',  и  программа  сразу
тогда уйдет  на  процедуру обра-
ботки прерывания).
148.
        XOR #71       ; расшифруем первый раз
        XOR HL        ; расшифруем второй раз
        LD (HL),A     ; и запишем в память
        INC HL        ; увеличим адрес
                      ; декодируемого блока
DECODE  DJNZ ADRES    ; вернемся, если весь
                      ; блок не расшифрован
                      ; далее следует зашифрованный блок
2
   Посмотрев на  листинг  беглым
взглядом, можно и не  увидеть, в
чем же здесь "крутая"  заковыка.
А дело в том, что адрес,  загру-
жаемый вначале  в  регистр 'HL',
указывает на значение смещения в
операторе DJNZ. Как раз с  этого
заначения и начинается  дешифра-
ция.
   Что это дает ?
   А  то,  что  неизвестно, куда
замкнут цикл  расксоривания. Ис-
пользование   регистра  'R'  для
формирования  начального   ключа
декодера  не  позволяет  просле-
дить работу дешифратора в  поша-
говом  режиме.  Точку   останова
ставить тоже нельзя, так как она
изменится декодером  или  собьет
значение в регисте 'R'.
    Дать отработать этому  куску
полностью - тоже не  выход:  что
там  идет  первыми  командами  -
неизвестно!  Единственное,   что
можно сделать  в  этой  ситуации
для "раскалывания", это...
   А впрочем,  поломайте  голову
сами.
   Данная программа может приме-
няться и как дешифратор,  и  как
шифратор в разные моменты време-
ни.
   А если таких модулей в  прог-
рамме много и они  шифруют - де-
шифруют не только  головной  мо-
дуль, но и друг друга, то  можно
с уверенностью  сказать - легкой
победы у хаккера не будет.

      ДИНАМИЧЕСКАЯ ЗАЩИТА.

   Данный метод включает в  себя
команды 'JP', 'CALL' по  динами-
чески изменяемым адресам и само-
генерирующиеся исполняемые  кус-
ки программы  (например,  в  ре-
зультате  каких-то  арифметичес-
ких действий). Сюда же можно от-
нести работу во ВТОРОМ  прерыва-
нии, постоянный  контроль  особо
важных кусков  методом  подсчета
контрольной  суммы  и   контроль
времени исполнения отдельных мо-
дулей  программы  ( по  регистру
'R').

   СКРЫТЫЕ (неявные) ПЕРЕХОДЫ.

   Вместо  команд  'JP',  'CALL'
можно    использовать    команды
'RET', 'RETN', 'RETI', предвари-
тельно записав в стек нужные ад-
реса,  полученные   каким-нибудь
заумным способом. Или же исполь-
зовать нестандартные входы в ПЗУ
SOS  или ТРДОС, где лежат нужные
Вам команды.

    ПРИЕМ "БАБЫ ЯГИ" или бег
        впереди паровоза.

   1. Стек  определяется  непос-
редственно в область исполняемых
команд, и данные, сохраняемые  в
стеке, являются  как  бы  частью
генерируемой  кодовой последова-
тельности.
   2.  Для  каждой  подпрограммы
выделяется свой маленький  стек,
лежащий сразу за самой  подпрог-
раммой, выше по адресам.
   Первый способ  хорошо  приме-
нять в самосоздающейся  програм-
ме, которая при генерации испол-
няемого кода бежит вверх по  ад-
ресам, а за ней следом бежит  ее
стек, затирая следы модуля гене-
рации. А за  стеком  бегут  коды
генерируемого модуля.
   Программа, можно сказать, бе-
жит впереди паровоза.
   Второй способ - не только за-
путывает взломщика, но и являет-
ся  хорошей  защитой  от   МАГИК
кнопки, так как при  нажатии  на
нее  стек  текущей  подпрограммы
кончится, и  будут  затерты  уже
рабочие коды.

           ПУСТЫШКИ.

   Включение  в  тело  программы
важных на вид, но никогда не ис-
полнямых кусков, на которые ИМИ-
ТИРУЕТСЯ передача управления.
   В теле пустышки  должны  при-
сутствовать "важные" подпрограм-
мы типа "печать",  "обращение  к
диску", "дешифрация" и  др.  для
привлечения внимания хаккера. На
разборку таких  пустышек  обычно
тратится много времени  и отвле-
кается внимание от главного  мо-
дуля.
   Можно сделать и иначе. В тело
пустышки включить несколько осо-
бо важных ключевых команд с  не-
явными переходами.

 НЕСТАНДАРТНОЕ КОМПРЕССИРОВАНИЕ.

   Обычно  алгоритмы  компрессии
программ для Спектрума  основаны
на подсчете одинаковых повторяю-
щихся  байтов  и  записи  вместо
этого кодовой  последовательнос-
ти - "вид байта" + "число повто-
ров этого байта". Но чтобы запу-
тать хаккера, можно придумать  и
свой, отличный от  других  алго-
ритм компрессии. Это может  быть
упаковка 2-х  смежных  байтов  в
один, компрессия  с  использова-
нием специальных таблиц  и  т.д.
Это  тоже  сильно  снизит  темпы
вскрытия программы.

        РАБОТА НА ЭКРАНЕ
        (в экранном ОЗУ).

   Это самый распостраненный ме-
тод защиты для Спектрума, и, по-
моему, этот метод  еще  остается
актуальным.
   Здесь широкий простор для вы-
думки: можно встраивать исполня-
емые коды в спрайты, в шрифты, в
рисунки.
   А  когда  этот  рисунок   или
спрайт будет выводиться  на  эк-
ран,  передавать  управление  на
лежащую  там   программу.    Это
сильно  затруднит    трассировку
программы отладчиком, если вооб-
ще трассировка станет возможна.

   2. ЗАЩИТА ОТ КОПИРОВАНИЯ.

   Все эти вышеперечисленные ме-
тоды  предназначены  для  защиты
тела программы  от  взламывания,
но если эти меры еще  сочетаются
с  защитой  от  копирования,  то
уровень  защищенности  программы
становится на порядок выше.
   Защита  магнитофонных   прог-
рамм  от  копирования  строится,
как правило, на изменении  стан-
дартных констант сигнала  считы-
вания или записи.
   Из  наиболее   примечательных
защит можно привести такие, как:
"джерки тон" - плавающая  часто-
та сигнала, избыточная длина мо-
дуля, добавление  лишних  байтов
после   байта   паритета,   гло-
бальное изменение структуры сиг-
нала,  турбо-загрузка,  загрузка
задом-наперед и другие...
   Не останавливаясь подробно на
магнитофонных защитах  (об  этом
написано уже много книг  и  бро-
шюр), перейдем сразу к  рассмот-
рению защиты ДИСКОВОЙ.
   Самые первые защищающие прог-
раммы работали по принципу иска-
жения информации в каталоге дис-
ка. Искажались  величины  "объем
файла  в секторах"  для  БЕЙСИК-
программ  и  изменялись данные в
8-ом  секторе  нулевой   дорожки
(байты "количество файлов на ди-
ске", байт  "двухсторонний - од-
носторонний диск", байт  "начало
и количество свободного места".
   Весь каталог запутывался так,
чтобы копировщик не мог правиль-
но  скопировать выбранную  прог-
рамму.
   Пример тому - программа  CLO-
SE.  Эта программа обнуляет 13-е
байты в БЕЙСИК-заголовках, иска-
жает байты "начало" и "количест-
во свободного места"  на  диске,
тип  диска, количество файлов на
диске. Изменению также подверга-
ется имя первого файла на диске:
в него вводится "непечатающийся"
код.
   Программы на диске после  та-
кой защиты запускаются как обыч-
но, так как измененные  байты  в
процессе запуска не участвуют.
   Это простая защита, но коман-
де ТРДОС "COPY" или копировщикам
типа  MOA-SERVICE  здесь уже де-
лать нечего. С такого диска надо
или  снимать  защиту,  или  (что
проще)  скопировать его ТРЕКОВЫМ
копировщиком.

             *  *  *

   Следующим методом защиты  яв-
ляется способ искажения всей ин-
формации в области каталога. Вся
служебная информация  заголовков
забивается нулями или фальшивыми
данными.
   В  этом   случае   необходима
программа с именем 'boot', кото-
рая имеет "правильный" заголовок
и содержит в  себе  таблицу всех
"правильных" заголовков  на дис-
ке.  Эта  программа должна иметь
загрузчик  (естественно,  НЕ  на
БЕЙСИКЕ), который бы умел загру-
жать кодовые  блоки  программ  с
диска, исходя  из значений внут-
ренней таблицы.
   Можно сделать несколько иначе
и написать для  каждой программы
отдельный загрузчик  в виде фай-
ла. Запомнить дисковые  "коорди-
наты"  этих  файлов  (это  длина
блока, номер начального сектора,
начальный трек) и сразу же иска-
зить/стереть  эти координаты  из
каталога.
   Для вызова  этих  загрузчиков
необходима головная программа, в
которой будет истинная  информа-
ция о загрузчиках и процедура их
считывания и запуска.
   Естественно, загрузчики  дол-
жны быть зашифрованы и закодиро-
ваны, а  то  все  вышеизложенное
потеряет всякий смысл.
   Но и в этом  случае  потреко-
вое копирование всего диска сво-
дит такую защиту на нет !
   Логическим  продолжением  вы-
шеприведенного метода стал  спо-
соб расположения загрузчиков или
на  служебных  дорожках    диска
(83-85 цилиндры) и/или в нестан-
дартных секторах  (номер сектора
больший чем 16, и/или длина сек-
тора <> 256 байтам).
   В  этом  случае    необходима
программа нестандартного  форма-
тирования, а это, как  Вы  пони-
маете, работа  на  самом  низком
уровне, через ПЗУ ТРДОС.
   Диски с такой защитой "не бе-
рутся" обычными трековыми  копи-
ровщиками и являются  достаточно
защищенными  для   коммерческого
распостранения.
   С точки зрения хаккера  такой
диск копируется достаточно  лег-
ко.  Необходимо   просканировать
структуру формата  всех  дорожек
диска   (например,    программой
"ADS"  или  через  команду  ВГ93
"ЧТЕНИЕ ДОРОЖКИ ЦЕЛИКОМ";  #E0),
выудить все "неправильные"  сек-
тора и дорожки.
   Далее отформатировать диск  с
аналогичным форматом и, скопиро-
вав  сначала  защищенный    диск
обычным  трековым  копировщиком,
докопировать все  "неправильные"
сектора  и  дорожки  при  помощи
функций ТРДОС  (C = #05 - чтение
сектора и C = #06 - запись  сек-
тора).
   Высшим программным  пилотажем
в деле  защиты  является  способ
глобального  изменения   способа
форматирования.
   Например, в  область  "пробе-
лов"  заносятся  байты, отличные
от байта #4E.  Изменяется  длина
"пробела". Тип сектора (т.е. его
длина)    указывается    байтом,
большим чем 3, что, в  принципе,
указывает на величину сектора  >
1024.  Байт  "сторона  диска"  и
"номер дорожки" тоже  указывают-
ся "с потолка"...
   Головная же программа на  та-
ком диске должна опрашивать  эти
нестандартные величины и  прихо-
дить к выводу:  "родной  или  не
родной это диск?".
   Для копирования такого  диска
Вам потребуется знать не  только
точные номера секторов, их  дли-
ну и количество на дорожке, но и
вообще всю структуру формата.
   Выход тут  один - скопировать
формат каждой дорожки бит в бит.
Сделать такую программу  не  так
уж и сложно, надо помнить только
один момент:

  КАК БЫ НИ БЫЛ ИЗМЕНЕН ФОРМАТ,
НЕКОТОРЫЕ БАЙТЫ И ИХ  ПОСЛЕДОВА-
      ТЕЛЬНОСТЬ ЯВЛЯЮТСЯ
       ОБЯЗАТЕЛЬНЫМИ !!

   Обязательными являются  байты
(уже записанные) и их последова-
тельность (по  порядку  следова-
ния):

#A1,#FE -адресная метка индекса,
     данные о дорожке и секторе;
#A1,#FB -адресная метка данных.

   Вывод отсюда прост  и  очеви-
ден...
   Да простят  меня  многие, кто
защищает свои диски от копирова-
ния - ниже я привожу краткий ал-
горитм  универсального,  всефор-
матного копировщика дисков.

   1. Прочитать  командой   кон-
троллера #E0 всю  дорожку  цели-
ком в  ОЗУ,  через  подпрограмму
ТРДОС #3FDB <#3FE5> (дать коман-
ду 4-5 раз для верности).
   2. По меткам IAM  определить:
сколько  секторов  на   дорожке,
длину секторов и  НОМЕРА  секто-
ров. Запомнить где нибудь  полу-
ченные данные.
   3. Программно   проанализиро-
вать и изменить считанный дамп:
 а) если байт МЕНЬШЕ, чем #F4  -
оставить без изменения;
 б) если байт РАВЕН  #A1, вместо
него вписать #F5  и  вписать  по
adrs-1 и adrs-2  от этого  места
то же самое, если по adrs+1  код
#FE или #FB;
 в) если байт РАВЕН #FE -  оста-
вить;
 г) если байт РАВЕН #FB -  оста-
вить;
 д) вместо ШЕСТОГО  байта  (пер-
вые байты от #A1; #FE) ПОСТАВИТЬ
байт #F7  (здесь  должны быть  2
байта контрольной суммы);
 е) далее Вы должны просто  про-
пустить  область  данных.  Длина
области зависит от типа  сектора
и  ПЕРВЫЙ  БАЙТ  ПОСЛЕ   области
ДАННЫХ НЕОБХОДИМО заменить  бай-
том  #F7  (2  байта  контрольной
суммы);
 ж) Перейти к пункту "а)" и пов-
торять до тех пор, пока не  кон-
чится весь дамп дорожки.
    4. Теперь, когда дамп форма-
та у нас готов, записать его  на
соответствующую дорожку  другого
ДИСКА командой  #F4  через  под-
программу  TRDOS  #3FC0  <#3FCA>
(повторить запись  4-5  раз  для
верности).
 - Проанализировать, какие номе-
ра секторов проставлены в форма-
те и их количество.
 - Считать с  копируемого  диска
соответствующие  сектора  (можно
даже функцией  ТРДОС, но  только
по ОДНОМУ сектору)  в отведенный
буфер в ОЗУ.
 - Записать соответствующие сек-
тора из буфера ОЗУ на диск с на-
шим форматом.
 - Повторить все снова  для  ос-
тальных дорожек.

   Данную программу целесообраз-
но настроить для  ДВУХ  дисково-
дов, но можно и для одного (тог-
да у Вас через 3 минуты  заболит
рука, меняющая диски в  дисково-
де).
   Дальнейшее усложнение  защит-
ных  мер  от  копирования  можно
направить по пути "лазерных  ды-
рок" и "плавающих байтов'.  Мож-
но также пойти по пути записи  в
область пробела байтов  больших,
чем #F4 (без участия  микросхемы
ВГ93 - иначе не получится).
   Но и для этих способов  защи-
ты  найдутся  контрмеры.   Можно
только признать, что не  оскуде-
ла земля хаккерами. Да и арсенал
средств снятия защит гораздо бо-
лее изощрен и многочисленен, чем
арсенал для их установки.
   В заключение этой статьи нес-
колько слов о последнем блоке  в
комплексе защит. Это  блок  "от-
ветной реакции"  на  взламывание
или незаконное копирование.  Тут
уж широкий простор для фантазии:
от угрожающих  надписей, гудков,
попыток  стирания/форматирования
диска  до попыток "сломать" дис-
ковод, давая ему команды  "выйти
на 255 цилиндр" или  "найти  243
дорожку".




Другие статьи номера:

TR-DOS для начинающих - Часть 1.

Авторская разработка - General Sound - мультимедиа для ZX Spectrum!

Визитная карточка - Представляем новый электронный журнал "Major Wares" (c) Codebusters & V.M.G.

Компьютерная новелла - Knight Lore "Преданья рыцарских времен".

Новые программы - И.Рощин. HELP_Z80. В.Давыдов. Catalog's Base v1.8.

Описание оболочки журнала "ZX-РЕВЮ"

Перекресток драконов - Aavlon, Castle of Dreams, Erik the Viking.

Перекресток драконов - Eureka!, Eye of Bain, Kentilla.

Перекресток - Sherlock, Apollo, Shadows of Mordor, Rigels Revenge, Temple of Terror, ID, That's the Spirit, Return to Ithaka.

Ретро - Дж.Хардман, Э.Хьюзон. 40 лучших процедур.

Советы экспертов - Castle Master.

Советы экспертов - Firelord.

Советы экспертов - Stonkers.

Форум-игры - Insult Megademo, Catch 23, Livingstone, Rock Star ate my Hampster, НЛО-2: Дьяволы Бездны, Terminator 2, Venturama, The Spririts, Nipper, Sweewo'S World, King's Bounti-2, Hacker 2, Black Magic, Satcom, Звёздное Наследие.

Форум - А.Гура. Кодекс программиста.

Форум - А.Стрельников. Перспективы развития ZX Spectrum.

Форум - В.Давыдов. По материалам, опубликованным в ZX-РЕВЮ: Некоторые вопросы, связанные с автостартом Бейсик-программ. Redefine Keys. Процедура печати 42 символов в строке. Процедура умножения HL=B*C. Доработка посекторных загрузчиков. Мини-драйвер дисковых операций.

Форум - Группа 'Light'. Музыкальный процессор для ZX-Speccy.

Форум - Д.Федоров: Печать картинки с маской с точностью до пиксела. Алгоритм расчета адреса по координатам с точностью до пиксела.

Форум - И.Рощин. Совместное использование ZX ASM 3.0 и STS 5.1.

Форум - М.Бекарев. Расчет адреса экранной области по знакоместу и наоборот.

Форум - П.Федин. Доработка Profi для бесконфликтного подключения периферии.

Форум - С.Астров. Генератор псевдослучайных чисел.

Читатель-читателю - В.Сироткин. Защита программ (взгляд на проблему).

Читатель-читателю - И.Рощин. Драйвер экрана для компьютера "Пентагон-128".

Этюды - А.Савинов: Процедура вывода на экран символов двойной высоты. Процедура "растворения" символов.

Этюды - А.Уржа. Процедура рисования окружности.

Этюды - В.Сироткин. Программа подсчета контрольной суммы.

Этюды - Е.Волчков. Улучшение подпрограммы вычисления адреса в дисплейном файле.

Этюды - Е.Мороз. Бегущая строчка.

Этюды - И.Командин. Программа проявления экрана.

Этюды - И.Рощин. Два графических эффекта.

Этюды - М.Лазутов: Программа модернизации шрифта. Программа кодирования/декодирования блока кодов. Эффект с атрибутами.

Этюды - О.Смолянкин: Процедуры очистки экрана. Вывод текстовых сообщений на экран.

Письма счастья как правильно делать email рассылку.

Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Новости - Новости от FLASH на 08.06.97 года.
MESSAGE 2 PLAYGEAR - о Sound Drive.
Coding - реализация Phong Bump Mapping на Speccy.

В этот день...   5 декабря