ZX-Forum №2 1993 г.

Профессиональный подход - Русификация - новые решения старой проблемы.


ПРОФЕССИОНАЛЬНЫЙ ПОДХОД

Русификация - новые решения старой проблемы

© ИНФОРКОМ, Москва, 1994.

Вот уже примерно десятилетие прошло с того момента, как "Спектрум" начал "триумфальное шествие" по нашей стране. Но до сих пор более или менее приемлемо не решен один из основных вопросов "Спектрум-Бейсика" - это его русификация. Вообще-то, существует масса способов и приёмов, чтобы заставить компьютер печатать по-русски, но у всех у них те или иные недостатки. Рассмотрим некоторые из них (ну, русификацию с помощью UDG-символов здесь рассматривать не будем, из-за практической малопригодности для серьезного дела).

Итак, первый приём, предусмотренный операционной системой - загружаемый символьный набор. Это, казалось бы, решение всех проблем: печатай хоть русским, хоть каким угодно шрифтом, переключился на загруженный символьный набор и печатай, что хочешь. Но, в том-то и дело, что надо переключаться - при помощи POKE или GO SUB, а для этого приходится разбивать фразу на русские и английские слова и выводить их при помощи отдельных операторов PRINT, а между ними-то и расставлять те самые POKE или GO SUB, переключающие символьные наборы. Зачастую, к этому приходится прибегать через слово. Да и вид листинга программы получается какой-то несуразный. Либо корявые токены и системные сообщения, напечатанные русскими буквами, либо нечитаемый русский текст, напечатанный английскими буквами. Все это выглядит не очень симпатично, хотя мы все к этому уже привыкли; а что делать? К тому же если не хочешь расставлять POKE или GO SUB, тогда есть упрощенный вариант - печатай только заглавными русскими и латинскими (это наш типовой способ русификации при помощи русско-латинского символьного набора "НС" в кодировке КОИ-7 по стандарту ASCII). А, в общем, русификация при помощи загружаемого символьного набора, хотя и не так удобна, как хотелось бы, но, в принципе, вполне приемлема, тат как конечная цель все-таки достигается.

Существует более "крутой", глобальный вариант русификации - при помощи нового ПЗУ. Вот здесь все, как по маслу: нажал кнопку и печатай, хоть русским, хоть латинским, хоть в одном операторе PRINT, хоть в разных, хоть заглавными, хоть строчными. И курсор, и листинг выглядят так, как надо. Ну, в общем, предел мечтаний. Но только до тех пор, пока сидишь за своим, русифицированным таким способом компьютером. А как только захотел показать другу только-что сделанную программу - стоп! У него-то стандартное ПЗУ. Так что способ этот хорош только для несоизмеримо малого числа компьютеров. Да и то, не всегда. Где-то из-за нового ПЗУ интересная фирменная программа перестает работать, где-то музыки нет и т.д. и т.п., в общем - несовместимость. Стандартное ПЗУ - это объективная реальность, от этого никуда не уйти, поэтому вариант с новым ПЗУ на деле оказывается не так уж хорош.

В новом ПЗУ для переключения в русский регистр и печати русских букв применяются новые канальные процедуры ввода/вывода. Из этого непосредственно следует следующий способ русификации - при помощи каналов и потоков. Стандартно, к потоку #1 подключена процедура ввода KEY-INPUT (#10A8) и процедура печати PRINT-OUT (#09F4). К потоку #2 подключена та же процедура печати. Если мы создадим для клавиатуры новую процедуру ввода, обеспечивающую переход в русский регистр по нажатию какой-либо клавиши или комбинации клавиш, а для экрана -новую процедуру вывода для обеспечения перехода к печати русских букв (изменение значения CHARS, определяющего текущий символьный набор), то, подключив эти процедуры к стандартным потокам, обслуживающим клавиатуру (#1) и экран (#2), мы можем реализовать удобный способ русификации. И всё будет замечательно: и попереключаться в РУС. и ЛАТ. можно будет вдоволь в каждом операторе PRINT, и листинг будет смотреться так, как надо, и будут доступны и заглавные и строчные и русские и латинские буквы, но все это - только до первого оператора CLS или CLEAR или до запроса "scroll?" или до нажатия ENTER для получения автоматического листинга - во всех этих случаях происходит очистка экрана (или служебного экрана - нижних двух строк) и восстановление стандартного подключения каналов к потокам. Можно, конечно, в программах после каждого CLS производить заново подключение новых процедур при помощи тех же GO SUB, но редактирование Бейсик-программы станет практически невозможным, так как восстановление стандартного включения каналов будет происходить после каждого нажатия ENTER.

В своё время мы занимались таким способом русификации, были разработаны и реализованы новые канальные процедуры ввода/вывода, но дело намертво уперлось в "CLS" и получить практические результаты тогда не удалось. Процедуры были отложены "в долгий ящик" до лучших времён или идей. И вот, сейчас, мы можем обрадовать наших читателей тем, что такие времена настали благодаря письму с Украины, из г. Черкассы, его прислал Милищук Сергей Васильевич. Он предлагает для подключения новых канальных процедур ввода/вывода использовать прерывания 2 рода. Представьте себе: только операционная система после CLS восстановит стандартное подключение каналов, а мы, при помощи IM2, вновь будем подключать их так, как нам надо. И это будет происходить 50 раз в секунду. Так что стандартное включение "продержится" максимум 1/50 долю секунды, а затем вновь подключатся наши новые процедуры. Вот программа, реализующая такой способ.

