;-----------------------------------------------------------------------------
;                              Calendario ZX 1.1
;                      Listagem do Codigo Fonte Assembly
;                          Por Cleber Jean Barranco
;                           cleberjean@hotmail.com
;                       Florestopolis - Parana - Brasil
;                                 03/Ago/2006
;-----------------------------------------------------------------------------


Key5 .equ $21
Key6 .equ $22
Key7 .equ $23
Key8 .equ $24
KeyD .equ $29
Shift_Key5 .equ $72
Shift_Key6 .equ $71
Shift_Key7 .equ $70
Shift_Key8 .equ $73
Shift_Spc  .equ $0C


;Nome do programa e ocultacao dos codigos na linha REM

    db   $A8,$A6,$B1,$AA,$B3,$A9,$76,$76


;====  V A R I A V E I S   U T I L I Z A D A S   N O   P R O G R A M A  ======

;Variaveis usadas pelo programa

MES_CAL:
    db   8             ;mes que esta' sendo exibido

ANO_CAL:
    dw   2006          ;ano que esta' sendo exibido

DIAS_MES:
    db   00h           ;# de dias do mes 

;Reserved (utilizado na versao 2.x e deixado aqui para manter o inicio do programa em 4090h) 

    dw   0000h


;===================  I N I C I O   D O   P R O G R A M A  ===================

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Entrada do programa (endereco 16528 (4090h))
; O comportamento do programa depende do valor armazenado no
; endereco 16417 (4021h) (alterado durante a execucao do programa) como segue:
;
;    Valor          Acao
;    -----          ----
;      0     Cria caixa de mensagem.
;      1     Cria a moldura do calendario.
;    2-255   Executa o calendario.
;
; Observacao: O conteudo do endereco 16417 e' alterado durante a execucao do
; ==========  do calendario (armazena o codigo da ultima tecla pressionada).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Entry_Point:
    ld   a,(4021h)     ;obtem a acao a ser executada
    cp   1
    jp   z,Draw_Frame  ;desenha a moldura do calendario
    and  a
    jp   nz,Calendar   ;executa o calendario


;=====  I N I C I O   D A   T E L A   P A R A   P E D I R   A   D A T A  =====

;Cria as linhas superior e inferior (retorna B = 0 para a rotina seguinte)

    ld   hl,(400Ch)
    push hl
    ld   de,22h
    add  hl,de
    ld   b,20h         ;comprimento da linha superior
    ld   (hl),$03
    inc  hl
    djnz $-3           ;traca a linha superior (salta para LD (HL),$03)
    ld   de,0274h      ;1 + 33 + 627
    add  hl,de
    ld   b,20h         ;comprimento da linha inferior
    ld   (hl),$83
    inc  hl
    djnz $-3           ;traca a linha inferior (salta para LD (HL),$83)


;===================  C A I X A   D E   M E N S A G E M  =====================

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Cria a caixa de mensagem para pedir o mes e o ano
;
; Esta rotina funciona em conjunto com o BASIC para
; escrever o titulo e o conteudo da caixa. Isto e'
; feito assim para facilitar a traducao do programa
; para outros idiomas.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    pop  hl            ;D_File
    ld   c,0CEh        ;posicao da caixa
    add  hl,bc         ;aproveita B que foi zerado na rotina anterior
    ld   b,12h         ;largura da janela
    ld   c,07h         ;altura da janela
    call Shadow        ;cria a sombra da janela (retorna valor em DE)
    dec  b
    dec  b             ;largura interna da caixa (caixa menos as bordas laterais)
    dec  c
    dec  c             ;altura interna da caixa (caixa menos as bordas superior e inferior)
    push hl            ;salva a posicao da janela no video
    call Draw_Rectangle
    pop  hl            ;restaura a posicao da janela no video
    inc  b
    inc  b             ;largura externa da janela
    ld   (hl),$80      ;barra de titulo da janela
    inc  hl
    djnz $-3           ;salta para LD (HL),$80
    ret                ;retorna ao BASIC


;===============  M O L D U R A   D O   C A L E N D A R I O  =================

;Desenha a moldura do calendario

