อีมูเลเตอร์ทำงานอย่างไรและเขียนอย่างไร? [ปิด]


968

อีมูเลเตอร์ทำงานอย่างไร เมื่อฉันเห็นตัวเลียนแบบ NES / SNES หรือ C64 มันทำให้ฉันประหลาดใจ

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

คุณต้องจำลองโปรเซสเซอร์ของเครื่องเหล่านั้นโดยการตีความคำแนะนำการประกอบเฉพาะหรือไม่? มีอะไรอีกบ้างในเรื่องนี้? โดยทั่วไปแล้วพวกเขาได้รับการออกแบบอย่างไร?

คุณสามารถให้คำแนะนำกับผู้ที่สนใจในการเขียนโปรแกรมจำลอง (โดยเฉพาะระบบเกม) ได้หรือไม่?


15
สิ่งที่สำคัญที่สุดที่คุณต้องค้นหาคือ "คู่มือโปรแกรมเมอร์" สำหรับระบบนั้นเนื่องจากรายละเอียด "สัญญา" ระหว่างผู้ขาย HW และโปรแกรมเมอร์และซ่อนรายละเอียดที่ไม่เกี่ยวข้องและสามารถเปลี่ยนแปลงได้ โอกาสของคุณขึ้นอยู่กับความนิยมของระบบ
Uri

155
ทางเลือกของเกมที่ดี
Cristián Romo

2
ใช่ฉันเชื่ออย่างนั้น: en.wikipedia.org/wiki/The_Legend_of_Zelda:_A_Link_to_the_Past
mmcdole

16
สำหรับทุกคนที่สงสัยว่าEmulation vs Simulation
Lazer

8
นับตั้งแต่ครั้งแรกที่ฉันเล่นเกมนั้นฉันสงสัยอยู่เสมอว่าทำไมรูลจึงทิ้งก้อนหินด้วยก้อนหิน "8-Ball" :-)
แม่น้ำวิเวียน

คำตอบ:


1124

การจำลองเป็นพื้นที่ที่มีหลายแง่มุม นี่คือแนวคิดพื้นฐานและส่วนประกอบการทำงาน ฉันจะแบ่งมันออกเป็นชิ้น ๆ แล้วกรอกรายละเอียดผ่านการแก้ไข หลายสิ่งที่ฉันจะอธิบายจะต้องใช้ความรู้เกี่ยวกับการทำงานภายในของโปรเซสเซอร์ - ความรู้การชุมนุมเป็นสิ่งที่จำเป็น หากฉันเข้าใจบางสิ่งเล็กน้อยเกินไปโปรดถามคำถามเพื่อให้ฉันสามารถปรับปรุงคำตอบนี้ได้

แนวคิดพื้นฐาน:

การจำลองทำงานโดยการจัดการพฤติกรรมของโปรเซสเซอร์และส่วนประกอบแต่ละตัว คุณสร้างแต่ละชิ้นส่วนของระบบจากนั้นเชื่อมต่อชิ้นส่วนที่คล้ายกับสายไฟในฮาร์ดแวร์

การจำลองการประมวลผล:

มีสามวิธีในการจัดการการจำลองโปรเซสเซอร์:

  • การตีความ
  • การรวบรวมซ้ำแบบไดนามิก
  • รวบรวมใหม่คงที่

ด้วยพา ธ ทั้งหมดเหล่านี้คุณมีเป้าหมายโดยรวมเหมือนกัน: รันโค้ดบางส่วนเพื่อแก้ไขสถานะโปรเซสเซอร์และโต้ตอบกับ 'ฮาร์ดแวร์' สถานะตัวประมวลผลเป็นการรวมกลุ่มของตัวประมวลผลการลงทะเบียนตัวจัดการขัดจังหวะ ฯลฯ สำหรับเป้าหมายตัวประมวลผลที่กำหนด สำหรับ 6502 คุณจะมีจำนวนของจำนวนเต็ม 8 บิตเป็นตัวแทนของการลงทะเบียน: A, X, Y, PและS; คุณต้องมีการPCลงทะเบียน16 บิต

ด้วยการตีความคุณจะเริ่มที่IP(ตัวชี้คำสั่ง - เรียกอีกอย่างว่าตัวPCนับโปรแกรม) และอ่านคำแนะนำจากหน่วยความจำ รหัสของคุณวิเคราะห์คำสั่งนี้และใช้ข้อมูลนี้เพื่อเปลี่ยนสถานะตัวประมวลผลตามที่ระบุโดยตัวประมวลผลของคุณ ปัญหาหลักของการตีความคือช้ามาก ทุกครั้งที่คุณจัดการกับคำสั่งที่กำหนดคุณจะต้องถอดรหัสและดำเนินการสิ่งที่จำเป็น