Листинг 1.

00010

;DiCHARS by Milischuk S.

00302

; Вывод

на экран

00020

;(C) 1994

00310

PRNOUT

CALL #0B03

00040

ORG

64389

00320

CALL

CHR

00050

NEW DEFW

#FC00

00330

CP

#20

00052

; Запуск программы

00340

JP

NC,#0AD9

00054

; RANDOMIZE USR

64391

00350

CP

6

00060

IM2 DI

00360

JP

C,#0A69

00070

LD

A, #FB

00370

CP

#18

00080

LD

I,A

00380

JP

NC,#0A6 9

00090

IM

2

00390

LD

HL,TCONTR-6

00100

EI

00400

JP

#0A07

00110

HALT

00410

TCONTR

DEFB

18,20,22,24,

17

00120

RET

00420

DEFB

16,15,23,13,

12

00122

; Выход из программы

00430

DEFB

41,40,39,38

00124

; RANDOMIZE USR

64401

00440

DEFB

37,36,30,29

00130

IM1 IM

1

00450

JP

#0A5F

00140

PUSH

HL

00460

JP

#0A69

00150

LD

HL,#09F4

00470

JP

#0A23

00160

LD

(#5CBB),HL

00480

JP

#0A3D

00170

LD

(#5CC5),HL

00490

CALL

HOME

00180

POP

HL

00500

JP

#0A4F

00190

EI

00510

PTV2

LD

DE,PCONT

00200

HALT

00520

LD

(#5C0F) ,A

00210

RET

00530

JR

PCHANG

00212

; Обслуживание

00540

DEFW

I NT

00214

; прерываний 2 ;

рода

00550

P2OP

LD

DE,PTV2

00220

INT PUSH

HL

00560

JR

PTV1

00230

LD

HL,KEYIN

00570

P1OP

LD

DE,PCONT

00240

LD

(#5CB8) , HL

00580

PTV1

LD

(#5C0E),A

00250

LD

HL,PRNOUT

00590

PCHANG

DI

00260

LD

(#5CB6),HL

00600

JP

#0A8 0

00270

LD

(#5CBB),HL

00610

PCONT

EI

00280

LD

( #5CC5) ,HL

00620

LD

DE,PRNOUT

00290

POP

HL

00630

JP

#0A8A

00300

JP

#0038

00632

; Ввод

00640

KEYIN

BIT

3,(IY+2)

01180

EX

DE, HL

00650

CALL

NZ,OUTPR

01190

CALL

OUTL2

00660

AND

A

01200

JP

#1144

00670

BIT

5,(IY+1)

01210

OUTL2

SET

0,(IY+1)

00680

RET

Z

01220

PUSH

DE

00690

LD

A,(#5C08)

01230

EX

DE, HL

00700

RES

5,(IY+1)

01240

RES

2,(IY+48)

00710

PUSH

AF

01250

LD

HL,#5C3B

00720

BIT

5,(IY+2)

01260

RES

2, (HL)

00730

CALL

NZ,#0D6E

01270

BIT

5, (IY+55)

00740

POP

AF

01280

JR

Z, L18 94

00750

CP

#20

01290

SET

2, (HL)

00760

JP

NC,#111B

01300

L1894

LD

HL,(#5C5F)

00770

CP

#10

01310

AND

A

00780

JR

NC,KCONTR

01320

SBC

HL, DE

00790

CP

06

01330

JR

NZ,L18A1

00800

JP

NC,#10DB

01340

LD

A, #3F

00810

LD

B, A

01350

CALL

#18C1

00820

AND

1

01360

L18A1

CALL

#18E1

00830

LD

C, A

01370

EX

DE, HL

00840

LD

A, B

01380

LD

A,(HL)

00850

RRA

01390

CALL

CHR

00860

ADD

A, #12

01400

CALL

#18B6

00870

JR

KDATA

01410

INC

HL

00880

JP

#10DB

01420

CP

#0D

00890

KCONTR

LD

B,A

01430

JR

Z,L18B4

00900

AND

7

01440

EX

DE, HL

00910

LD

C, A

01450

CALL

#1937

00920

LD

A, #10

01460

JR

L1894

00930

BIT

3, B

01470

L18B4

CALL

HOME

00940

JR

NZ,KDATA

01480

POP

DE

00950

INC

A

01490

RET

00960

KDATA

LD

(IY-45),C

01492

; Изменение символьного

00970

LD

DE,KNEXT

01492

; набора

если

символ

00980

DI

01494

; "P" в

граф.

регистре

00990

JR

KCHANG

01500

CHR

CP

#9F

01000

KNEXT

LD

A,(#5C0D)

01510

RET

NZ

01010

LD

DE,KEYIN

01520

PUSH

HL

01020

EI

01530

PUSH

DE

01030

KCHANG

JP

#1113

01540

LD

HL, (#5C3 6)

01040

OUTPR

CALL

#0D4D

01550

LD

DE, (NEW)

01050

RES

3,(IY+2)

01560

LD

(NEW),HL

01060

RES

5,(IY+2)

01570

LD

(#5C3 6) ,DE

01070

LD

HL,(#5C8A)

01580

POP

DE

01080

PUSH

HL

01590

POP

HL

01090

LD

HL,(#5C3D)

01592

; Вместо

"Р"

граф.

01100

PUSH

HL

01592

; печатать "ПРОБЕЛ"

01110

LD

HL,#1167

01600

LD

A,#20

01120

PUSH

HL

01610

RET

01130

LD

(#5C3D),SP

01610

; Возврат к исходному

01140

LD

HL, (#5C82 )

01612

; символьному

набору

01150

PUSH

HL

01620

HOME

PUSH

HL

01160

SCF

01630

LD

HL,#3C00

01170

CALL

#1195

01640

LD

(#5C3 6) ,HL

01650 LD HL,#FC00 01670 POP HL

01660 LD (NEW),HL 01680 RET

Обратите внимание на строки 260-280. Они рассчитаны на магнитофонный вариант Спектрума. Для дискового их надо изменить:

00260 LD (#5D2 6),HL

00270 LD (#5D2B),HL

00280 LD (#5D35),HL

Хотя канал принтера можно к новой процедуре и не подключать, поэтому вместо команды в строке 280 можно поставить три команды NOP.

Запуск программы происходит при выполнении RANDOMIZE USR 64391 - при этом включается режим прерываний 2 рода, подключающий новые процедуры ввода/вывода к стандартным потокам. Русский символьный набор расположен с адреса #FC00+#0100=#FD00=64768. Переключение символьного набора происходит при вводе с клавиатуры символа "Р" в графическом регистре (код=#9F). При этом процедура устроена так, что вместо графического "Р" печатается " пробел".

Перед обращением к дисководу или в иных случаях, когда требуется отключить режим IM2, это может быть выполнено командой RANDOMIZE USR 64401.

Конечно, ничего не даётся даром. Предлагаемый способ имеет и свои недостатки. Так, после оператора CLS перед первым оператором PRINT должно успеть произойти прерывание, прежде чем что-то будет напечатано на экране - иначе будут подключены ещё стандартные канальные процедуры ввода/вывода. Практически реализовать это можно, введя (если надо) после CLS задержку на одно прерывание - 1/50 секунды. PAUSE 1 - вполне для этого подходит. Сложнее дела обстоят с оператором INPUT. Как известно, в момент выполнения этого оператора происходит очистка служебного экрана - двух нижних строк - со всеми вытекающими последствиями в смысле отключения новых канальных процедур ввода/вывода. И вводом PAUSE 1 здесь проблему не решить, так как очистка экрана происходит именно в момент исполнения оператора INPUT. Поэтому приходится идти на ухищрения другого рода - заставить компьютер "долго думать", выполняя INPUT, чтобы за это время успело произойти прерывание. Сергей Васильевич советует сделать это, например, так:

INPUT CHR$(COS 0*8);" ZX_PEBKl_"

здесь символ "_" обозначает переключатель шрифтов - "Р" в графическом регистре. Относительно долгое вычисление COS, казалось бы, совсем ненужное в операторе INPUT, приводит к той самой задержке, благодаря которой успевают подключиться новые канальные процедуры. Но к оператору INPUT мы ещё вернёмся.

Хотя программа, приведенная Сергеем Васильевичем, не лишена недостатков (например, неудобное переключение РУС/ЛАТ при помощи перехода в графический регистр, а затем обратно, да и печать при этом пробела лишает возможности слитного написания русских и латинских символов), но это уже не столь важно. Главное - он предложил идею: как при помощи IM2 бороться с подключением стандартных канальных процедур ввода/вывода во время CLS. Вот тут-то и вспомнили мы о том, что где-то "в долгом ящике" лежат разработанные давным-давно процедуры ввода/вывода, предназначенные для русификации. Теперь пришло время, смахнув пыль с этих записей, извлечь их на свет Божий. Далее мы приводим наш вариант русификации при помощи канальных процедур ввода/вывода, который нам удалось довести до рабочего состояния благодаря письму Сергея Васильевича. Собственно не "процедур", а "процедуры", так как процедура KEY-INPUT не изменена, но об этом - чуть позже.

Решено было использовать следующие "шрифтовые" комбинации клавиш: SYMBOL SHIFT + ENTER - включение русского шрифта; SYMBOL SHIFT + SPACE - включение латинского шрифта.

По идее, новая канальная процедура ввода должна перехватывать нажатие заданных шрифтовых комбинаций клавиш. При разработке процедуры встал вопрос, какие коды использовать для этого. Здесь надо внести некоторую ясность. Надо четко различать понятия: "код клавиши", "вводимый код", "печатный код" и "управляющий код". И, в связи с этим, самое время сделать небольшое отступление.

Некоторые подробности, касающиеся символьных кодов.

Код клавиши - это входной параметр, а вводимый код - выходной параметр канальной процедуры ввода KEY-INPUT. Если мы вводим букву, цифру, символ или токен, то код клавиши является и вводимым кодом. Вводимые коды с 32 по 255 являются печатными кодами. А вот с кодами меньше 32 ситуация иная. Например, при нажатии клавиши INV.VIDEO на вход процедуры KEY-INPUT подается код клавиши=5; при этом на выходе из процедуры KEY-INPUT для ввода в текст Бейсик-строки выдаются управляющие коды: CHR$ 20; CHR$ 1, а отнюдь не CHR$ 5 (который для печати не используется). Запустите Бейсик-программу: 10 PAUSE 0: PRINT CODE INKEY$: GO TO 10

Нажмите клавишу INV.VIDEO - на экране напечатается "5". Остановите программу и выполните PRINT CHR$ 5. Напечатается "?" (непечатаемый код). В любом справочнике по " Спектруму" Вы сможете найти значения кодов клавиш с 4 по 15 - это редактирующие клавиши. А что же коды клавиш с 0 по 3 и с 16 по 31? Как правило, в справочниках их нет. Выходит, они не используются? Нет, это неверно. Эти коды используются канальной процедурой KEY-INPUT при нажатии цифровых клавиш в режиме EXTEND MODE - благодаря им Вы можете вставлять непосредственно в текст управляющие коды INK, PAPER, BRIGHT и FLASH. Так, например, при нажатии в режиме EXT.MODE клавишей CAPS SHIFT + 1, на вход в процедуру KEY-INPUT будет подан код клавиши 25, благодаря которому на выходе из процедуры KEY-INPUT мы получим результат: в текст Бейсик-строки будет вставлена последовательность управляющих кодов: CHR$ 16; CHR$ 1, что даст INK 1. Полный перечень кодов клавиш приведен в таблице 1.

При нажатии клавиш редактирования, имеющих коды с 6 по 15 выполняется определенное редактирующее действие. При нажатии комбинаций клавиш, дающих коды клавиш 0 - 5 и 16 - 31, процедура KEYINPUT вводит в текст Бейсик-строки соответствующие управляющие коды INK, PAPER, INVERSE, BRIGHT и FLASH. Перечень этих управляющих кодов приведен в таблице 2 (не путать с кодами клавиш из таблицы 1).

Из этих таблиц вытекают два вывода.

1. Для переключения шрифтов можно использовать вводимые в текст Бейсик-строки неиспользуемые управляющие коды (из таблицы 2). Как видим, их более чем достаточно. Было решено переключение шрифтов выполнять однобайтовыми управляющими кодами (в отличие, скажем, от двухбайтовых INVERSE, BRIGHT и т.п.). Мы приняли за основу управляющие коды 4 и 5 для включения ЛАТ. и РУС. регистров соответственно.

Здесь, конечно, тоже желательно придерживаться какого-то стандарта. Поэтому мы просим наших читателей, имеющих русифицированные ПЗУ (использующиеся, например, в компьютерах "Дельта-С", и других) сообщить нам, какие управляющие коды используются там для переключения шрифтов. Благодаря такому соответствию удастся достичь совместимости с готовыми русскими Бейсик-программами, набранными при помощи любых русифицированных ПЗУ.

2. Не существует свободных кодов клавиш, к которым можно было бы "привязать" шрифтовые комбинации клавиш SYMBOL SHIFT + ENTER и SYMBOL SHIFT + SPACE. Предположим, что мы захотим использовать коды клавиш 4 и 5 - тогда мы лишимся возможности вводить с клавиатуры управляющие коды инверсии INV.VIDEO и TR.VIDEO (см. таблицу 1). Мы можем условиться, что это будут коды клавиш 2 и 3, но тогда мы не сможем с клавиатуры вводить управляющие коды яркости и т.д. Поэтому, для обеспечения совместимости на уровне использования управляющих клавиш было принято принципиальное решение: оставить канальную процедуру ввода KEY-INPUT без изменения, а факт нажатия SYMBOL SHIFT + ENTER и SYMBOL SHIFT + SPACE перехватывать на уровне подпрограммы обслуживания прерывания. Эта же подпрограмма будет и вводить в текст редактируемой Бейсик-строки или INPUT-строку шрифтовые

Итак, опрос шрифтовых комбинаций клавиш и вставка шрифтовых управляющих кодов будет происходить на уровне процедуры обслуживания прерываний 2 рода. Но при этом необходимо учесть, в каком режиме находится Спектрум. Если идёт редактирование Бейсик-строки или INPUT-строки (работает редактор Бейсика), то надо всё это делать. Если же идёт исполнение Бейсик-программы (запуск по команде RUN, при этом работает интерпретатор Бейсика), то отработка нажатия шрифтовых клавиш должна быть заблокирована. Процедура обработки прерывания 2 рода должна определять это.

Теперь можно переходить непосредственно к листингу программы "Резидентный русификатор".

управляющие коды 4 или 5. А вот канальная процедура вывода PRINT-OUT - новая. Она обеспечивает обработку неиспользуемых ранее управляющих кодов 4 и 5.

Таблица 1._ Таблица 2_

Управл яющий код

Значение

0

не используется

1

не используется

2

не используется

3

не используется

4

не используется

5

не используется

6

COMMA CONTROL

7

не используется

8

BACK (LEFT)

9

не используется

10

не используется

11

не используется

12

не используется

13

CARRIAGE RETURN

14

не используется

15

не используется

16

INK CONTROL

17

PAPER CONTROL

18

FLASH CONTROL

19

BRIGHT CONTROL

20

INVERSE CONTROL

21

OVER CONTROL

22

AT CONTROL

23

TAB CONTROL

24

не используется

25

не используется

26

не используется

27

не используется

28

не используется

29

не используется

30

не используется

31

не используется

Код клавиши

Комбинация клавиш

Действие

0

E.MODE; CS+8

FLASH 0

1

E.MODE; CS+9

FLASH 1

2

E.MODE; 8

BRIGHT 0

3

E.MODE; 9

BRIGHT 1

4

CS + 3

INVERSE 0

5

CS + 4

INVERSE 1

6

CS + 2

CAPS LOCK

7

CS + 1

EDIT

8

CS + 5

LEFT

9

CS + 8

RIGHT

10

CS+6

DOWN

11

CS + 7

UP

12

CS + 0

DELETE

13

ENTER

ENTER

14

CS + SS

EXT.MODE

15

CS + 9

GRAPH

16

E.MODE; 0

PAPER 0

17

E.MODE; 1

PAPER 1

18

E.MODE; 2

PAPER 2

19

E.MODE; 3

PAPER 3

20

E.MODE; 4

PAPER 4

21

E.MODE; 5

PAPER 5

22

E.MODE; 6

PAPER 6

23

E.MODE; 7

PAPER 7

24

E.MODE; CS+0

INK 0

25

E.MODE; CS+1

INK 1

26

E.MODE; CS+2

INK 2

27

E.MODE; CS+3

INK 3

28

E.MODE; CS+4

INK 4

29

E.MODE; CS+5

INK 5

30

E.MODE; CS+6

INK 6

31

E.MODE; CS+7

INK 7

Листинг 2.

00001

; (С)

ALANSOFT'

94 .

00520

LD

(HL),E

00002

; "Resident-Rusifikator"

00530

INC

HL

00010

ORG

63000

00540

LD

(HL),D

00020

ENT

00550

INC

HL

00030

;

00560

INC

HL

00040

START

JP

START1

00570

INC

HL

00050

;-----

00580

INC

HL

00060

STOP

DI

00590

LD

(HL),E

00070

LD

HL,

(#5C4F)

00600

INC

HL

00080

LD

(HL

) ,#F4

00610

LD

(HL),D

00090

INC

HL

00620

INT1

LD

HL,(#5C78)

00100

LD

(HL

) ,#09

00630

INC

HL

00110

INC

HL

00640

LD

(#5C7 8) ,HL

00120

INC

HL

00650

LD

A, H

00130

INC

HL

00660

OR

L

00140

INC

HL

00670

JR

NZ, INT2

00150

LD

(HL

) ,#F4

00680

INC

(IY+64)

00160

INC

HL

00690

INT2

LD

HL,(#5CB2)

00170

LD

(HL

) ,#09

00700

LD

DE,(#5C3D)

00180

IM

1

00710

INC

DE

00190

EI

00720

INC

DE

00200

HALT

00730

INC

DE

00210

RET

00740

OR

A

00220

;-----

00750

SBC

HL, DE

00230

START1

DI

00760

LD

A, H

00240

LD

DE,

INT

00770

OR

L

00250

LD

HL,

#FDFD

00780

JR

Z, INT8

00260

LD

(HL

) , #C3

00790

INT3

LD

A,#7F

00270

INC

HL

00800

IN

A,(#FE)

00280

LD

(HL

) ,E

00810

BIT

1,A

00290

INC

HL

00820

JR

NZ, INT7

00300

LD

(HL

) ,D

00830

LD

A,(KEY)

00310

INC

HL

00840

OR

A

00320

LD

(HL

) ,#FD

00850

JR

NZ, INT6

00330

LD

D, H

00860

LD

A, #7F

00340

LD

E, L

00870

IN

A,(#FE)

00350

INC

DE

00880

BIT

0,A

00360

LD

BC,

256

00890

JR

NZ, INT4

00370

LDIR

00900

LD

A, 4

00380

LD

A, #FE

; LAT

00390

LD

I,A

00910

JR

INT5

00400

IM

2

00920

INT4

LD

A,#BF

00410

LD

BC,

(#5C3 6)

00930

IN

A,(#FE)

00420

EI

00940

BIT

0,A

00430

HALT

00950

JR

NZ, INT7

00440

RET

00960

LD

A, 5

00450

; RUS

00460

INT

PUSH

AF

00970

INT5

LD

(KEY),A

00470

PUSH

HL

00980

CALL

#0F81

00480

PUSH

BC

00990

LD

D, 0

00490

PUSH

DE

01000

LD

E,(IY-1)

00500

LD

HL,

(#5C4F)

01010

LD

HL,#0 0C8

00510

LD

DE,

PRINT

01020

CALL

#03B5

01030

CALL

#111D

01450

DEFB

PO1OP-TAB-18

01040

INT6

JP

#004D

01460

DEFB

PO1OP-TAB-19

01050

INT7

XOR

A

01470

DEFB

PO1OP-TAB-2 0

01060

LD

(KEY) , A

01480

DEFB

PO1OP-TAB-21

01070

INT8

JP

#004A

01490

DEFB

PO2OP-TAB-22

01080

;------

01500

DEFB

PO2OP-TAB-23

01090

KEY

DEFB

0

01510

;------

01100

01520

QUEST

JP

#0A69

01110

PRINT

CP

#20

01530

COMMA

JP

#0A5F

01120

JR

C,PRN1

01540

LEFT

JP

#0A23

01130

CP

#A5

01550

RIGHT

JP

#0A3D

01140

CALL

NC,LAT

01560

ENTER

JP

#0A4F

01150

LD

HL,ALPH

01570

POTV2

LD

DE,POCONT

01160

BIT

0, (HL)

01580

LD

(#5C0F) ,A

01170

CALL

Z,CHRLAT

01590

JR

POCHAN

01180

CALL

NZ, CHRRUS

01600

PO2OP

LD

DE,POTV2

01190

CALL

#0B03

01610

JR

POTV1

01200

JP

#0AD9

01620

PO1OP

LD

DE,POCONT

01210

PRN1

CALL

#0B03

01630

POTV1

LD

(#5C0E),A

01220

CP

#18

01640

POCHAN

DI

01230

JR

NC,QUEST

01650

JP

#0A8 0

01240

LD

HL,TAB

01660

POCONT

EI

01250

JP

#0A07

01670

LD

DE,PRINT

01260

;------

01680

JP

#0A8A

01270

TAB

DEFB

QUEST-TAB-

0

01690

;------

01280

DEFB

QUEST-TAB-

1

01700

LAT

LD

HL,ALPH

01290

DEFB

QUEST-TAB-

2

01710

RES

0,(HL)

01300

DEFB

QUEST-TAB-

3

01720

CHRLAT

LD

HL,FNTLAT-2 5 6

01310

DEFB

LAT-TAB-4

01730

JR

LO

01320

DEFB

RUS-TAB-5

01740

RUS

LD

HL,ALPH

01330

DEFB

COMMA-TAB--

6

01750

SET

0,(HL)

01340

DEFB

QUEST-TAB-

7

01760

CHRRUS

LD

HL,FNTRUS-256

01350

DEFB

LEFT-TAB-8

01770

LO

LD

(#5C3 6),HL

01360

DEFB

RIGHT-TAB-

9

01780

RET

01370

DEFB

QUEST-TAB-

10

01790

;------

01380

DEFB

QUEST-TAB-

11

01800

ALPH

DEFB

0

01390

DEFB

QUEST-TAB-

12

; LAT

01400

DEFB

ENTER-TAB-

13

01810

01410

DEFB

QUEST-TAB-

14

01820

FNTRUS

DEFS

768

01420

DEFB

QUEST-TAB-

15

01830

;------

01430

DEFB

PO1OP-TAB-

16

01840

FNTLAT

DEFS

768

01440

DEFB

PO1OP-TAB-

17

Инициализация русификатора (включение режима прерываний 2 рода) выполняется командой RANDOMIZE USR 63000. Такой адрес процедуры был выбран для легкости запоминания, адрес восстановления прерываний 1 рода - 63003, что тоже легко запоминается.

Процедура инициализации START (START1) учитывает несовместимость по прерываниям IM 2 некоторых компьютеров, о чем мы неоднократно сообщали на страницах ZX-РЕВЮ (см. например РЕВЮ за 1994 год, № 1 стр. 24, № 4 стр. 52). При инициализации создается 257-байтовый буфер, начиная с #FE00 по #FF00 включительно, заполненный кодом #FD, так что при векторе прерывания, равном #FE, независимо от значения младшего байта, считается один и тот же адрес процедуры обработки прерывания: #FDFD. А по этому адресу находится безусловный переход на реальный адрес процедуры INT. Кроме того, регистровая пара ВС загружается значением системной переменной CHARS. Это абсолютно ни на что не влияет, но может оказаться в некоторых случаях полезно: подав

после инициализации команду PRINT USR 63000, мы получим значение CHARS латинского символьного набора, а, подав команду PRINT "<SYMB.SHIFT+ENTER>"; USR 63000 получим значение CHARS русского символьного набора.

Процедуру STOP (RANDOMIZE USR 63003) необходимо использовать во всех случаях, когда недопустимо использование прерываний 2 рода, например, перед тем, как обращаться к дисководу. После завершения выполнения команды TR-DOS вновь инициализируйте систему командой RANDOMIZE USR 63000.

Теперь подробнее о процедуре INT (строка 460). Многие её элементы и точки входа соответствуют процедуре ПЗУ RST #38, поэтому для сравнения можно дисассемблировать интересующий фрагмент ПЗУ с адреса #0038 по #0052 включительно.

После сохранения на стеке значений регистров, происходит замена канальной информации. Причем, безразлично, используете Вы магнитофон или дисковод - процедура учитывает это, используя значение системной переменной CHANS (строка 500). Вместо процедуры ПЗУ PRINTOUT задается (при помощи регистра DE) новая процедура PRINT для потоков #0 и #2 (для принтера -поток #3 - новая процедура не подключается, так как должен быть предварительно определен тип интерфейса и принцип переключения РУС/ЛАТ для каждого конкретного принтера).

Процедура INT1 дублирует ПЗУ - эта часть обеспечивает наращивание системной переменной FRAMES - внутренних часов Спектрума.

Процедура INT2 определяет, в каком режиме находится Спектрум (об этом говорилось выше). Определяется это путем сравнения значения системной переменной ERR_SP (в регистре DE) со значением RAMTOP (в регистре HL). Если значение ERR_SP на три байта меньше, чем значение RAMTOP, значит, Спектрум находится в режиме выполнения Бейсик-программы. Иначе - в режиме редактирования (кстати сказать, это обстоятельство было выяснено путем просмотра содержимого ERR_SP при помощи резидентного отладчика TRACER, опубликованного в ZX-PEB^^93, стр.33).

Если Спектрум находится не в режиме редактирования Бейсик-строки или INPUT-строки, то выполняется переход через INT8 в соответствующую точку ПЗУ для штатного вызова процедуры опроса клавиатуры KEY-INT. Иначе - продолжение работы.

Процедура INT3 выполняет сканирование правого нижнего полуряда клавиатуры и проверяет, нажата ли клавиша SYMBOL SHIFT. Если нет, то происходит переход на INT7 - здесь обнуляется вспомогательная системная ячейка KEY - она регистрирует факт нажатия шрифтовой комбинации клавиш. Ее значение проверяется после проверки нажатия SYMBOL SHIFT (строки 830-850). Если ячейка не пуста, значит шрифтовая комбинация клавиш уже была зафиксирована в прошлом цикле прерываний и, следовательно, были выполнены все действия, связанные с переключением регистров. В этом случае выполняется переход через INT6 в точку завершения процедуры обработки прерывания. Таким образом, при нажатии шрифтовых комбинаций клавиш блокируется автоповтор -предотвращается многократный ввод шрифтовых управляющих кодов при удержании клавишей нажатыми длительное время.

Далее, если нажата клавиша SIMBOL SHIFT, проверяется нажатие SPACE (со строки 860). Если она не нажата, то переход на проверку нажатия ENTER - INT4. Иначе - в аккумулятор заносится управляющий код 4, предназначенный для включения регистра ЛАТ. При дальнейшем переходе на INT5 это значение заносится и в ячейку KEY для сигнализации о нажатии шрифтовой комбинации клавиш при следующем прерывании.

В том случае, если нажата не SPACE, а ENTER, в аккумулятор и ячейку KEY заносится управляющий код 5, предназначенный для включения регистра РУС.

Далее, вызовом подпрограммы ПЗУ ADD-CHAR (строка 980) выполняется выделение одного байта памяти в редактируемой области и вставка вводимого кода в редактируемую Бейсик-строку или INPUT-строку. При этом, как и при вводе любого другого символа, выдается стандартный звуковой сигнал (строки 990-1020) и происходит перепечатка редактируемой строки в нижней части экрана вызовом процедуры ED-COPY (строка 1030), как это всегда происходит при вводе очередного символа с клавиатуры. На этом обработка прерывания заканчивается.

Теперь рассмотрим новую канальную процедуру вывода PRINT, которая подключается вместо стандартной процедуры ПЗУ PRINT-OUT. Многие её элементы и точки входа соответствуют процедуре ПЗУ #09F4. Для сравнения можно дисассемблировать фрагмент ПЗУ с адреса #09F4 по #0A10 включительно.

Прежде всего (строка 1110) проверяется, является ли обрабатываемый код печатным или управляющим кодом. Если это управляющий код, то переход на PRN1, если печатный код -

дальнейшая проверка. Если этот печатный код является токеном, то должен быть выведен на печать английскими буквами, для этого происходит вызов подпрограммы переключения регистра LAT. Далее выполняется проверка текущего состояния шрифтового регистрового флага - нулевого бита системной ячейки ALPH. Его равенство нулю свидетельствует о включенном регистре ЛАТ. В этом случае происходит изменение текущего значения CHARS, соответствующее латинскому символьному набору. Если значение флага ALPH не равно нулю, задается значение CHARS русского символьного набора.

Далее (строка 1190) следует вызов подпрограммы ПЗУ PO-FETCH для ввода координат позиции печати из соответствующих системных переменных, как это делается в стандартной процедуре PRINT-OUT.

Изложенное выше касалось печатных кодов. Для обработки управляющих кодов предназначена процедура PRN1. Здесь после вызова PO-FETCH, если символ больше или равен #18, происходит переход на печать "?". Для управляющих кодов с 0 по #17 происходит расчет дальнейшего адреса по таблице аналогично тому, как это делается в процедуре ПЗУ #09F4. Здесь в строках 1310, 1320 задается отработка шрифтовых управляющих кодов. Остальные процедуры, задаваемые при помощи таблицы TAB, используют соответствующие процедуры ПЗУ или построены аналогично им (строки 1520-1680).

Подпрограммы LAT и RUS занимаются непосредственно переключением символьных наборов с соответствующим изменением регистрового флага - 0 бита ячейки ALPH.

И, в заключение, о символьных наборах. Приведенная процедура использует два стилизованных "утолщенных" символьных набора. Причем, для корректной работы необходимо обеспечить полное соответствие их первой трети, то есть символов с кодами с 32 по 63 включительно (символы и цифры).

Можно несколько сократить размер суммарного блока кодов, если использовать вместо латинского - символьный набор ПЗУ. При этом русский символьный набор должен иметь однотипный дизайн, а первая треть - символы и цифры - копировать символьный набор ПЗУ. Все изменения в процедуре сводятся к замене одной строки листинга: 018 4 0 FNTLAT EQU #3C0 0.

Как обычно, приводим шестнадцатиричный дамп блока кодов резидентного русификатора.

F618

C3

32

F6

F3

2A

4F

5C

36

F7

F620

F4

23

36

09

23

23

23

23

F8

F628

36

F4

23

36

09

ED

56

FB

E8

F630

76

C9

F3

11

57

F6

21

FD

D4

F638

FD

36

C3

23

73

23

72

23

72

F640

36

FD

54

5D

13

01

00

01

2 F

F648

ED

B0

3E

FE

ED

47

ED

5E

96

F650

ED

4B

36

5C

FB

76

C9

F5

3F

F658

E5

C5

D5

2A

4F

5C

11

CD

80

F660

F6

73

23

72

23

23

23

23

E0

F668

73

23

72

2A

78

5C

23

22

A9

F670

78

5C

7C

B5

20

03

FD

34

BF

F678

40

2A

B2

5C

ED

5B

3D

5C

C7

F680

13

13

13

B7

ED

52

7C

B5

D6

F688

28

3F

3E

7F

DB

FE

CB

4F

95

F690

20

33

3A

CC

F6

B7

20

2A

D6

F698

3E

7F

DB

FE

CB

47

20

04

5A

F6A0

3E

04

18

0A

3E

BF

DB

FE

D0

F6A8

CB

47

20

19

3E

05

32

CC

2A

F6B0

F6

CD

81

0F

16

00

FD

5E

6A

F6B8

FF

21

C8

00

CD

B5

03

CD

E8

F6C0

1D

11

C3

4D

00

AF

32

CC

A1

F6C8

F6

C3

4A

00

00

FE

20

38

17

F6D0

16

FE

A5

D4

39

F7

21

4F

F3

F6D8

F7

CB

46

CC

3E

F7

C4

48

E3

F6E0

F7

CD

03

0B

C3

D9

0A

CD

1B

F6E8

03

0B

FE

18

30

1E

21

F4

65

F6F0

F6

C3

07

0A

18

17

16

15

0A

F6F8

41

4A

15

11

16

18

0E

0D

E8

F7 0 0

0C

17

0A

09

24

23

22

21

B7

F7 0 8

20

1F

19

18

C3

69

0A

C3

68

F710

5F

0A

C3

23

0A

C3

3D

0A

6A

F718

C3

4F

0A

11

32

F7

32

0F

A6

F720

5C

18

0B

11

1B

F7

18

03

D4

F728

11

32

F7

32

0E

5C

F3

C3

AB

F7 3 0

80

0A

FB

11

CD

F6

C3

8A

CD

F7 3 8

0A

21

4F

F7

CB

86

21

50

62

F7 4 0

F9

18

08

21

4F

F7

CB

C6

48

F7 4 8

21

50

F6

22

36

5C

C9

00

23

После набора сохраните полученный блок кодов командой: SAVE "rus"CODE 63000,312

Можете подгрузить символьные наборы: LOAD "chr rus" CODE 63312: LOAD "chr lat" CODE 64080

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

SAVE "rus" CODE 63000,1848

(или SAVE "rus" CODE 63000,1080 для одного символьного набора)

Для запуска процедуры в работу можно воспользоваться простейшим Бейсик-загрузчиком: 10 CLEAR 62999: LOAD "rus"CODE

20 PRINT AT 11,2; INVERSE 1,-"START - RANDOMIZE USR 63000",-AT 13,2;" STOP - RANDOMIZE USR 63003",-#0,-FLASH 1;" Press any key to NEW ": P

AUSE 0 30 NEW

После нажатия клавиши и выполнения команды NEW, выполните RANDOMIZE USR 63000 и можете начинать работу, используя шрифтовые комбинации клавиш SYMBOL SHIFT + ENTER и SYMBOL SHIFT + SPACE.

Однако для готовых программ удобно загружать блок кодов русификатора и инициализировать его при старте программы, причем переделки существующих программ сводятся к минимуму, вместо традиционной загрузки русского символьного набора (LOAD "chr"CODE 64600) может быть следующее (автостарт программы со 2 строки):

1 GO TO 100

2 CLEAR 62999: LOAD "rus"CODE

3 RANDOMIZE USR 63000 100 ... Бейсик-программа

.:

Подведём итоги. Что нового имеет теперь пользователь? Один раз перед началом работы требуется загрузить и запустить процедуру в кодах: RANDOMIZE USR 63000. Благодаря этому появляется возможность использовать русские и латинские заглавные и строчные буквы.

Раскладка клавиатуры в русском регистре соответствует "ЯВЕРТЫ...", хотя, если подключить не только новую канальную процедуру PRINT-OUT, но и KEY-INPUT, можно реализовать любую раскладку клавиатуры. В русском регистре курсор изменяется: он принимает вид [Л] - для строчных и [Ц] - для заглавных букв. При вводе русского текста нет необходимости в конце русской фразы переключаться опять в латинский регистр (аналогично INVERSE VIDEO и TRUE VIDEO, чтобы не нарушать удобочитаемость листинга). Новая канальная процедура печати сделает это сама, встретив первый же токен. Благодаря этому листинг программы всегда читается так, как должен. Цветовые управляющие коды, а также CHR$ 6 (COMMA CONTROL) могут быть введены с клавиатуры как обычно и действуют корректно. Имеется возможность полной совместимости с любой версией русифицированных ПЗУ, что позволяет использовать программы, набранные с их помощью с минимальной адаптацией.

Но ничего не даётся даром. Как в адаптируемых, так и в набираемых заново программах, после CLS, как уже говорилось, может потребоваться вставка PAUSE 1. Больше хлопот доставляет оператор INPUT. Причём, если это просто INPUT a$, то проблемы вообще нет. Если же INPUT " string" ;a$ причём в выражении "string" встречаются переключатели шрифтов, то тут и возникает та самая проблема CLS. Здесь, как говорилось выше, надо каким-то образом заставить компьютер "долго думать". Это можно сделать, например, так: INPUT CHR$ SQR 16; "ENGLISH string";a$ или так: INPUT CHR$ SQR 25; "РУССКИИ текст"^. Относительно долгое вычисление SQR приводит к требуемой задержке. Сама же предварительная подача управляющих кодов 4 или 5 позволяет заранее переключить регистр, подготовив пользователю ввод либо латинским либо русским шрифтом (аналогично тому, как Вы заранее перед командой INPUT включаете или выключаете регистр CAPS LOCK, подавая команду POKE 23658,8 или POKE 23658,0).

Как видим, новая процедура является серьёзным прорывом в деле русификации Спектрум-Бейсика, хотя и имеет определенные недостатки. Слово Вам, уважаемые читатели. Как говорится, кто сможет, пусть сделает лучше. Мы готовы дать слово всем, кто поможет в решении этой проблемы.

AAA




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



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

Похожие статьи:
Открытые письма Nemo №6.266
Юмор - Как затащить хакера в спальню.
Новости - ACL практически в полном дауне.

В этот день...   22 июля