يتم إنشاء الرسومات بواسطة شريحة خاصة تسمى وحدة معالجة الصور (PPU). هذه واحدة من الشرائح التي تمنح NES تميّزاً. للتوضيح، يمكن لأي شخص أن يلتقط معالج 6502 من المتجر التقني، فلماذا يختلف NES عن، على سبيل المثال، Apple 2 أو Commodore 64؟ حسناً، ما يميز NES عن الأجهزة الأخرى هي الشرائح التي تحيط بالمعالج: PPU وAPU. تشمل هذه القدرات الرسومية والصوتية الفريدة لـ NES، على التوالي.
مع ذلك، تقوم PPU بعرض الرسومات الثنائية الأبعاد المسماة sprites و الخلفيات، وتخرج النتيجة إلى إشارة الفيديو.
تنظيم المحتوى
لرسم شيء ما على الشاشة، يجب أن تعرف PPU ما الرسومات التي سترسمها، أين تضعها على الشاشة، وكيف ترسمها (أي أي لون يجب استخدامه).
للإجابة على هذه الأسئلة، جاءت PPU مبرمجة مسبقاً بخريطة ذاكرة مختلفة تبحث عن نوع البيانات التالي:
- يتم سحب بيانات الرسومات من شريط اللعبة، الذي يتضمن شريحة مخصصة تسمى ذاكرة الكائنات التي تخزن الرسومات ثنائية الأبعاد (تسمى البلاطات) منظمة في بنية بيانات تُسمى جدول النمط. تتجسد ذاكرة الكائنات في شكل 'ذاكرة للقراءة فقط' (ROM) أو 'ذاكرة الوصول العشوائي' (RAM) اعتمادًا على ما إذا كانت اللعبة تُرسل مع مجموعة ثابتة من الرسومات أو يجب على المعالج المركزي التدخل، على التوالي.
- يُوجّه PPU حتى 8 كيلوبايت من ذاكرة الكائنات منظمة إلى مجموعتين من 4 كيلوبايت لكل منهما.
- توجد البيانات الفوقية التي تخبر PPU 'أين' و 'كيف' ترسم الرسومات في مناطق أخرى:
- يتم تركيب 2 كيلوبايت منفصل من ذاكرة SRAM على اللوحة الأم، هذه المرة مخصصة للبيانات المتعلقة بالرسومات. تسمي نينتندو هذه المساحة ذاكرة الفيديو (VRAM) وتخزن هيكلين من البيانات يسمى جداول الأسماء.
- يحتوي PPU على 256 بايت من ذاكرة DRAM لتخزين ذاكرة سمات الكائنات (OAM).
- أخيراً، تحتوي PPU أيضًا على 4 بايت من الذاكرة لتعريف المجموعات اللونية.
لا تقلق بشأن المصطلحات الجديدة، سيتم مناقشة معنى هذه الهياكل البيانية خطوة بخطوة في الفقرات التالية.
بناء الإطار
كما هو الحال مع أقرانها المعاصرين، تم تصميم هذه الشريحة لسلوك عرض CRT. لا يوجد مخزن مؤقت للإطار: ستقوم PPU بالرسم بالتزامن مع شعاع CRT، وبناء الصورة أثناء الطيران.
يقوم PPU برسم الإطارات بأبعاد ثابتة 256x240 بكسل . لسوء الحظ، بسبب التفاوتات في معايير الفيديو التناظرية حول العالم، ستختلف الصورة في مظهرها اعتمادًا على المنطقة التي تعرض منها (NTSC أو PAL). بإيجاز، تلفزيونات NTSC تقوم بقص الحواف العلوية والسفلية لاستيعاب المسح الزائد (حوالي ~224 خط مسح مرئي)، لذا تعتبر هذه الحواف 'مناطق خطرة' من قبل المطورين عند تحديد مكان وضع العناصر على اللعبة. من جهة أخرى، تلفزيونات PAL لن تقص الحواف ولكن ستظهر أشرطة سوداء إضافية لملء الإشارة الأطول (PAL يستخدم 288 خط مسح).
خلف الكواليس، يتكون الإطار الذي ينتجه PPU من طبقتين مختلفتين. لأغراض التوضيح، دعونا نستخدم Super Mario Bros. لنوضح كيف يعمل هذا:
بلاط

