添加项目文件。

This commit is contained in:
2025-08-02 01:55:10 +08:00
parent 66c6a1a7fe
commit 280f128a84
5 changed files with 666 additions and 0 deletions

232
DDSExtractor/Program.vb Normal file
View File

@ -0,0 +1,232 @@
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports System.Diagnostics
Module DdsExtractor
' DDS <20>ļ<EFBFBD>ͷ<EFBFBD><CDB7>ʶ
Private ReadOnly DDS_HEADER As Byte() = {&H44, &H44, &H53, &H20} ' "DDS "
Private ReadOnly POF_MARKER As String = "POF"
Public Const Version As String = "v1.1.2"
Dim currentPath As String = AppDomain.CurrentDomain.BaseDirectory
Dim targetExePath As String = Path.Combine(currentPath, "DDSPatcher.exe")
Sub Main()
Console.ForegroundColor = ConsoleColor.DarkCyan
Console.WriteLine($"DDS <20>ļ<EFBFBD><C4BC><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> {Version} by ChilorXN.")
Console.ForegroundColor = ConsoleColor.DarkYellow
Console.WriteLine("<EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> .afb <20><> .svo <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>·<EFBFBD><C2B7><>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD>ļ<EFBFBD>)")
Console.ForegroundColor = ConsoleColor.White
Console.WriteLine("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'Patcher' <20><><EFBFBD><EFBFBD>ͬĿ¼<C4BF>µ<EFBFBD>DDS<44>޲<EFBFBD><DEB2><EFBFBD><EFBFBD><EFBFBD>")
Console.WriteLine("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'exit' <20>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>")
' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>
While True
Console.WriteLine()
Console.ForegroundColor = ConsoleColor.Blue
Console.Write("[Extractor]")
Console.ForegroundColor = ConsoleColor.White
Console.Write("> ")
Dim input As String = Console.ReadLine()
' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Select Case input.Trim().ToLower()
Case "patcher"
Console.WriteLine($"<EFBFBD><EFBFBD>ǰ·<EFBFBD><EFBFBD><EFBFBD><EFBFBD>{currentPath}")
If File.Exists(targetExePath) Then
Console.ForegroundColor = ConsoleColor.Green
Console.WriteLine("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...")
Console.ForegroundColor = ConsoleColor.White
Try
' ʹ<><CAB9>Process<73><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>򣨲<EFBFBD><F2A3A8B2>ȴ<EFBFBD><C8B4>˳<EFBFBD><CBB3><EFBFBD>
Dim processInfo As New ProcessStartInfo() With {
.FileName = targetExePath,
.UseShellExecute = True ' ʹ<><CAB9>Shellִ<6C>п<EFBFBD><D0BF>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
Process.Start(processInfo)
Console.WriteLine("<EFBFBD>ѳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DDSPatcher")
Catch ex As Exception
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine($"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>DDS<EFBFBD>޲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>{ex.Message}")
Console.ForegroundColor = ConsoleColor.White
End Try
Else
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>ǰĿ¼<EFBFBD><EFBFBD>δ<EFBFBD>ҵ<EFBFBD>DDSPatcher.exe<78><65><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DDSExtractor<6F><72><EFBFBD>ڵ<EFBFBD><DAB5>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>")
Console.ForegroundColor = ConsoleColor.White
End If
Continue While
Case "clear"
Console.Clear()
Continue While
Case "help", "about", "version"
Console.ForegroundColor = ConsoleColor.DarkCyan
Console.WriteLine($"DDS <20>ļ<EFBFBD><C4BC><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> {Version} by ChilorXN.")
Console.ForegroundColor = ConsoleColor.DarkYellow
Console.WriteLine("<EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> .afb <20><> .svo <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>·<EFBFBD><C2B7><>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD>ļ<EFBFBD>)")
Console.ForegroundColor = ConsoleColor.White
Console.WriteLine("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'Patcher' <20><><EFBFBD><EFBFBD>ͬĿ¼<C4BF>µ<EFBFBD>DDS<44>޲<EFBFBD><DEB2><EFBFBD><EFBFBD><EFBFBD>")
Console.WriteLine("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'clear' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ")
Console.WriteLine("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'help' <20>ٴβ鿴<CEB2><E9BFB4><EFBFBD><EFBFBD>")
Console.WriteLine("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'exit' <20>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>")
Continue While
Case "exit", "quit"
Exit While
End Select
' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
ProcessInputFiles(input)
End While
Console.WriteLine("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD>")
End Sub
Private Sub ProcessInputFiles(input As String)
' <20><><EFBFBD><EFBFBD><EFBFBD>Ϸŵ<CFB7><C5B5>ļ<EFBFBD>·<EFBFBD><C2B7>(Windows<77>ն˻<D5B6><CBBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ű<EFBFBD><C5B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ո<EFBFBD><D5B8><EFBFBD><EFBFBD>ļ<EFBFBD>·<EFBFBD><C2B7>)
Dim filePaths As New List(Of String)()
Dim inQuotes As Boolean = False
Dim currentPath As New System.Text.StringBuilder()
For Each c As Char In input
If c = """"c Then
If inQuotes Then
' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ű<EFBFBD><C5B0><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
filePaths.Add(currentPath.ToString())
currentPath.Clear()
inQuotes = False
Else
' <20><>ʼ<EFBFBD><CABC><EFBFBD>Ű<EFBFBD><C5B0><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
inQuotes = True
End If
ElseIf Not inQuotes AndAlso Char.IsWhiteSpace(c) Then
' <20><><EFBFBD><EFBFBD><EFBFBD>Ű<EFBFBD><C5B0><EFBFBD><EFBFBD>Ŀո<C4BF><D5B8>ָ<EFBFBD><D6B8><EFBFBD>
If currentPath.Length > 0 Then
filePaths.Add(currentPath.ToString())
currentPath.Clear()
End If
Else
' <20><><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD>ǰ·<C7B0><C2B7>
currentPath.Append(c)
End If
Next
' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>·<EFBFBD><C2B7>
If currentPath.Length > 0 Then
filePaths.Add(currentPath.ToString())
End If
' <20><><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>ļ<EFBFBD>
For Each filePath In filePaths
If Not String.IsNullOrWhiteSpace(filePath) Then
Try
ProcessFile(filePath)
Catch ex As Exception
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine($"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD> {filePath} ʱ<><CAB1><EFBFBD><EFBFBD>: {ex.Message}")
Console.ForegroundColor = ConsoleColor.White
End Try
End If
Next
End Sub
Private Sub ProcessFile(filePath As String)
If Not File.Exists(filePath) Then
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine($"<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: {filePath}")
Console.ForegroundColor = ConsoleColor.White
Return
End If
Dim extension As String = Path.GetExtension(filePath).ToLower()
If extension <> ".afb" AndAlso extension <> ".svo" Then
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine($"<EFBFBD><EFBFBD>֧<EFBFBD>ֵ<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: {filePath} (<28><>֧<EFBFBD><D6A7> .afb <20><> .svo)")
Console.ForegroundColor = ConsoleColor.White
Return
End If
Console.WriteLine($"<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>: {filePath}")
Dim fileData As Byte() = File.ReadAllBytes(filePath)
Dim ddsList As List(Of Byte()) = ExtractDdsFiles(fileData, extension = ".afb")
Console.WriteLine($"<EFBFBD>ҵ<EFBFBD> {ddsList.Count} <20><> DDS <20>ļ<EFBFBD>")
' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1> DDS <20>ļ<EFBFBD>
Dim baseName As String = Path.GetFileNameWithoutExtension(filePath)
Dim outputDir As String = Path.Combine(Path.GetDirectoryName(filePath), $"{baseName}_extracted")
Directory.CreateDirectory(outputDir)
For i As Integer = 0 To ddsList.Count - 1
Dim outputPath As String = Path.Combine(outputDir, $"{baseName}_{i + 1}.dds")
File.WriteAllBytes(outputPath, ddsList(i))
Console.ForegroundColor = ConsoleColor.Green
Console.WriteLine($"<EFBFBD>ѱ<EFBFBD><EFBFBD><EFBFBD>: {outputPath}")
Console.ForegroundColor = ConsoleColor.White
Next
End Sub
Private Function ExtractDdsFiles(fileData As Byte(), isAfbFile As Boolean) As List(Of Byte())
Dim ddsFiles As New List(Of Byte())()
Dim position As Integer = 0
While position < fileData.Length - 4
' <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD> DDS <20>ļ<EFBFBD>ͷ
If fileData(position) = DDS_HEADER(0) AndAlso
fileData(position + 1) = DDS_HEADER(1) AndAlso
fileData(position + 2) = DDS_HEADER(2) AndAlso
fileData(position + 3) = DDS_HEADER(3) Then
' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> DDS <20>ļ<EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Dim nextDdsPos As Integer = FindNextDdsHeader(fileData, position + 4)
Dim endPos As Integer = If(nextDdsPos <> -1, nextDdsPos, fileData.Length)
' <20><><EFBFBD><EFBFBD> AFB <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD> POF <20><><EFBFBD><EFBFBD>
If isAfbFile AndAlso nextDdsPos = -1 Then
Dim pofPos As Integer = FindPofMarker(fileData, position + 4)
If pofPos <> -1 Then
endPos = pofPos
End If
End If
' <20><>ȡ DDS <20><><EFBFBD><EFBFBD>
Dim ddsLength As Integer = endPos - position
Dim ddsData(ddsLength - 1) As Byte
Array.Copy(fileData, position, ddsData, 0, ddsLength)
ddsFiles.Add(ddsData)
position = endPos
Else
position += 1
End If
End While
Return ddsFiles
End Function
Private Function FindNextDdsHeader(data As Byte(), startPos As Integer) As Integer
For i As Integer = startPos To data.Length - 4
If data(i) = DDS_HEADER(0) AndAlso
data(i + 1) = DDS_HEADER(1) AndAlso
data(i + 2) = DDS_HEADER(2) AndAlso
data(i + 3) = DDS_HEADER(3) Then
Return i
End If
Next
Return -1
End Function
Private Function FindPofMarker(data As Byte(), startPos As Integer) As Integer
' POF <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ASCII <20>ַ<EFBFBD><D6B7><EFBFBD> "POF"
For i As Integer = startPos To data.Length - 3
If data(i) = AscW("P"c) AndAlso
data(i + 1) = AscW("O"c) AndAlso
data(i + 2) = AscW("F"c) Then
Return i
End If
Next
Return -1
End Function
End Module