DIY افعل ذلك بنفسك وحدة التحكم في اللعبة

صورة


هذا المنشور هو مقدمة لمقاطع الفيديو الخاصة بوحدة التحكم "محلية الصنع" المصنوعة من البداية. كنت مستوحاة من كل من لوحات المفاتيح الرجعية والعينات الحديثة ، ولكن حصلت على الهندسة المعمارية الخاصة بي. أخبرني أصدقائي باستمرار أنني يجب أن أتحدث عن مشروعي ، وألا أفعل كل شيء على وجه الحصر "من أجل نفسي" ، لذلك أنا هنا أقوم بنشر هذا المنشور.


الاهتمام ، هذه ترجمة


كيف بدأ كل شيء


اسمي سيرجيو فييرا ، لقد نشأت في البرتغال في الثمانينيات والتسعينيات من القرن الماضي ، ولدي حنين طويل للألعاب القديمة ، خاصة بالنسبة للجيل الثالث والرابع من وحدات التحكم.


قبل بضع سنوات ، قررت أن أفهم بشكل أفضل الإلكترونيات ومحاولة إنشاء بادئة خاصة بي.


من خلال المهنة ، أنا مبرمج ولم يكن لدي أي خبرة كمهندس إلكتروني ، باستثناء (ولا ينبغي اعتباره) ترقيات مستقلة لـ destkop.


رغم أنني لم تكن لدي أي خبرة ، إلا أنني قلت لنفسي "لماذا لا؟" ، لقد اشتريت عدة كتب وعدة مجموعات إلكترونية وبدأت الدراسة بناءً على مشاعري حول ما يستحق الدراسة.


أردت أن أصنع بادئة مماثلة لتلك التي تسبب لي مشاعر الحنين ، أردت شيئًا بين NES و Super Nintendo ، أو ربما بين نظام Sega Master System و Mega Drive .


تحتوي هذه المفاتيح على وحدة المعالجة المركزية (CPU) وشريحة فيديو أصلية (لم يتم تسميتها باسم وحدة معالجة الرسومات (GPU)) وشريحة صوت مدمجة وأحيانًا خارجية.


تم توزيع الألعاب على الخراطيش ، والتي كانت بشكل عام امتدادات للحديد ، وأحيانًا مجرد رقائق ROM ، وأحيانًا كانت تحتوي على مكونات إضافية.


كانت الخطة الأصلية هي إنشاء بادئة ذات الخصائص التالية:


  • بدون مضاهاة ، يجب أن تعمل الألعاب والبرامج على أجهزة حقيقية ، وليس بالضرورة في تلك الأوقات ، ولكن بالسرعة الكافية للمهمة ، ولا شيء أكثر من ذلك.
  • مع وحدة المعالجة المركزية الرجعية الحقيقية.
  • مع إخراج التلفزيون التناظرية.
  • مع الصوت
  • مع دعم تحكم مزدوج
  • التمرير يصبح و الرسوم المتحركة العفاريت
  • مع ميزات لدعم ألعاب النظام الأساسي مثل Mario ، وبالطبع جميع أنواع الألعاب الأخرى.
  • مع تنزيل الألعاب والبرامج من بطاقات SD.

لماذا بطاقات SD ، وليس الخراطيش ، حسنًا ، إنها أكثر عملية بكثير ، يمكنك نسخها من جهاز الكمبيوتر الخاص بك. وستعني الخراطيش ، أولاً ، مزيدًا من الحديد في جهاز فك التشفير ، وثانيًا ، إنتاج الحديد لكل برنامج.


إنتاج


إشارة الفيديو


أول شيء فعلته هو إنشاء إشارة فيديو.


تحتوي أي وحدة تحكم في الفترة التي أخذت كعينة على العديد من رقائق الرسومات الخاصة ، مما يعني أن جميعها لديها مواصفات مختلفة.
لهذا السبب ، لم أكن أرغب في استخدام شريحة رسومات جاهزة ، فقد أردت أن تحتوي وحدة التحكم على مواصفات رسومات فريدة. وبما أنني لم أتمكن من إنشاء شريحة الرسوم البيانية الخاصة بي ، وفي ذلك الوقت لم أستطع استخدام FPGA ، قررت أن أقصر نفسي على توليد إشارة بيانية برمجية باستخدام متحكم دقيق 8 بتات و 20 ميغا هرتز.


هذا ليس كثيرًا ، وهو مجرد حل قوي بما فيه الكفاية للرسومات من المستوى الذي كنت مهتمًا به.


وهكذا ، بدأت باستخدام متحكم Atmega644 بنقاء 20 ميجاهرتز لإنشاء إشارة فيديو PAL للتلفزيون. اضطررت إلى التغلب على بروتوكول PAL لأن الشريحة نفسها لا تعرف كيفية القيام بذلك.


imageVPU اختبار 1


imageVPU اختبار 2


ينتج متحكم الألوان 8 بت (RGB332 ، 3 بت أحمر ، 3 بت أخضر و 2 أزرق) وتحول DAC السلبي كل ذلك إلى RGB. لحسن الحظ في البرتغال ، تم تجهيز جميع أجهزة التلفزيون تقريبًا بموصل SCART وهي تدعم إدخال RGB.


