; Ejemplo de input de texto ORG 35000 ld hl, $3d00-256 call Font_Set_Charset ;;; Imprimir cadena "Introduce un texto:" ld hl, cadena1 ld b, 4 ld c, 0 call Font_Set_XY call PrintString_8x8_Format ;;; Obtener el input del usuario ld hl, input1 ld a, 20 call InputString_8x8 ;;; Imprimir "Tu cadena es:" + la cadena resultante ld hl, cadena2 call PrintString_8x8_Format ld hl, input1 call PrintString_8x8_Format ret cadena1 DB "Introduce un texto:", FONT_CRLF, FONT_CRLF DB FONT_SET_INK, 2, FONT_SET_STYLE, FONT_BOLD DB "> ", FONT_EOS cadena2 DB FONT_CRLF, FONT_CRLF, FONT_SET_STYLE, FONT_NORMAL DB FONT_SET_INK, 0, "Tu cadena es: ", FONT_CRLF, FONT_CRLF DB FONT_SET_INK, 2, FONT_SET_STYLE, FONT_BOLD, FONT_EOS input1 DS 35 DB 0 ;------------------------------------------------------------- LAST_K EQU 23560 KEY_SCAN EQU $028e ;------------------------------------------------------------- ; InputString_8x8: ; Obtiene una cadena de texto desde teclado. ; ; Entrada: ; Registro HL = Puntero a la cadena de texto a obtener. ; Registro A = Longitud maxima de la cadena a obtener ; Usa: ;------------------------------------------------------------- InputString_8x8: push hl ; Guardamos el puntero a la cadena push de push bc ; Modificados por KEY_SCAN ld (inputs_counter), a ; Contador de caracteres a usar ld (inputs_limit), a ; Guardamos la longitud maxima inputs_start: ld a, '_' ; Imprimir nuevo cursor call Font_SafePrintChar_8x8 xor a ld (LAST_K), a ; Limpiar ultima tecla pulsada inputs_loop: push hl call KEY_SCAN ; Escanear el teclado pop hl ld a, (LAST_K) ; Obtener el valor decodificado cp 13 jr z, inputs_end ; Es enter? -> fin de rutina cp 12 jr z, inputs_delete ; Es DELETE? -> borrar caracter cp 32 jr c, inputs_loop ; Es < 32? -> repetir bucle escaneo ex af, af' ; Nos guardamos el valor ASCII en A' ;;; Comprobacion de longitud maxima de cadena ld a, (inputs_counter) ; A = caracteres disponibles or a ; Comprobar si es 0 jr z, inputs_loop ; Si es cero, no insertar caracter dec a ld (inputs_counter), a ; Decrementar espacio disponible ex af, af' ; Recuperamos ASCII de A' ld (hl), a ; Guardamos el caracter leido inc hl ; Avanzamos al siguiente caracter ; Imprimimos el caracter y el cursor: call Font_SafePrintChar_8x8 call Font_Inc_X jr inputs_start inputs_end: ; ENTER pulsado -> Fin de la rutina ld a, ' ' ; Borramos de la pantalla el cursor call Font_SafePrintChar_8x8 xor a ld (hl), a ; Almacenamos un FIN DE CADENA en HL pop bc pop de ; Recuperamos valores de registros pop hl ; Recuperamos el inicio de la cadena ret inputs_delete: ; DELETE pulsado -> Borrar caracter ld a, (inputs_limit) ld b, a ld a, (inputs_counter) cp b ; Si char_disponibles-limite == 0 ... jr z, inputs_loop ; ... no podemos borrar (inicio de cadena) inc a ; Si no, si que podemos borrar: ld (inputs_counter), a ; incrementar espacio disponible dec hl ; Decrementar puntero en la cadena ld a, ' ' ; Borrar cursor y caracter anterior call Font_SafePrintChar_8x8 call Font_Dec_X jr inputs_start ; Bucle principal inputs_counter DB 0 inputs_limit DB 0 ;------------------------------------------------------------- FONT_CHARSET DW $3d00-256 FONT_ATTRIB DB 56 FONT_STYLE DB 0 FONT_X DB 0 FONT_Y DB 0 FONT_SCRWIDTH EQU 32 FONT_SCRHEIGHT EQU 24 FONT_NORMAL EQU 0 FONT_BOLD EQU 1 FONT_UNDERSC EQU 2 FONT_ITALIC EQU 3 FONT_EOS EQU 0 FONT_SET_STYLE EQU 1 FONT_SET_X EQU 2 FONT_SET_Y EQU 3 FONT_SET_INK EQU 4 FONT_SET_PAPER EQU 5 FONT_SET_ATTRIB EQU 6 FONT_SET_BRIGHT EQU 7 FONT_SET_FLASH EQU 8 FONT_XXXXXX EQU 9 ; Libre para ampliaciones FONT_LF EQU 10 FONT_CRLF EQU 11 FONT_BLANK EQU 12 FONT_CR EQU 13 FONT_BACKSPACE EQU 14 FONT_TAB EQU 15 FONT_INC_X EQU 16 ; De la 17 a la 31 libres ;------------------------------------------------------------- ; Tabla con las direcciones de las 16 rutinas de cambio. Notese ; que la numero 9 queda libre para una posible ampliacion. ;------------------------------------------------------------- FONT_CALL_JUMP_TABLE: DW Font_Set_Style, Font_Set_X, Font_Set_Y, Font_Set_Ink DW Font_Set_Paper, Font_Set_Attrib, Font_Set_Bright DW Font_Set_Flash, 0000, Font_LF, Font_CRLF, Font_Blank DW Font_CR, Font_Backspace, Font_Tab, Font_Inc_X ;------------------------------------------------------------- ; Establecer el CHARSET en USO ; Entrada : HL = direccion del charset en memoria ;------------------------------------------------------------- Font_Set_Charset: ld (FONT_CHARSET), hl ret ;------------------------------------------------------------- ; Establecer el estilo de texto en uso. ; Entrada : A = estilo ;------------------------------------------------------------- Font_Set_Style: ld (FONT_STYLE), a ret ;------------------------------------------------------------- ; Establecer la coordenada X en pantalla. ; Entrada : A = coordenada X ;------------------------------------------------------------- Font_Set_X: ld (FONT_X), a ret ;------------------------------------------------------------- ; Establecer la coordenada Y en pantalla. ; Entrada : A = coordenada Y ;------------------------------------------------------------- Font_Set_Y: ld (FONT_Y), a ret ;------------------------------------------------------------- ; Establecer la posicion X,Y del curso de fuente en pantalla. ; Entrada : B = Coordenada Y ; C = Coordenada X ;------------------------------------------------------------- Font_Set_XY: ld (FONT_X), bc ret ;------------------------------------------------------------- ; Establecer un valor de tinta para el atributo en curso. ; Entrada : A = Tinta (0-7) ; Modifica: AF ;------------------------------------------------------------- Font_Set_Ink: push bc ; Preservamos registros and 7 ; Borramos bits 7-3 ld b, a ; Lo guardamos en B ld a, (FONT_ATTRIB) ; Cogemos el atributo actual and %11111000 ; Borramos el valor de INK or b ; Insertamos INK en A ld (FONT_ATTRIB), a ; Guardamos el valor de INK pop bc ret ;------------------------------------------------------------- ; Establecer un valor de papel para el atributo en curso. ; Entrada : A = Papel (0-7) ; Modifica: AF ;------------------------------------------------------------- Font_Set_Paper: push bc ; Preservamos registros and 7 ; Borramos bits 7-3 rlca ; A = 00000XXX -> 0000XXX0 rlca ; A = 000XXX00 rlca ; A = 00XXX000 <-- Valor en paper ld b, a ; Lo guardamos en B ld a, (FONT_ATTRIB) ; Cogemos el atributo actual and %11000111 ; Borramos los datos de PAPER or b ; Insertamos PAPER en A ld (FONT_ATTRIB), a ; Guardamos el valor de PaPER pop bc ret ;------------------------------------------------------------- ; Establecer un valor de atributo para la impresion. ; Entrada : A = Tinta ;------------------------------------------------------------- Font_Set_Attrib: ld (FONT_ATTRIB), a ret ;------------------------------------------------------------- ; Establecer un valor de brillo (1/0) en el atributo actual. ; Entrada : A = Brillo (0-7) ; Modifica: AF ;------------------------------------------------------------- Font_Set_Bright: and 1 ; A = solo bit 0 de A ld a, (FONT_ATTRIB) ; Cargamos en A el atributo jr nz, fsbright_1 ; Si el bit solicitado era res 6, a ; Seteamos a 0 el bit de flash ld (FONT_ATTRIB), a ; Escribimos el atributo ret fsbright_1: set 6, a ; Seteamos a 1 el bit de brillo ld (FONT_ATTRIB), a ; Escribimos el atributo ret ;------------------------------------------------------------- ; Establecer un valor de flash (1/0) en el atributo actual. ; Entrada : A = Flash (1/0) ; Modifica: AF ;------------------------------------------------------------- Font_Set_Flash: and 1 ; A = solo bit 0 de A ld a, (FONT_ATTRIB) ; Cargamos en A el atributo jr nz, fsflash_1 ; Si el bit solicitado era res 7, a ; Seteamos a 0 el bit de flash ld (FONT_ATTRIB), a ; Escribimos el atributo ret fsflash_1: set 7, a ; Seteamos a 1 el bit de flash ld (FONT_ATTRIB), a ; Escribimos el atributo ret ;------------------------------------------------------------- ; Imprime un espacio, sobreescribiendo la posicion actual del ; cursor e incrementando X en una unidad. ; de la pantalla (actualizando Y en consecuencia). ; Modifica: AF ;------------------------------------------------------------- Font_Blank: ld a, ' ' ; Imprimir caracter espacio push bc push de push hl call PrintChar_8x8 ; Sobreescribir caracter pop hl pop de pop bc call Font_Inc_X ; Incrementamos la coord X ret ;------------------------------------------------------------- ; Incrementa en 1 la coordenada X teniendo en cuenta el borde ; de la pantalla (actualizando Y en consecuencia). ; Modifica: AF ;------------------------------------------------------------- Font_Inc_X: ld a, (FONT_X) ; Incrementamos la X inc a ; pero comprobamos si borde derecho cp FONT_SCRWIDTH-1 ; X > ANCHO-1? jr c, fincx_noedgex ; No, se puede guardar el valor call Font_CRLF ret fincx_noedgex: ld (FONT_X), a ; Establecemos el valor de X ret ;------------------------------------------------------------- ; Produce un LineFeed (incrementa Y en 1). Tiene en cuenta ; las variables de altura de la pantalla. ; Modifica: AF ;------------------------------------------------------------- Font_LF: ld a, (FONT_Y) ; Cogemos coordenada Y cp FONT_SCRHEIGHT-1 ; Estamos en la parte inferior jr nc, fontlf_noedge ; de pantalla? -> No avanzar inc a ; No estamos, avanzar ld (FONT_Y), a fontlf_noedge: ret ;------------------------------------------------------------- ; Produce un Retorno de Carro (Carriage Return) -> X=0. ; Modifica: AF ;------------------------------------------------------------- Font_CR: xor a ld (FONT_X), a ret ;------------------------------------------------------------- ; Provoca un LF y un CR en ese orden. ; Modifica: AF ;------------------------------------------------------------- Font_CRLF: call Font_LF call Font_CR ret ;------------------------------------------------------------- ; Imprime un tabulador (3 espacios) mediante PrintString. ; Modifica: AF ;------------------------------------------------------------- Font_Tab: push bc push de push hl ld hl, font_tab_string call PrintString_8x8_Format ; Imprimimos 3 espacios pop hl pop de pop bc ret font_tab_string DB " ", 0 ;------------------------------------------------------------- ; Decrementa la coordenada X, simultando un backspace. ; No realiza el borrado en si. ; Modifica: AF ;------------------------------------------------------------- Font_Dec_X: ld a, (FONT_X) ; Cargamos la coordenada X or a ret z ; Es cero? no se hace nada (salir) dec a ; No es cero? Decrementar ld (FONT_X), a ret ; Salir ;------------------------------------------------------------- ; Decrementa la coordenada X, simultando un backspace. No ; realiza el borrado en si. ; Modifica: AF ;------------------------------------------------------------- Font_Backspace: call Font_Dec_X ld a, ' ' ; Imprimir caracter espacio push bc push de push hl call PrintChar_8x8 ; Sobreescribir caracter pop hl pop de pop bc ret ; Salir ;------------------------------------------------------------- ; Ejecuta PrintChar_8x8 preservando registros ;------------------------------------------------------------- Font_SafePrintChar_8x8 push bc push de push hl ; Preservar registros call PrintChar_8x8 ; Imprimir caracter pop hl ; Recuperar registros pop de pop bc ret ;------------------------------------------------------------- ; PrintString_8x8_Format: ; Imprime una cadena de texto de un charset de fuente 8x8. ; ; Entrada (paso por parametros en memoria): ; ----------------------------------------------------- ; FONT_CHARSET = Direccion de memoria del charset. ; FONT_X = Coordenada X en baja resolucion (0-31) ; FONT_Y = Coordenada Y en baja resolucion (0-23) ; FONT_ATTRIB = Atributo a utilizar en la impresion. ; Registro HL = Puntero a la cadena de texto a imprimir. ; Debe acabar en cero (FONT_EOS). ; Usa: DE, BC ;------------------------------------------------------------- PrintString_8x8_Format: ;;; Bucle de impresion de caracter pstring8_loop: ld a, (hl) ; Leemos un caracter de la cadena inc hl ; Apuntamos al siguiente caracter cp 32 ; Es menor que 32? jp c, pstring8_ccontrol ; Si, es un codigo de control, saltar push hl ; Salvaguardamos HL call PrintChar_8x8 ; Imprimimos el caracter pop hl ; Recuperamos HL ;;; Avanzamos el cursor usando Font_Blank, que incrementa X ;;; y actualiza X e Y si se llega al borde de la pantalla call Font_Inc_X ; Avanzar coordenada X jr pstring8_loop ; Continuar impresion hasta CHAR=0 pstring8_ccontrol: or a ; A es cero? ret z ; Si es 0 (fin de cadena) volver ;;; Si estamos aqui es porque es un codigo de control distinto > 0 ;;; Ahora debemos calcular la direccion de la rutina que lo atendera. ;;; Calculamos la direccion destino a la que saltar usando ;;; la tabla de saltos y el codigo de control como indice ex de, hl ld hl, FONT_CALL_JUMP_TABLE rlca ; A = A * 2 = codigo de control * 2 ld c, a ld b, 0 ; BC = A*2 add hl, bc ; HL = DIR FONT_CALL_JUMP_TABLE+(CodControl*2) ld c, (hl) ; Leemos la parte baja de la direccion en C... inc hl ; ... para no corromper HL y poder leer ... ld h, (hl) ; ... la parte alta sobre H ... ld l, c ; No hemos usado A porque se usa en el CP ;;; Si CCONTROL>0 y CCONTROL<10 -> recoger parametro y saltar a rutina ;;; Si CCONTROL>9 y CCONTROL<32 -> saltar a rutina sin recogida cp 18 ; Comprobamos si (CCONTROL-1)*2 < 18 jp nc, pstring8_noparam ; Es decir, si CCONTROL > 9, no hay param ;;; Si CCONTROL < 10 -> recoger parametro: ld a, (de) ; Cogemos el parametro en cuestion de la cadena inc de ; Apuntamos al siguiente caracter ;;; Realizamos el salto a la rutina con o sin parametro recogido pstring8_noparam: ld bc, pstring8_retaddr ; Ponemos en BC la dir de retorno push bc ; Hacemos un push de la dir de retorno jp (hl) ; Saltamos a la rutina seleccionada ;;; Este es el punto al que volvemos tras la rutina pstring8_retaddr: ex de, hl ; Recuperamos en HL el puntero a cadena jr pstring8_loop ; Continuamos en el bucle ret ;------------------------------------------------------------- ; PrintChar_8x8: ; Imprime un caracter de 8x8 pixeles de un charset usando ; el estilo especificado en FONT_STYLE ; ; Entrada (paso por parametros en memoria): ; ----------------------------------------------------- ; FONT_CHARSET = Direccion de memoria del charset. ; FONT_X = Coordenada X en baja resolucion (0-31) ; FONT_Y = Coordenada Y en baja resolucion (0-23) ; FONT_ATTRIB = Atributo a utilizar en la impresion. ; FONT_STYLE = Estilo a utilizar (0-N). ; Registro A = ASCII del caracter a dibujar. ;------------------------------------------------------------- PrintChar_8x8: ld bc, (FONT_X) ; B = Y, C = X ex af, af' ; Nos guardamos el caracter en A' ;;; Calculamos las coordenadas destino de pantalla en DE: ld a, b and $18 add a, $40 ld d, a ld a, b and 7 rrca rrca rrca add a, c ld e, a ; DE contiene ahora la direccion destino. ;;; Calcular posicion origen (array sprites) en HL como: ;;; direccion = base_sprites + (NUM_SPRITE*8) ex af, af' ; Recuperamos el caracter a dibujar de A' ld bc, (FONT_CHARSET) ld h, 0 ld l, a add hl, hl add hl, hl add hl, hl add hl, bc ; HL = BC + HL = FONT_CHARSET + (A * 8) ex de, hl ; Intercambiamos DE y HL (DE=origen, HL=destino) ;;; NUEVO: Verificacion del estilo actual ld a, (FONT_STYLE) ; Obtenemos el estilo actual or a jr nz, pchar8_estilos_on ; Si es != cero, saltar ;;;;;; Estilo NORMAL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ld b, 8 ; 8 scanlines a dibujar drawchar_loop_normal: ld a, (de) ; Tomamos el dato del caracter ld (hl), a ; Establecemos el valor en videomemoria inc de inc h djnz drawchar_loop_normal jr pchar8_printattr pchar8_estilos_on: cp FONT_BOLD ; ¿Es estilo NEGRITA? jr nz, pchar8_nobold ; No, saltar ;;;;;; Estilo NEGRITA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ld b, 8 ; 8 scanlines a dibujar drawchar_loop_bold: ld a, (de) ; Tomamos el dato del caracter ld c, a ; Creamos copia de A rrca ; Desplazamos A or c ; Y agregamos C ld (hl), a ; Establecemos el valor en videomemoria inc de ; Incrementamos puntero en caracter inc h ; Incrementamos puntero en pantalla (scanline+=1) djnz drawchar_loop_bold jr pchar8_printattr pchar8_nobold: cp FONT_UNDERSC ; ¿Es estilo SUBRAYADO? jr nz, pchar8_noundersc ; No, saltar ;;;;;; Estilo SUBRAYADO ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ld b, 7 ; 7 scanlines a dibujar normales drawchar_loop_undersc: ld a, (de) ; Tomamos el dato del caracter ld (hl), a ; Establecemos el valor en videomemoria inc de inc h djnz drawchar_loop_undersc ;;; El octavo scanline, una linea de subrayado ld a, 255 ; Ultima linea = subrayado ld (hl), a inc h ; Necesario para el sub a, 8 jr pchar8_printattr pchar8_noundersc: cp FONT_ITALIC ; ¿Es estilo ITALICA? jr nz, pchar8_UNKNOWN ; No, saltar ;;;;;; Estilo ITALICA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; 3 primeros scanlines, a la derecha, ld b, 3 drawchar_loop_italic1: ld a, (de) ; Tomamos el dato del caracter sra a ; Desplazamos A a la derecha ld (hl), a ; Establecemos el valor en videomemoria inc de inc h djnz drawchar_loop_italic1 ;;; 2 siguientes scanlines, sin tocar ld b, 2 drawchar_loop_italic2: ld a, (de) ; Tomamos el dato del caracter ld (hl), a ; Establecemos el valor en videomemoria inc de inc h djnz drawchar_loop_italic2 ld b, 3 drawchar_loop_italic3: ;;; 3 ultimos scanlines, a la izquierda, ld a, (de) ; Tomamos el dato del caracter sla a ; Desplazamos A ld (hl), a ; Establecemos el valor en videomemoria inc de inc h djnz drawchar_loop_italic3 jr pchar8_printattr pchar8_UNKNOWN: ; Estilo desconocido... ld b, 8 ; Lo imprimimos con el normal jr drawchar_loop_normal ; (estilo por defecto) ;;; Impresion de los atributos pchar8_printattr: ld a, h ; Recuperamos el valor inicial de HL sub 8 ; Restando los 8 scanlines avanzados ;;; Calcular posicion destino en area de atributos en DE. ; A = H rrca ; Codigo de Get_Attr_Offset_From_Image rrca rrca and 3 or $58 ld d, a ld e, l ;;; Escribir el atributo en memoria ld a, (FONT_ATTRIB) ld (de), a ; Escribimos el atributo en memoria ret END 35000