Last updated on

طريقة إنشاء باتشات Cemu بصيغة .asm وتحويل patches.txt


Cemu Patches Native .asm Cemu 2.6 PowerPC 32-bit

دليل للمطورين يشرح صيغة الباتش الأصلية داخل Cemu 2.x، وتحديد ملفات RPX وRPL عن طريق CRC، وكتابة التعليمات داخل Codecave، واستخدام Labels وConstants وData Directives، ثم نقل باتشات Cemuhook القديمة إلى صيغة Cemu الأصلية.

نافذة Graphic Packs التي يستخدمها المستخدم لتنزيل الحزم، البحث عنها، وتفعيل الباتش المطلوب داخل Cemu.

وضع الباتشات حاليًا في Cemu 2.6

صيغة .asm الأصلية هي الصيغة الأساسية لهذا الدليل، ويطبقها Cemu مباشرة من داخل Graphic Packs بدون إضافة خارجية.
patches.txt القديمة ما زال Cemu يقرأها للتوافق مع الحزم القديمة، لكنها صيغة موروثة من Cemuhook وليست الخيار الأفضل لباتش جديد.
Cemuhook إضافة قديمة ومتوقفة عمليًا مع Cemu 2.x، لذلك لا تثبتها من أجل Assembly Patching أو باتشات FPS الحديثة.
عند إنشاء باتش جديد استخدم patch_<name>.asm مع rules.txt بإصدار version = 6.

وش هي Cemu Patches؟

بداية من Cemu 1.17.0 صار المحاكي يدعم تعديل Game Code مباشرة من خلال Graphic Packs. قبل ذلك كانت عملية Assembly Patching تعتمد على Cemuhook وملف patches.txt.

صيغة التوافق القديمة patches.txt بدأت مع Cemuhook، ويقرأها Cemu حاليًا للتوافق مع الحزم القديمة.
صيغة Cemu الأصلية patch_<anything>.asm وهي الصيغة الموصى بها عند إنشاء باتش جديد.
هذا موضوع تطوير باتشات، مو شرح تفعيل Graphic Packs للمستخدم العادي. كتابة عنوان خاطئ أو CRC غير صحيح ممكن يمنع الباتش من العمل أو يكسر تنفيذ اللعبة.

مكان الملف وتسميته

عندما يطابق rules.txt اللعبة، يفحص Cemu مجلد Graphic Pack بحثًا عن أي ملف يطابق النمط:

File pattern ASM
patch_<anything>.asm
صحيح patch_main.asm
صحيح patch_fps.asm
غير مطابق my_patch.asm
تقدر تحط أكثر من ملف Patch داخل الحزمة، وتقدر تحط أكثر من Patch Group داخل نفس الملف.

الحد الأدنى المطلوب داخل rules.txt

ملف rules.txt هو اللي يربط الحزمة باللعبة ويحدد اسمها ومسار ظهورها داخل نافذة Graphic Packs. مع Cemu 2.x استخدم version = 6.

rules.txt Graphic Pack v6
[Definition]
titleIds = 0005000012345600
name = My Patch
path = "Example Game/Mods/My Patch"
description = Applies a custom PPC patch.
version = 6
titleIds ضع Title ID للنسخة الأساسية التي تستهدفها الحزمة. أضف أكثر من قيمة فقط عندما يكون نفس الباتش صالحًا فعلًا لهذه الإصدارات.
path وname يحددان مكان ظهور الحزمة واسمها داخل Cemu، وليس اسم مجلد Windows فقط.
titleIds يحدد اللعبة التي تظهر لها الحزمة، بينما moduleMatches يحدد RPX أو RPL الذي سيطبق عليه كود الباتش. الاثنين لهم وظيفة مختلفة.

وش يشوف المستخدم النهائي داخل Cemu؟

واجهة Cemu الفعلية + Community Graphic Packs

المطور يكتب rules.txt وملفات patch_*.asm، لكن المستخدم النهائي ما يحتاج يفتح الكود. كل اللي يشوفه هو اسم الحزمة ومسارها ووصفها والخيارات الموجودة في نافذة Graphic Packs.