Draw_Frame:
    ld   hl,(400Ch)
    inc  hl
    push hl
    ld   b,20h
    ld   (hl),$00
    inc  hl
    djnz $-3           ;apaga a 1a. linha da tela (CLS)
    pop  hl
    ld   b,1Fh         ;largura da moldura (31 colunas)
    ld   c,16h         ;altura da da moldura (22 linhas)
    call Shadow        ;cria a sombra da moldura (retorna valor em DE)
    dec  b
    dec  b             ;largura interna
    ld   c,1
    call Draw_Rectangle
    ld   c, 0Fh        ;numero de linhas no meio do calendario
    call Draw_Sides
    ld   c,2


Draw_Rectangle:
    ld   a,b           ;copia a largura interna do retangulo para A
    ld   (hl),$07      ;borda superior esquerda
    inc  hl
    ld   (hl),$03      ;meio da borda superior
    inc  hl
    djnz $-3
    ld   (hl),$84      ;borda superior direita
    add  hl,de
    ld   b,a
    call Draw_Sides
    ld   (hl),$82      ;borda inferior esquerda
    inc  hl
    ld   (hl),$83      ;meio da borda inferior
    inc  hl
    djnz $-3
    ld   (hl),$81      ;borda inferior direita
    add  hl,de
    ld   b,a           ;retorna B (largura interna do retangulo) preservado
    ret


;Desenha as laterais das janelas (preserva A e B (obrigatorio), zera C)

Draw_Sides:
    ld   (hl),$05      ;borda esquerda do retangulo
    inc  hl
    push bc
    ld   (hl),$00      ;interior do retangulo
    inc  hl
    djnz $-3
    ld   (hl),$85      ;borda direita do retangulo
    add  hl,de
    pop  bc
    dec  c
    jr   nz,Draw_Sides
    ret


