Pertanyaan Bagaimana cara kerja emulator dan bagaimana cara mereka menulis? [Tutup]


Bagaimana cara kerja emulator? Ketika saya melihat emulator NES / SNES atau C64, itu mengejutkan saya.

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

Apakah Anda harus meniru prosesor dari mesin-mesin itu dengan menafsirkan instruksi perakitan tertentu? Apa lagi yang masuk ke dalamnya? Bagaimana mereka biasanya dirancang?

Bisakah Anda memberikan saran untuk seseorang yang tertarik menulis emulator (terutama sistem permainan)?


969
2018-01-15 22:10


asal


Jawaban:


Emulasi adalah bidang multi-faceted. Berikut adalah ide dasar dan komponen fungsional. Saya akan membaginya menjadi beberapa bagian dan kemudian mengisi detailnya melalui pengeditan. Banyak hal yang akan saya jelaskan akan membutuhkan pengetahuan tentang cara kerja dalam prosesor - pengetahuan perakitan diperlukan. Jika saya agak terlalu samar pada hal-hal tertentu, silakan ajukan pertanyaan sehingga saya dapat terus meningkatkan jawaban ini.

Ide dasar:

Emulasi bekerja dengan menangani perilaku prosesor dan komponen individual. Anda membangun masing-masing bagian dari sistem dan kemudian menghubungkan potongan-potongan seperti kabel di perangkat keras.

Emulasi prosesor:

Ada tiga cara menangani emulasi prosesor:

  • Interpretasi
  • Kompilasi ulang dinamis
  • Kompilasi ulang statis

Dengan semua jalur ini, Anda memiliki tujuan keseluruhan yang sama: jalankan sekumpulan kode untuk memodifikasi keadaan prosesor dan berinteraksi dengan 'perangkat keras'. Keadaan prosesor adalah konglomerasi dari register prosesor, interrupt handler, dll untuk target prosesor yang diberikan. Untuk 6502, Anda akan memiliki sejumlah bilangan bulat 8-bit yang mewakili register: A, X, Y, P, dan S; Anda juga akan memiliki 16-bit PC daftar.

Dengan interpretasi, Anda mulai di IP (Penunjuk instruksi - juga disebut PC, penghitung program) dan membaca instruksi dari memori. Kode Anda mem-parsing instruksi ini dan menggunakan informasi ini untuk mengubah status prosesor seperti yang ditentukan oleh prosesor Anda. Masalah intinya dengan interpretasi adalah itu sangat lambat; setiap kali Anda menangani instruksi yang diberikan, Anda harus memecahkan kode dan melakukan operasi yang diperlukan.

Dengan rekompilasi dinamis, Anda melakukan iterasi terhadap kode seperti interpretasi, tetapi alih-alih hanya mengeksekusi opcode, Anda membangun daftar operasi. Setelah Anda mencapai instruksi cabang, Anda mengkompilasi daftar operasi ini ke kode mesin untuk platform host Anda, kemudian Anda cache kode yang dikompilasi ini dan jalankan. Kemudian ketika Anda menekan grup instruksi yang diberikan lagi, Anda hanya perlu mengeksekusi kode dari cache. (BTW, kebanyakan orang tidak benar-benar membuat daftar instruksi tetapi mengkompilasi mereka ke kode mesin dengan cepat - ini membuatnya lebih sulit untuk mengoptimalkan, tetapi itu di luar lingkup jawaban ini, kecuali cukup orang yang tertarik)

Dengan kompilasi ulang statis, Anda melakukan hal yang sama seperti dalam kompilasi ulang dinamis, tetapi Anda mengikuti ranting. Anda akhirnya membangun sepotong kode yang mewakili semua kode dalam program, yang kemudian dapat dijalankan tanpa gangguan lebih lanjut. Ini akan menjadi mekanisme yang bagus jika bukan karena masalah berikut:

  • Kode yang tidak ada dalam program untuk memulai (misalnya terkompresi, dienkripsi, dibuat / diubah saat runtime, dll.) Tidak akan dikompilasi ulang, sehingga tidak akan berjalan
  • Sudah terbukti bahwa menemukan semua kode dalam biner yang diberikan setara dengan Menghentikan masalah

Ini menggabungkan untuk membuat kompilasi statis benar-benar tidak layak dalam 99% kasus. Untuk informasi lebih lanjut, Michael Steil telah melakukan riset hebat dalam kompilasi ulang statis - yang terbaik yang pernah saya lihat.

