ZX-News
#26
03 апреля 1997 |
|
General Sound - О процессе адаптации фирменных игрушек под General Sound - первые результаты (Xecutor, Target Renegade). Руководство по программированию, краткое описание, технические характеристики, система команд.
GENERAL SOUND ══════════════════════════ Ньюска идет в ногу со временем, и вот вам новая рубрика... ────────────────────────── (с) Михаил Блюм Zx-Masters GENER'ИЗАЦИЯ ПРОГРАММ Начался активный процесс адаптации фир- менных игрушек под GENERAL SOUND (GS). На этих выходных появились 2 первые - XECUTOR и TARGET RENEGADE. Первое впечатление от них - полный ИЗВ- РАТ. Вместо привычного бипера или AY игра- ет крутая 8-ми битная музыка, и все это на фоне... прыгающих груд монохромных пиксе- лей, да еще и на СИНКЛЕРе к тому же. :( Одним словом - что-то абсурдное и несо- поставимое. Но... после пяти минут игры, хотя бы в Target Renegade, ее уже трудно представить без этой техномузыки, смачных ударов по морде и в промежность, мясных пинков, взмахов молотков, криков жертв и падания поверженных тел. Чтобы вы смогли себе представить все эф- фекты, перечислю их: Музыка - всего 4 мелодии: одна в меню и три чередуются в пяти уровнях. Эффекты - всего 26 эффектов. Общие эффекты: 1. Щелкание бонуса при прохождении каждого уровня. 2. Возглас, осведомляющий о появлении еще одной жизни. 3. Звук, характеризующий потерю жизни. 4. Звук, характеризующий прохождение уров- ня. 5. Гудок - осведомляет об истечении време- ни. 6. Звук падения тела - играется на 7-ми нотах, в зависимости от уровня и игрока. 7. Удар рукой и пинок - в зависимости от удара играются на разных нотах. 8. Удар после прыжка и добивание - -//- 8. Удар в промежность двух видов: удар ко- леном и удар ногой с разворота. 10. Прыжок вверх. 11. Прыжок с разбега. 1-ый уровень: 12. Мотор мотоцикла. 13. Сбивание мотоциклом игрока. 14. Мах молотом. 2-ой уровень: 15. Выстрел. 16. Удар плеткой теткой. 17. Удар плеткой игроком. 18. Крик тетки при падении. 3-ий уровень: 19. Мах топором. 4-ый уровень: 20. Укус собаки. 21. Визг собаки. 5-ый уровень - здесь самые "мясные" звуки: 22. Удар лбом. 23. Смачный удар по печени и в морду. 24. Взмах и удар палкой. 25. Удар босса лбом с откидыванием жертвы на пол хребтом вниз. 26. Если Вы победите босса, то услышите: "АЛИЛУЯ!". Почти все эффекты играются с разными но- тами, которые зависят от номера игрока или врага. Дисперсия нот обычно выбирается случайным образом. Короче, почти каждый эффект играется на 3-7 нотах. Громкость музыки и эффектов можно регу- лировать "ползунками" в меню. Вот и все, что касается Target Renegade. Ну а Xecutor делал не я, поэтому не могу дать столь подрбного описания эффектов, скажу только, что их там 11. Следующими после Target Renegade будут ZYNAPS и POWERBOAT, а затем CHASE H.Q. и HEADBALL. Кроме того, по последним данным, начали озвучивать FROST BYTE и FLYING SHARK. Все это Вы сможете ожидать в апреле, а дальше все будет зависеть от уровня реали- зации таких игр, поэтому убедительная просьба ко всем СисОпам - не ставьте такие игры на BBS; к распространителям - не пи- ратствуйте, а то это дело зачахнет, т.к. кодеры не собираются адаптировать сие игры за просто так. А теперь, позвольте мне доозвучивать ZY- NAPS! ────────────────────────── (с) STINGER Руководство по программированию General Sound. Версия v1.03. Редакция 003. 1. Краткие технические характеристики GS. -------------------------------------- Процессор: Z80, 12MHz, без циклов wait ROM : 32k, 27256 RAM : Static Ram 128k всего, 112k доступно для модулей и сэмплов в базовой версии INT : 37.5 KHz Каналы : 4 независимых 8-и битных кана- ла, каждый с 6-и битным контролем громкос- ти. 2. Краткое описание GS, или много всякой лабуды. --------------------------------------------- GS - музыкальная карточка, предназначен- ная для проигрывания музыкальных модулей и отдельных сэмплов (эффектов). Модули для GS - это стандартные Амижные и PCшные 4-х канальные MOD файлы, а сэмп- лы - как Амижные signed sample, так и PCш- ные unsigned sample. Проигрыватель MOD файлов в GS является практически полным аналогом ProTracker'а на Амиге и создавался при интенсивном ис- пользовании исходников ProTracker'a. (Ис- ходники были из Protracker'а v2.1A by Lars "ZAP" Hamre - Amiga Freelancers) MOD Player поддерживает все команды Pro Tracker'а, за исключением двух: Е01 Filter On Амига-специфичная коман- да, включает фильтр высо- ких частот. EFX Invert Loop Я еще не видел плейера, который бы поддерживал эту команду. Воз- можно, она поддерживается на каких-то ста- рых плейерах. GS представляет из себя, по-сути, мик- ропроцессорный комплекс со своим процессо- ром, ПЗУ, ОЗУ и портами, и абсолютно не зависит от главного процессора Спектрума, что позволяет, например, загрузить свой любимый модуль, сбросить Спектрум, загру- зить ассемблер и творить под любимую музы- ку. Soft внутри GS полностью берет на себя задачи проигрывания звука, интерпретации модуля и т.д. Программирование GS'а сво- дится к передаче байт за байтом модуля и/или сэмплов, а затем требуется только подавать команды типа: запустить мо- дуль, установить глобальную громкость про- игрывания модуля, запустить сэмпл #09 в канале #02 и т.д. Если предполагается загрузить модуль вместе с сэмплами, то ОБЯЗАТЕЛЬНО требует- ся загружать вначале модуль, а затем сэмп- лы. При загрузке модуля очень рекомендуется оставить свободными 2к памяти, т.е. загру- жать модули длиной максимум 110K. Это ус- ловие не является необходимым, но его ис- полнение очень желательно в целях совмес- тимости с последующими версиями. Аналогично очень рекомендуется оставлять по 80 байт для каждого сэмпла, например, если требуется загрузить 63-х килобайтный модуль и 18 сэмплов, то имеем: Total_Sample_Length=112*1024-63*1024-2*1024-18*80=46688 байт Это суммарная длина сэмплов, которые при таком положении вещей могут быть загруже- ны. Если же, например, требуется вычислить, сколько поместится в память GS'а 2-х кило- байтных сэмплов, то это вычисляется следу- ющим образом: 112*1024/(2048+80)=53 сэмпла. В GS'е имеются 4 физических канала, ко- торые и проигрывают звук. Каналы 0 и 1 - левые, а 2 и 3 - правые. 3. Интерфейс со Спектрумом. ------------------------ На мир GS смотрит при помощи 4 регист- ров: 1. Command register - регистр команд, дос- тупный для записи порт по адресу 187. В этот регистр записываются команды. 2. Status register - регистр состояния, доступный для чтения порт по адресу 187. Биты регистра: 7 - Data bit, флаг данных 6 - Неопределен 5 - Неопределен 4 - Неопределен 3 - Неопределен 2 - Неопределен 1 - Неопределен 0 - Command bit, флаг команд Этот регистр позволяет определить состо- яние GS, в частности можно ли прочитать или записать очередной байт данных, или подать очередную команду, и т.п. 3. Data register - регистр данных, доступ- ный для записи порт по адресу 179. В этот регистр Спектрум записывает данные, напри- мер, это могут быть аргументы команд. 4. Output register - регистр вывода, дос- тупный для чтения порт по адресу 179. Из этого регистра Спектрум читает данные, идущие от GS. Command bit в регистре состояний уста- навливается аппаратно после записи команды в регистр команд. Сбрасываться в 0 он мо- жет только из GS, что сигнализирует об оп- ределенном этапе исполнения команды. Data bit в регистре состояний может быть установлен или сброшен как по желанию Спектрума, так и по желанию GS: при записи Спектрумом в регистр данных он аппаратно устанавливается в 1, а после чтения GS'ом из этого регистра сбрасывается в 0. При записи GS в регистр вывода он (все тот же Data bit) аппаратно устанавливается в 1, а после чтения из этого порта Спектрумом сбрасывается аппаратно в 0. Несмотря на то, что регистр данных и ре- гистр вывода расположены в пространстве адресов портов по одному и тому же адресу и воздействуют на один и тот же бит дан- ных, они являются двумя независимыми ре- гистрами. Значение, один раз записанное в один из этих регистров, остается неизмен- ным в нем до новой записи. Состояние бита данных очень часто неоп- ределено, и если в спецификации команд не определены значения этого бита на опреден- ных этапах исполнения команды, недопустимо делать какие-либо предположения относи- тельно значения этого бита. 4. Система команд GS. ------------------ Вначале позволю себе небольшое отступле- ние от собственно системы команд. GS, как известно, предназначен в основном для про- игрывания модулей и сэмплов. В данной вер- сии (1.03) GS ROM допукается загрузка од- ного модуля и/или до 32 сэмплов. Каждый сэмпл при загрузке его в память получает свой уникальный идентификатор, который однозначно определяет обращение к данному сэмплу в командах, которые требуют номер сэмпла. Самый первый загруженный сэмпл получает номер (handle) = 1, следую- щий - номер 2, и т.д. То же самое применимо и к модулям, и этот единственный загруженный модуль будет иметь handle=1 после загрузки. Особенностью данной версии является так- же то, что вначале требуется загружать мо- дуль, а затем уже сэмплы. Особенности описания команд: Команды описываются следующим образом: 1. Hex код команды 2. Название команды 3. Выполняемые действия при исполнении команды 4. Формат команды 5. Комментарии к команде Формат команды описывается следующим образом: GSCOM EQU 187 GSDAT EQU 179 SC #NN : Послать код команды в регистр команд LD A,#NN OUT (GSCOM),A WC : Ожидание сброса Command bit WCLP IN A,(GSCOM) RRCA JR C,WCLP SD Data : Послать данные в регистр данных LD A,Data OUT (GSDAT),A WD : Ожидание сброса Data bit, по сути, ожидание, пока GS не примет посланные ему данные WDLP IN A,(GSCOM) RLCA JR C,WDLP GD Data : Принять данные из регистра данных IN A,(GSDAT) WN : Ожидание установки Data bit, по сути, ожидание очередных данных от GS WNLP IN A,(GSCOM) RLCA JR NC,WNLP Команды GS: #00 Reset flags - Сбрасывает флаги Data bit и Command bit. SC #00 WC (Data bit=0, Command bit=0) #0E Go in Covox mode Переходит в режим Ковокс, напрямую копирует регистр данных в ЦАПы двух (правого и левого) каналов. Выход из этого режима - запись #00 в регистр команд. SC #0E WC SD \ SD \ ... / Это вывод в ЦАПы SD / SC #00 WC #F3 Warm restart Сбрасывает полностью GS, но пропускает этапы определения количества страниц памяти и их провеки, что очень сильно ускоряет процесс инициализации. SC #F3 WC #F4 Cold restart Полный перезапуск GS со всеми провер- ками. По сути, JP #0000. SC #F4 WC #20 Get total RAM Получить общий объем доступной памяти на GS. ( В базовой версии это 112к) SC #20 WC GD RAM.L(Младшая часть) WN GD RAM.M(Средняя часть) WN GD RAM.H(Старшая часть) Total RAM=65536*RAM.H+256*RAM.M+RAM.L #21 Get free RAM Получить общий объем свободной памяти на GS. SC #20 WC GD RAM.L(Младшая часть) WN GD RAM.M(Средняя часть) WN GD RAM.H(Старшая часть) Free_RAM=65536*RAM.H+256*RAM.M+RAM.L #23 Get number of RAM Pages Получить число страниц на GS. SC #23 WC GD Number_RAM_Pages В базовой версии 3 страницы. #2A Set Module Master Volume Установить громкость проигрывания модулей. SD Module_Master_Volume [#00..#40] SC #2A WC [GD Old_Master_Volume] - Старая громк. Маленький пример использования данной команды: (Предполагается, что играется модуль) LD B,#40 LOOP: LD A,B OUT (GSDAT),A LD A,#2A OUT (GSCOM),A EI HALT DJNZ LOOP LD A,#32 OUT (GSCOM),A Вышеописанное плавно снижает громкость играющего модуля, а затем останавливает его. #2B Set FX Master Volume Установить громкость проигрывания эффектов. SD FX_Master_Volume [#00..#40] SC #2B WC [GD Old_FX_Volume] - Старая громкость Аналогично предыдущей команде, но дейс- твует на сэмплы. С помощью этих двух команд можно регули- ровать баланс громкостей модуля и сэмплов, и т.п. #2E Set Current FX Установить текущий эффект. Просто присваивает переменной CURFX это зна- чение. Если какая-либо команда требу- ет номер сэмпла (sample handle), то можно вместо этого номера подать ей #00 и интерпретатор подставит вместо этого нуля значение переменной CURFX. (См. команды #38, #39, #40-#4F для понимания вышеизложенного.) SD Cur_FX SC #2E WC #30 Load Module Загрузка модуля в память. SC #30 WC [GD Module_Handle]-номер модуля (Command bit=0, Data bit=0) SC #D1 (Open Stream-открыть поток) WC SD \ WD \ ... Байты модуля SD / WD / SC #D2 (Close Stream-закрыть поток) WC Пример: LD HL,Mod_adress LD DE,0-Mod_length LD C,GSCOM LD A,#30 CALL SENDCOM LD A,#D1 CALL SENDCOM LD A,(HL) LOOP: IN B,(C) JP P,READY IN B,(C) JP M,LOOP READY: OUT (GSDAT),A INC HL LD A,(HL) INC E JP NZ,LOOP INC D JP NZ,LOOP WAIT: IN B,(C) ; Ждем принатия JP M,WAIT ;последнего байта LD A,#D2 CALL SENDCOM IN A,(GSDAT) ; Номер модуля OUT (GSDAT),A LD A,#31 SENDCOM: OUT (GSCOM),A WAITCOM: IN A,(GSCOM) RRCA JR C,WAITCOM RET #31 Play module Проигрывание модуля. SD Module_Handle - номер модуля SC #31 WC #32 Stop module Остановить проигрывание модуля. SC #32 WC #33 Continue module Продолжить проигрывание модуля после остановки. SC #33 WC #38 Load FX Загрузка сэмпла эффекта в память. Загружает беззнаковые сэмплы (PC type) SC #38 WC [GD FX_Handle]-номер сэмпла (Command bit=0, Data bit=0) SC #D1 (Open Stream-открыть поток) WC SD \ WD \ ... Байты сэмпла SD / WD / SC #D2 (Close Stream-закрыть поток) WC При загрузке каждого сэмпла, в памяти GS создается для этого сэмпла заголовок, в котором описываются различные параметры сэмпла. После загрузки эти параметры уста- навливаются в определенные значения, как то: Note=60, Volume=#40, FineTune=0, Seek- First=#0F, SeekLast=#0F, Priority=#80, No Loop и внутренняя переменная CurFX уста- навливается равной FX_Handle. Затем командами #40, #41, #42, #45, #46 и #47 можно эти значения по умолчанию сме- нить на свои. Это требуется потому что ко- манда #39 для инициации проигрывания сэмп- ла использует значения параметров из заго- ловка сэмпла. В своем естественном виде сэмплы обычно плохо пакуются компрессорами, но сжимае- мость обычно можно поднять, если перевести сэмпл в Delta-вид, т.е. хранить не абсо- лютные значения сэмпла, а относительное смещение относительно предыдущего байта. Примерно вот так вот можно перевести сэмпл в Delta-вид: LD HL,Start_of_sample LD DE,0-Length_of_sample LD C,#00 LOOP: LD A,(HL) SUB C LD C,(HL) LD (HL),A INC E JP NZ,LOOP INC D JP NZ,LOOP А вот как можно закачать сэмпл: LD IX,Parameters LD HL,Sample_adress LD DE,0-Sample_length LD C,GSCOM LD A,#38 CALL SENDCOM LD A,#D1 CALL SENDCOM LD A,(HL) LOOP: IN B,(C) JP P,READY IN B,(C) JP M,LOOP READY: OUT (GSDAT),A INC HL ADD A,(HL) INC E JP NZ,LOOP INC D JP NZ,LOOP WAIT: IN B,(C) ; Ждем принатия JP M,WAIT ;последнего байта LD A,#D2 CALL SENDCOM ; Теперь переопределяем параметры ; сэмпла по умолчанию своими ; значениями LD A,(IX+#00) OUT (GSDAT),A ; Нота LD A,#40 CALL SENDCOM LD A,(IX+#01) OUT (GSDAT),A ; Громкость LD A,#41 SENDCOM: OUT (GSCOM), A WAITCOM: IN A,(GSCOM) RRCA JR C,WAITCOM RET #39 Play FX Проигрывание эффекта. SD FX_Handle - номер сэмпла SC #39 WC При исполнении этой команды происходит следующее: смотрятся каналы, указанные в SeekFirst параметре нашего сэмпла, и если хотя-бы один из них свободен, в нем и про- игрывается сэмпл, в противном случае смот- рятся каналы, указанные в SeekLast и если один из них свободен, в нем и играется сэмпл, если свободных нет, то просматрива- ются все каналы, указанные SeekLast, из них выбирается канал с наименьшим приори- тетом и сравнивается с приоритетом нашего сэмпла (имеется в виду сэмпл, который мы хотим проиграть), если у этого сэмпла бу- дет больший приоритет, чем у сэмпла, уже играющего в канале, то играющий в канале сэмпл будет остановлен, а наш сэмпл будет запущен в этом канале вместо старого сэмп- ла. Вот такая вот приоритетная схема ... Когда сэмпл запускается в канале, то его нота, громкость и т.п. параметры записыва- ются в область данных канала из заголовка сэмпла. В общем случае, что-бы проиграть сэмпл с нужными параметрами, вы можете установить эти параметры после загрузки сэмпла и сме- ло использовать команду #39. Если же пара- метры должны меняться, то можно поступать следующим образом: командой #2E сделать текущим требуемый сэмпл, командами #4x из- менить его параметры, а затем уже запус- кать его командой #39. Альтернативный метод запуска сэмплов предоставляют команды #80..#9F, при испол- нении этих команд вы прямо в коде команды указываете, в каком канале требуется за- пустить сэмпл, и кроме этого, вы можете также указать с какой нотой и/или гром- костью требуется запустить сэмпл. #3A Stop FX in channels Остановка проигрывания эффектов в заданных каналах, которые указываются в маске каналов (Channel Mask). В ней единица в n-ном бите указывает на то, что эффект в n-ном канале требуется остановить SD Channel_Mask SC #3A WC Описанное выше есть идеальный вариант работы данной команды, но к сожалению не все так просто в этом мире, и эта команда действует не так, а именно: единица в бите 7 останавливает сэмпл в нулевом канале, и т.п. В следующих версиях это будет исправ- лено, а пока я могу порекомендовать оста- навливать вообще все сэмплы маской #FF. #3E Load FX (Extended version) Загрузка сэмпла эффекта в память. Позволяет загружать сэмплы со знаком. (Amiga type) SD #01 (Signed sample) SC #3E WC [GD FX_Handle]-номер сэмпла (Command bit=0, Data bit=0) SC #D1 (Open Stream-открыть поток) WC SD \ WD \ ... Байты сэмпла SD / WD / SC #D2 (Close Stream-закрыть поток) WC #40 Set FX Sample Playing Note Установка ноты по умолчанию для текущего эффекта. SD Note [0..95] SC #40 WC Note= 0 C-0 1 C#0 12 C-1 24 C-2 36 C-3 (C-1 в Амиге) 48 C-4 (C-2 в Амиге) 60 C-5 (C-3 в Амиге) 72 C-6 84 C-7 В данной версии Sound Generators Wave 2, 3 могут воспроизвести октавы 3, 4 и 5, по- этому допустимым значением параметра Note является диапазон от 36 до 71. #41 Set FX Sample Volume Установка громкости по умолчанию для текущего эффекта. SD FX_Volume [#00..#40] SC #41 WC #45 Set FX Sample Priority Установка приоритета для текущего эффекта. (См. команду #39) SD FX_Priority [#01..#fe] SC #45 WC #46 Set FX Sample Seek First parameter Установка параметра Seek First для текущего эффекта. (См. команду #39) SD FX_SeekFirst SC #46 WC #47 Set FX Sample Seek Last parameter Установка параметра Seek Last для текущего эффекта. (См. команду #39) SD FX_SeekLast SC #47 WC #60 Get Song Position Получение значения переменной Song_Position в текущем модуле. SC #60 WC GD Song_Position [#00..#FF] Можно интерпретировать как количество проигранных паттернов модуля. После старта модуля принимает значение 0 и увеличивает- ся на единицу после проигрывания очередно- го паттерна. Эта переменная может исполь- зоваться для синхронизирования процессов в Спектруме с проигрыванием модуля. Для это- го можно, например, в начале процедуры об- работки прерывания сделать SC #60, затем выполнить процедуры различных операций с экраном, скруллинга строчек и т.п. (т.е. чтобы была достаточная для выполнения ко- манды задержка), а затем прочитать значе- ние порта 179 (GD Song_Position), и срав- нить его с требуемым и, в случае равенс- тва, перейти на следующую часть демы, т.е. if (Song_Position==My_Position) then goto Next_Part_Of_Demo #61 Get Pattern Position Получение значения переменной Pattern_Position в текущем модуле. SC #61 WC GD Pattern_Position [#00..#3F] Получить значение смещения в паттерне (текущий ROW), использование - аналогично предыдущей команде, однако требуется заме- тить, что эта величина изменяется довольно быстро, и поэтому if (Pattern_Position>=My_Position) then goto Next_Part_Of_Demo #62 Get Mixed Position Получить значение Pattern_Position, немного смешанной с Song_Position. SC #62 WC GD Mixed_Position Mixed_Position: (по битам) 7-Song_Position.1 6-Song_Position.0 5-Pattern_Position.5 4-Pattern_Position.4 3-Pattern_Position.3 2-Pattern_Position.2 1-Pattern_Position.1 0-Pattern_Position.0 Т.е если получить Mixed_Position и сде- лать с ним AND #3F, то получится вылитый Pattern_Position, а если после получения его немного RLCA, RLCA, AND #02 - то это будут младшие два бита Song_Position. См. примечания к командам #60 и #61. #63 Get Channel Notes Получить ноты всех каналов модуля. SC #63 WC GD Note_of_channel_0 WN GD Note_of_channel_1 WN GD Note_of_channel_2 WN GD Note_of_channel_3 Если в каком-либо канале значение ноты изменилось с последнего исполнения команды #63, то бит 7 полученного заначения Note_of_channel_N будет в нуле, если же это значение то же самое, что и было раньше, то этот бит бу- дет в единице. Младшие семь битов и есть собственно нота от 0 до 95; если это зна- чение равно 127, то это означает, что ни- какие сэмплы в канале не играют. Данная команда предназначена в основном для пост- роения на ее основе различных анализато- ров. #64 Get Channel Volumes Получить громкости всех каналов модуля. SC #64 WC GD Volume_of_channel_0 WN GD Volume_of_channel_1 WN GD Volume_of_channel_2 WN GD Volume_of_channel_3 См. описание команды #63 #80 Direct Play FX Sample (#80..#83) Проигрывание сэмпла в заданном кана- ле. SD Sample_Number SC #80..#83 (Младшие биты определяют непосредственно номер канала, в котором требу ется играть сэмпл) WC #88 Direct Play FX Sample (#88..#8B) Проигрывание сэмпла в заданном кана- ле с заданной нотой. SD Sample_Number SC #88..#8B (Младшие биты определяют непосредственно номер канала, в котором требу ется играть сэмпл) WC SD Note [0..95] WD #90 Direct Play FX Sample (#90..#93) Проигрывание сэмпла в заданном кана- ле с заданной громкостью. SD Sample_Number SC #90..#93 (Младшие биты определяют непосредственно номер канала, в котором требу ется играть сэмпл) WC SD Volume [#00..#40] WD #98 Direct Play FX Sample (#98..#9B) Проигрывание сэмпла в заданном кана- ле с заданной нотой и громкостью. SD Sample_Number SC #88..#8B (Младшие биты определяют непосредственно номер канала, в котором требу ется играть сэмпл) WC SD Note [0..95] WD SD Volume [#00..#40] WD __________________________ ────────────────────
Другие статьи номера:
General Sound - О процессе адаптации фирменных игрушек под General Sound - первые результаты (Xecutor, Target Renegade). Руководство по программированию, краткое описание, технические характеристики, система команд. |
Глюки - STS 5.1 новые глюки. |
Железо - Описание XTR-модема. |
Лит.страничка - Из серии "Необъятная вселенная". |
Новости - XTR-modem новая разработка от X-Trade. |
Обмен опытом - IBM-PC Keyboard на ZX Spectrum... |
От редакции - В Питер пришла весна. |
Реклама - Реклама и объявления ... |
Похожие статьи:
В этот день... 16 октября