النظام الفرعي للرسومات الصحيح


نظرًا لأن المتحكم قوي جدًا ، وقررت استخدامه حصريًا لإنشاء إشارة فيديو (أطلق عليها اسم VPU - وحدة معالجة الفيديو) ، ثم قررت تنظيم مخزن مؤقت مزدوج في نفس الوقت.


اتضح أن المتحكم الثاني (PPU ، وحدة معالجة الصور ، رقاقة Atmega1284 أيضًا عند 20 ميجاهرتز) أنتج صورة في شريحة ذاكرة الوصول العشوائي 1 (أطلق عليها VRAM1) ، وأرسلت الشريحة الأولى محتويات الشريحة الثانية (VRAM2) إلى التلفزيون في نفس الوقت.


بعد إطار واحد ، وإطاران في نظام PAL هو 1/25 من الثانية ، يقوم VPU بتبديل VRAMs ويتم تبديلهما ، وتنتج وحدة PPU صورة في VRAM2 ، وتقوم وحدة VPU بإفلات VRAM1 من إخراج التلفزيون.


لقد تبين أن بطاقة الفيديو معقدة للغاية لأنني اضطررت إلى استخدام أجهزة خارجية حتى يتسنى لكل من المتحكمات الدقيقة استخدام كلاً من وحدات الذاكرة وتسريع الوصول إلى ذاكرة الوصول العشوائي ، لأنه يحتوي أيضًا على ضجيج بت ، لذا اضطررت إلى إضافة 74 مجموعة شرائح مثل عدادات ومحددات خطوط وأجهزة إرسال واستقبال وما إلى ذلك. .


تبين أيضًا أن البرامج الثابتة لـ VPU و PPU كانت مرهقة لأنني اضطررت إلى كتابة الكثير من التعليمات البرمجية للحصول على أقصى سرعة من الرسومات. في البداية تم كتابة كل شيء في المجمع ، ثم تمت إعادة كتابة جزء في C.


imageVideo مجلس 1


imageVideo مجلس 2


نتيجة لذلك ، تقوم وحدة PPU بإنشاء صورة بحجم 224 × 192 بكسل ، والتي يتم إرسالها بعد ذلك إلى التلفزيون عبر VPU. قد تجد دقة منخفضة ، لكنها في الواقع تقارب لوحات المفاتيح الموجودة في ذلك الوقت ، عادة ما تكون 256x224. دقة أقل قليلاً ، لكن سمحت لي بإضافة المزيد من الميزات التي يتمكن النظام من حسابها في إطار واحد.


كما في الأيام الخوالي ، تمتلك PPU آلياتها الصلبة الخاصة التي يجب أن تكون قادرًا على استخدامها. يتم تقديم الخلفية (الخلفية) من 8x8 حرفًا ، وتسمى أيضًا البلاط. اتضح أن حجم الخلفية هو 28x24 البلاط.


بحيث يمكن التمرير للخلف بسلاسة ، بكسل بالبكسل ، قمت بذلك هناك 4 شاشات افتراضية ، كل من مربعات 28 × 24 تمر بالذاكرة بالتتابع ويتم لفها حول بعضها البعض ، في الصورة يكون أكثر وضوحًا.


imageBackground


imageVirtual الخلفية


في الجزء العلوي من الخلفية ، يمكن لـ PPU تقديم 64 sprites والتي يمكن أن يكون ارتفاعها أو عرضها 8 أو 16 بكسل ، أي 1 أو 2 أو 4 بلاطات ويمكن أيضًا قلبها أفقياً و / أو رأسياً.


في الجزء العلوي من الجزء الخلفي ، يمكنك أيضًا عرض طبقة متراكبة ذات حجم عازلة واحد يبلغ 28 × 6 من البلاط ، وكان هذا مخصصًا لتقديم HUDs ، ودرجات حتى لا تتداخل مع العفاريت الرئيسية والتمرير الخلفي.


تتمثل إحدى الميزات "المتقدمة" في أنه يمكن التمرير في الخلفية بالكامل ، ولكن كل سطر على حدة ، والذي يسمح لكل أنواع التأثيرات المثيرة للاهتمام مثل الشاشات المنقسمة أو شبه المنظر .


يوجد أيضًا جدول للسمات يسمح لك بتعيين كل مربع على قيمة من 0 إلى 3 ، ومن ثم يمكنك تحديد صفحة من البلاط لكل التجانبات مع سمة واحدة أو زيادة قيمتها الرمزية. يكون هذا مناسبًا عندما تكون هناك أجزاء من النسخة الاحتياطية تحتاج إلى تغييرها بانتظام ولا يتعين على وحدة المعالجة المركزية حساب كل بلاطة على حدة ، يكفي أن تقول شيئًا مثل: "جميع البلاطات ذات السمة 1 ، تزيد القيمة الرقمية لشخصيتك بحلول 2" ، يمكن تنفيذ أشياء مماثلة من خلال تقنيات مختلفة لاحظ ، على سبيل المثال ، في مربعات الكتل في Mario حيث تكون علامة الاستفهام متحركة أو في الألعاب التي يوجد فيها شلال تتغير فيه جميع البلاط باستمرار مما يخلق تأثير سقوط الماء.


