Дебажил. На функции freemem (62),вроде, вываливается:
ld a,(memblock)
ld c,62
rst 0x10
Вид для печати
Решил проблему. Похоже, нумерация логических страниц в блоке с единицы...
Заменил номера страниц с 0 и 1 на 1 и 2 - заработал правильный выход в ОС.
нумерация страниц в блоке таки с нуля (0,1,2...)
а возврат в DSS у нас такой:
либо RST 0 который вызывает тоже самоеКод:; Exit program
exit:
ld bc,0041h
rst 10h
- - - Updated - - -
и зачем SP переставлять вручную, если DSS при загрузке EXE всё равно ставит в тот SP который в хедере? и соответственно при выходе в DSS через 41h всё вернётся туда где было
Хотел сделать обработку клавиатуры в прерывании через функцию ОС scankey. Вот так:
Почему-то это не работало...Цитата:
;здесь обработка клавиатуры
Ld a,(OldWin0Page); восстанавливаем системную страницу
out (0x82),a
ld a,0
ld (scankey),a
LD C,0x31 ;Функция опроса клавиатуры без ожидания
RST 0x10
JR Z,int2body1
ld a,d
and 127 ;убираем седьмой бит
ld (scankey),a
int2body1:
Ld a,(Win0Page)
out (0x82),a
Пришлось писать обработку AT-клавиатуры самому. Вот код:
Работает. Программа реагирует на клавиши направлений(стрелки) и ескейп. В каждое отдельное прерывание работает только треть кода: либо фиксация в переменной кода нажатой клавиши, либо отлов отжатия F0, или отлов отжатия расширенного кода E0F0. Прошу потестить на реале, так как есть подозрение что эмулятор не пропускает клавиши PrintScreen и Pause\Break. Нужно проверить - нажатие этих клавиш не приведёт ли к отключению реакции на клавиши? Алгоритм обработки нажатий реагирует на обычные( однобайтовые коды нажатий и двубайтовые отпусканий) и расширенные( двубайтовые для нажатий и трёхбайтовые для отпусканий) коды, но не на дополнительные. Вот, нажатие ПринтСкрин и Паузы может привести к непредсказуемым результатам, так как они имеют дополнительные коды( 4-6 байт). Есть подозрение, что нажатие Паузы заблокирует клавиатуру.Цитата:
;Клавиатура
SerialChAData EQU #18 ;регистр данных канала A последовательного порта контроллера Z84
SerialChACtrl EQU #19 ;контролирующий регистр канала A последовательного порта контроллера Z84
kbMoveUp EQU 0x75 ;стрелка вверх
kbMoveDown EQU 0x72 ;стрелка вниз
kbMoveLeft EQU 0x6B ;стрелка влево
kbMoveRight EQU 0x74 ;стрелка вправо
kbEsc EQU 0x76 ;ескейп
target defb 0 ;код нажатой клавиши
scankey defb 0
pflag defb 0
eflag defb 0 ;флаг расширенных кодов
fflag defb 0 ;флаг заполнения буфера
;_____________________________
;обработчик прерывания
int2m:
di
push af
push bc
push de
push hl
ld a,(tick)
cp 2
jr nc, int2body
inc a
ld (tick),a
int2body:
;здесь обработка клавиатуры AT[ps/2 scan set 2]
keys:
ld a,(target) ; проверяем переменную со сканкодом нажатой клавиши
or a
jp nz, keystep2 ;если не ноль, то переходим к отлову отжатия клавиши
;иначе проверяем сканкод нажатой клавиши
call scan
ld d,a
ld a,(fflag) ;проверяем буфер клавиатуры по флагу заполнения
or a
jp z, player ;если пуст - выходим
ld a,d
cp 0xF0; ;клавиша отжата?
jr nz, keystep11 ;нет - проверяем на байт расширения
call scan; ;иначе, освождаем буфер и выходим
jp player
keystep11:
cp 0xE0; ;проверка на байт расширения
jr nz,keystep12 ;если нерасширенный код, то переходим на обработку нерасширенных кодов
call scan ;иначе, читаем буфер и сравниваем с
cp 0xF0 ;кодом отжатия расширенного кода
jr nz,keystep13 ;если не отжатие, то расширенный код, переходим на обработку расширенных кодов
call scan ;иначе, освобождаем буфер и выходим
jp player
keystep13:
ld (target),a ;запоминаем расширенный код
ld a,1
ld (eflag),a ;устанавливаем флаг расширенного кода и выходим
jp player
keystep12:
ld (target),a ;запоминаем нерасширенный код
xor a
ld (eflag),a ;сбрасываем флаг расширенного кода и выходим
jp player
keystep2:
ld a,(eflag) ;по флагу расширенных кодов определяем какое отжатие ловить
or a
jr z, keystep_for_F0 ;если флаг сброшен, ловим простое отжатие F0 нерасширенных кодов
;иначе, отлов расширенного отжатия EOFO расширенных кодов
call scan
ld d,a
ld a,(fflag)
or a
jp z, player ;буфер пуст? да - выход
ld a,d
cp 0xE0 ;расширенный код?
jr nz,F0compare ;нет - проверка на обычное отжатие
call scan ;иначе,читаем буфер
cp 0xF0 ;проверка на расширенное отжатие
jr nz, player ;если не расширренное отжатие, то освобождаем буфер и выход
call scan ;иначе, читаем расширенный код клавиши, которая была отжата
ld b,a
ld a,(target)
cp b ;сравниваем код отжатой клавиши с клавишей, которая была нажата
jr nz, player ;если коды не совпадают - выход
;ld (scankey),a
xor a
ld (target),a ;иначе, сбрасываем переменную для кода нажатой клавиши
ld (eflag),a ; и сбрасываем флаг расширенных кодов
jr player ;выход
F0compare:
cp 0xF0 ;обычное отжатие?
jr nz, player ;нет -выход
call scan ;да - освобождаем буфер и выход
jr player
;отлов F0 (обычного отжатия нерасширенных кодов)
keystep_for_F0:
call scan ;читаем буфер
ld d,a
ld a,(fflag)
or a
jp z, player ;если буфер пуст - выход
ld a,d
cp 0xF0 ;обычное отжатие?
jr nz, E0compare ;если нет - проверка расширенных кодов
call scan ;иначе, читаем код отжатой клавиши
ld b,a
ld a,(target)
cp b ;сравниваем код отжатой клавиши с клавишей, которая была нажата
jr nz, player ;если коды не совпадают - выход
;ld (scankey),a
xor a
ld (target),a ;иначе, сбрасываем переменную для кода нажатой клавиши
jr player ;выход
E0compare: ;отлов расширенных кодов для освобождения буфера
cp 0xE0 ;расширенный код?
jr nz, player ;если нет - выход
call scan ;иначе, читаем буфер
cp 0xF0 ;расширенное отжатие?
jr nz, player ;если нет - выход
call scan ;иначе, освобождаем буфер от кода отжатой клавиши и выход
jr player
;работа c плеером
player:
pop hl
pop de
pop bc
pop af
ei
reti
;_______________________________
scan:
;проверка есть ли данные от клавиатуры
IN a,(SerialChACtrl) ;бит0 = 0 - нет данных;бит0 = 1 - есть данные
and 1
ld (fflag),a
JR z,scanexit
;если данные есть
IN a,(SerialChAData)
scanexit:
ret
Ссылка на образ диска https://dropmefiles.com/9jsV5
Может, кто приведёт пример более оптимального кода обработки нажатий клавиш клавиатуры? У меня слишком громоздкий получился.
Полезные ссылки по теме:
https://dvsav.ru/at-ps2-keyboard/
https://ru.wikipedia.org/wiki/%D0%A1...BA%D0%BE%D0%B4
Смотрел ещё исходники Клада от CHRV. Там обработчик совсем другой и для других целей( обработка нажатий нескольких клавиш). Мне не подойдёт.
в обработчике прерываний DSS лучше не вызывать
тем более клавишные подпрограммы - DSS ведь само по прерыванию инфу про кнопки берёт
говорят, что клавиатуру можно по ZX-спектрумовски читать даже в режиме Спринтера - я не пробовал, ну и там естественно без курсорных и расширенных клавиш будет...
Shaos, мне бы кто на реале посмотрел тест клавитуры и отписался, клавиши ПринтСкрин и Пауза блокируют ли программу. Нужно стрелки понажимать чтоб квадратик подвигался, а затем нажать ПринтСкрин и Паузу в любом порядке, и затем снова стрелки. Эмулятор клавиши Принтскрин и Паузы не передаёт программе,поэтому я не знаю что будет на реале при нажатии этих клавиш.
Просто, если есть возможность, погоняй на реале, напиши на форум какой результат. Нужно узнать работают ли стрелки после нажатия клавиш ПринтСкрин и Пауза. Обработку клавиатуры я делаю для игры.
Образ диска https://dropmefiles.com/9jsV5
У меня сейчас Спринтер в разобранном виде (переезжает со стола в ПЦ-корпус) - может Сайман или RomanRom2 смогут позапускать
Smalovsky, проверил. после запуска нажал на стрелку вправо. кубик начал движение. как его остановить? при нажатии на esc реакции нет. кубик доезжает до (почти) границы экрана и всё зависает. кубик за собой оставляет какие то полоски, с шагом и возрастанием. потом после ребута запустил снова. нажал на курсор вниз. кубик поехал вниз. далее всё аналогично. реакции на pause или print screen никакой нет.
Не знаю почему у тебя не работает опрос на прерываниях.
У меня опрос клавиатуры нормально работал, я делал так:
Обработчик прерваний в конце вызывает RST #38 (досовский обработчик прерываний IM1):
В коде проверка клавиатуры:Цитата:
Im2Handler:
di
push all
...
pop all
ei
rst #38
Цитата:
CheckKeys:
ld c,Dss.ScanKey
rst #10
ret z ;ничего не нажато
;определение нажатой кнопки
ret
Непонятно. В эмуляторе всё работает. Надо бы, что бы ещё кто на спринтере проверил.
Это исправил.
Вот видео работы обновленной программы на эмуляторе( теперь уже спрайт двигается на фоне):
https://www.youtube.com/watch?v=-HQI...VNNFgH&index=1
Возможно проблемы с клавиатурой в этом кусочке программы:
Это надо разбираться с последовательным портом будет.Цитата:
scan:
;проверка есть ли данные от клавиатуры
IN a,(SerialChACtrl) ;бит0 = 0 - нет данных;бит0 = 1 - есть данные
and 1
ld (fflag),a
JR z,scanexit
;если данные есть
IN a,(SerialChAData)
;вот тут возможно нужно что-то отправить в порт SerialChACtrl, что бы разрешить дальнейшую пересылку данных от клавиатуры
scanexit:
ret
Программа для тестирования:
https://dropmefiles.com/4hFOg