PAGE_0: equ 82h ; порт 0 окна = addr 0000h PAGE_1: equ 0A2h ; порт 1 окна = 4000h PAGE_2: equ 0C2h ; порт 2 окна = 8000h PAGE_3: equ 0E2h ; порт 3 окна = 0c000h SIO_CONTROL_A: EQU 19h SIO_DATA_REG_A: EQU 18h SIO_CONTROL_B: EQU 1Bh SIO_DATA_REG_B: EQU 1Ah CTC_CH0: equ 10h CTC_CH1: equ 11h CTC_CH2: equ 12h CTC_CH3: equ 13h RGMOD equ 0c9h ; .... ; Запомним текущий видео-режим LD C, DSS.GetVMod RST 10h LD HL, GetVMod_Error_Message ;JR C, PutError LD C, A LD (.Current_VMod), BC ; Запрос памяти ; сохраним текущие значения страниц IN A, (PAGE_1) LD (SavePage1), A IN A, (PAGE_3) LD (SavePage3), A ; Настройка прерываний CTC и SIO LD HL, IM2_Empty : LD (0FDFFh), HL LD (0FD10h), hl LD (0FD12h), hl LD (0FD14h), hl LD (0FD16h), hl LD (0FD18h), hl LD (0FD1Ah), hl LD (0FD1Ch), hl LD (0FD1Eh), hl LD HL, IM2_VShandler : LD (0FD06h), HL LD A, I LD (.SaveInterrupt), A LD A, 0FDh DI LD I, A IM 2 .Sync: EI HALT DI IN A, (SIO_CONTROL_A) BIT 0, A ; 0-bit, байт пришел ? JR Z, .EndSync ; да, это прерывание от клавиатуры CALL Keyboard.PS2_Scan JR .Sync .EndSync: LD B, 5 .loopSync: DJNZ .loopSync ; Настройка CTC LD A, 057h : OUT (CTC_CH2), A LD A, 112 : OUT (CTC_CH2), A LD A, 0d7h : OUT (CTC_CH3), A LD A, 160 : OUT (CTC_CH3), A LD A, 0 : OUT (CTC_CH0), A ; Настройка SIO LD A, 1 : OUT (SIO_CONTROL_A), A LD A, 18h : OUT (SIO_CONTROL_A), A LD A, 2 : OUT (SIO_CONTROL_B), A LD A, 10h : OUT (SIO_CONTROL_B), A LD HL, IM2_Keyhandler LD (0FDFFh), HL LD (0FD10h), hl LD (0FD12h), hl LD (0FD14h), hl LD (0FD16h), hl LD (0FD18h), hl LD (0FD1Ah), hl LD (0FD1Ch), hl LD (0FD1Eh), hl Loop: ; основаной цикл ; ................ LD A, (Keyboard.KeyFlags) BIT 7, A JR NZ, .Key_ESC JP Loop .Key_ESC: ; Выход DI ; Восстановим прерывания и CTC LD A, 057h : OUT (CTC_CH3), A LD A, 160 : OUT (CTC_CH3), A ; Восстановим SIO LD A, 1 : OUT (SIO_CONTROL_A), A LD A, 0 : OUT (SIO_CONTROL_A), A LD A, 2 : OUT (SIO_CONTROL_B), A LD A, 10h : OUT (SIO_CONTROL_B), A .SaveInterrupt+*: LD A, 0 LD I, A IM 1 EI CALL Keyboard.PS2_Clear_Buf ; Восстанавливаем страницы памяти LD A,(SavePage1) OUT (PAGE_1), A LD A,(SavePage3) OUT (PAGE_3), A ; Освободим память запрошенную память ; возвращаем текстовый режим .Current_VMod+*: LD BC, 0 LD A, C LD C, DSS.SetVMod RST 10h .Exit: .ExitCode+*: LD B, 0 LD C, DSS.Exit RST 10h JR $ UpdateMechanics: LD A, (Keyboard.KeyFlags) OR A RET Z BIT 3, A JR NZ, .Key_UP BIT 2, A JR NZ, .Key_DOWN RET .Key_DOWN: ; ... .Key_UP: ; ... RET IM2_Empty: EI RETI IM2_Keyhandler: PUSH AF, BC, DE, HL EXX EX AF, AF PUSH AF, BC, DE, HL, IX, IY IN A, (SIO_CONTROL_A) BIT 0, A ; 0-bit, байт пришел ? CALL NZ, Keyboard.PS2_Scan ; да, это прерывание от клавиатуры .SkipClearKeyFlags: POP IY, IX, HL, DE, BC, AF EX AF, AF EXX POP HL, DE, BC, AF EI RETI IM2_VShandler: PUSH AF, BC, DE, HL EXX EX AF, AF PUSH AF, BC, DE, HL, IX, IY .NeedChangePage+*: LD A, 0 ; 1 - нужно переключить экран OR A JR Z, .skip .NumberScreen+*: LD B, 0 ; 0/1 - номер экрана, который в данный момент выводится ; Переключаем экран IN A, (RGMOD) AND 0feh OR B XOR 1 OUT (RGMOD), A AND 1 LD (.NumberScreen), A XOR A LD (.NeedChangePage), A .skip: CALL UpdateMechanics ; Возможно нужно перенести из прерывания ; Расчет FPS ; .......... POP IY, IX, HL, DE, BC, AF EX AF, AF EXX POP HL, DE, BC, AF EI RETI ; очистка буфера клавиатуры ; Портит регистры AF Keyboard.PS2_Clear_Buf: IN a, (SIO_CONTROL_A) BIT 0, a RET Z IN A, (SIO_DATA_REG_A) JR PS2_Clear_Buf ; Из PS/2 возвращает в Keyboard.KeyFlags нажатые клавиши: ; бит кнопка ; 0 - RIGHT ; 1 - LEFT ; 2 - DOWN ; 3 - UP ; 4 - SPACE ; 5 - none ; 6 - ENTER ; 7 - ESC ; Портит регистры AF, BC, DE, HL Keyboard.PS2_Scan: LD HL, .KeyStatus LD DE, 0c686h ; D - код команды SET 0, (HL) / E - код команды RES 0, (HL) .Loop IN a, (SIO_CONTROL_A) BIT 0, a RET Z IN A, (SIO_DATA_REG_A) CP 0E0h JR NZ, .kh1 SET 7, (HL) ; // двойной сканкод JR .Loop .kh1: CP 0F0h JR NZ, .kh2 SET 6, (HL) ; // отпускание клавиши JR .Loop .kh2: BIT 7, A ; автоповтор? JR Z, .kh3 LD (HL), 0 JR .Loop .kh3: LD B, 8 BIT 6, (HL) LD C, D ; С - код команды SET 0, (HL) JR Z, .KeyPress .KeyRelease: LD C, E ; С - код команды RES 0, (HL) .KeyPress: LD (HL), 0 PUSH HL INC HL .KeyPressLoop: CP (HL) JR Z, .SetKey INC HL DJNZ .KeyPressLoop POP HL JR .Loop .SetKey: LD A, B DEC A CPL RLA RLA RLA AND 00111000b OR C LD (.CodeSet + 1), A ; Изменяем команду по .CodeSet POP HL DEC HL .CodeSet: SET 0, (HL) INC HL JR .Loop .KeyFlags: DB 0 .KeyStatus: DB 0 .KeysArray: DB 74h, 6bh, 72h, 75h, 29h, 00h, 5ah, 76h Keyboard.KeyFlags: EQU .KeyFlags SavePage1: DB 0 SavePage3: DB 0