وحدة المعالجة المركزية


عندما عملت بطاقة الفيديو الخاصة بي ، بدأت العمل مع وحدة المعالجة المركزية كـ Zilog 80 لجهاز فك التشفير الخاص بي.


أحد الأسباب وراء اختيار Z80 ، إضافة إلى حقيقة أنه وحدة المعالجة المركزية الرجعية الرائعة ، هو قدرته على معالجة فضاءين 16 بت ، أحدهما للذاكرة والثاني لمنافذ الإدخال / الإخراج ، على الأقل 6502 الأسطوري ، على سبيل المثال ، لا يمكن ، يمكنه فقط معالجة مساحة 16 بت ، وعليك تعيينها في الذاكرة بالإضافة إلى العديد من الأجهزة الخارجية ، الفيديو ، الصوت ، المقود ، مولد الأرقام العشوائية للأجهزة ، إلخ. من الملائم أن يكون لديك فضاءان للعنوان ، أحدهما يعطى بالكامل ما يصل إلى 64 كيلو بايت من الكود والبيانات في الذاكرة والثاني للوصول إلى الأجهزة الخارجية.


أولاً ، قمت بتوصيل وحدة المعالجة المركزية بـ EEPROM التي يوجد بها برنامج الاختبار الخاص بي وأيضًا توصيله عبر مساحة الإدخال / الإخراج إلى وحدة التحكم الدقيقة التي قمت بتثبيتها حتى أتمكن من الاتصال بجهاز الكمبيوتر الخاص بي عبر RS232 ومراقبة كيفية عمل وحدة المعالجة المركزية وكل شيء آخر. أسمي هذا متحكم Atmega324 الذي يعمل على 20 ميغا هرتز IO MCU - وحدة متحكم الإدخال / الإخراج ، وهي مسؤولة عن التحكم في الوصول إلى أجهزة التحكم في الألعاب (جويستيكس) ، قارئ بطاقة SD ، ولوحة مفاتيح PS / 2 واتصال عبر RS232.


imageCPU المجلس 1


تتصل وحدة المعالجة المركزية بشريحة ذاكرة 128 كيلوبايت ، منها 56 كيلوبايت فقط ، وهذا بالطبع هراء ، لكن لا يمكنني الحصول إلا على 128 أو 32 كيلوبايت. اتضح أن الذاكرة تتكون من 8 كيلو بايت من ذاكرة الوصول العشوائي و 56 كيلو بايت من ذاكرة الوصول العشوائي.


بعد ذلك ، قمت بتحديث البرنامج الثابت IO MCU باستخدام هذه المكتبة وحصلت على دعم لقارئات بطاقة SD.


الآن يمكن لوحدة المعالجة المركزية أن تتصفح الأدلة ، وأنظر ما يكمن فيها ، وأن تفتح وتقرأ الملفات. كل هذا يتم عن طريق الكتابة والقراءة إلى عناوين محددة في مساحة الإدخال / الإخراج.


توصيل وحدة المعالجة المركزية إلى PPU


والشيء التالي الذي قمت به هو الاتصال بين وحدة المعالجة المركزية ووحدة PPU. للقيام بذلك ، قمت بتطبيق "حل بسيط" وهو شراء ذاكرة الوصول العشوائي ثنائية المنافذ ، وهي شريحة ذاكرة الوصول العشوائي هذه التي يمكن توصيلها مباشرة بحافلتين مختلفتين. هذا يسمح له بالتخلص من الرقائق الإضافية مثل محددات الخطوط ، علاوة على ذلك ، يسمح بالوصول المتزامن تقريبًا إلى الذاكرة من كلا الرقائق. يمكن لـ PPU آخر الوصول مباشرة إلى وحدة المعالجة المركزية على كل إطار عن طريق تنشيط المقاطعات غير القابلة للإخفاء الخاصة به . اتضح أن وحدة المعالجة المركزية تتلقى مقاطعة على كل إطار ، وهو أمر مفيد لمختلف مهام توقيت وفهم عندما حان الوقت للقيام بتحديث الرسومات.


يحدث كل إطار تفاعل لوحدة المعالجة المركزية (CPU) و PPU و VPU وفقًا للمخطط التالي:


  1. يقوم PPU بنسخ المعلومات من ذاكرة PPU إلى الذاكرة الداخلية.
  2. يرسل PPU إشارة مقاطعة إلى وحدة المعالجة المركزية.
  3. في الوقت نفسه:
    • تنتقل وحدة المعالجة المركزية إلى وظيفة المقاطعة وتبدأ في تحديث ذاكرة PPU بحالة رسومات جديدة. يجب أن يعود البرنامج من المقاطعة حتى الكتلة التالية.
    • يعرض PPU صورة تستند إلى معلومات تم نسخها مسبقًا إلى أحد VRAM.
    • تقوم VPU بإرسال صورة من VRAM آخر إلى خرج التلفزيون.

