mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 07:31:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
171
Code/Tools/MixViewer/AVAssetSuck.cpp
Normal file
171
Code/Tools/MixViewer/AVAssetSuck.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "avassetsuck.h"
|
||||
#include "ffactory.h"
|
||||
#include "mixfile.h"
|
||||
#include "rawfile.h"
|
||||
#include "bittype.h"
|
||||
#include "mixcombiningdialog.h"
|
||||
|
||||
|
||||
|
||||
|
||||
AVAssetSuckerClass::AVAssetSuckerClass(void) :
|
||||
Dialog(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AVAssetSuckerClass::Suck(char *input_file, char *output_file)
|
||||
{
|
||||
strcpy(InputFile, input_file);
|
||||
strcpy(OutputFile, output_file);
|
||||
|
||||
//
|
||||
// Kick off the worker thread...
|
||||
//
|
||||
::AfxBeginThread (Do_Stuff, (LPVOID)this);
|
||||
|
||||
//
|
||||
// Show the UI
|
||||
//
|
||||
MixCombiningDialogClass dialog;
|
||||
Dialog = &dialog;
|
||||
dialog.DoModal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned int AVAssetSuckerClass::Do_Stuff(void *param)
|
||||
{
|
||||
((AVAssetSuckerClass*)param)->Thread_Suck();
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
void AVAssetSuckerClass::Thread_Suck(void)
|
||||
{
|
||||
char name[_MAX_PATH];
|
||||
|
||||
while (Dialog == NULL) {
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Get just the file name.
|
||||
*/
|
||||
char justname[_MAX_PATH];
|
||||
_splitpath(InputFile, NULL, NULL, justname, NULL);
|
||||
char text[_MAX_PATH + 128];
|
||||
sprintf(text, "Copying files from %s...", justname);
|
||||
|
||||
Dialog->Set_Title("Stripping AV assets...");
|
||||
Dialog->Set_Status_Text(text);
|
||||
Dialog->Set_Progress_Percent (0);
|
||||
|
||||
MixFileFactoryClass mix_in(InputFile, _TheFileFactory);
|
||||
if (mix_in.Is_Valid() && mix_in.Build_Internal_Filename_List()) {
|
||||
|
||||
/*
|
||||
** Get the list of files in the source mix file.
|
||||
*/
|
||||
DynamicVectorClass<StringClass> filename_list;
|
||||
mix_in.Get_Filename_List(filename_list);
|
||||
|
||||
/*
|
||||
** Create the output mix file.
|
||||
*/
|
||||
MixFileCreator mix_out(OutputFile);
|
||||
|
||||
/*
|
||||
** Loop through all the files copying anything that isn't audio or texture.
|
||||
*/
|
||||
for (int i=0 ; i<filename_list.Count() ; i++) {
|
||||
|
||||
strcpy(name, filename_list[i].Peek_Buffer());
|
||||
strupr(name);
|
||||
|
||||
if (strstr(name, ".WAV") == 0) {
|
||||
if (strstr(name, ".TGA") == 0) {
|
||||
if (strstr(name, ".DDS") == 0) {
|
||||
if (strstr(name, ".MP3") == 0) {
|
||||
Copy_File(&mix_in, &mix_out, filename_list[i].Peek_Buffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dialog->Set_Progress_Percent((float)i / float(filename_list.Count() + 1));
|
||||
}
|
||||
}
|
||||
Dialog->PostMessage(WM_COMMAND, MAKELPARAM(IDOK, BN_CLICKED));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AVAssetSuckerClass::Copy_File(MixFileFactoryClass *src_mix, MixFileCreator *dest_mix, char *filename)
|
||||
{
|
||||
//
|
||||
// Get the file data from the source mix
|
||||
//
|
||||
FileClass *src_file = src_mix->Get_File (filename);
|
||||
src_file->Open ();
|
||||
int size = src_file->Size();
|
||||
|
||||
//
|
||||
// Create a temporary destination file for the data
|
||||
//
|
||||
char temp_file_name[_MAX_PATH];
|
||||
char temp_path[_MAX_PATH];
|
||||
int chars = GetTempPath(_MAX_PATH, temp_path);
|
||||
if (chars) {
|
||||
int res = GetTempFileName(temp_path, "MIX", 0, temp_file_name);
|
||||
if (res == 0) {
|
||||
WWDEBUG_SAY(("GetTempFileName failed with error code %d\n", GetLastError()));
|
||||
} else {
|
||||
RawFileClass temp_file(temp_file_name);
|
||||
if (temp_file.Open(RawFileClass::WRITE)) {
|
||||
|
||||
//
|
||||
// Save the data in the temp file.
|
||||
//
|
||||
void *bigbuf = new char [size + 1024];
|
||||
src_file->Read(bigbuf, size);
|
||||
temp_file.Write(bigbuf, size);
|
||||
temp_file.Close();
|
||||
|
||||
//
|
||||
// Add the temp file to the mix file.
|
||||
//
|
||||
dest_mix->Add_File(temp_file_name, filename);
|
||||
|
||||
//
|
||||
// Delete the temp file.
|
||||
//
|
||||
DeleteFile(temp_file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
src_mix->Return_File(src_file);
|
||||
}
|
||||
51
Code/Tools/MixViewer/AVAssetSuck.h
Normal file
51
Code/Tools/MixViewer/AVAssetSuck.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _AVASSETSUCK_H
|
||||
#define _AVASSETSUCK_H
|
||||
|
||||
class MixFileFactoryClass;
|
||||
class MixFileCreator;
|
||||
class MixCombiningDialogClass;
|
||||
|
||||
|
||||
|
||||
class AVAssetSuckerClass
|
||||
{
|
||||
public:
|
||||
AVAssetSuckerClass(void);
|
||||
void Suck(char *input_file, char *output_file);
|
||||
static unsigned int Do_Stuff(void *param);
|
||||
void Thread_Suck(void);
|
||||
|
||||
|
||||
private:
|
||||
void Copy_File(MixFileFactoryClass *src_mix, MixFileCreator *dest_mix, char *filename);
|
||||
|
||||
MixCombiningDialogClass *Dialog;
|
||||
char InputFile[1024];
|
||||
char OutputFile[1024];
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //_AVASSETSUCK_H
|
||||
747
Code/Tools/MixViewer/MainFrm.cpp
Normal file
747
Code/Tools/MixViewer/MainFrm.cpp
Normal file
@@ -0,0 +1,747 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// MainFrm.cpp : implementation of the CMainFrame class
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "mixviewer.h"
|
||||
#include "mainfrm.h"
|
||||
#include "wwstring.h"
|
||||
#include "duplicatecombiner.h"
|
||||
#include "wwfile.h"
|
||||
#include "ffactory.h"
|
||||
#include "mixfile.h"
|
||||
#include "avassetsuck.h"
|
||||
#include "mixpatchmaker.h"
|
||||
#include "ffactory.h"
|
||||
#include "mixfile.h"
|
||||
#include "mixviewerdoc.h"
|
||||
#include "makemixfiledialog.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMainFrame
|
||||
|
||||
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
|
||||
|
||||
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
|
||||
//{{AFX_MSG_MAP(CMainFrame)
|
||||
ON_WM_CREATE()
|
||||
ON_COMMAND(IDM_COMBINE_DUPLICATES, OnCombineDuplicates)
|
||||
ON_COMMAND(IDM_CREATE_MIX_FILE, OnCreateMixFile)
|
||||
ON_COMMAND(IDM_EXPORT_FILES, OnExportFiles)
|
||||
ON_COMMAND(IDM_REMOVE_AV_ASSETS, OnRemoveAVAssets)
|
||||
ON_COMMAND(IDM_MAKE_MIX_PATCH, OnMakeMixPatch)
|
||||
ON_WM_DROPFILES()
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
static UINT indicators[] =
|
||||
{
|
||||
ID_SEPARATOR, // status line indicator
|
||||
ID_INDICATOR_CAPS,
|
||||
ID_INDICATOR_NUM,
|
||||
ID_INDICATOR_SCRL,
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMainFrame construction/destruction
|
||||
|
||||
CMainFrame::CMainFrame()
|
||||
{
|
||||
// TODO: add member initialization code here
|
||||
|
||||
}
|
||||
|
||||
CMainFrame::~CMainFrame()
|
||||
{
|
||||
}
|
||||
|
||||
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
||||
{
|
||||
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
|
||||
return -1;
|
||||
|
||||
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
|
||||
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
|
||||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
|
||||
{
|
||||
TRACE0("Failed to create toolbar\n");
|
||||
return -1; // fail to create
|
||||
}
|
||||
|
||||
if (!m_wndStatusBar.Create(this) ||
|
||||
!m_wndStatusBar.SetIndicators(indicators,
|
||||
sizeof(indicators)/sizeof(UINT)))
|
||||
{
|
||||
TRACE0("Failed to create status bar\n");
|
||||
return -1; // fail to create
|
||||
}
|
||||
|
||||
// TODO: Delete these three lines if you don't want the toolbar to
|
||||
// be dockable
|
||||
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
|
||||
EnableDocking(CBRS_ALIGN_ANY);
|
||||
DockControlBar(&m_wndToolBar);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
|
||||
{
|
||||
if( !CFrameWnd::PreCreateWindow(cs) )
|
||||
return FALSE;
|
||||
// TODO: Modify the Window class or styles here by modifying
|
||||
// the CREATESTRUCT cs
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMainFrame diagnostics
|
||||
|
||||
#ifdef _DEBUG
|
||||
void CMainFrame::AssertValid() const
|
||||
{
|
||||
CFrameWnd::AssertValid();
|
||||
}
|
||||
|
||||
void CMainFrame::Dump(CDumpContext& dc) const
|
||||
{
|
||||
CFrameWnd::Dump(dc);
|
||||
}
|
||||
|
||||
#endif //_DEBUG
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMainFrame message handlers
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Filename_From_Path
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
CString
|
||||
Get_Filename_From_Path (LPCTSTR path)
|
||||
{
|
||||
// Find the last occurance of the directory deliminator
|
||||
LPCTSTR filename = ::strrchr (path, '\\');
|
||||
if (filename != NULL) {
|
||||
// Increment past the directory deliminator
|
||||
filename ++;
|
||||
} else {
|
||||
filename = path;
|
||||
}
|
||||
|
||||
// Return the filename part of the path
|
||||
return CString (filename);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Strip_Filename_From_Path
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
CString
|
||||
Strip_Filename_From_Path (LPCTSTR path)
|
||||
{
|
||||
// Copy the path to a buffer we can modify
|
||||
TCHAR temp_path[MAX_PATH];
|
||||
::lstrcpy (temp_path, path);
|
||||
|
||||
// Find the last occurance of the directory deliminator
|
||||
LPTSTR filename = ::strrchr (temp_path, '\\');
|
||||
if (filename != NULL) {
|
||||
|
||||
// Strip off the filename
|
||||
filename[0] = 0;
|
||||
} else if ((temp_path[1] != ':') && (temp_path[1] != '\\')) {
|
||||
temp_path[0] = 0;
|
||||
}
|
||||
|
||||
// Return the path only
|
||||
return StringClass (temp_path);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnCombineDuplicates
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMainFrame::OnCombineDuplicates (void)
|
||||
{
|
||||
CFileDialog dialog ( TRUE,
|
||||
".dat",
|
||||
"always.dat",
|
||||
OFN_HIDEREADONLY | OFN_EXPLORER,
|
||||
"Mix File (*.dat, *.mix)|*.dat;*.mix||",
|
||||
this);
|
||||
|
||||
dialog.m_ofn.lpstrTitle = "Pick Shared Mix File";
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
DuplicateRemoverClass combiner;
|
||||
|
||||
//
|
||||
// Determine what directory to search
|
||||
//
|
||||
StringClass full_path = dialog.GetPathName ();
|
||||
StringClass directory = Strip_Filename_From_Path (full_path);
|
||||
combiner.Set_Destination_File (full_path);
|
||||
|
||||
WIN32_FIND_DATA find_info = { 0 };
|
||||
BOOL keep_going = TRUE;
|
||||
|
||||
CString search_mask = directory + "\\*.mix";
|
||||
|
||||
//
|
||||
// Loop over all the mix files in the search directory
|
||||
//
|
||||
int count = 0;
|
||||
for (HANDLE find_handle = ::FindFirstFile (search_mask, &find_info);
|
||||
(find_handle != INVALID_HANDLE_VALUE) && keep_going;
|
||||
keep_going = ::FindNextFile (find_handle, &find_info))
|
||||
{
|
||||
//
|
||||
// Check to make sure this isn't a directory
|
||||
//
|
||||
if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
StringClass full_path = directory;
|
||||
full_path += "\\";
|
||||
full_path += find_info.cFileName;
|
||||
combiner.Add_Mix_File (full_path);
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Close the handle we needed for the file find routines
|
||||
//
|
||||
if (find_handle != INVALID_HANDLE_VALUE) {
|
||||
::FindClose (find_handle);
|
||||
}
|
||||
|
||||
//
|
||||
// Combine the files (if necessary)
|
||||
//
|
||||
if (count > 0) {
|
||||
combiner.Process ();
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnCreateMixFile
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMainFrame::OnCreateMixFile (void)
|
||||
{
|
||||
MakeMixFileDialogClass dialog( this );
|
||||
dialog.DoModal();
|
||||
return ;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnExportFiles
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMainFrame::OnExportFiles (void)
|
||||
{
|
||||
StringClass current_filename;
|
||||
|
||||
CDocument * doc = GetActiveDocument();
|
||||
if ( doc != NULL ) {
|
||||
current_filename = doc->GetPathName();
|
||||
}
|
||||
|
||||
if ( !current_filename.Is_Empty() ) {
|
||||
|
||||
DynamicVectorClass<StringClass> filenames;
|
||||
MixFileFactoryClass mix_factory (current_filename, _TheFileFactory);
|
||||
if ( mix_factory.Build_Filename_List( filenames ) ) {
|
||||
|
||||
// Make the destination folder
|
||||
StringClass export_path = current_filename;
|
||||
export_path += " Files";
|
||||
int result = (int)::CreateDirectory( export_path, NULL );
|
||||
int error = ::GetLastError();
|
||||
if ( result != 0 || error == ERROR_ALREADY_EXISTS ) {
|
||||
|
||||
bool read_error = false;
|
||||
bool write_error = false;
|
||||
|
||||
for (int index = 0; index < filenames.Count (); index ++) {
|
||||
StringClass source_name = filenames[index];
|
||||
StringClass dest_name;
|
||||
dest_name = export_path;
|
||||
dest_name += "\\";
|
||||
dest_name += filenames[index];
|
||||
|
||||
// If the filename contains a /, create the directory
|
||||
if ( ::strchr( filenames[index], '\\' ) != NULL ) {
|
||||
StringClass dest_folder = dest_name;
|
||||
int length = ::strrchr( dest_folder, '\\' ) - dest_folder;
|
||||
dest_folder.Erase( length, dest_folder.Get_Length() - length );
|
||||
int result = (int)::CreateDirectory( dest_folder, NULL );
|
||||
int error = ::GetLastError();
|
||||
if ( result == 0 && error != ERROR_ALREADY_EXISTS ) {
|
||||
StringClass message;
|
||||
message.Format ("Failed to create folder %s.", dest_folder );
|
||||
MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FileClass * source_file = mix_factory.Get_File( source_name );
|
||||
FileClass * dest_file = _TheFileFactory->Get_File( dest_name );
|
||||
|
||||
if ( dest_file ) {
|
||||
if ( dest_file->Open( FileClass::WRITE ) == 0 ) {
|
||||
StringClass message;
|
||||
message.Format ("Failed to open %s for writing.", dest_name );
|
||||
MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ( source_file ) {
|
||||
if ( source_file->Open() == 0 ) {
|
||||
StringClass message;
|
||||
message.Format ("Failed to open %s for reading.", source_name );
|
||||
MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( source_file && source_file->Is_Available() &&
|
||||
dest_file && dest_file->Is_Available() ) {
|
||||
|
||||
int length = source_file->Size();
|
||||
unsigned char file_buffer[4096];
|
||||
|
||||
while ( length > 0 ) {
|
||||
int amount = min ( (int)length, (int)sizeof( file_buffer ) );
|
||||
if ( source_file->Read( &(file_buffer[0]), amount ) != amount ) {
|
||||
read_error = true;
|
||||
length = 0;
|
||||
}
|
||||
if ( dest_file->Write( &file_buffer[0], amount ) != amount ) {
|
||||
write_error = true;
|
||||
length = 0;
|
||||
}
|
||||
length -= amount;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( source_file != NULL ) {
|
||||
mix_factory.Return_File( source_file );
|
||||
}
|
||||
if ( dest_file != NULL ) {
|
||||
_TheFileFactory->Return_File( dest_file );
|
||||
}
|
||||
|
||||
if ( read_error ) {
|
||||
StringClass message;
|
||||
message.Format ("Read Error on %s.", source_name );
|
||||
MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
|
||||
return;
|
||||
}
|
||||
if ( write_error ) {
|
||||
StringClass message;
|
||||
message.Format ("Write Error on %s.", dest_name );
|
||||
MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
// filenames[index];
|
||||
}
|
||||
|
||||
} else {
|
||||
StringClass message;
|
||||
message.Format ("Failed to create folder %s.", export_path);
|
||||
MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
|
||||
}
|
||||
|
||||
} else {
|
||||
StringClass message;
|
||||
message.Format ("Error reading the filename list from %s.", current_filename);
|
||||
MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
|
||||
}
|
||||
} else {
|
||||
StringClass message;
|
||||
message.Format ("No Current Mix File.");
|
||||
MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnRemoveAVAssets
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMainFrame::OnRemoveAVAssets (void)
|
||||
{
|
||||
CFileDialog dialog(true, ".mix", NULL, OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
|
||||
dialog.m_ofn.lpstrTitle = "Pick Mix Files";
|
||||
|
||||
char *file_name_buffer = new char [65536];
|
||||
*file_name_buffer = 0;
|
||||
|
||||
dialog.m_ofn.lpstrFile = file_name_buffer;
|
||||
dialog.m_ofn.nMaxFile = 65535;
|
||||
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Process each mix file and put the stripped mix file into a 'temp' subdirectory under the current one.
|
||||
//
|
||||
POSITION pos = dialog.GetStartPosition();
|
||||
|
||||
while (pos != NULL) {
|
||||
StringClass file_name = dialog.GetNextPathName(pos);
|
||||
|
||||
//
|
||||
// Get just the path portion.
|
||||
//
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char path[_MAX_PATH];
|
||||
char name[_MAX_PATH];
|
||||
char ext[_MAX_PATH];
|
||||
_splitpath(file_name, drive, dir, name, ext);
|
||||
|
||||
//
|
||||
// Make sure the temp directory exists.
|
||||
//
|
||||
strcat(dir, "temp\\");
|
||||
_makepath(path, drive, dir, NULL, NULL);
|
||||
CreateDirectory(path, NULL);
|
||||
|
||||
//
|
||||
// Make the output file name.
|
||||
//
|
||||
char output_file[_MAX_PATH];
|
||||
_makepath(output_file, drive, dir, name, ext);
|
||||
|
||||
AVAssetSuckerClass sucker;
|
||||
sucker.Suck(file_name.Peek_Buffer(), output_file);
|
||||
}
|
||||
}
|
||||
delete [] file_name_buffer;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnMakeMixPatch
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMainFrame::OnMakeMixPatch(void)
|
||||
{
|
||||
//
|
||||
// Ask for the name of the old source mix file.
|
||||
//
|
||||
CFileDialog dialog(true, ".mix", NULL, OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
|
||||
dialog.m_ofn.lpstrTitle = "Pick Old Source Mix File";
|
||||
|
||||
char file_name_buffer[1024];
|
||||
file_name_buffer[0] = 0;
|
||||
|
||||
dialog.m_ofn.lpstrFile = file_name_buffer;
|
||||
dialog.m_ofn.nMaxFile = 1024;
|
||||
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Pull the name of the old source mix file.
|
||||
//
|
||||
POSITION pos = dialog.GetStartPosition();
|
||||
StringClass old_file_name = dialog.GetNextPathName(pos);
|
||||
|
||||
//
|
||||
// Ask for the name of the new source mix file.
|
||||
//
|
||||
CFileDialog dialog2(true, ".mix", NULL, OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
|
||||
dialog2.m_ofn.lpstrTitle = "Pick New Source Mix File";
|
||||
|
||||
file_name_buffer[0] = 0;
|
||||
|
||||
dialog2.m_ofn.lpstrFile = file_name_buffer;
|
||||
dialog2.m_ofn.nMaxFile = 1024;
|
||||
|
||||
if (dialog2.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Pull the name of the new source mix file.
|
||||
//
|
||||
pos = dialog2.GetStartPosition();
|
||||
StringClass new_file_name = dialog2.GetNextPathName(pos);
|
||||
|
||||
|
||||
//
|
||||
// Ask for the name of the output mix file.
|
||||
//
|
||||
CFileDialog dialog3(true, ".mix", NULL, OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
|
||||
dialog3.m_ofn.lpstrTitle = "Pick Output Patch Mix File";
|
||||
|
||||
file_name_buffer[0] = 0;
|
||||
|
||||
dialog3.m_ofn.lpstrFile = file_name_buffer;
|
||||
dialog3.m_ofn.nMaxFile = 1024;
|
||||
|
||||
if (dialog3.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Pull the name of the new source mix file.
|
||||
//
|
||||
pos = dialog3.GetStartPosition();
|
||||
StringClass out_file_name = dialog3.GetNextPathName(pos);
|
||||
|
||||
//
|
||||
// Ask for the directory containing the old source art.
|
||||
//
|
||||
char path[_MAX_PATH + 256];
|
||||
BROWSEINFO binfo;
|
||||
binfo.hwndOwner = NULL;
|
||||
binfo.pidlRoot = NULL;
|
||||
binfo.pszDisplayName = path;
|
||||
binfo.lpszTitle = "Select Old Source Art Directory";
|
||||
binfo.ulFlags = 0;
|
||||
binfo.lpfn = NULL;
|
||||
binfo.lParam = 0;
|
||||
binfo.iImage = 0;
|
||||
|
||||
LPITEMIDLIST itemptr = SHBrowseForFolder(&binfo);
|
||||
|
||||
if (itemptr) {
|
||||
|
||||
char old_art_dir[_MAX_PATH + 256];
|
||||
|
||||
if (SHGetPathFromIDList(itemptr, old_art_dir)) {
|
||||
|
||||
//
|
||||
// Ask for the directory containing the new source art.
|
||||
//
|
||||
char path[_MAX_PATH + 256];
|
||||
BROWSEINFO binfo;
|
||||
binfo.hwndOwner = NULL;
|
||||
binfo.pidlRoot = NULL;
|
||||
binfo.pszDisplayName = path;
|
||||
binfo.lpszTitle = "Select New Source Art Directory";
|
||||
binfo.ulFlags = 0;
|
||||
binfo.lpfn = NULL;
|
||||
binfo.lParam = 0;
|
||||
binfo.iImage = 0;
|
||||
|
||||
itemptr = SHBrowseForFolder(&binfo);
|
||||
|
||||
if (itemptr) {
|
||||
char new_art_dir[_MAX_PATH + 256];
|
||||
if (SHGetPathFromIDList(itemptr, new_art_dir)) {
|
||||
MixPatchMakerClass patcher;
|
||||
patcher.Make_Patch(old_file_name.Peek_Buffer(), new_file_name.Peek_Buffer(), out_file_name.Peek_Buffer(), old_art_dir, new_art_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WindowProc
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
LRESULT
|
||||
CMainFrame::WindowProc
|
||||
(
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam
|
||||
)
|
||||
{
|
||||
return CFrameWnd::WindowProc(message, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDropFiles
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMainFrame::OnDropFiles (HDROP hDropInfo)
|
||||
{
|
||||
SetActiveWindow ();
|
||||
|
||||
CWinApp *win_app = AfxGetApp ();
|
||||
ASSERT (win_app != NULL);
|
||||
|
||||
//
|
||||
// Get the count of files from the drop query
|
||||
//
|
||||
int file_count = (int)::DragQueryFile (hDropInfo, (UINT)-1, NULL, 0);
|
||||
if (file_count > 0) {
|
||||
|
||||
CMixViewerDoc *doc = (CMixViewerDoc *)GetActiveDocument ();
|
||||
|
||||
if (file_count == 1) {
|
||||
|
||||
//
|
||||
// Get the filename...
|
||||
//
|
||||
TCHAR filename[_MAX_PATH];
|
||||
::DragQueryFile (hDropInfo, 0, filename, _MAX_PATH);
|
||||
|
||||
//
|
||||
// Get the extension from the filename
|
||||
//
|
||||
char extension[_MAX_EXT] = { 0 };
|
||||
::_splitpath (filename, NULL, NULL, NULL, extension);
|
||||
|
||||
//
|
||||
// Is this a mix file, or should we be adding this file to the mix?
|
||||
//
|
||||
if ( ::lstrcmpi (extension, ".mix") == 0 ||
|
||||
::lstrcmpi (extension, ".dat") == 0 ||
|
||||
::lstrcmpi (extension, ".dbs") == 0)
|
||||
{
|
||||
win_app->OpenDocumentFile (filename);
|
||||
} else {
|
||||
Add_To_Mix_File (doc->GetPathName (), filename);
|
||||
doc->Reload_Views ();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
DynamicVectorClass<StringClass> file_list;
|
||||
|
||||
//
|
||||
// Loop over each of the dropped files and add them to the current mix file
|
||||
//
|
||||
for (int index = 0; index < file_count; index ++) {
|
||||
|
||||
//
|
||||
// Add this file to a list so we can batch add all the files...
|
||||
//
|
||||
TCHAR filename[_MAX_PATH];
|
||||
::DragQueryFile (hDropInfo, index, filename, _MAX_PATH);
|
||||
file_list.Add (filename);
|
||||
}
|
||||
::DragFinish(hDropInfo);
|
||||
|
||||
//
|
||||
// Add the mix files to the list
|
||||
//
|
||||
Add_To_Mix_File (doc->GetPathName (), file_list);
|
||||
doc->Reload_Views ();
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add_To_Mix_File
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMainFrame::Add_To_Mix_File (const char *mix_filename, const char *filename)
|
||||
{
|
||||
DynamicVectorClass<StringClass> file_list;
|
||||
file_list.Add (filename);
|
||||
Add_To_Mix_File (mix_filename, file_list);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add_To_Mix_File
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMainFrame::Add_To_Mix_File (const char *mix_filename, DynamicVectorClass<StringClass> &new_file_list)
|
||||
{
|
||||
//
|
||||
// Set the current directory...
|
||||
//
|
||||
CString path = Strip_Filename_From_Path (mix_filename);
|
||||
if (path.GetLength () > 0) {
|
||||
::SetCurrentDirectory (path);
|
||||
}
|
||||
|
||||
//
|
||||
// Get access to the mix file in qestion
|
||||
//
|
||||
MixFileFactoryClass *mix_factory = new MixFileFactoryClass (mix_filename, _TheFileFactory);
|
||||
if (mix_factory->Is_Valid () && mix_factory->Build_Internal_Filename_List ()) {
|
||||
|
||||
//
|
||||
// Now add the new files into the mix file...
|
||||
//
|
||||
for (int index = 0; index < new_file_list.Count (); index ++) {
|
||||
CString filename = ::Get_Filename_From_Path (new_file_list[index]);
|
||||
mix_factory->Delete_File (filename);
|
||||
mix_factory->Add_File (new_file_list[index], filename);
|
||||
}
|
||||
|
||||
//
|
||||
// Do it!
|
||||
//
|
||||
mix_factory->Flush_Changes ();
|
||||
}
|
||||
|
||||
//
|
||||
// Free the mix factory
|
||||
//
|
||||
delete mix_factory;
|
||||
mix_factory = NULL;
|
||||
return ;
|
||||
}
|
||||
96
Code/Tools/MixViewer/MainFrm.h
Normal file
96
Code/Tools/MixViewer/MainFrm.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// MainFrm.h : interface of the CMainFrame class
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_MAINFRM_H__BA36CCDC_B39E_4972_B9DC_A531CDEF5E4B__INCLUDED_)
|
||||
#define AFX_MAINFRM_H__BA36CCDC_B39E_4972_B9DC_A531CDEF5E4B__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "wwstring.h"
|
||||
#include "vector.h"
|
||||
|
||||
CString Strip_Filename_From_Path (LPCTSTR path);
|
||||
|
||||
class CMainFrame : public CFrameWnd
|
||||
{
|
||||
|
||||
protected: // create from serialization only
|
||||
CMainFrame();
|
||||
DECLARE_DYNCREATE(CMainFrame)
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
|
||||
// Operations
|
||||
public:
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CMainFrame)
|
||||
public:
|
||||
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
|
||||
protected:
|
||||
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
virtual ~CMainFrame();
|
||||
#ifdef _DEBUG
|
||||
virtual void AssertValid() const;
|
||||
virtual void Dump(CDumpContext& dc) const;
|
||||
#endif
|
||||
|
||||
protected: // control bar embedded members
|
||||
CStatusBar m_wndStatusBar;
|
||||
CToolBar m_wndToolBar;
|
||||
|
||||
// Generated message map functions
|
||||
protected:
|
||||
//{{AFX_MSG(CMainFrame)
|
||||
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
|
||||
afx_msg void OnCombineDuplicates();
|
||||
afx_msg void OnRemoveAVAssets();
|
||||
afx_msg void OnMakeMixPatch();
|
||||
afx_msg void OnDropFiles(HDROP hDropInfo);
|
||||
afx_msg void OnCreateMixFile();
|
||||
afx_msg void OnExportFiles();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////////////////////
|
||||
void Add_To_Mix_File (const char *mix_filename, const char *filename);
|
||||
void Add_To_Mix_File (const char *mix_filename, DynamicVectorClass<StringClass> &new_file_list);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_MAINFRM_H__BA36CCDC_B39E_4972_B9DC_A531CDEF5E4B__INCLUDED_)
|
||||
219
Code/Tools/MixViewer/MakeMixFileDialog.cpp
Normal file
219
Code/Tools/MixViewer/MakeMixFileDialog.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// MakeMixFileDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "mixviewer.h"
|
||||
#include "MakeMixFileDialog.h"
|
||||
#include "wwstring.h"
|
||||
#include "MainFrm.h"
|
||||
#include "mixfile.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// MakeMixFileDialogClass dialog
|
||||
|
||||
|
||||
MakeMixFileDialogClass::MakeMixFileDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(MakeMixFileDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(MakeMixFileDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
}
|
||||
|
||||
|
||||
void MakeMixFileDialogClass::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(MakeMixFileDialogClass)
|
||||
// NOTE: the ClassWizard will add DDX and DDV calls here
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(MakeMixFileDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(MakeMixFileDialogClass)
|
||||
ON_BN_CLICKED(IDC_BROWSE_FILE, OnBrowseFile)
|
||||
ON_BN_CLICKED(IDC_BROWSE_DIR, OnBrowseDir)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// MakeMixFileDialogClass message handlers
|
||||
|
||||
BOOL MakeMixFileDialogClass::OnInitDialog()
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
// TODO: Add extra initialization here
|
||||
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
// EXCEPTION: OCX Property Pages should return FALSE
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
*/
|
||||
unsigned MakeMixFileDialogClass::Add_Files (const StringClass &basepath, const StringClass &subpath, MixFileCreator &mixfile)
|
||||
{
|
||||
const char wildcardname [] = "*.*";
|
||||
|
||||
unsigned filecount;
|
||||
StringClass findfilepathname;
|
||||
WIN32_FIND_DATA finddata;
|
||||
HANDLE handle;
|
||||
|
||||
filecount = 0;
|
||||
if (basepath.Get_Length() > 0) {
|
||||
findfilepathname = basepath;
|
||||
findfilepathname += "\\";
|
||||
}
|
||||
if (subpath.Get_Length() > 0) {
|
||||
findfilepathname += subpath;
|
||||
findfilepathname += "\\";
|
||||
}
|
||||
findfilepathname += wildcardname;
|
||||
handle = FindFirstFile (findfilepathname, &finddata);
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
|
||||
bool done;
|
||||
|
||||
done = false;
|
||||
while (!done) {
|
||||
|
||||
// Filter out system files.
|
||||
if (finddata.cFileName [0] != '.') {
|
||||
|
||||
StringClass subpathname;
|
||||
|
||||
if (subpath.Get_Length() > 0) {
|
||||
subpathname += subpath;
|
||||
subpathname += "\\";
|
||||
}
|
||||
subpathname += finddata.cFileName;
|
||||
|
||||
// Is it a subdirectory?
|
||||
if ((finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
|
||||
// Recurse on subdirectory.
|
||||
filecount += Add_Files (basepath, subpathname, mixfile);
|
||||
|
||||
} else {
|
||||
|
||||
StringClass fullpathname;
|
||||
|
||||
if (basepath.Get_Length() > 0) {
|
||||
fullpathname += basepath;
|
||||
fullpathname += "\\";
|
||||
}
|
||||
if (subpath.Get_Length() > 0) {
|
||||
fullpathname += subpath;
|
||||
fullpathname += "\\";
|
||||
}
|
||||
fullpathname += finddata.cFileName;
|
||||
if ( MixFilename != fullpathname ) {
|
||||
mixfile.Add_File (fullpathname, subpathname);
|
||||
filecount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
done = !FindNextFile (handle, &finddata);
|
||||
}
|
||||
}
|
||||
return (filecount);
|
||||
}
|
||||
|
||||
void MakeMixFileDialogClass::OnOK()
|
||||
{
|
||||
CString mix_name;
|
||||
GetDlgItemText( IDC_BROWSE_FILE_NAME, mix_name );
|
||||
CString dir_name;
|
||||
GetDlgItemText( IDC_BROWSE_DIR_NAME, dir_name );
|
||||
|
||||
if ( mix_name.IsEmpty() ) {
|
||||
StringClass message;
|
||||
message.Format ("Invalid Mix File.");
|
||||
MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
|
||||
} else if ( dir_name.IsEmpty() ) {
|
||||
StringClass message;
|
||||
message.Format ("Invalid Source Directory.");
|
||||
MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
|
||||
} else {
|
||||
|
||||
MixFilename = mix_name;
|
||||
MixFileCreator mixfile (mix_name);
|
||||
StringClass basepath (dir_name);
|
||||
StringClass subpath;
|
||||
StringClass message;
|
||||
int filecount = Add_Files (basepath, subpath, mixfile);
|
||||
if (filecount > 0) {
|
||||
message.Format ("%u files added\n", filecount);
|
||||
} else {
|
||||
message.Format ("No files found in source directory\n");
|
||||
}
|
||||
MessageBox (message, "Mix File Created", MB_OK);
|
||||
|
||||
CDialog::OnOK();
|
||||
}
|
||||
}
|
||||
|
||||
void MakeMixFileDialogClass::OnBrowseFile()
|
||||
{
|
||||
CString old_name;
|
||||
GetDlgItemText( IDC_BROWSE_FILE_NAME, old_name );
|
||||
|
||||
CFileDialog dialog ( TRUE,
|
||||
".mix",
|
||||
old_name,
|
||||
OFN_HIDEREADONLY | OFN_EXPLORER,
|
||||
"Mix File (*.mix)|*.mix||",
|
||||
this);
|
||||
|
||||
dialog.m_ofn.lpstrTitle = "Pick Mix File to Create";
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
SetDlgItemText( IDC_BROWSE_FILE_NAME, dialog.GetPathName () );
|
||||
}
|
||||
}
|
||||
|
||||
void MakeMixFileDialogClass::OnBrowseDir()
|
||||
{
|
||||
CString old_name;
|
||||
GetDlgItemText( IDC_BROWSE_DIR_NAME, old_name );
|
||||
|
||||
CFileDialog dialog ( TRUE,
|
||||
NULL, //".",
|
||||
old_name,
|
||||
OFN_HIDEREADONLY | OFN_EXPLORER,
|
||||
NULL, //"Mix File (*.mix)|*.mix||",
|
||||
this);
|
||||
|
||||
dialog.m_ofn.lpstrTitle = "Pick A File In the Root Source Directory";
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
StringClass filename = dialog.GetPathName ();
|
||||
StringClass directory = Strip_Filename_From_Path (filename);
|
||||
SetDlgItemText( IDC_BROWSE_DIR_NAME, directory );
|
||||
}
|
||||
}
|
||||
72
Code/Tools/MixViewer/MakeMixFileDialog.h
Normal file
72
Code/Tools/MixViewer/MakeMixFileDialog.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_MAKEMIXFILEDIALOG_H__8A52B67D_3497_4915_825C_199D6EC5995D__INCLUDED_)
|
||||
#define AFX_MAKEMIXFILEDIALOG_H__8A52B67D_3497_4915_825C_199D6EC5995D__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
// MakeMixFileDialog.h : header file
|
||||
//
|
||||
|
||||
#include "mixfile.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// MakeMixFileDialogClass dialog
|
||||
|
||||
class MakeMixFileDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
MakeMixFileDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(MakeMixFileDialogClass)
|
||||
enum { IDD = IDD_MAKE_MIX_FILE };
|
||||
// NOTE: the ClassWizard will add data members here
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(MakeMixFileDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
unsigned Add_Files (const StringClass &basepath, const StringClass &subpath, MixFileCreator &mixfile);
|
||||
StringClass MixFilename;
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(MakeMixFileDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
virtual void OnOK();
|
||||
afx_msg void OnBrowseFile();
|
||||
afx_msg void OnBrowseDir();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_MAKEMIXFILEDIALOG_H__8A52B67D_3497_4915_825C_199D6EC5995D__INCLUDED_)
|
||||
122
Code/Tools/MixViewer/MixCombiningDialog.cpp
Normal file
122
Code/Tools/MixViewer/MixCombiningDialog.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// MixCombiningDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "MixViewer.h"
|
||||
#include "MixCombiningDialog.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// MixCombiningDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
MixCombiningDialogClass::MixCombiningDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(MixCombiningDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(MixCombiningDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
MixCombiningDialogClass::DoDataExchange (CDataExchange *pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(MixCombiningDialogClass)
|
||||
DDX_Control(pDX, IDC_PROGRESS, ProgressCtrl);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(MixCombiningDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(MixCombiningDialogClass)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
MixCombiningDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
ProgressCtrl.SetPos (0);
|
||||
ProgressCtrl.SetRange (0, 100);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Status_Text
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
MixCombiningDialogClass::Set_Status_Text (const char *text)
|
||||
{
|
||||
while (!::IsWindow(m_hWnd)) {}
|
||||
SetDlgItemText (IDC_STATUS, text);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Progress_Percent
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
MixCombiningDialogClass::Set_Progress_Percent (float percent)
|
||||
{
|
||||
while (!::IsWindow(m_hWnd)) {}
|
||||
ProgressCtrl.SetPos ((int)(percent * 100.0f));
|
||||
return ;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Title
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void MixCombiningDialogClass::Set_Title(const char *text)
|
||||
{
|
||||
while (!::IsWindow(m_hWnd)) {}
|
||||
SetWindowText(text);
|
||||
}
|
||||
75
Code/Tools/MixViewer/MixCombiningDialog.h
Normal file
75
Code/Tools/MixViewer/MixCombiningDialog.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_MIXCOMBININGDIALOG_H__F9BADF1D_9DAA_423E_BB9B_85765370E37E__INCLUDED_)
|
||||
#define AFX_MIXCOMBININGDIALOG_H__F9BADF1D_9DAA_423E_BB9B_85765370E37E__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
// MixCombiningDialog.h : header file
|
||||
//
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// MixCombiningDialogClass dialog
|
||||
|
||||
class MixCombiningDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
MixCombiningDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(MixCombiningDialogClass)
|
||||
enum { IDD = IDD_COMBINING_DIALOG };
|
||||
CProgressCtrl ProgressCtrl;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(MixCombiningDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(MixCombiningDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
void Set_Status_Text (const char *text);
|
||||
void Set_Progress_Percent (float percent);
|
||||
void Set_Title(const char *text);
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_MIXCOMBININGDIALOG_H__F9BADF1D_9DAA_423E_BB9B_85765370E37E__INCLUDED_)
|
||||
451
Code/Tools/MixViewer/MixPatchMaker.cpp
Normal file
451
Code/Tools/MixViewer/MixPatchMaker.cpp
Normal file
@@ -0,0 +1,451 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "mixpatchmaker.h"
|
||||
#include "ffactory.h"
|
||||
#include "mixfile.h"
|
||||
#include "rawfile.h"
|
||||
#include "bittype.h"
|
||||
#include "mixcombiningdialog.h"
|
||||
|
||||
|
||||
|
||||
|
||||
MixPatchMakerClass::MixPatchMakerClass(void) :
|
||||
Dialog(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MixPatchMakerClass::Make_Patch(char *old_input_file, char *new_input_file, char *output_file, char *old_art_dir, char *new_art_dir)
|
||||
{
|
||||
strcpy(OldInputFile, old_input_file);
|
||||
strcpy(NewInputFile, new_input_file);
|
||||
strcpy(OutputFile, output_file);
|
||||
strcpy(OldArtDir, old_art_dir);
|
||||
strcpy(NewArtDir, new_art_dir);
|
||||
|
||||
//
|
||||
// Kick off the worker thread...
|
||||
//
|
||||
::AfxBeginThread(Do_Stuff, (LPVOID)this);
|
||||
|
||||
//
|
||||
// Show the UI
|
||||
//
|
||||
MixCombiningDialogClass dialog;
|
||||
Dialog = &dialog;
|
||||
dialog.DoModal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned int MixPatchMakerClass::Do_Stuff(void *param)
|
||||
{
|
||||
((MixPatchMakerClass*)param)->Thread_Make();
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
void MixPatchMakerClass::Thread_Make(void)
|
||||
{
|
||||
char name[_MAX_PATH];
|
||||
char name_compare[_MAX_PATH];
|
||||
|
||||
while (Dialog == NULL) {
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Get just the file name.
|
||||
*/
|
||||
char justname[_MAX_PATH];
|
||||
char justname_new[_MAX_PATH];
|
||||
_splitpath(OldInputFile, NULL, NULL, justname, NULL);
|
||||
_splitpath(NewInputFile, NULL, NULL, justname_new, NULL);
|
||||
char text[_MAX_PATH + 128];
|
||||
sprintf(text, "Looking for differences between %s and %s...", justname, justname_new);
|
||||
|
||||
Dialog->Set_Title("Building patch mixfile...");
|
||||
Dialog->Set_Status_Text(text);
|
||||
Dialog->Set_Progress_Percent (0);
|
||||
|
||||
MixFileFactoryClass old_mix(OldInputFile, _TheFileFactory);
|
||||
MixFileFactoryClass new_mix(NewInputFile, _TheFileFactory);
|
||||
if (new_mix.Is_Valid() && new_mix.Build_Internal_Filename_List()) {
|
||||
if (old_mix.Is_Valid() && old_mix.Build_Internal_Filename_List()) {
|
||||
|
||||
/*
|
||||
** Get the list of files in the new source mix file.
|
||||
*/
|
||||
DynamicVectorClass<StringClass> new_filename_list;
|
||||
new_mix.Get_Filename_List(new_filename_list);
|
||||
|
||||
/*
|
||||
** Get the list of files in the old source mix file.
|
||||
*/
|
||||
DynamicVectorClass<StringClass> old_filename_list;
|
||||
old_mix.Get_Filename_List(old_filename_list);
|
||||
|
||||
/*
|
||||
** Create the output mix file.
|
||||
*/
|
||||
MixFileCreator mix_out(OutputFile);
|
||||
|
||||
/*
|
||||
** Loop through all the files in the new source mix. If a file doesn't exist in the old one, or it does exist but is
|
||||
** different, then copy it into the output mix file.
|
||||
*/
|
||||
for (int i=0 ; i<new_filename_list.Count() ; i++) {
|
||||
|
||||
strcpy(name, new_filename_list[i].Peek_Buffer());
|
||||
strupr(name);
|
||||
bool copy = false;
|
||||
|
||||
if (stricmp(name, "STRINGS.TDB") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
** Search for the file in the old mixfile.
|
||||
*/
|
||||
bool found = false;
|
||||
for (int j=0 ; j<old_filename_list.Count() ; j++) {
|
||||
strcpy(name_compare, old_filename_list[j].Peek_Buffer());
|
||||
if (stricmp(name, name_compare) == 0) {
|
||||
found = true;
|
||||
|
||||
/*
|
||||
** There's a file with the same name in the old mix file. See if it's byte for byte identical. If it's not
|
||||
** then we need to use the newer file in the patch mix.
|
||||
*/
|
||||
bool same = Compare_File(&new_mix, &old_mix, new_filename_list[i].Peek_Buffer());
|
||||
if (!same) {
|
||||
|
||||
/*
|
||||
** If it's a .dds (texture) file, compare the source art for changes. The .dds can change even when the
|
||||
** source art doesn't.
|
||||
*/
|
||||
if (strstr(name, ".DDS")) {
|
||||
char targa_name[_MAX_PATH];
|
||||
strcpy(targa_name, name);
|
||||
char *ext = strstr(targa_name, ".DDS");
|
||||
if (ext) {
|
||||
strcpy(ext, ".TGA");
|
||||
|
||||
/*
|
||||
** If the two source art files are the same then break out.
|
||||
*/
|
||||
if (Compare_Source_Art_File(targa_name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
copy = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If the file doesn't exist at all in the older mixfile then it needs to be in the patch mix.
|
||||
*/
|
||||
if (!found) {
|
||||
copy = true;
|
||||
}
|
||||
|
||||
if (copy) {
|
||||
Copy_File(&new_mix, &mix_out, new_filename_list[i].Peek_Buffer());
|
||||
}
|
||||
|
||||
Dialog->Set_Progress_Percent((float)i / float(new_filename_list.Count() + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
Dialog->PostMessage(WM_COMMAND, MAKELPARAM(IDOK, BN_CLICKED));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void MixPatchMakerClass::Copy_File(MixFileFactoryClass *src_mix, MixFileCreator *dest_mix, char *filename)
|
||||
{
|
||||
//
|
||||
// Get the file data from the source mix
|
||||
//
|
||||
FileClass *src_file = src_mix->Get_File (filename);
|
||||
src_file->Open ();
|
||||
int size = src_file->Size();
|
||||
|
||||
//
|
||||
// Create a temporary destination file for the data
|
||||
//
|
||||
char temp_file_name[_MAX_PATH];
|
||||
char temp_path[_MAX_PATH];
|
||||
int chars = GetTempPath(_MAX_PATH, temp_path);
|
||||
if (chars) {
|
||||
int res = GetTempFileName(temp_path, "MIX", 0, temp_file_name);
|
||||
if (res == 0) {
|
||||
WWDEBUG_SAY(("GetTempFileName failed with error code %d\n", GetLastError()));
|
||||
} else {
|
||||
RawFileClass temp_file(temp_file_name);
|
||||
if (temp_file.Open(RawFileClass::WRITE)) {
|
||||
|
||||
//
|
||||
// Save the data in the temp file.
|
||||
//
|
||||
void *bigbuf = new char [size + 1024];
|
||||
src_file->Read(bigbuf, size);
|
||||
temp_file.Write(bigbuf, size);
|
||||
delete [] bigbuf;
|
||||
temp_file.Close();
|
||||
|
||||
//
|
||||
// Add the temp file to the mix file.
|
||||
//
|
||||
dest_mix->Add_File(temp_file_name, filename);
|
||||
|
||||
//
|
||||
// Delete the temp file.
|
||||
//
|
||||
DeleteFile(temp_file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
src_mix->Return_File(src_file);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* MixPatchMakerClass::Compare_File -- Compare two files in seperate mixfiles. *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: First mixfile *
|
||||
* Second mixfile *
|
||||
* Name of file to compare *
|
||||
* *
|
||||
* OUTPUT: true if files are the same *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/5/2002 9:54PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
bool MixPatchMakerClass::Compare_File(MixFileFactoryClass *src_mix, MixFileFactoryClass *dest_mix, char *filename)
|
||||
{
|
||||
/*
|
||||
** Get the file data from the source mix
|
||||
*/
|
||||
FileClass *src_file = src_mix->Get_File(filename);
|
||||
int size = src_file->Size();
|
||||
|
||||
|
||||
/*
|
||||
** Get the file data from the dest mix
|
||||
*/
|
||||
FileClass *dest_file = dest_mix->Get_File(filename);
|
||||
|
||||
/*
|
||||
** If the two files are a different size then we know they aren't the same.
|
||||
*/
|
||||
if (size != dest_file->Size()) {
|
||||
src_mix->Return_File(src_file);
|
||||
dest_mix->Return_File(dest_file);
|
||||
return(false);
|
||||
}
|
||||
|
||||
/*
|
||||
** Read the source file into memory.
|
||||
*/
|
||||
src_file->Open();
|
||||
unsigned char *src_data = new unsigned char [size + 32];
|
||||
src_file->Read(src_data, size);
|
||||
src_file->Close();
|
||||
|
||||
/*
|
||||
** Read the dest file into memory.
|
||||
*/
|
||||
dest_file->Open();
|
||||
unsigned char *dest_data = new unsigned char [size + 32];
|
||||
dest_file->Read(dest_data, size);
|
||||
dest_file->Close();
|
||||
|
||||
/*
|
||||
** Compare them.
|
||||
*/
|
||||
bool same = (memcmp(src_data, dest_data, size) == 0) ? true : false;
|
||||
|
||||
/*
|
||||
** Clean up.
|
||||
*/
|
||||
delete [] src_data;
|
||||
delete [] dest_data;
|
||||
src_mix->Return_File(src_file);
|
||||
dest_mix->Return_File(dest_file);
|
||||
|
||||
return(same);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* MixPatchMakerClass::Compare_Source_Art_File -- Compare source art .tga files *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Filename *
|
||||
* *
|
||||
* OUTPUT: True if same *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/21/2002 4:31PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
bool MixPatchMakerClass::Compare_Source_Art_File(char *filename)
|
||||
{
|
||||
/*
|
||||
** Find the file in the old source art directory.
|
||||
*/
|
||||
char path_to_old_file[_MAX_PATH + 256];
|
||||
bool got = Find_File(filename, OldArtDir, path_to_old_file);
|
||||
|
||||
if (got) {
|
||||
|
||||
/*
|
||||
** Find the file in the old source art directory.
|
||||
*/
|
||||
char path_to_new_file[_MAX_PATH + 256];
|
||||
got = Find_File(filename, NewArtDir, path_to_new_file);
|
||||
|
||||
if (got) {
|
||||
|
||||
/*
|
||||
** Both files exist. Load them and compare.
|
||||
*/
|
||||
RawFileClass file1(path_to_old_file);
|
||||
RawFileClass file2(path_to_new_file);
|
||||
|
||||
if (file1.Size() == file2.Size()) {
|
||||
|
||||
int size = file1.Size();
|
||||
|
||||
unsigned char * buf1 = new unsigned char [size + 1024];
|
||||
unsigned char * buf2 = new unsigned char [size + 1024];
|
||||
|
||||
file1.Read(buf1, size);
|
||||
file2.Read(buf2, size);
|
||||
int diff = memcmp(buf1, buf2, size);
|
||||
|
||||
delete [] buf1;
|
||||
delete [] buf2;
|
||||
|
||||
if (diff == 0) {
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* MixPatchMakerClass::Find_File -- Find a file in a directory or sub directory *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Name of file to search for *
|
||||
* Path to start search *
|
||||
* Ptr to string to receive path/filename of file if found *
|
||||
* *
|
||||
* OUTPUT: True if file was found *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/21/2002 8:45PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
bool MixPatchMakerClass::Find_File(char *file_name, char *path, char *found_path)
|
||||
{
|
||||
/*
|
||||
** Look in the current directory.
|
||||
*/
|
||||
char path_to_file[_MAX_PATH + 256];
|
||||
char *pointless_pointer = NULL;
|
||||
int len = SearchPath(path, file_name, NULL, sizeof(path_to_file), path_to_file, &pointless_pointer);
|
||||
|
||||
if (len) {
|
||||
strcpy(found_path, path_to_file);
|
||||
return(true);
|
||||
}
|
||||
|
||||
/*
|
||||
** Look for a subdirectory to search.
|
||||
*/
|
||||
WIN32_FIND_DATA find_info = { 0 };
|
||||
HANDLE find_handle;
|
||||
char search_path[_MAX_PATH + 128];
|
||||
strcpy(search_path, path);
|
||||
strcat(search_path, "\\*.*");
|
||||
find_handle = FindFirstFile(search_path, &find_info);
|
||||
|
||||
while (find_handle != INVALID_HANDLE_VALUE) {
|
||||
if ((find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
|
||||
if (strcmp(find_info.cFileName, ".") != 0) {
|
||||
if (strcmp(find_info.cFileName, "..") != 0) {
|
||||
char new_dir_name[_MAX_PATH + 128];
|
||||
strcpy(new_dir_name, path);
|
||||
strcat(new_dir_name, "\\");
|
||||
strcat(new_dir_name, find_info.cFileName);
|
||||
bool found = Find_File(file_name, new_dir_name, found_path);
|
||||
if (found) {
|
||||
FindClose(find_handle);
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FindNextFile(find_handle, &find_info) == 0) {
|
||||
FindClose(find_handle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
56
Code/Tools/MixViewer/MixPatchMaker.h
Normal file
56
Code/Tools/MixViewer/MixPatchMaker.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _MIXPATCHMAKER_H
|
||||
#define _MIXPATCHMAKER_H
|
||||
|
||||
class MixFileFactoryClass;
|
||||
class MixFileCreator;
|
||||
class MixCombiningDialogClass;
|
||||
|
||||
|
||||
|
||||
class MixPatchMakerClass
|
||||
{
|
||||
public:
|
||||
MixPatchMakerClass(void);
|
||||
void Make_Patch(char *old_input_file, char *new_input_file, char *output_file, char *old_art_dir, char *new_art_dir);
|
||||
static unsigned int Do_Stuff(void *param);
|
||||
void Thread_Make(void);
|
||||
|
||||
|
||||
private:
|
||||
void Copy_File(MixFileFactoryClass *src_mix, MixFileCreator *dest_mix, char *filename);
|
||||
bool Compare_File(MixFileFactoryClass *src_mix, MixFileFactoryClass *dest_mix, char *filename);
|
||||
bool Compare_Source_Art_File(char *filename);
|
||||
bool Find_File(char *file_name, char *path, char *found_path);
|
||||
|
||||
MixCombiningDialogClass *Dialog;
|
||||
char OldInputFile[1024];
|
||||
char NewInputFile[1024];
|
||||
char OutputFile[1024];
|
||||
char OldArtDir[1024];
|
||||
char NewArtDir[1024];
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //_MIXPATCHMAKER_H
|
||||
175
Code/Tools/MixViewer/MixViewer.cpp
Normal file
175
Code/Tools/MixViewer/MixViewer.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// MixViewer.cpp : Defines the class behaviors for the application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "MixViewer.h"
|
||||
|
||||
#include "MainFrm.h"
|
||||
#include "MixViewerDoc.h"
|
||||
#include "MixViewerView.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMixViewerApp
|
||||
|
||||
BEGIN_MESSAGE_MAP(CMixViewerApp, CWinApp)
|
||||
//{{AFX_MSG_MAP(CMixViewerApp)
|
||||
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
|
||||
// NOTE - the ClassWizard will add and remove mapping macros here.
|
||||
// DO NOT EDIT what you see in these blocks of generated code!
|
||||
//}}AFX_MSG_MAP
|
||||
// Standard file based document commands
|
||||
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
|
||||
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMixViewerApp construction
|
||||
|
||||
CMixViewerApp::CMixViewerApp()
|
||||
{
|
||||
// TODO: add construction code here,
|
||||
// Place all significant initialization in InitInstance
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// The one and only CMixViewerApp object
|
||||
|
||||
CMixViewerApp theApp;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMixViewerApp initialization
|
||||
|
||||
BOOL CMixViewerApp::InitInstance()
|
||||
{
|
||||
AfxEnableControlContainer();
|
||||
|
||||
// Standard initialization
|
||||
// If you are not using these features and wish to reduce the size
|
||||
// of your final executable, you should remove from the following
|
||||
// the specific initialization routines you do not need.
|
||||
|
||||
#ifdef _AFXDLL
|
||||
Enable3dControls(); // Call this when using MFC in a shared DLL
|
||||
#else
|
||||
Enable3dControlsStatic(); // Call this when linking to MFC statically
|
||||
#endif
|
||||
|
||||
// Change the registry key under which our settings are stored.
|
||||
// TODO: You should modify this string to be something appropriate
|
||||
// such as the name of your company or organization.
|
||||
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
|
||||
|
||||
LoadStdProfileSettings(8); // Load standard INI file options (including MRU)
|
||||
|
||||
// Register the application's document templates. Document templates
|
||||
// serve as the connection between documents, frame windows and views.
|
||||
|
||||
CSingleDocTemplate* pDocTemplate;
|
||||
pDocTemplate = new CSingleDocTemplate(
|
||||
IDR_MAINFRAME,
|
||||
RUNTIME_CLASS(CMixViewerDoc),
|
||||
RUNTIME_CLASS(CMainFrame), // main SDI frame window
|
||||
RUNTIME_CLASS(CMixViewerView));
|
||||
AddDocTemplate(pDocTemplate);
|
||||
|
||||
// Enable DDE Execute open
|
||||
EnableShellOpen();
|
||||
RegisterShellFileTypes(TRUE);
|
||||
|
||||
// Parse command line for standard shell commands, DDE, file open
|
||||
CCommandLineInfo cmdInfo;
|
||||
ParseCommandLine(cmdInfo);
|
||||
|
||||
// Dispatch commands specified on the command line
|
||||
if (!ProcessShellCommand(cmdInfo))
|
||||
return FALSE;
|
||||
|
||||
// The one and only window has been initialized, so show and update it.
|
||||
m_pMainWnd->DragAcceptFiles (TRUE);
|
||||
m_pMainWnd->ShowWindow (SW_SHOW);
|
||||
m_pMainWnd->UpdateWindow ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CAboutDlg dialog used for App About
|
||||
|
||||
class CAboutDlg : public CDialog
|
||||
{
|
||||
public:
|
||||
CAboutDlg();
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(CAboutDlg)
|
||||
enum { IDD = IDD_ABOUTBOX };
|
||||
//}}AFX_DATA
|
||||
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CAboutDlg)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
//{{AFX_MSG(CAboutDlg)
|
||||
// No message handlers
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
|
||||
{
|
||||
//{{AFX_DATA_INIT(CAboutDlg)
|
||||
//}}AFX_DATA_INIT
|
||||
}
|
||||
|
||||
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(CAboutDlg)
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
|
||||
//{{AFX_MSG_MAP(CAboutDlg)
|
||||
// No message handlers
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
// App command to run the dialog
|
||||
void CMixViewerApp::OnAppAbout()
|
||||
{
|
||||
CAboutDlg aboutDlg;
|
||||
aboutDlg.DoModal();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMixViewerApp message handlers
|
||||
|
||||
215
Code/Tools/MixViewer/MixViewer.dsp
Normal file
215
Code/Tools/MixViewer/MixViewer.dsp
Normal file
@@ -0,0 +1,215 @@
|
||||
# Microsoft Developer Studio Project File - Name="MixViewer" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||
|
||||
CFG=MixViewer - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "MixViewer.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "MixViewer.mak" CFG="MixViewer - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "MixViewer - Win32 Release" (based on "Win32 (x86) Application")
|
||||
!MESSAGE "MixViewer - Win32 Debug" (based on "Win32 (x86) Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/Commando/Code/Tools/MixViewer", QSDEAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "MixViewer - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 6
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 5
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\wwlib" /I "..\..\wwdebug" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
|
||||
# ADD LINK32 wwlib.lib wwdebug.lib winmm.lib /nologo /subsystem:windows /machine:I386 /libpath:"..\..\libs\profile"
|
||||
|
||||
!ELSEIF "$(CFG)" == "MixViewer - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 6
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 5
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\wwlib" /I "..\..\wwdebug" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386
|
||||
# ADD LINK32 wwlib.lib wwdebug.lib winmm.lib /nologo /subsystem:windows /map:"..\..\..\Run\MixViewerD.map" /debug /machine:I386 /out:"..\..\..\Run\MixViewerD.exe" /libpath:"..\..\libs\debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "MixViewer - Win32 Release"
|
||||
# Name "MixViewer - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\AVAssetSuck.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\duplicatecombiner.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MainFrm.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MakeMixFileDialog.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MixCombiningDialog.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MixPatchMaker.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MixViewer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MixViewer.rc
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MixViewerDoc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MixViewerView.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\AVAssetSuck.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\duplicatecombiner.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MainFrm.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MakeMixFileDialog.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MixCombiningDialog.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MixPatchMaker.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MixViewer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MixViewerDoc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MixViewerView.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Resource.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\res\icon1.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\res\MixViewer.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\res\MixViewer.rc2
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\res\MixViewerDoc.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\res\Toolbar.bmp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ReadMe.txt
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
67
Code/Tools/MixViewer/MixViewer.h
Normal file
67
Code/Tools/MixViewer/MixViewer.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// MixViewer.h : main header file for the MIXVIEWER application
|
||||
//
|
||||
|
||||
#if !defined(AFX_MIXVIEWER_H__E184F3F7_FBE5_497F_8D2F_730CD788C579__INCLUDED_)
|
||||
#define AFX_MIXVIEWER_H__E184F3F7_FBE5_497F_8D2F_730CD788C579__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#ifndef __AFXWIN_H__
|
||||
#error include 'stdafx.h' before including this file for PCH
|
||||
#endif
|
||||
|
||||
#include "resource.h" // main symbols
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMixViewerApp:
|
||||
// See MixViewer.cpp for the implementation of this class
|
||||
//
|
||||
|
||||
class CMixViewerApp : public CWinApp
|
||||
{
|
||||
public:
|
||||
CMixViewerApp();
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CMixViewerApp)
|
||||
public:
|
||||
virtual BOOL InitInstance();
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
//{{AFX_MSG(CMixViewerApp)
|
||||
afx_msg void OnAppAbout();
|
||||
// NOTE - the ClassWizard will add and remove member functions here.
|
||||
// DO NOT EDIT what you see in these blocks of generated code !
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_MIXVIEWER_H__E184F3F7_FBE5_497F_8D2F_730CD788C579__INCLUDED_)
|
||||
432
Code/Tools/MixViewer/MixViewer.rc
Normal file
432
Code/Tools/MixViewer/MixViewer.rc
Normal file
@@ -0,0 +1,432 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#define _AFX_NO_SPLITTER_RESOURCES\r\n"
|
||||
"#define _AFX_NO_OLE_RESOURCES\r\n"
|
||||
"#define _AFX_NO_TRACKER_RESOURCES\r\n"
|
||||
"#define _AFX_NO_PROPERTY_RESOURCES\r\n"
|
||||
"\r\n"
|
||||
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
|
||||
"#ifdef _WIN32\r\n"
|
||||
"LANGUAGE 9, 1\r\n"
|
||||
"#pragma code_page(1252)\r\n"
|
||||
"#endif //_WIN32\r\n"
|
||||
"#include ""res\\MixViewer.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
|
||||
"#include ""afxres.rc"" // Standard components\r\n"
|
||||
"#endif\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDR_MAINFRAME ICON DISCARDABLE "res\\MixViewer.ico"
|
||||
IDR_MIXVIETYPE ICON DISCARDABLE "res\\MixViewerDoc.ico"
|
||||
IDI_ICON1 ICON DISCARDABLE "res\\icon1.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Bitmap
|
||||
//
|
||||
|
||||
IDR_MAINFRAME BITMAP MOVEABLE PURE "res\\Toolbar.bmp"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Toolbar
|
||||
//
|
||||
|
||||
IDR_MAINFRAME TOOLBAR DISCARDABLE 16, 15
|
||||
BEGIN
|
||||
BUTTON ID_FILE_NEW
|
||||
BUTTON ID_FILE_OPEN
|
||||
BUTTON ID_FILE_SAVE
|
||||
SEPARATOR
|
||||
BUTTON IDM_COMBINE_DUPLICATES
|
||||
BUTTON IDM_REMOVE_AV_ASSETS
|
||||
BUTTON IDM_MAKE_MIX_PATCH
|
||||
BUTTON ID_APP_ABOUT
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
//
|
||||
|
||||
IDR_MAINFRAME MENU PRELOAD DISCARDABLE
|
||||
BEGIN
|
||||
POPUP "&File"
|
||||
BEGIN
|
||||
MENUITEM "&New\tCtrl+N", ID_FILE_NEW
|
||||
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
|
||||
MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE
|
||||
MENUITEM "Save &As...", ID_FILE_SAVE_AS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Combine &Duplicates...", IDM_COMBINE_DUPLICATES
|
||||
MENUITEM "&Remove Audio and Visual Assets", IDM_REMOVE_AV_ASSETS
|
||||
MENUITEM "&Build Patch Mixfile", IDM_MAKE_MIX_PATCH
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Create Mix File...", IDM_CREATE_MIX_FILE
|
||||
MENUITEM "&Export Files...", IDM_EXPORT_FILES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "E&xit", ID_APP_EXIT
|
||||
END
|
||||
POPUP "&Edit"
|
||||
BEGIN
|
||||
MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT
|
||||
MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY
|
||||
MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE
|
||||
END
|
||||
POPUP "&View"
|
||||
BEGIN
|
||||
MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
|
||||
MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
|
||||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&About MixViewer...", ID_APP_ABOUT
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Accelerator
|
||||
//
|
||||
|
||||
IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE
|
||||
BEGIN
|
||||
"N", ID_FILE_NEW, VIRTKEY, CONTROL
|
||||
"O", ID_FILE_OPEN, VIRTKEY, CONTROL
|
||||
"S", ID_FILE_SAVE, VIRTKEY, CONTROL
|
||||
"Z", ID_EDIT_UNDO, VIRTKEY, CONTROL
|
||||
"X", ID_EDIT_CUT, VIRTKEY, CONTROL
|
||||
"C", ID_EDIT_COPY, VIRTKEY, CONTROL
|
||||
"V", ID_EDIT_PASTE, VIRTKEY, CONTROL
|
||||
VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT
|
||||
VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT
|
||||
VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL
|
||||
VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT
|
||||
VK_F6, ID_NEXT_PANE, VIRTKEY
|
||||
VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 235, 55
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "About MixViewer"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20
|
||||
LTEXT "MixViewer Version 1.0",IDC_STATIC,40,10,119,8,
|
||||
SS_NOPREFIX
|
||||
LTEXT "Copyright (C) 2001",IDC_STATIC,40,25,119,8
|
||||
DEFPUSHBUTTON "OK",IDOK,178,7,50,14,WS_GROUP
|
||||
END
|
||||
|
||||
IDD_COMBINING_DIALOG DIALOG DISCARDABLE 0, 0, 186, 58
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
|
||||
CAPTION "Mix Combiner"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
LTEXT "Building File Lists...",IDC_STATUS,7,7,172,22
|
||||
CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER,7,
|
||||
40,172,11
|
||||
END
|
||||
|
||||
IDD_MAKE_MIX_FILE DIALOG DISCARDABLE 0, 0, 386, 74
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Create Mix File"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Generate MIX file",IDOK,96,53,86,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,204,53,86,14
|
||||
EDITTEXT IDC_BROWSE_DIR_NAME,65,33,256,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_BROWSE_FILE_NAME,66,7,256,14,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "Browse...",IDC_BROWSE_FILE,329,7,50,14
|
||||
PUSHBUTTON "Browse...",IDC_BROWSE_DIR,329,33,50,14
|
||||
RTEXT "MIX Filename:",IDC_STATIC,7,7,57,14,SS_CENTERIMAGE
|
||||
RTEXT "Source Directory:",IDC_STATIC,7,33,57,14,SS_CENTERIMAGE
|
||||
END
|
||||
|
||||
|
||||
#ifndef _MAC
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "\0"
|
||||
VALUE "FileDescription", "MixViewer MFC Application\0"
|
||||
VALUE "FileVersion", "1, 0, 0, 1\0"
|
||||
VALUE "InternalName", "MixViewer\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2001\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "MixViewer.EXE\0"
|
||||
VALUE "ProductName", "MixViewer Application\0"
|
||||
VALUE "ProductVersion", "1, 0, 0, 1\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // !_MAC
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO DISCARDABLE
|
||||
BEGIN
|
||||
IDD_ABOUTBOX, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 228
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 48
|
||||
END
|
||||
|
||||
IDD_COMBINING_DIALOG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 179
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 51
|
||||
END
|
||||
|
||||
IDD_MAKE_MIX_FILE, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 379
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 67
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE PRELOAD DISCARDABLE
|
||||
BEGIN
|
||||
IDR_MAINFRAME "MixViewer\n\nMixVie\nMix Files (*.mix)\n.mix\nMixViewer.Document\nMixVie Document"
|
||||
END
|
||||
|
||||
STRINGTABLE PRELOAD DISCARDABLE
|
||||
BEGIN
|
||||
AFX_IDS_APP_TITLE "MixViewer"
|
||||
AFX_IDS_IDLEMESSAGE "Ready"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
ID_INDICATOR_EXT "EXT"
|
||||
ID_INDICATOR_CAPS "CAP"
|
||||
ID_INDICATOR_NUM "NUM"
|
||||
ID_INDICATOR_SCRL "SCRL"
|
||||
ID_INDICATOR_OVR "OVR"
|
||||
ID_INDICATOR_REC "REC"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
ID_FILE_NEW "Create a new document\nNew"
|
||||
ID_FILE_OPEN "Open an existing document\nOpen"
|
||||
ID_FILE_CLOSE "Close the active document\nClose"
|
||||
ID_FILE_SAVE "Save the active document\nSave"
|
||||
ID_FILE_SAVE_AS "Save the active document with a new name\nSave As"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
ID_APP_ABOUT "Display program information, version number and copyright\nAbout"
|
||||
ID_APP_EXIT "Quit the application; prompts to save documents\nExit"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
ID_FILE_MRU_FILE1 "Open this document"
|
||||
ID_FILE_MRU_FILE2 "Open this document"
|
||||
ID_FILE_MRU_FILE3 "Open this document"
|
||||
ID_FILE_MRU_FILE4 "Open this document"
|
||||
ID_FILE_MRU_FILE5 "Open this document"
|
||||
ID_FILE_MRU_FILE6 "Open this document"
|
||||
ID_FILE_MRU_FILE7 "Open this document"
|
||||
ID_FILE_MRU_FILE8 "Open this document"
|
||||
ID_FILE_MRU_FILE9 "Open this document"
|
||||
ID_FILE_MRU_FILE10 "Open this document"
|
||||
ID_FILE_MRU_FILE11 "Open this document"
|
||||
ID_FILE_MRU_FILE12 "Open this document"
|
||||
ID_FILE_MRU_FILE13 "Open this document"
|
||||
ID_FILE_MRU_FILE14 "Open this document"
|
||||
ID_FILE_MRU_FILE15 "Open this document"
|
||||
ID_FILE_MRU_FILE16 "Open this document"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
ID_NEXT_PANE "Switch to the next window pane\nNext Pane"
|
||||
ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
ID_WINDOW_SPLIT "Split the active window into panes\nSplit"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
ID_EDIT_CLEAR "Erase the selection\nErase"
|
||||
ID_EDIT_CLEAR_ALL "Erase everything\nErase All"
|
||||
ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy"
|
||||
ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut"
|
||||
ID_EDIT_FIND "Find the specified text\nFind"
|
||||
ID_EDIT_PASTE "Insert Clipboard contents\nPaste"
|
||||
ID_EDIT_REPEAT "Repeat the last action\nRepeat"
|
||||
ID_EDIT_REPLACE "Replace specific text with different text\nReplace"
|
||||
ID_EDIT_SELECT_ALL "Select the entire document\nSelect All"
|
||||
ID_EDIT_UNDO "Undo the last action\nUndo"
|
||||
ID_EDIT_REDO "Redo the previously undone action\nRedo"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar"
|
||||
ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
AFX_IDS_SCSIZE "Change the window size"
|
||||
AFX_IDS_SCMOVE "Change the window position"
|
||||
AFX_IDS_SCMINIMIZE "Reduce the window to an icon"
|
||||
AFX_IDS_SCMAXIMIZE "Enlarge the window to full size"
|
||||
AFX_IDS_SCNEXTWINDOW "Switch to the next document window"
|
||||
AFX_IDS_SCPREVWINDOW "Switch to the previous document window"
|
||||
AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
AFX_IDS_SCRESTORE "Restore the window to normal size"
|
||||
AFX_IDS_SCTASKLIST "Activate Task List"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDM_COMBINE_DUPLICATES "Combine duplicates from a file set into a shared mix file.\nCombine Duplicates"
|
||||
IDM_REMOVE_AV_ASSETS "Strip out audio and visual assets from a mixfile.\nRemove Audio and Visual Assets"
|
||||
IDM_CREATE_MIX_FILE "Creates a MIX file.\nCreate a MIX file"
|
||||
IDM_EXPORT_FILES "Export all files into a directory.\nExport Files"
|
||||
IDM_MAKE_MIX_PATCH "Build a patch mixfile from two source mix files.\nBuild Patch Mixfile"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
#define _AFX_NO_SPLITTER_RESOURCES
|
||||
#define _AFX_NO_OLE_RESOURCES
|
||||
#define _AFX_NO_TRACKER_RESOURCES
|
||||
#define _AFX_NO_PROPERTY_RESOURCES
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE 9, 1
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
#include "res\MixViewer.rc2" // non-Microsoft Visual C++ edited resources
|
||||
#include "afxres.rc" // Standard components
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
171
Code/Tools/MixViewer/MixViewerDoc.cpp
Normal file
171
Code/Tools/MixViewer/MixViewerDoc.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// MixViewerDoc.cpp : implementation of the CMixViewerDoc class
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "mixviewer.h"
|
||||
#include "mixviewerdoc.h"
|
||||
#include "mixviewerview.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMixViewerDoc
|
||||
|
||||
IMPLEMENT_DYNCREATE(CMixViewerDoc, CDocument)
|
||||
|
||||
BEGIN_MESSAGE_MAP(CMixViewerDoc, CDocument)
|
||||
//{{AFX_MSG_MAP(CMixViewerDoc)
|
||||
// NOTE - the ClassWizard will add and remove mapping macros here.
|
||||
// DO NOT EDIT what you see in these blocks of generated code!
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMixViewerDoc construction/destruction
|
||||
|
||||
CMixViewerDoc::CMixViewerDoc()
|
||||
{
|
||||
// TODO: add one-time construction code here
|
||||
|
||||
}
|
||||
|
||||
CMixViewerDoc::~CMixViewerDoc()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMixViewerDoc serialization
|
||||
|
||||
void CMixViewerDoc::Serialize(CArchive& ar)
|
||||
{
|
||||
if (ar.IsStoring())
|
||||
{
|
||||
// TODO: add storing code here
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: add loading code here
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMixViewerDoc diagnostics
|
||||
|
||||
#ifdef _DEBUG
|
||||
void CMixViewerDoc::AssertValid() const
|
||||
{
|
||||
CDocument::AssertValid();
|
||||
}
|
||||
|
||||
void CMixViewerDoc::Dump(CDumpContext& dc) const
|
||||
{
|
||||
CDocument::Dump(dc);
|
||||
}
|
||||
#endif //_DEBUG
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnNewDocument
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
CMixViewerDoc::OnNewDocument (void)
|
||||
{
|
||||
if (!CDocument::OnNewDocument ()) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Update each view
|
||||
//
|
||||
POSITION pos = GetFirstViewPosition ();
|
||||
while (pos != NULL)
|
||||
{
|
||||
CMixViewerView *view = (CMixViewerView *)GetNextView (pos);
|
||||
view->Reset ();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOpenDocument
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
CMixViewerDoc::OnOpenDocument (LPCTSTR path)
|
||||
{
|
||||
if (!CDocument::OnOpenDocument (path)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Start fresh
|
||||
//
|
||||
OnNewDocument ();
|
||||
|
||||
//
|
||||
// Update each view
|
||||
//
|
||||
POSITION pos = GetFirstViewPosition ();
|
||||
while (pos != NULL)
|
||||
{
|
||||
CMixViewerView *view = (CMixViewerView *)GetNextView (pos);
|
||||
view->Reload (path);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Reload_Views
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMixViewerDoc::Reload_Views (void)
|
||||
{
|
||||
//
|
||||
// Update each view
|
||||
//
|
||||
POSITION pos = GetFirstViewPosition ();
|
||||
while (pos != NULL)
|
||||
{
|
||||
CMixViewerView *view = (CMixViewerView *)GetNextView (pos);
|
||||
view->Reload (GetPathName ());
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
79
Code/Tools/MixViewer/MixViewerDoc.h
Normal file
79
Code/Tools/MixViewer/MixViewerDoc.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// MixViewerDoc.h : interface of the CMixViewerDoc class
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_MIXVIEWERDOC_H__3E44CD42_6816_4308_AD7B_241F70244FF1__INCLUDED_)
|
||||
#define AFX_MIXVIEWERDOC_H__3E44CD42_6816_4308_AD7B_241F70244FF1__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
|
||||
class CMixViewerDoc : public CDocument
|
||||
{
|
||||
protected: // create from serialization only
|
||||
CMixViewerDoc();
|
||||
DECLARE_DYNCREATE(CMixViewerDoc)
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
|
||||
// Operations
|
||||
public:
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CMixViewerDoc)
|
||||
public:
|
||||
virtual BOOL OnNewDocument();
|
||||
virtual void Serialize(CArchive& ar);
|
||||
virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
virtual ~CMixViewerDoc();
|
||||
#ifdef _DEBUG
|
||||
virtual void AssertValid() const;
|
||||
virtual void Dump(CDumpContext& dc) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
protected:
|
||||
//{{AFX_MSG(CMixViewerDoc)
|
||||
// NOTE - the ClassWizard will add and remove member functions here.
|
||||
// DO NOT EDIT what you see in these blocks of generated code !
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
void Reload_Views (void);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_MIXVIEWERDOC_H__3E44CD42_6816_4308_AD7B_241F70244FF1__INCLUDED_)
|
||||
340
Code/Tools/MixViewer/MixViewerView.cpp
Normal file
340
Code/Tools/MixViewer/MixViewerView.cpp
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// MixViewerView.cpp : implementation of the CMixViewerView class
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "MixViewer.h"
|
||||
|
||||
#include "mixviewerdoc.h"
|
||||
#include "mixviewerview.h"
|
||||
#include "ffactory.h"
|
||||
#include "mixfile.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Local prototypes
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
static int CALLBACK MixFilenamesListSortCallback (LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMixViewerView
|
||||
|
||||
IMPLEMENT_DYNCREATE(CMixViewerView, CListView)
|
||||
|
||||
BEGIN_MESSAGE_MAP(CMixViewerView, CListView)
|
||||
//{{AFX_MSG_MAP(CMixViewerView)
|
||||
ON_WM_CREATE()
|
||||
ON_NOTIFY_REFLECT(LVN_DELETEITEM, OnDeleteitem)
|
||||
ON_WM_WINDOWPOSCHANGING()
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CMixViewerView
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CMixViewerView::CMixViewerView (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~CMixViewerView
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CMixViewerView::~CMixViewerView (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PreCreateWindow
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
CMixViewerView::PreCreateWindow (CREATESTRUCT &cs)
|
||||
{
|
||||
cs.style |= LVS_REPORT;
|
||||
|
||||
return CListView::PreCreateWindow (cs);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDraw
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMixViewerView::OnDraw (CDC *pDC)
|
||||
{
|
||||
CMixViewerDoc* pDoc = GetDocument();
|
||||
ASSERT_VALID(pDoc);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitialUpdate
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMixViewerView::OnInitialUpdate (void)
|
||||
{
|
||||
CListView::OnInitialUpdate ();
|
||||
|
||||
//
|
||||
// Size the column
|
||||
//
|
||||
CRect rect;
|
||||
GetListCtrl ().GetClientRect (&rect);
|
||||
rect.right -= ::GetSystemMetrics (SM_CXVSCROLL) + 2;
|
||||
GetListCtrl ().SetColumnWidth (0, rect.Width ());
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CMixViewerView diagnostics
|
||||
|
||||
#ifdef _DEBUG
|
||||
void CMixViewerView::AssertValid() const
|
||||
{
|
||||
CListView::AssertValid();
|
||||
}
|
||||
|
||||
void CMixViewerView::Dump(CDumpContext& dc) const
|
||||
{
|
||||
CListView::Dump(dc);
|
||||
}
|
||||
|
||||
CMixViewerDoc* CMixViewerView::GetDocument() // non-debug version is inline
|
||||
{
|
||||
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMixViewerDoc)));
|
||||
return (CMixViewerDoc*)m_pDocument;
|
||||
}
|
||||
#endif //_DEBUG
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Reload
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMixViewerView::Reload (const char *filename)
|
||||
{
|
||||
CurrentFilename = filename;
|
||||
|
||||
CMixViewerDoc *document = GetDocument ();
|
||||
if (document == NULL) {
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Start fresh
|
||||
//
|
||||
GetListCtrl ().DeleteAllItems ();
|
||||
|
||||
//
|
||||
// Get the filename list from the mix file
|
||||
//
|
||||
MixFileFactoryClass mix_factory (filename, _TheFileFactory);
|
||||
if (mix_factory.Build_Filename_List (FilenameList)) {
|
||||
|
||||
//
|
||||
// Add each filename to the list
|
||||
//
|
||||
for (int index = 0; index < FilenameList.Count (); index ++) {
|
||||
int item_index = GetListCtrl ().InsertItem (index, FilenameList[index]);
|
||||
if (item_index != -1) {
|
||||
GetListCtrl ().SetItemData (item_index, (DWORD)new StringClass (FilenameList[index]));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Sort the data
|
||||
//
|
||||
GetListCtrl ().SortItems (MixFilenamesListSortCallback, 0);
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// Notify the user
|
||||
//
|
||||
StringClass message;
|
||||
message.Format ("Error reading the filename list from %s.", filename);
|
||||
MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Reset
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMixViewerView::Reset (void)
|
||||
{
|
||||
GetListCtrl ().DeleteAllItems ();
|
||||
FilenameList.Delete_All ();
|
||||
CurrentFilename = "";
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnCreate
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
int
|
||||
CMixViewerView::OnCreate (LPCREATESTRUCT lpCreateStruct)
|
||||
{
|
||||
if (CListView::OnCreate (lpCreateStruct) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the list control
|
||||
//
|
||||
GetListCtrl ().SetExtendedStyle (GetListCtrl ().GetExtendedStyle () | LVS_EX_FULLROWSELECT);
|
||||
GetListCtrl ().InsertColumn (0, "Filename");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// MixFilenamesListSortCallback
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
int CALLBACK
|
||||
MixFilenamesListSortCallback
|
||||
(
|
||||
LPARAM lParam1,
|
||||
LPARAM lParam2,
|
||||
LPARAM lParamSort
|
||||
)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
//
|
||||
// Get the data from list control
|
||||
//
|
||||
StringClass *item_data1 = (StringClass *)lParam1;
|
||||
StringClass *item_data2 = (StringClass *)lParam2;
|
||||
if (item_data1 != NULL && item_data2 != NULL) {
|
||||
|
||||
|
||||
bool is_1_dir = (::strrchr (*item_data1, '\\') != NULL);
|
||||
bool is_2_dir = (::strrchr (*item_data2, '\\') != NULL);
|
||||
|
||||
if (is_1_dir && is_2_dir == false) {
|
||||
retval = -1;
|
||||
} else if (is_1_dir == false && is_2_dir) {
|
||||
retval = 1;
|
||||
} else {
|
||||
|
||||
//
|
||||
// Do a simple string compare
|
||||
//
|
||||
retval = item_data1->Compare_No_Case (*item_data2);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDeleteitem
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMixViewerView::OnDeleteitem (NMHDR *pNMHDR, LRESULT *pResult)
|
||||
{
|
||||
NM_LISTVIEW* pNMListView = (NM_LISTVIEW *)pNMHDR;
|
||||
*pResult = 0;
|
||||
|
||||
//
|
||||
// Get the string associated with this entry
|
||||
//
|
||||
StringClass *string = (StringClass *)GetListCtrl ().GetItemData (pNMListView->iItem);
|
||||
GetListCtrl ().SetItemData (pNMListView->iItem, 0);
|
||||
|
||||
//
|
||||
// Free the string
|
||||
//
|
||||
if (string != NULL) {
|
||||
delete string;
|
||||
string = NULL;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnWindowPosChanging
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CMixViewerView::OnWindowPosChanging (WINDOWPOS FAR *lpwndpos)
|
||||
{
|
||||
if ((lpwndpos->flags & SWP_NOSIZE) == 0) {
|
||||
|
||||
//
|
||||
// Get the current percent of the column width
|
||||
//
|
||||
CRect rect;
|
||||
GetListCtrl ().GetWindowRect (&rect);
|
||||
int curr_width = GetListCtrl ().GetColumnWidth (0);
|
||||
float percent = (float)curr_width / (float)rect.Width ();
|
||||
|
||||
//
|
||||
// Size the column
|
||||
//
|
||||
int new_width = int(lpwndpos->cx * percent);
|
||||
GetListCtrl ().SetColumnWidth (0, new_width);
|
||||
}
|
||||
|
||||
CListView::OnWindowPosChanging (lpwndpos);
|
||||
return ;
|
||||
}
|
||||
112
Code/Tools/MixViewer/MixViewerView.h
Normal file
112
Code/Tools/MixViewer/MixViewerView.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// MixViewerView.h : interface of the CMixViewerView class
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_MIXVIEWERVIEW_H__562AE398_6B91_4DA8_B325_73D4EC73EB36__INCLUDED_)
|
||||
#define AFX_MIXVIEWERVIEW_H__562AE398_6B91_4DA8_B325_73D4EC73EB36__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
|
||||
#include "resource.h"
|
||||
#include "vector.h"
|
||||
#include "wwstring.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CMixViewerView
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
class CMixViewerView : public CListView
|
||||
{
|
||||
protected: // create from serialization only
|
||||
CMixViewerView();
|
||||
DECLARE_DYNCREATE(CMixViewerView)
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
CMixViewerDoc* GetDocument();
|
||||
|
||||
// Operations
|
||||
public:
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CMixViewerView)
|
||||
public:
|
||||
virtual void OnDraw(CDC* pDC); // overridden to draw this view
|
||||
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
|
||||
protected:
|
||||
virtual void OnInitialUpdate(); // called first time after construct
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
virtual ~CMixViewerView();
|
||||
#ifdef _DEBUG
|
||||
virtual void AssertValid() const;
|
||||
virtual void Dump(CDumpContext& dc) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
protected:
|
||||
//{{AFX_MSG(CMixViewerView)
|
||||
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
|
||||
afx_msg void OnDeleteitem(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnWindowPosChanging(WINDOWPOS FAR* lpwndpos);
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void Reload (const char *filename);
|
||||
void Reset (void);
|
||||
|
||||
private:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
DynamicVectorClass<StringClass> FilenameList;
|
||||
|
||||
StringClass CurrentFilename;
|
||||
};
|
||||
|
||||
|
||||
#ifndef _DEBUG // debug version in MixViewerView.cpp
|
||||
inline CMixViewerDoc* CMixViewerView::GetDocument()
|
||||
{ return (CMixViewerDoc*)m_pDocument; }
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_MIXVIEWERVIEW_H__562AE398_6B91_4DA8_B325_73D4EC73EB36__INCLUDED_)
|
||||
33
Code/Tools/MixViewer/Resource.h
Normal file
33
Code/Tools/MixViewer/Resource.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by MixViewer.rc
|
||||
//
|
||||
#define IDD_ABOUTBOX 100
|
||||
#define IDR_MAINFRAME 128
|
||||
#define IDR_MIXVIETYPE 129
|
||||
#define IDD_COMBINING_DIALOG 130
|
||||
#define IDI_ICON1 131
|
||||
#define IDD_MAKE_MIX_FILE 132
|
||||
#define IDC_STATUS 1000
|
||||
#define IDC_PROGRESS 1001
|
||||
#define IDC_BROWSE_DIR_NAME 1002
|
||||
#define IDC_BROWSE_FILE_NAME 1003
|
||||
#define IDC_BROWSE_FILE 1004
|
||||
#define IDC_BROWSE_DIR 1005
|
||||
#define IDM_COMBINE_DUPLICATES 32771
|
||||
#define IDM_REMOVE_AV_ASSETS 32773
|
||||
#define IDM_CREATE_MIX_FILE 32775
|
||||
#define IDM_EXPORT_FILES 32776
|
||||
#define IDM_MAKE_MIX_PATCH 32777
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_3D_CONTROLS 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 133
|
||||
#define _APS_NEXT_COMMAND_VALUE 32778
|
||||
#define _APS_NEXT_CONTROL_VALUE 1006
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
26
Code/Tools/MixViewer/StdAfx.cpp
Normal file
26
Code/Tools/MixViewer/StdAfx.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// MixViewer.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
|
||||
46
Code/Tools/MixViewer/StdAfx.h
Normal file
46
Code/Tools/MixViewer/StdAfx.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#if !defined(AFX_STDAFX_H__FDF881A5_EA5E_4820_A638_5E0BBA8E14D5__INCLUDED_)
|
||||
#define AFX_STDAFX_H__FDF881A5_EA5E_4820_A638_5E0BBA8E14D5__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#include <afxwin.h> // MFC core and standard components
|
||||
#include <afxext.h> // MFC extensions
|
||||
#include <afxcview.h>
|
||||
#include <afxdisp.h> // MFC Automation classes
|
||||
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
|
||||
#ifndef _AFX_NO_AFXCMN_SUPPORT
|
||||
#include <afxcmn.h> // MFC support for Windows Common Controls
|
||||
#endif // _AFX_NO_AFXCMN_SUPPORT
|
||||
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__FDF881A5_EA5E_4820_A638_5E0BBA8E14D5__INCLUDED_)
|
||||
592
Code/Tools/MixViewer/duplicatecombiner.cpp
Normal file
592
Code/Tools/MixViewer/duplicatecombiner.cpp
Normal file
@@ -0,0 +1,592 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WWAudio *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/MixViewer/duplicatecombiner.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 2/21/02 5:25p $*
|
||||
* *
|
||||
* $Revision:: 3 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "duplicatecombiner.h"
|
||||
#include "ffactory.h"
|
||||
#include "mixfile.h"
|
||||
#include "rawfile.h"
|
||||
#include "bittype.h"
|
||||
#include "mixcombiningdialog.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DuplicateRemoverClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
DuplicateRemoverClass::DuplicateRemoverClass (void) :
|
||||
TempFilenameStart (0),
|
||||
Dialog (NULL)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~DuplicateRemoverClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
DuplicateRemoverClass::~DuplicateRemoverClass (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Process
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
void
|
||||
DuplicateRemoverClass::Process (void)
|
||||
{
|
||||
//
|
||||
// Kick off the worker thread...
|
||||
//
|
||||
::AfxBeginThread (fnThreadProc, (LPVOID)this);
|
||||
|
||||
//
|
||||
// Show the UI
|
||||
//
|
||||
MixCombiningDialogClass dialog;
|
||||
Dialog = &dialog;
|
||||
dialog.DoModal ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// fnThreadProc
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
UINT
|
||||
DuplicateRemoverClass::fnThreadProc (LPVOID pParam)
|
||||
{
|
||||
//
|
||||
// Simply ask the combiner to start processing
|
||||
//
|
||||
DuplicateRemoverClass *remover = (DuplicateRemoverClass *)pParam;
|
||||
if (remover != NULL) {
|
||||
remover->Internal_Process ();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Internal_Process
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
void
|
||||
DuplicateRemoverClass::Internal_Process (void)
|
||||
{
|
||||
Make_Temp_Directory ();
|
||||
|
||||
//
|
||||
// Open the source mix files
|
||||
//
|
||||
DynamicVectorClass<MixFileFactoryClass *> mix_file_list;
|
||||
Open_Mix_Files (mix_file_list);
|
||||
|
||||
//
|
||||
// Open the destination mix factory
|
||||
//
|
||||
MixFileFactoryClass dest_factory (DestinationMixFilename, _TheFileFactory);
|
||||
if (dest_factory.Is_Valid () && dest_factory.Build_Internal_Filename_List ()) {
|
||||
Dialog->Set_Status_Text ("Building temporary files...");
|
||||
Dialog->Set_Progress_Percent (0);
|
||||
|
||||
//
|
||||
// Loop over each mix file...
|
||||
//
|
||||
for (int mix_index = 0; mix_index < mix_file_list.Count (); mix_index ++) {
|
||||
|
||||
//
|
||||
// Get the list of filenames inside this mix file
|
||||
//
|
||||
DynamicVectorClass<StringClass> filename_list;
|
||||
mix_file_list[mix_index]->Get_Filename_List (filename_list);
|
||||
|
||||
for (int file_index = 0; file_index < filename_list.Count (); file_index ++) {
|
||||
StringClass filename = ::strlwr (filename_list[file_index].Peek_Buffer ());
|
||||
|
||||
DynamicVectorClass<int> dup_indices;
|
||||
dup_indices.Add (mix_index);
|
||||
|
||||
//
|
||||
// Try to find this file in any of the other mix files
|
||||
//
|
||||
for (int test_mix_index = 0; test_mix_index < mix_file_list.Count (); test_mix_index ++) {
|
||||
if (test_mix_index != mix_index && Is_File_In_Factory (filename, mix_file_list[test_mix_index])) {
|
||||
dup_indices.Add (test_mix_index);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check to see if this file is already in the "destination" file
|
||||
//
|
||||
bool is_in_dest = Is_File_In_Factory (filename, &dest_factory);
|
||||
|
||||
//
|
||||
// Were there any duplicates?
|
||||
//
|
||||
if (dup_indices.Count () > 1 || is_in_dest) {
|
||||
|
||||
//
|
||||
// Copy the file from the source to the destination factory
|
||||
//
|
||||
if (is_in_dest == false) {
|
||||
Copy_File (mix_file_list[mix_index], &dest_factory, filename);
|
||||
}
|
||||
|
||||
//
|
||||
// Remove all the duplicates from the mix files
|
||||
//
|
||||
for (int dup_index = 0; dup_index < dup_indices.Count (); dup_index ++) {
|
||||
mix_file_list[dup_indices[dup_index]]->Delete_File (filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Update the UI
|
||||
//
|
||||
Dialog->Set_Progress_Percent ((float)mix_index / float(mix_file_list.Count () + 1));
|
||||
}
|
||||
|
||||
//
|
||||
// Save the changes
|
||||
//
|
||||
Dialog->Set_Status_Text ("Reconstructing mix files...");
|
||||
Dialog->Set_Progress_Percent (0);
|
||||
dest_factory.Flush_Changes ();
|
||||
Dialog->Set_Progress_Percent (1.0F / float(mix_file_list.Count () + 1));
|
||||
for (int index = 0; index < mix_file_list.Count (); index ++) {
|
||||
mix_file_list[index]->Flush_Changes ();
|
||||
Dialog->Set_Progress_Percent ((float)index / float(mix_file_list.Count () + 1));
|
||||
}
|
||||
Dialog->Set_Progress_Percent (1.0F);
|
||||
}
|
||||
|
||||
//
|
||||
// Free each of the mix file factories
|
||||
//
|
||||
Close_Mix_Files (mix_file_list);
|
||||
|
||||
//
|
||||
// Remove the temporary directory we created
|
||||
//
|
||||
Delete_Temp_Directory ();
|
||||
|
||||
//
|
||||
// Close the dialog
|
||||
//
|
||||
Dialog->PostMessage (WM_COMMAND, MAKELPARAM (IDOK, BN_CLICKED));
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copy_File
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
void
|
||||
DuplicateRemoverClass::Copy_File
|
||||
(
|
||||
MixFileFactoryClass * src_mix,
|
||||
MixFileFactoryClass * dest_mix,
|
||||
const char * filename
|
||||
)
|
||||
{
|
||||
//
|
||||
// Get the file data from the source mix
|
||||
//
|
||||
FileClass *src_file = src_mix->Get_File (filename);
|
||||
src_file->Open ();
|
||||
|
||||
//
|
||||
// Create a destination file for the data
|
||||
//
|
||||
StringClass full_path;
|
||||
Get_Temp_Filename (full_path);
|
||||
RawFileClass dest_file;
|
||||
dest_file.Set_Name (full_path);
|
||||
if (dest_file.Open (RawFileClass::WRITE)) {
|
||||
|
||||
//
|
||||
// Copy the data from the source mix file to the destination file
|
||||
//
|
||||
int file_size = src_file->Size ();
|
||||
uint8 buffer[4096];
|
||||
while (file_size > 0) {
|
||||
|
||||
//
|
||||
// Read the data from the source file
|
||||
//
|
||||
int bytes = min (file_size, (int)sizeof (buffer));
|
||||
int copied_size = src_file->Read (buffer, bytes);
|
||||
file_size -= copied_size;
|
||||
if (copied_size <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the data to the dest file
|
||||
//
|
||||
dest_file.Write (buffer, copied_size);
|
||||
}
|
||||
|
||||
//
|
||||
// Add the file to the destination mix file
|
||||
//
|
||||
dest_mix->Add_File (full_path, filename);
|
||||
|
||||
//
|
||||
// Close the temporary data file
|
||||
//
|
||||
dest_file.Close ();
|
||||
}
|
||||
|
||||
//
|
||||
// Return the file
|
||||
//
|
||||
src_mix->Return_File (src_file);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Open_Mix_Files
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
void
|
||||
DuplicateRemoverClass::Open_Mix_Files (DynamicVectorClass<MixFileFactoryClass *> &list)
|
||||
{
|
||||
//
|
||||
// Loop over all the mix filenames in our list
|
||||
//
|
||||
for (int index = 0; index < MixFileList.Count (); index ++) {
|
||||
|
||||
//
|
||||
// Create this mix file factory and add it to our list
|
||||
//
|
||||
MixFileFactoryClass *mix_factory = new MixFileFactoryClass (MixFileList[index], _TheFileFactory);
|
||||
if (mix_factory->Is_Valid () && mix_factory->Build_Internal_Filename_List ()) {
|
||||
list.Add (mix_factory);
|
||||
} else {
|
||||
delete mix_factory;
|
||||
mix_factory = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Update the UI
|
||||
//
|
||||
Dialog->Set_Progress_Percent ((float)index / float(MixFileList.Count () + 1));
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Close_Mix_Files
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
void
|
||||
DuplicateRemoverClass::Close_Mix_Files (DynamicVectorClass<MixFileFactoryClass *> &list)
|
||||
{
|
||||
//
|
||||
// Simply free each entry in the list
|
||||
//
|
||||
for (int index = 0; index < list.Count (); index ++) {
|
||||
delete list[index];
|
||||
}
|
||||
|
||||
list.Delete_All ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// Make_Temp_Directory
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void
|
||||
DuplicateRemoverClass::Make_Temp_Directory (void)
|
||||
{
|
||||
//
|
||||
// Get the path of the temp directory
|
||||
//
|
||||
char temp_dir[MAX_PATH] = { 0 };
|
||||
::GetTempPath (sizeof (temp_dir), temp_dir);
|
||||
|
||||
CString temp_path = Make_Path (temp_dir, "mixcombiner");
|
||||
|
||||
//
|
||||
// Try to find a unique temp directory to store our data
|
||||
//
|
||||
int index = 0;
|
||||
do {
|
||||
TempDirectory.Format ("%s%.2d.DIR", (const char *)temp_path, index++);
|
||||
} while (GetFileAttributes (TempDirectory) != 0xFFFFFFFF);
|
||||
|
||||
//
|
||||
// Create the directory
|
||||
//
|
||||
::CreateDirectory (TempDirectory, NULL);
|
||||
::SetCurrentDirectory (TempDirectory);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// Delete_Temp_Directory
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void
|
||||
DuplicateRemoverClass::Delete_Temp_Directory (void)
|
||||
{
|
||||
//
|
||||
// Change the current directory so we can remove the temporary one
|
||||
//
|
||||
::SetCurrentDirectory ("c:\\");
|
||||
|
||||
//
|
||||
// Remove the temporary directory
|
||||
//
|
||||
Clean_Directory (TempDirectory);
|
||||
::RemoveDirectory (TempDirectory);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Clean_Directory
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
DuplicateRemoverClass::Clean_Directory (LPCTSTR local_dir)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
//
|
||||
// Build a search mask from the directory
|
||||
//
|
||||
StringClass search_mask = StringClass (local_dir) + "\\*.*";
|
||||
|
||||
//
|
||||
// Loop through all the files in this directory and add them
|
||||
// to our list
|
||||
//
|
||||
DynamicVectorClass<StringClass> file_list;
|
||||
BOOL keep_going = TRUE;
|
||||
WIN32_FIND_DATA find_info = { 0 };
|
||||
for (HANDLE hfind = ::FindFirstFile (search_mask, &find_info);
|
||||
(hfind != INVALID_HANDLE_VALUE) && keep_going;
|
||||
keep_going = ::FindNextFile (hfind, &find_info))
|
||||
{
|
||||
|
||||
//
|
||||
// If this file isn't a directory, add it to the list
|
||||
//
|
||||
if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
StringClass filename = find_info.cFileName;
|
||||
file_list.Add (filename);
|
||||
} else if (find_info.cFileName[0] != '.') {
|
||||
|
||||
//
|
||||
// Recurse into this subdirectory
|
||||
//
|
||||
StringClass full_path = Make_Path (local_dir, find_info.cFileName);
|
||||
Clean_Directory (full_path);
|
||||
|
||||
//
|
||||
// Add this directory to the list so it will get
|
||||
// deleted with the files...
|
||||
//
|
||||
StringClass filename = find_info.cFileName;
|
||||
file_list.Add (filename);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Close the search handle
|
||||
//
|
||||
if (hfind != NULL) {
|
||||
::FindClose (hfind);
|
||||
}
|
||||
|
||||
//
|
||||
// Now loop through all the files and delete them
|
||||
//
|
||||
for (int index = 0; index < file_list.Count (); index ++) {
|
||||
StringClass &filename = file_list[index];
|
||||
StringClass full_path = Make_Path (local_dir, filename);
|
||||
Delete_File (full_path);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Make_Path
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
StringClass
|
||||
DuplicateRemoverClass::Make_Path (LPCTSTR path, LPCTSTR filename)
|
||||
{
|
||||
StringClass full_path = path;
|
||||
|
||||
//
|
||||
// Delimit the path if necessary
|
||||
//
|
||||
if (full_path[full_path.Get_Length () - 1] != '\\') {
|
||||
full_path += "\\";
|
||||
}
|
||||
|
||||
//
|
||||
// Concatenate the filename onto the path
|
||||
//
|
||||
full_path += filename;
|
||||
|
||||
return full_path;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Temp_Filename
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void
|
||||
DuplicateRemoverClass::Get_Temp_Filename (StringClass &full_path)
|
||||
{
|
||||
CString temp_path = Make_Path (TempDirectory, "tempfile");
|
||||
|
||||
//
|
||||
// Try to find a unique temp filename
|
||||
//
|
||||
do {
|
||||
full_path.Format ("%s%.5d.dat", (const char *)temp_path, TempFilenameStart++);
|
||||
} while (GetFileAttributes (full_path) != 0xFFFFFFFF);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Delete_File
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
DuplicateRemoverClass::Delete_File (LPCTSTR filename)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
ASSERT (filename != NULL);
|
||||
if (filename != NULL) {
|
||||
|
||||
//
|
||||
// Strip the readonly bit off if necessary
|
||||
//
|
||||
DWORD attributes = ::GetFileAttributes (filename);
|
||||
if ((attributes != 0xFFFFFFFF) &&
|
||||
((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY))
|
||||
{
|
||||
::SetFileAttributes (filename, attributes & (~FILE_ATTRIBUTE_READONLY));
|
||||
}
|
||||
|
||||
//
|
||||
// Perform the delete operation!
|
||||
//
|
||||
if ((attributes != 0xFFFFFFFF) &&
|
||||
((attributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
retval = (::RemoveDirectory (filename) == TRUE);
|
||||
} else {
|
||||
retval = (::DeleteFile (filename) == TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Is_File_In_Factory
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
DuplicateRemoverClass::Is_File_In_Factory (const StringClass &filename, MixFileFactoryClass *factory)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
//
|
||||
// Get the list of filenames inside this mix file
|
||||
//
|
||||
DynamicVectorClass<StringClass> *test_filename_list = NULL;
|
||||
factory->Get_Filename_List (&test_filename_list);
|
||||
|
||||
//
|
||||
// Try to find the file inside this mix file
|
||||
//
|
||||
for (int index = 0; index < test_filename_list->Count (); index ++) {
|
||||
if (filename.Compare_No_Case ((*test_filename_list)[index]) == 0) {
|
||||
retval = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
123
Code/Tools/MixViewer/duplicatecombiner.h
Normal file
123
Code/Tools/MixViewer/duplicatecombiner.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WWAudio *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/MixViewer/duplicatecombiner.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 9/12/01 7:17p $*
|
||||
* *
|
||||
* $Revision:: 2 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __DUPLICATE_REMOVER_H
|
||||
#define __DUPLICATE_REMOVER_H
|
||||
|
||||
#include "wwstring.h"
|
||||
#include "vector.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
class MixFileFactoryClass;
|
||||
class MixCombiningDialogClass;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DuplicateRemoverClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
class DuplicateRemoverClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructor
|
||||
//////////////////////////////////////////////////////////////////
|
||||
DuplicateRemoverClass (void);
|
||||
~DuplicateRemoverClass (void);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Configuration
|
||||
//
|
||||
void Add_Mix_File (const char *filename) { MixFileList.Add (filename); }
|
||||
void Set_Destination_File (const char *filename) { DestinationMixFilename = filename; }
|
||||
|
||||
//
|
||||
// Processing
|
||||
//
|
||||
void Process (void);
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
void Open_Mix_Files (DynamicVectorClass<MixFileFactoryClass *> &list);
|
||||
void Close_Mix_Files (DynamicVectorClass<MixFileFactoryClass *> &list);
|
||||
void Internal_Process (void);
|
||||
|
||||
static UINT fnThreadProc (LPVOID pParam);
|
||||
|
||||
|
||||
//
|
||||
// Utilities
|
||||
//
|
||||
void Copy_File (MixFileFactoryClass *src_mix, MixFileFactoryClass *dest_mix, const char *filename);
|
||||
bool Clean_Directory (LPCTSTR local_dir);
|
||||
void Get_Temp_Filename (StringClass &full_path);
|
||||
void Make_Temp_Directory (void);
|
||||
void Delete_Temp_Directory (void);
|
||||
bool Delete_File (LPCTSTR filename);
|
||||
StringClass Make_Path (LPCTSTR path, LPCTSTR filename);
|
||||
bool Is_File_In_Factory (const StringClass &filename, MixFileFactoryClass *factory);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////////////
|
||||
DynamicVectorClass<StringClass> MixFileList;
|
||||
StringClass DestinationMixFilename;
|
||||
StringClass TempDirectory;
|
||||
int TempFilenameStart;
|
||||
MixCombiningDialogClass * Dialog;
|
||||
};
|
||||
|
||||
|
||||
#endif //__DUPLICATE_REMOVER_H
|
||||
|
||||
BIN
Code/Tools/MixViewer/res/MixViewer.ico
Normal file
BIN
Code/Tools/MixViewer/res/MixViewer.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
13
Code/Tools/MixViewer/res/MixViewer.rc2
Normal file
13
Code/Tools/MixViewer/res/MixViewer.rc2
Normal file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// MIXVIEWER.RC2 - resources Microsoft Visual C++ does not edit directly
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#error this file is not editable by Microsoft Visual C++
|
||||
#endif //APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Add manually edited resources here...
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BIN
Code/Tools/MixViewer/res/MixViewerDoc.ico
Normal file
BIN
Code/Tools/MixViewer/res/MixViewerDoc.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Code/Tools/MixViewer/res/Toolbar.bmp
Normal file
BIN
Code/Tools/MixViewer/res/Toolbar.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 958 B |
BIN
Code/Tools/MixViewer/res/icon1.ico
Normal file
BIN
Code/Tools/MixViewer/res/icon1.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 766 B |
Reference in New Issue
Block a user