ด้วยการคอมไพล์ซ้ำแบบไดนามิกคุณวนซ้ำรหัสเหมือนกับการตีความ แต่แทนที่จะเรียกใช้ opcodes คุณจะสร้างรายการการดำเนินการ เมื่อคุณไปถึงคำสั่งสาขาแล้วคุณจะต้องรวบรวมรายการการดำเนินการนี้ไปยังรหัสเครื่องสำหรับแพลตฟอร์มโฮสต์ของคุณจากนั้นคุณแคชรหัสที่คอมไพล์แล้วและเรียกใช้งาน จากนั้นเมื่อคุณกดกลุ่มคำสั่งที่กำหนดอีกครั้งคุณจะต้องรันโค้ดจากแคช (BTW คนส่วนใหญ่ไม่ได้ทำรายการคำแนะนำจริง ๆ แต่รวบรวมพวกเขาเป็นรหัสเครื่องจักรได้ทันที - นี่ทำให้ยากต่อการปรับให้เหมาะสม แต่มันอยู่นอกขอบเขตของคำตอบนี้เว้นแต่มีคนสนใจพอ)

ด้วยการรวบรวมซ้ำแบบคงที่คุณทำเช่นเดียวกับในการรวบรวมซ้ำแบบไดนามิก แต่คุณตามสาขา คุณต้องสร้างกลุ่มของรหัสที่แสดงถึงรหัสทั้งหมดในโปรแกรมซึ่งสามารถดำเนินการได้โดยไม่มีการรบกวนเพิ่มเติม นี่จะเป็นกลไกที่ยอดเยี่ยมหากไม่ได้มีปัญหาดังต่อไปนี้:

  • รหัสที่ไม่ได้อยู่ในโปรแกรมที่จะเริ่มต้นด้วย (เช่นบีบอัดเข้ารหัสสร้าง / แก้ไขเมื่อรันไทม์ ฯลฯ ) จะไม่ถูกคอมไพล์ใหม่ดังนั้นจึงจะไม่ทำงาน
  • ได้รับการพิสูจน์แล้วว่าการค้นหารหัสทั้งหมดในไบนารีที่กำหนดนั้นเทียบเท่ากับปัญหาการหยุดทำงาน

การรวมกันเหล่านี้เพื่อให้การคอมไพล์ซ้ำแบบคงที่เป็นไปไม่ได้อย่างสมบูรณ์ใน 99% ของกรณี สำหรับข้อมูลเพิ่มเติม Michael Steil ได้ทำการวิจัยที่ยอดเยี่ยมเกี่ยวกับการรวบรวมซ้ำแบบคงที่ซึ่งดีที่สุดที่ฉันเคยเห็น

อีกด้านหนึ่งของการจำลองโปรเซสเซอร์คือวิธีการที่คุณโต้ตอบกับฮาร์ดแวร์ นี่มีสองด้านจริง ๆ :

  • เวลาประมวลผล
  • การจัดการขัดจังหวะ

เวลาประมวลผล:

บางแพลตฟอร์ม - โดยเฉพาะคอนโซลที่อายุมากกว่าเช่น NES, SNES และอื่น ๆ - ต้องการให้อีมูเลเตอร์ของคุณมีเวลาที่เข้มงวดเพื่อให้เข้ากันได้อย่างสมบูรณ์ ด้วย NES คุณจะมี PPU (หน่วยประมวลผลพิกเซล) ซึ่งกำหนดให้ CPU ใส่พิกเซลลงในหน่วยความจำในเวลาที่แม่นยำ หากคุณใช้การตีความคุณสามารถนับรอบและเลียนแบบเวลาที่เหมาะสมได้อย่างง่ายดาย ด้วยการคอมไพล์แบบไดนามิก / คงที่สิ่งต่าง ๆ มีความซับซ้อนมากขึ้น

การจัดการขัดจังหวะ:

การขัดจังหวะเป็นกลไกหลักที่ CPU สื่อสารกับฮาร์ดแวร์ โดยทั่วไปส่วนประกอบฮาร์ดแวร์ของคุณจะบอก CPU เกี่ยวกับสิ่งที่ขัดจังหวะด้วย นี่เป็นวิธีที่ตรงไปตรงมา - เมื่อโค้ดของคุณขว้างอินเทอร์รัปต์ที่กำหนดมาให้คุณดูที่ตารางตัวจัดการอินเทอร์รัปต์และโทรติดต่อกลับที่เหมาะสม

การจำลองฮาร์ดแวร์:

มีสองด้านในการจำลองอุปกรณ์ฮาร์ดแวร์ที่ให้มา:

  • จำลองการทำงานของอุปกรณ์
  • จำลองอุปกรณ์อินเตอร์เฟสจริง

นำกรณีของฮาร์ดไดรฟ์ ฟังก์ชั่นถูกจำลองด้วยการสร้างที่เก็บข้อมูลสำรองรูทีนการอ่าน / เขียน / รูปแบบ ฯลฯ ส่วนนี้โดยทั่วไปจะตรงไปตรงมามาก