;==================  S O M B R A   D A S   J A N E L A S  ====================

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Cria a sombra das janelas (24 bytes)
; Versao 1.1 de 02/08/2006.
; Entrada:
;   HL = Endereco da posicao da janela proprietaria da sombra
;    B = largura da janela proprietaria da sombra
;    C = altura da janela proprietaria da sombra
; Retorno:
;   HL e BC preservados (obrigatorio)
;   DE = Valor do incremento para o calculo do endereco das linhas
;        (sera' usado pelas janelas proprietarias)
;   Acumulador limpo (0) (nao e' obrigatorio)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Shadow:
    push hl            ;salva o endereco da janela dentro do D_File
    ld   de,0022h      ;1 linha abaixo (33 colunas) + 1 coluna `a direita
    add  hl,de         ;obtem a posicao da sombra
    ld   a,21h
    sub  b             ;33 - a largura da sombra
    ld   e,a
    ld   a,c           ;copia o numero de linhas em A
    push bc            ;salva o contador colunas (B)
    ld   (hl),$08
    inc  hl
    djnz $-3           ;LD (HL),$08
    pop  bc            ;restaura o contador de colunas (B)
    add  hl,de         ;calcula o endereco da proxima linha
    dec  a             ;decrementa o contador de linhas da sombra
    jr   nz,$-9        ;volta para PUSH BC
    inc  de
    pop  hl            ;restaura o endereco da janela dentro do D_File
    ret


;================  I N I C I O   D O   C A L E N D A R I O  ==================

;Inicio do codigo do calendario

Calendar:
    bit  7,(iy+3Bh)    ;verifica se o computador esta' em FAST
    call z,0F2Bh       ;chama o modo SLOW, qualquer que seje o modo FAST

Show_Month:
    call Update_Month  ;exibe o mes
        

;Aguarda o pressionamento de uma tecla (loop do programa)

Wait_Key:
    call Get_Key
    ld   a,c           ;copia a tecla pressionada para A
    cp   $7F
    jr   z,Wait_Key    ;nenhuma tecla pressionada

;Teclas sem Shift pressionado

    and  a             ;testa o pressionamento do espaco (CHR$ 0)
    ret  z             ;retorna ao BASIC
    cp   Key5
    jr   z,Back_Month
    cp   Key6
    jr   z,Back_Year
    cp   Key7
    jr   z,Forward_Year
    cp   Key8
    jr   z,Forward_Month

;Teclas com Shift pressionado

    cp   Shift_Spc     ;testa pressionamento de shift+espaco
    ret  z             ;retorna ao BASIC
    cp   Shift_Key5
    jr   z,Back_Month
    cp   Shift_Key6
    jr   z,Back_Year
    cp   Shift_Key7
    jr   z,Forward_Year
    cp   Shift_Key8
    jr   z,Forward_Month
    cp   KeyD
    jr   z,Calendar_Date
    jr   Wait_Key
              

;========  A V A N C A   O U   V O L T A   M E S E S   E   A N O S  ==========

;Volta o mes

Back_Month:
    ld  a,(MES_CAL)
    dec a
    jr  nz,Saves_Month
    ld  hl,(ANO_CAL)
    dec hl
    ld  a,l
    cp  6Ch            ;verifica se o ano chegou a 1900
    jr  nz,$+5
    ld  hl,2099
    ld  a,0Ch

Saves_YearMonth:
    ld  (ANO_CAL),hl

Saves_Month:
    ld  (MES_CAL),a    ;salva o novo mes
    jr  Show_Month     ;e atualiza o calendario


;Volta o ano

Back_Year:
    ld  hl,(ANO_CAL)
    dec hl
    ld  a,l
    cp  6Ch            ;verifica se o ano chegou a 1900
    jr  nz,Saves_Year
    ld  hl,2099

Saves_Year:
    ld  (ANO_CAL),hl   ;salva o novo ano
    jr  Show_Month     ;e atualiza o calendario


;Avanca o Mes

Forward_Month:
    ld  a,(MES_CAL)
    inc a
    cp  0Dh
    jr  nz,Saves_Month
    ld  hl,(ANO_CAL)
    inc hl
    ld  a,l
    cp  34h            ;verifica se o ano chegou a 2100
    jr  nz,$+5
    ld  hl,1901
    ld  a,01h
    jr  Saves_YearMonth


;Avanca o ano

Forward_Year:
    ld  hl,(ANO_CAL)
    inc hl
    ld  a,l
    cp  34h            ;verifica se o ano chegou a 2100
    jr  nz,Saves_Year       
    ld  hl,1901        ;complementa o ano
    jr  Saves_Year


;Data da criacao/revisao do programa

Calendar_Date:
    ld  a,8            ;mes
    ld  hl,2006        ;ano
    jr  Saves_YearMonth


;===============  A T U A L I Z A   O   C A L E N D A R I O  =================

;Atualiza o calendario com o novo mes

Update_Month:
    call Clear_Buffer      ;limpa o conteudo do buffer de impressao
    call Print_Month_Name  ;monta o nome do mes e o ano no buffer
    call Calc_Month_Length ;calcula o # de dias do mes
    call Calc_Week_Day     ;calcula o dia da semana em que o mes comeca
    add  a,a               ;Dia da semana x 2
    add  a,a               ;Dia da semana x 4 (cada dia ocupa 4 colunas do video)


;Calcula do endereco do dia 1o. do mes

    ld   hl,(401Ch)
    ld   de,27         ;1 + 26 caracteres
    add  hl,de         ;endereco da 1a. semana dentro do buffer
    ld   (400Eh),hl    ;salva o endereco da 1a. semana
    ld   e,a
    add  hl,de         ;desloca para o dia da semana em que comeca o mes
    ex   de,hl         ;move o endereco para DE
    ld   a,1           ;primeiro dia do mes


;Impressao dos dias

Print_Days:
    push af
    call Print_Day     ;imprime o dia (retorna B=0)


;Verifica se todos os dias foram impressos

    ld   a,(DIAS_MES)  ;obtem o numero de dias do mes
    ld   c,a
    pop  af            ;obtem o ultimo dia impresso
    cp   c             ;verifica se foi o ultimo dia do mes
    ld   c,1Ah         ;numero de colunas na linha
    jr   z,Buff2Scn    ;encerra a impressao dos dias copiando o conteudo do buffer para o video
    inc  a             ;proximo dia do mes
    ld   hl,(400Eh)
    add  hl,bc         ;obtem o endereco da impressao do Sabado (B foi zerado por Print_Day)
    sbc  hl,de         ;verifica se terminou a semana (DE = endereco da proxima impressao)
    jr   nz,Same_Line
    ld   (400Eh),de    ;imprimir na linha de baixo (outra semana)
    jr   Print_Days

Same_Line:
    inc  de            ;espaco entre os dias
    inc  de            ;espaco entre os dias
    jr   Print_Days    ;continua imprimindo na mesma linha


;======================  L I M P A   O   B U F F E R  ========================

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Limpa o conteudo do buffer (17 bytes)
; Entrada:
;   Nada.
; Retorno:
;   DE e Acumulador preservados. (OBRIGATORIO)
;   BC = 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Clear_Buffer:
    ld   hl,(401Ch)
    inc  hl
    ld   c,07h         ;apagar 7 linhas
    ld   b,1Ah         ;tamanho da linha em caracteres
    ld   (hl),$00      ;apaga caractere
    inc  hl
    djnz $-3           ;salta para LD (HL),$00
    dec  c
    jr   nz,$-8        ;salta para LD B,1Ah
    ret


;==========  C O P I A   O   B U F F E R   P A R A   A   T E L A  ============

;Copia o conteudo do buffer para a tela e retorna para Get_Key
;Entrada: BC = numero de colunas por linha

Buff2Scn:
    ld   hl,(400Ch)
    ld   de,0024h
    add  hl,de
    ex   de,hl
    ld   hl,(401Ch)
    inc  hl
    ldir               ;copia o nome do mes para o cabecalho do calendario


;Copia os dias do mes para o corpo do calendario

    ld   c,8Bh         ;posicao dos dias dentro do calendario
    ex   de,hl
    add  hl,bc         ;endereco da 1a. linha (semana), dentro do D_File
    ex   de,hl
    ld   b,06h         ;numero de linhas a copiar
    ld   c,1Ah         ;numero de caracteres por linha, a copiar

Copies_Week:
    push bc
    ld   b,0
    ldir
    ld   c,28h
    ex   de,hl
    add  hl,bc
    ex   de,hl
    pop  bc    
    djnz Copies_Week
    ret


;=================  M O N T A   O   N O M E   D O   M E S  ===================

;Monta o nome do mes e o ano, no buffer do mes (variavel do sistema PRBUFF)

Print_Month_Name:
    ld   a,(MES_CAL)
    dec  a             ;os meses devem comecar em zero para poder realizar o calculo
    ld   d,a
    add  a,a           ;mes * 2
    add  a,a           ;mes * 4
    add  a,a           ;mes * 8
    add  a,d           ;mes * 9
    ld   e,a
    ld   d,0
    ld   hl,Month_Name
    add  hl,de         ;endereco do nome do mes
    ld   de,403Ch      ;endereco do buffer do mes
    ld   b,09h         ;comprimento maximo da string do nome do mes
    ld   a,(hl)
    and  a             ;terminou o nome do mes?
    jr   z,Preposition ;entao salta para EX DE,HL
    ld   (de),a
    inc  de
    inc  hl
    djnz $-7           ;volta para LD A,(HL)


;Preposicao " de "

Preposition:
    ex   de,hl         ;passa o endereco da impressao dentro do buffer, para HL
    sub  a
    ld   (hl),a        ;espaco
    inc  hl
    ld   (hl),$29      ;letra D
    inc  hl
    ld   (hl),$2A      ;letra E
    inc  hl
    ld   (hl),a        ;espaco
    inc  hl
    ex   de,hl         ;volta o endereco da impressao no buffer para DE


;Adiciona o ano

    ld   hl,(ANO_CAL)
    push bc
    call Thousand
    pop  bc
    ld   a,11h         ;comprimento maximo de mes + o ano
    sub  b


;Copia o nome do mes + o ano para o cabecalho do calendario

    ld   hl,(401Ch)
    ld   de,000Eh      ;1 + 13
    add  hl,de
    ld   b,d           ;zera B
    ld   c,a           ;total de caracteres a imprimir
    rrca               ;"LEN(mes) / 2" (ATENCAO: bit 7 de A recebe o conteudo do bit 0)
    and  7Fh           ;limpa o bit 7 de A (veja o comentario anterior) e reseta carry
    ld   e,a
    sbc  hl,de         ;centraliza o nome do mes, no cabecalho
    ex   de,hl
    ld   hl,403Ch      ;endereco do rascunho com o nome do mes e ano (PRBUFF)
    ldir
    ret                ;volta para Update_Month


;===========  E N C O N T R A   O   T A M A N H O   D O   M E S  =============

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Calcula o numero de dias do mes (33 bytes)
; Entrada:
;   Nada
; Retorno:
;   A = total de dias do mes
;   C = mes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Calc_Month_Length:
    ld   a,(MES_CAL)
    cp   2             ;Fevereiro?
    jr   nz,Not_Feb
    ld   a,(ANO_CAL)
    and  %00000011     ;testa se o ano e' bissexto
    ld   a,28          ;# de dias em Fevereiro
    jr   nz,Saves_Days ;ano nao e' bissexto
    inc  a             ;Fevereiro tem 29 Dias
    jr   Saves_Days

Not_Feb:
    ld   c,a
    srl  a             ;mes / 2
    srl  a             ;mes / 4
    srl  a             ;mes / 8
    add  a,c           ;apos a operacao: bit 0 de A = 1 se mes = 31 dias
    or   1Eh           ;A = 30 ou 31 se mes = 30 ou 31 dias

Saves_Days:
    ld   (DIAS_MES),a  ;salva o numero de dias do mes
    ret


;============  E N C O N T R A   O   I N I C I O   D O   M E S  ==============

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Descobre o dia em que o mes comeca
; Obedece ao algoritmo:
;
; Entrada:
;   Nada
; Retorno:
;   Acumulador = dia da semana em que o mes comeca (Domingo = 0)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Calc_Week_Day:
    ld   de,(ANO_CAL)
    ld   a,(MES_CAL)
    inc  a             ;mes = mes + 1
    cp   04
    jr   nc,March      ;mes > 2
    add  a,0Ch         ;soma 12 ao mes
    dec  de            ;decrementa o ano

March:
    ld   l,a
    add  a,a           ;A x 2
    add  a,a           ;A x 4
    ld   h,a           ;copia A x 4 para H
    add  a,a           ;A x 8
    add  a,h           ;A x 8 + A x 4 = A x 12
    add  a,l           ;A x 12 + A = A x 13
    ld   l,a
    ld   h,00h
    ld   c,05h
    call DivMOD        ;A x 13 / 5
    ex   de,hl         ;HL = JL
    ld   b,h
    ld   c,l
    add  hl,hl         ;JL x 2
    add  hl,hl         ;JL x 4
    add  hl,bc         ;JL x 4 + JL = JL x 5
    ld   c,04h
    call DivMOD        ;JL x 5 / 4
    add  hl,de         ;(A x 13 / 5) + (JL x 5 / 4)
    dec  hl            ;((A x 13 / 5) + (JL x 5 / 4)) - 1
    ld   c,07h         ;MOD 7


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Rotina para calculo de modulo e divisao
; Entrada: HL = # a dividir, C = divisor (ou modulo)
; Retorno: HL = Quociente, A = Resto, DE preservado (obrigatorio).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

DivMOD:
    xor  a             ;zera Acumulador e Carry
    ld   b,10h

Dividing:
    add  hl,hl
    rla
    cp   c
    jr   c,$+4
    sub  c
    inc  l
    djnz Dividing
    ret


;==============  I M P R I M E   O S   D I A S   D O   M E S  ================

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Impressao dos dias do Mes
; Entrada:
;   A = dia a imprimir
;  DE = endereco da impressao
; Retorno:
;   B = zero (0) (NECESSARIO)
;   C = 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Print_Day:
    ld   b,0           ;zera B para a rotina de impressao
    ld   h,b           ;zera H (o valor maximo armazenado em HL sera' 31)
    ld   l,a           ;HL = dia a imprimir no buffer
    cp   0Ah           ;dia < 10?
    jr   nc,Ten        ;dia >= 10
    sub  a
    ld   (DE),a        ;imprime um espaco `a esquerda do numero
    inc  de
    jr   Unit          ;imprime a unidade do numero


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Rotina impressora de numeros
; Entrada:
;   HL = # a imprimir
;   DE = endereco inicial da impressao dentro do Buffer
; Retorno:
;   HL destruido
;   DE endereco seguinte ao ultimo caractere impresso
;   BC = 1
;   Acumulador = ultimo algarismo impresso
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Thousand:
    ld   bc,1000
    call Print_Number

Hundred:
    ld   bc,100        ;carrega BC com 100 e ao mesmo tempo zera o registrador B
    call Print_Number

Ten:
    ld   c,10          ;BC = 10 (B zerado anteriormente)
    call Print_Number

Unit:
    ld   c,1           ;BC = 1

Print_Number:
    ld   a,$1C         ;valor CHR$ do algarismo 0
    and  a             ;reseta Carry
    sbc  hl,bc
    jr   c,$+5         ;salta para ADD HL,BC
    inc  a
    jr   $-5           ;salta para SBC HL,BC
    add  hl,bc
    ld   (de),a        ;imprime o numero na tela
    inc  de
    ret


;==================  L E I T U R A   D O   T E C L A D O  ====================

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Rotina de leitura de teclas e auto-repeticao - Versao 5.5 (66 bytes).
;
; Observacao: Registrador de retorno da tecla pressionada mudado de D para C.
; ==========
;
; Entrada:
;   Nada.
; Retorno:
;   C = Codigo CHR$ da tecla pressionada. $7F para nenhuma.
;   Destroi todos os demais registradores.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Get_Key: 
    ld   bc,(4025h)       ;obtem o status do teclado (LAST_K)
    ld   a,c
    add  a,1              ;alguma tecla pressionada? (INC A nao seta o Carry)
    jr   c,None_Key       ;nao


;Obtem o valor CHR$ da tecla atualmente pressionada e compara com a ultima

    call 07BDh            ;obtem o valor CHR$ da tecla
    ld   c,(HL)           ;copia para C
    ld   a,(4021h)        ;obtem a ultima tecla
    cp   c                ;compara com a tecla atual
    jr   nz,Different_Key
    ld   de,4034h         ;FRAMES (usado nas temporizacoes)
    ld   hl,403Bh
    bit  1,(hl)           ;repeticao da tecla esta' ativada?
    jr   z,Delay          ;nao


;Repeticao da tecla (10 caracteres/s)

    ld   a,(de)           ;FRAMES
    cp   0FAh             ;delay da taxa de repeticao (255 - 6 + 1)
    jr   nc,None_Key      ;retorna nada no intervalo entre duas repeticoes

Repeat_Key:
    ld   a,(4028h)        ;MARGIN
    add  a,0E0h           ;seta carry se sistema = 50Hz
    sbc  a,a
    dec  a                ;A=254 se 50Hz ou 255 se 60Hz
    ld   (de),a           ;reseta o delay da taxa de repeticao
    set  1,(hl)           ;habilita a repeticao da tecla
    ret                   ;retorna com o codigo da tecla pressionada, em C


;Delay aproximado de 1 segundo antes de comecar a repetir a tecla

Delay:
    ld   a,(de)           ;FRAMES
    cp   0C9h             ;delay (media entre 50/60 Hz)
    jr   c,Repeat_Key


;Nenhuma tecla pressionada

None_Key:
    ld   c,$7F            ;retornando nada
    ret  nc               ;retorno usado pelo trechos de repeticao 


;Tecla e' diferente da ultima ou nenhuma tecla pressionada

Different_Key:
    ld   hl,4034h
    ld   (hl),0FFh        ;reseta o delay de 1 segundo
    ld   l,3Bh
    res  1,(hl)           ;desabilita a repeticao de tecla
    ld   l,21h
    ld   (hl),c           ;salva a tecla pressionada
    ret                   ;retorna com o codigo da tecla pressionada, em C


;=====================  N O M E S   D O S   M E S E S  =======================

;Matriz com os nomes dos meses (9 bytes por nome)
;Exceto para Fevereiro, todos os nomes terminam com espaco

Month_Name:
    db   $2F,$26,$33,$2A,$2E,$37,$34,$00,$00  ;Janeiro
    db   $2B,$2A,$3B,$2A,$37,$2A,$2E,$37,$34  ;Fevereiro
    db   $32,$26,$37,$28,$34,$00,$00,$00,$00  ;Marco
    db   $26,$27,$37,$2E,$31,$00,$00,$00,$00  ;Abril
    db   $32,$26,$2E,$34,$00,$00,$00,$00,$00  ;Maio
    db   $2F,$3A,$33,$2D,$34,$00,$00,$00,$00  ;Junho
    db   $2F,$3A,$31,$2D,$34,$00,$00,$00,$00  ;Julho
    db   $26,$2C,$34,$38,$39,$34,$00,$00,$00  ;Agosto
    db   $38,$2A,$39,$2A,$32,$27,$37,$34,$00  ;Setembro
    db   $34,$3A,$39,$3A,$27,$37,$34,$00,$00  ;Outubro
    db   $33,$34,$3B,$2A,$32,$27,$37,$34,$00  ;Novembro
    db   $29,$2A,$3F,$2A,$32,$27,$37,$34,$00  ;Dezembro
