Pergunta

Como fazer emuladores trabalho? Quando vejo NES / SNES ou C64 emuladores, ele me surpreende.

http://www.tommowalker.co.uk/snemzelda.png

Você tem que emular o processador dessas máquinas, interpretando suas instruções de montagem em particular? O que mais vai para ele? Como são normalmente concebidos?

Você pode dar algum conselho para alguém interessado em escrever um emulador (particularmente um sistema de jogo)?

Foi útil?

Solução

Emulação é uma área multi-facetada. Aqui estão as idéias básicas e componentes funcionais. Eu vou quebrá-lo em pedaços e, em seguida, preencher os dados via edições. Muitas das coisas que eu vou descrever irá exigir conhecimento do funcionamento interno de processadores - montagem de conhecimento é necessário. Se eu sou um pouco vago sobre certas coisas, por favor, fazer perguntas para que eu possa continuar a melhorar esta resposta.

idéia básica:

Emulação funciona por manipulação do comportamento do processador e os componentes individuais. Você constrói cada parte individual do sistema e, em seguida, ligar as peças muito parecido com fios fazer em hardware.

emulação Processador:

Há três maneiras de lidar com emulação de processador:

  • Interpretação
  • recompilação dinâmica
  • estática recompilação

Com todos esses caminhos, você tem o mesmo objetivo geral: executar um pedaço de código para modificar estado do processador e interagir com 'hardware'. estado do processador é um conglomerado dos registos de processadores, controladores de interrupções, etc para um alvo determinado processador. Para o 6502, você teria um número de inteiros de 8 bits que representam registros: A, X, Y, P e S; você também tem um registo de 16 bits PC.

Com a interpretação, você começar no IP (ponteiro de instrução - também chamado PC, contador de programa) e ler a instrução da memória. Seu código analisa esta instrução e usa esta informação para estado do processador alter conforme especificado pelo seu processador. O principal problema com a interpretação é que é muito lento; cada vez que você lidar com uma determinada instrução, você tem que decodificá-lo e executar a operação necessária.

Com recompilação dinâmica, você iterar sobre o código muito parecido com interpretação, mas em vez de opcodes apenas executando, você construir uma lista de operações. Depois de chegar a uma instrução de desvio, você compilar esta lista de operações para código de máquina para sua plataforma host, então você armazenar em cache este código compilado e executá-lo. Então, quando você bate um determinado grupo instrução novamente, você só tem que executar o código a partir do cache. (Aliás, a maioria das pessoas não realmente fazer uma lista de instruções, mas compilá-los para código de máquina em tempo real - o que torna mais difícil para otimizar, mas que está fora do escopo desta resposta, a menos que as pessoas o suficiente estiver interessado)

Com recompilação estática, você fazer o mesmo que na recompilação dinâmica, mas você seguir ramos. Você acaba construindo um pedaço de código que representa todo o código no programa, que pode então ser executado sem qualquer interferência. Este seria um grande mecanismo, se não fosse para os seguintes problemas:

  • O código que não está no programa para começar (por exemplo comprimido, criptografado, gerado / modificado em tempo de execução, etc) não vai ser recompilados, por isso não será executado
  • Está provado que encontrar todo o código em um determinado binário é equivalente ao Travar problema

Estas se combinam para fazer recompilação estática completamente inviável em 99% dos casos. Para mais informações, Michael Steil fez alguma grande investigação sobre recompilação estática - o melhor que eu vi

.

O outro lado para a emulação do processador é a maneira pela qual você interage com o hardware. Isso realmente tem dois lados:

  • tempo Processor
  • manipulação de interrupção

tempo Processador:

Certas plataformas - especialmente consoles mais antigos como o NES, SNES, etc - exigem seu emulador para ter tempo estrito para ser completamente compatível. Com o NES, você tem a PPU (unidade de processamento de pixels), que exige que a CPU colocar pixels em sua memória em momentos precisos. Se você usar interpretação, você pode facilmente contar os ciclos eemular momento adequado; com dinâmica / recompilação estática, as coisas são um / lot / mais complexa.

manipulação de interrupção:

Interrupções são o principal mecanismo que os comunica com CPU com hardware. Geralmente, os componentes de hardware vai contar a CPU que as interrupções que se preocupa. Isto é bastante simples -. Quando seu código lança uma determinada interrupção, você olha para a mesa manipulador de interrupção e chamar o callback adequada

emulação de hardware:

Há dois lados para emular um determinado dispositivo de hardware:

  • Emulando a funcionalidade do dispositivo
  • Emulando as interfaces de dispositivo real

Veja o caso de um disco rígido. A funcionalidade é emulado, criando o armazenamento de apoio, de leitura / gravação / rotinas de formato, etc. Esta parte é geralmente muito simples.

A interface real do dispositivo é um pouco mais complexa. Esta é geralmente uma combinação de registos de memória mapeada (por exemplo, partes da memória que os relógios de dispositivo para alterações a fazer sinalização) e interrupções. Para uma unidade de disco rígido, você pode ter uma área de memória mapeada onde colocar os comandos ler, escreve, etc, então leia este volta de dados.

eu entrar em mais detalhes, mas há um milhão de maneiras que você pode ir com ele. Se você tiver quaisquer perguntas específicas aqui, sinta-se livre para perguntar e eu vou adicionar a informação.

Recursos:

Eu acho que eu dei uma boa bastante introdução aqui, mas há um tonelada de áreas adicionais. Estou mais do que feliz em ajudar com qualquer dúvida; Estive muito vago na maior parte deste simplesmente devido à imensa complexidade.

obrigatório Wikipedia links:

recursos de emulação gerais:

  • Zofar - Aqui é onde eu tenho o meu início com emulação, primeiros emuladores de download e, eventualmente, saqueando sua imensa arquivos de documentação. Este é o melhor recurso absoluto você pode eventualmente ter.
  • NGEmu -. Não muitos recursos diretos, mas seus fóruns são imbatíveis
  • RomHacking.net - A seção de documentos contém recursos sobre arquitetura da máquina para consoles populares

projectos emulador para referência:

  • IronBabel - Esta é uma plataforma de emulação para .NET, escrito em Nemerle e recompila código para C # no vôo. Disclaimer:. Este é o meu projeto, para perdão do plug descarado
  • BSnes -. Um SNES impressionantes emulador com o objetivo de precisão ciclo-perfeito
  • MAME - O arcada emulador. Grande referência.
  • 6502asm.com -. Este é um JavaScript 6502 emulador com um fórum fresco pouco
  • dynarec'd 6502asm - Este é um pequeno hack que eu fiz ao longo de um dia ou dois . Tomei o emulador existente 6502asm.com e mudou de recompilar dinamicamente o código para JavaScript para aumentos de velocidade maciças.

referências Processador de recompilação:

  • A investigação sobre recompilação estática feita por Michael Steil (acima referenciado) culminou na neste artigo e você pode encontrar fonte e que aqui .

Adenda:

Tem sido bem mais de um anouma vez que esta resposta foi submetido e com toda a atenção que tem recebido, eu percebi que é hora de atualizar algumas coisas.

Talvez a coisa mais excitante na emulação agora é libcpu , iniciado pelo referido Michael Steil . É uma biblioteca destinada a apoiar um grande número de núcleos de CPU, que usam LLVM para recompilação (estático e dinâmico!). Ele tem um enorme potencial, e eu acho que vai fazer grandes coisas para emulação.

EMU-docs também foi trazido a minha atenção, que abriga um grande repositório de documentação do sistema, que é muito útil para fins de emulação. Eu não passei muito tempo lá, mas parece que eles têm um monte de grandes recursos.

Estou feliz Este post foi útil, e eu estou esperando que eu possa sair minha bunda e terminar o meu livro sobre o assunto até o final do ano / início do próximo ano.

Outras dicas

Um cara chamado Victor Moya del Barrio escreveu sua tese sobre este tema. Um monte de boas informações em 152 páginas. Você pode baixar o PDF aqui .

Se você não quiser se registrar com Scribd , você pode google para o título PDF, "Estudo das técnicas de programação de emulação" . Há um par de diferentes fontes para o PDF.

Emulação pode parecer assustador, mas é realmente muito mais fácil do que a simulação.

Qualquer processador tem, tipicamente, uma especificação bem escrito que descreve estados, interacções, etc.

Se você não se preocupam com o desempenho em tudo, então você pode facilmente emular a maioria dos processadores mais antigos que usam programas orientados muito elegante objeto. Por exemplo, um processador X86 precisaria de algo para manter o estado de registros (fácil), algo para manter o estado da memória (fácil), e algo que levaria cada comando de entrada e aplicá-lo para o estado atual da máquina. Se você realmente queria precisão, você faria também traduções de memória emular caching, etc., mas isso é factível.