อินเทอร์เฟซที่แท้จริงของอุปกรณ์นั้นซับซ้อนกว่าเล็กน้อย นี่คือการรวมกันของการลงทะเบียนหน่วยความจำที่แมปบางส่วน (เช่นส่วนของหน่วยความจำที่อุปกรณ์มองหาการเปลี่ยนแปลงเพื่อส่งสัญญาณ) และการขัดจังหวะ สำหรับฮาร์ดไดรฟ์คุณอาจมีพื้นที่หน่วยความจำที่แมปซึ่งคุณวางคำสั่งอ่านเขียน ฯลฯ จากนั้นอ่านข้อมูลนี้กลับ

ฉันจะลงรายละเอียดเพิ่มเติม แต่มีหลายวิธีที่คุณสามารถไปกับมันได้ หากคุณมีคำถามเฉพาะที่นี่โปรดถามและฉันจะเพิ่มข้อมูล

แหล่งข้อมูล:

ฉันคิดว่าฉันได้รับที่ดีงามบทนำที่นี่ แต่มีตันในพื้นที่เพิ่มเติม ฉันมีความสุขมากกว่าที่จะช่วยตอบคำถามใด ๆ ฉันคลุมเครือมากในเรื่องนี้เพราะความซับซ้อนอันยิ่งใหญ่

ลิงค์บังคับวิกิพีเดีย:

ทรัพยากรการจำลองทั่วไป:

  • Zophar - นี่คือที่ที่ฉันเริ่มต้นด้วยการจำลองการดาวน์โหลดอีมูเลเตอร์แรกและในที่สุดก็ปล้นเอกสารที่มีขนาดใหญ่มาก นี่เป็นแหล่งข้อมูลที่ดีที่สุดที่คุณสามารถมีได้
  • NGEmu - มีทรัพยากรไม่มากนักโดยตรง แต่ฟอรัมของพวกเขานั้นไม่สามารถเอาชนะได้
  • RomHacking.net - ส่วนเอกสารมีทรัพยากรเกี่ยวกับสถาปัตยกรรมเครื่องสำหรับคอนโซลที่ได้รับความนิยม

โครงการจำลองเพื่อการอ้างอิง:

  • IronBabel - นี่คือแพลตฟอร์มการจำลองสำหรับ. NET, เขียนด้วย Nemerle และคอมไพล์โค้ดใหม่เป็น C # ได้ทันที คำเตือน: นี่คือโครงการของฉันดังนั้นโปรดอภัยเสียบไร้ยางอาย
  • BSnes - โปรแกรมจำลอง SNES ที่ยอดเยี่ยมพร้อมเป้าหมายความแม่นยำที่สมบูรณ์แบบ
  • MAME - ตัวจำลองอาร์เคด การอ้างอิงที่ดี
  • 6502asm.com - นี่คืออีมูเลเตอร์ JavaScript 6502 พร้อมฟอรัมเล็ก ๆ
  • dynarec'd 6502asm - นี่คือการแฮ็กเล็กน้อยที่ฉันทำในหนึ่งหรือสองวัน ฉันเอาอีมูเลเตอร์ที่มีอยู่จาก 6502asm.com และเปลี่ยนเป็นโค้ดซ้ำอีกครั้งแบบไดนามิกเป็น JavaScript เพื่อเพิ่มความเร็วสูง

การอ้างอิงการคอมไพล์ซ้ำตัวประมวลผล:

  • การวิจัยลงใน recompilation คงทำโดยไมเคิล Steil (อ้างถึงข้างต้น) culminated ในบทความนี้และคุณสามารถหาแหล่งที่มาและเช่นที่นี่

ภาคผนวก:

เป็นเวลานานกว่าหนึ่งปีแล้วตั้งแต่คำตอบนี้ถูกส่งมาและด้วยความสนใจทั้งหมดที่ได้รับฉันคิดว่าถึงเวลาที่จะต้องปรับปรุงบางสิ่ง

บางทีสิ่งที่น่าตื่นเต้นที่สุดในการลอกเลียนแบบในตอนนี้ก็คือlibcpuซึ่งเริ่มโดย Michael Steil มันเป็นไลบรารีที่มีวัตถุประสงค์เพื่อสนับสนุนคอร์ CPU จำนวนมากซึ่งใช้ LLVM สำหรับการคอมไพล์ใหม่ (สแตติกและไดนามิก!) มันมีศักยภาพมากและฉันคิดว่ามันจะทำสิ่งที่ดีสำหรับการลอกเลียนแบบ

emu-docsก็ถูกนำมาให้ฉันด้วยเช่นกันซึ่งเป็นที่เก็บเอกสารระบบที่ยอดเยี่ยมซึ่งมีประโยชน์มากสำหรับการจำลอง ฉันไม่ได้ใช้เวลามากที่นั่น แต่ดูเหมือนว่าพวกเขามีทรัพยากรที่ดีมากมาย

