; Redefinir teclas y ver el estado de las teclas elegidas "en el juego". ORG 33500 call CLS call Redefinir_Teclas call CLS call Wait_For_No_Key ; Esperar a que no haya teclas pulsadas ; Bucle del programa, lee nuestras teclas e imprime primero la ; "leyenda" de las teclas y luego el byte de estado de teclado: bucle: ld de, 0 call CursorAt ; Nos vamos a (0,0) ld de, msg_keys call PrintString ; Imprimimos mensaje "*<>^v" call Leer_Teclado_Empaquetado call PrintBin ; Imprimimos estado teclas (A) en binario jr bucle ; Repetir hasta reset ; Mensajes del programa msg_izq DEFB "Izquierda? ", _EOS msg_der DEFB "Derecha? ", _EOS msg_arriba DEFB "Arriba? ", _EOS msg_abajo DEFB "Abajo? ", _EOS msg_disp DEFB "Disparo? ", _EOS msg_keys DEFB " *<>^v", _CR, _EOS ; Teclas por defecto si no se redefine: O P Q A SPACE tecla_izq DEFB $1a tecla_der DEFB $22 tecla_arriba DEFB $25 tecla_abajo DEFB $26 tecla_disp DEFB $20 ;----------------------------------------------------------------------- ; Utiliza Redefine_Key para obtener en las variables "tecla_*" los ; scancodes de las diferentes teclas que selecciona el usuario. ; Llama a "Redefine_Key" para mostrar el mensaje y pedir la tecla. ; ; ENTRADA: Nada ; SALIDA: Nada ; MODIFICA: AF, DE, HL, Flags ;----------------------------------------------------------------------- Redefinir_Teclas: ; Los siguientes textos se podrian haber impreso tambien usando un bucle ; con inc de (avanzar cadena) e inc hl (avanzar tecla a escribir) ld de, msg_izq call PrintString ; Imprimir mensaje "Izquierda?" call Redefine_Key ; Esperar pulsacion (e imprimir ASCII) ld hl, tecla_izq ; Apuntamos HL a la variable tecla_izq ld (hl), a ld de, msg_der ; Siguiente mensaje: "Derecha?" call PrintString call Redefine_Key ; Esperar pulsacion (e imprimir ASCII) ld hl, tecla_der ld (hl), a ; Guardamos tecla pulsada ld de, msg_arriba ; Repetimos con ARRIBA call PrintString call Redefine_Key ld hl, tecla_arriba ld (hl), a ld de, msg_abajo ; Repetimos con ABAJO call PrintString call Redefine_Key ld hl, tecla_abajo ld (hl), a ld de, msg_disp ; Repetimos con DISPARO call PrintString call Redefine_Key ld hl, tecla_disp ld (hl), a ret ;----------------------------------------------------------------------- ; Utiliza Find_Key para obtener una tecla válida. Se queda en un bucle ; de espera hasta que una sola tecla esté pulsada, y la devuelve en A. ; Además, imprime por pantalla el codigo ASCII de la tecla. ; ; ENTRADA: Nada ; SALIDA: A = scancode ; MODIFICA: Flags ;----------------------------------------------------------------------- Redefine_Key: push de push hl call Wait_For_No_Key wait_for_scan_loop: call Find_Key jr nz, wait_for_scan_loop ; Mas de una tecla leida, repetir ld a, d cp $ff ; si A es $ff => ninguna tecla pulsada jr z, wait_for_scan_loop ; Repetimos hasta que A != $ff ld h, d ; Nos hacemos copia de D en H call Scancode2Ascii ; Convertir D (scancode) en A (ASCII) cp 'e' ; ¿Es 'e'? Imprimir "ENTER" jr nz, redef_key_NO_ENTER ld de, redef_key_enter call PrintString jr redef_key_end ; Impreso texto, salimos redef_key_NO_ENTER: cp 's' ; ¿Es 's'? Imprimir "SPACE" jr nz, redef_key_NO_SPACE ld de, redef_key_space call PrintString jr redef_key_end redef_key_NO_SPACE: cp 'c' ; ¿Es 'c'? Imprimir "CS" jr nz, redef_key_NO_CAPSSHIFT ld de, redef_key_cs call PrintString jr redef_key_end redef_key_NO_CAPSSHIFT: cp 'y' ; ¿Es 'y'? Imprimir "SS" jr nz, redef_key_NO_SYMBOLSHIFT ld de, redef_key_ss call PrintString jr redef_key_end redef_key_NO_SYMBOLSHIFT: ; Si llegamos aqui no era tecla especial. rst 16 ; Ninguna tecla especial => Print ASCII ld a, d redef_key_end: ld a, h ; Recuperamos scancode call PrintCR ; Imprimir retorno de carro pop hl pop de ret ; Volver con registros preservados redef_key_enter DB "ENTER", _EOS redef_key_space DB "SPACE", _EOS redef_key_ss DB "SS", _EOS redef_key_cs DB "CS", _EOS ;----------------------------------------------------------------------- ; Lee el estado de las teclas definidas en variables y almacena en A ; dicho estado (1=pulsada, 0=no pulsada). El byte está codificado así: ; ; BITS 4 3 2 1 0 ; SIGNIFICADO FIRE LEFT RIGHT UP DOWN ; ; ENTRADA: NADA (usa las variables tecla_*) ; Se podria modificar para recibir HL = direccion tecla1 ; SALIDA: A = byte de estado de las teclas (empaquetadas en bits). ; MODIFICA: A, HL y CarryFlag ;----------------------------------------------------------------------- Leer_Teclado_Empaquetado: push de ld d, 0 ; D = 0 ld hl, tecla_izq ; Apuntamos HL a la primera de las teclas (izq) ld a, (hl) ; leemos su valor call Check_Key jr c, tecl_izq_notpressed set 3, d ; Si pulsada, ponemos bit 3 a 1. ; Usando A podríamos usar "or %00001000" tecl_izq_notpressed: inc hl ; inc hl a siguiente tecla en memoria (der) ld a, (hl) ; leemos su valor call Check_Key jr c, tecl_der_notpressed set 2, d ; Si pulsada, ponemos bit 2 a 1. tecl_der_notpressed: inc hl ; apuntamos HL a siguiente tecla (arriba) ld a, (hl) ; leemos su valor call Check_Key jr c, tecl_arr_notpressed set 1, d ; Si pulsada, ponemos bit 1 a 1. tecl_arr_notpressed: inc hl ; apuntamos HL a siguiente tecla (abajo) ld a, (hl) ; leemos su valor call Check_Key jr c, tecl_aba_notpressed set 0, d ; Si pulsada, ponemos bit 0 a 1. tecl_aba_notpressed: inc hl ; apuntamos HL a siguiente tecla (disparo) ld a, (hl) ; leemos su valorprimera call Check_Key jr c, tecl_fire_notpressed set 4, d ; Si pulsada, ponemos bit 4 a 1. tecl_fire_notpressed: ; Podriamos añadir codigo para disparo 2 ld a, d pop de ret ; Devolvemos en A el estado de las teclas ;----------------------------------------------------------------------- ; Chequea el teclado para detectar la pulsación de una tecla. ; Modifica A, H, DE y BC. ; Devuelve un código en el registro D que indica: ; ; Bits 0, 1 y 2 de "D": Semifila de teclas (puerto) detectada. ; Bits 3, 4 y 5 de "D": Tecla (posición) en esa semifila ; => (00TTTSSS) ; ; Así, el valor devuelto nos indica la semifila a leer y el bit a testear. ; ; El registro D valdrá 255 ($ff) si no hay ninguna tecla pulsada. ; ; Flags: ZF 0: Más de una tecla pulsada ; ZF 1: Tecla correctamente leída ;----------------------------------------------------------------------- Find_Key: ld de, $ff2f ; Valor inicial "ninguna tecla" ld bc, $fefe ; Puerto NXHALF: in a, (c) cpl and %00011111 jr z, NPRESS ; Saltar si ninguna tecla pulsada inc d ; Comprobamos si hay más de 1 tecla pulsada ret nz ; Si es así volver con Z a 0 ld h, a ; Cálculo del valor de la tecla ld a, e KLOOP: sub 8 srl h jr nc, KLOOP ret nz ; Comprobar si más de una tecla pulsada ld d, a ; Guardar valor de tecla en D NPRESS: ; Comprobar el resto de semifilas dec e rlc b jr c, NXHALF ; Repetimos escaneo para otra semifila cp a ; Ponemos flag a zero ret z ; Volvemos ;----------------------------------------------------------------------- ; Chequea el estado de una tecla concreta, aquella de scancode ; codificado en A (como parametro de entrada). ; ; Entrada: A = scancode (00SSSTTT). ; Devuelve: CARRY FLAG = 0 -> Tecla pulsada ; CARRY FLAG = 1 y BC = 0 -> Tecla no pulsada ;----------------------------------------------------------------------- Check_Key: push bc ld c, a ; Copia de A and %00000111 ; Aislamos tecla inc a ld b, a ; B = 16 - (num. linea direccion) srl c srl c srl c ld a, 5 sub c ld c, a ; C = (semifila + 1) ld a, $fe CKHiFind: ; Calcular el octeto de mayor peso del puerto rrca djnz CKHiFind in a, ($fe) ; Leemos la semifila CKNXKey: rra dec c jr nz, CKNXKey ; Ponemos el bit de tecla en el CF pop bc ret ;----------------------------------------------------------------------- ; Scancode2Ascii: convierte un scancode en un valor ASCII ; IN: D = scancode de la tecla a analizar ; OUT: A = Codigo ASCII de la tecla (0-9 y A-Z) ; minusculas: e = ENTER, s = SPACE, c = CAPSSHIFT e = SYMBOLSHIFT ;----------------------------------------------------------------------- Scancode2Ascii: push hl push bc ld hl, 0 ld bc, TABLA_Scancode2ASCII add hl, bc ; HL apunta al inicio de la tabla ; buscamos en la tabla un max de 40 veces por el codigo ; le sumamos 40 a HL, leemos el valor de (HL) y ret A SC2Ascii_1: ld a, (hl) ; leemos un byte de la tabla cp "1" ; Si es "1" fin de la rutina (porque en ; (la tabla habriamos llegado a los ASCIIs) jr z, SC2Ascii_Exit ; (y es condicion de forzado de salida) inc hl ; incrementamos puntero de HL cp d ; comparamos si A==D (nuestro scancode) jr nz, SC2Ascii_1 SC2Ascii_Found: ld bc, 39 ; Sumamos 39(+inc hl=40) para ir a la add hl, bc ; seccion de la tabla con el codigo ASCII ld a, (hl) ; leemos el codigo ASCII de esa tabla SC2Ascii_Exit: pop bc pop hl ret ; 40 scancodes seguidos de sus ASCIIs equivalentes TABLA_Scancode2ASCII: DEFB $24, $1c, $14, $0c, $04, $03, $0b, $13, $1b, $23 DEFB $25, $1d, $15, $0d, $05, $02, $0a, $12, $1a, $22 DEFB $26, $1e, $16, $0e, $06, $01, $09, $11, $19, $21 DEFB $27, $1f, $17, $0f, $07, $00, $08, $10, $18, $20 DEFB "1234567890QWERTYUIOPASDFGHJKLecZXCVBNMys" ;-- Incluir libreria de utilidades -- INCLUDE "utils.asm" END 33500