Na verdade, muitos fabricantes de microchips e CPU testar programas contra um emulador do chip e depois contra o próprio chip, o que os ajuda a descobrir se há problemas nas especificações do chip, ou na implementação real do chip em hardware. Por exemplo, é possível escrever uma especificação chip que resultaria em impasses, e quando um prazo ocorre no hardware é importante para ver se ele poderia ser reproduzida na especificação desde que indica um problema maior do que algo na implementação de chip.

Claro, emuladores de jogos de vídeo geralmente se preocupam com o desempenho de modo que eles não usam implementações ingênuas, e eles também incluem código que interfaces com OS do sistema host, por exemplo, para usar desenho e som.

Considerando o muito lento desempenho dos videogames antigos (NES / SNES, etc.), a emulação é bastante fácil em sistemas modernos. Na verdade, é ainda mais surpreendente que você poderia simplesmente baixar um conjunto de todos os jogos SNES nunca ou qualquer jogo de Atari 2600 nunca, considerando que, quando esses sistemas eram populares tendo livre acesso a todos os cartuchos teria sido um sonho tornado realidade.

Eu sei que esta questão é um pouco velho, mas eu gostaria de acrescentar algo à discussão. A maioria das respostas aqui giram em torno emuladores interpretar as instruções de máquina dos sistemas que emulam.

No entanto, há uma exceção muito bem conhecida a essa chamada "UltraHLE" ( Wikipedia artigo ). UltraHLE, um dos mais famosos emuladores já criados, emulado comerciais Nintendo 64 jogos (com um desempenho decente em computadores domésticos) no momento em que foi amplamente considerado impossível fazê-lo. Por uma questão de fato, a Nintendo ainda estava produzindo novos títulos para o Nintendo 64, quando UltraHLE foi criado!

Pela primeira vez, vi artigos sobre emuladores em revistas impressas, onde antes, eu só tinha visto eles discutido na web.

O conceito de UltraHLE era tornar possível o impossível emulando biblioteca C chama em vez de chamadas de nível de máquina.

vale alguma coisa dar uma olhada é a tentativa de Imran Nazar em escrever um Gameboy emulador em JavaScript.

Depois de criar o meu próprio emulador da BBC Microcomputador dos anos 80 (tipo VBeeb no Google), há uma série de coisas para saber.

  • Você não está emulando a coisa real, como tal, que seria uma réplica. Em vez disso, você está emulando Estado . Um bom exemplo é uma calculadora, a coisa real tem botões, tela, caso etc. Mas para emular uma calculadora você só precisa emular se botões são cima ou para baixo, o que segmentos de LCD estão em, etc. Basicamente, um conjunto de números representando todas as combinações possíveis de coisas que podem mudar em uma calculadora.
  • Você só precisa da interface do emulador para aparecer e se comportam como a coisa real. A mais convincente esta é a mais próxima a emulação é. O que se passa nos bastidores pode ser qualquer coisa que você gosta. Mas, para a facilidade de escrever um emulador, existe um mapeamento mental que acontece entre o sistema real, isto é, batatas fritas, monitores, teclados, placas de circuito, eo código de computador abstrato.
  • Para emular um sistema de computador, é mais fácil de quebrá-la em pedaços menores e imitar aqueles pedaços individualmente. string, então todo o lote em conjunto para o produto acabado. Muito parecido com um conjunto de caixas-pretas com entradas e saídas, que se presta muito bem para programação orientada a objeto. Você pode ainda subdividir esses pedaços para facilitar a vida.

Na prática, você está olhando geralmente para escrever para a velocidade e fidelidade da emulação. Isso ocorre porque o software no sistema de destino irá (podem) ser executado de forma mais lenta do que o hardware original no sistema de origem. Isso pode restringir a escolha da linguagem de programação, compiladores, sistema de destino etc.
Além disso, você tem que circunscrevem o que você está preparado para emular, por exemplo não é necessário emular o estado de tensão dos transistores em um microprocessador, mas provavelmente necessário para emular o estado do conjunto de registradores do microprocessador.
De um modo geral quanto menor o nível de detalhe de emulação, mais fidelidade você vai chegar ao sistema original.
Finalmente, a informação para sistemas mais antigos podem estar incompletos ou inexistentes. Assim, espera obter de equipamento original é essencial, ou pelo menos premiação além outra boa emulador que alguém tenha escrito!

Sim, você tem de interpretar todo o binário bagunça código de máquina "à mão". Não só isso, na maioria das vezes você também tem que simular algum hardware exótico que não tem um equivalente na máquina de destino.