ฉันดีใจที่โพสต์นี้มีประโยชน์และฉันหวังว่าฉันจะลาออกและจบหนังสือของฉันในหัวข้อภายในสิ้นปี / ต้นปีหน้า


37
นี่เป็นคำตอบที่ยิ่งใหญ่แล้ว หากคุณสามารถชี้ให้ฉันเห็นถึงทรัพยากรใด ๆ เช่นกันในตอนท้ายของเรื่องนี้ก็จะได้รับการชื่นชม ฉันกำลังดูว่าระบบ SNES หรือ NES อาจเลียนแบบและทำให้เป็นโครงการภาคการศึกษาของฉัน
mmcdole

8
อย่างแน่นอน ฉันจะรวบรวมรายการทรัพยากรที่ดี หากพวกคุณมีคำขอเฉพาะฉันจะทำอย่างเต็มที่เพื่อเติมเต็ม
Cody Brocious

3
@thenonhacker โครงการ IronBabel ที่อ้างถึงในส่วนทรัพยากรของฉันเป็นของฉัน (ปลั๊กไร้ยางอายถูกทำเครื่องหมาย;))
Cody Brocious

1
"มันได้รับการพิสูจน์แล้วว่าการค้นหารหัสทั้งหมดในไบนารีที่กำหนดนั้นเทียบเท่ากับปัญหาการหยุดชะงัก" - โปรดอ้างอิง? หรือควรเป็น "มันได้รับการพิสูจน์แล้วว่าการค้นหารหัสทั้งหมดในไบนารีใด ๆ ที่ให้นั้นเทียบเท่ากับปัญหาการหยุดชะงัก"? ยังไม่สามารถเข้าถึงกระดาษของ Steil :-(
squelart

4
คุณพูดถึงคุณกำลังเขียนหนังสือ คุณช่วยบอกเราเกี่ยวกับสิ่งนั้นได้ไหม ฉันคนหนึ่งสนใจที่จะอ่านมัน
alex

126

ผู้ชายที่ชื่อ Victor Moya del Barrio เขียนวิทยานิพนธ์ของเขาในหัวข้อนี้ ข้อมูลที่ดีมากมายใน 152 หน้า คุณสามารถดาวน์โหลดไฟล์ PDF ที่นี่

หากคุณไม่ต้องการที่จะลงทะเบียนกับScribdคุณสามารถ google สำหรับชื่อไฟล์ PDF, "การศึกษาของเทคนิคในการเขียนโปรแกรมการแข่งขัน" มีแหล่งข้อมูลที่แตกต่างกันสองสามอย่างสำหรับ PDF


43

การจำลองอาจดูน่ากลัว แต่จริงๆแล้วง่ายกว่าการจำลอง

ตัวประมวลผลใด ๆ มักมีข้อกำหนดที่เป็นลายลักษณ์อักษรที่อธิบายสถานะการโต้ตอบ ฯลฯ

หากคุณไม่สนใจเกี่ยวกับประสิทธิภาพเลยคุณสามารถเลียนแบบตัวประมวลผลรุ่นเก่าที่สุดได้อย่างง่ายดายโดยใช้โปรแกรมเชิงวัตถุที่หรูหรามาก ตัวอย่างเช่นตัวประมวลผล X86 จะต้องมีบางสิ่งบางอย่างในการรักษาสถานะของการลงทะเบียน (ง่าย) สิ่งที่จะรักษาสถานะของหน่วยความจำ (ง่าย) และสิ่งที่จะใช้คำสั่งขาเข้าแต่ละครั้งและนำไปใช้กับสถานะปัจจุบันของเครื่อง หากคุณต้องการความแม่นยำอย่างแท้จริงคุณจะต้องจำลองการแปลหน่วยความจำแคช ฯลฯ แต่ก็สามารถทำได้

ในความเป็นจริงผู้ผลิตไมโครชิพและซีพียูจำนวนมากทำการทดสอบโปรแกรมกับตัวจำลองของชิปและต่อกับตัวชิปเองซึ่งจะช่วยให้พวกเขาทราบว่ามีปัญหาในข้อกำหนดเฉพาะของชิปหรือในการนำชิปมาใช้จริงในฮาร์ดแวร์ ตัวอย่างเช่นมีความเป็นไปได้ที่จะเขียนข้อมูลจำเพาะของชิปที่จะส่งผลให้เกิดการหยุดชะงักและเมื่อกำหนดเวลาเกิดขึ้นในฮาร์ดแวร์สิ่งสำคัญคือต้องดูว่าสามารถทำซ้ำข้อมูลจำเพาะในข้อมูลจำเพาะได้หรือไม่

แน่นอนว่าอีมูเลเตอร์สำหรับวิดีโอเกมมักจะสนใจเรื่องประสิทธิภาพดังนั้นจึงไม่ใช้การปรับใช้ที่ไร้เดียงสาและพวกเขายังมีรหัสที่เชื่อมต่อกับระบบปฏิบัติการของระบบโฮสต์เช่นใช้การวาดภาพและเสียง

เมื่อพิจารณาถึงประสิทธิภาพที่ช้ามากของวิดีโอเกมเก่า (NES / SNES เป็นต้น) การเลียนแบบค่อนข้างง่ายสำหรับระบบที่ทันสมัย ในความเป็นจริงมันวิเศษยิ่งกว่าที่คุณจะสามารถดาวน์โหลดเกม SNES ทุกเกมได้ตลอดเวลาหรือเกม Atari 2600 ใด ๆ ที่เคยมีมาเมื่อพิจารณาว่าเมื่อระบบเหล่านี้ได้รับความนิยมและการเข้าถึงตลับหมึกฟรีทุกครั้ง


1
ความแตกต่างระหว่างการจำลองและการจำลองคืออะไร?
Wei Hu

2
@Wei: โดยทั่วไปผู้เลียนแบบควรจะทำตัวเหมือน "ภายนอก" เหมือนระบบที่เลียนแบบ แต่ไม่มีอะไรจะพูดว่ามันต้องถูกนำไปใช้ในลักษณะเดียวกัน ตัวจำลองถูกนำไปใช้ในลักษณะที่เลียนแบบระบบจำลองและผลที่ได้จะมีลักษณะเหมือนมัน
Uri

เมื่อคุณเห็น "เครื่องมือจำลอง" คิดว่ามันคล้ายกันในขณะที่เครื่องจำลอง "จำลอง"
mP


29

ฉันรู้ว่าคำถามนี้ค่อนข้างเก่า แต่ฉันอยากจะเพิ่มบางสิ่งลงในการสนทนา คำตอบส่วนใหญ่อยู่ตรงกลางรอบตัวเลียนแบบตีความคำสั่งเครื่องของระบบที่เลียนแบบ

อย่างไรก็ตามมีข้อยกเว้นที่รู้จักกันดีในเรื่องนี้ซึ่งเรียกว่า "UltraHLE" ( WIKIpedia article) ) UltraHLE หนึ่งในผู้เลียนแบบที่มีชื่อเสียงที่สุดที่เคยสร้างเกม Nintendo 64 เชิงพาณิชย์จำลอง (พร้อมประสิทธิภาพที่ดีในคอมพิวเตอร์ที่บ้าน) ในเวลาที่มันถูกพิจารณาว่าเป็นไปไม่ได้ ตามความเป็นจริงแล้ว Nintendo ยังคงผลิตเกมใหม่สำหรับ Nintendo 64 เมื่อ UltraHLE ถูกสร้างขึ้น!