Sisi lain dari emulasi prosesor adalah cara Anda berinteraksi dengan perangkat keras. Ini benar-benar memiliki dua sisi:

  • Waktu prosesor
  • Penanganan interupsi

Waktu prosesor:

Platform tertentu - terutama konsol lama seperti NES, SNES, dll - mengharuskan emulator Anda untuk memiliki waktu yang ketat agar kompatibel sepenuhnya. Dengan NES, Anda memiliki PPU (unit pemrosesan piksel) yang mengharuskan CPU meletakkan piksel ke dalam memorinya pada saat-saat yang tepat. Jika Anda menggunakan interpretasi, Anda dapat dengan mudah menghitung siklus dan meniru waktu yang tepat; dengan rekompilasi dinamis / statis, hal-hal yang / banyak / lebih kompleks.

Penanganan interupsi:

Interupsi adalah mekanisme utama yang CPU berkomunikasi dengan perangkat keras. Secara umum, komponen perangkat keras Anda akan memberi tahu CPU apa interupsi yang ia pedulikan. Ini cukup mudah - ketika kode Anda melempar interupsi tertentu, Anda melihat tabel interrupt handler dan memanggil callback yang tepat.

Emulasi perangkat keras:

Ada dua sisi untuk meniru perangkat keras yang diberikan:

  • Meniru fungsionalitas perangkat
  • Meniru antarmuka perangkat yang sebenarnya

Ambil contoh hard-drive. Fungsionalitas ini ditiru dengan membuat penyimpanan backing, rutinitas baca / tulis / format, dll. Bagian ini umumnya sangat mudah.

Antarmuka perangkat sebenarnya sedikit lebih rumit. Ini umumnya merupakan kombinasi dari register yang dipetakan memori (misalnya bagian memori yang ditonton perangkat untuk melakukan perubahan untuk memberi sinyal) dan menyela. Untuk hard drive, Anda mungkin memiliki area yang dipetakan memori tempat Anda menempatkan perintah baca, menulis, dll, lalu baca kembali data ini.

Saya akan membahas lebih detail, tetapi ada sejuta cara yang bisa Anda lakukan dengannya. Jika Anda memiliki pertanyaan spesifik di sini, silakan bertanya dan saya akan menambahkan info.

Sumber daya:

Saya pikir saya sudah memberikan intro yang cukup bagus di sini, tetapi ada a ton area tambahan. Saya dengan senang hati membantu dengan pertanyaan apa pun; Saya sudah sangat tidak jelas dalam sebagian besar ini hanya karena kompleksitas yang sangat besar.

Tautan Wikipedia wajib:

Sumber daya emulasi umum:

  • Zophar  - Di sinilah saya memulai dengan emulasi, pertama mengunduh emulator dan akhirnya menjarah arsip dokumentasi mereka yang sangat besar. Ini adalah sumber daya terbaik yang mungkin Anda miliki.
  • NGEmu - Tidak banyak sumber daya langsung, tetapi forum mereka tidak ada duanya.
  • RomHacking.net- Bagian dokumen berisi sumber daya mengenai arsitektur mesin untuk konsol populer

Proyek-proyek emulator untuk referensi:

  • IronBabel - Ini adalah platform emulasi untuk .NET, ditulis dalam Nemerle dan mengkompilasi ulang kode ke C # dengan cepat. Disclaimer: Ini adalah proyek saya, jadi maafkan steker tak tahu malu.
  • BSnes - Emulator SNES yang mengagumkan dengan tujuan akurasi siklus sempurna.
  • MAME - Itu arcade emulator. Referensi bagus.
  • 6502asm.com  - Ini adalah emulator JavaScript 6502 dengan forum kecil yang keren.
  • dynarec'd 6502asm - Ini sedikit hack yang saya lakukan selama satu atau dua hari. Saya mengambil emulator yang ada dari 6502asm.com dan mengubahnya menjadi rekompilasi kode secara dinamis ke JavaScript untuk peningkatan kecepatan yang sangat besar.

Referensi penyatuan ulang prosesor:

  • Penelitian tentang kompilasi ulang statis yang dilakukan oleh Michael Steil (direferensikan di atas) memuncak pada kertas ini dan Anda dapat menemukan sumber dan semacamnya sini.

Tambahan:

Sudah lebih dari setahun sejak jawaban ini diajukan dan dengan semua perhatian yang didapat, saya pikir sudah waktunya untuk memperbarui beberapa hal.

