Olá zeurt,
Ainda não tive tempo de explicar como foram feitas as últimas modificações. Na verdade, explicar é mais complicado do que descobrir e fazer . Mas eu tive uma idéia (ou ideia, ainda não me acostumei com o acordo ortográfico). Vou disponibilizar meu arquivo idb do IDA com a identificação e os comentários de todas as modificações. Acho que é a melhor coisa!
Novamente obrigado por compartilhar tudo isso! Vou aproveitar bastante o arquivo idb do IDA quando você disponibilizá-lo.
Tenho algumas perguntas, curiosidades:
1- Como você identificou os endereços EEPROM livres (e se certificou de que eles não interfeririam em nenhuma outra função)?
2- Você conseguiu remover a fonte 6 ou 7 (que eram iguais)? Se sim, como?
3- Acho que as descobertas sobre os menus ocultos você irá incluir no arquivo do IDA, não é?
1- Para identificar os endereços EEPROM, acho que o mais correto seria usar o MTKTool para ler um determinado endereço online, criando um log enquanto você faz as mais diversas operações no player. Mas o meu MTKTool não consegue ler os endereços EEPROM, não sei se é bug no programa ou incompatibilidade com o chip (ou se não sei usar direito). Então eu primeiro dei uma olhada no menu, para ver os endereços usados ali e depois eu fiz uma busca no 8032, procurando as sequências 7F XX 7E 00 12 (endereço do PrefGet) e 7E 00 7F XX 12 (endereço do PrefGet). Não tendo nenhuma delas, já é uma boa chance de não ser usado (99%), pois ainda tem o ARM. O 1% restante é na sorte mesmo! Mas os testes ajudam na confirmação final.
2- Ainda não removi a fonte repetida. Fiz uma pequena busca infrutífera e deixei para depois.
3- Sim, vou colocar. Mas posso resumir alguma coisa. Todas as rotinas que trabalham o menu estão no banco 2 (no DV397H). São várias rotinas. Tem a que desenha e atualiza o menu geral quando você navega por ele, a que desenha e atualiza o menu quando você entra em um submenu (entra pela direita) e outra quando você sai (esquerda). Há a rotina que desenha o menu quando você navega pelos submenus, a que desenha o menu quando você entra nas opções (direita) etc. Enfim, se você destrava um submenu, tem que fazer em todas as rotinas, pois, caso contrário, ele voltará a ficar travado dependendo do que estiver fazendo.
Antes de irmos para as subrotinas, devo dizer que tudo que descobri foi graças a três endereços de memória importantíssimos (no DV397H). #FD87, que guarda o número do menu corrente selecionado (de 0 até 4), #FD88, que guarda o número do submenu (também começa em 0) e #FD8B, que guarda o número da opção em que o cursor está (começa em 0 também). Então, para descobrir como os submenus do menu Display ficavam travados, procurei algo que fosse simultanemente condicional a #FD87=#1 (segundo menu, que é o Display) e a #FD88=#2 (terceiro submenu, que está travado). Vamos às rotinas. Vou colocar apenas o endereço inicial delas. Aí fica fácil de procurar no IDA e comparar as modificações que eu fiz com o firmware original:
* Aplica (chama) opções dos submenus: B2_13E4.
* Desenha opções dos submenus, quando você navega por eles: B2_3722.Nessa rotina, por exemplo, há o trecho:
B2:39EB 90 FD 87 mov DPTR, #XRAM_FD87
B2:39EE E0 movx A, @DPTR
B2:39EF B4 01 2A cjne A, #1, B2_3A1C ; desloca opcoes,
B2:39EF ; apos submenu 3,
B2:39EF ; menu 1
B2:39F2 90 FB D6 mov DPTR, #XRAM_FBD6
B2:39F5 E0 movx A, @DPTR
B2:39F6 FF mov R7, A
B2:39F7 C3 clr C
B2:39F8 94 03 subb A, #3
B2:39FA 40 20 jc B2_3A1C
Esse trecho checa se estamos no menu 1 (Display) para depois deslocar a posição das opções a partir da terceira (3) posição. Isso faz com que mesmo que se destrave os submenus após a segunda posição, suas opções sejam mostradas como se você estivesse dois submenus abaixo.
* Desenha menu durante navegação principal: B2:4378.Nesse trecho, os comentários falam por si:
B2:43FB EF mov A, R7
B2:43FC B4 01 08 cjne A, #1, B2_4407 ; analisa menu 1
B2:43FF ED mov A, R5
B2:4400 64 02 xrl A, #2 ; corta submenu 2 do menu 1
B2:4402 70 03 jnz B2_4407
B2:4404 02 48 FC ljmp B2_48FC
B2:4407 ; ---------------------------------------------------------------------------
B2:4407
B2:4407 B2_4407: ; CODE XREF: B2_4378+84_j
B2:4407 ; B2_4378+8A_j
B2:4407 EF mov A, R7
B2:4408 64 01 xrl A, #1 ; analisa menu 1
B2:440A 70 2E jnz B2_443A
B2:440C ED mov A, R5
B2:440D 64 03 xrl A, #3 ; corta submenu 3 do menu 1
B2:440F 70 29 jnz B2_443A
Outros trechos:
B2:44F8 90 FD 87 mov DPTR, #XRAM_FD87
B2:44FB E0 movx A, @DPTR
B2:44FC B4 01 23 cjne A, #1, B2_4522
B2:44FF 90 FB D6 mov DPTR, #XRAM_FBD6
B2:4502 E0 movx A, @DPTR
B2:4503 B4 03 1C cjne A, #3, B2_4522 ; cor cinza submenu 3, menu 1
B2:4F33 90 FD 87 mov DPTR, #0xFD87
B2:4F36 E0 movx A, @DPTR
B2:4F37 B4 01 28 cjne A, #1, B2_4F62 ; salta submenu 3, menu 1
B2:4839 90 FD 87 mov DPTR, #0xFD87
B2:483C E0 movx A, @DPTR
B2:483D B4 01 23 cjne A, #1, B2_4863
B2:4840 90 FB D6 mov DPTR, #XRAM_FBD6
B2:4843 E0 movx A, @DPTR
B2:4844 B4 03 1C cjne A, #3, B2_4863 ; cor cinza opcao do submenu 3, menu 1
B2:4847 7F 47 mov R7, #0x47 ; '
* Navega submenus: B2:53C0.B2:548A 20 E0 0E jb ACC.0, B2_549B ; menu 1, submenu 1 dependente?
B2:548D 90 FD 87 mov DPTR, #XRAM_FD87
B2:5490 E0 movx A, @DPTR
B2:5491 B4 01 07 cjne A, #1, B2_549B ; navegacao menu 1 baixo
B2:5494 A3 inc DPTR
B2:5495 E0 movx A, @DPTR
B2:5496 70 03 jnz B2_549B
B2:5498 E0 movx A, @DPTR
B2:5499 04 inc A ; pula submenu 1 dependente
* Desenha menu ao entrar pela direita: B2:5840.B2:58ED B2_58ED: ; CODE XREF: B2_5840+A8_j
B2:58ED EF mov A, R7
B2:58EE B4 01 08 cjne A, #1, B2_58F9 ; analisa menu 1
B2:58F1 ED mov A, R5
B2:58F2 64 02 xrl A, #2 ; corta submenu 2 do menu 1
B2:58F4 70 03 jnz B2_58F9
B2:58F6 02 5C 77 ljmp B2_5C77
* Navega opções dos submenus: B2:76A6.
* Desenha menu após aplicar opções: B2:948C.
* Navegacao cima/baixo menu principal: B2:C9B0.Além disso, havia o problema do submenu VoD DivX. As rotinas tratam esse submenu de forma fixa. Seja o que for que estiver selecionado na posição 3 do quinto menu terá como opção a palavra "Select" e, ao ser pressionado Enter, será chamada a tela do VoD DivX. Não seria problema nenhum deixá-lo na posição 3 e continuar adicionando submenus abaixo dele, mas a idéia de jogá-lo para o fim (oitavo submenu) é boa (exatamente o que Br0max e Xypro fizeram), pois o mesmo só tem uma opção, fazendo com que a sua caixa de opções não invada o borda do menu. Do contrário, deixando, por exemplo, o submenu PBC por último, a opção Off (segunda opção) não cabe na tela, invadindo a borda inferior do menu. Então, para que coubesse oito submenus no menu Outros, tive que mudar o submenu Vod DivX para o oitavo lugar. Além de mudar a estrutura de menus, foi necessário alterar o byte #2 (posição 3) para #7 (posição 8 ) nos seguintes pontos:
B2:17A2 B4 02 1B cjne A, #2, B2_17C0 ; DivX VOD 1
............
B2:3D3E B4 02 27 cjne A, #2, B2_3D68 ; DivX VOD 2
............
B2:469F 64 02 xrl A, #2 ; DivX VOD 3
............
B2:4714 64 02 xrl A, #2 ; DivX VOD 4
Muito legal que você esteja trabalhando nessa implementação (TEMPO RESTANTE/TOTAL). Para mim, essa seria realmente a próxima prioridade...
Tudo que você descobriu até agora em relação a isso, para mim é novidade. Vou tentar ir assimilando aos poucos para tentar depois implementar no DV256K. Falando nisso, qual é o trecho do 8032 do xypro 5.1 que contêm essa implementação? Gostaria de complementar dizendo que, se foi feita alguma modificação no ARM do xypro 5.1, foi muito pequena, pois comparando o ARM do xypro 5.1 com o ARM do br0max 4 (ambos se baseiam no mesmo ARM original), existem apenas 117 bytes diferentes. Inclusive você pode até dar uma olhadinha nesse bytes pra ver se tem algo que interessa...
Também tentei descobrir como se seleciona o tempo restante no xypro 5.1, lendo os tópicos relacionados nos fóruns, porém também não vi nehuma referência a isso. Para mim, o ideal seria: pressionar DISPLAY, ir até a linha onde é exibido o TEMPO CORRENTE, e com as setas laterais (ou apenas a seta da direita), alternar entre TEMPO CORRENTE, TEMPO RESTANTE, TEMPO TOTAL (opcional) e função GOTO. Ou seja, se alternaria entre esses itens da mesma forma que se pode alternar as legendas e as trilhas de áudio (inclusive, os itens do menu DISPLAY que podem ser selecionados dessa maneira apresentam um seta para esquerda no início e uma seta para direita no fim, indicando essa possibildade de alternancia).
Espero que de tudo certo!
Acho que você está certo. Deve ter sido assim que ele fez mesmo. Mas é meio complicado de entender. Então eu passei logo a analisar as rotinas que ele modificou e cheguei às minhas descobertas. A primeira coisa que vi foi a diferença na seguinte rotina (firmware Xypro 5.1):
; mostra tempo?
B4_A274:
; FUNCTION CHUNK AT B4:FFA0 SIZE 0000002C BYTES
mov DPTR, #XRAM_FBC3
mov A, R6
movx @DPTR, A
inc DPTR
mov A, R7
movx @DPTR, A
Ao procurar por rotinas parecidas com essa (procure por EF 24 30 90 ? ? F0 80 06 90 ? ? 74 2D), achamos 4. Duas no banco 1 e 2 no banco 4 (Xypro 5.1) ou no banco 3 (DV397H). 1 eu já descobri que é responsável por exibir o tempo de DVD (está no banco 1) e a outra exibe o tempo de DivX (banco 3, no caso do DV397H). Para descobrir o que cada uma faz, teste colocando um 22 (ret) no início da rotina. Isso "desliga" a função. Foi assim que eu descobri que a rotina B3_9F60 (mostra tempo) é responsável pela exibição do tempo de um DivX no DV397H. Seguindo as chamadas desta, e também quem a chama, descobri as seguintes rotinas ou trechos de rotinas:
Tratamento inicial antes de chamar "mostra tempo": B3:9F49.
Mostra tempo quando aperta display: B3:3A50.
Atualiza tempo: B3:BA70.
Aplica tempo função go to: B3:A6A8.
E analisando mais, vi que dando um Arm_GetChar com 7F 60 7E 02, temos o valor das horas em BCD, com 7F 61 7E 02, o valor dos minutos e com 7F 62 7E 02, o valor dos segundos. Já 0270, 0271 e 0272 nos dão o tempo total, formato H M S como no caso anterior (acabei de descobrir que para o modo DVD, esse é o tempo total do capítulo, não do filme inteiro; para o filme inteiro, os endereços são 0274, 0275 e 0276).
Vejamos a seguinte rotina, chamada pela que processa o função go to. Ela analisa se o tempo digitado é válido, ou seja, se segundos ou minutos não são maiores que 59 e nem se o tempo digitado é maior que o tempo total do DivX. Note que antes de fazer comparações, os valores de tempo são transformados em binário pela função BCD2BIN (B5_D726):
B1:CCBC ; tempo digitado
B1:CCBC ; funcao go to
B1:CCBC ; restringe valores
B1:CCBC
B1:CCBC BankSw_480_B1_CCBC: ; CODE XREF: B1_416B+10B_p
B1:CCBC ; DATA XREF: B0:B0_BS_480_B1_CCBC_o ...
B1:CCBC 90 FB D6 mov DPTR, #XRAM_FBD6
B1:CCBF EF mov A, R7
B1:CCC0 F0 movx @DPTR, A
B1:CCC1 A3 inc DPTR
B1:CCC2 ED mov A, R5
B1:CCC3 F0 movx @DPTR, A
B1:CCC4 A3 inc DPTR
B1:CCC5 EB mov A, R3
B1:CCC6 F0 movx @DPTR, A
B1:CCC7 90 FB D7 mov DPTR, #XRAM_FBD7
B1:CCCA E0 movx A, @DPTR
B1:CCCB D3 setb C
B1:CCCC 94 3B subb A, #0x3B ; ';' ; maior que 59
B1:CCCE 40 01 jc B1_CCD1
B1:CCD0 22 ret
B1:CCD1 ; ---------------------------------------------------------------------------
B1:CCD1
B1:CCD1 B1_CCD1: ; CODE XREF: BankSw_480_B1_CCBC+12_j
B1:CCD1 90 FB D8 mov DPTR, #XRAM_FBD8
B1:CCD4 E0 movx A, @DPTR
B1:CCD5 D3 setb C
B1:CCD6 94 3B subb A, #0x3B ; ';' ; maior que 59
B1:CCD8 40 01 jc B1_CCDB
B1:CCDA 22 ret
B1:CCDB ; ---------------------------------------------------------------------------
B1:CCDB
B1:CCDB B1_CCDB: ; CODE XREF: BankSw_480_B1_CCBC+1C_j
B1:CCDB 90 FC 5A mov DPTR, #XRAM_FC5A
B1:CCDE E0 movx A, @DPTR
B1:CCDF B4 02 19 cjne A, #2, B1_CCFB
B1:CCE2 90 FB D6 mov DPTR, #XRAM_FBD6
B1:CCE5 E0 movx A, @DPTR
B1:CCE6 FF mov R7, A
B1:CCE7 D3 setb C
B1:CCE8 94 01 subb A, #1
B1:CCEA 40 01 jc B1_CCED
B1:CCEC 22 ret
B1:CCED ; ---------------------------------------------------------------------------
B1:CCED
B1:CCED B1_CCED: ; CODE XREF: BankSw_480_B1_CCBC+2E_j
B1:CCED EF mov A, R7
B1:CCEE 64 01 xrl A, #1
B1:CCF0 70 2D jnz B1_CD1F
B1:CCF2 90 FB D7 mov DPTR, #XRAM_FBD7
B1:CCF5 E0 movx A, @DPTR
B1:CCF6 24 3C add A, #0x3C ; '<'
B1:CCF8 F0 movx @DPTR, A
B1:CCF9 80 24 sjmp B1_CD1F
B1:CCFB ; ---------------------------------------------------------------------------
B1:CCFB
B1:CCFB B1_CCFB: ; CODE XREF: BankSw_480_B1_CCBC+23_j
B1:CCFB 7F 70 mov R7, #0x70 ; 'p' ; tempo total, H
B1:CCFD 7E 02 mov R6, #2
B1:CCFF 12 03 A3 lcall B1_BS_31_B4_F1E6
B1:CD02 12 04 F3 lcall B1_BS_87_B5_D726
B1:CD05 90 FB D9 mov DPTR, #XRAM_FBD9
B1:CD08 EF mov A, R7
B1:CD09 F0 movx @DPTR, A
B1:CD0A 90 FB D6 mov DPTR, #XRAM_FBD6
B1:CD0D E0 movx A, @DPTR
B1:CD0E FE mov R6, A
B1:CD0F D3 setb C
B1:CD10 9F subb A, R7
B1:CD11 40 01 jc B1_CD14
B1:CD13 22 ret
B1:CD14 ; ---------------------------------------------------------------------------
B1:CD14
B1:CD14 B1_CD14: ; CODE XREF: BankSw_480_B1_CCBC+55_j
B1:CD14 90 FB D9 mov DPTR, #XRAM_FBD9
B1:CD17 E0 movx A, @DPTR
B1:CD18 FF mov R7, A
B1:CD19 EE mov A, R6
B1:CD1A C3 clr C
B1:CD1B 9F subb A, R7
B1:CD1C 50 01 jnc B1_CD1F
B1:CD1E 22 ret
B1:CD1F ; ---------------------------------------------------------------------------
B1:CD1F
B1:CD1F B1_CD1F: ; CODE XREF: BankSw_480_B1_CCBC+34_j
B1:CD1F ; BankSw_480_B1_CCBC+3D_j ...
B1:CD1F 7F 71 mov R7, #0x71 ; 'q' ; tempo total, M
B1:CD21 7E 02 mov R6, #2
B1:CD23 12 03 A3 lcall B1_BS_31_B4_F1E6
B1:CD26 12 04 F3 lcall B1_BS_87_B5_D726
B1:CD29 90 FB D9 mov DPTR, #XRAM_FBD9
B1:CD2C EF mov A, R7
B1:CD2D F0 movx @DPTR, A
B1:CD2E 90 FB D7 mov DPTR, #XRAM_FBD7
B1:CD31 E0 movx A, @DPTR
B1:CD32 FE mov R6, A
B1:CD33 D3 setb C
B1:CD34 9F subb A, R7
B1:CD35 40 01 jc B1_CD38
B1:CD37 22 ret
B1:CD38 ; ---------------------------------------------------------------------------
B1:CD38
B1:CD38 B1_CD38: ; CODE XREF: BankSw_480_B1_CCBC+79_j
B1:CD38 90 FB D9 mov DPTR, #XRAM_FBD9
B1:CD3B E0 movx A, @DPTR
B1:CD3C FF mov R7, A
B1:CD3D EE mov A, R6
B1:CD3E C3 clr C
B1:CD3F 9F subb A, R7
B1:CD40 50 01 jnc B1_CD43
B1:CD42 22 ret
B1:CD43 ; ---------------------------------------------------------------------------
B1:CD43
B1:CD43 B1_CD43: ; CODE XREF: BankSw_480_B1_CCBC+84_j
B1:CD43 7F 72 mov R7, #0x72 ; 'r' ; tempo total, S
B1:CD45 7E 02 mov R6, #2
B1:CD47 12 03 A3 lcall B1_BS_31_B4_F1E6
B1:CD4A 12 04 F3 lcall B1_BS_87_B5_D726
B1:CD4D 90 FB D9 mov DPTR, #XRAM_FBD9
B1:CD50 EF mov A, R7
B1:CD51 F0 movx @DPTR, A
B1:CD52 90 FB D8 mov DPTR, #XRAM_FBD8
B1:CD55 E0 movx A, @DPTR
B1:CD56 D3 setb C
B1:CD57 9F subb A, R7
B1:CD58 40 01 jc B1_CD5B
B1:CD5A 22 ret
B1:CD5B ; ---------------------------------------------------------------------------
B1:CD5B
B1:CD5B B1_CD5B: ; CODE XREF: BankSw_480_B1_CCBC+9C_j
B1:CD5B D3 setb C
B1:CD5C 22 ret
Se não conseguir implementar a mudança usando a navegação na função go to, vou ao menos deixar a opção no Setup, pois já será de grande ajuda. Será possível o usuário ver no painel frontal o tempo progressivo e no OSD deixar o tempo restante.
Já que estou empolgado agora, vou escrever um pouco mais.
A mudança no Screensaver foi a mais simples. Eu copiei a modificação feita pelo Xypro. O Xypro usa o endereço 75 da EEPROM. Então, procurando por 7F 75 7E 00 12 achei a função:
B2:F2A0 B2_F2A0: ; CODE XREF: B2_CB61+18_j
B2:F2A0 7F 75 mov R7, #0x75 ; 'u'
B2:F2A2 7E 00 mov R6, #0
B2:F2A4 12 09 49 lcall B2_BS_272_B1_CF1E
B2:F2A7 EF mov A, R7
B2:F2A8 70 06 jnz B2_F2B0
B2:F2AA 90 FC 43 mov DPTR, #0xFC43
B2:F2AD 02 CB 7C ljmp B2_CB7C
B2:F2B0 ; ---------------------------------------------------------------------------
B2:F2B0
B2:F2B0 B2_F2B0: ; CODE XREF: B2_CB61+2747_j
B2:F2B0 C3 clr C
B2:F2B1 22 ret
Mudando para visão gráfica, vemos que não passa de um gancho da rotina B2_CB61, que é a rotina do Screensaver. No DV397H há uma rotina idêntica. Foi só criar o mesmo gancho. O gancho aí em cima apenas verifica se o Screensaver está habilitado. Se estiver, devolve o controle para a rotina do Screensaver. Se não, vai embora.
Bom, por último, temos a opção NTSC / PAL. No firmware Xypro e no Br0max, o endereço de EEPROM utilizado é 0F. Isso não faz a menor diferença no DV397H. E também não entendi como eles fizeram. Mas analisando a rotina BankSw_453_B5_7F1E do DV397H, responsável pela alteração de resolução (o DV397H permite 480i, 480p, 720p, 1080i e 1080p), descobri que o sistema é definido pelo endereço #002A compartilhado com o ARM. Se fizermos um Arm_PutChar nesse endereço com o valor #2, mudamos para NTSC. O valor 0, muda para PAL B/G. O problema é que a mudança não é imediata. Precisamos reiniciar o aparelho. No entanto, descobri uma rotina que, se chamada com o endereço correspondente, aplica a mudança imediatamente. Talvez já seja conhecida do pessoal do fórum. Eu ainda não procurei se há algum texto sobre ela. Começa no endereço B1:DE40. Após fazer a mudança no endereço, deve-se chamar a rotina zerando todos os registradores R's, com excessão de R6 e R7, que levam o endereço da modificação. Por exemplo, no seguinte trecho, envia-se o byte #2 para #002A, e depois chama-se a rotina B1:DE40 para que a mudança seja aplicada imediatamente:
7D 02 mov R5, #2
7F 2A mov R7, #0x2A
7E 00 mov R6, #0
12 03 A9 lcall B1_BS_32_B4_F36A
E4 clr A
FB mov R3, A
FA mov R2, A
FD mov R5, A
FC mov R4, A
7F 2A mov R7, #0x2A
FE mov R6, A
12 DE 40 lcall BankSw_327_B1_DE40
Mas aí havia o problema da resolução. Na verdade, há duas cadeias de resoluções: 480i, 480p, 720p, 1080i e 1080p para NTSC e 576i, 576p, 720p, 1080i e 1080p para PAL, que estão em forma de tabela:
B5:01EF 06 B5_1EF: .byte 6 ;480p ; DATA XREF: BankSw_453_B5_7F1E+2C_o
B5:01EF ; BankSw_453_B5_7F1E+79_o ...
B5:01F0 02 .byte 2 ;720p
B5:01F1 03 .byte 3 ;1080i
B5:01F2 0A .byte 0xA ;1080p
B5:01F3 04 .byte 4 ;480i
B5:01F4 09 B5_1F4: .byte 9 ;576p ; DATA XREF: BankSw_453_B5_7F1E+3A_o
B5:01F4 ; BankSw_453_B5_7F1E+9B_o ...
B5:01F5 07 .byte 7 ;720p
B5:01F6 08 .byte 8 ;1080i
B5:01F7 0B .byte 0xB ;1080p
B5:01F8 05 .byte 5 ;576i
Se alterarmos apenas o sistema, quando tentarmos mudar a resolução, o player irá travar. A solução foi descobrir, após mudar o sistema, em qual resolução estava e mudar para a resolução correspondete da outra cadeia. A resolução deve ser enviada (ou lida) ao endereço compartilhado #0F82. Depois do PutChar, então é só chamar BankSw_327_B1_DE40 com R6=#0F e R7=82 para aplicar a mudança de resolução imediatamente (o que aplicará também a mudança de sistema, gravada em #002A).
No final, foi só acertar a posição das legendas com MTKWindows. Aumentei a defasagem PALDY de 48 para 90 (eu acho).
Bom, é isso. Espero ter ajudado!