Bom, então vamos lá!
Uma outra utilidade para o Zoom Out é reduzir o tamanho do filme para compensar uma baixa resolução. Eu às vezes prefiro assistir a um filme em tamanho menor do que ver aqueles borrados gigantes.
Os valores não podem ser modificados de forma precisa, pelo menos não no 8032. Talvez só diretamente no ARM, mas aí teríamos que descobrir as rotinas que realizam o redimensionamento. O nível de zoom depende de valores inteiros absolutos repassados a uma rotina que compartilha dados com o ARM (semelhante a ARM_PutChar). Muito provavelmente deve haver uma tabela no ARM (ou pelo menos uma sequência de CMPs) que aplica redimensionamentos diferentes para cada valor repassado. Eu testei valores diferentes e medi (sim, com uma régua mesmo) a variação na tela. Se algo era mostrado com 10cm de comprimento, passou a ter 9,6cm após aplicada a primeira escala modificada, portanto, com 96% do tamanho original. Não se trata do valor da redução e sim do resultado final, como acontece nos softwares gráficos. Por sinal, os 200%, 300% e 400% parecem estar errados. Em 200%, a meu ver, deveria ser dobrado tudo que tenha uma dimensão. Acho que já vi algum texto do
Ryan falando sobre isso.
A área, então, quadriplicaria. Mas, pelo que medi, é a área que quase dobra. Os comprimentos aumentam só 1,4 vezes, aproximadamente. Fiquei com vontade de corrigir esses valores, mas deixei esse "bug" pra lá.
Implementação do Zoom Out
PARTE 1:O sistema é relativamente simples:
Existe uma posição de memória que guarda o índice usado para selecionar o zoom, que no caso do DV397H com chip M é #FE06.
Existe uma rotina que aplica o zoom, enviando um determinado valor ao ARM, de acordo com o índice em #FE06.
Há a rotina que eu já relatei num post anterior, que exibe o valor de zoom na tela, conforme o índice em #FE06 (foi a que eu alterei para diminuir o tempo de exibição da informação de zoom).
Há a rotina que eu também já relatei anteriormente, que faz algumas atualizações no índice em #FE06, chama essas duas últimas rotinas e desabilita (desabilitava) a legenda DivX.
Além disso, existem as rotinas chamadas pela RC_Table que atualizam o índice em #FE06 e chamam as demais quando apertamos a tecla zoom e também as que executam o scan quando pressionamos as setas em modo zoom.
Antes de mostrar a rotina que aplica o zoom, vou explicar como funciona a atualização do índice, o que também explica a escolha da nova quantidade de escalas de zoom. Inicialmente, temos a seguinte correspondência entre o índice em #FE06 e o zoom:
#10 -> 100%
#11 -> 200%
#12 -> 300%
#13 -> 400%
Porém, o valor não é normalmente incrementando e, caso atinja 14, volte a 0, como estamos acostumados. As rotinas, de um modo geral, realizam um AND #3 com o valor. Ao realizarmos a função lógica AND #3 com qualquer valor hexadecimal, só podemos ter 4 resultados: 0, 1, 2 ou 3. A atualização do índice se faz da seguinte forma: incremente o índice e faça um AND #3. Assim, mesmo que se incremente de forma indefinida o valor do índice, temos sempre a sequência 0, 1, 2, 3, 0, 1, 2, 3, 0,... porque o AND #3 funciona como um limitante (funciona como módulo 3, em álgebra). E as rotinas irão aplicar / mostrar o zoom, seguindo a tabela:
#10 -> AND #3 -> #0 -> 100%
#11 -> AND #3 -> #1 -> 200%
#12 -> AND #3 -> #2 -> 300%
#13 -> AND #3 -> #3 -> 400%
#14 -> AND #3 -> #0 -> 100%
#15 -> AND #3 -> #1 -> 200%
#16 -> AND #3 -> #2 -> 300%
#17 -> AND #3 -> #3 -> 400%
.................
.................
Algumas vezes, porém, o índice é guardado após o AND #3. E além disso, para "zerar", quando necessário, faz-se um AND #FC (#FC é o inverso de #3, em binário). Assim, nem sempre o índice cresce indefinidamente.
Essa característica limitante do AND existe para todos os números na forma (2^n - 1), em que n é o número de bits setados à direita. Com 2 bits setados, temos 2^2-1 = 3. Com 3 bits setados, teremos 2^3 -1 = 7. Portanto, uma forma fácil de aumentar a quantidade de tipos de zoom, sem ter que alterar a estrutura das rotinas (o que demandaria também mais espaço para o código), é alterar o AND #3 para AND #7 (e o AND #FC para AND #F8, já que o inverso de #B00000111 = #B11111000) e passamos a ter a seguinte tabela:
#10 -> AND #7 -> #0 -> 100%
#11 -> AND #7 -> #1 -> 200%
#12 -> AND #7 -> #2 -> 300%
#13 -> AND #7 -> #3 -> 400%
#14 -> AND #7 -> #4 -> vago
#15 -> AND #7 -> #5 -> vago
#16 -> AND #7 -> #6 -> vago
#17 -> AND #7 -> #7 -> vago
#18 -> AND #7 -> #0 -> 100%
#19 -> AND #7 -> #1 -> 200%
.................
.................
Portanto, ao fazer isso, passei a ter mais 4 opções para o zoom. Como estava pensando em apenas mais 2 opções (algo em torno de 90% e algo em torno de 80%), tive que usar mais 2 opções para outros valores.
A rotina que aplica o zoom é a seguinte:
B3:D95E ; =============== S U B R O U T I N E =======================================
B3:D95E
B3:D95E ; aplica zoom
B3:D95E
B3:D95E B3_D95E: ; CODE XREF: B3:B3_1547_p
B3:D95E ; BankSw_243_B3_AD73:B3_AE72_p
B3:D95E 90 FE 06 mov DPTR, #XRAM_FE06
B3:D961 E0 movx A, @DPTR
B3:D962 54 03 anl A, #3 ; alterar para anl A, #7
B3:D964 14 dec A
B3:D965 60 1E jz B3_D985 ; se 0, após o dec, eh porque era #1 apos o AND
B3:D967 14 dec A
B3:D968 60 3A jz B3_D9A4 ; se 0, após 2 decs, eh porque era #2 apos o AND
B3:D96A 14 dec A
B3:D96B 60 56 jz B3_D9C3 ; se 0, após 3 decs, eh porque era #3 apos o AND
B3:D96D 24 03 add A, #3 ; inserir jump para processar novos valores (#4, #5, #6 e #7)
B3:D96F 70 71 jnz B3_D9E2
B3:D971 90 FE 07 mov DPTR, #XRAM_FE07 ; inicio zoom 100%
B3:D974 74 07 mov A, #7
B3:D976 F0 movx @DPTR, A
B3:D977 A3 inc DPTR
B3:D978 F0 movx @DPTR, A
B3:D979 E4 clr A ; aplicar zoom 100%
B3:D97A 90 FB EA mov DPTR, #XRAM_FBEA
B3:D97D F0 movx @DPTR, A
B3:D97E FB mov R3, A
B3:D97F FD mov R5, A ; valor #0 em R5 = corresponde a 100%
B3:D980 7F 2E mov R7, #0x2E ; '.'
B3:D982 02 06 01 ljmp B3_BS_132_B2_FB93 ; enviar para o ARM
B3:D985 ; ---------------------------------------------------------------------------
B3:D985
B3:D985 B3_D985: ; CODE XREF: B3_D95E+7_j
B3:D985 7D 03 mov R5, #3 ; inicio zoom 200%
B3:D987 7F 2C mov R7, #0x2C ; ','
B3:D989 7E 07 mov R6, #7
B3:D98B 12 03 A9 lcall B3_BS_32_B4_F36A
B3:D98E 7D 03 mov R5, #3
B3:D990 7F 2B mov R7, #0x2B ; '+'
B3:D992 7E 07 mov R6, #7
B3:D994 12 03 A9 lcall B3_BS_32_B4_F36A
B3:D997 E4 clr A ; aplicar zoom 200%
B3:D998 90 FB EA mov DPTR, #XRAM_FBEA
B3:D99B F0 movx @DPTR, A
B3:D99C FB mov R3, A
B3:D99D 7D 04 mov R5, #4 ; valor #4 em R5 = corresponde a 200%
B3:D99F 7F 2E mov R7, #0x2E ; '.'
B3:D9A1 02 06 01 ljmp B3_BS_132_B2_FB93 ; enviar para o ARM
B3:D9A4 ; ---------------------------------------------------------------------------
B3:D9A4
B3:D9A4 B3_D9A4: ; CODE XREF: B3_D95E+A_j
B3:D9A4 7D 04 mov R5, #4 ; inicio zoom 300%
B3:D9A6 7F 2C mov R7, #0x2C ; ','
B3:D9A8 7E 07 mov R6, #7
B3:D9AA 12 03 A9 lcall B3_BS_32_B4_F36A
B3:D9AD 7D 04 mov R5, #4
B3:D9AF 7F 2B mov R7, #0x2B ; '+'
B3:D9B1 7E 07 mov R6, #7
B3:D9B3 12 03 A9 lcall B3_BS_32_B4_F36A
B3:D9B6 E4 clr A ; aplicar zoom 300%
B3:D9B7 90 FB EA mov DPTR, #XRAM_FBEA
B3:D9BA F0 movx @DPTR, A
B3:D9BB FB mov R3, A
B3:D9BC 7D 06 mov R5, #6 ; valor #6 em R5 = corresponde a 300%
B3:D9BE 7F 2E mov R7, #0x2E ; '.'
B3:D9C0 02 06 01 ljmp B3_BS_132_B2_FB93 ; enviar para o ARM
B3:D9C3 ; ---------------------------------------------------------------------------
B3:D9C3
B3:D9C3 B3_D9C3: ; CODE XREF: B3_D95E+D_j
B3:D9C3 7D 05 mov R5, #5 ; inicio zoom 400%
B3:D9C5 7F 2C mov R7, #0x2C ; ','
B3:D9C7 7E 07 mov R6, #7
B3:D9C9 12 03 A9 lcall B3_BS_32_B4_F36A
B3:D9CC 7D 05 mov R5, #5
B3:D9CE 7F 2B mov R7, #0x2B ; '+'
B3:D9D0 7E 07 mov R6, #7
B3:D9D2 12 03 A9 lcall B3_BS_32_B4_F36A
B3:D9D5 E4 clr A ; aplicar zoom 400%
B3:D9D6 90 FB EA mov DPTR, #XRAM_FBEA
B3:D9D9 F0 movx @DPTR, A
B3:D9DA FB mov R3, A
B3:D9DB 7D 08 mov R5, #8 ; valor #8 em R5 = corresponde a 400%
B3:D9DD 7F 2E mov R7, #0x2E ; '.'
B3:D9DF 12 06 01 lcall B3_BS_132_B2_FB93
B3:D9E2
B3:D9E2 B3_D9E2: ; CODE XREF: B3_D95E+11_j
B3:D9E2 22 ret
B3:D9E2 ; End of function B3_D95E
Vemos que no início de cada segmento que aplica um zoom, com excessão do de 100%, temos 2 ARM_PutChar que não identifiquei o motivo. Nos testes, alterei os valores, eliminei esses trechos, e não fez qualquer diferença em nada. Mas o local que realmente define o nível de zoom está no final de cada segmento. Por exemplo, no caso do zoom de 200%:
B3:D997 E4 clr A ; aplicar zoom 200%
B3:D998 90 FB EA mov DPTR, #XRAM_FBEA
B3:D99B F0 movx @DPTR, A
B3:D99C FB mov R3, A
B3:D99D 7D 04 mov R5, #4 ; valor #4 em R5 = corresponde a 200%
B3:D99F 7F 2E mov R7, #0x2E ; '.'
B3:D9A1 02 06 01 ljmp B3_BS_132_B2_FB93 ; enviar para o ARM
Então fiz testes alterando o valor de R5 nesse trecho. Já tínhamos 0 para 100%, 4 para 200%, 6 para 300% e 8 para 400%. Testei 1, 2 e 3, e não fizeram nada em DivX. Posteriormente, ao testar com DVD, eles deram um pequeno aumento de zoom. Não medi, mas diria algo em torno de 110%, 120% e 130%. Os valores 5 e 7 também não fizeram nada em DivX e não testei em DVD. O valor #9 gera o zoom gigante, os horríveis 1600% (que, após medição, revelaram-se 800%), em todos os tipos de arquivos. Ao testar o valor #0A, vi que a tela ficou um pouquinho menor em DivX. Medi 96%. Em DVD e foto, não faz diferença. #0B dá 71% para DivX e DVD/VCD, mas nada para imagens. Já #0C, dá 57%. Ainda tem o #0D, que deu em torno de 45%, eu acho.
A minha escolha foi então deixar 1600% (mas corrigido para 800%), 96%, 71% e 57%. A razão do zoom gigante era apenas para os arquivos de foto, os únicos em que aquele zoom pode ter alguma utilidade. Mas tive 2 problemas com os 800% de zoom. O primeiro é que, como 96% não funciona em DVDs nem em fotos (e os demais só em vídeos), quando o usuário selecionasse 96%, ficaria com a tela ainda em 800% do zoom anterior, o que pareceria um bug horrível. O outro problema é que todo zoom in abre a função scan para que possamos navegar pela imagem com as setas. Na rotina que eu apresentarei a seguir, eu identifiquei o trecho que desenha o retângulo de scan, que diminui de tamanho de acordo com o zoom, mas ia dar um trabalho a mais para determinar os valores exatos da largura e da altura do retângulo, bem como os valores máximos e mínimos do deslocamento. Então deixei 100% repetido como quarta opção (o que deixou um aspecto bem legal, dando a ideia de que o zoom out simplesmente não funciona quando for o caso), seguido de 96%, 71% e 57%. Outra coisa interessante é que quando você deixa no segundo 100% e o ícone de zoom some, ao apertar zoom novamente, volta-se ao primeiro 100%, fazendo com que tenha que se percorrer a sequencia novamente (isso, obviamente, não ocorre quando deixamos nas opções de zoom out).