Mungkin hal yang paling menarik dalam persaingan sekarang adalah libcpu, dimulai oleh Michael Steil yang disebutkan tadi. Ini adalah perpustakaan yang ditujukan untuk mendukung sejumlah besar core CPU, yang menggunakan LLVM untuk rekompilasi (statis dan dinamis!). Itu punya potensi besar, dan saya pikir itu akan melakukan hal-hal hebat untuk persaingan.

emu-docs juga telah dibawa ke perhatian saya, yang menyimpan repositori besar dokumentasi sistem, yang sangat berguna untuk tujuan emulasi. Saya belum menghabiskan banyak waktu di sana, tetapi sepertinya mereka memiliki banyak sumber daya yang hebat.

Saya senang posting ini telah membantu, dan saya berharap saya bisa turun dari pantat saya dan menyelesaikan buku saya tentang masalah ini pada akhir tahun / awal tahun depan.


1127
2018-01-15 22:13



Seorang pria bernama Victor Moya del Barrio menulis tesisnya tentang topik ini. Banyak informasi bagus di 152 halaman. Anda dapat mengunduh PDF sini.

Jika Anda tidak ingin mendaftar Scribd, Anda dapat google untuk judul PDF, "Studi teknik untuk pemrograman emulasi". Ada beberapa sumber berbeda untuk PDF.


126
2018-02-02 17:27



Emulasi mungkin tampak menakutkan tetapi sebenarnya lebih mudah daripada simulasi.

Setiap prosesor biasanya memiliki spesifikasi yang ditulis dengan baik yang menggambarkan keadaan, interaksi, dll.

Jika Anda tidak peduli dengan kinerja sama sekali, maka Anda dapat dengan mudah meniru sebagian besar prosesor yang lebih tua menggunakan program berorientasi objek yang sangat elegan. Sebagai contoh, prosesor X86 memerlukan sesuatu untuk mempertahankan keadaan register (mudah), sesuatu untuk mempertahankan status memori (mudah), dan sesuatu yang akan mengambil setiap perintah yang masuk dan menerapkannya ke keadaan mesin saat ini. Jika Anda benar-benar ingin akurasi, Anda juga akan meniru terjemahan memori, caching, dll, tetapi itu bisa dilakukan.

Faktanya, banyak program pengujian produsen microchip dan CPU melawan emulator chip dan kemudian melawan chip itu sendiri, yang membantu mereka mengetahui apakah ada masalah dalam spesifikasi chip, atau dalam implementasi chip perangkat keras. Sebagai contoh, adalah mungkin untuk menulis spesifikasi chip yang akan menghasilkan deadlock, dan ketika tenggat waktu terjadi pada perangkat keras penting untuk melihat apakah itu dapat direproduksi dalam spesifikasi karena itu menunjukkan masalah yang lebih besar daripada sesuatu dalam implementasi chip.

Tentu saja, emulator untuk permainan video biasanya peduli dengan kinerja sehingga mereka tidak menggunakan implementasi yang naif, dan mereka juga menyertakan kode yang berinteraksi dengan OS sistem host, misalnya untuk menggunakan gambar dan suara.

Mempertimbangkan kinerja yang sangat lambat dari video game lama (NES / SNES, dll.), Emulasi cukup mudah pada sistem modern. Bahkan, yang lebih menakjubkan lagi adalah Anda dapat mengunduh satu set setiap game SNES yang pernah ada atau game Atari 2600, mengingat ketika sistem ini populer, akses bebas ke setiap cartridge pasti menjadi mimpi yang menjadi kenyataan.


43
2018-01-15 22:43



Saya tahu bahwa pertanyaan ini agak lama, tetapi saya ingin menambahkan sesuatu ke diskusi. Sebagian besar jawaban di sini berpusat pada emulator yang menafsirkan instruksi mesin dari sistem yang mereka tiru.

Namun, ada pengecualian yang sangat terkenal untuk ini yang disebut "UltraHLE" (Artikel WIKIpedia). UltraHLE, salah satu emulator paling terkenal yang pernah dibuat, meniru game-game Nintendo 64 komersial (dengan kinerja yang layak di komputer rumah) pada saat itu secara luas dianggap mustahil untuk melakukannya. Faktanya, Nintendo masih memproduksi judul baru untuk Nintendo 64 ketika UltraHLE dibuat!