في الوقت نفسه تقريبًا ، بدأت في دعم وحدات التحكم في اللعبة ، في البداية كنت أرغب في استخدام وحدات تحكم Nintendo ، لكن مآخذها مملوكة وصعبة بوجه عام ، لذلك استقرت على وحدات تحكم ذات 6 أزرار متوافقة مع Mega Drive / Genesis ، ولديها مآخذ توصيل DB-9 قياسية التي هي في كل مكان.


imageJoint المجلس 1


كتابة أول لعبة حقيقية


في هذا الوقت ، كان لدي بالفعل وحدة المعالجة المركزية القادرة على التحكم في PPU ، والعمل باستخدام المقود ، وقراءة بطاقات SD ... لقد حان الوقت لكتابة اللعبة الأولى ، بالطبع في مجمّع Z80 ، استغرق الأمر عدة أيام من وقت الفراغ.



إضافة رسومات ديناميكية


كان كل شيء رائعًا ، كان لدي وحدة التحكم في اللعبة الخاصة بي ، لكن هذا لم يكن كافياً بالنسبة لي ، لأنه في اللعبة كان علي استخدام الرسومات المخزنة في ذاكرة PPU وكان من المستحيل رسم البلاط للعبة معينة وكان من الممكن تغييرها فقط عن طريق إعادة تحميل ROM. بدأت أفكر في كيفية إضافة المزيد من الذاكرة بحيث يمكن لوحدة المعالجة المركزية تحميل أحرف للبلاطات فيه ، وبعد ذلك يمكن أن تقرأ وحدة PPU كل شيء من هناك وكيف يمكن القيام بذلك بسهولة لأن البادئة تحولت بالفعل إلى أنها معقدة وكبيرة.


وقد توصلت إلى ما يلي: لن يتمكن سوى وحدة PPU من الوصول إلى هذه الذاكرة الجديدة ، وسوف تقوم وحدة المعالجة المركزية بتحميل البيانات من خلال وحدة PPU هناك ، وفي حين أن عملية التحميل هذه قيد التقدم ، لا يمكن استخدام هذه الذاكرة للرسم ، لكن سيكون من الممكن السحب من ROM في هذا الوقت.


بعد نهاية الحمل ، تقوم وحدة المعالجة المركزية بتبديل ذاكرة ROM الداخلية إلى هذه الذاكرة الجديدة ، والتي أسميتها Character RAM (CHR-RAM) وفي هذا الوضع ، ستبدأ وحدة PPU في رسم رسومات ديناميكية ، وربما لا يكون هذا هو الحل الأفضل ، ولكنه يعمل. نتيجة لذلك ، تم تثبيت ذاكرة جديدة 128 كيلو بايت ويمكن تخزين 1024 حرفًا لكل منها 8x8 بكسل للخلفية ونفس عدد الأحرف بالنسبة للعفاريت.


imageJoint المجلس 2


وأخيرا الصوت


وصلت اليدين الصوت الماضي. في البداية ، أردت صوتًا مثل ما هو موجود في Uzebox ، أي أن المتحكم الدقيق يولد 4 قنوات من صوت PWM.


ومع ذلك ، اتضح أنه يمكنني بسهولة الحصول على الرقائق القديمة وأمرت بعدة شرائح توليفية FM YM3438 ، هؤلاء الشباب متوافقون تمامًا مع YM2612 المستخدم في Mega Drive / Genesis. من خلال تثبيتها ، يمكنك الحصول على موسيقى Mega Drive عالية الجودة ومؤثرات صوتية تنتجها وحدة التحكم.


قمت بتثبيت متحكم آخر وسمّته SPU (وحدة معالج الصوت) ، وهو يتحكم في YM3438 ويمكنه توليد الأصوات بنفسي. تتحكم فيه وحدة المعالجة المركزية (CPU) من خلال ذاكرة ثنائية المنافذ ، وهذه المرة لا تتجاوز 2 كيلو بايت.


كما هو الحال في وحدة الرسوم ، تحتوي وحدة الصوت على 128 كيلو بايت من الذاكرة لتخزين عينات PCM والتصحيحات الصوتية ، تقوم وحدة المعالجة المركزية بتحميل البيانات في هذه الذاكرة عن طريق الوصول إلى SPU. اتضح أن وحدة المعالجة المركزية إما أن تطلب من SPU تنفيذ الأوامر من هذه الذاكرة أو تحديث أوامر SPU في كل إطار.


تتحكم وحدة المعالجة المركزية في أربع قنوات PWM من خلال أربعة مخازن مؤقتة في ذاكرة SPU. تمر SPU عبر هذه المخازن المؤقتة وتنفذ الأوامر المكتوبة لهم. يوجد أيضًا مخزن مؤقت واحد لرقاقة توليف FM.