جدولان من الأنماط مع عدة قوالب مجمعة معًا.

بلاطة واحدة.
للبدء، يستخدم PPU البلاطات كمكون أساسي لإنتاج الرسومات الخلفية والخلفيات.
تعرّف NES القوالب كخرائط بكسل أساسية بحجم 8x8، يتم تخزينها في ذاكرة الشخصيات (التي تقع في خرطوشة اللعبة) وتنظم في بنية بيانات كبيرة تسمى جدول الأنماط . كل قالب يشغل 16 بايت ويحتوي جدول الأنماط 256 قالبًا . نظرًا لأن PPU يعالج ما يصل إلى 8 ك.ب من ذاكرة الأحرف، فإنه يمكنه الوصول إلى جدولين من الأنماط.
داخل القالب، يتم ترميز كل بكسل باستخدام قيمة مكونة من 2 بت، والتي تشير إلى أحد الألوان الأربعة من لوحة الألوان. يمكن للمبرمجين تحديد ما يصل إلى ثمانية لوحات ألوان (أربع للخلفيات والأربع الباقية للشخصيات). تشير الألوان المرجعية في كل لوحة إلى 'لوحة الألوان الرئيسية' المكونة من 64 لونًا ، والتي تمثل جميع الألوان التي يمكن أن تنتجها هذه الوحدة. تتكون اللوحات من أربعة ألوان، على الرغم من أن لونًا واحدًا محجوز لـ الشفاف.
لبدء رسم شيء ما على الشاشة، تعبئ الألعاب مجموعة من الجداول بمراجع للقوالب في ذاكرة الشخصيات. كل جدول مسؤول عن طبقة واحدة (شخصية أو خلفية) من الإطار. ثم، يقرأ PPU من تلك الجداول ويقوم بتركيب خطوط المسح التي سيتم تشغيلها بواسطة بندقية CRT.
سأشرح الآن كيف تعمل كل طبقة/جدول وكيف تختلف من حيث الوظائف.
طبقة الخلفية

