يقوم Diablo II بتخزين شخصية لعبتك على القرص كملف .d2s. هذا هو تنسيق ملف ثنائي يشفر جميع الإحصائيات والعناصر والاسم وغيرها من البيانات.
يتم تخزين الأعداد الصحيحة في Little Endian Byte Order ، وهو البايت الأصلي الذي يرتب على بنية X86 يعتمد Diablo II على.
يبدأ كل ملف .d2s برأس 765 بايت ، وبعد ذلك تكون البيانات ذات طول متغير.
| عرافة | بايت | طول | DESC |
|---|---|---|---|
| 0x00 | 0 | 4 | توقيع (0xaa55aa55) |
| 0x04 | 4 | 4 | معرف الإصدار |
| 0x08 | 8 | 4 | حجم الملف |
| 0x0C | 12 | 4 | الشيكومات |
| 0x10 | 16 | 4 | سلاح نشط |
| 0x14 | 20 | 16 | اسم الشخصية |
| 0x24 | 36 | 1 | حالة الشخصية |
| 0x25 | 37 | 1 | تطور الشخصية |
| 0x26 | 38 | 2 | ؟ |
| 0x28 | 40 | 1 | فئة الشخصية |
| 0x29 | 41 | 2 | ؟ |
| 0x2b | 43 | 1 | مستوى |
| 0x2c | 44 | 4 | ؟ |
| 0x30 | 48 | 4 | وقت |
| 0x34 | 52 | 4 | ؟ |
| 0x38 | 56 | 64 | مفاتيح |
| 0x78 | 120 | 4 | الماوس اليسار |
| 0x7C | 124 | 4 | الفأر الأيمن |
| 0x80 | 128 | 4 | الماوس الأيسر (مفتاح الأسلحة) |
| 0x84 | 132 | 4 | الماوس الأيمن (مفتاح الأسلحة) |
| 0x88 | 136 | 32 | مظهر قائمة الأحرف |
| 0xa8 | 168 | 3 | صعوبة |
| 0xab | 171 | 4 | رسم خريطة |
| 0xaf | 175 | 2 | ؟ |
| 0xb1 | 177 | 2 | ميت ميت؟ |
| 0xb3 | 179 | 4 | بذرة مير؟ |
| 0xb7 | 183 | 2 | معرف اسم MERC |
| 0xb9 | 185 | 2 | نوع مير |
| 0xBB | 187 | 4 | تجربة MERC |
| 0xBF | 191 | 144 | ؟ |
| 0x14f | 335 | 298 | السعي |
| 0x279 | 633 | 81 | نقطة الطريق |
| 0x2CA | 714 | 51 | NPC |
| 0x2FD | 765 | الإحصائيات | |
| أغراض |
إصدار الملف. القيم التالية معروفة:
71 هو 1.00 إلى V1.0687 هو 1.07 أو مجموعة التوسع v1.0889 هي لعبة قياسية v1.0892 هو V1.09 (كل من اللعبة القياسية ومجموعة التوسع.)96 هو v1.10+لحساب اختبارات الاختبارات ، قم بتعيين قيمةها في بيانات .d2s لتكون صفرًا وتكرارها من خلال جميع البايتات في البيانات التي تحسب اختبارات 32 بت:
sum = ( sum << 1 ) + data [ i ];المصدر: #5
const fs = require ( "fs" ) ;
const path = require ( "path" ) ;
const file = path . join ( process . cwd ( ) , "path_to_save.d2s" ) ;
function calculateSum ( data ) {
let sum = 0 ;
for ( let i = 0 ; i < data . length ; i ++ ) {
let ch = data [ i ] ;
if ( i >= 12 && i < 16 ) {
ch = 0 ;
}
ch += sum < 0 ;
sum = ( sum << 1 ) + ch ;
}
return sum ;
}
function littleToBigEndian ( number ) {
return new DataView (
Int32Array . of (
new DataView ( Int32Array . of ( number ) . buffer ) . getUint32 ( 0 , true )
) . buffer
) ;
}
function ashex ( buffer ) {
return buffer . getUint32 ( 0 , false ) . toString ( 16 ) ;
}
async function readSafeFile ( ) {
return await new Promise ( ( resolve , reject ) => {
fs . readFile ( file , ( err , data ) => {
if ( err ) return reject ( err ) ;
return resolve ( data ) ;
} ) ;
} ) ;
}
async function writeCheckSumToSafeFile ( data ) {
return await new Promise ( ( resolve , reject ) => {
fs . writeFile ( file , data , err => {
if ( err ) reject ( err ) ;
resolve ( ) ;
} ) ;
} ) ;
}
readSafeFile ( ) . then ( data => {
const sum = calculateSum ( data ) ;
const bufferSum = littleToBigEndian ( sum ) ;
const hex = ashex ( bufferSum ) ;
const newData = data ;
for ( let i = 0 ; i < 4 ; i ++ ) {
newData [ 12 + i ] = bufferSum . getInt8 ( i ) ;
}
writeCheckSumToSafeFile ( newData ) . then ( ( ) => console . log ( hex ) ) ;
} ) ;المصدر: https://github.com/gucio321/d2d2s/blob/66f91e2af7b3949ca7f279aae397bd8904519e2d/pkg/d2s/d2s.go#l397
// CalculateChecksum calculates a checksum and saves in a byte slice
func CalculateChecksum ( data * [] byte ) {
var sum uint32
for i := range * data {
sum = (( sum << 1 ) % math . MaxUint32 ) | ( sum >> ( int32Size * byteLen - 1 ))
sum += uint32 (( * data )[ i ])
}
sumBytes := make ([] byte , int32Size )
binary . LittleEndian . PutUint32 ( sumBytes , sum )
const (
int32Size = 4
checksumPosition = 12
)
for i := 0 ; i < int32Size ; i ++ {
( * data )[ checksumPosition + i ] = sumBytes [ i ]
}
}إذا كان Checksum غير صالح ، فلن يفتح Diablo II ملف حفظ.
تودو
يتم تخزين أسماء الأحرف كمجموعة من 16 حرفًا تحتوي على سلسلة خالية من إنهاء مبطنة مع 0x00 للبايت المتبقية. يتم تخزين الشخصيات على أنها ASCII 8 بت ، ولكن تذكر أن ساري المفعول يجب أن يتبع هذه القواعد:
- ) أو تحت السطح ( _ )هذا مجال 8 بت:
| قليل | DESC |
|---|---|
| 0 | ؟ |
| 1 | ؟ |
| 2 | المتشددين |
| 3 | مات |
| 4 | ؟ |
| 5 | توسع |
| 6 | ؟ |
| 7 | ؟ |
تودو
| بطاقة تعريف | فصل |
|---|---|
| 0 | أمازون |
| 1 | الساحرة |
| 2 | مستحضر الأرواح |
| 3 | بالادين |
| 4 | البربرة |
| 5 | درويد |
| 6 | قاتل |
تكون قيمة المستوى هذه مرئية فقط في شاشة تحديد الأحرف ويجب أن تكون هي نفسها في قسم الإحصائيات.
تودو
32 بنية البايت التي يحدد كيف تبدو الحرف في القائمة لا تتغير في اللعبة
3 بايت من البيانات التي تشير إلى أي من الصعوبات الثلاث التي فتحتها الشخصية. كل بايت يمثل إحدى الصعوبات. في هذا الترتيب: طبيعي ، كابوس ، والجحيم. كل بايت عبارة عن بايت منظم مثل هذا:
| 7 | 6 | 5 | 4 | 3 | 2 ، 1 ، 0 |
|---|---|---|---|---|---|
| نشيط؟ | مجهول | مجهول | مجهول | مجهول | أي فعل (0-4)؟ |
تودو
تودو
تبدأ بيانات Waypoint بـ 2 chars "WS" و 6 بايت غير معروف ، دائمًا = {0x01 ، 0x00 ، 0x00 ، 0x00 ، 0x50 ، 0x00}
توجد ثلاث هياكل لكل صعوبة ، في الإزاحة 641 و 665 و 689.
محتويات هذا الهيكل كما يلي
| بايت | بايت | محتويات |
|---|---|---|
| 0 | 2 بايت | {0x02 ، 0x01} غرض غير معروف |
| 2 | 5 بايت | نقطة Waypoint Bitfield من أجل أقل أهمية |
| 7 | 17 بايت | مجهول |
في نقطة الطريق Bitfield ، تعني قيمة واحدة من 1 أن نقطة الطريق يتم تمكينها في ترتيب من أدنى إلى أعلى ، لذلك 0 هو المعسكر المارق (ACT I) وما إلى ذلك. يتم تنشيط نقطة الطريق الأولى في كل صعوبة دائمًا.
تودو
تودو (تشفير 9 بت)
يتم تخزين العناصر في القوائم التي وصفها هذا الرأس:
| بايت | مقاس | DESC |
|---|---|---|
| 0 | 2 | "JM" |
| 2 | 2 | عدد العناصر |
بعد هذا يأتي عن عناصر. يبدأ كل عنصر بهيكل أساسي 14 بايت. العديد من الحقول في هذا الهيكل ليست "محاذاة بايت" ويتم وصفها بموضعها وأحجامها.
| قليل | مقاس | DESC |
|---|---|---|
| 0 | 16 | "JM" (منفصل عن رأس القائمة) |
| 16 | 4 | ؟ |
| 20 | 1 | تم تحديدها |
| 21 | 6 | ؟ |
| 27 | 1 | مقبس |
| 28 | 1 | ؟ |
| 29 | 1 | التقطت منذ آخر حفظ |
| 30 | 2 | ؟ |
| 32 | 1 | أذن |
| 33 | 1 | معدات بداية |
| 34 | 3 | ؟ |
| 37 | 1 | مضغوط |
| 38 | 1 | أثيري |
| 39 | 1 | ؟ |
| 40 | 1 | مخصصة |
| 41 | 1 | ؟ |
| 42 | 1 | وسيلة لكنها |
| 43 | 15 | ؟ |
| 58 | 3 | الوالد |
| 61 | 4 | مجهزة |
| 65 | 4 | عمود |
| 69 | 3 | صف |
| 72 | 1 | ؟ |
| 73 | 3 | خبأ |
| 76 | 4 | ؟ |
| 80 | 24 | اكتب رمز (3 أحرف) |
| 108 | بيانات العنصر الممتدة |
إذا تم تمييز العنصر على أنه Compact (تم تعيين Bit 37) ، فلن توجد معلومات عن عنصر موسعة وتم الانتهاء من العنصر.
العناصر التي تحتوي على بتات مخزن المعلومات الموسعة بناءً على المعلومات الموجودة في رأس العنصر. على سبيل المثال ، فإن عنصرًا تم وضع علامة عليه Socketed سيخزن عددًا صحيحًا إضافيًا 3 بت يكرز عدد المقابس التي لدى العنصر.
| قليل | مقاس | DESC |
|---|---|---|
| 108 | مآخذ | |
| رسومات مخصصة | ||
| فئة محددة | ||
| جودة | ||
| تعديل |
يتم الإشارة إلى الرسومات المخصصة بتضليل واحد ، والذي إذا تم تعيينه يعني رقم 3 بت لفهرس الرسوم. إذا لم يتم تعيين البت ، فإن 3 بتات غير موجودة.
| قليل | مقاس | DESC |
|---|---|---|
| 0 | 1 | يحتوي العنصر على رسومات مخصصة |
| 1 | 3 | فهرس الرسوم البديلة |
تحتوي العناصر الصفية مثل Barbarian Helms أو Amazon Bows على خصائص خاصة خاصة بهذه الأنواع من العناصر. إذا كان الجزء الأول فارغًا ، فلن يكون هناك 11 بت المتبقية.
| قليل | مقاس | DESC |
|---|---|---|
| 0 | 1 | يحتوي العنصر على بيانات فئة محددة |
| 1 | 11 | فئة أجزاء محددة |
يتم تشفير جودة العنصر على أنها عدد صحيح 4 بت.
بعد كل عنصر هي قائمة من التعديلات. القائمة عبارة عن سلسلة من أزواج القيمة الرئيسية حيث يكون المفتاح رقم 9 بت وتعتمد القيمة على المفتاح. تنتهي القائمة عندما يتم العثور على المفتاح 511 ( 0x1ff ) والذي يتم تعيين كل 9 بتات.
باستخدام ملف ItemStatCost.txt كملف CSV الذي تم تحديده في علامة تبويب ، يمكنك استخراج عمود ID الذي يقوم بتعيين مفاتيح 9 بت. الأعمدة Save Bits وتصور Param Bits المراوغة حجم وزارة الدفاع.
الاستثناء الوحيد هو معدلات نمط Min-Max التي تستخدم الصف التالي في CSV لتخزين الجزء "Max" من وزارة الدفاع. يمكن أن تكون أحجام البت لهذين الاثنين مختلفة ويجب أن تلتزمها للحصول على الحجم الكلي.
تودو
توجد جميع العناصر في مكان ما ولها "أحد الوالدين" يمكن أن يكون عنصرًا آخر ، مثل عند إدخال جوهرة.
| قيمة | DESC |
|---|---|
| 0 | تخزين |
| 1 | مجهزة |
| 2 | حزام |
| 4 | المؤشر |
| 6 | غرض |
بالنسبة للعناصر التي يتم "تخزينها" ، تصف عدد صحيح ثلاثي الأجزاء بدءًا من بت 73 مكانًا مكان تخزين العنصر:
| قيمة | DESC |
|---|---|
| 1 | جرد |
| 4 | هورادريك مكعب |
| 5 | خبأ |
العناصر المجهزة تصف فتحتها:
| قيمة | فتحة |
|---|---|
| 1 | خوذة |
| 2 | تميمة |
| 3 | درع |
| 4 | سلاح (يمين) |
| 5 | سلاح (يسار) |
| 6 | الحلقة (يمين) |
| 7 | حلقة (يسار) |
| 8 | حزام |
| 9 | أحذية |
| 10 | قفازات |
| 11 | سلاح بديل (يمين) |
| 12 | سلاح بديل (يسار) |