في المجموع ، كما هو الحال في الرسم البياني ، فإن التفاعل بين وحدة المعالجة المركزية و SPU يذهب وفقا للمخطط:


  1. SPU بنسخ البيانات من SPU إلى الذاكرة الداخلية.
  2. SPU ينتظر مقاطعة من PPU (هذا للتزامن)
  3. في نفس الوقت
    • وحدة المعالجة المركزية بتحديث المخازن المؤقتة قناة PWM والمخازن المؤقتة المزج FM.
    • ينفّذ SPU الأوامر في المخازن المؤقتة وفقًا للبيانات الموجودة في الذاكرة الداخلية.
    • جنبا إلى جنب مع كل هذا ، تقوم SPU بتحديث أصوات PWM بتردد 16 كيلو هرتز.

imageSound المجلس 1


ما خرج في النهاية


بعد أن كانت جميع الكتل جاهزة ، ذهب البعض إلى اللوح.
بالنسبة لكتلة وحدة المعالجة المركزية ، تمكنت من تطوير وطلب ثنائي الفينيل متعدد الكلور مخصص ، لا أعرف ما إذا كان الأمر يستحق ذلك بالنسبة للوحدات النمطية الأخرى ، أعتقد أنني كنت محظوظًا حقًا لأن ثنائي الفينيل متعدد الكلور يعمل على الفور.


على اللوح الآن (حتى الآن) هناك صوت فقط.
إليك كيف يبدو اليوم:


imageConsole 1


هندسة معمارية


يوضح الرسم التخطيطي المكونات في كل كتلة وكيفية تفاعلها مع بعضها البعض. الشيء الوحيد الذي لا يظهر هو الإشارة من PPU إلى وحدة المعالجة المركزية على كل إطار كمقاطعة ونفس الإشارة التي تذهب إلى SPU.


صورة العمارة


  • وحدة المعالجة المركزية: Zilog Z80 بسرعة 10 ميغاهيرتز
  • وحدة المعالجة المركزية: 8 كيلو بايت EEPROM ، يحتوي على رمز أداة تحميل التشغيل
  • وحدة المعالجة المركزية - ذاكرة الوصول العشوائي: 128 كيلو بايت من ذاكرة الوصول العشوائي (56 كيلو بايت المتوفرة) ، رمز والبيانات للبرامج / الألعاب
  • IO MCU: Atmega324 ، هي الواجهة بين وحدة المعالجة المركزية و RS232 ولوحة المفاتيح PS / 2 وعصا التحكم ونظام ملفات بطاقة SD
  • PPU-RAM: 4 كيلو بايت من ذاكرة المنفذ المزدوج ، الذاكرة الوسيطة بين وحدة المعالجة المركزية ووحدة PPU
  • ذاكرة الوصول العشوائي (CHR-RAM): ذاكرة وصول عشوائي (RAM) تبلغ 128 كيلو بايت ، تقوم بتخزين مربعات ديناميكية للدعم (الركيزة) والعفاريت (بالأحرف 8 × 8 بكسل).
  • VRAM1 ، VRAM2: ذاكرة الوصول العشوائي 128 كيلو بايت (43008 متوفرة بالفعل) ، يتم استخدامها من أجل أداة إزالة الإطارات ، ويكتبون PPU وقراءة VPU منهم.
  • PPU (وحدة معالجة الصور): Atmega1284 ، يرسم إطارًا في إطار المكياج.
  • VPU (وحدة معالجة الفيديو): يقوم Atmega324 بقراءة الأداة Framebuffer وإنشاء إشارة RGB و PAL وتزامنها.
  • SPU-RAM: ذاكرة الوصول العشوائي ثنائية المنافذ ثنائية المنافذ ، 2 كيلوبايت ، تعمل كواجهة بين وحدة المعالجة المركزية و SPU.
  • SNDRAM: ذاكرة الوصول العشوائي (RAM) بحجم 128 كيلوبايت ، تقوم بتخزين تصحيحات PWM ، وعينات PCM وكتل التعليمات الخاصة بمزج FM.
  • YM3438: YM3438 ، رقاقة توليف FM.
  • SPU (وحدة معالجة الصوت): تقوم Atmega644 بإنشاء الأصوات باستخدام مبدأ تعديل عرض النبض (PWM) وتتحكم في YM3438.

المواصفات النهائية


وحدة المعالجة المركزية:


  • وحدة المعالجة المركزية 8 بت Zilog Z80 على تردد 10Mhz.
  • 8 كيلوبايت ROM ل bootloader.
  • ذاكرة الوصول العشوائي 56 كيلو بايت.

IO:


  • قراءة البيانات من قارئ بطاقة SD FAT16 / FAT32.
  • قراءة / الكتابة إلى منفذ RS232.
  • وحدات تحكم لعبة 2 MegaDrive / Genesis- متوافق.
  • لوحة المفاتيح PS2.