خريطة الخلفية المخصصة مع المنطقة المحددة معلّمة.
طبقة الخلفية هي خريطة بحجم 512x480 بكسل تحتوي على قوالب ثابتة . قد تتذكر أن الإطار القابل للمشاهدة أصغر بكثير، لذا تقرر الألعاب أي جزء من الطبقة يتم اختياره للعرض. يمكن أيضًا نقل المنطقة القابلة للمشاهدة أثناء اللعب؛ هذه هي الطريقة التي يتم بها تحقيق تأثير التمرير.
لتوفير الذاكرة، يتم دمج مجموعات من أربعة قوالب في خرائط بكسل بحجم 16x16 تسمى الكتل، والتي تشترك جميع القوالب داخلها في لوحة ألوان.
جداول الأسماء (المخزنة في VRAM) تحدد أي القوالب ستعرض في طبقة الخلفية. يبحث PPU عن أربع جداول أسماء بحجم 1024-بايت، كل واحدة منها تتوافق مع ربع من الطبقة. ومع ذلك، هناك 2 كيلوبايت فقط من VRAM المتاحة! نتيجة لذلك، يمكن تخزين جدولين فقط بدون أجهزة إضافية من الخرطوشة. ومع ذلك، يجب معالجة الاثنين المتبقيين في مكان ما: معظم الألعاب تعين الاثنين المتبقيين حيث تكون الأولين (وهذا يسمى المطابقة).
بينما قد تبدو هذه البنية معيبة في البداية، فقد صممت لتخفض التكاليف مع توفير التوسعية البسيطة: إذا كانت الألعاب بحاجة إلى خلفية أوسع، يمكن تضمين VRAM إضافية في الخرطوشة.
تخزن آخر بايتات من كل جدول أسماء جدول السمات بحجم 64 بايت المحدد أي لوحة ألوان مخصصة لكل كتلة .
طبقة رسومات
الشخصيات هي القوالب التي يمكن تحريكها حول الشاشة. كما يمكنها أن تتداخل مع بعضها البعض، أو تظهر خلف الخلفية. سيتم تحديد الصورة القابلة للعرض بناءً على قيمة الأولوية لها (وهو نفس مفهوم 'الطبقات' في برامج التصميم الجرافيكي التقليدية).
جدول ذاكرة السمة للكائنات (OAM) يحدد أي القوالب سيتم استخدامها كشخصيات . بالإضافة إلى فهرس القوالب، تحتوي كل إدخال على موقع (x,y) وسمات متعددة (لوحة الألوان، الأولوية، وأعلام الانعكاس). يتم تخزين هذا الجدول في ذاكرة DRAM بحجم 256-بايت الموجودة في رقاقة PPU.
يمكن ملء جدول OAM بواسطة وحدة المعالجة المركزية. ومع ذلك، يمكن أن يكون هذا بطيئًا جدًا في التطبيق (ويخاطر بإفساد الإطار إذا لم يتم في الوقت المناسب)، نتيجة لذلك، تحتوي وحدة PPU على مكون صغير يسمى الوصول المباشر إلى الذاكرة أو "DMA" الذي يمكن برمجته (عن طريق تغيير سجلات PPU) لجلب الجدول من ذاكرة WRAM. مع DMA، يتم ضمان تحميل الجدول عند رسم الإطار التالي، ولكن تذكر أن وحدة المعالجة المركزية ستتوقف أثناء النقل!
تقتصر PPU على ثمانية رسومات لكل سطر مسح وما يصل إلى 64 رسمة لكل إطار. يمكن تجاوز حد سطر المسح بفضل تقنية تسمى 'دوران ترتيب OAM'، حيث تقوم اللعبة بتعديل ترتيب الإدخالات يدوياً في OAM. هذا يجعل PPU ترسم مجموعة رسومات مختلفة في كل إطار، وسرعة شعاع CRT ستخدع المستخدم لرؤية رسومات أكثر من المسموح بها. ومع ذلك، ستظهر أيضًا كمضية على الشاشة.
تقسيم الخلفية

