Added ability to extract all TIMs to PNG; Now PNG's name includes CLUT index.

This commit is contained in:
meffi@lab313.ru
2014-04-10 23:22:23 +00:00
parent 1d63ac1b95
commit 90c0e78a66
9 changed files with 278 additions and 169 deletions

View File

@@ -6,7 +6,7 @@
<MainSource>tim2view.dpr</MainSource> <MainSource>tim2view.dpr</MainSource>
<Base>True</Base> <Base>True</Base>
<Config Condition="'$(Config)'==''">Release</Config> <Config Condition="'$(Config)'==''">Release</Config>
<Platform Condition="'$(Platform)'==''">Win64</Platform> <Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>3</TargetedPlatforms> <TargetedPlatforms>3</TargetedPlatforms>
<AppType>Application</AppType> <AppType>Application</AppType>
</PropertyGroup> </PropertyGroup>

Binary file not shown.

View File

@@ -78,12 +78,15 @@ begin
Exit; Exit;
pFile := GetMemory(cSectorHeaderSize); pFile := GetMemory(cSectorHeaderSize);
try
tmp := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); tmp := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
tmp.Read(pFile^[0], cSectorHeaderSize); tmp.Read(pFile^[0], cSectorHeaderSize);
Result := ((Sz mod cSectorSize) = 0) and Result := ((Sz mod cSectorSize) = 0) and (CompareMem(@cSectorHeader, pFile, cSectorHeaderSize));
(CompareMem(@cSectorHeader, pFile, cSectorHeaderSize)); finally
tmp.free; tmp.free;
FreeMemory(pFile); FreeMemory(pFile);
end;
end; end;
procedure ReplaceTimInFileFromMemory(const FileName: string; TIM: PTIM; procedure ReplaceTimInFileFromMemory(const FileName: string; TIM: PTIM;

View File

@@ -7,16 +7,19 @@ uses
const const
cProgramName = 'Tim2View by [Lab 313]'; cProgramName = 'Tim2View by [Lab 313]';
cProgramVersion = '2.0 Stable'; cProgramVersion = '2.0 Release';
cExtractedTimsDir = 'TIMS'; cExtractedTimsDir = 'TIMS';
cExtractedPngsDir = 'PNGS';
cMaxFileSize = $2EAEED80; cMaxFileSize = $2EAEED80;
cAutoExtractionTimFormat = '%s_%.6d_%.2db' + '.tim'; cAutoExtractionTimFormat = '%s_%.6d_%.2db' + '.tim';
cAutoExtractionPngFormat = '%s_%.6d_%.2db_%.2dc' + '.png';
cCLUTGridColsCount = 32; cCLUTGridColsCount = 32;
sStatusBarScanningFile = 'Scanning File...'; sStatusBarScanningFile = 'Scanning File...';
sStatusBarTimsExtracting = 'TIMs Extracting...'; sStatusBarTimsExtracting = 'TIMs Extracting...';
sStatusBarTimsExtracted = 'Exctracted Successfully!'; sStatusBarPngsExtracting = 'PNGs Extracting...';
sStatusBarExtracted = 'Exctracted Successfully!';
sStatusBarParsingResult = 'Parsing Result...'; sStatusBarParsingResult = 'Parsing Result...';
sScanResultGood = 'Scan completed!'; sScanResultGood = 'Scan completed!';
sSelectDirCaption = 'Please, select directory for scan...'; sSelectDirCaption = 'Please, select directory for scan...';

View File

@@ -576,9 +576,9 @@ object frmMain: TfrmMain
TabOrder = 0 TabOrder = 0
object lvList: TListView object lvList: TListView
Left = 0 Left = 0
Top = 0 Top = 49
Width = 240 Width = 240
Height = 481 Height = 432
Align = alClient Align = alClient
Columns = < Columns = <
item item
@@ -613,6 +613,39 @@ object frmMain: TfrmMain
ViewStyle = vsReport ViewStyle = vsReport
OnChange = lvListChange OnChange = lvListChange
OnData = lvListData OnData = lvListData
ExplicitLeft = 1
ExplicitTop = 28
ExplicitHeight = 448
end
object pnlExtractAll: TPanel
Left = 0
Top = 0
Width = 240
Height = 49
Align = alTop
BevelOuter = bvLowered
TabOrder = 1
object btnExtractAllTims: TButton
Left = 139
Top = 1
Width = 100
Height = 47
Action = actExtractPNGs
Align = alRight
TabOrder = 0
WordWrap = True
ExplicitLeft = 128
end
object btnExtractPNGs: TButton
Left = 1
Top = 1
Width = 100
Height = 47
Action = actExtractTIMs
Align = alLeft
TabOrder = 1
WordWrap = True
end
end end
end end
object pnlImage: TPanel object pnlImage: TPanel
@@ -923,11 +956,17 @@ object frmMain: TfrmMain
Caption = '&Open TIMs with T2V' Caption = '&Open TIMs with T2V'
OnExecute = actAssocTimsExecute OnExecute = actAssocTimsExecute
end end
object actExtractList: TAction object actExtractTIMs: TAction
Caption = '&Extract TIMs' Caption = 'Extract all &TIMs'#13#10'(Shift+F2)'
Enabled = False Enabled = False
ShortCut = 112 ShortCut = 8305
OnExecute = actExtractListExecute OnExecute = actExtractTIMsExecute
end
object actExtractPNGs: TAction
Caption = '&Extract all PNGs'#13#10'(Shift+F4)'
Enabled = False
ShortCut = 8307
OnExecute = actExtractPNGsExecute
end end
object actChangeClutIdx: TAction object actChangeClutIdx: TAction
end end
@@ -941,12 +980,6 @@ object frmMain: TfrmMain
object pmList: TPopupMenu object pmList: TPopupMenu
Left = 640 Left = 640
Top = 502 Top = 502
object ExtractTIMs1: TMenuItem
Action = actExtractList
end
object N6: TMenuItem
Caption = '-'
end
object ExtractTIM1: TMenuItem object ExtractTIM1: TMenuItem
Action = actExtractTim Action = actExtractTim
end end

View File

@@ -77,14 +77,16 @@ type
mnTimInfoMain: TMenuItem; mnTimInfoMain: TMenuItem;
actAssocTims: TAction; actAssocTims: TAction;
mnAssociate: TMenuItem; mnAssociate: TMenuItem;
N6: TMenuItem; actExtractTIMs: TAction;
actExtractList: TAction;
ExtractTIMs1: TMenuItem;
pbTim: TImage; pbTim: TImage;
btnShowClut: TButton; btnShowClut: TButton;
cbbCLUT: TComboBox; cbbCLUT: TComboBox;
actReturnFocus: TAction; actReturnFocus: TAction;
actDrawSelectedTim: TAction; actDrawSelectedTim: TAction;
actExtractPNGs: TAction;
pnlExtractAll: TPanel;
btnExtractAllTims: TButton;
btnExtractPNGs: TButton;
procedure btnStopScanClick(Sender: TObject); procedure btnStopScanClick(Sender: TObject);
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure lvListData(Sender: TObject; Item: TListItem); procedure lvListData(Sender: TObject; Item: TListItem);
@@ -107,13 +109,14 @@ type
procedure actStretchExecute(Sender: TObject); procedure actStretchExecute(Sender: TObject);
procedure actTimInfoExecute(Sender: TObject); procedure actTimInfoExecute(Sender: TObject);
procedure actAssocTimsExecute(Sender: TObject); procedure actAssocTimsExecute(Sender: TObject);
procedure actExtractListExecute(Sender: TObject); procedure actExtractTIMsExecute(Sender: TObject);
procedure cbbTranspModeChange(Sender: TObject); procedure cbbTranspModeChange(Sender: TObject);
procedure btnShowClutClick(Sender: TObject); procedure btnShowClutClick(Sender: TObject);
procedure lvListChange(Sender: TObject; Item: TListItem; procedure lvListChange(Sender: TObject; Item: TListItem;
Change: TItemChange); Change: TItemChange);
procedure actReturnFocusExecute(Sender: TObject); procedure actReturnFocusExecute(Sender: TObject);
procedure actDrawSelectedTimExecute(Sender: TObject); procedure actDrawSelectedTimExecute(Sender: TObject);
procedure actExtractPNGsExecute(Sender: TObject);
private private
{ Private declarations } { Private declarations }
// pResult: PNativeXml; // pResult: PNativeXml;
@@ -134,7 +137,8 @@ type
function ListIdx: Integer; function ListIdx: Integer;
function TimIdx(Index: Integer): TScanTim; function TimIdx(Index: Integer): TScanTim;
function SelTim(NewBitMode: Integer = $FF): PTIM; function SelTim(NewBitMode: Integer = $FF): PTIM;
function SelTimName: string; function FormatTimName(const FileName: string; ListIdx_, BitMode: Integer): string;
function FormatPngName(const FileName: string; ListIdx_, BitMode, Clut: Integer): string;
procedure DrawSelTim; procedure DrawSelTim;
procedure DrawSelClut; procedure DrawSelClut;
procedure UpdateCLUTInfo; procedure UpdateCLUTInfo;
@@ -158,7 +162,7 @@ var
implementation implementation
uses uses
uCDIMAGE, uBrowseForFolder, System.Win.Registry; uCDIMAGE, uBrowseForFolder, System.Win.Registry, Vcl.Imaging.pngimage;
{$R *.dfm} {$R *.dfm}
@@ -319,10 +323,10 @@ begin
Close; Close;
end; end;
procedure TfrmMain.actExtractListExecute(Sender: TObject); procedure TfrmMain.actExtractTIMsExecute(Sender: TObject);
var var
I, OFFSET, BIT_MODE, SIZE: Integer; I, OFFSET, BIT_MODE, SIZE: Integer;
FName, TIM_NAME, Path: string; FName, Path: string;
IsImage: Boolean; IsImage: Boolean;
ScanTim: TScanTim; ScanTim: TScanTim;
TIM: PTIM; TIM: PTIM;
@@ -332,6 +336,8 @@ begin
FName := ScanRes.ScanFile; FName := ScanRes.ScanFile;
IsImage := ScanRes.IsImage; IsImage := ScanRes.IsImage;
pbProgress.Position := 0;
pbProgress.Max := ScanRes.Count;
for I := 1 to ScanRes.Count do for I := 1 to ScanRes.Count do
begin begin
ScanTim := TimIdx(I - 1); ScanTim := TimIdx(I - 1);
@@ -339,26 +345,79 @@ begin
SIZE := ScanTim.Size; SIZE := ScanTim.Size;
BIT_MODE := ScanTim.BitMode; BIT_MODE := ScanTim.BitMode;
TIM_NAME := Format(cAutoExtractionTimFormat, [ExtractJustName(FName), I, BIT_MODE]);
Path := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)) + cExtractedTimsDir); Path := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)) + cExtractedTimsDir);
CreateDir(Path); CreateDir(Path);
Path := IncludeTrailingPathDelimiter(Path + ExtractFileName(FName)); Path := IncludeTrailingPathDelimiter(Path + ExtractFileName(FName));
CreateDir(Path); CreateDir(Path);
TIM := LoadTimFromFile(FName, OFFSET, IsImage, SIZE); TIM := LoadTimFromFile(FName, OFFSET, IsImage, SIZE);
SaveTimToFile(Path + TIM_NAME, TIM); SaveTimToFile(Path + FormatTimName(FName, I - 1, BIT_MODE), TIM);
FreeTIM(TIM); FreeTIM(TIM);
pbProgress.Position := I;
Application.ProcessMessages;
end; end;
lblStatus.Caption := sStatusBarTimsExtracted; lblStatus.Caption := sStatusBarExtracted;
MessageBeep(MB_ICONINFORMATION); MessageBeep(MB_ICONINFORMATION);
pbProgress.Position := 0;
end;
procedure TfrmMain.actExtractPNGsExecute(Sender: TObject);
var
I, OFFSET, BIT_MODE, SIZE: Integer;
FName, Path: string;
IsImage: Boolean;
ScanTim: TScanTim;
TIM: PTIM;
PNG_: PPNGImage;
begin
lblStatus.Caption := sStatusBarPngsExtracting;
FName := ScanRes.ScanFile;
IsImage := ScanRes.IsImage;
New(PNG_);
pbProgress.Position := 0;
pbProgress.Max := ScanRes.Count;
for I := 1 to ScanRes.Count do
begin
ScanTim := TimIdx(I - 1);
OFFSET := ScanTim.Position;
SIZE := ScanTim.Size;
BIT_MODE := ScanTim.BitMode;
Path := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)) + cExtractedPngsDir);
CreateDir(Path);
Path := IncludeTrailingPathDelimiter(Path + ExtractFileName(FName));
CreateDir(Path);
PNG_^ := TPngImage.CreateBlank(COLOR_RGBALPHA, 16, ScanTim.Width, ScanTim.Height);
PNG_^.CompressionLevel := 0;
PNG_^.Filters := [];
TIM := LoadTimFromFile(FName, OFFSET, IsImage, SIZE);
TimToPNG(TIM, cbbCLUT.ItemIndex, PNG_, cbbTranspMode.ItemIndex);
PNG_^.SaveToFile(Path + FormatPngName(FName, I - 1, BIT_MODE, 0));
PNG_^.Free;
FreeTIM(TIM);
pbProgress.Position := I;
Application.ProcessMessages;
end;
Dispose(PNG_);
lblStatus.Caption := sStatusBarExtracted;
MessageBeep(MB_ICONINFORMATION);
pbProgress.Position := 0;
end; end;
procedure TfrmMain.actExtractTimExecute(Sender: TObject); procedure TfrmMain.actExtractTimExecute(Sender: TObject);
var var
TIM: PTIM; TIM: PTIM;
begin begin
dlgSaveTIM.FileName := SelTimName; dlgSaveTIM.FileName := FormatTimName(ScanRes.ScanFile, ListIdx, TimIdx(ListIdx).BitMode);
if not dlgSaveTIM.Execute then Exit; if not dlgSaveTIM.Execute then Exit;
@@ -423,12 +482,8 @@ begin
end; end;
procedure TfrmMain.actTim2PngExecute(Sender: TObject); procedure TfrmMain.actTim2PngExecute(Sender: TObject);
var
FName: string;
begin begin
FName := SelTimName; dlgSavePNG.FileName := FormatPngName(ScanRes.ScanFile, ListIdx, TimIdx(ListIdx).BitMode, cbbCLUT.ItemIndex);
FName := ChangeFileExt(FName, '.png');
dlgSavePNG.FileName := FName;
if not dlgSavePNG.Execute then Exit; if not dlgSavePNG.Execute then Exit;
@@ -459,8 +514,8 @@ begin
+ Tab + '%s' + Row + Row + + Tab + '%s' + Row + Row +
'HEADER INFO' + Row + 'Version:' + Tab + '%d' + Row + 'BPP:' + Tab + '%d' 'HEADER INFO' + Row + 'Version:' + Tab + '%d' + Row + 'BPP:' + Tab + '%d'
+ Row + Row, [SelTimName, Index + 1, TimIdx(Index).Position, + Row + Row, [FormatTimName(ScanRes.ScanFile, Index, TimIdx(Index).BitMode),
BppToBitMode(TIM), IsGoodTIM, Index + 1, TimIdx(Index).Position, BppToBitMode(TIM), IsGoodTIM,
GetTimVersion(TIM), GetTimBPP(TIM)]); GetTimVersion(TIM), GetTimBPP(TIM)]);
@@ -558,7 +613,8 @@ begin
cbbFiles.Enabled := (cbbFiles.Items.Count <> 0); cbbFiles.Enabled := (cbbFiles.Items.Count <> 0);
lvList.Enabled := cbbFiles.Enabled; lvList.Enabled := cbbFiles.Enabled;
actExtractList.Enabled := cbbFiles.Enabled; actExtractTIMs.Enabled := cbbFiles.Enabled;
actExtractPNGs.Enabled := cbbFiles.Enabled;
actCloseFile.Enabled := cbbFiles.Enabled; actCloseFile.Enabled := cbbFiles.Enabled;
actCloseFiles.Enabled := cbbFiles.Enabled; actCloseFiles.Enabled := cbbFiles.Enabled;
actReplaceTim.Enabled := (lvList.SelCount = 1); actReplaceTim.Enabled := (lvList.SelCount = 1);
@@ -587,9 +643,14 @@ begin
Result^.HEAD^.bBPP := NewBitMode; Result^.HEAD^.bBPP := NewBitMode;
end; end;
function TfrmMain.SelTimName: string; function TfrmMain.FormatTimName(const FileName: string; ListIdx_, BitMode: Integer): string;
begin begin
Result := Format(cAutoExtractionTimFormat, [ExtractJustName(ScanRes.ScanFile), ListIdx + 1, TimIdx(ListIdx).BitMode]); Result := Format(cAutoExtractionTimFormat, [ExtractJustName(FileName), ListIdx_ + 1, BitMode]);
end;
function TfrmMain.FormatPngName(const FileName: string; ListIdx_, BitMode, Clut: Integer): string;
begin
Result := Format(cAutoExtractionPngFormat, [ExtractJustName(FileName), ListIdx_ + 1, BitMode, Clut + 1]);
end; end;
procedure TfrmMain.DrawSelClut; procedure TfrmMain.DrawSelClut;
@@ -647,10 +708,10 @@ begin
PNG^ := nil; PNG^ := nil;
end; end;
if cbbCLUT.Text = sThisTimHasNoClut then (*if cbbCLUT.Text = sThisTimHasNoClut then
Index := -1 Index := -1
else else
Index := cbbCLUT.ItemIndex; *)Index := cbbCLUT.ItemIndex;
TimToPNG(TIM, Index, PNG, cbbTranspMode.ItemIndex); TimToPNG(TIM, Index, PNG, cbbTranspMode.ItemIndex);
PNG.AssignTo(pbTim.Picture.Bitmap); PNG.AssignTo(pbTim.Picture.Bitmap);