فيديو:


  • القرار 224x192 بكسل.
  • 25 لقطة في الثانية (نصف FPS من PAL).
  • 256 لونا (RGB332).
  • خلفية افتراضية 2 × 2 (448 × 384 بكسل) ، مع التمرير القائم على بكسل ثنائي الاتجاه ، بناءً على أربع صفحات بملء الشاشة.
  • 64 sprites بعرض و ارتفاع 8 أو 16 بكسل مع إمكانية انعكاس أفقي ورأسي.
  • تتكون الخلفية والعفاريت من أحرف 8 × 8 بكسل لكل منها.
  • ذاكرة فيديو رمزية من 1024 حرفا للخلفية و 1024 للعفاريت.
  • 64 التمرير الأفقي المستقل على طول الخطوط المحددة
  • 8 التمرير العمودي المستقل على طول الخطوط المحددة
  • تراكب 224 × 48 بكسل مع شفافية مفتاح اللون الاختيارية.
  • خلفية سمة الجدول.
  • RGB ومركب PAL عبر موصل SCART.

الصوت:


  • PWM لمدة 8 بت و 4 قنوات ، مع أشكال موجية مدمجة: مربعة ، جيب ، منشار ، ضوضاء ، إلخ.
  • عينات من 8 بتات و kHz 8 في إحدى قنوات PWM.
  • رقاقة توليف FM YM3438 محملة بالتعليمات بتردد 50 هيرتز.

تطوير وحدة التحكم


بالنسبة لوحدة التحكم ، تمت كتابة أداة تحميل التشغيل. يتم وضع محمل الإقلاع في وحدة المعالجة المركزية ROM ويمكن أن يستغرق ما يصل إلى 8 كيلو بايت. ويستخدم 256 بايت الأولى من ذاكرة الوصول العشوائي. المحمل هو أول ما تنفذ وحدة المعالجة المركزية. هناك حاجة لإظهار البرامج الموجودة على بطاقة SD.


توجد هذه البرامج في ملفات تحتوي على تعليمات برمجية مترجمة وقد تحتوي أيضًا على رسومات وصوت.


بعد اختيار البرنامج ، يتم تحميله في ذاكرة وحدة المعالجة المركزية ، ذاكرة CHR وذاكرة SPU. بعد ذلك يتم تنفيذ رمز البرنامج. الحد الأقصى لحجم الكود الذي تم تحميله في وحدة التحكم هو 56 كيلو بايت ، باستثناء البايت 256 الأولى ، وبالطبع تحتاج إلى أن تأخذ في الاعتبار مساحة مكدس والبيانات.
وتم إنشاء أداة تحميل التشغيل هذه والبرامج الأخرى المكتوبة لوحدة التحكم هذه بنفس الطريقة الموضحة أدناه.


الذاكرة / IO الخرائط


المهم عند تطوير هذه البادئة هو أن تأخذ في الاعتبار كيفية وصول وحدة المعالجة المركزية إلى الكتل المختلفة وتخصيص مساحة العنوان لإدخال المدخلات ومساحة عنوان الذاكرة بشكل صحيح.


تصل وحدة المعالجة المركزية إلى ذاكرة الوصول العشوائي لمحمّل الإقلاع عبر مساحة عنوان الذاكرة.


مساحة عنوان الذاكرة
imageMemory رسم الخرائط


وإلى PPU-RAM و SPU-RAM و IO MCU من خلال مساحة عنوان الإدخال / الإخراج.


مساحة عنوان الإدخال / الإخراج
رسم الخرائط imageIO


كما ترون من الجدول ، يتم تخصيص عناوين لجميع الأجهزة ، IO MCU ، PPU و SPU داخل مساحة عنوان I / O.


إدارة PPU


, PPU PPU 1000h-1FFFh -.


PPU


imagePPU Mapping


PPU Status :


  1. (CHR-RAM)
  2. CHR
  3. , CPU

, , :
64 . CPU - 1004h-1143h (320 ), 5 (5 * 64 = 320):


  1. , : Active, Flipped_X, Flipped_Y, PageBit0, PageBit1, AboveOverlay, Width16, Height16.
  2. , ( ).
  3. ( — )
  4. X
  5. Y

, , Active 1, X Y , 32/32 , .


.


, 10, 4145 (1004h + (5 x 9)), 1 , , x=100 y=120, 4148 100 4149 120.



.


.


ORG 2100h PPU_SPRITES: EQU $1004 SPRITE_CHR: EQU 72 SPRITE_COLORKEY: EQU $1F SPRITE_INIT_POS_X: EQU 140 SPRITE_INIT_POS_Y: EQU 124 jp main DS $2166-$ nmi: ;    (NMI) ld bc, PPU_SPRITES + 3 ld a, (sprite_dir) and a, 1 jr z, subX in a, (c) ;  X inc a out (c), a cp 248 jr nz, updateY ld a, (sprite_dir) xor a, 1 ld (sprite_dir), a jp updateY subX: in a, (c) ;  X dec a out (c), a cp 32 jr nz, updateY ld a, (sprite_dir) xor a, 1 ld (sprite_dir), a updateY: inc bc ld a, (sprite_dir) and a, 2 jr z, subY in a, (c) ;  Y inc a out (c), a cp 216 jr nz, moveEnd ld a, (sprite_dir) xor a, 2 ld (sprite_dir), a jp moveEnd subY: in a, (c) ;  Y dec a out (c), a cp 32 jr nz, moveEnd ld a, (sprite_dir) xor a, 2 ld (sprite_dir), a moveEnd: ret main: ld bc, PPU_SPRITES ld a, 1 out (c), a ;   0 inc bc ld a, SPRITE_CHR out (c), a ;    0 inc bc ld a, SPRITE_COLORKEY out (c), a ;     0 inc bc ld a, SPRITE_INIT_POS_X out (c), a ;     0 inc bc ld a, SPRITE_INIT_POS_Y out (c), a ;   Y  0 mainLoop: jp mainLoop sprite_dir: DB 0 

