ФОРУМ
СПОСОБ ПЕРЕКЛЮЧЕНИЯ ZS 256 В РЕЖИМ TURBO.
(с) Мезенцев Александр (MALEX from Legionsoft), 1996.
Прочитал первый номер ZX РЕВЮ за этот год, и увидел в нем, как программно переключаться на режим "TURBO" в "SCORPIONS". У меня тоже "SCORPION", и я решил поделиться своим способом переключения в режим "TURBO":
RST 8
DEFB #87 - Включает режим "TURBO"
RST 8
DEFB #88 - Выключает режим "TURBO"
Эти функции я нашел сам, когда методом "научного тыка" хотел найти еще какие нибудь функции. Может кто-то нашел еще что-то?
(с) Седов Алексей, г.Москва, 1996
УСОВЕРШЕНСТВОВАННЫЙ ТУРБО-ЗАГРУЗЧИК.
Предлагаю вашему вниманию усовершенствованный турбо-загрузчик (скорость чтения вдвое выше, чем у варианта, опубликованного в ZX РЕВЮ 95/5). Если хотите, чтобы головка диска "ерзала" в два раза быстрее - удалите строки отмеченные звездочкой (правда никакого практического применения для двусторонних дисков эта процедура иметь не будет, но зато хоть послушаете, как быстро может передвигаться головка дисковода при загрузке с одностороннего диска).
Листинг программы:
ORG 32000 DI
LD A,0 AND A RRA
LD C,#7F CALL DOS DEFW #2A53 LD A,#1C @@3 CALL DOS DEFW #2FC3 CALL DOS DEFW #3EF5
LD A,#3C BIT 0,D JR Z,$+4 @@2 LD A,#2C CALL DOS DEFW #1FF3 @@1 CALL #1F54 JR NC,@@7 PUSH HL PUSH BC LD A,(#5CD6) PUSH AF LD C,#5F LD A,E INC A CALL DOS DEFW #2A53 LD BC,@@5 PUSH BC LD BC,7 PUSH BC LD BC,#2090 PUSH BC LD BC,#017F JP 15664 @@5 DI
LD HL,#5CD6 POP AF CP (HL) JR Z,$+3 LD (HL),A POP BC POP HL JR NZ,@@1 INC H DEC B JR Z,@@6 INC E BIT 4,E JR Z,@@1 LD E,0 INC D BIT 0,D ;* JR NZ,@@2 ;* LD A,#58 JR @@3 @@6 INC E BIT 4,E JR Z,$+5 LD E,0 INC D @@7 EI RET
DOS EX (SP),HL LD (@@4+1),DE
LD E,(HL) INC HL LD D,(HL) INC HL EX (SP),HL PUSH DE @@4 LD DE,0 JP 15664
TEST ORG 31900 LD B,8 PUSH BC LD HL,32768 LD B,128 CALL 32000 POP BC DJNZ $-10 EI RET
Программа тестировалась на компьютере, оснащенном двухсторонним дисководом и операционной системой TR-DOS 5.03.
(с) KSA, г.Москва.
Я бы хотел сделать несколько предложений автору эмулятора спектрума на PC - Углекову Константину.
На мой взгляд, в твоем отладчике не хватает функций загрузки и записи на спектрумовский (!) диск кодоых фрагментов и ассемблерного текста. Неплохо бы было, если бы там был встроенный калькулятор, понимающий не только HEX, но и BIN и DEC.
Еще я не понял почему частота огибающей увеличена в несколько раз, и почему не эмулируется шум? (Правда, насчет шума я точно сказать не могу, так как у меня нет ADLIB'a, и я пользуюсь эмулятором оного на GRAVIS ULTRASOUND'e, но факт остается фактом: писать музыку в эмуляторе невозможно...
Кстати, неплохо бы было еще сделать произвольное переопределение кнопок расширенной клавиатуры, а нерасширенные клавиши принять в IBM'овском соответствии...
(С) Андрей
г.Новгород.
Получил ZX-РЕВЮ 96/1-2 и, как обычно, начал его читать с Форума. Прочитав в нем от начала и до конца письмо по программе LIFE, я попытался написать такую же игру. Сначала (для пробы) я написал ее в BASICS. Конечно, не было смысла обрабатывать весь экран (192*256) точек, и я написал ее для размера экрана 22*32. На проверку одного экрана уходило до 30-40 секунд. Я, также, написал подпрограмму для определения размеров окна. Скорость после этого стала повыше. Но я заметил следующую особенность: дело в том, что когда мой SPECCY проверял условия рождаемости, он "зависал" на время, которое в 1.5 раза превышало время, затрачиваемое на проверку условий гибели и выживания в сумме. ( Все эти я организовал в разных блоках, сделав три пары (по X и Y) включенных друг в друга циклов). Почему мы получаем такие затраты во времени?
А дело вот в чем. На экране пустых клеток гораздо больше чем
закрашенных, а так как компьютер, проверяя условия рождаемости, смотрит на каждую незакрашенную клетку (при этом проверяя еще 8 клеток вокруг нее), работа, конечно же, тормозится. Я разработал алгоритм, следуя которому мы можем "вынуть" все клетки, вокруг которых нет ни одной закрашенной. Как это сделать? Нужно перебрать в окне каждую закрашенную клетку и проверяем каждую пустую вокруг нее на условие рождаемости. При этом скорость несколько повышается и из проверки мы "выкидываем" около 20% незакрашенных клеток (а иногда бывает и больше).
(С) Рюмик С.М.
г.Чернигов, 1996
НЕСТАНДАРТНОЕ ИСПОЛЬЗОВАНИЕ РЕГИСТРА R.
Как известно, микропроцессор Z80 имеет в своем составе регистр обслуживания динамической памяти, так называемый, регистр R.
Подобного регистра не было в предшественнике Z80 - микропроцессоре I8080 ( отечественный аналог КР580БМ80А ). Разработчики Z80 изначально ориентировались на применение в качестве ОЗУ микросхем динамической памяти, требующих периодической регенерации (восстановления) хранимой информации.
РЕГЕНЕРАЦИЯ ПАМЯТИ В КОМПЬЮТЕРЕ "ZX-SPECTRUM"
Рассмотрим общие принципы регенерации ОЗУ через регистр R.
Содержимое 8-и разрядного регистра R, в каждом машинном цикле M1 микропроцессора Z80 выдается на шину адреса. После выполнения очередной команды, содержимое регистра R увеличивается на единицу. В схеме компьютера "ZX-SPECTRUM" задействованы 7 младших разрядов регистра R, которые аппаратно через мультиплексор подаются на адресные входы восьми микросхем динамической памяти К565РУ5.
Микросхема Е-565РУ5 организована матрицей запоминающих элементов - 128 строк по 512 столбцов. Одновременно информация может быть регенерирована в одной из 128 строк ОЗУ при спаде сигнала выборки строки RAS и единичном уровне сигнала выборки столбца CAS.
7 младших разрядов регистра R однозначно определяют порядковый номер строки от #00 до #7F. Итого 128 строк.
В "ZX-SPECTRUM" процесс обращения к ОЗУ синхронизирован сигналом MREQ от Z80, который подается непосредственно на входы RAS микросхем ГО65РУ5. Вся информация в памяти гарантированно регенерируется через каждые 128 команд программы. Согласно справочным данным, время регенерации ^ef для микросхем К565РУ5 должно быть не более 2 мс, иначе информация в ОЗУ "потечет". Это условие для компьютера "ZX-SPECTRUM" выполняется без особого труда, т.к. ^ef при работе обычной программы составляет величину примерно от 150 мкс (для 4-тактных команд) до 900 мкс (для 23-тактных команд).
Под словом "обычная программа" подразумевается программа, не использующая установку регистра R. Из ассемблера к регистру R можно обратиться через команды LD A,R и LD R,A.
В свое время, применение регистра R для обслуживания динамической памяти значительно упростило схему компьютера "ZX-SPECTRUM", т.к. отпала необходимость в применении специальных мультиплексоров и счетчиков регенерации.
Следует отметить, что в фирменном "ZX-SPECTRUM-48" регенерация памяти на регистре R была осуществлена только для верхних 32 кБайт памяти по адресам #8000 - #FFFF. Видео-ОЗУ и часть памяти по адресам #4000 - #7FFF, были выполнены с постоянной принудительной регенерацией от синхросчетчиков компьютера. Такой тип архитектуры компьютера называется - "с раздельными полями памяти".
Существуют модели, где вся память регенерируется через регистр R или от синхросчетчиков. Подобный тип архитектуры компьютера называется - "с общим полем памяти".
ЧАСТИЧНАЯ РЕГЕНЕРАЦИЯ ОЗУ
Использование регистра R в программах для "ZX-SPECTRUM" является экзотикой. Как правило, программисты обращаются к регистру R в двух случаях: для получения псевдослучайной величины и для организации циклической защиты от просмотра программ методом "заксоривания"
Еще один нестандартный прием программирования пришлось применить, решая практическую задачу - измерение периода регенерации ^ef микросхем К565РУ5. Для этого необходимо было организовать частичную регенерацию ОЗУ, т.е. в какой-то части памяти в течение определенного отрезка времени не должны были восстанавливаться данные.
"Сердцем" программы измереня ^ef является кодовый блок "активной" задержки на регистре R, который предлагается к детальному рассмотрению.
Понимание работы программы невозможно без изучения временной диаграммы (рис. 1) цикла выборки команды микропроцессора Z80 (Дж. Коффрон. Технические средства микропроцессорных систем. - М.: Мир, 1983).
|<== Цикл М1 выборки команды ==>|
| T 1 | T2 | Т3 | t4 | ! --- --- --- --- --- !
/ / / / / !
CLK
V PC V R+(A8-A15) V ! A0-A15 / / / !
MREQ
/ / / /
I
V
Регенерация 1 Регенерация 2
РИС. 1
Циклом выборки начинается выполнение любой команды Z80, как однобайтной, так и многобайтной.
В начале такта T1 содержимое 16-разрядного счетчика команд РС подается на адресную шину A0-A15. Через половину периода следования тактовых импульсов CLK (Z80, вывод 6) происходит активизация сигнала MREQ (Z80, вывод 19). Так как MREQ в "ZX-SPECTRUM" подан непосредственно на входы RAS линейки микросхем
К565РУ5, то в этот момент происходит первая регенерация информации в строке ОЗУ с адресом, определяемым младшими 7 разрядами счетчика адреса РС.
Такт T2 - подготовительный, микропроцессор анализирует внешние сигналы.
Такт T3 и T4 цикла выборки команды специально предназначены для регенерации динамической памяти.
В начале такта T3 процессор выставляет на адресную шину адрес регенерации, где младшие 8 разрядов определяются содержимым регистра R. Старшие 8 разрядов A8-A15 остаются неизменными. По спаду сигнала MREQ происходит вторая регенерация информации в ОЗУ.
Итого, за один цикл M1 восстановление данных в памяти происходит дважды. Если младшие 7 разрядов счетчика РС и регистра R совпадают, то будет регенерирована дважды одна и та же строка ОЗУ, а если не совпадают - то однократно две разные строки ОЗУ.
В листинге 1 приведен дизассемблированный блок кодов, выполняющий функцию задержки с "активной" паузой на регистре R. В таблице 1 расписаны состояния счетчика команд РС и регистра R в процессе работы программы.
ЛИСТИНГ 1
LD B,#10 ; Задержка на регистре В. LD A,#02 ; Начальная установка А. JP L1 ; Начало цикла В. L2 DEC DE ; Уменьшение счетчика. ED 4F LD R,A ; Установка R.
15 DEC D ; Проверка на
14 INC D ; достижение D=0.
20 F9 JR NZ,L2 ; Цикл DE. 10 78 DJNZ L1 ; Цикл В.
#75F8:06 10 #75FA: 3E 02 #75FC: C3 80 76 #75FF: 1B
#7600 #7602 #7603 #7604 #7606
#7680: ED 4F L1 LD R,A ; Установка R.
#7682: 11 00 21 LD DE,#2100 ; Задержка на регистре DE.
#7685: C3 FF 75 JP L2 ; Начало цикла DE.
ТАБЛИЦА 1
i Цикл задержки DE j Цикл задержки В j АДРЕС j j j
i 7 младших разрядов j 7 младших разрядов j ^четчика РС j регистра Rj счетчика РС j регистра R
#75FF j #7F
#02 (#07) j #00 #01 j #02 (#06)
#03 #04 j #05
j #04 #05 j #05 #06 #07 j #06 j
... j
#7600 #7602 #7603 #7604 #7606
#7680 #7682 #7685
I
j #00 #01 j j #02 #03 #04 j j #05 #06 #07 j
L===========================================================-
Для увеличения длительности паузы, в программе применены два вложенных цикла задержки на регистах B и DE.
Собственно "активная" пауза начинается со строки #75FF. Далее, в процессе работы программы, счетчик адреса РС поочередно принимает значения #75FF - #7607 и #7680 - #7687. При этом 7 младших разрядов A0-A6 (PC) на шине адреса в режиме "Регенерация 1" (рис. 1) будут принимать 9 дискретных значений: #7F, #00-#07.
В то же время в регистр R в строке #7680 заносится начальное число #02, и при выполнении очередной команды значение R будет увеличиваться на единицу. В таблице 1 показаны изменения младших 7 разрядов счетчика команд РС и регистра R в двух циклах DE и B при точке отсчета #7600. Обратите внимание, что по команде LD R,A регистр R меняет свое значение дважды: в самом начале увеличивает свое значение на единицу, а в конце принимает значение аккумулятора A.
В итоге 7 младших разрядов A0-A6 (R) шины адреса в режиме "Регенерация 2" будут находиться в диапазоне #02-#07.
Таким образом, в цикле "активной" паузы регенерация информации происходит не во всех 128 строках ОЗУ, а лишь в 9 строках с порядковыми номерами #7F, #00-#07. Причем часть программы по адресам #7680-#7687 будет находиться под регенерационной защитой #75FF-#7607.
Меняя значения начальной установки регистра R, а также расширяя "тело" задержки, можно увеличить количество регенерируемых строк ОЗУ по своему усмотрению. При частичной регенерации появляется возможность разместить программу в ОЗУ "кусками" под защитой регенерируемых строк.
Измерение периода регенерации микросхем памяти является частной задачей, что, однако, не ограничивает применение самой идеи в других областях, например, для определения архитектуры компьютера, для организации защиты программ, для изощренного наказания за несанкционированное копирование и т.д.
А.Астафьев, г.Новосибирск.
Теперь пару слов об аппаратной части Спектрума. А точнее речь пойдет о сигналах INT и скорости работы. На примере некоторых программ - Arkanoid, Shosk и т.д. всем нам пришлось убедиться, что, увы, лишь немногие отечественные копии знаменитого Spectruma в полной мере совместимы с оригиналом. Как правило, расхождения приходится наблюдать в качестве графики. Происходит это по следующей причине.
Так как в Спектруме-48 отсутствует вторая экранная область, то это не позволяет применять технику работы с двумя видеообластями и заставляет искать альтернативные пути. Одним из способов является способ кэширования видеообласти или ее части. Такой кэш называется rome buffer. Изображение сначала строится в видеобуфере, который, кстати, имеет более простую структуру, нежели экран. Примеров можно привести массу - все три Savage, Turtles, Three Weeks in Paradise, Xecutor, Slap Fight, Chase H.Q., Rex'S и огромнейшее колличество остальных.
К сожалению, недостатком данного метода является то, что буфер занимает от 4 до 6K памяти, и на перекидку этого буфера в экранную область процессор затрачивает очень много времени, в то время, как процедуру перекидки всеми средствами стараются сделать как можно быстрее. Из-за огромных потерь времени такие программы, как правило, никогда не успевают синхронизироваться с частотой кадров - 50 Hz (что всегда обеспечивает исключительно плавную графику), и работают, в лучшем случае, с частотой 5-25 Hz. Это заставляет искать менее совершенные, но более быстродействующие методы. Многие программисты
останавливаются на синхронизированном с разверткой выводе на экран. При таком методе работы необходимо изменить картинку на экране (содержимое видеообласти) либо до того, как луч прошел по ней (или ее активной части), либо уже после этого, но, ни в коем случае, не во время пересечения лучем развертки активной части экранной области.
"Подловить" луч можно очень просто - на фирменной машине точно с началом обратного хода по кадрам приходит сигнал INT. Программно определить момент прихода INT можно разными способами. Можно командой HALT, и Z80 остановится до прихода очередного INT, можно разместить процедуры обработки экрана в самой Interrupt Service Routine -ISR ( программа обработки прерываний). Или же заставить ISR изменять какую-либо переменную, и по ней судить о наличии прерывания, или как-нибудь еще. После того, как момент начала сканирования растра зафиксирован, пока луч идет по верхнему бордюру, программа стирает спрайты из видеообласти. Затем, когда вся "старая" графика стерта, и луч развертки не дошел до изображения, программа все перерисовывает заново. Если не успеть поставить перед лучем графику - луч просто-напросто зафиксирует ее отсутствие, и мы ничего не увидим, т.к. стереть уже стерли, а выставить не успели.
Альтернативным способом является другой - когда перед тем, как луч пойдет по видеообласти, мы выставляем всю графику, а когда луч развертки прошел видеообласть - мы все стираем (данный способ и работает в первом ArkanoidS). Таким образом, как видим, существуют моменты, когда на экране отсутствует большинство подвижных спрайтов! Естественно, опытные программисты все это отлично понимают и пытаются сделать все без сучка и задоринки, для чего приходится очень точно (!) синхронизировать все записи в экранную область памяти.
Ну, а что же получается на отечественных вариациях Спектрума? Мало того, что на большинстве машин сигнал INT приходит вообще как попало - соответственно правильная привязка к лучу развертки может вообще начисто отсутствовать, но еще и соотношение скорости Z80 к лучу совсем иное! На этом месте следует, пожалуй, разъяснить про какое еще отношение скорости идет речь. А в виду я имею вот что. Даже сделав идеальное время прихода сигнала INT, не удастся полностью скопировать фирменный Спектрум. Дело в том, что на фирменной машине Z80 работает чуточку медленнее, чем на отечественных вариантах (за исключением редких случаев, когда наши спектрумы даже медленней чем фирменные). Ну, а к чему это приводит - можете судить сами.
Во-первых, как я объяснял выше, сначала, перед приходом луча, спрайты стираются. Если этот процесс протекает быстрее, чем на фирменной машине, а как правило так и бывает, то процессор, естественно, успевает стереть/выставить графику, и мы ничего не замечаем. Все вроде бы гладко. Но дело в том, что на фирменной машине процессор в разные моменты времени работает по разному, а именно - пока луч идет либо по верхнему, либо по нижнему бордюру, Z80 работает немного быстрее! Иными словами, Z80 делает "рывок вперед", а на отечественых спектрумах процессор практически везде работает равномерно. Это то и приводит к тому, что выводя графику данным методом, отечественная машина зачастую стерев спрайты, не успевает их выставить, как задумывал программист на на оригинальном Спектруме, и спрайты начинают "моргать", исчезать, искажаться в верхней части экрана.
Аналогичным образом, правда уже из-за того, что большинство отечественных машин имеют скорость работы большую чем фирменный Спектрум, неправильно работает и масса программ с выводом спрайтов, аналогичным Arkanoid-1. Здесь беда уже в том, что мячик, тварей и битку мы поставили, но пока луч еще не прошел по ним - мы начинаем все стирать. Таким образом, исчезают спрайты внизу экрана.
Из всех отечественных машин наиболее близко к фирменной машине приближается
"Ленинградский вариант" Сергея Зонова. Но так было до недавнего времени. Сейчас народные умельцы пытаются дорабатывать известные вариации совковых версий Спектрума, и народ начинает соображать что же ему нужно.
В свое время, за неимением лучшего, мне пришлось дорабатывать "Ленинградку". Из-за того, что скорость процессора ну никак не похожа на скорость работы Z80 фирменного спектрума - пришлось изобретать что-то иное. Я решил плавно сдвигать сигнал INT. Конечно, говорить о полной совместимости не приходится, но по крайней мере, в большинстве программ - Shase H.Q. 128, Arkanoid, Dark Fusion перестали моргать и исчезать спрайты. Аналогично, появились и MULTOCOLOR -эффекты в массе фирменных программ - Xecutor, Zunaps, Octan, Puzznik и массе других ( GUTZ, AGENT -X, URIDIUM...).
Настроить мою примочку лучще всего можно по игрушке Octan. Там в меню надпись Octan должна быть без "калков". Кстати, на фирменной машине в этом же самом Oktan^ кирпичная стена не красная, а красно-зеленая. Нижние половинки кирпичиков зеленые! Схема:
+5B
----+-- !
---- + +-- + 22K
! L------ !
I ь I
! !
14! 155АГ1 ! —T-+--T--— !
5! ! ! 11 !
Ji I i11 I
6 нога D40.2 -+ ! ! +......+ 0.033
! ! ! ! + __II II
( кс ) 3! ! ! !10 --T----- + ! ! +-------
I I ! ! ! ! ! Ill II ! 4! ! ! !1 Г1 II1
+-- + ! ! +------ К формирователю INT,
! L--+-T--+— на конденсатор RC-цепи
! 7!
I ' I ! !
I I
-+- -+-
Все это дело работает у меня уже года три. Обладателям "Ленинграда" напомню, что иногда плата работает медленней чем нужно. В таких случаях помогает конденсатор между землей и 11 ножкой D4 (в некоторых случаях ставят между землей и 12 ногой D4). Емкость конденсатора лежит в пределах 100-1000 пикофарад.
Теперь о другом. Хочу предложить команду, которая способна заменить знаменитую команду LDIR для перекидки блоков памяти. Эта команда на байт длинее, чем LDIR - ее длина составляет три байта, но зато работает она быстрее!!! Выглядит она так:
CALL #33C3 или CD C3 33. Пример использования:
LD ^,откуда
LD DE,куда LD ВС,сколько
CALL #33C3 ; перекидка блока (как LDIR)
По адресу #33C3 находится конец процедуры " MOVE A FLOATING-POINT NUMBER" и выглядит он следующим образом: LDIR, RET. Переход по этому адресу используется, как правило, для перемещения блока программы и его старта. Делается это так:
LD ^,откуда LD DE,куда LD ВС,сколько PUSH DE JP #33C3
При этом пересылаемые данные могут затереть этот блок, чего нельзя было бы сделать, если бы вместо JP #33C3 стояло бы LDIR: RET. Вот поэтому эта точка и используется. Более скоростная работа команды LDIR внутри Спектрума объясняется тем, что в оригинальном компьютере, Z80 не тормозится при работе с ПЗУ . То же касается практически всех вариантов отечественных Speccy (хотя бывают и исключения). Команда же LDIR
выполняется отнюдь не "внутри процессора", а скорее как LDI: JP PE,$-2, то есть я хочу сказать, что команды циклических обработок цепочек как бы "постоянно выполняются" - т.е. генерируют в процессоре сигнал M1 и допускают реакцию на прерывание, не окончив своего цикла, и так далее... Вот поэтому есть разница в скорости выполнения LDIR, хотя и маленькая. Но если пересылается (или сдвигается) блок солидных размеров - это уже можно применять. Остается добавить - не забывайте, что в ПЗУ Спектрума процедуры работают быстрее - это особенно касается процедур #0556 (LOAD BYTES) и #04C2 (SAVE BITES)! Для расчета экранных координат нетабличным методом, можно использовать #22B1. Работает она быстрее, чем ее более короткие варианты на страницах журнала. В BC задайте YX координаты, потом дайте LD A,B: CALL #22B1. На выходе будет HL - адрес в экране, А - номер пиксела в байте.
Крюков А., г.Северодвинск.
В ZX РЕВЮ 96/1-2 была напечатана статья о доработке программы TASM 3.0 с целью запуска ее на компьютерах, на которых не проходит команда OUT (#FD),A.
После прочтения заметки у меня возникла мысль подвергнуть похожей процедуре программу "FAIRLIGHT 1", которая, также, не идет на компьютерах типа "SCORPION".
Итак: "FAIRLIGHT 1", версия 128 K, дисковая версия V. MAKAREVICH 1991 год.
При помощи DISK-DOCTORS ищем следующие последовательности байтов (строчкой ниже измененный байт).
3E 14 |
32 33 B7 |
54 |
|
3E 11 |
32 33 B7 |
51 |
|
3E 10 |
32 33 B7 |
50 |
|
3E 13 |
D3 FD |
53 |
|
3E 10 |
D3 FD |
50 |
|
3E 13 |
D3 FD |
Я прошел программу до конца - все работает нормально.
Несмачный Д., г. Москва
К вопросу Максима Аржиловского в рубрике "Что бы это значило?". ZX РЕВЮ 95/6, стр 39.
Недавно перечитывал ваш журнал и наткнулся на эту загадку. Я уже и раньше сталкивался с таким эффектом в своих программах в машинном коде. Все дело в частоте кадровой развертки, довольно медленной, по сравнению с частотой работы процессора. Каким образом работает эта программа?
Она попеременно то стирает то вновь записывает эти буквы ("О.К."). Так вот, в тот момент, когда буквы стираются, происходит смена кадра, и из зрения выпадает момент, когда кадр чист. То есть, мы видим вроде бы не мерцающую надпись. Однако, поскольку частота смены изображений и частота кадровой развертки не синхронизированы, то мерцание все-таки происходит, хотя и довольно медленное (медленнее чем пульсация данных в экранной области памяти). Десятая же строка замедляет работу программы настолько, что кадровая развертка уже успевает за программой и не гасит циклы. Более интересный эффект получим, если подставим в 10 строку REM, а 30 запишем так:
30 GOTO 20
Эффект сработает только в том случае, если строки расположены в начале программы.
Спасибо Максиму. До него я не знал, что этот эффект можно получить и на медленном BASICS.
Токарев Игорь Николаевич из г. Мирный обнаружил некоторые неточности в листинге программы "V_PRINT", опубликованной в ZX-РЕВЮ 96/1-2, стр.53.
Для нормальной работы машинного кода необходимо внести изменения в следующие строки:
240 CALL CLBUF 980 INITPR LD A,#88 990 OUT (#7F),A
В строке 1040 для принтера без автоперевода строки (в частности для "Электроники МС6313") в аккумулятор надо грузить не 12, а 24.
Для тех, у кого есть ПК "Scorpion ZS 256", для адаптации этой программы достаточно изменить следующие строки:
980 INITPR LD A,27
1760 ; DRIVER FOR "Scorpion ZS 256"
1770 PRINTR PUSH AF
1780 RST #8
1790 DEFB #80
1800 POP AF
1810 RET
1820;========================
и удалить строки 990, 1000, а также 1830-1880.
При этом, если при работе принтера помигивает индикатор режима "TURBO", то это говорит о том, что "процесс идет" нормально.
(C) Артамонов Алексей
г.Москва 1996
Хочу поделиться своими мыслями по поводу анимации спрайтов в программах. Я думаю, что у читателей Ваших изданий не возникнут проблемы с выводом спрайтов на экран, т.к. по этому поводу было напечатано достаточно информации. Я решил написать о том, как можно "заставить" спрайты вести себя по-разному. Мой способ нельзя назвать самым простым, но и сложным его тоже называть не стоит. Мой способ заключается в том, что где-то в памяти, не важно где, отводится место под очередь спрайтов, в которую помещаются адреса или номера спрайтов, которые могут встретиться на этом уровне игры или во всей игре. Затем Вы разрабатываете формат описания спрайта (структуру описания спрайта). Поля в этой структуре будут зависеть от типа спрайта, но одно поле в этой структуре должно быть обязательно. Это поле находится в самом начале структуры и в него заносится адрес процедуры, которая обрабатывает этот спрайт. Назовем эту функцию sprite-функцией. Для одинаковых спрайтов, т.е. спрайтов одного типа, эта функция должна быть одна и та же, хотя это и не обязательно. Вы также пишите функцию, которая будет обслуживать очередь спрайтов. Действия этой функции заключаются в том, что она, сканируя очередь, выбирает адрес или номер спрайта (в зависимости от формата очереди спрайтов) и вызывает sprite-функцию данного спрайта. Этот процесс продолжается до тех пор, пока не будут обработаны все спрайты из очереди, после чего все повторяется сначала. Алгоритм этой функции не кажется мне сложным и вряд ли нужно писать ее пример. Теперь рассмотрим действия, совершаемые sprite-функцией. Эта функция, в зависимости от спрайта, может сама выводить его на экран, или вызывать общую функцию для вывода спрайтов, или же комбинировать оба способа. Она также должна, используя дополнительные данные из структуры спрайта, изменять его состояние, порождать новые спрайты, или же, наоборот, удалять их из очереди. Именно эта sprite-функция отвечает за поведение спрайта. Приводить текст этой функции не имеет никакого смысла, т.к. для каждого типа спрайта она будет своя. В заключении хочу сказать несколько слов о размере очереди спрайтов. Конечно, Вы должны его определить сами, но я советую Вам не увлекаться, т.к. это приведет к расходу памяти и, что более важно, к снижению быстродействия игры. Обычно 25-30 спрайтов на уровне вполне достаточно для большинства игр. Надеюсь, Вы поняли суть идеи, и у Вас уже появились и мысли по этому поводу.
(с) Павел Федин, г.Москва.
Здравствуйте, все! Я прочитал в ZX-РЕВЮ 4-5/1996 статьи О. Литвинова и П. Лебедева по поводу TR-DOS и теперь хочу на них ответить, а также привести некоторую информацию о своих планах относительно развития SPECCY. Итак, начну по порядку. Во-первых, Хочу прояснить ситуацию относительно глюков в загрузчиках, о которых упомянул О. Литвинов. В журнале ZX-FORMAT N3 уже освещалась эта тема и был дан способ исправления ошибки в ПЗУ, вызывающей это явление. Во время написания своего дизассемблера ПЗУ я, конечно же, не мог ее не заметить, но должен сказать, что способ исправления ошибки, приведенный в ZX-FORMATе, можно немного модифицировать, сэкономив немного памяти. Мой вариант я опробовал на недоделанной мной TR-DOS 6.01. Также считаю нужным описать причину странного поведения дисковода. Итак, назначение точки входа #3EB2 - определение физического номера дорожки, на которой стоит головка. Это нужно для того, чтобы каждый дисковод мог правильно позиционироваться. Ведь эта операция нормально выполняется только если в регистре дорожки ВГ-93 находится номер текущей дорожки. Но регистр то один, а дисководов - до четырех, поэтому каждый раз при обращении к дисководу приходится устанавливать регистр дорожки "вручную". Для того, чтобы лучше вникнуть в суть дела, я приведу текст начала подпрограммы #3EB2. Он выглядит так:
#3EB2 CALL #1FEB ;выбор верхней стороны диска, на случай, если он односторонний IN A,(#1F) ;запоминаем бит готовности дисковода (смысл неизвестен, хотя AND #80 ;он используется подпрограммой позиционирования на логический LD (#5CCD),A;трек. Если он равен 1, то после позиционирования происходит ;задержка).
IN A,(#3F) ;берем текущее значение регистра дорожки (для раскрутки диско-;вода).
LD H,A ;помещаем его в H (на случай ошибки чтения). CALL #3E44 ;позиционирование на физическую дорожку с номером в A. Поскольку этот номер взят из регистра дорожки, то головка двигаться не будет, но дисковод закрутится. Далее чтение адресного маркера и помещение в H номера текущей дорожки.
При вызове #3E44 в регистре B должна быть константа позиционирования (8 -11). Но, как видите, в регистре B может быть все, что угодно. Вот и глючит дисковод. Ну так вот, в журнале сказано вместо CALL #3E44 поставить CALL куда-нибудь в пустоту, где и разместить следующую подпрограмму:
PUSH HL ;сохраняем регистры PUSH AF
CALL #3E08;берем константу позиционирования для текущего дисковода
LD B,A ;помещаем ее в B
POP AF восстанавливаем регистры.
POP HL
JP #3E44 ;дальше все как было, только уже без глюков
Мой способ почти такой же, только я поменял не CALL #3E44, а CALL #1FEB. Благодаря этому, теперь не надо сохранять регистры. Включаемый фрагмент теперь выглядит так:
CALL #3E08 LD B,A JP #1FEB
Тем, кто будет произвдить у себя сию доработку, советую попробовать разместить эту подпрограммку по адресу #3С33. Дело в том, что в моей версии TR-DOS она размещена именно там. Только не подумайте, что я считаю себя пупом земли, просто я считаю, что такие вещи должны быть стандартизированы, дабы избежать несовместимости. Конечно, если при этом будет выявлена несовместимость с существующим программным обеспечением, придется подыскать другой адрес, и я в таком случае тоже буду глобально переделывать свои доработки в TR-DOS 6.01.
Теперь по поводу письма Павла Лебедева об обращениях к портам ВГ-93. У меня стоит TR-DOS 5.04T. В ней нет НИ ОДНОЙ подпрограммы прямого ввода из какого-либо порта. Я не видел стандартную версию TR-DOS 5.03 и, к сожалению, не могу ничего сказать по поводу того, что находится у автора письма по адресу #09BF. Но могу кое-что посоветовать. Проверку на "стандартность" можно провести так: включите монитор в режим DUMP и просто пробегитесь по всему ПЗУ. Иногда там можно найти нечто интересное типа подписи настоящего автора прошивки. Если она есть, то, скорее всего, это не стандартная версия, хотя повторяю: Я НЕ ВИДЕЛ СТАНДАРТНЫХ ВЕРСИЙ. Также я поддерживаю идею автора и сообщаю адреса своих подпрограмм вывода в порты ВГ-93:
#1E3A OUT (#3F),A RET
#1FF3 OUT (#FF),A RET
#2F0C OUT (#FF),A RET
#2FC3 OUT (#1F),A RET
#2A53 OUT (C),A RET
По идее, эти точки входа должны быть у всех пользователей TR-DOS 5.03 и производных, так как они являются частями рабочих подпрограмм TR-DOS.
Также, я знаю ответ на вопрос Андрея Рубина относительно странного поведения редактора командной строки TR-DOS. Дело в том, что автор сильно ошибается, думая что при работе в TR-DOS "SOS и не пахнет". На самом деле при работе в TR-DOS машина большую часть времени проводит именно в ПЗУ бейсика. Оттуда и все его атавизмы, такие как имена файлов в кавычках, возможность использования бейсиков-ских переменных и выражений вместо числовых параметров в командах, а также и то, на что обратил внимание автор. Дело тут в том, что строку-то вводит не DOS, а все тот же бейсик. В нем есть подпрограмма #0F2C, выполняющая редактирование строки при вводе программ, команд, данных. Она же следит за видом курсора, отрабатывает нажатие клавиш "вверх", "вниз" и EDIT. По нажатию ENTER происходит выход из редактора и возврат туда, откуда он был вызван. Как вы уже догадались, TR-DOS не вводит строку сама, а просто вызывает #0F2C из ПЗУ бейсика. Редактор исправно вводит команду, между делом опрашивая все служебные клавиши и отрабатывает их так, как и положено бейсику. По нажатию ENTER происходит возврат в TR-DOS, и она начинает обрабатывать строку как свою команду. Она берет первый символ строки и проверяет его по списку ключевых слов. Если это слово ей не знакомо, то она просто проглатывает строку без всяких замечаний и возвращается в командный режим. Вот и исчезает строка из программы при вводе.
Кстати, с этим связан еще одно интересное явление. Поскольку команды в TR-DOS идентифицируются по первому символу строки, то ввод бейсик-строки с номером, начинающимся на 4 или 8 повлечет за собой выполнение команды 40 или 80 соответственно. Это связяно с тем, что в TR-DOS синтаксический контроль сильно упрощен, и ей все равно, что будет стоять после 4 и 8 - лишь бы что-то стояло.
Ну а теперь - "гвоздь программы". В последнее время среди здравомыслящих людей стала часто звучать тема о смене встроенного программного обеспечения на SPECCY. Разрешите присоединиться. Итак, наш проект - новые DOS и BIOS вместо бейсика-128. Концепция следующая: из ПЗУ удаляется никому не нужный бейсик-128, и туда прошивается BIOS - программа, организующая работу с аппаратными средствами компьютера. В начальных адресах ПЗУ записывается керналь - куча JP, ведущих на сами подпрограммы. Обращаться к ПЗУ можно только через эту часть. Таким образом можно изменять и улучшать содержимое ПЗУ без потери совместимости. В ядро BIOS войдут подпрограммы для работы с расширенной памятью, винчестером, принтером, мышью, энергонезависимой памятью, часами. Слышим крики: "для какого компьютера?!!!!" ДЛЯ ЛЮБОГО! Ведь ПЗУ можно менять как угодно. Тогда можно выпустить версии BIOS для Пентагона, Scorpion'a, PROFI, ATM и прочих машин, которые сильно различаются портами управления дополнительными ресурсами. Ведь уже не надо обращаться к портам напрямую. Например, надо установить такую-то страницу памяти - помещаем ее номер в аккумулятор и вызываем, скажем, RST #20. По каким портам управляется память - забота не ваша, а BIOS-а. И так со всем железом.
Новому BIOS-у нужна и новая DOS. Хорошая, гибкая система, с возможностью подключения своих драйверов устройств - вдруг в ПЗУ такое устройство не предусмотрено. Про сегментированные файлы с большой длиной и говорить не надо - тут и так все ясно. Работа уже начата. Если кто-то хочет высказать свое мнение по этому поводу - пишите. С радостью выслушаем. Ведь навернякя каждый человек сможет предложить что-то ценное. Неплохо было бы, если бы ИНФОРКОМ выделил в своем журнале немного места специально для обсуждения этого проекта. Ведь это такое дело, которое надо делать всем вместе. Надеюсь, что вы заинтересуетесь и ответите. Также предлагаем вам самим придумать название нового DOS'a. Ждем предложений.
(C) Федин Павел, 10.07.1996.
Проект BIOS-96 разработан совместно API Soft и Scorpion Club.
ИНФОРКОМ, как всегда, к Вашим услугам - идея очень перспективная!
(С) Николай Михайлов
Алтайский край, 1996
Точная дешифрация портов #1F и #FE в "Ленинграде -1"
В "Ленинграде-1" клавиатура и джойстик обслуживаются одними и теми же микросхемами D37,D38 (555КП11). А дешифрация портов ввода - вывода выполнена настолько грубо, что все выходные порты 0...254 работают как порт 254 (#FE), а выходные порты все четные - 254, все нечетные - 31, т.к. используется только один адрес - А0. С этим и связаны все проблемы, о которых немало написано на страницах "ZX-РЕВЮ".
Я предлагаю раз и навсегда закрыть эту тему, тем более, что возможности в "Ленинграде-1" для этого созданы. Соберите только в дополнение предлагаемую схему.
Клавиатура читается только как порт #FE(254), кемпстон-джойстик - как порт #1F(31), любые другие порты свободны, т.е. при чтении из них на шине данных #FF.
Рассмотрим более подробно: DD1,DD2.4 - точная дешифрация адреса #FE'; DD5,DD4 - точная дешифрация адреса #1F'.
Сигнал IOWRFE' подключают к выводу 9 D39 (555ТМ9).
Сигнал 1F переключает каналы мультиплексоров D37,D38 следующим образом: "1" - чтение состояния джойстика; "0" - чтение клавиатуры.
На DD2.1, DD2.2, DD3.2 собрана схема переключения D37,D38 в третье состояние: мультиплексоры работают только при выборе сигналов IORD', FE',1F'. Для любого другого порта на шине данных #FF, т.е. мультиплексоры отключены.
Можно проверить:
10 FOR I=0 TO 254
20 PRINT IN I, "I="; I
30 NEXT I
Для порта #1F(I=31) будет напечатано 0, для любого другого - 255. Для порта #FE(I=254) будет напечатана цифра, отличная от 255 только при нажатой клавише клавиатуры.
Таким образом сигналы джойстика не мешают при чтении программы с магнитофона, т.е. незадействованные входы 6,10,13 D38 можно и нужно заземлить, нагрузочные резисторы джойстика заменить на 1 Ком, а их общую точку соединить с "землей" и использовать джойстик с контактами на
замыкание.
ИФК: Колесов Александр из Ростова-на-Дону советует всем, кто пользуется Мини-драйвером дисковых операций (ZX-РЕВЮ 4/95), внести в него несколько изменений.
КОРР: Предлагаю доработку, позволяющую получить релоцируемый вариант Мини-драйвера.
Для начала строки 25, 36 и 51 (здесь и далее ссылки на исходный вариант А.Алексеева) переделываем следующим образом:
25 CALL #007C CD 7C 00 JR DOS 18 64
36 CALL #007C CD 7C 00 JR DOS 18 4F
51 M3: CALL #007C CD 7C 00 JR DOS 18 2E
Как видим, все сводится к замене команды CALL DOS на CALL #007C и относительному переходу на метку DOS.
Далее, ввиду того, что после внесенных изменений длина программы увеличилась на шесть байтов, исправляем следующие строки:
63 M4: DJNZ L3 10 CE 67 DJNZ L1 10 B0
И, наконец, самое главное. Переделываем программу (это еще шесть дополнительных байтов) начиная со строки 78 (метка DOS):
78 DOS: DEC SP 3B DEC SP 3B EX (SP),HL E3 INC HL 23 INC HL 23 EX (SP),HL E3 PUSH IX DD E5 JP #3D2F C3 2F 3D END
Из всего вышесказанного ясно, что изменения коснулись только способа вызова подпрограмм из ПЗУ TR-DOS. Теперь коментарии.
После того, как отработает всем известная (см. например, ZX-РЕВЮ 95/1) конструкция CALL #007C, по команде JR DOS попадаем на метку DOS и получаем на стеке адрес следующей за CALL #007C команды, в нашем случае - это JR DOS:
DEC SP DEC SP
Помещаем содержимое вершины стека (т.е. адрес возврата) в HL, а HL сохраняем на стеке: EX (SP),HL
Увеличиваем значение адреса возврата, чтобы после выхода из подпрограммы ПЗУ TR-DOS "проскочить" JR DOS: INC HL INC HL
Возвращаем на стек новый адрес возврата и восстанавливаем HL: EX (SP),HL
А теперь, как обычно, помещаем на стек адрес подпрограммы из ПЗУ TR-DOS и переходим на ее исполнение: PUSH IX JP #3D2F
Вот и все. Смело набирайте и пользуйтесь: пашет как зверь!
ВЫЗОВ TR-DOS ИЗ МЕНЮ БЕЙСИКА-128
Интересное письмо прислал нам Бандура Сергей Иванович г. Николаев. КОРР: Как справедливо заметил Paul Smith (ZX-Ревю N1-2, 1996г., стр.48) от Бейсика-128 "одна морока с загрузкой программ". Кроме того, занят буфер принтера, невозмжно использовать LPRINT-III, есть проблемы с некорректной обработкой редактором Бейсика-128 управляющих кодов, вставляемых для затруднения просмотра текста программ.
Ниже предлагается доработка ПЗУ Бейсика-128 (ROM0), при вызове TR-DOS переводящая машину в режим, который можно назвать "48K с открытым портом".
Идею и саму программу перевода я подсмотрел в загрузчике к TASM2.0 (сам ассемблер не работает). Режим отличается тем, что устанавливаются стандартные каналы ввода-вывода, работает редактор Бейсик-48, но сегменты ОЗУ и экран можно переключать при помощи OUT 32765,N, так что тестирующие программы определяют режим как 128K. При этом в любой момент возможно OUT 32765,48 -закрыть порт и установить стандартный режим 48K.
Поскольку ПЗУ Бейсика-48 (ROM1) не изменяется, не возникает проблем с совместимостью.
Дальнейшее описание сделано с допущением, что копия ПЗУ Бейсик-128 загружена в ОЗУ с адреса #8000.
Доработки сводятся к следующему:
1. Адрес #A75E: сообщение Tape loader заменяем на TR-DOS; сообщение Tape tester заменяем на Tape loader. Старший бит в последнем символе каждого байта должен быть установлен в 1 (+#80).
2. По адресу #A746 заносим #16; по адресу #A752 заносим #31 (меняем местами).
3. По адресу #B853 заносим #84; по адресу #B857 заносим #5E (тоже меняем местами).
4. С адреса #BBE9, на месте блока Tape tester, размещаем такую программу:
ORG #BBE9 DI
LD DE,#5B00 LD HL,#3BF8 LD BC,#002F LDIR JP #5B00 LD A,#10 LD BC,#7FFD
OUT (C),A ;включаем ПЗУ 48K LD SP,#FF54 LD HL,#1303 PUSH HL
LD (#5C3D),SP стандартная LD HL,#1BB0 ;процедура об-PUSH HL ;работки ошибок
LD HL,(#5C4F) ;стандартный
LD DE,#000F ;канал принтера
ADD HL,DE
LD DE,#1B5E
EX DE,HL
LD BC,#0004
LDIR
RES 4,(IY+1) ;признак стан-;дартной конфи-;гурации
EI
JP #3D00 ;RANDOMIZE USR 15616
Теперь для запуска TR-DOS не нужно по буквам набирать RANDOMIZE USR 15616, а достаточно нажать клавишу ENTER. Пункт Tape tester исключен, ведь если есть дисковод, тестирующая программа может быть загружена с диска.