1
افتح Options → Graphic packs.
2
للحزم الرسمية اضغط Download latest community graphic packs.
3
للحزمة اليدوية أو التجريبية ضع المجلد داخل graphicPacks، وليس downloadedGraphicPacks.
4
فعّل المربع بجانب الحزمة، ثم شغل اللعبة أو أعد تشغيل Cemu.
5
ظهور اسم الحزمة باللون الأخضر أثناء تشغيل اللعبة يعني أنها Active.
لو عدلت حزمة موجودة داخل downloadedGraphicPacks، انسخها أولًا إلى مجلد graphicPacks حتى ما يستبدلها التحديث التلقائي للحزم.

مثال واضح على ظهور الحزمة وخياراتها للمستخدم النهائي؛ الاسم والمسار والوصف والـPresets كلها تأتي من ملفات Graphic Pack.

ملاحظات مهمة من تطوير Cemu

Release Notes + Developer Tracker
Cemu 1.17.0 أضاف دعمًا أصليًا لملف patches.txt، وقدم صيغة .asm الجديدة مع Automatic Codecave Sizing وWrite Cursor وLabels وVariables، وإمكانية تقسيم الباتش إلى عدة ملفات ومجموعات.
Cemu 1.20.2 صار Cemu نفسه يتولى تطبيق باتشات Cemuhook حتى لو كانت الإضافة مثبتة، مع تنبيه أن بعض Syntax وSemantics تختلف عند التحويل.
Cemu 1.22.2 صار Disassembly View يعرض أسماء Functions وLabels المعرفة داخل Graphic Pack، ويعرض نوع البيانات مثل .float.
Cemu 2.6 والمستودع الحالي صيغة .asm ما زالت مستخدمة في الإصدار الحالي، والأمثلة الفعلية موجودة في مستودع cemu_graphic_packs، وخصوصًا مجلد Mods الذي يحتوي باتشات FPS والغش وتعديلات اللعب.
أفضل طريقة لتعلم الصيغة بعد فهم الأساسيات هي فتح باتش فعلي من المستودع، ومقارنة rules.txt مع patch_*.asm وسجل تشغيل اللعبة.

Patch Groups وmoduleMatches

كل مجموعة باتش تبدأ باسم داخل أقواس مربعة، ثم moduleMatches الذي يحتوي CRC واحدًا أو أكثر لتحديد ملفات RPX أو RPL المستهدفة.

patch_main.asm Patch group
[group_name]
moduleMatches = 0x11223344, 0xCFF30E4E
اسم المجموعة يستخدم أساسًا في Debugging. رسائل الأخطاء تشير إلى اسم المجموعة ورقم السطر.
moduleMatches قائمة CRCs خاصة بملفات RPX أو RPL المستهدفة، وقد تحتوي أكثر من إصدار عندما يكون نفس الكود صالحًا لها.
تقدر تحصل CRC الخاص بكل Module من ملف log.txt بعد تشغيل اللعبة في Cemu.
Labels وConstants تقدر تُستخدم بين مجموعات مختلفة داخل نفس Graphic Pack فقط عندما تكون المجموعات مفعلة لنفس Module أو CRC. ما تقدر المجموعة تصل إلى تعريفات خارج الحزمة الحالية.

تعديل تعليمات منفردة

أبسط استخدام هو الكتابة داخل عنوان محدد في الـModule. اكتب العنوان، ثم علامة =، وبعدها تعليمة PowerPC أو Data Directive يدعمها المجمّع.

patch_main.asm Per-line addresses
0x0200E3A4 = li r3, 0
0x0200E400 = nop
li r3, 0 يستبدل التعليمة الموجودة في العنوان ويضع القيمة 0 في r3.
nop يعطل التعليمة الأصلية في العنوان المحدد.

Write Cursor واستخدام .origin

لما تكتب عدة تعليمات متتالية، ما تحتاج تحسب عنوان كل سطر يدويًا. استخدم .origin لتحديد مؤشر الكتابة، وCemu يزيده تلقائيًا بعد كل تعليمة أو Data Directive.