Untuk pertama kalinya, saya melihat artikel tentang emulator di majalah cetak di mana sebelumnya, saya hanya melihat mereka dibahas di web.

Konsep UltraHLE adalah untuk memungkinkan yang tidak mungkin dengan meniru panggilan C library bukan panggilan tingkat mesin.


29
2017-07-07 18:17



Yang patut dicermati adalah upaya Imran Nazar menulis a Game Boy emulator di JavaScript.


22
2017-11-11 10:19



Setelah membuat emulator saya sendiri dari BBC Microcomputer tahun 80-an (ketik VBeeb ke Google), ada sejumlah hal yang perlu diketahui.

  • Anda tidak meniru hal yang nyata seperti itu, itu akan menjadi replika. Sebaliknya, Anda meniru Negara. Contoh yang baik adalah kalkulator, yang asli memiliki tombol, layar, huruf, dll. Tetapi untuk mengemulasikan kalkulator, Anda hanya perlu mengemulasi apakah tombol naik atau turun, segmen LCD mana yang aktif, dll. Pada dasarnya, satu set angka mewakili semua kemungkinan kombinasi hal-hal yang dapat berubah dalam kalkulator.
  • Anda hanya perlu antarmuka emulator untuk muncul dan berperilaku seperti yang asli. Semakin meyakinkan ini semakin dekat emulasi. Apa yang terjadi di belakang layar dapat menjadi apa pun yang Anda suka. Tapi, untuk kemudahan menulis emulator, ada pemetaan mental yang terjadi antara sistem nyata, yaitu chip, display, keyboard, papan sirkuit, dan kode komputer abstrak.
  • Untuk meniru sistem komputer, paling mudah untuk memecahnya menjadi bagian-bagian yang lebih kecil dan meniru potongan-potongan itu satu per satu. Kemudian string semuanya bersama-sama untuk produk jadi. Mirip seperti sekumpulan kotak hitam dengan input dan output, yang cocok untuk pemrograman berorientasi objek. Anda dapat membagi lagi potongan ini untuk mempermudah hidup.

Secara praktis, Anda biasanya ingin menulis untuk kecepatan dan kesetiaan emulasi. Ini karena perangkat lunak pada sistem target akan (mungkin) berjalan lebih lambat daripada perangkat keras asli pada sistem sumber. Itu mungkin membatasi pilihan bahasa pemrograman, kompiler, sistem target, dll.
Selanjutnya bahwa Anda harus membatasi apa yang Anda siap untuk meniru, misalnya tidak perlu untuk meniru keadaan tegangan transistor dalam mikroprosesor, tetapi mungkin perlu untuk meniru keadaan set register dari mikroprosesor.
Secara umum semakin kecil tingkat detail emulasi, semakin fidelity Anda akan sampai ke sistem yang asli.
Akhirnya, informasi untuk sistem yang lebih tua mungkin tidak lengkap atau tidak ada. Jadi mendapatkan peralatan asli sangat penting, atau setidaknya memisahkan emulator lain yang baik yang ditulis orang lain!


18
2017-08-05 15:36



Ya, Anda harus menafsirkan seluruh kode mesin biner berantakan "dengan tangan". Tidak hanya itu, sebagian besar waktu Anda juga harus mensimulasikan beberapa perangkat keras eksotis yang tidak memiliki setara pada mesin target.

Pendekatan sederhana adalah menafsirkan instruksi satu per satu. Itu bekerja dengan baik, tapi lambat. Pendekatan yang lebih cepat adalah rekompilasi - menerjemahkan kode mesin sumber ke kode mesin target. Ini lebih rumit, karena kebanyakan instruksi tidak akan memetakan satu-ke-satu. Sebaliknya, Anda harus membuat pekerjaan yang rumit yang melibatkan kode tambahan. Namun pada akhirnya jauh lebih cepat. Kebanyakan emulator modern melakukan ini.


17
2018-01-15 22:17



Ketika Anda mengembangkan emulator Anda menafsirkan perakitan prosesor yang sedang dikerjakan sistem (Z80, 8080, CPU PS, dll.).

Anda juga harus meniru semua periferal yang dimiliki sistem (keluaran video, pengontrol).

Anda harus mulai menulis emulator untuk sistem simpe seperti yang lama baik Game Boy (yang menggunakan prosesor Z80, saya tidak tidak salah) ATAU untuk C64.


15
2018-01-15 22:21