Diablo II จัดเก็บตัวละครเกมของคุณบนดิสก์เป็นไฟล์. d2s นี่คือรูปแบบไฟล์ไบนารีที่เข้ารหัสสถิติรายการชื่อและข้อมูลอื่น ๆ ทั้งหมด
จำนวนเต็มจะถูกเก็บไว้ในคำสั่ง Little Endian Byte ซึ่งเป็นการสั่งซื้อไบต์ดั้งเดิมในสถาปัตยกรรม X86 Diablo II ขึ้นอยู่กับ
ไฟล์. d2s แต่ละไฟล์เริ่มต้นด้วยส่วนหัว 765 ไบต์หลังจากนั้นข้อมูลมีความยาวตัวแปร
| hex | ไบต์ | ความยาว | แยกออกจากกัน |
|---|---|---|---|
| 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 | Merc Dead? |
| 0xb3 | 179 | 4 | เมล็ดเมอร์? |
| 0xb7 | 183 | 2 | รหัสชื่อ Merc |
| 0xb9 | 185 | 2 | ประเภท Merc |
| 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+ในการคำนวณ checksum ตั้งค่าของมันในข้อมูล. 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#l3977
// 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 ]
}
}หากการตรวจสอบไม่ถูกต้อง Diablo II จะไม่เปิดไฟล์บันทึก
สิ่งที่ต้องทำ
ชื่ออักขระคือการจัดเก็บเป็นอาร์เรย์ของ 16 อักขระซึ่งมีสตริงที่ถูกยกเลิก null ที่มี 0x00 สำหรับไบต์ที่เหลือ ตัวละครถูกเก็บไว้เป็น ASCII 8 บิต แต่จำไว้ว่าถูกต้องจะต้องปฏิบัติตามกฎเหล่านี้:
- ) หรือขีดล่าง ( _ )นี่คือฟิลด์ 8 บิต:
| นิดหน่อย | แยกออกจากกัน |
|---|---|
| 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 ตัวอักษร "WS" และ 6 ไบต์ที่ไม่รู้จัก, เสมอ = {0x01, 0x00, 0x00, 0x00, 0x50, 0x00}
มีโครงสร้างสามโครงสร้างสำหรับความยากลำบากแต่ละครั้งที่ชดเชย 641, 665 และ 689
เนื้อหาของโครงสร้างนี้มีดังนี้
| ไบต์ | ไบต์ | สารบัญ |
|---|---|---|
| 0 | 2 ไบต์ | {0x02, 0x01} วัตถุประสงค์ที่ไม่รู้จัก |
| 2 | 5 ไบต์ | Waypoint Bitfield ตามลำดับที่สำคัญน้อยที่สุด |
| 7 | 17 ไบต์ | ไม่รู้จัก |
ใน bitfield waypoint ค่าบิต 1 หมายความว่า waypoint เปิดใช้งานมันอยู่ในลำดับจากต่ำสุดไปสูงสุดดังนั้น 0 คือ chamment rigue (Act i) ฯลฯ จุดเริ่มต้นของ Waypoint ในแต่ละความยากจะถูกเปิดใช้งานเสมอ
สิ่งที่ต้องทำ
TODO (การเข้ารหัส 9 บิต)
รายการจะถูกเก็บไว้ในรายการที่อธิบายโดยส่วนหัวนี้:
| ไบต์ | ขนาด | แยกออกจากกัน |
|---|---|---|
| 0 | 2 | "JM" |
| 2 | 2 | จำนวนรายการ |
หลังจากนี้รายการ N แต่ละรายการเริ่มต้นด้วยโครงสร้างพื้นฐาน 14 ไบต์ หลายฟิลด์ในโครงสร้างนี้ไม่ได้ "จัดแนวไบต์" และอธิบายโดยตำแหน่งและขนาดบิตของพวกเขา
| นิดหน่อย | ขนาด | แยกออกจากกัน |
|---|---|---|
| 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 (บิต 37 ถูกตั้งค่า) จะไม่มีข้อมูลรายการเพิ่มเติมและรายการเสร็จสิ้น
รายการที่มีบิตเก็บข้อมูลเพิ่มเติมตามข้อมูลในส่วนหัวรายการ ตัวอย่างเช่นรายการที่ทำเครื่องหมายว่าเป็น Socketed จะจัดเก็บจำนวนเต็ม 3 บิตที่เข้ารหัสจำนวนซ็อกเก็ตที่มีกี่รายการ
| นิดหน่อย | ขนาด | แยกออกจากกัน |
|---|---|---|
| 108 | ซ็อกเก็ต | |
| กราฟิกที่กำหนดเอง | ||
| ชั้นเรียนเฉพาะ | ||
| คุณภาพ | ||
| ม็อด |
กราฟิกที่กำหนดเองจะถูกแสดงด้วยบิตเดียวซึ่งหากตั้งค่าหมายถึงหมายเลข 3 บิตสำหรับดัชนีกราฟิกดังต่อไปนี้ หากบิตไม่ได้ตั้งค่า 3 บิตจะไม่มีอยู่
| นิดหน่อย | ขนาด | แยกออกจากกัน |
|---|---|---|
| 0 | 1 | รายการมีกราฟิกที่กำหนดเอง |
| 1 | 3 | ดัชนีกราฟิกสำรอง |
รายการคลาสเช่น Helms Barbarian หรือ Amazon Bows มีคุณสมบัติพิเศษเฉพาะสำหรับรายการเหล่านั้น หากบิตแรกว่างเปล่าจะไม่ปรากฏ 11 บิตที่เหลืออยู่
| นิดหน่อย | ขนาด | แยกออกจากกัน |
|---|---|---|
| 0 | 1 | รายการมีข้อมูลเฉพาะคลาส |
| 1 | 11 | บิตเฉพาะชั้นเรียน |
คุณภาพของรายการถูกเข้ารหัสเป็นจำนวนเต็ม 4 บิต
หลังจากแต่ละรายการเป็นรายการของ mods รายการคือชุดของคู่คีย์ค่าที่คีย์คือหมายเลข 9 บิตและค่าขึ้นอยู่กับคีย์ รายการจะสิ้นสุดเมื่อพบคีย์ 511 ( 0x1ff ) ซึ่งเป็นทั้งหมด 9 บิตถูกตั้งค่า
การใช้ไฟล์ ItemStatCost.txt เป็นไฟล์ CSV ที่กำหนดแท็บคุณสามารถแยกคอลัมน์ ID ซึ่งแมปกับคีย์ 9 บิต คอลัมน์ Save Bits และ Param Bits อธิบายว่า mod มีขนาดใหญ่แค่ไหน
ข้อยกเว้นเพียงอย่างเดียวคือตัวดัดแปลงสไตล์ Min-Max ซึ่งใช้แถวถัดไปใน CSV เพื่อจัดเก็บส่วน "สูงสุด" ของ mod ขนาดบิตของทั้งสองนี้อาจแตกต่างกันและคุณควรสรุปเพื่อให้ได้ขนาดทั้งหมด
สิ่งที่ต้องทำ
รายการทั้งหมดตั้งอยู่ที่ไหนสักแห่งและมี "ผู้ปกครอง" ซึ่งอาจเป็นรายการอื่นเช่นเมื่อใส่อัญมณี
| ค่า | แยกออกจากกัน |
|---|---|
| 0 | ที่เก็บไว้แล้ว |
| 1 | มีอุปกรณ์ครบครัน |
| 2 | เข็มขัด |
| 4 | เคอร์เซอร์ |
| 6 | รายการ |
สำหรับรายการที่ "เก็บไว้" การเข้ารหัสจำนวนเต็ม 3 บิตเริ่มต้นที่บิต 73 อธิบายตำแหน่งที่จะจัดเก็บรายการ:
| ค่า | แยกออกจากกัน |
|---|---|
| 1 | รายการสิ่งของ |
| 4 | คิวบ์ Horadric |
| 5 | ที่ซ่อน |
รายการที่ติดตั้งอธิบายสล็อตของพวกเขา:
| ค่า | ช่องเสียบ |
|---|---|
| 1 | หมวกนิรภัย |
| 2 | เครื่องราง |
| 3 | เกราะ |
| 4 | อาวุธ (ขวา) |
| 5 | อาวุธ (ซ้าย) |
| 6 | แหวน (ขวา) |
| 7 | แหวน (ซ้าย) |
| 8 | เข็มขัด |
| 9 | รองเท้าบูท |
| 10 | ถุงมือ |
| 11 | อาวุธสำรอง (ขวา) |
| 12 | อาวุธสำรอง (ซ้าย) |