باستخدام لغة C


يمكنك أيضًا استخدام لغة C ، لذلك نحتاج إلى برنامج التحويل البرمجي SDCC وبعض الأدوات المساعدة الإضافية.


قد يكون كود C أبطأ ، لكن كتابته أسرع وأسهل.


فيما يلي مثال على الكود الذي يفعل نفس رمز المجمّع أعلاه ، ويستخدم مكتبة تساعد في إجراء مكالمات إلى PPU:


 #include <console.h> #define SPRITE_CHR 72 #define SPRITE_COLORKEY 0x1F #define SPRITE_INIT_POS_X 140 #define SPRITE_INIT_POS_Y 124 struct s_sprite sprite = { 1, SPRITE_CHR, SPRITE_COLORKEY, SPRITE_INIT_POS_X, SPRITE_INIT_POS_Y }; uint8_t sprite_dir = 0; void nmi() { if (sprite_dir & 1) { sprite.x++; if (sprite.x == 248) { sprite_dir ^= 1; } } else { sprite.x--; if (sprite.x == 32) { sprite_dir ^= 1; } } if (sprite_dir & 2) { sprite.y++; if (sprite.y == 216) { sprite_dir ^= 2; } } else { sprite.y--; if (sprite.x == 32) { sprite_dir ^= 2; } } set_sprite(0, sprite); } void main() { while(1) { } } 

رسومات ديناميكية


(في الرسومات المخصصة الأصلية. تقريبًا.)


في البادئة ROM ، يتم خياطة صفحة واحدة من التجانبات للنسخ الخلفي وصفحة أخرى من العفاريت الجاهزة) افتراضيًا ، يمكنك فقط استخدام هذه الرسومات الثابتة ، ولكن يمكنك التبديل إلى الديناميكي.


كان هدفي هو أن جميع الرسومات اللازمة في شكل ثنائي تم تحميلها على الفور في ذاكرة الوصول العشوائي CHR ، ويمكن للكود الموجود في أداة تحميل التشغيل من ROM القيام بذلك. للقيام بذلك ، قمت بعمل عدة صور بالحجم الصحيح مع رموز مفيدة مختلفة:


صورة مكونات البلاط


نظرًا لأن ذاكرة الرسومات الديناميكية تتكون من 4 صفحات تحتوي على 256 حرفًا لكل منها 8 × 8 بكسل و 4 صفحات من نفس الأحرف للعفاريت ، قمت بتحويل الصور إلى تنسيق PNG ، وحذفها نسخ مكررة:


صورة ورقة imageSample


ثم استخدم أداة مكتوبة ذاتياً لترجمتها كلها إلى تنسيق ثنائي RGB332 مع كتل 8x8.


imageGraphics سطر الأوامر


نتيجة لذلك ، لدينا ملفات ذات أحرف ، حيث تنتقل جميع الأحرف بالتتابع واحدًا تلو الآخر ، ويستغرق كل منها 64 بايت.


صوت


تم تحويل عينات RAW ذات الموجة إلى عينات 8 بت 8 كيلو هرتز PCM.


تتم كتابة بقع المؤثرات الصوتية على PWM والموسيقى مع تعليمات خاصة.


بالنسبة لرقاقة Yamaha YM3438 FM التجميعية ، فقد وجدت برنامجًا يدعى DefleMask ينتج موسيقى متزامنة مع PAL لرقاقة Genesis YM2612 المتوافقة مع YM3438.


تقوم DefleMask بتصدير الموسيقى بتنسيق VGM وقمت بتحويلها باستخدام أداة مساعدة خاصة أخرى إلى تنسيق ثنائي خاص بي.


يتم دمج جميع الثنائيات من جميع الأنواع الثلاثة من الصوت في ملف ثنائي واحد ، والذي يمكن لمحمل الإقلاع الخاص بي قراءته وتحميله في ذاكرة صوت SDN RAM.


imageSound سطر الأوامر


رابط إلى الملف النهائي


يتم دمج الشفرة القابلة للتنفيذ الثنائية والرسومات والصوت في ملف PRG واحد. يحتوي ملف PRG على رأس يتم فيه وصف كل شيء بما إذا كانت هناك بيانات صوتية ورسومات ، ومدى احتلالها والبيانات نفسها.


يمكن كتابة هذا الملف على بطاقة SD ، وينظر إليه محمل الإقلاع بوحدة التحكم ويقوم بتنزيل كل شيء إلى الأماكن المناسبة ويطلق الكود القابل للتنفيذ الخاص بالبرنامج.


imagePRG سطر الأوامر


منافس


