龙之谷-技术资料-第6讲解析器源代码

2019年12月7日08:04:48 发表评论 26
广告也精彩

 

本期内容无关紧要

解析工具更新至V0.03

修改了部分BUG
虚拟文件夹的排列方法增加了自动排序功能。
虚拟文件列表的内容更加详细,方便大家研究。龙之谷-技术资料-第6讲解析器源代码

新增了[地址]一栏,可以在对应的资源文件的相对地址中找到指定文件的起始位置。

对于大家反映的如何解压之问题,
我当前还没有完全的解开,
但可以给大家提供一种方法,
就是在OD下断,然后从内存中提取出来,这是最简单的解压方法。

资源解析器[龙之谷]的开发源代码

==================================
;[文件名称]: 龙之谷破解测试3.pb
;[文件版本]: 0,0,0,3
;[文件数量]: 单文件
;[程序名称]: 迷路解析器-龙之谷V0.03
;[开发语言]: PureBasic4.0
;[测试平台]: WinXP(SP3)
;[开 发 者]: 迷路仟[QQ:714095563]
;[开发时间]: 2010.7.12
;==================================

;====== 自定义数据库文件类型结构

  1. Structure TypeDataFile
  2. FullName$
  3. Address.l
  4. Size.l
  5. Other3.l
  6. Other4.l
  7. Other5.l
  8. EndStructure
  9. Global NewList _ListFile.TypeDataFile()       ;用来存放各个类型资源文件解析出来的文件的名称,指针地址,大小
  10. Global NewList _ListShowFile.TypeDataFile()
  11. Global NewList _ListPath$()                   ;用来存放各个解析分来的文件夹的路径
  12. Global NewList _OptimalPath()
  13. Global NewList _SetListPath$()                ;用来存放树形控件中子项的信息
  14. Global _FileCount.l
  15. Global _GameName$ = "[龙之谷]"
  16. Global _GameResource$
  17. Global _IsLoad = #False
  18. Global WinWidth = 600
  19. Global WinHeight = 450
  20. ;字体计量转换
  21. Procedure.s FileSizeToBKM( FileSize )
  22.    If FileSize >1000
  23.       FileSizeF.f = FileSize / 1024
  24.       If FileSizeF > 1000
  25.          FileSizeF = FileSizeF / 1024
  26.          FileSize$ = StrF(FileSizeF ,2) + " M"
  27.       Else
  28.          FileSize$ = StrF(FileSizeF,2) + " K"
  29.       EndIf
  30.    Else
  31.       FileSize$ = Str(FileSize) + " B"
  32.    EndIf
  33.    ProcedureReturn FileSize$
  34. EndProcedure
  35. ;截取指定N个"\"的路径,整理用的
  36. Procedure.s GetNumPath( Path$, PathNum )      
  37.    Count = CountString(Path$, "\")
  38.    ReturnPath$ = "\"
  39.    If Count > = PathNum : Count = PathNum : EndIf
  40.    For i = 2 To Count
  41.       ReturnPath$ = ReturnPath$ + StringField(Path$, i, "\") + "\"
  42.    Next    
  43.    ProcedureReturn ReturnPath$
  44.    
  45. EndProcedure
  46. ;将同类文件的路径归类,整理用的
  47. Procedure OptimalNumPath(PathNum)      
  48.    Count = CountList( _ListPath$() ) - 1
  49.    While i < Count
  50.       SelectElement(_ListPath$(),i)
  51.       NumPath$ = GetNumPath( _ListPath$(), PathNum )
  52.       For k = i + 1 To Count
  53.          SelectElement(_ListPath$(),k)
  54.          Path$ = _ListPath$()
  55.          NewNumPath$ = GetNumPath(Path$, PathNum )      
  56.          If NumPath$ = NewNumPath$      
  57.             DeleteElement(_ListPath$()) 
  58.             SelectElement(_ListPath$(),i)
  59.             InsertElement(_ListPath$()) 
  60.             _ListPath$() = Path$
  61.             i = i + 1            
  62.          EndIf      
  63.       Next
  64.       i = i + 1
  65.    Wend
  66. EndProcedure
  67. ;将所有的路径进行整理归类,整理用的
  68. Procedure OptimalPath()
  69.    For PathNum = 2 To 5
  70.       OptimalNumPath(PathNum) 
  71.    Next 
  72.    
  73. EndProcedure
  74. ;构建控件
  75. Procedure CreateGadgets()
  76.    ;构建菜单
  77.    If CreateMenu(0, WindowID(0)) 
  78.       MenuTitle("文件")
  79.          MenuItem(11, "打开资源" )
  80.          MenuItem(12, "刷新资源" )          
  81.          MenuItem(13, "关闭资源" )
  82.          MenuBar() 
  83.          MenuItem(19, "退出"     )      
  84.       MenuTitle("资源")
  85.          MenuItem(21, "虚拟文件另存为" )
  86.          MenuItem(22, "替换虚拟文件" )          
  87.       MenuTitle("联系QQ:714095563[迷路仟]")
  88.    EndIf
  89.    ;构建状态栏   
  90.    If CreateStatusBar(0, WindowID(0))
  91.       AddStatusBarField(250)
  92.       AddStatusBarField(500)
  93.       StatusBarText(0, 0, "欢迎使用[迷路系列解析器]", #PB_StatusBar_BorderLess | #PB_StatusBar_Center)
  94.       StatusBarText(0, 1, " - 迷路制造 - ", #PB_StatusBar_BorderLess )
  95.    EndIf
  96.    ;构建弹出菜单
  97.    If CreatePopupImageMenu(1, #PB_Menu_ModernLook)     
  98.       MenuItem(21, "虚拟文件另存为" )
  99.       MenuItem(22, "替换虚拟文件" )      
  100.    EndIf
  101.    ;构建窗体   
  102.    Width = WinWidth - 20
  103.    Height = WinHeight - 60
  104.       TreeGadget    ( 1001, 0, 0, 0, 0, #PB_Tree_AlwaysShowSelection ) 
  105.       ListIconGadget( 1002, 0, 0, 0, 0, "",40, #PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection|#PB_ListIcon_HeaderDragDrop) 
  106.       SplitterGadget( 1000, 0, 0, 400, 0, 1001, 1002, #PB_Splitter_Vertical ) 
  107.       SetGadgetColor( 1001, #PB_Gadget_BackColor, $F4CF94 )
  108.       SetGadgetColor( 1002, #PB_Gadget_BackColor, $CDE2BE )
  109.       SetGadgetState( 1000, 120 )
  110.       AddGadgetColumn ( 1002, 1, "文件名", 200) 
  111.       ColText$ = "文件名,地址,大小(10),大小(16),解压后大小[10],解压后大小[16],附加信息,特征码"
  112.       For i = 2 To 8
  113.          Text$ = StringField(ColText$, i, ",")
  114.          AddGadgetColumn ( 1002, i, Text$, 100)        
  115.       Next 
  116.       ListViewSpalte.LV_COLUMN 
  117.       ListViewSpalte\mask = #LVCF_FMT 
  118.       ListViewSpalte\fmt = #LVCFMT_RIGHT
  119.       SendMessage_(GadgetID(1002), #LVM_SETCOLUMN, 0, @ListViewSpalte) 
  120.       ;SendMessage_(GadgetID(1002), #LVM_SETCOLUMN, 1, @ListViewSpalte)              
  121.       SendMessage_(GadgetID(1002), #LVM_SETCOLUMN, 3, @ListViewSpalte) 
  122.       SendMessage_(GadgetID(1002), #LVM_SETCOLUMN, 5, @ListViewSpalte)   
  123.      
  124. EndProcedure
  125. ;菜单可用性定义
  126. Procedure DisableMenuGadget( Disable )
  127.    DisableMenuItem(0,11,(Disable>>7)&1)      
  128.    DisableMenuItem(0,12,(Disable>>6)&1) 
  129.    DisableMenuItem(0,13,(Disable>>5)&1) 
  130.    DisableMenuItem(0,19,(Disable>>4)&1)
  131.    DisableMenuItem(0,21,(Disable>>3)&1) 
  132.    DisableMenuItem(0,22,(Disable>>2)&1)
  133.    DisableMenuItem(1,21,(Disable>>1)&1) 
  134.    DisableMenuItem(1,22,(Disable>>0)&1)  
  135. EndProcedure
  136. ;文件夹列表初始化
  137. Procedure LoadToTreeGadget( GadgetID )
  138.    ClearGadgetItemList(GadgetID)
  139.    AddGadgetItem ( GadgetID, -1, "请选择[文件][打开资源]", 0, 0) 
  140.    StatusBarText(0, 1, " - 迷路制造 - ", #PB_StatusBar_BorderLess )
  141.    DisableMenuGadget( %01101111 )
  142. EndProcedure
  143. ;将文件夹加载到文件夹列表中
  144. Procedure NewListToTreeGadget( GadgetID, FileName$ )
  145. Dim FloorName$(6)
  146. ;====== 初始化树形控件中的子项信息
  147.    OptimalPath()                     ;整理路径,整理用的
  148.    ClearGadgetItemList(GadgetID)     ;清空树形控件 
  149.    ClearList(_SetListPath$())         ;清空树形控件中的子项信息
  150.    AddElement(_SetListPath$()) 
  151.    _SetListPath$() = "\
  152.    Path$ = _GameName$ + " -- " + GetFilePart(FileName$)
  153.    AddGadgetItem ( GadgetID, -1, Path$, 0, 0)
  154.    ;====== 加载到树形控件
  155.    ForEach _ListPath$()
  156.       Floor = CountString(_ListPath$(),"\") - 1
  157.       If Floor > 0
  158.          For Index = 1 To Floor
  159.             FoldName$ = StringField(_ListPath$(),Index + 1,"\")
  160.             If FloorName$(Index) <> FoldName$
  161.                FloorName$(Index) = FoldName$
  162.                AddGadgetItem(GadgetID, -1, FoldName$ , 0, Index)
  163.                Text$ = "\"
  164.                For i = 1 To Index 
  165.                   Text$ = Text$ + FloorName$(i) + "\"
  166.                Next 
  167.                AddElement(_SetListPath$())
  168.                _SetListPath$() = Text$
  169.             EndIf 
  170.          Next 
  171.       EndIf 
  172.    Next 
  173.    StatusBarText(0, 1, "共有[" + Str(CountList(_SetListPath$())) + "]个文件夹和[" + Str(_FileCount) + "]个文件.")
  174.    _IsLoad = #True
  175.    SetGadgetItemState(1001, 0, #PB_Tree_Expanded)
  176.    
  177. EndProcedure
  178. ;加载指定文件夹中的文件
  179. Procedure NewListToListGadget( )
  180.    If _IsLoad = #True
  181.       ListIndex = GetGadgetState(1001) 
  182.       SelectElement(_SetListPath$(), ListIndex)
  183.       ClearGadgetItemList( 1002 )
  184.       ClearList(_ListShowFile())      ;清空树形控件中的子项信息
  185.       ForEach _ListFile()
  186.          If GetPathPart(_ListFile()\FullName$) = _SetListPath$()
  187.             AddElement(_ListShowFile()) 
  188.             _ListShowFile()\FullName$ = GetFilePart(_ListFile()\FullName$)
  189.             _ListShowFile()\Address   = _ListFile()\Address
  190.             _ListShowFile()\Size      = _ListFile()\Size
  191.             Size1$ = FileSizeToBKM( _ListFile()\Size ) 
  192.             Size2$ = FileSizeToBKM( _ListFile()\Other4 )             
  193.             ;"序,文件名,地址,大小(10),大小(16),解压后大小[10],解压后大小[16],附加信息,特征码"
  194.             Count = Count + 1
  195.             Text$ = RSet(Str(Count), 4, "0") + Chr(10)                              ;序
  196.             Text$ = Text$ + GetFilePart(_ListFile()\FullName$) + Chr(10)            ;文件名
  197.             Text$ = Text$ + "0x" + RSet(HexQ(_ListFile()\Address),8,"0") + Chr(10) ;地址
  198.             Text$ = Text$ + Size1$ + Chr(10)                                        ;大小(10)
  199.             Text$ = Text$ + HexQ(_ListFile()\Size) + Chr(10)                       ;大小(16)            
  200.             Text$ = Text$ + Size2$ + Chr(10)                                        ;解压后大小[10]
  201.             Text$ = Text$ + HexQ(_ListFile()\Other4) + Chr(10)                      ;解压后大小[16] 
  202.             Text$ = Text$ + HexQ(_ListFile()\Other3) + Chr(10)                      ;附加信息,
  203.             Text$ = Text$ + HexQ(_ListFile()\Other5) + Chr(10)                      ;特征码,                                                      
  204.             AddGadgetItem( 1002,-1, Text$ )
  205.          EndIf 
  206.       Next 
  207.       StatusBarText(0, 1, "在虚拟目录[" + _SetListPath$() + "]下,共有[" + Str(Count) + "]个文件.")
  208.    EndIf
  209. EndProcedure
  210. ;加载数据到链表
  211. Procedure LoadDataToNewList( GadgetID, FileName$)
  212.     ;打开 <游戏资源文件>
  213. FileHandle = CreateFile_(FileName$, $40000000 | $80000000, 3, 0, 3, 0, 0)
  214. If FileHandle >0
  215.     ;====== 读取资源文件的头部信息
  216.     FileSize = FileSize(FileName$)
  217.     ReadSize = $110
  218.     *MemoryID = AllocateMemory(ReadSize)
  219.     Paddess = SetFilePointer_(FileHandle, 0, 0, 0)            ;获取资源文件起始地址的指针
  220.     ReadFile_(FileHandle, *MemoryID, ReadSize, @Paddess, 0)   ;加载资源文件 
  221.     ;====== 获取关键的资源文件信息
  222.     _FileCount = PeekL(*MemoryID + $104)                      ;文件的数量
  223.     Pos = PeekL(*MemoryID + $108)                             ;文件索引的起始位置       
  224.     ;====== 加载资源文件索引部分的内容
  225.     FileSize = FileSize - Pos 
  226.     *MemoryID = ReAllocateMemory(*MemoryID, FileSize)      
  227.     Paddess = SetFilePointer_(FileHandle, Pos, 0, 0)          ;获取资源文件起始地址的指针
  228.     ReadFile_(FileHandle, *MemoryID, FileSize, @Paddess, 0)   ;加载资源文件
  229.     ;====== 关闭资源文件
  230.     CloseHandle_(FileHandle)   
  231. Else     
  232.     MessageRequester("出错提示", "找不到" + FileName$ + "]资源文件..." )
  233.     ProcedureReturn -1 
  234. EndIf 
  235. Pos = 0
  236. ;====== 清空链表
  237. ClearList(_ListFile()) 
  238. ClearList(_ListPath$()) 
  239. ;====== 加载文件信息到链表 
  240.    For i = 1 To _FileCount
  241.       AddElement(_ListFile()) 
  242.       _ListFile()\FullName$ = PeekS(*MemoryID + Pos)    ;获取文件的全名称
  243.       _ListFile()\Address = PeekL(*MemoryID + Pos + $10C)    
  244.       _ListFile()\Size    = PeekL(*MemoryID + Pos + $100)    
  245.       _ListFile()\Other3 = PeekL(*MemoryID + Pos + $108)    
  246.       _ListFile()\Other4 = PeekL(*MemoryID + Pos + $104)    
  247.       _ListFile()\Other5 = PeekL(*MemoryID + Pos + $110)    
  248.        ;====== 加载新的路径
  249.       Path$ = GetPathPart(_ListFile()\FullName$)        ;获取文件的路径
  250.       If FilePath$ <> Path$ 
  251.          AddElement(_ListPath$()) 
  252.          _ListPath$() = Path$
  253.          FilePath$ = Path$         
  254.       EndIf 
  255.       ;====== 步进到下一个文件内存地址
  256.       Pos = Pos + $13C 
  257.       Files = Files + 1
  258.    Next 
  259.    NewListToTreeGadget( GadgetID, FileName$ )
  260.    MessageRequester("解析完成", "总共解析出 [" + Str(_FileCount) + "] 个文件.")
  261. EndProcedure
  262. ;加载游戏资源
  263. Procedure OpenResourceFile( )
  264.    StandardFile$ = "Resource00.pak"   
  265.    Pattern$ = "资源文件(*.pak)|*.pak"
  266.    Pattern = 0    
  267.    FileName$ = OpenFileRequester("请选择" + GameName$ + "资源文件", StandardFile$, Pattern$, Pattern)
  268.    If FileSize(FileName$)>0
  269.       _GameResource$ = FileName$
  270.       LoadDataToNewList(1001, _GameResource$)
  271.       DisableMenuGadget( %00001111 )
  272.    Else
  273.       MessageRequester("错误提示", "您指定的文件不存在.", 0) 
  274.    EndIf
  275. EndProcedure
  276. ;虚拟文件另存为
  277. Procedure SaveAsResourceFile( GadgetID, FileName$ )
  278.    ListIndex = GetGadgetState(GadgetID)
  279.    If ListIndex <0 : ProcedureReturn : EndIf 
  280.     
  281.     ;打开 <游戏资源文件>
  282.    FileHandle = CreateFile_(FileName$, $40000000 | $80000000, 3, 0, 3, 0, 0)
  283.    If FileHandle >0
  284.       SelectElement(_ListShowFile(), ListIndex)
  285.       ;====== 读取资源文件的头部信息
  286.       FileSize = _ListShowFile()\Size
  287.       *MemoryID = AllocateMemory(FileSize)    
  288.       Paddess = SetFilePointer_(FileHandle, _ListShowFile()\Address, 0, 0)    ;获取资源文件起始地址的指针 
  289.       ReadFile_(FileHandle, *MemoryID, FileSize, @Paddess, 0)   ;加载资源文件 
  290.       ;====== 关闭资源文件
  291.       CloseHandle_(FileHandle) 
  292.     
  293.       Pattern$ = "虚拟文件(*.*)|*.*"
  294.       StandardFile$ = _ListShowFile()\FullName$
  295.       Pattern = 0   
  296.       File$ = SaveFileRequester("请选择要另存为的位置", StandardFile$, Pattern$, Pattern)
  297.       If File$
  298.          If FileSize(File$)>0
  299.             Text$ = File$ + Chr(10) + "指定位置已经有同名文件存在" + Chr(10) + "是否要替代文件?"
  300.             Msg = MessageRequester("提示",Text$ , #PB_MessageRequester_YesNo ) 
  301.             If Msg = #PB_MessageRequester_No : ProcedureReturn -1 : EndIf 
  302.          EndIf 
  303.          If CreateFile(1, File$)                   ;生成 资源文件
  304.             WriteData(1, *MemoryID, FileSize )
  305.             CloseFile(1)
  306.          Else
  307.             MessageRequester("提示", "存放文件时出错", 16)
  308.             End
  309.          EndIf           
  310.          Text$ = "虚拟文件:[" + _ListShowFile()\FullName$ + "]提取到 " + Chr(10) 
  311.          Text$ = Text$ + "[" + File$ + "]成功, " + Chr(10) + "并保存为独立文件. "
  312.          MessageRequester("提取成功", Text$, 0)
  313.       Else
  314.          MessageRequester("提示", "请选择要存放的文件夹及文件名称", 16) 
  315.       EndIf
  316. Else     
  317.     MessageRequester("出错提示", "找不到" + FileName$ + "]资源文件..." )
  318.     ProcedureReturn -1 
  319. EndIf 
  320. EndProcedure
  321. ;菜单事件
  322. Procedure My_Event_Menu()
  323.    Select EventMenu()
  324.       Case 11; "打开资源
  325.          ClearGadgetItemList(1002)
  326.          OpenResourceFile()
  327.          _IsLoad = #True
  328.       Case 12;"刷新资源"
  329.          ClearGadgetItemList(1002)   ;清空树形控件                   
  330.          LoadDataToNewList(1001, _GameResource$)
  331.       Case 13;"关闭资源"                
  332.          ClearGadgetItemList(1001)   ;清空树形控件 
  333.          ClearGadgetItemList(1002)   ;清空树形控件 
  334.          _IsLoad = #False 
  335.          LoadToTreeGadget( 1001 )
  336.       Case 19;"退出"
  337.          Quit = #True
  338.       Case 21;"虚拟文件另存为"
  339.          SaveAsResourceFile( 1002, _GameResource$ )         
  340.       Case 22;"替换虚拟文件"
  341.          ;.........此部分内容删除
  342.       MessageRequester("替换虚拟文件","为了游戏开发商与运营商的利益,此功能不对外开放. ", 16)                 
  343.    EndSelect
  344. EndProcedure
  345. ;控件事件
  346. Procedure My_Event_Gadget()
  347.    
  348.    Select EventGadget()
  349.       Case 1001
  350.          If EventType() = #PB_EventType_LeftDoubleClick
  351.             NewListToListGadget( )
  352.          EndIf 
  353.       Case 1002 
  354.          If GetGadgetState(1002) >= 0
  355.             DisableMenuGadget( %00000101 )
  356.             If EventType() = #PB_EventType_RightClick 
  357.                DisplayPopupMenu(1, WindowID(0))
  358.             EndIf 
  359.          Else 
  360.             DisableMenuGadget( %00001111 ) 
  361.          EndIf 
  362.    EndSelect
  363.    
  364. EndProcedure
  365. ;主程序部分
  366. WinFlags.l = #PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget
  367. WinFlags = WinFlags | #PB_Window_SystemMenu | #PB_Window_SizeGadget 
  368.    If OpenWindow(0, 0, 0, WinWidth, WinHeight, "迷路[龙之谷]解析器V0.03", WinFlags)
  369.       If CreateGadgetList(WindowID(0))
  370.          CreateGadgets()
  371.          LoadToTreeGadget( 1001 )
  372.          Repeat
  373.             WinEventID = WaitWindowEvent()
  374.             Select WinEventID
  375.                Case #PB_Event_CloseWindow
  376.                   Quit = #True
  377.                Case #PB_Event_SizeWindow
  378.                   If EventWindow() = 0
  379.                      Width = WindowWidth(0) - 20
  380.                      Height = WindowHeight(0) - 60
  381.                      ResizeGadget(1000, 10, 10, Width, Height)
  382.                   EndIf
  383.                Case #PB_Event_Menu
  384.                   My_Event_Menu()
  385.                Case #PB_Event_Gadget
  386.                   My_Event_Gadget()
  387.             EndSelect
  388.          Until Quit = #True
  389.       EndIf
  390.    EndIf
  391. End

以下附上相关工具下载文章链接

工具

老周工具包(龙之谷全功能工具)

工具

老周工具包 DNTⅡTOOL 最终版

DNT编辑工具

榴莲大神写的一个龙之谷DNT编辑工具 DNTEditor

PAK工具

龙之谷补丁工坊 v2.4 用于打包和解包龙之谷客户端PAK的工具

DNT ACT编辑器

龙之谷 超级DNT ACT编辑器1.5.2

广告也精彩
七玩网(admin)
广告也精彩

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: