quarta-feira, 31 de outubro de 2012

Emuladores: Como escrever um emulador

Essa semana fiquei pensando como os emuladores de computadores e consoles são programados.

O primeiro passo para criarmos um emulador é emular o processador central. No caso do MSX que é o tema principal do nosso blog (lembre-se que em outro post eu disse que o blog é de eletrônica e computação também :) . No caso do Z80, precisamos pensar nos seguintes aspectos: input, processamento e output. Sabendo que o Z80 tem: 40 pinos, 22 registradores internos, uma ULA (Unidade Logica Aritimetica) e, 158 instruções elementares. O clock do Z80 é de ~3,58MHZ

Então vamos lá. Sugiro fazer a implementação em C/C++ ou em Java.

O nosso processador emulado deve ser capaz de ler as instruções da ROM e da RAM virtuais, processa-las e então mudar o estado de seus pinos de acordo com o resultado. Isso tudo em um loop de programação que é "regulado" pelo nosso clock emulado que deve ser de ~3,58MHZ (mesmo que nossos PCs sejam de 2,20GHZ e com dois processadores!). Esse seria um tipo de emulador interpretador. O clock do Z80 é no pino 6 que em HW verdadeiro é alimentado por um gerador de clock que gera uma onda quadrada. No emulador devemos simular isso calculando e ajustando a velocidade do loop, ou se você preferir, criando uma função geradora de clock que chama uma função principal que vai emular o Z80 no nosso emulador a frequência do clock.

Assim, vamos precisar de 22 variáveis no escopo interno da função do processador (locais) que são os registradores do Z80. Sendo que 18 delas são de 8 bits (A, B, C, D, E,  F, H, I, L, R, A', B', C', D', E', F', H', I', L', R') e 4 são de 16 bits (IX, IY, SP, PC).

Também vamos precisar de 40 variáveis para representar os pinos do Z80. Tanto no escopo interno da função do processador quanto para serem retornadas globalmente para o emulador, já que os pinos estão "soldados" a nossa placa-mãe virtual. Assim, por exemplo, as variáveis que representam os barramentos de dados, endereços e controle são vistas pelo escopo do emulador inteiro. Lembre-se que os barramento de dados tanto pode ler quanto escrever na memoria RAM.

A brincadeira começa quando o Z80 lê do registrador PC (Program Conter) o endereço de memoria RAM da próxima instrução a ser executada. Lembre que no Z80 os endereços são de 16 bits e o conteúdo de cada endereço da memoria é de 8 bits. Assim, a nosso loop deve ler da nossa memoria virtual essa instrução processa la e em seguida atualizar os valores de todos os pinos de saída (Variáveis corres pondentes) e incrementar o PC.

Quanto as 158 instruções do Z80, você já deve estar imaginado que vamos precisar de um swith/case para tratar todas elas e quem sabe chamar método específicos para cada uma delas.

Não parece tão difícil, mas também não e tão fácil escolher a melhor estrutura do programa emulador. Lembre-se que o emulador dever emular outros circuitos como a VDP e o processador de som, entre outros e você terá que atualizar o estado de cada elemento do computador virtual no loop principal do emulador.

Por hora é só pessoal. Em tempo atualizarei esse post quando tiver mais ideias ou melhorias no texto.
Abraços,

O Editor.

Nenhum comentário:

Postar um comentário