كتبت محاكيًا لوحدة التحكم الخاصة بي في C ++ باستخدام wxWidgets لتسهيل تطويرها.


تمت محاكاة وحدة المعالجة المركزية بواسطة مكتبة libz80 .


تمت إضافة ميزات إلى المضاهاة لتصحيح الأخطاء ، يمكنني إيقافه في أي وقت والقيام بالتصحيح التجميعي خطوة بخطوة ، وهناك تعيين لرمز المصدر في C. إذا تم استخدام هذه اللغة للعبة.


وفقًا للرسم البياني ، أستطيع أن أنظر إلى ذاكرة الفيديو ، وفي جداول الرموز وفي ذاكرة CHR نفسها.


فيما يلي مثال لبرنامج يعمل على محاكي مع تشغيل أدوات تصحيح الأخطاء.


imageEmulator التجريبي


برمجة التجريبي


تم تصوير مقاطع الفيديو هذه بكاميرا هاتف ذكي تستهدف شاشة تلفزيون CRT ، أعتذر عن جودة الصورة غير الكاملة.


مترجم BASIC القابل للبرمجة من لوحة المفاتيح PS / 2 ، بعد البرنامج الأول ، أظهر كيفية الكتابة مباشرة إلى ذاكرة PPU من خلال مساحة عنوان الإدخال / الإخراج عن طريق تنشيط ونقل العفريت:



عرض توضيحي للرسومات ، في هذا الفيديو ، قم بتنزيل 64 sprites بسرعة 64 × 16 ، على خلفية خلفية من خلال التمرير الديناميكي وتراكب يتحرك أسفل العفاريت:



يُظهر العرض التوضيحي الصوتي إمكانات YM3438 و PWM للصوت ، وتحتل بيانات الصوت الخاصة بهذا العرض التوضيحي وموسيقى FM وأصوات PWM معًا جميعًا تقريباً 128 كيلو بايت من ذاكرة الصوت.



تم استخدام Tetris ، بشكل حصري تقريبًا ميزات الخلفية ، والموسيقى على YM3438 ، والمؤثرات الصوتية على تصحيحات PWM للرسومات.



استنتاج


هذا المشروع حقًا أصبح حقيقة ، لقد كنت أعمل عليه منذ عدة سنوات ، مع الانقطاعات ، والنظر في وقت فراغي ، لم أكن أعتقد مطلقًا أنني سأذهب بعيدًا في إنشاء وحدة التحكم في الفيديو الخاصة بألعاب الرجعية. بطبيعة الحال ، ليست مثالية ، وأنا بالتأكيد لست خبيراً في مجال الإلكترونيات ، ومن الواضح أن هناك عناصر كثيرة للغاية في جهاز فك التشفير ، ولا شك في أنه يمكن للمرء أن يفعل ما هو أفضل وربما يكون بعض القراء يفكرون في الأمر.


لكن مع ذلك ، أثناء عملي في هذا المشروع ، تعلمت الكثير عن الإلكترونيات وأجهزة الألعاب وتصميم الكمبيوتر ولغة التجميع وأشياء أخرى مثيرة للاهتمام ، والأهم من ذلك أنني تلقيت رضاًا كبيرًا عن لعب الألعاب التي كتبت أنا شخصياً على الأجهزة التي طورتها بنفسي. وجمعها.


لدي خطط لجعل لوحات المفاتيح / أجهزة الكمبيوتر وأكثر من ذلك. في الواقع ، أنا أقوم بالفعل بصنع جهاز استقبال جديد ، وهو جاهز تقريبًا ، وهو جهاز فك تشفير مبسط قائم على لوحة FPGA وعدة مكونات إضافية (بكمية أقل بكثير مما في هذا المشروع ، بالتأكيد) ، والفكرة هي أن تكون أرخص بكثير وأكثر تكرارًا.


على الرغم من أنني كتبت الكثير عن هذا المشروع هنا ، مما لا شك فيه أنه يمكن مناقشة المزيد ، إلا أنني بالكاد ذكرت كيف يعمل محرك الصوت ، وكيف تتفاعل وحدة المعالجة المركزية مع ذلك ، وهناك الكثير الذي يمكن القيام به حول نظام الرسومات ووحدات الإدخال / الإخراج الأخرى ووحدة التحكم بأكملها سيكون أن أقول.


بالنظر إلى رد فعل القراء ، يمكنني كتابة المزيد من المقالات التي تركز على التحديثات أو تفاصيل حول مجموعات بادئات فردية أو مشاريع أخرى.


المشاريع والمواقع وقنوات يوتيوب التي ألهمتني وساعدتني في المعرفة التقنية:


هذه المواقع / القنوات ليست مصدر إلهام فحسب ، ولكنها ساعدتني أيضًا في إيجاد حلول للمشاكل المعقدة التي نشأت أثناء العمل في هذا المشروع.



شكرا لقراءتك هنا. :)


إذا كانت لديك أسئلة أو تعليقات ، فيرجى كتابة التعليقات أدناه (المقالة الأصلية باللغة الإنجليزية على جيثب. تقريبا.)

Source: https://habr.com/ru/post/ar444006/


All Articles