View File

@@ -89,10 +89,7 @@ var
begin begin
Synchronize(StartScan); Synchronize(StartScan);
pSrcFileStream := TFileStream.Create(pScanResult.ScanFile, fmOpenRead or try
fmShareDenyWrite);
pSrcFileStream.Position := 0;
if pScanResult.IsImage then if pScanResult.IsImage then
pSectorBufferSize := cSectorBufferSize pSectorBufferSize := cSectorBufferSize
else else
@@ -103,6 +100,11 @@ begin
SectorBuffer := GetMemory(pSectorBufferSize); SectorBuffer := GetMemory(pSectorBufferSize);
ClearBuffer := GetMemory(pClearBufferSize); ClearBuffer := GetMemory(pClearBufferSize);
pSrcFileStream := TFileStream.Create(pScanResult.ScanFile, fmOpenRead or
fmShareDenyWrite);
pSrcFileStream.Position := 0;
TIM := CreateTIM; TIM := CreateTIM;
pStatusText := sStatusBarScanningFile; pStatusText := sStatusBarScanningFile;
@@ -160,6 +162,7 @@ begin
ClearSectorBuffer(SectorBuffer, ClearBuffer); ClearSectorBuffer(SectorBuffer, ClearBuffer);
end; end;
end; end;
finally
FreeTIM(TIM); FreeTIM(TIM);
FreeMemory(SectorBuffer); FreeMemory(SectorBuffer);
FreeMemory(ClearBuffer); FreeMemory(ClearBuffer);
@@ -170,6 +173,7 @@ begin
pStatusText := ''; pStatusText := '';
Synchronize(FinishScan); Synchronize(FinishScan);
end;
end; end;
procedure TScanThread.FinishScan; procedure TScanThread.FinishScan;
@@ -201,7 +205,8 @@ procedure TScanThread.StartScan;
begin begin
frmMain.cbbFiles.Enabled := False; frmMain.cbbFiles.Enabled := False;
frmMain.lvList.Enabled := False; frmMain.lvList.Enabled := False;
frmMain.actExtractList.Enabled := False; frmMain.actExtractTIMs.Enabled := False;
frmMain.actExtractPNGs.Enabled := False;
frmMain.pbProgress.Max := GetFileSizeAPI(pScanResult.ScanFile); frmMain.pbProgress.Max := GetFileSizeAPI(pScanResult.ScanFile);
frmMain.pbProgress.Position := 0; frmMain.pbProgress.Position := 0;

