Процедура попроще:
XOR A
LD (23560),A
LD IY,#5C3A
RST 56
Вешается на прерывания. Последнюю нажатую клавишу можно получить из ячейки по адресу 23560.
По адресам 23561 и 23562 можно изменить задержку опроса клавиш.
Автор процедуры Fyrex/Mayhem.
Вид для печати
Процедура попроще:
XOR A
LD (23560),A
LD IY,#5C3A
RST 56
Вешается на прерывания. Последнюю нажатую клавишу можно получить из ячейки по адресу 23560.
По адресам 23561 и 23562 можно изменить задержку опроса клавиш.
Автор процедуры Fyrex/Mayhem.
Немного не то. Нужна с буфером.
Буферизованный опрос клавиатуры, реализованный для ZXDev. Коды клавиш берутся из LAST_K, соответственно, работает автоповтор клавиш. Исходник оформлен для сборки компилятором SDCC.
Вопросы, предложения, критика?Код:#define KeyBufSize 8
// Возвращает количество клавиш в буфере.
unsigned char Input_Available (void);
// Возвращает код нажатой клавиши.
// Если нажатых клавиш нет, ожидает.
char Input_Read (void);
// Вызывайте из обработчика прерываний IM 2.
void Input_RunMe50Hz (void);
/*--------------------------------- Cut here ---------------------------------*/
char Input_keyBuf [KeyBufSize];
/* Закономерно считаем, что более актуальны клавиши, нажатые позднее,
поэтому при переполнении буфера будем удалять из него нажатые ранее.
Эта стратегия кажется более удачной, чем игнорирование всех клавиш,
нажатых после переполнения буфера (как в контроллере клавиатуры IBM PC). */
char Input_Read (void) {
__asm
LOOPrptbuf$:
LD HL,#_Input_keysAvailable+1
LD A,(HL)
OR A
JR Z,LOOPrptbuf$
DEC (HL)
.globl _Input_keyOut
_Input_keyOut: ; Read a key:
LD HL,#_Input_keyBuf ; key := keyBuf[keyOut];
LD C,(HL)
INC HL ; keyOut := (keyOut+1) MOD KeyBufSize;
LD A,L
SUB #<_Input_keyBuf+KeyBufSize
JR NZ,Save_keyOut$
LD HL,#_Input_keyBuf
Save_keyOut$:
LD (_Input_keyOut+1),HL
LD L,C ; RETURN key
__endasm;
} //Input_Read
void Input_RunMe50Hz (void) __naked {
__asm
LD IY,#0x5C3A
RST 0x38
BIT 5,1(IY)
RET Z
RES 5,1(IY)
_Input_keyIn:
LD HL,#_Input_keyBuf ; Add a key:
LD A,-50(IY) ; keyBuf[keyIn] := CHR(keyCode);
LD (HL),A
INC HL
LD A,L
SUB #<_Input_keyBuf+KeyBufSize
JR NZ,Save_keyIn$
LD HL,#_Input_keyBuf
Save_keyIn$:
LD (_Input_keyIn+1),HL
.globl _Input_keysAvailable
_Input_keysAvailable:
LD A,#0 ; Check overflow:
CP #8 ; IF keysAvailable > 8 THEN keysAvailable := 8 END;
ADC #0
LD (_Input_keysAvailable+1),A
RET C
JR _Input_keyOut
__endasm;
} //Input_RunMe50Hz
/*--------------------------------- Cut here ---------------------------------*/
unsigned char Input_Available (void) {
__asm
LD HL,(_Input_keysAvailable+1)
__endasm;
} //Input_Available
В приведённом выше коде есть баг (!). Было:
Стало:Код:.globl _Input_keysAvailable
_Input_keysAvailable:
LD A,#0 ; Check overflow:
CP #8 ; IF keysAvailable > 8 THEN keysAvailable := 8 END;
ADC #0
LD (_Input_keysAvailable+1),A
RET C
JR _Input_keyOut
Баг связан с тем, что не было учтено влияние команды ADC #0 на флаг переноса, и процедура реагировала без переполнения буфера как на его переполнение.Код:.globl _Input_keysAvailable
_Input_keysAvailable:
LD A,#0 ; Check overflow:
CP #KeyBufSize ; IF keysAvailable > 8 THEN keysAvailable := 8 END;
JR NC,_Input_keyOut
INC A
LD (_Input_keysAvailable+1),A
RET