เป็นครั้งแรกที่ฉันเห็นบทความเกี่ยวกับอีมูเลเตอร์ในนิตยสารสิ่งพิมพ์ที่ฉันเคยเห็นพวกเขาพูดคุยกันทางเว็บเท่านั้น

แนวคิดของ UltraHLE คือการทำให้เป็นไปไม่ได้โดยการจำลองการโทร C แทนการเรียกระดับเครื่อง


22

สิ่งที่ควรค่าแก่การดูคือความพยายามของ Imran Nazar ในการเขียนตัวจำลองGameboyใน JavaScript


1
เราจะรับคำแนะนำ opcode แบบ raw สำหรับเกม Gameboy ได้อย่างไร
Pacerier

มีอุปกรณ์จำนวนหนึ่งขายใน 'ตลาดมืด' คุณจะไม่พบพวกมันในร้านค้าสำคัญในโลกที่พัฒนาแล้ว อุปกรณ์เหล่านี้สามารถคัดลอกคำแนะนำจากคาร์ทริดจ์เกมไปยังไฟล์ที่มักเรียกว่า "ROM" Google "Gameboy Roms" แต่ระวังลิงค์ที่ไม่ปลอดภัยและไซต์โจมตี!
Vivian River

18

หลังจากได้สร้างอีมูเลเตอร์จำลองของฉันเองของ BBC Microcomputer ของยุค 80 (พิมพ์ VBeeb ลงใน Google) มีหลายสิ่งที่ต้องรู้

  • คุณไม่ได้เลียนแบบของจริงเช่นนี้ซึ่งจะเป็นแบบจำลอง แต่คุณเลียนแบบรัฐของรัฐตัวอย่างที่ดีคือเครื่องคิดเลขของจริงมีปุ่มหน้าจอตัวเรือน ฯลฯ แต่เพื่อเลียนแบบเครื่องคิดเลขคุณเพียงแค่เลียนแบบปุ่มว่าขึ้นหรือลงซึ่งส่วนของ LCD เปิดอยู่เป็นต้นโดยทั่วไปชุดตัวเลข เป็นตัวแทนของทุกสิ่งที่สามารถเปลี่ยนแปลงได้ในเครื่องคิดเลข
  • คุณต้องการเพียงอินเทอร์เฟซของอีมูเลเตอร์เพื่อให้ปรากฏและทำงานเหมือนของจริง ยิ่งเชื่อว่านี่คือการเลียนแบบยิ่งใกล้ สิ่งที่เกิดขึ้นเบื้องหลังอาจเป็นอะไรก็ได้ที่คุณชอบ แต่เพื่อความสะดวกในการเขียนอีมูเลเตอร์จึงมีการทำแผนที่ทางจิตที่เกิดขึ้นระหว่างระบบจริงเช่นชิปจอแสดงผลแป้นพิมพ์แผงวงจรและรหัสคอมพิวเตอร์ที่เป็นนามธรรม
  • เพื่อเลียนแบบระบบคอมพิวเตอร์วิธีที่ง่ายที่สุดในการแบ่งมันเป็นชิ้นเล็ก ๆ และเลียนแบบชิ้นเหล่านั้นแยกกัน จากนั้นร้อยลอตรวมเข้าด้วยกันสำหรับผลิตภัณฑ์สำเร็จรูป เหมือนชุดกล่องดำที่มีอินพุตและเอาต์พุตซึ่งให้ยืมตัวเองได้อย่างงดงามสำหรับการเขียนโปรแกรมเชิงวัตถุ คุณสามารถแบ่งย่อยเหล่านี้เพิ่มเติมเพื่อทำให้ชีวิตง่ายขึ้น

