شنو هو nesformer؟
nesformer هو runtime تجريبي ديال NES، فين CPU 6502 ديال الكونصول، و2 KB ديال RAM ديال الخدمة، وROM ديال البرنامج فالكارتوش خدامين داخل الأوزان والحالة ديال checkpoint عادي من نوع Qwen3_5ForCausalLM. الأوزان ما تدرّبوش. عوض هاد الشي، compiler حسبهم باش يطبّقو circuit ديال CPU.
فوقت اللعب، الموديل كيتوقّع log ديال تنفيذ CPU token ب token. برنامج Python اللي خدام فالـhost كيوفّر باقي مكوّنات الكونصول: كيرسم گرافيك، كيقرا input ديال controller، كيتكلف بالتوقيت، كيجاوب على قراءات I/O، وكيدخل interrupt ديال NMI ديال vertical blanking.
المشروع مبني على Qwenputer وكيعاود يستعمل compiler وتقنية الذاكرة المركزية ديالو. كل head من Gated DeltaNet كيتكلف بمصفوفة حالة. المفاتيح والاستعلامات one-hot كيخليو الصفوف فهاد المصفوفة يخدمو بحال خلايا الذاكرة، وكيحتافظو بالـregisters وRAM وبيانات الكارتوش.
المزايا الرئيسية
- Compiled وماشي trained: كل وزن ماشي صفر كيتولّد انطلاقاً من مواصفات circuit.
- صيغة checkpoint عادية: الـcheckpoint عبارة عن folder عادي ديال Hugging Face، ويمكن تحميلو بـ
Qwen3_5ForCausalLM.from_pretrainedبلا model code مخصص. - مجموعة تعليمات 6502 الرسمية كاملة: الـcircuit كيطبّق جميع الـ151 opcode الرسمية، وaddressing modes، والـflags، وعمليات stack، وBRK، والدخول لـNMI.
- دعم NROM قابل لإعادة الاستعمال: نفس الأوزان يقدرو يشغلو ROMات مختلفة بصيغة iNES mapper 0، حيث الكارتوش المختار كيتكتب فحالة الموديل عند البداية.
- تحكمات مبرمجة: يمكن جدولة ضغطات الأزرار حسب frame من سطر الأوامر.
- تصدير بصري: يمكن عرض التشغيل فـterminal متوافق وحفظ frames بصيغة GIF أو PNG.
- التحقق من التنفيذ: الأمر
checkكيقارن output ديال الموديل مع CPU المرجعي المرفق وكيوقف عند أول اختلاف. - عدة محركات للتنفيذ: nesformer فيه engine سريع ديال numba، وengine عادي ديال NumPy، وengine ديال Transformers الأصلي.
فهم شنو كيجري داخل الموديل
الـcheckpoint فيه core ديال 6502، وregisters وflags ديال CPU، و2 KB ديال RAM ديال الخدمة، وجدول ثابت ديال program ROM بحجم 32 KB. كيتكلف حتى بجلب البرامج، وقراءة البيانات، وعمليات stack، وقراءات OAM DMA.
الـhost باق مسؤول على renderer ديال PPU، والـpalette، والـcontrollers، وتوقيت vblank NMI، وعدّ الدورات، والتعامل مع registers ديال APU. الصوت ما مطبّقش. الـhost كيدخل القيم ديال قراءات I/O وأحداث NMI فـtoken stream، ولكن ما كيفحصش مباشرة registers ولا RAM ديال الموديل من برا trace اللي كيخرجو.
nesformer كيماثل CPU بواسطة inference ديال الموديل، ولكن ماشي NES كاملة مطبّقة غير داخل الأوزان.
المتطلبات وإعداد المجلد
خاصك Python 3.11 ولا أحدث، وsource archive ديال nesformer، وweights archive بوحدو. فكّ الضغط على الجوج archives فـنفس المجلد الرئيسي. خاص مجلد weights يكون حدّ package ديال Python، وماشي داخلها.
nesformer/
├── nesformer/
├── chipformer/
├── roms/
├── examples/
├── tests/
├── pyproject.toml
└── weights/
├── config.json
├── generation_config.json
├── model.safetensors
├── nesformer.json
└── SHA256SUMS
شغّل جميع الأوامر من المجلد الرئيسي اللي باين لفوق. افتراضياً، CLI كيقلب على weights/ حدّ package ديال nesformer/.
تحقق من weights اللي حملتي
استعمل ملف checksum المرفق باش تتأكد بلي weights تفكّو مزيان:
shasum -a 256 -c weights/SHA256SUMS
إلا خليتي الـcheckpoint فبلاصة أخرى، مرّر المسار ديالو بـ--weights /path/to/weights ملي تستعمل run ولا check ولا trace. الأمر info كيقبل مسار الـcheckpoint مباشرة.
ثبّت nesformer
صايب virtual environment وفعّلو، ومن بعد ثبّت الحزم المطلوبة للحسابات العددية ومعالجة الصور:
python3 -m venv .venv
source .venv/bin/activate
pip install numpy scipy numba pillow
فـWindows، فعّل البيئة بهاد الأمر:
.venv\Scripts\activate
الـengine الافتراضي fast كيستعمل numba. أول تشغيل كيدوز تقريباً 20 ثانية فـcompilation ديال engine. التشغيلات الموالية كتعيد استعمال هاد compilation.
شغّل أول لعبة ديالك
المستودع فيه ROMات تجريبية برخص حرة. الأمر التالي كيشغّل Thwaite لمدة 600 frame، وكيعرض frames فالـterminal، وكيدخل sequence مبرمجة ديال ضغطات Start وA:
python -m nesformer run roms/thwaite.nes --frames 600 --show \
--buttons "start@90-95+200-205,a@230-233+250-253+270-273+290-293+310-313+330-333+350-353+370-373+390-393+410-413+430-433+450-453+470-473+490-493+510-513+530-533+550-553+570-573+590-593"
الخيار --show كيرسم كل frame مولّد فالـterminal باستعمال ألوان 24-bit، بحال iTerm2 ولا Windows Terminal. ملي كيسالي التنفيذ، CLI كيحفظ GIF متحرك مسمي باسم ROM، بحال thwaite.gif.
الأداء أبطأ بزاف من NES حقيقية. من بعد compilation الأولى، frame كياخذ غالباً بين ثانية وست ثواني. تشغيل من 600 frame كيمثل 10 ثواني من وقت NES، وقد ياخذ تقريباً 25 دقيقة.
شغّل ROM متوافق ديالك
حط ROM اللي حاصل عليه بطريقة قانونية فمجلد roms/ ولا عطِ مسار آخر. خاص ROM يستعمل لوحة NROM، اللي كتتعرف بـiNES mapper 0. من الأمثلة المتوافقة Super Mario Bros. وDonkey Kong وExcitebike، ولكن هاد ROMات التجارية ما مرفقاش.
هاد المثال كيبدا Super Mario Bros.، كيشد Right، وكيبرمج بزاف ديال القفزات:
python -m nesformer run roms/smb.nes --frames 600 --show \
--buttons "start@60-65,right@200-600,a@250-265+300-315+360-375+420-435+480-495+540-555"
الـROM كيتحمّل فحالة DeltaNet ديال الموديل ملي كيبدا. ما محتاجش تعاود تبني الـcheckpoint لكل لعبة متوافقة.
إدخال المتحكم بالسكريبت
الخيار --buttons كيقبل إدخالات مفصولين بفواصل. كل إدخال فيه اسم زر واحد ولا أكثر، الرمز @، ونطاق واحد ولا أكثر ديال الفريمات.
start@60-65
right@200-600
a@250-265+300-315
right+b@200-600
start@60-65كيضغط على Start من الفريم 60 حتى للفريم 65.right@200-600كيشد Right فالفترة المحددة.a@250-265+300-315كيبرمج جوج ضغطات على الزر A.right+b@200-600كيشد Right وB فآن واحد.
الأسماء المتاحة هي a، b، select، start، up، down، left، وright. الفريمات كيبداو من لحظة التشغيل وكيزيدو بسرعة 60 فريم فالثانية. بالتالي الفريم 600 كيمثل 10 ثواني من وقت NES.
غالباً ما كاينش مشكل إلا بديتي الضغط بشوية بكري، حيث الألعاب كتتجاهل التحكم فالشاشات اللي ما كايناش فيها الحركة. مدة الضغط تقدر تكون مهمة؛ مثلاً، ضغط أطول على A كيعطي قفزة أعلى فـSuper Mario Bros.
التحكم فإخراج الفريمات
افتراضياً، الأمر run كينفذ 120 فريم وكيكتب GIF بالاسم ديال الـROM. استعمل خيارات الإخراج باش تخصص النتيجة:
python -m nesformer run roms/thwaite.nes \
--frames 300 \
--every 2 \
--scale 3 \
--gif output/thwaite.gif
--frames Nكيوقف من بعد N فريم.--gif PATHكيحدد فين يتحفظ GIF المتحرك.--png DIRكيحفظ الفريمات المحتافَظ بها كملفات PNG منفصلة.--every Nكيحتافظ بكل فريم رقم N.--scale Nكيكبر الفريمات المحفوظة بعامل صحيح.--showكيعرض الفريمات المتولدة فالترمينال.
استعمال --png بوحدو كيعطل إخراج GIF. زيد خيار --gif صريح إلا بغيتي فريمات PNG وأنيميشن بجوج.
python -m nesformer run roms/thwaite.nes \
--frames 120 \
--png frames \
--gif thwaite.gif
فحص التنفيذ والتحقق منو
قارن مع CPU المرجعي
الأمر check كيشغل الـcheckpoint ومرجع 6502 التقليدي ديال المشروع حداه حداه. كيوقف عند أول اختلاف فالتوكنات:
python -m nesformer check roms/thwaite.nes --tokens 50000
الطول الافتراضي للمقارنة هو 50,000 توكن. تقدر تمرر نفس خيارات --buttons و--weights و--engine و--no-skip اللي كيتقبلوها أوامر التنفيذ الأخرى.
طبع سلسلة توكنات الموديل
استعمل trace باش تفحص سجلات CPU اللي كيخرجها الموديل:
python -m nesformer trace roms/thwaite.nes --tokens 100
الطول الافتراضي للتتبع هو 40 توكن. أغلب تعليمات CPU كتحتاج توكن واحد، بينما التعليمات اللي فيها I/O أو قراءة المؤشرات أو عمليات المكدس أو DMA تقدر تنتج سجلات متعددة التوكنات.
حفظ معرّفات التوكنات أثناء التشغيل
الأمر run يقدر يكتب معرّفات التوكنات المتولدة فملف باش تحللها من بعد:
python -m nesformer run roms/thwaite.nes \
--frames 60 \
--trace trace.txt
وتقدر حتى تستعمل --max-tokens N باش توقف التنفيذ من بعد عدد محدد من التوكنات المتولدة، بلا ما تعتمد غير على حد الفريمات.
اختيار محرك التنفيذ
nesformer كيوفر ثلاثة ديال المحركات بخصائص مختلفة فالأداء والاعتماديات:
- fast: التنفيذ الافتراضي بـnumba. الـREADME كيذكر تقريباً 1,650 توكن فالثانية على نواة CPU وحدة فآلة التطوير.
- numpy: تنفيذ أبسط بـNumPy، بسرعة مذكورة تقريباً 210 توكن فالثانية.
- hf: Hugging Face Transformers العادي، بسرعة مذكورة تقريباً 10 توكنات فالثانية.
اختار المحرك بـ--engine:
python -m nesformer run roms/thwaite.nes --frames 3 --engine numpy
استعمل Transformers العادي
سطّب الاعتماديات الإضافية قبل ما تختار محرك Hugging Face:
pip install "torch>=2.6" "transformers>=5.22"
python -m nesformer run roms/thwaite.nes --frames 3 --engine hf
الـcheckpoint ما محتاج حتى تنفيذ مخصص للموديل. داخلياً، nesformer كيحمّلو، كيفك ترميز توكن padding واحد، كيكتب الحالة الأولية ديال الآلة فحالات DeltaNet ديال الـcache، ومن بعد كيرجع يدخل التوكنات المتولدة وحدة بوحدة.
نصائح متقدمة
خلي الأوزان خارج المستودع
استعمل --weights ملي يكون الـcheckpoint مخزن فبلاصة أخرى:
python -m nesformer run roms/thwaite.nes \
--weights /path/to/weights \
--frames 120
فحص معلومات الـcheckpoint
استعمل أمر المعلومات باش توصف الـcheckpoint:
python -m nesformer info
إلا ما كانتش الأوزان فالمجلد الافتراضي، عطِ المسار ديالها للأمر info.
إعادة بناء الـcheckpoint
المستودع فيه المصرّف اللي خاص لإعادة توليد checkpoint ديال الدارة. البناء العادي كيكتب فـweights/ وكياخذ تقريباً 10 ثواني حسب الـREADME:
python -m nesformer build
اختار مجلد إخراج آخر بهاد الشكل:
python -m nesformer build --out compiled-weights
فهم تخطي حلقات الخمول
ألعاب NES كيتسناو بزاف vblank فـ loops قصار. ملي كيكتاشف النظام المضيف loop كيتعاود بالضبط وما فيه حتى كتابة فـ RAM ولا I/O، كيقدّم الساعة قريب للحدث الجاي ديال PPU ومن بعد كينفّذ التكرارات اللي بقات. هاد التحسين كينقص بزاف من توليد التوكنات مع الحفاظ على الفريمات اللي باينة وتوقيت I/O.
دَوّز --no-skip باش يتنفّذ كل تكرار ديال idle-loop. هاد الشي أبطأ، ولكن يقدر يفيد ملي كتدرس التسلسل الكامل ديال التوكنات:
python -m nesformer trace roms/thwaite.nes --tokens 100 --no-skip
شغّل مجموعة الاختبارات
ثبّت الاعتماديات ديال الاختبار وشغّل pytest:
pip install pytest py65
python -m pytest -q tests
الاختبارات كتاخذ بضع دقايق. كيقارنو CPU المرجعي مع log ديال nestest، وكيفحصو الدارة المترجمة مقابل المرجع، وكيتأكدو من الأوزان اللي خدامة باستمرار، وكايختابرو تحسين idle-loop.
قيود مهمّة
- NROM فقط: الألعاب خاصها تستعمل iNES mapper 0. الـ mappers اللي كيبدلو البنوك بحال MMC1 وMMC3 ما مدعومينش.
- غير opcodes الرسمية: إلا تصادف opcode غير رسمي ديال 6502، كيتصدر
HALT. - التنفيذ من ROM: الكود خاصو يتنفّذ من ROM ديال الكارتوش؛ القفز لـ RAM كيصدر
HALT. - ما كاينش دعم IRQ: BRK وNMI خدامين، ولكن IRQ ديال فريم APU وDMC ما خدامينش.
- سلوك I/O محدود: التعليمات ديال read-modify-write على سجلات I/O ما كتنتجش كتابة I/O، والعناوين من
$4020حتى$7FFFكتتقرا بصفر. - تفاصيل الرسومات تقريبية: التصيير كيتدار scanline ب scanline، والتأثيرات اللي كتوقع وسط scanline ما كتعاودش، وsprite-0 hit وsprite overflow تقريبيين.
- ما كاينش الصوت: كتابات سجلات APU مقبولة، ولكن الصوت ما كيتولّدش.
- التنفيذ بطيء: حتى مع تخطّي idle-loop، المشروع كيجري تقريباً أبطأ من console حقيقية بـ 150 حتى 290 مرة.
الخلاصة
nesformer كيبين باللي checkpoint ديال transformer يقدر يخدم كحاسوب compiled دقيق، ماشي غير كنموذج لغة مدرّب. منين كيتنظمو المصدر والأوزان بالطريقة الصحيحة، تقدر تشغّل ألعاب NROM المتوافقة، وتتحكم أوتوماتيكياً فالإدخال ديال controller، وتصدّر الفريمات، وتفحص توكنات CPU، وتقارن التنفيذ مع 6502 مرجعي. القيود ديالو فـ mapper والرسومات والصوت والسرعة كاتخليه نظام تجريبي، ولكن checkpoint القياسي Qwen3.5 وأدوات التحقق ديالو كيعطيو طريقة عملية لدراسة الحساب المرمّز مباشرة فـ أوزان النموذج وحالة DeltaNet.