طبقة الخلفية المرسومة التي تبرز الجزأين بتعريف قيم التمرير المختلفة. فقط الجزء الثاني يتنقل عندما يتحرك ماريو.
قبل أن نتابع، هناك شيء لم أخبرك به بعد. إذا لعبت Super Mario Bros، ستلاحظ أنه عندما يتحرك ماريو، تتحرك المشهد بسهولة. ومع ذلك، ستلاحظ أيضًا أن المنطقة العلوية (حيث الإحصاءات) تبقى ثابتة رغم أن كلا الجزأين جزء من نفس طبقة الخلفية! إذًا، ماذا يحدث هنا؟ حسنًا، اللعبة تغير قيم التمرير في منتصف الإطار لعرض سطح العالم والإحصاءات (الموجودة في جزء ثابت من الخلفية) في نفس الوقت. لا يوفر نظام NES هذه الميزة محلياً، ولكن اللعبة تستنتج التوقيتات من خلال مراقبة حالة وحدة معالجة الرسوميات (تظهر عبر سجل الحالة الخاص بها ).
لتحقيق ذلك، تقوم الألعاب بتنفيذ تقنية تسمى ضرب العفريت 0. تقوم لعبة Super Mario Bros بتوجيه PPU لرسم عفريت وهمي خلف العملة، وهذا يحدث ليكون العفريت الأول المرسوم داخل الإطار. بعد أن تضيء PPU العفريت، تقوم بتحديث سجل الحالة الخاص بها بعلم يشير إلى أنه تم رسم العفريت الأول (المعروف باسم 'عفريت 0'). في هذه الأثناء، تتحقق اللعبة باستمرار في منتصف الإطار إذا كان حالة الرسمة 0 قد تم تفعيلها (المعروفة ب'الإصابة')، إذا حدث ذلك، تتابع اللعبة لتحديث خاصية التمرير في جدول الخلفية لتحريكها إلى حيث يوجد ماريو.
بشكل عام، يُعتبر 'ضربة السبرايت 0' إجراءً حساساً للغاية، حيث أنه من السهل العبث بالتوقيتات (لا يتم مسح علم السبرايت 0 بعد استقطابه، مما يؤدي إلى 'إيجابيات مزدوجة' ). علاوة على ذلك، بما أن هذا الروتين يتكرر إلى ما لا نهاية، فإنه يمكن أن يكون مكلفًا جدًا (من حيث دورات وحدة المعالجة المركزية) للتنفيذ. ولكن من ناحية أخرى، تولى المربعات اللاحقة هذه الوظيفة باستخدام مقاطعات تلقائية تتسبب في التشغيل عندما تصطدم بسرورة مسح تعسفية (وهي تقنية أكثر كفاءة بكثير)، مما حسن بشكل كبير القدرات البصرية لـ Super Mario Bros 3، على سبيل المثال.
النتيجة
بمجرد الانتهاء من الإطار، حان وقت الانتقال إلى الإطار التالي!
ومع ذلك، لا يمكن لوحدة المعالجة المركزية تعديل أي جدول يتم استخدامه حاليًا بواسطة PPU، وإلا، قد تظهر قطع أثرية على الشاشة. لذلك، عند اكتمال جميع خطوط المسح، تتسبب PPU في حدوث مقاطعة إيقاف العمودي (V-Blank) على وحدة المعالجة المركزية . هذا يخطر اللعبة أنها يمكن أن تبدأ في تحديث الجداول دون تمزيق الصورة المعروضة حاليًا. في تلك اللحظة، يشير شعاع CRT إلى ما تحت المنطقة المرئية للشاشة، في العرض الزائد (أو منطقة الحدود السفلية).
يمكن تحديث مجموعة محدودة فقط من سجلات PPU خارج نافذة V-Blank ، وهو ما يفسر القدرة على تمرير طبقة الخلفية في منتصف الإطار.
الأسرار و القيود
إذا كنت تفكر في أن نظام التخزين المؤقت للإطار مع الذاكرة المخصصة لتخزين الإطار الكامل كان سيكون مفضلًا: كانت تكاليف ذاكرة الوصول العشوائي مرتفعة جدًا، وكان هدف وحدة التحكم هو أن تكون ميسورة التكلفة. دعني الآن أريك لماذا أثبت التصميم أنه فعال ومرن للغاية.
التمرير المتعدد

Super Mario Bros. 2. إعداد Nametable للتمرير العمودي (الانعكاس الأفقي).

Super Mario Bros. 3. يمكن لماريو الركض والطيران، لذلك تحتاج PPU للتمرير بشكل قطري. لاحظ الحافة اليمنى التي تظهر لوحة الألوان الخاطئة! تم تطبيق قناع على الحافة اليسرى.
بعض الألعاب تتطلب من الشخصية الرئيسية التحرك عموديًا - وبالتالي سيتم إعداد Nametable مع الانعكاس الأفقي. تحتاج الألعاب الأخرى إلى تحريك شخصيتها إلى اليسار واليمين، وبالتالي تستخدم الانعكاس العمودي بدلاً من ذلك.
سيسمح أي نوع من الانعكاس لـ PPU بتحديث بلاطات الخلفية دون أن يلاحظ المستخدم: هناك مساحة كافية للتمرير أثناء رسم بلاطات جديدة على مسافة.
لكن ماذا لو أرادت الشخصية التحرك بشكل قطري؟ يمكن لـ PPU التمرير في أي اتجاه، ولكن بدون ذاكرة VRAM إضافية، يجب أن تشترك الحواف في نفس لوحة الألوان (تذكر أن البلاط ينظم في كتل).
هذا هو السبب في أن بعض الألعاب مثل Super Mario Bros. 3 تظهر رسومًا غريبة على الحافة اليمنى للشاشة بينما يتحرك ماريو (تم إعداد اللعبة للتمرير العمودي) . من الممكن أنهم احتاجوا إلى تقليل تكلفة الأجهزة لكل خرطوشة (نظرًا لأن هذه اللعبة تحتوي بالفعل على قارئ قوي).
كنوع ممتع من الإصلاح: سمحت PPU للمطورين بتطبيق قناع عمودي على البلاط، مما يخفي بشكل فعال جزءًا من المنطقة المعطلة.
تبادل البلاط