patch_main.asm Text section
.origin = 0x0200E3A4
bla someLabel
blr
السطر الأول يكتب في 0x0200E3A4.
السطر الثاني يكتب تلقائيًا في 0x0200E3A8.
العنوان المكتوب مباشرة بصيغة address = instruction له أولوية أعلى من .origin، ولا يزيد مؤشر الكتابة الحالي.

كتابة Function داخل Codecave

الكلمة codecave تنقل مؤشر الكتابة إلى مساحة غير مستخدمة مخصصة للكود الإضافي.

patch_main.asm Codecave function
.origin = codecave

someLabel: li r3, 0 blr

1
يبدأ Cemu الكتابة داخل منطقة Codecave.
2
ينشئ Label باسم someLabel في الموضع الحالي.
3
يكتب التعليمات بالتتابع ويحدث العناوين تلقائيًا.

Labels والعناوين الخارجية

عرّف Label بكتابة الاسم متبوعًا بنقطتين. Cemu يعالج Relocation تلقائيًا عشان يظل الاسم يشير إلى مكان الكود الصحيح في الذاكرة.

patch_main.asm Local label
OurLabel:

وتقدر تربط Label بعنوان موجود داخل Text أو Data Section في اللعبة:

patch_main.asm External address label
0x0202034C = ExternalLabel:
هذا مفيد عند استدعاء Function موجودة داخل اللعبة أو الوصول إلى Variable خارج كودك الإضافي.

Constants وExpressions

صيغة Cemu تدعم Constants وعمليات حسابية وقت التجميع، وتقدر تستخدم Preset Variables القادمة من Graphic Pack.

patch_main.asm Constant
myConst = $presetVariable + 5
li r3, myConst

أو تكتب التعبير مباشرة داخل التعليمة:

patch_main.asm Inline expression
li r3, $presetVariable + 5
Constant ما يحجز مساحة في الذاكرة، لذلك ما يصلح كهدف لتعليمات Load أو Store. لما تحتاج Variable قابلًا للعنونة استخدم Data Directive مع Label.

Data Directives المدعومة

.byteعدد 8-bit
.shortعدد 16-bit
.intعدد 32-bit
.ptrAlias لـ.int
.floatFloat 32-bit
.doubleFloat 64-bit
.stringنص بطول متغير
patch_main.asm Float variable
SomeFloat:
.float 123.45

lis r12, SomeFloat@ha lfs f0, SomeFloat@l(r12)

Label SomeFloat يشير إلى مكان القيمة داخل الذاكرة، لذلك تقدر تستخدمه مع تعليمات Load وStore.

الفرق الخطير عند التحويل من Cemuhook

الصيغتان تقبلان كتابة name = value، لكن معنى السطر مختلف.

Cemuhook name = 0x12345 يتعامل معها كPointer إلى العنوان ويطبق Relocation.
Cemu .asm نفس السطر ينشئ Constant قيمته 0x12345 بدون Relocation.
للحصول على نفس سلوك Cemuhook اكتب: name = reloc(0x12345) أو: 0x12345 = name:

مثال كامل: الصيغة القديمة مقابل صيغة Cemu

Cemuhook — patches.txt
[PatchName]
moduleMatches = 0x12345678

code Cave

codeCaveSize = 0x24

preset variable

_ourVariable = 0x0000000 0x0000000 = .int $gfxPackPresetVariable

function in code cave

_codeCaveFunction = 0x0000004 0x0000004 = lis r11, _ourVariable@ha 0x0000008 = lwz r11, _ourVariable@l(r11) 0x000000C = cmpwi r11, 1 0x0000010 = bne .+0x0C 0x0000014 = li r3, 0 0x0000018 = blr 0x000001C = addi r3, r3, 1 0x0000020 = blr

redirect game code

0x21EFAA8 = bla _codeCaveFunction

Cemu — patch_main.asm
[PatchName]
moduleMatches = 0x12345678

.origin = codecave

preset variable

_ourVariable: .int $gfxPackPresetVariable

function in code cave

_codeCaveFunction: lis r11, _ourVariable@ha lwz r11, _ourVariable@l(r11) cmpwi r11, 1 bne label_skip li r3, 0 blr

label_skip: addi r3, r3, 1 blr

redirect game code