โดยทั่วไปคุณกำลังมองหาการเขียนเพื่อความเร็วและความเที่ยงตรงของการจำลอง เนื่องจากซอฟต์แวร์ในระบบเป้าหมายจะ (อาจ) ทำงานช้ากว่าฮาร์ดแวร์ดั้งเดิมในระบบต้นทาง นั่นอาจ จำกัด การเลือกภาษาการเขียนโปรแกรมคอมไพเลอร์ระบบเป้าหมาย ฯลฯ
นอกจากนี้คุณต้อง จำกัด สิ่งที่คุณเตรียมที่จะเลียนแบบตัวอย่างเช่นไม่จำเป็นต้องจำลองสถานะแรงดันไฟฟ้าของทรานซิสเตอร์ในไมโครโปรเซสเซอร์ แต่อาจจำเป็น เพื่อจำลองสถานะของชุดรีจิสเตอร์ของไมโครโปรเซสเซอร์
โดยทั่วไปเมื่อพูดถึงระดับรายละเอียดของการจำลองที่น้อยลงความเที่ยงตรงที่มากขึ้นคุณจะไปที่ระบบดั้งเดิม
ในที่สุดข้อมูลสำหรับระบบเก่าอาจไม่สมบูรณ์หรือไม่มีอยู่จริง ดังนั้นการยึดอุปกรณ์ดั้งเดิมจึงเป็นสิ่งจำเป็นหรืออย่างน้อยก็ต้องแยกอีมูเลเตอร์ที่ดีอื่น ๆ ที่ผู้อื่นเขียน!


17

ใช่คุณต้องตีความระเบียบรหัสเครื่องทั้งไบนารีด้วยมือ "" ไม่เพียงแค่นั้นเวลาส่วนใหญ่คุณต้องจำลองฮาร์ดแวร์แปลกใหม่บางอย่างที่ไม่ได้เทียบเท่ากับเครื่องเป้าหมาย

วิธีการง่าย ๆ คือการตีความคำแนะนำแบบหนึ่งต่อหนึ่ง มันใช้งานได้ดี แต่มันช้า วิธีที่เร็วกว่าคือการคอมไพล์ซ้ำ - แปลรหัสเครื่องต้นทางไปยังรหัสเครื่องเป้าหมาย สิ่งนี้ซับซ้อนกว่าเนื่องจากคำแนะนำส่วนใหญ่จะไม่จับคู่แบบหนึ่งต่อหนึ่ง แต่คุณจะต้องทำการแก้ไขอย่างละเอียดที่เกี่ยวข้องกับรหัสเพิ่มเติม แต่ในท้ายที่สุดมันเร็วกว่ามาก ตัวเลียนแบบที่ทันสมัยที่สุดทำเช่นนี้


1
สิ่งที่แย่ที่สุดคือเอกสารที่หายไปโดยไกล เมื่อคุณค้นพบว่าแกน Z80 ที่ได้รับการดัดแปลงใน GameBoy Color นั้นมีการตั้งค่าสถานะที่ไม่มีเอกสารที่เกมที่คุณกำลังทดสอบใช้อยู่นั้นทำให้คุณเริ่มหมดศรัทธา
Callum Rogers