View File

@@ -35,19 +35,19 @@ unit uSettings;
{ TSettings } { TSettings }
procedure TCustomSettings.LoadFromFile() ; procedure TCustomSettings.LoadFromFile() ;
var var
Stream: TStream; Stream: TStream;
begin begin
if not FileExists(FFileName) then Exit; if not FileExists(FFileName) then Exit;
Stream := TFileStream.Create(FFileName, fmOpenRead or fmShareDenyWrite) ;
try try
Stream := TFileStream.Create(FFileName, fmOpenRead or fmShareDenyWrite) ;
LoadFromStream(Stream) ; LoadFromStream(Stream) ;
finally finally
Stream.Free; Stream.Free;
end; end;
end; end;
procedure TCustomSettings.LoadFromStream(const Stream: TStream) ; procedure TCustomSettings.LoadFromStream(const Stream: TStream) ;
var var

View File

@@ -372,6 +372,7 @@ var
Sector: TCDSector; Sector: TCDSector;
P, TIM_FULL_SECTORS: Integer; P, TIM_FULL_SECTORS: Integer;
begin begin
try
sImageStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); sImageStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
TimSectorNumber := Position div cSectorSize + 1; TimSectorNumber := Position div cSectorSize + 1;
@@ -416,12 +417,13 @@ begin
LastPartSize := SIZE - P; LastPartSize := SIZE - P;
Move(Sector.dwData[0], TIM_BUF^[P], LastPartSize); Move(Sector.dwData[0], TIM_BUF^[P], LastPartSize);
end; end;
finally
P := 0; P := 0;
Result := nil; Result := nil;
LoadTimFromBuf(TIM_BUF, Result, P); LoadTimFromBuf(TIM_BUF, Result, P);
sImageStream.Free; sImageStream.Free;
Dispose(TIM_BUF); Dispose(TIM_BUF);
end;
end; end;
function LoadTimFromStream(Stream: TStream; var Position: Integer; function LoadTimFromStream(Stream: TStream; var Position: Integer;
@@ -455,9 +457,12 @@ var
begin begin
if not ImageScan then if not ImageScan then
begin begin
try
sTIM := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); sTIM := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
Result := LoadTimFromStream(sTIM, Position, dwSize); Result := LoadTimFromStream(sTIM, Position, dwSize);
finally
sTIM.Free; sTIM.Free;
end;
Exit; Exit;
end; end;
@@ -468,8 +473,7 @@ procedure SaveTimToFile(const FileName: string; TIM: PTIM);
var var
tmp: TMemoryStream; tmp: TMemoryStream;
begin begin
if TIM = nil then if TIM = nil then Exit;
Exit;
tmp := TMemoryStream.Create; tmp := TMemoryStream.Create;
tmp.Write(TIM^.DATA^[0], TIM^.dwSize); tmp.Write(TIM^.DATA^[0], TIM^.dwSize);