A abordagem simples é interpretar as instruções um por um. Isso funciona bem, mas é lento. Uma abordagem mais rápido é recompilação - traduzir o código de máquina de origem para código de máquina-alvo. Isso é mais complicado, como a maioria das instruções não irá mapear um-para-um. Em vez disso você terá que fazer elaboradas soluções alternativas que envolvem código adicional. Mas no final é muito mais rápido. A maioria dos emuladores modernos fazer isso.

Quando você desenvolver um emulador que você está interpretando o processador de montagem que o sistema está trabalhando em (Z80, 8080, PS CPU, etc.).

Você também precisa emular todos os periféricos que o sistema tem (saída de vídeo, controlador).

Você deve começar a escrever emuladores para os sistemas simpe como o bom e velho Game Boy (que o uso processador de um Z80, não estou não confundir) ou para C64.

Emulator são muito difíceis de criar uma vez que existem muitos hacks (como no incomum efeitos), problemas de tempo, etc que você precisa para simular.

Para um exemplo disso, veja http://queue.acm.org/detail .cfm? id = 1755886 .

Isso também irá mostrar-lhe por que você ‘necessidade’ de uma CPU multi-GHz para emular um 1MHz.

Também confira Emulators.com para grandes conselhos sobre otimização de nível de instrução para EIC, e muitas outras guloseimas Darek Mihocka na construção de emuladores eficientes.

Eu nunca fiz nada tão chique como para emular uma consola de jogos, mas eu queria fazer um curso, uma vez que a tarefa era escrever um emulador para a máquina descrita no Andrew Tanenbaums Estruturado Organização de computadores . Isso foi divertido um me deu um monte de aha momentos. Você pode querer pegar esse livro-se antes de mergulhar para escrever um emulador real.

Conselhos sobre emulando um sistema real ou a sua própria coisa? Posso dizer que emuladores funcionar emulando o hardware inteira. Talvez não para baixo ao circuito (como bits movendo-se como o HW faria. Mover o byte é o resultado final para copiar o byte é bom). Emulator são muito difíceis de criar uma vez que existem muitos hacks (como em efeitos incomuns), problemas de tempo, etc que você precisa para simular. Se um (entrada) peça é errado todo o sistema pode fazer para baixo ou na melhor das hipóteses têm um bug / falha.

O Shared Source Device Emulator contém edificável código-fonte para um emulador PocketPC / Smartphone (Requer Visual Studio, é executado no Windows). Eu trabalhei em V1 e V2 do lançamento binário.

Ele aborda muitas questões de emulação: - tradução de endereço eficiente de convidado virtual para física convidado para host virtual - compilação JIT de código de hóspedes - simulação de dispositivos periféricos, como placas de rede, touchscreen e áudio - integração UI, para teclado e mouse do host - save / restore do estado, para simulação de currículo do modo de baixo consumo de energia

Para adicionar a resposta fornecida pelo @Cody Brocious
No contexto da virtualização onde está a emular um novo sistema (CPU, I / O, etc.) para uma máquina virtual, podemos ver as seguintes categorias de emuladores.

Interpretação: bochs é um exemplo de intérprete, é um emulador x86 PC, leva cada instrução do sistema convidado traduz em um outro conjunto de instruções (do ISA host) para produzir os effect.Yes Pretende-se muito lento , ele não armazena em cache qualquer coisa assim que cada instrução passa pelo mesmo ciclo.

Dinâmica emalator: Qemu é um emulador dinâmico. Ele faz na tradução mosca de instrução de hóspedes também armazena em cache results.The melhor parte é que seja executado como muitas instruções quanto possível diretamente no sistema host para que a emulação é mais rápido. Também como mencionado por Cody, divide-se o código em blocos (1 único fluxo de execução).

estática emulador: Até eu sei que não há nenhum emulador estática que pode ser útil em virtualização.

Como eu iria começar a emulação.

livros 1.Get baseados em torno de programação de baixo nível, você vai precisar dele para o sistema de "fingir" que operam da Nintendo ... game boy ...

livros 2.Get sobre emulação especificamente, e talvez OS desenvolvimento. (Você não estará fazendo um sistema operacional, mas o mais próximo a ele.

3.Look em alguns emuladores de código aberto, especialmente as do sistema você quer fazer um emulador para.

trechos 4.Copie do código mais complexo em seu IDE / compliler. Isto vai poupar escrevendo código longo. Isto é o que eu faço para o desenvolvimento do sistema operacional, use um distrito de linux

scroll top