-
Notifications
You must be signed in to change notification settings - Fork 6
/
LSPK-lib.sbp
823 lines (681 loc) · 22.3 KB
/
LSPK-lib.sbp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
'TheLastStory pk archive library for AB4 - RGBA_CRT 2017-2018
Type LSPK_FILEINFO
index As Long
hash As DWord
path As *FilePath
pkh As *PKH_INFO_BLOCK
End Type
Type LSPK_DIRINFO
name As BytePtr
index As Long
info As *PFS_DIR_INFO
End Type
Type LSPK_FINDDATA
isDir As BOOL
current As Long
stop As Long
parentDir As *LSPK_DIRINFO
End Type
Typedef LSPK_FINDHANDLE = *LSPK_FINDDATA
'FALSEを返すと終了
Typedef LSPK_CALLBACK = *Function(hFind As LSPK_FINDHANDLE,info As VoidPtr,path As *FilePath,userdata As VoidPtr,lv As Long) As BOOL
/* LSPK_CALLBACKについて
* ディレクトリ捜査は、捜査関数にコールバック関数を渡す。
* ディレクトリまたはファイルが見つかるとこーーるバックが呼ばれる。
* コールバック関数は、呼ばれたらディレクトリかファイルかを判断し、表示やファイルの保存などを行う。
*/
Enum LSPK_ARCHIVE_ERROR
LSPK_OK = 0
LSPK_ERR_PKH_OPEN
LSPK_ERR_PKH_FORMAT
LSPK_ERR_PFS
LSPK_ERR_PK
_LSPK_ERR_COUNT
End Enum
Dim LSPK_ARHIVE_ERROR_TEXT_TBL[_LSPK_ERR_COUNT] = [ _
"No error",_
"Can not open PKH file.",_
"Unknown PKH File Format. (invalid Block Size)",_
"PFS file error.",_
"PK file error.",_
] AS BytePtr
Enum LSPK_COMPRESS_TYPE
LSPK_CTYPE_UNKNOWN = 0
LSPK_CTYPE_ZLIB
LSPK_CTYPE_ZLIB_2
LSPK_CTYPE_LZ1X
_LSPK_CTYPE_COUNT
End Enum
Dim LSPK_COMPRESS_TYPE_TEXT_TBL[_LSPK_CTYPE_COUNT] = [ _
"Unknown",_
"Zlib Compress",_
"Zlib Compress (maybe)",_
"LZ10/LZ11 Compress"
] AS BytePtr
Class LSPK_ARCHIVE
Public
pkh As PKH_READER
pfs As PFS_READER
pk As File
' 圧縮タイプを手動設定する場合はopenArchiveのあとでやってください
compressType As LSPK_COMPRESS_TYPE
Private
pkPath As FilePath
lastErrorID As LSPK_ARCHIVE_ERROR
lastErrorGLE AS DWord
Public
'pkアーカイブを開く(拡張子無視)
Function openArchive(pkPathStr As BytePtr)(bNoPKH As BOOL,bNoPFS As BOOL,bNoPK As BOOL) As BOOL
'default return ERROR
openArchive = FALSE
pkPath.SetPath(pkPathStr)
pkPath.deleteExtension()
debug
If bNoPKH=FALSE Then
lastErrorID = pkh.LoadPkhFile(pkPath.genAddedPath(".pkh"))
If lastErrorID <> LSPK_OK Then
lastErrorGLE = GetLastError()
ExitFunction
Endif
lastErrorID = LSPK_OK
Endif
If bNoPFS=FALSE Then
If pfs.LoadPfsFile( pkPath.genAddedPath(".pfs")) = FALSE Then
lastErrorID = LSPK_ERR_PFS
lastErrorGLE = GetLastError()
ExitFunction
Endif
Endif
If bNoPK=FALSE Then
If pk.openFile(pkPath.genAddedPath(".pk"),GENERIC_READ) = FALSE Then
lastErrorID = LSPK_ERR_PK
lastErrorGLE = GetLastError()
ExitFunction
Endif
'pk の圧縮タイプを検出
compressType = autoDetectcmpType()
Endif
' If bNoPFS=FALSE Then ret += pfs.LoadPfsFile( pkPath.genAddedPath(".pfs"))
' If bNoPK =FALSE Then ret += pk.openFile(pkPath.genAddedPath(".pk"),GENERIC_READ)
' If ret<>TRUE*(3-bNoPKH-bNoPFS-bNoPK) Then openArchive=FALSE : Exitfunction
openArchive=TRUE
End Function
'内部ファイルパスを基にファイルアクセス(filenameはNULL可)
Function getFileInfo(path As BytePtr,filename As BytePtr) As *LSPK_FILEINFO
Dim ret As *LSPK_FILEINFO, fullpath As *FilePath
ret=new_LSPK_FILEINFO()
fullpath=new FilePath()
fullpath->SetPath(path)
If filename<> NULL then fullpath->PushFile(filename)
ret->path = fullpath
ret->hash=path2crc(fullpath->GetPath())
ret->index= pkh.GetTableIndexFromHash(ret->hash)
If ret->index = -1 Then
free_LSPK_FILEINFO(ret)
ExitFunction
End If
ret->pkh = pkh.GetPkhInfoBlock(ret->index)
getFileInfo=ret
End Function
'fileInfoからファイルの実バイナリを取得
'使い終わったらfree_bufferで解放
Function getFileBuffer(fileinfo As *LSPK_FILEINFO) As BytePtr
getFileBuffer=calloc(fileinfo->pkh->com_size)
If readPK(fileinfo->pkh->offsetLow,fileinfo->pkh->offsetHigh,getFileBuffer,fileinfo->pkh->com_size) = FALSE Then
free(getFileBuffer)
getFileBuffer=NULL
End If
End Function
'オフセットから直にPKファイルを読む
Function readPK(offsetLo As DWord, offsetHi AS DWord, buffer As BytePtr, length As Long) As BOOL
pk.setFilePtr(offsetLo, offsetHi)
If pk.read(buffer,length)>=0 Then
readPK = TRUE
End If
End Function
/* Function getCurrentDir() As BytePtr
getCurrentDir=curDir.GetPath()
End Function*/
'指定インデックスのディレクトリ情報取得
'使い終わればfree_LSPK_DIRINFOで解放
Function getDirInfo(index As Long) As *LSPK_DIRINFO
Dim ret As *LSPK_DIRINFO
ret=new_LSPK_DIRINFO()
ret->index=index
ret->name=pfs.GetStr(index)
ret->info=pfs.GetDirInfo(index)
getDirInfo=ret
End Function
Function getArchiveName() AS BytePtr
getArchiveName=pkPath.GetFileName()
End Function
Function getLastErrorID() AS Long
getLastErrorID = lastErrorID
EndFunction
Function getLastErrorText() AS BytePtr
if lastErrorID >= _LSPK_ERR_COUNT Then
getLastErrorText="[[UNKNOWN ERROR]]"
ExitFunction
Endif
getLastErrorText = LSPK_ARHIVE_ERROR_TEXT_TBL[lastErrorID]
EndFunction
Function autoDetectcmpType() AS LSPK_COMPRESS_TYPE
Dim cmpType AS LSPK_COMPRESS_TYPE
Dim maybeZlib As BOOL
Dim i AS Long
' 圧縮フォーマットが確定するまで6つぐらい検査
For i=0 To 5
cmpType = checkCompressType(i)
if cmpType = LSPK_CTYPE_UNKNOWN Then
continue
Else if cmpType = LSPK_CTYPE_ZLIB_2 Then
maybeZlib = TRUE
continue
End If
maybeZlib = FALSE
ExitFor
Next
if maybeZlib Then
cmpType=LSPK_CTYPE_ZLIB
debug
Endif
autoDetectcmpType = cmpType
End Function
'----------------------------------------
'
Private
'指定フォルダの再帰調査を開始
Function start_slove(dirId As Long,bFindDir As BOOL) As LSPK_FINDHANDLE
Dim ret As LSPK_FINDHANDLE,dirInfo As *LSPK_DIRINFO
ret=calloc(sizeof(LSPK_FINDDATA))
dirInfo = getDirInfo(dirId)
ret->isDir=bFindDir
ret->parentDir = dirInfo
If bFindDir Then
ret->current=dirInfo->info->start_child_dir
ret->stop = ret->current + dirInfo->info->child_dir_count
Else
ret->current=dirInfo->info->start_child_file
ret->stop=ret->current+dirInfo->info->child_file_count
End If
start_slove=ret
EndFunction
'ファイル名を返す NULL返しで終了 解放不要
Function next_sloveFile(hFind As LSPK_FINDHANDLE) As BytePtr
If hFind->current >= hFind->stop Then ExitFunction
next_sloveFile=pfs.GetFileStr(hFind->current)
hFind->current++
End Function
'次のディレクトリ
Function next_sloveDir(hFind As LSPK_FINDHANDLE) As *LSPK_DIRINFO
If hFind->current >= hFind->stop Then ExitFunction
next_sloveDir=getDirInfo(hFind->current)
hFind->current++
End Function
'----------------------------------------
Function checkCompressType(id AS DWord) AS LSPK_COMPRESS_TYPE
Dim fileInfo AS *PKH_INFO_BLOCK
fileInfo = pkh.GetPkhInfoBlock(id)
Dim firstBytes[3] As Byte,ret AS LSPK_COMPRESS_TYPE
Dim isPkLoaded As BOOL
if pk.getHandle() = NULL Then
isPkLoaded = TRUE
If pk.openFile(pkPath.genAddedPath(".pk"),GENERIC_READ) = FALSE Then
checkCompressType=LSPK_CTYPE_UNKNOWN
ExitFunction
Endif
Else
isPkLoaded = FALSE
Endif
if readPK(fileInfo->offsetLow, fileInfo->offsetHigh, firstBytes,4) = FALSE Then
checkCompressType = LSPK_CTYPE_UNKNOWN
debug
ExitFunction
Endif
Select Case firstBytes[0]
Case &H78
ret = LSPK_CTYPE_ZLIB
Case &H10
ret = LSPK_CTYPE_LZ1X
Case &H11
ret = LSPK_CTYPE_LZ1X
Case Else
'下位4ビットが08hだったらZLIB圧縮の可能性がかすかにある
if (firstBytes[0] And &H0F) = &H08 Then
ret = LSPK_CTYPE_ZLIB_2
Else
ret = LSPK_CTYPE_UNKNOWN
End If
End Select
if isPkLoaded Then
pk.close()
End If
checkCompressType = ret
End Function
Public
Sub free_LSPK_FILEINFO(struct As *LSPK_FILEINFO)
struct->path->Destroy()
delete struct->path
free(struct)
End Sub
Sub free_LSPK_DIRINFO(struct As *LSPK_DIRINFO)
free(struct)
End Sub
Sub free_LSPK_FINDHANDLE(struct As LSPK_FINDHANDLE)
free_LSPK_DIRINFO(struct->parentDir)
free(struct)
End Sub
Sub free_buffer(ptr As BytePtr)
free(ptr)
End Sub
'----------------------------------------
'ディレクトリID, ディレクトリオンリーフラグ,パス(ユーザー側はNULL),コールバック,ユーザーデータ,再帰レベル
Sub slvDir(dirid As Long,bDirOnly As BOOL,path As *FilePath,callback As LSPK_CALLBACK,userdata As VoidPtr,lv As Long)
Dim bDelPath As BOOL
If path=NULL Then
path=new FilePath()
path->setPathSeparator("/")
path->SetPath("")
bDelPath=TRUE
End If
Dim hf As LSPK_FINDHANDLE
hf=start_slove(dirid,TRUE)
Dim cur As *LSPK_DIRINFO
Do
cur=next_sloveDir(hf()) '次のファイルを走査
If cur = NULL Then ExitDo 'ファイルなし
'パスの階層を増やして下層の走査
path->PushDir(cur->name)
'コールバックにディレクトリを通知(ハンドルで判断Dir/File)
If callback(hf,cur,path,userdata,lv)=FALSE Then
free_LSPK_DIRINFO(cur)
ExitDo
End If
slvDir(cur->index,bDirOnly,path,callback,userdata,lv+1) 'sub dir
If bDirOnly=FALSE Then slvFile(cur->index,path,callback,userdata,lv+1) 'current dir files
path->PopDir()
free_LSPK_DIRINFO(cur)
Loop
free_LSPK_FINDHANDLE(hf)
If bDelPath Then
path->Destroy()
delete path
End If
End Sub
Sub slvFile(dirid As Long,path As *FilePath,callback As LSPK_CALLBACK,userdata As VoidPtr,lv As Long)
Dim hf As LSPK_FINDHANDLE
hf=start_slove(dirid,FALSE)
Dim cur As *LSPK_FILEINFO,filename As BytePtr
Do
filename=next_sloveFile(hf())
If filename = NULL Then ExitDo
path->PushFile(filename)
cur=getFileInfo(path->GetPath(),NULL)
If cur<>NULL Then
If callback(hf,cur,path,userdata,lv)=FALSE Then
free_LSPK_FILEINFO(cur)
ExitDo
End If
Else
printf(ex"[File not found!] %s\n",path->GetPath())
End If
path->PopDir()
If cur<>NULL Then free_LSPK_FILEINFO(cur)
Loop
free_LSPK_FINDHANDLE(hf)
End Sub
Private
Function new_LSPK_FILEINFO() As *LSPK_FILEINFO
new_LSPK_FILEINFO=calloc(sizeof(LSPK_FILEINFO))
End Function
Function new_LSPK_DIRINFO() As *LSPK_DIRINFO
new_LSPK_DIRINFO=calloc(sizeof(LSPK_DIRINFO))
End Function
'Windowsの'\'からPKの'/'へ置き換え、小文字化
Function path2crc(str As BytePtr) As DWord
Dim lower As BytePtr , leng As Long , i As long
leng=lstrlen(str)
lower=calloc(leng+1)
memcpy(lower,str,leng)
lower[leng]=0
CharLower(lower)
For i = 0 To leng
If lower[i]=Asc("\") Then lower[i]=Asc("/")
Next i
path2crc=crc32(lower,leng)
free(lower)
EndFunction
End Class
'------------------------------------------------------------------------------
'http://forum.xentax.com/viewtopic.php?f=10&t=5938
'http://rgbacrt.seesaa.net/article/437742154.html
'------------------------------------------------------------------------------
Type PFS_DIR_INFO
dirID As DWord
parentID As DWord
start_child_dir As DWord
child_dir_count As DWord
start_child_file As DWord
child_file_count As DWord
EndType
Class PFS_READER
Private
dir_count As DWord
file_count As DWord
dirInfo As *PFS_DIR_INFO '(24 * num of dir) bytes
strOffsetTable As *DWord
strTable As BytePtr 'NULL TERMINATED
Public
Sub ~PFS_READER()
Destroy()
EndSub
Sub Destroy()
dir_count=0
file_count=0
If dirInfo<>0 Then free(dirInfo):dirInfo=0
If strOffsetTable<>0 Then free(strOffsetTable):strOffsetTable=0
If strTable<>0 Then free(strTable):strTable=0
EndSub
Function LoadPfsFile(FileName As BytePtr) As BOOL
Dim hFile As HANDLE
hFile=OpenFile(FileName,GENERIC_READ)
If hFile=-1 Then hFile=0:LoadPfsFile=FALSE:ExitFunction
'init memory
Destroy()
'Load header area
SetFilePointer(hFile,8,NULL,FILE_BEGIN)
LoadFile(hFile,VarPtr(dir_count),sizeof(DWord))
LoadFile(hFile,VarPtr(file_count),sizeof(DWord))
ChangeEndianDW(dir_count)
ChangeEndianDW(file_count)
If dir_count=0 or file_count=0 Then LoadPfsFile=FALSE:ExitFunction
'Load directry info table
dirInfo=calloc((dir_count+1)*sizeof(PFS_DIR_INFO))
LoadFile(hFile,dirInfo,dir_count*sizeof(PFS_DIR_INFO))
Dim i As Long
For i = 0 To dir_count-1
ChangeEndianDW(dirInfo[i].child_dir_count)
ChangeEndianDW(dirInfo[i].child_file_count)
ChangeEndianDW(dirInfo[i].dirID)
ChangeEndianDW(dirInfo[i].parentID)
ChangeEndianDW(dirInfo[i].start_child_dir)
ChangeEndianDW(dirInfo[i].start_child_file)
Next i
'Print "[dir info table] file pointer : 0x"+Hex$(GetFilePointer(hFile))
'Load string offset table
strOffsetTable=calloc((dir_count+file_count+1)*sizeof(DWord))
LoadFile(hFile,strOffsetTable,(dir_count+file_count)*sizeof(DWord))
For i = 0 To dir_count+file_count-1
ChangeEndianDW(strOffsetTable[i])
Next i
' Print "StringTableStart : 0x"+Hex$(GetFilePointer(hFile))
'Load remain data
strTable=calloc(GetFileSize(hFile,NULL)-GetFilePointer(hFile)+10)
LoadFile(hFile,strTable,GetFileSize(hFile,NULL)-GetFilePointer(hFile))
' Print "PFS End of File : 0x"+Hex$(GetFilePointer(hFile))
CloseHandle(hFile)
LoadPfsFile=TRUE
EndFunction
Function GetDirInfo(ID As Long) As *PFS_DIR_INFO
If dir_count<ID Then debug:ExitFunction
GetDirInfo=VarPtr(dirInfo[ID])
EndFunction
Function GetAllDirCount() As Long
GetAllDirCount=dir_count
EndFunction
Function GetAllFileCount() As Long
GetAllFileCount=file_count
EndFunction
Function GetStrOffset(ID As Long) As DWord
GetStrOffset=strOffsetTable[ID]
EndFunction
Function GetStr(ID As Long) As DWord
GetStr=strTable+strOffsetTable[ID]
EndFunction
Function GetFileStr(ID As Long) As DWord
GetFileStr=strTable+strOffsetTable[ID+dir_count]
EndFunction
End Class
'---------------------------------------------------------------------------------------------
Type PKH_INFO_BLOCK_24
hash As DWord
dummy1 AS DWord
offsetHigh AS DWord
offsetLow As DWord
dec_size As DWord
com_size As DWord
EndType
Type PKH_INFO_BLOCK_16
hash As DWord
offset As DWord
dec_size As DWord
com_size As DWord
EndType
'抽象化されたIFNOBLOCKのデータ
Type PKH_INFO_BLOCK
hash As DWord
offsetLow As DWord
offsetHigh As DWord
dec_size As DWord
com_size As DWord
EndType
Class PKH_READER
Private
cFile As DWord 'file count
PKH_Table As *PKH_INFO_BLOCK
blockSize AS DWord
Public
Sub ~PKH_READER()
Destroy()
EndSub
Sub Destroy()
cFile=0
If PKH_Table<>0 Then free(PKH_Table):PKH_Table=0
EndSub
Function LoadPkhFile(FileName As BytePtr) As LSPK_ARCHIVE_ERROR
Dim hFile As HANDLE
hFile=OpenFile(FileName,GENERIC_READ)
If hFile=-1 then
LoadPkhFile = LSPK_ERR_PKH_OPEN
ExitFunction
Endif
'Init Memory
Destroy()
'Load File Count
LoadFile(hFile,VarPtr(cFile),sizeof(DWord))
ChangeEndianDW(cFile)
Dim tableSize AS DWord
tableSize = GetFileSize(hFile,NULL) - sizeof(DWord)
/*
If cFile*sizeof(PKH_INFO_BLOCK)+sizeof(DWord) <> GetFileSize(hFile,NULL) Then
printf(ex"[Warning][PKH] ファイル数とPKHサイズが一致しません。\n")
'cFile = ( GetFileSize(hFile,NULL) - sizeof(DWord) ) / sizeof(PKH_INFO_BLOCK)
LoadPkhFile=FALSE:ExitFunction
Endif
PKH_Table=calloc(cFile*sizeof(PKH_INFO_BLOCK)+20)
*/
'Load RAW Table
Dim rawTableBuffer AS BytePtr
rawTableBuffer = calloc( tableSize+20 )
LoadFile(hFile,rawTableBuffer,tableSize)
'RAW Table to Abstracted PKH Table
LoadPkhFile = BuildPkhTable(cFile, rawTableBuffer, tableSize)
printf(ex"PkhInfo:\n Count of files : %d\n Actual table size : %d bytes\n Block Size : %d bytes\n\n", cFile, tableSize, blockSize )
if LoadPkhFile <> LSPK_OK Then
ExitFunction
Endif
free(rawTableBuffer) : rawTableBuffer = NULL
CloseHandle(hFile)
LoadPkhFile = LSPK_OK
EndFunction
' PKHの種類が2つあるので中間形式に変換
Function BuildPkhTable(fileCount AS DWord, rawTable AS VoidPtr, tableSize AS DWord) As LSPK_ARCHIVE_ERROR
'Dim blockSize AS DWord // クラス変数に
blockSize = tableSize / fileCount
Dim i aS Long
' PKH16の場合
if blockSize = 16 Then
Dim pkh16 AS *PKH_INFO_BLOCK_16
pkh16=rawTable
'allocate PKH TABLE buffer
PKH_Table = calloc( sizeof(PKH_INFO_BLOCK) * fileCount )
For i = 0 To cFile-1
PKH_Table[i].hash = ReverseDWord(pkh16[i].hash)
PKH_Table[i].offsetLow = ReverseDWord(pkh16[i].offset)
PKH_Table[i].offsetHigh = 0
PKH_Table[i].com_size = ReverseDWord(pkh16[i].com_size)
PKH_Table[i].dec_size = ReverseDWord(pkh16[i].dec_size)
if PKH_Table[i].com_size = 0 Then
PKH_Table[i].com_size = PKH_Table[i].dec_size
Endif
Next i
Elseif blockSize = 24 Then
'rawTable to _24
Dim pkh24 AS *PKH_INFO_BLOCK_24
pkh24 = rawTable
'allocate PKH TABLE buffer
PKH_Table = calloc( sizeof(PKH_INFO_BLOCK) * fileCount )
For i = 0 To cFile-1
PKH_Table[i].hash = ReverseDWord(pkh24[i].hash)
PKH_Table[i].offsetLow = ReverseDWord(pkh24[i].offsetLow)
PKH_Table[i].offsetHigh = ReverseDWord(pkh24[i].offsetHigh)
PKH_Table[i].com_size = ReverseDWord(pkh24[i].com_size)
PKH_Table[i].dec_size = ReverseDWord(pkh24[i].dec_size)
if PKH_Table[i].com_size = 0 Then
PKH_Table[i].com_size = PKH_Table[i].dec_size
Endif
Next i
Else
BuildPkhTable = LSPK_ERR_PKH_FORMAT
ExitFunction
End If
BuildPkhTable = LSPK_OK
End Function
Function GetPkhInfoBlock(ID As DWord) As *PKH_INFO_BLOCK
if ID <= cFile Then
GetPkhInfoBlock=VarPtr(PKH_Table[ID])
Else
GetPkhInfoBlock=NULL
debug
Endif
EndFunction
Function GetFileCount() As Long
GetFileCount=cFile
EndFunction
Function GetOffset(ID As Long) As Long
GetOffset=PKH_Table[ID].offset
EndFunction
Function GetCmpSize(ID As Long) As Long
GetCmpSize=PKH_Table[ID].com_size
EndFunction
Function GetDecSize(ID As Long) As Long
GetDecSize=PKH_Table[ID].dec_size
EndFunction
Function GetHash(ID As Long) As Long
GetHash=PKH_Table[ID].hash
EndFunction
Function GetTableIndexFromHash(CRC32 As DWord) As Long
'二分探索
Dim pivot As DWord, top As DWord, bottom As DWord, i As DWord,dbg As DWord
top=0 : bottom=cFile-1
Do
pivot = ( top + bottom ) / 2
If PKH_Table[pivot].hash=CRC32 Then
' If CRC32 = &H744172D3 As DWord then debug
'発見
GetTableIndexFromHash=pivot
ExitFunction
ElseIf PKH_Table[pivot].hash < CRC32 Then
'上半分を探索
top = pivot + 1
Else'If PKH_Table[pivot].hash > CRC32 Then
'下半分を検索
bottom = pivot - 1
Endif
If dbg = pivot Then debug:Exitdo
dbg=pivot
If top > bottom Then ExitDo
Loop
GetTableIndexFromHash=-1
EndFunction
End Class
'----------------------------------------------------------------------
'CRC32ノーマルのテーブル(CRC32bとは違う)。 main.dolの0x00737AD0あたりに同じくCRCテーブルがある。それと照合したが一致していた。
'256 * 4bytes = 1024Byte
Dim crc32tab[255] = [
&H00000000, &H04C11DB7, &H09823B6E, &H0D4326D9,
&H130476DC, &H17C56B6B, &H1A864DB2, &H1E475005,
&H2608EDB8, &H22C9F00F, &H2F8AD6D6, &H2B4BCB61,
&H350C9B64, &H31CD86D3, &H3C8EA00A, &H384FBDBD,
&H4C11DB70, &H48D0C6C7, &H4593E01E, &H4152FDA9,
&H5F15ADAC, &H5BD4B01B, &H569796C2, &H52568B75,
&H6A1936C8, &H6ED82B7F, &H639B0DA6, &H675A1011,
&H791D4014, &H7DDC5DA3, &H709F7B7A, &H745E66CD,
&H9823B6E0, &H9CE2AB57, &H91A18D8E, &H95609039,
&H8B27C03C, &H8FE6DD8B, &H82A5FB52, &H8664E6E5,
&HBE2B5B58, &HBAEA46EF, &HB7A96036, &HB3687D81,
&HAD2F2D84, &HA9EE3033, &HA4AD16EA, &HA06C0B5D,
&HD4326D90, &HD0F37027, &HDDB056FE, &HD9714B49,
&HC7361B4C, &HC3F706FB, &HCEB42022, &HCA753D95,
&HF23A8028, &HF6FB9D9F, &HFBB8BB46, &HFF79A6F1,
&HE13EF6F4, &HE5FFEB43, &HE8BCCD9A, &HEC7DD02D,
&H34867077, &H30476DC0, &H3D044B19, &H39C556AE,
&H278206AB, &H23431B1C, &H2E003DC5, &H2AC12072,
&H128E9DCF, &H164F8078, &H1B0CA6A1, &H1FCDBB16,
&H018AEB13, &H054BF6A4, &H0808D07D, &H0CC9CDCA,
&H7897AB07, &H7C56B6B0, &H71159069, &H75D48DDE,
&H6B93DDDB, &H6F52C06C, &H6211E6B5, &H66D0FB02,
&H5E9F46BF, &H5A5E5B08, &H571D7DD1, &H53DC6066,
&H4D9B3063, &H495A2DD4, &H44190B0D, &H40D816BA,
&HACA5C697, &HA864DB20, &HA527FDF9, &HA1E6E04E,
&HBFA1B04B, &HBB60ADFC, &HB6238B25, &HB2E29692,
&H8AAD2B2F, &H8E6C3698, &H832F1041, &H87EE0DF6,
&H99A95DF3, &H9D684044, &H902B669D, &H94EA7B2A,
&HE0B41DE7, &HE4750050, &HE9362689, &HEDF73B3E,
&HF3B06B3B, &HF771768C, &HFA325055, &HFEF34DE2,
&HC6BCF05F, &HC27DEDE8, &HCF3ECB31, &HCBFFD686,
&HD5B88683, &HD1799B34, &HDC3ABDED, &HD8FBA05A,
&H690CE0EE, &H6DCDFD59, &H608EDB80, &H644FC637,
&H7A089632, &H7EC98B85, &H738AAD5C, &H774BB0EB,
&H4F040D56, &H4BC510E1, &H46863638, &H42472B8F,
&H5C007B8A, &H58C1663D, &H558240E4, &H51435D53,
&H251D3B9E, &H21DC2629, &H2C9F00F0, &H285E1D47,
&H36194D42, &H32D850F5, &H3F9B762C, &H3B5A6B9B,
&H0315D626, &H07D4CB91, &H0A97ED48, &H0E56F0FF,
&H1011A0FA, &H14D0BD4D, &H19939B94, &H1D528623,
&HF12F560E, &HF5EE4BB9, &HF8AD6D60, &HFC6C70D7,
&HE22B20D2, &HE6EA3D65, &HEBA91BBC, &HEF68060B,
&HD727BBB6, &HD3E6A601, &HDEA580D8, &HDA649D6F,
&HC423CD6A, &HC0E2D0DD, &HCDA1F604, &HC960EBB3,
&HBD3E8D7E, &HB9FF90C9, &HB4BCB610, &HB07DABA7,
&HAE3AFBA2, &HAAFBE615, &HA7B8C0CC, &HA379DD7B,
&H9B3660C6, &H9FF77D71, &H92B45BA8, &H9675461F,
&H8832161A, &H8CF30BAD, &H81B02D74, &H857130C3,
&H5D8A9099, &H594B8D2E, &H5408ABF7, &H50C9B640,
&H4E8EE645, &H4A4FFBF2, &H470CDD2B, &H43CDC09C,
&H7B827D21, &H7F436096, &H7200464F, &H76C15BF8,
&H68860BFD, &H6C47164A, &H61043093, &H65C52D24,
&H119B4BE9, &H155A565E, &H18197087, &H1CD86D30,
&H029F3D35, &H065E2082, &H0B1D065B, &H0FDC1BEC,
&H3793A651, &H3352BBE6, &H3E119D3F, &H3AD08088,
&H2497D08D, &H2056CD3A, &H2D15EBE3, &H29D4F654,
&HC5A92679, &HC1683BCE, &HCC2B1D17, &HC8EA00A0,
&HD6AD50A5, &HD26C4D12, &HDF2F6BCB, &HDBEE767C,
&HE3A1CBC1, &HE760D676, &HEA23F0AF, &HEEE2ED18,
&HF0A5BD1D, &HF464A0AA, &HF9278673, &HFDE69BC4,
&H89B8FD09, &H8D79E0BE, &H803AC667, &H84FBDBD0,
&H9ABC8BD5, &H9E7D9662, &H933EB0BB, &H97FFAD0C,
&HAFB010B1, &HAB710D06, &HA6322BDF, &HA2F33668,
&HBCB4666D, &HB8757BDA, &HB5365D03, &HB1F740B4, ] As DWord
Function crc32(data As BytePtr,len As DWord) As DWord
crc32 = &HFFFFFFFF
While len
crc32 = (crc32 << 8) xor crc32tab[(crc32 >> 24) xor ((data[0]) and &HFF)]
len--
data++
Wend
crc32 = NOT(crc32)
EndFunction
Function crc32str(str As BytePtr) As Long
crc32str=crc32(str,lstrlen(str))
EndFunction