1
Pet peeve: เป็นรหัสเครื่อง(เอกพจน์) ไม่ใช่รหัสเครื่อง(พหูพจน์); เช่นเดียวกับของรหัสมอร์สไม่ได้รหัสมอร์ส
Lawrence Dol

1
@Vilx: อันที่จริงไม่ใช่ - คำว่า "machine code" ซึ่งอ้างถึงชุดคำสั่งสำหรับ CPU นั้นมีการใช้งานมาตั้งแต่เริ่มก่อตั้งซอฟต์แวร์และไม่ได้เป็นพหูพจน์ มันหมายถึง " ชุดคำสั่ง" เป็นรูปเอกพจน์ไม่ใช่รูปแบบพหูพจน์ "คำแนะนำ" เช่นเดียวกับรหัสโปรแกรมรหัสมอร์ส ฯลฯ การใช้รูปแบบพหูพจน์ได้พุ่งเข้ามาจากการใช้ในทางที่ผิดโดยทั่วไปโดยผู้ที่พูดภาษาอังกฤษเป็นภาษาที่สอง
Lawrence Dol

1
@ ซอฟต์แวร์ Monkey - แต่ฉันไม่สามารถใช้คำว่า "code" เพื่ออ้างถึงไอเท็มเดี่ยวจากเซตได้หรือไม่ ตัวอย่างเช่น: " ... --- ...- รหัสมอร์สสามตัวนี้เป็นตัวแทนของตัวอักษรสามตัว S, O, S. " เพราะ...เป็นรหัสที่ใช้แทนตัวอักษร "S" ไม่มี?
Vilx-

1
ไม่มีรหัสคำนามนับไม่ได้มันไม่มีรูปพหูพจน์เช่นน้ำหรือทราย ..
อีวาน

15

เมื่อคุณพัฒนาอีมูเลเตอร์คุณกำลังตีความชุดตัวประมวลผลที่ระบบกำลังทำงานอยู่ (Z80, 8080, PS CPU ฯลฯ )

คุณต้องจำลองอุปกรณ์ต่อพ่วงทั้งหมดที่ระบบมี (เอาท์พุทวิดีโอคอนโทรลเลอร์)

คุณควรเริ่มเขียนอีมูเลเตอร์สำหรับระบบ simpe เช่นGame Boy ตัวเก่าที่ดี(ที่ใช้โปรเซสเซอร์ Z80 ฉันไม่ผิดพลาด) หรือสำหรับ C64


9
C64 เป็นระบบ "ง่าย"? ในขณะที่ 6510 นั้นค่อนข้างง่าย (เมื่อคุณครอบคลุม opcodes ที่ไม่อยู่ในรายการ) ชิพเสียง (SID) และวิดีโอ (VIC) ล้วนแต่เรียบง่าย เพื่อให้บรรลุความเข้ากันได้ในระดับที่เหมาะสมคุณจะต้องจำลองพวกเขา - ข้อบกพร่องของฮาร์ดแวร์และทั้งหมด
moobaa

10

ตัวจำลองนั้นสร้างได้ยากมากเนื่องจากมีแฮ็กจำนวนมาก (เช่นเอฟเฟกต์ผิดปกติ) ปัญหาเกี่ยวกับเวลา ฯลฯ ที่คุณต้องจำลอง

สำหรับตัวอย่างนี้ให้ดูที่http://queue.acm.org/detail.cfm?id=1755886 http://queue.acm.org/detail.cfm?id=1755886

สิ่งนี้จะแสดงให้คุณเห็นว่าทำไมคุณถึงต้องการ Multi-GHz CPU สำหรับการจำลอง 1MHz


9

ตรวจสอบEmulators.comของ Darek Mihocka's สำหรับคำแนะนำที่ดีในการเพิ่มประสิทธิภาพระดับการเรียนการสอนสำหรับ JIT และสารพัดอื่น ๆ ในการสร้างอีมูเลเตอร์ที่มีประสิทธิภาพ


7

ฉันไม่เคยทำอะไรเพื่อให้เป็นแฟนซีที่จะเลียนแบบเกมคอนโซล แต่ผมไม่ใช้หลักสูตรครั้งที่ได้รับมอบหมายคือการเขียนโปรแกรมจำลองสำหรับเครื่องที่อธิบายไว้ในแอนดรู Tanenbaums โครงสร้างองค์การคอมพิวเตอร์ มันสนุกและให้เวลาฉันได้มากเลย คุณอาจต้องการที่จะหยิบหนังสือเล่มนั้นก่อนที่จะดำน้ำในการเขียนโปรแกรมจำลองที่แท้จริง


4

คำแนะนำในการเลียนแบบระบบจริงหรือของคุณเอง? ฉันสามารถพูดได้ว่าอีมูเลเตอร์ทำงานโดยเลียนแบบฮาร์ดแวร์ทั้งหมด อาจไม่ถึงวงจร (เช่นการเคลื่อนย้ายบิตรอบ ๆ อย่าง HW จะทำได้การย้ายไบต์เป็นผลลัพธ์สุดท้ายดังนั้นการคัดลอกไบต์ก็ใช้ได้) ตัวจำลองนั้นสร้างได้ยากมากเนื่องจากมีแฮ็กจำนวนมาก (เช่นเอฟเฟกต์ผิดปกติ) ปัญหาเกี่ยวกับเวลา ฯลฯ ที่คุณต้องจำลอง หากชิ้นส่วนหนึ่ง (อินพุต) ไม่ถูกต้องทั้งระบบสามารถทำลงได้หรืออย่างดีที่สุดมีข้อบกพร่อง / ผิดพลาด


4

มาใช้ร่วมกัน Emulator อุปกรณ์มีรหัสที่มา buildable เพื่อจำลอง PocketPC / มาร์ทโฟน (ต้องใช้ Visual Studio, ทำงานบน Windows) ฉันทำงานกับ V1 และ V2 ของไบนารีรีลีส

มันจัดการกับปัญหาการจำลองหลายอย่าง: - การแปลที่อยู่อย่างมีประสิทธิภาพจากแขกเสมือนเป็นแขกรับเชิญทางกายภาพเพื่อโฮสต์เสมือน - รวบรวม JIT ของรหัสแขก - จำลองอุปกรณ์ต่อพ่วงเช่นอะแดปเตอร์เครือข่ายหน้าจอสัมผัสและเสียง - การรวม UI สำหรับคีย์บอร์ดโฮสต์และเมาส์ - บันทึก / กู้คืนสถานะสำหรับการจำลองเรซูเม่จากโหมดพลังงานต่ำ


1

ในการเพิ่มคำตอบที่ได้รับจาก @Cody Brocious
ในบริบทของการจำลองเสมือนซึ่งคุณจำลองระบบใหม่ (CPU, I / O ฯลฯ ) ไปยังเครื่องเสมือนเราสามารถดูหมวดจำลองต่อไปนี้

การแปลความหมาย: bochs เป็นตัวอย่างของล่ามมันเป็นอีมูเลเตอร์ x86 พีซีใช้คำสั่งจากระบบแขกแต่ละคนแปลมันในชุดคำสั่งอื่น (ของโฮสต์ ISA) เพื่อสร้างเอฟเฟกต์ที่ตั้งใจไว้มันช้ามากมันไม่ได้เลย ไม่แคชอะไรเลยดังนั้นทุกคำสั่งจะผ่านรอบเดียวกัน

Dynamic emalator: Qemu เป็นโปรแกรมจำลองแบบไดนามิก การแปลแบบทันทีของคำสั่งของแขกยังเก็บผลลัพธ์ส่วนที่ดีที่สุดคือการประมวลผลคำแนะนำให้มากที่สุดโดยตรงบนระบบโฮสต์เพื่อให้การจำลองนั้นเร็วขึ้น ตามที่ Cody กล่าวถึงมันจะแบ่งรหัสออกเป็นบล็อก (การประมวลผล 1 ครั้ง)

ตัวจำลองแบบคงที่: เท่าที่ฉันรู้ไม่มีตัวจำลองแบบคงที่ที่มีประโยชน์ในการจำลองเสมือน


1

ฉันจะเริ่มเลียนแบบได้อย่างไร

1. รับหนังสือจากการเขียนโปรแกรมระดับต่ำคุณจะต้องใช้สำหรับระบบปฏิบัติการ "เสแสร้ง" ของ Nintendo ... เกมบอย ...

2. รับหนังสือเกี่ยวกับการจำลองโดยเฉพาะและอาจจะเป็นการพัฒนาระบบปฏิบัติการ (คุณจะไม่สร้างระบบปฏิบัติการ แต่จะใกล้เคียงที่สุด

3. ดูอีมูเลเตอร์โอเพ่นซอร์สบางตัวโดยเฉพาะอย่างยิ่งระบบที่คุณต้องการสร้างอีมูเลเตอร์

4. คัดลอกโค้ดที่ซับซ้อนมากขึ้นไปยัง IDE / compliler ของคุณ วิธีนี้จะช่วยให้คุณเขียนรหัสยาว ๆ ได้ นี่คือสิ่งที่ฉันทำเพื่อการพัฒนาระบบปฏิบัติการใช้ย่านของลินุกซ์


1

ฉันเขียนบทความเกี่ยวกับการลอกเลียนแบบ Chip-8 ใน JavaScriptJavaScript

มันเป็นจุดเริ่มต้นที่ยอดเยี่ยมเนื่องจากระบบไม่ซับซ้อนมาก แต่คุณยังคงได้เรียนรู้วิธีการทำงานของ opcodes, stack, register, etc

ฉันจะเขียนคำแนะนำที่ยาวขึ้นสำหรับ NES ในไม่ช้า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.