0x21EFAA8 = bla _codeCaveFunction

صيغة Cemu أوضح لأن Labels تستبدل الحسابات اليدوية لعناوين Codecave، و.origin = codecave يدير مؤشر الكتابة بدل تحديد Offset لكل سطر.

ترتيب إنشاء باتش جديد

1
أنشئ Graphic Pack صحيحًا يحتوي rules.txt.
2
شغل اللعبة واستخرج CRC للـRPX أو RPL من log.txt.
3
أنشئ ملفًا باسم يبدأ بـ patch_ وينتهي بـ.asm.
4
أضف Patch Group واكتب moduleMatches.
5
ضع الكود الإضافي في Codecave، ثم اربط Game Code به باستخدام Branch مناسب مثل bla.
6
فعّل Graphic Pack، شغل اللعبة، وراجع log.txt لأي Parse أو Assembly Error.

تأكد أن الباتش اشتغل من log.txt

Cemu Bug Tracker القديم — سجل تشغيل فعلي

سجل Cemu يعطيك اسم الـModule والـChecksum واسم Patch Group الذي تم تطبيقه، وقد يعرض نطاق Codecave والحزمة المفعلة. المثال التالي مأخوذ من تقرير قديم في Bug Tracker ويظل مفيدًا لفهم شكل السجل:

log.txt Runtime verification
Loaded module 'turbo' with checksum 0xd09700ce
Applying patch group 'MK8FullDrawVer4_1'
Activate graphic pack: Mario Kart 8/Mods/60FPS in splitscreen
Applying patch group 'MK8AspectVer4_1' (Codecave: 01800000-01800018)
Loaded module + checksum هذه القيمة هي اللي تقارنها مع moduleMatches.
Applying patch group ظهورها يعني أن CRC طابق وأن Cemu بدأ تطبيق المجموعة.
Codecave range ظهور النطاق يؤكد أن Cemu حجز مساحة للكود الإضافي.
Activate graphic pack يوضح اسم الحزمة والمسار والـPreset الذي اشتغل فعليًا.
ابحث داخل السجل عن: Loaded module checksum Applying patch group Codecave
إذا الحزمة ظهرت Active لكن ما ظهر Applying patch group، فالسبب الأقرب CRC غير مطابق، اسم ملف غير صحيح، أو Parse Error قبل التطبيق.

أخطاء شائعة تمنع الباتش من العمل

اسم الملف غير صحيح لازم يطابق patch_<anything>.asm.
CRC غير مطابق الباتش ما يتفعل إذا Module CRC مختلف عن moduleMatches.
Relocation خاطئ نقل تعريفات Cemuhook بصيغة name = address بدون reloc().
Branch أو Label غير صالح راجع اسم الـLabel ورسالة الـAssembler وموضع Codecave؛ لا تفترض أن كل نوع Branch يصل إلى أي عنوان.
Preset Variable مفقود تأكد أن الاسم معرف في rules.txt.
تعارض Graphic Packs حزمتان تعدلان العنوان نفسه ممكن تسببان كراش أو سلوكًا غير متوقع.

متى المشكلة من الباتش وليست من Cemu؟

في Bug Tracker الرسمي أُغلق تقرير كراش لأن العطل كان يظهر فقط مع Graphic Pack، وتم توجيهه ليُصلح داخل الحزمة نفسها بدل تعديل Cemu Core.

1
عطل الحزمة وحدها وجرب نفس المكان داخل اللعبة.
2
إذا اختفت المشكلة، أعد تفعيل الحزمة وحدد أي Patch Group يسببها.
3
أرفق log.txt بعد حدوث المشكلة مباشرة.
4
اكتب Cemu Version، إصدار اللعبة، Region، Module Checksum، واسم الحزمة والـPreset.
5
افتح التقرير في Issues الخاصة بمستودع Community Graphic Packs عندما تكون المشكلة مرتبطة بالحزمة فقط، وليس في مستودع Cemu Core.
المشاكل اللي تستمر بعد تعطيل جميع Graphic Packs تُفحص بعدها كمشكلة في Cemu أو اللعبة أو التعريفات، مو كخطأ باتش.

المصادر الرسمية