الإطار الفعلي المعروض للمستخدم.
ميزة أخرى لـSuper Mario Bros. 3 هي كمية الرسومات التي يمكنه عرضها.
هذه اللعبة تعرض المزيد من بلاطات الخلفية أكثر من المسموح بها بشكل صارم. فكيف تفعل ذلك؟ إذا أخذنا لقطة شاشة في وقتين مختلفين أثناء إنشاء العرض، يمكننا أن نرى أن الإطار النهائي في الواقع يتكون من إطارين مختلفين.
هذه خدعة أخرى من المتحكم MMC3، الذي لم يُستخدم فقط للوصول إلى مساحة أكبر في ذاكرة برنامج القراءة فقط، بل أيضًا يزيد مساحة ذاكرة الشخصيات بتوصيل شريحتين مختلفتين للشخصيات. من خلال التحقق من أي جزء من الشاشة يطلبه معالج الصور، سيعيد المتحكم التوجيه إلى إحدى الشريحتين - مما يسمح برؤية المزيد من البلاطات الفريدة على الشاشة مما كان مدعومًا في الأصل .
سلوك غريب
خلال بحثي، صادفت العديد من المقالات المثيرة للاهتمام التي تشرح السلوك غير المعتاد لـPPU، لذا فكرت في ذكر بعضها هنا:
- على عكس وحدة معالجة الفيديو لنظام الـ ماستر، التي تولد ألوان RGB التي يتم ترميزها لاحقًا إلى إشارات NTSC/PAL للبث، فإن وحدة معالجة الرسوميات لنظام NES تقوم بكل ذلك مرة واحدة . لذلك، لا يوجد اتصال واحد-لواحد بين ألوان لوحة الألوان الرئيسية لوحدة معالجة الرسوميات والمساحة اللونية القياسية لـ RGB (المعتمدة على نطاق واسع من التكنولوجيا الحالية). يترك هذا بعض المساحة للتفسير وبالتالي ستعرض المحاكيات المختلفة لوحات ألوان مختلفة.
- الفروقات بين لوحات ألوان RGB تكون أكثر وضوحًا مع طقم Tim Worthington's DIY الذي يضيف إشارة خروج RGB إلى NES، حيث إنه يحتوي أيضًا على مفتاح يختار بين ثلاث لوحات محددة مسبقاً .
- تحتوي اللوحة الرئيسية على لون 'ملعون' (
$0D) الذي قد يتسبب في فوضى في إشارة تلفزيون NTSC . حسناً، ما يحدث هو أن بعض أجهزة التلفاز تخطئ في الإشارة لعرض ذلك اللون مع إشارة الفراغ، لذلك قد يحدث وميض. - يعتمد PPU على DRAM لتخزين ذاكرة سمات الكائنات (OAM). الآن، تحتاج ذاكرة DRAM إلى التحديث باستمرار لمنع فقدان البيانات (على عكس ذاكرة SRAM)، واتضح أن وحدة معالجة الرسوميات لن تقوم بتحديث ذاكرة DRAM عندما لا ترسم الإطار . يتجلى هذا خلال الحجب الرأسي. لهذا السبب، يُنصح بعدم تحديث OAM خارج الحجب الرأسي، حيث أن الفترة غير المحدثة التي تحدث خلال الحجب الرأسي سوف تكون قد أفسدت جزءًا من الجدول.
- إن إصدار PPU لنظم PAL ليس متأثراً بهذا، حيث يتم تحديثه خلال الحجب الرأسي (الذي يستمر لفترة أطول في نظم PAL).




