Bagaimana cara kerja emulator? Ketika saya melihat emulator NES / SNES atau C64, saya terkejut.
Apakah Anda harus meniru prosesor mesin-mesin itu dengan menafsirkan instruksi perakitan khusus? Apa lagi yang masuk ke dalamnya? Bagaimana mereka biasanya dirancang?
Bisakah Anda memberikan saran untuk seseorang yang tertarik untuk menulis emulator (khususnya sistem game)?
Jawaban:
Emulasi adalah bidang multi-segi. Berikut adalah ide-ide dasar dan komponen fungsional. Saya akan memecahnya menjadi beberapa bagian dan kemudian mengisi rincian melalui suntingan. Banyak hal yang akan saya uraikan akan membutuhkan pengetahuan tentang cara kerja prosesor - pengetahuan perakitan diperlukan. Jika saya agak terlalu kabur dalam hal-hal tertentu, silakan ajukan pertanyaan agar saya dapat terus meningkatkan jawaban ini.
Ide dasar:
Emulasi bekerja dengan menangani perilaku prosesor dan komponen individual. Anda membangun masing-masing bagian sistem dan kemudian menghubungkan potongan seperti kabel dalam perangkat keras.
Emulasi prosesor:
Ada tiga cara menangani emulasi prosesor:
Dengan semua jalur ini, Anda memiliki tujuan keseluruhan yang sama: mengeksekusi kode untuk memodifikasi keadaan prosesor dan berinteraksi dengan 'perangkat keras'. Status prosesor adalah konglomerasi 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
, danS
; Anda juga akan memilikiPC
register 16-bit .Dengan interpretasi, Anda mulai pada
IP
(penunjuk instruksi - juga disebutPC
, penghitung program) dan membaca instruksi dari memori. Kode Anda mem-parsing instruksi ini dan menggunakan informasi ini untuk mengubah kondisi prosesor seperti yang ditentukan oleh prosesor Anda. Masalah inti dengan interpretasi adalah bahwa itu sangat lambat; setiap kali Anda menangani instruksi yang diberikan, Anda harus memecahkan kode dan melakukan operasi yang diperlukan.Dengan kompilasi ulang yang dinamis, Anda beralih pada kode seperti interpretasi, tetapi alih-alih hanya menjalankan opcode, Anda membangun daftar operasi. Setelah Anda mencapai instruksi cabang, Anda mengkompilasi daftar operasi ini ke kode mesin untuk platform host Anda, kemudian Anda men-cache kode yang dikompilasi ini dan menjalankannya. Kemudian ketika Anda menekan kelompok instruksi yang diberikan lagi, Anda hanya perlu menjalankan kode dari cache. (BTW, kebanyakan orang tidak benar-benar membuat daftar instruksi tetapi mengompilasinya ke kode mesin dengan cepat - ini membuatnya lebih sulit untuk dioptimalkan, tapi itu di luar cakupan jawaban ini, kecuali cukup banyak orang yang tertarik)
Dengan kompilasi ulang statis, Anda melakukan hal yang sama seperti pada kompilasi ulang dinamis, tetapi Anda mengikuti cabang. Anda akhirnya membangun sepotong kode yang mewakili semua kode dalam program, yang kemudian dapat dieksekusi tanpa gangguan lebih lanjut. Ini akan menjadi mekanisme yang hebat jika bukan karena masalah berikut:
Ini bergabung untuk membuat kompilasi statis sepenuhnya tidak mungkin dilakukan pada 99% kasus. Untuk informasi lebih lanjut, Michael Steil telah melakukan penelitian besar dalam kompilasi 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:
Platform tertentu - terutama konsol yang lebih tua seperti NES, SNES, dll - mengharuskan emulator Anda memiliki waktu yang ketat agar sepenuhnya kompatibel. Dengan NES, Anda memiliki PPU (unit pengolah piksel) yang mengharuskan CPU memasukkan 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 kompilasi dinamis / statis, semuanya menjadi / lot / lebih kompleks.
Penanganan interupsi:
Interupsi adalah mekanisme utama yang berkomunikasi dengan perangkat keras oleh CPU. Secara umum, komponen perangkat keras Anda akan memberi tahu CPU apa gangguan yang dipedulikannya. Ini cukup mudah - ketika kode Anda memberikan interupsi yang diberikan, Anda melihat tabel penangan interrupt dan memanggil callback yang tepat.
Emulasi perangkat keras:
Ada dua sisi untuk meniru perangkat perangkat keras yang diberikan:
Ambil kasus hard drive. Fungsionalitas ditiru dengan membuat penyimpanan backing, rutinitas baca / tulis / format, dll. Bagian ini umumnya sangat mudah.
Antarmuka sebenarnya dari perangkat ini sedikit lebih kompleks. Ini umumnya merupakan kombinasi dari register yang dipetakan memori (mis. Bagian memori yang diperhatikan oleh perangkat untuk melakukan pensinyalan) dan menyela. Untuk hard drive, Anda mungkin memiliki area yang dipetakan memori tempat Anda menempatkan perintah baca, tulis, dll, lalu baca kembali data ini.
Saya akan membahas lebih detail, tetapi ada sejuta cara Anda bisa melakukannya. Jika Anda memiliki pertanyaan khusus di sini, jangan ragu untuk bertanya dan saya akan menambahkan informasinya.
Sumber:
Saya pikir saya sudah memberikan intro yang cukup bagus di sini, tetapi ada satu ton area tambahan. Saya sangat senang membantu dengan pertanyaan apa pun; Saya sudah sangat kabur dalam sebagian besar ini hanya karena kompleksitas yang sangat besar.
Tautan Wikipedia wajib:
Sumber daya emulasi umum:
Proyek emulator untuk referensi:
Referensi kompilasi ulang prosesor:
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 saat ini adalah libcpu , dimulai oleh Michael Steil yang disebutkan di atas. Ini adalah perpustakaan yang dimaksudkan untuk mendukung sejumlah besar inti CPU, yang menggunakan LLVM untuk kompilasi (statis dan dinamis!). Itu punya potensi besar, dan saya pikir itu akan melakukan hal-hal hebat untuk dicontoh.
emu-docs juga telah menarik perhatian saya, yang menampung repositori sistem dokumentasi yang bagus, 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 keluar dari pantat saya dan menyelesaikan buku saya pada subjek pada akhir tahun / awal tahun depan.
sumber
Seorang pria bernama Victor Moya del Barrio menulis tesisnya tentang topik ini. Banyak informasi bagus di 152 halaman. Anda dapat mengunduh PDF di sini .
Jika Anda tidak ingin mendaftar dengan scribd , Anda dapat google untuk judul PDF, "Studi teknik pemrograman emulasi" . Ada beberapa sumber berbeda untuk PDF.
sumber
Emulasi mungkin tampak menakutkan tetapi sebenarnya cukup mudah daripada simulasi.
Setiap prosesor biasanya memiliki spesifikasi yang ditulis dengan baik yang menggambarkan status, interaksi, dll.
Jika Anda tidak peduli dengan kinerja sama sekali, maka Anda dapat dengan mudah meniru kebanyakan prosesor yang lebih tua menggunakan program berorientasi objek yang sangat elegan. Sebagai contoh, prosesor X86 akan membutuhkan sesuatu untuk mempertahankan status register (mudah), sesuatu untuk mempertahankan status memori (mudah), dan sesuatu yang akan mengambil setiap perintah yang masuk dan menerapkannya pada keadaan mesin saat ini. Jika Anda benar-benar menginginkan keakuratan, Anda juga akan meniru terjemahan memori, caching, dll., Tetapi itu bisa dilakukan.
Faktanya, banyak produsen microchip dan CPU menguji program terhadap emulator chip dan kemudian terhadap chip itu sendiri, yang membantu mereka mengetahui apakah ada masalah dalam spesifikasi chip, atau dalam implementasi chip yang sebenarnya dalam perangkat keras. Sebagai contoh, adalah mungkin untuk menulis spesifikasi chip yang akan menghasilkan kebuntuan, 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 naif, dan mereka juga menyertakan kode yang berinteraksi dengan OS sistem host, misalnya untuk menggunakan gambar dan suara.
Mengingat kinerja video game lama yang sangat lambat (NES / SNES, dll.), Emulasi cukup mudah pada sistem modern. Bahkan, bahkan lebih menakjubkan bahwa Anda bisa mengunduh satu set setiap game SNES yang pernah ada atau game Atari 2600 yang pernah ada, mengingat bahwa ketika sistem ini populer memiliki akses gratis ke setiap cartridge akan menjadi mimpi yang menjadi kenyataan.
sumber
Saya tahu bahwa pertanyaan ini agak lama, tetapi saya ingin menambahkan sesuatu ke dalam 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 disebut "UltraHLE" ( artikel WIKIpedia ). UltraHLE, salah satu emulator paling terkenal yang pernah dibuat, meniru game Nintendo 64 komersial (dengan kinerja yang layak di komputer rumah) pada saat itu secara luas dianggap mustahil untuk dilakukan. 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 hal yang mustahil dengan meniru panggilan C library alih-alih panggilan tingkat mesin.
sumber
Yang patut dicermati adalah upaya Imran Nazar untuk menulis emulator Game Boy di JavaScript.
sumber
Setelah membuat emulator saya sendiri dari Microcomputer BBC tahun 80-an (ketik VBeeb ke Google), ada sejumlah hal yang perlu diketahui.
Secara praktis, Anda umumnya ingin menulis untuk kecepatan dan kesetiaan persaingan. 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.
Lebih jauh lagi, Anda harus membatasi apa yang Anda siap tiru, misalnya tidak perlu meniru keadaan tegangan transistor dalam mikroprosesor, tetapi mungkin perlu untuk meniru keadaan set register mikroprosesor.
Secara umum, semakin kecil tingkat detail persaingan, semakin tinggi kesetiaan Anda pada sistem aslinya.
Akhirnya, informasi untuk sistem yang lebih lama mungkin tidak lengkap atau tidak ada. Jadi mendapatkan peralatan asli adalah penting, atau setidaknya memisahkan emulator bagus lain yang telah ditulis orang lain!
sumber
Ya, Anda harus menafsirkan seluruh kekacauan kode mesin biner "dengan tangan". Tidak hanya itu, sebagian besar waktu Anda juga harus mensimulasikan beberapa perangkat keras eksotis yang tidak memiliki padanan pada mesin target.
Pendekatan sederhana adalah menafsirkan instruksi satu per satu. Itu bekerja dengan baik, tetapi lambat. Pendekatan yang lebih cepat adalah kompilasi ulang - menerjemahkan kode mesin sumber ke kode mesin target. Ini lebih rumit, karena sebagian besar instruksi tidak akan memetakan satu-ke-satu. Alih-alih, Anda harus membuat penyelesaian rumit yang melibatkan kode tambahan. Tetapi pada akhirnya itu jauh lebih cepat. Kebanyakan emulator modern melakukan ini.
sumber
... --- ...
- ketiga kode Morse ini mewakili tiga huruf S, O, S." Karena...
merupakan kode yang mewakili huruf "S". Tidak?Saat Anda mengembangkan emulator, Anda menafsirkan unit prosesor yang sedang dikerjakan sistem (Z80, 8080, PS CPU, dll.).
Anda juga perlu meniru semua periferal yang dimiliki sistem (output video, pengontrol).
Anda harus mulai menulis emulator untuk sistem simpel seperti Game Boy tua yang baik (yang menggunakan prosesor Z80, saya tidak salah) ATAU untuk C64.
sumber
Untuk contohnya, lihat http://queue.acm.org/detail.cfm?id=1755886 .
Itu juga akan menunjukkan kepada Anda mengapa Anda 'membutuhkan' CPU multi-GHz untuk meniru yang 1MHz.
sumber
Juga periksa Darek Mihocka's Emulators.com untuk saran hebat tentang pengoptimalan tingkat instruksi untuk JIT, dan banyak barang lainnya untuk membangun emulator yang efisien.
sumber
Saya tidak pernah melakukan sesuatu yang begitu mewah untuk meniru konsol permainan tetapi saya mengambil kursus sekali di mana tugasnya adalah menulis emulator untuk mesin yang dijelaskan dalam Andrew Tanenbaums Structured Computer Organization . Itu menyenangkan dan memberi saya banyak momen aha. Anda mungkin ingin mengambil buku itu sebelum menyelam untuk menulis emulator nyata.
sumber
Nasihat tentang meniru sistem nyata atau hal Anda sendiri? Saya dapat mengatakan bahwa emulator bekerja dengan meniru SELURUH perangkat keras. Mungkin tidak turun ke sirkuit (seperti memindahkan bit seperti yang dilakukan HW. Memindahkan byte adalah hasil akhir sehingga menyalin byte tidak masalah). Emulator sangat sulit dibuat karena ada banyak peretasan (seperti pada efek yang tidak biasa), masalah waktu, dll yang perlu Anda simulasikan. Jika salah satu (input) salah, seluruh sistem dapat melakukan down atau paling tidak memiliki bug / kesalahan.
sumber
The Shared Source Perangkat Emulator berisi kode sumber dapat dibangun untuk emulator PocketPC / Smartphone (Membutuhkan Visual Studio, berjalan pada Windows). Saya bekerja pada V1 dan V2 dari rilis biner.
Ini menangani banyak masalah persaingan: - terjemahan alamat efisien dari virtual tamu ke fisik tamu ke virtual tuan rumah - Kompilasi JIT dari kode tamu - Simulasi perangkat periferal seperti adapter jaringan, layar sentuh dan audio - Integrasi UI, untuk keyboard dan mouse host - simpan / mengembalikan keadaan, untuk simulasi resume dari mode daya rendah
sumber
Untuk menambahkan jawaban yang diberikan oleh @Cody Brocious
Dalam konteks virtualisasi tempat Anda meniru sistem baru (CPU, I / O dll) ke mesin virtual, kita dapat melihat kategori emulator berikut.
Interpretasi: bochs adalah contoh dari interpreter, ini adalah sebuah emulator PC x86, dibutuhkan setiap instruksi dari sistem tamu menerjemahkannya dalam set instruksi lain (dari host host) untuk menghasilkan efek yang diinginkan. Ya, itu sangat lambat, tidak Tembolok apa pun sehingga setiap instruksi melewati siklus yang sama.
Emalator dinamis: Qemu adalah emulator dinamis. Itu dengan terjemahan tamu instruksi juga cache hasil. Bagian terbaik adalah yang mengeksekusi instruksi sebanyak mungkin langsung pada sistem host sehingga emulasi lebih cepat. Juga seperti yang disebutkan oleh Cody, ia membagi kode menjadi blok (1 alur eksekusi tunggal).
Emulator statis: Sejauh yang saya tahu tidak ada emulator statis yang dapat membantu dalam virtualisasi.
sumber
Bagaimana saya akan memulai persaingan.
1.Dapatkan buku yang berbasis pada pemrograman tingkat rendah, Anda akan membutuhkannya untuk sistem operasi "pretend" Nintendo ... game boy ...
2. Dapatkan buku tentang persaingan khusus, dan mungkin pengembangan os. (Anda tidak akan membuat os, tetapi yang paling dekat dengannya.
3. Lihat beberapa emulator open source, terutama yang Anda inginkan untuk membuat emulator.
4. salin cuplikan kode yang lebih kompleks ke dalam IDE / compliler Anda. Ini akan menghemat Anda menulis kode panjang. Inilah yang saya lakukan untuk pengembangan os, gunakan distrik linux
sumber
Saya menulis artikel tentang meniru sistem Chip-8 dalam JavaScript .
Ini adalah tempat yang bagus untuk memulai karena sistemnya tidak terlalu rumit, tetapi Anda masih belajar bagaimana opcodes, stack, register, dll berfungsi.
Saya akan menulis panduan yang lebih panjang segera untuk SEN.
sumber