Delete obsolete AoE3Ed code

This was SVN commit r10909.
This commit is contained in:
Ykkrosh 2012-01-14 19:12:18 +00:00
parent c9cdde256f
commit e4b2de4bba
30 changed files with 5 additions and 3798 deletions

View File

@ -249,23 +249,6 @@ extern_lib_defs = {
})
end,
},
devil = {
compile_settings = function()
if os.is("windows") then
add_default_include_paths("devil")
end
end,
link_settings = function()
-- On Windows, it uses #pragma comment(lib ...) to link the library,
-- so we only need to include the library-search-path
if os.is("windows") then
add_default_lib_paths("devil")
end
add_default_links({
unix_names = { "IL", "ILU" },
})
end,
},
enet = {
compile_settings = function()
if not _OPTIONS["with-system-enet"] then
@ -565,23 +548,6 @@ extern_lib_defs = {
})
end,
},
xerces = {
compile_settings = function()
if os.is("windows") then
add_default_include_paths("xerces")
end
end,
link_settings = function()
if os.is("windows") then
add_default_lib_paths("xerces")
end
add_default_links({
win_names = { "xerces-c_2" },
unix_names = { "xerces-c" },
no_delayload = 1,
})
end,
},
zlib = {
compile_settings = function()
if os.is("windows") then

View File

@ -1,7 +1,6 @@
newoption { trigger = "atlas", description = "Include Atlas scenario editor projects" }
newoption { trigger = "collada", description = "Include COLLADA projects (requires FCollada library)" }
newoption { trigger = "coverage", description = "Enable code coverage data collection (GCC only)" }
newoption { trigger = "aoe3ed", description = "Include AoE3Ed" }
newoption { trigger = "icc", description = "Use Intel C++ Compiler (Linux only; should use either \"--cc icc\" or --without-pch too, and then set CXX=icpc before calling make)" }
newoption { trigger = "outpath", description = "Location for generated project files" }
newoption { trigger = "without-tests", description = "Disable generation of test projects" }
@ -730,10 +729,6 @@ function setup_atlas_project(project_name, target_type, rel_source_dirs, rel_inc
project_add_contents(source_root, rel_source_dirs, rel_include_dirs, extra_params)
project_add_extern_libs(extern_libs, target_type)
if _OPTIONS["aoe3ed"] then
defines { "USE_AOE3ED" }
end
-- Platform Specifics
if os.is("windows") then
defines { "_UNICODE" }
@ -812,12 +807,6 @@ function setup_atlas_projects()
"AtlasObject",
"AtlasScript",
}
if _OPTIONS["aoe3ed"] then
table.insert(atlas_src, "ArchiveViewer")
table.insert(atlas_src, "FileConverter")
table.insert(atlas_extra_links, "DatafileIO")
table.insert(atlas_extra_links, "xerces-c")
end
atlas_extern_libs = {
"boost",
@ -830,9 +819,6 @@ function setup_atlas_projects()
"x11",
"zlib",
}
if _OPTIONS["aoe3ed"] then
table.insert(atlas_extern_libs, "devil")
end
setup_atlas_project("AtlasUI", "SharedLib", atlas_src,
{ -- include
@ -847,25 +833,6 @@ function setup_atlas_projects()
extra_links = atlas_extra_links,
extra_files = { "Misc/atlas.rc" }
})
if _OPTIONS["aoe3ed"] then
setup_atlas_project("DatafileIO", "StaticLib",
{ -- src
".",
"BAR",
"DDT",
"SCN",
"Stream",
"XMB"
},{ -- include
},{ -- extern_libs
"devil",
"xerces",
"zlib"
},{ -- extra_params
})
end
end
@ -899,9 +866,6 @@ function setup_atlas_frontend_project (project_name)
project_add_manifest()
else -- Non-Windows, = Unix
if _OPTIONS["aoe3ed"] then
links { "DatafileIO" }
end
links { "AtlasObject" }
end
@ -911,10 +875,6 @@ end
function setup_atlas_frontends()
setup_atlas_frontend_project("ActorEditor")
if _OPTIONS["aoe3ed"] then
setup_atlas_frontend_project("ArchiveViewer")
setup_atlas_frontend_project("FileConverter")
end
end

View File

@ -1,43 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
// Use WinXP-style controls
# if _MSC_VER >= 1400 // (can't be bothered to implement this for VC7.1...)
# pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df'\"")
# endif
# define ATLASDLLIMPEXP extern "C" __declspec(dllimport)
#else
# define ATLASDLLIMPEXP extern "C"
#endif
#include "AtlasUI/Misc/DLLInterface.h"
#ifdef _WIN32
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
#else
int main()
#endif
{
Atlas_StartWindow(L"ArchiveViewer");
return 0;
}

View File

@ -1 +0,0 @@
IDI_ICON1 ICON "..\\AtlasUI\\Misc\\Graphics\\ArchiveViewer.ico"

View File

@ -1,43 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
// Use WinXP-style controls
# if _MSC_VER >= 1400 // (can't be bothered to implement this for VC7.1...)
# pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df'\"")
# endif
# define ATLASDLLIMPEXP extern "C" __declspec(dllimport)
#else
# define ATLASDLLIMPEXP extern "C"
#endif
#include "AtlasUI/Misc/DLLInterface.h"
#ifdef _WIN32
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
#else
int main()
#endif
{
Atlas_StartWindow(L"FileConverter");
return 0;
}

View File

@ -1 +0,0 @@
IDI_ICON1 ICON "..\\AtlasUI\\Misc\\Graphics\\FileConverter.ico"

View File

@ -8,15 +8,6 @@ my @progs = (
PROJECT_NAME => "ActorEditor",
WINDOW_NAME => "ActorEditor",
},
{
PROJECT_NAME => "FileConverter",
WINDOW_NAME => "FileConverter",
},
{
PROJECT_NAME => "ArchiveViewer",
WINDOW_NAME => "ArchiveViewer",
},
);
for my $p (@progs) {

View File

@ -1,652 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "ArchiveViewer.h"
#include "Misc/Version.h"
#include <set>
#include <algorithm>
#include "DatafileIO/BAR/BAR.h"
#include "DatafileIO/Stream/Stream.h"
#include "DatafileIO/Stream/wx.h"
using namespace DatafileIO;
#include "wx/dnd.h"
#include "wx/confbase.h"
#include "wx/wfstream.h"
#include "wx/tooltip.h"
#include "wx/progdlg.h"
#include "wx/regex.h"
#ifdef __WXMSW__
# include "wx/msw/registry.h"
#endif
// Possible TODO: Remove duplication of AtlasWindow code
enum {
ID_ExtractSelected,
ID_ExtractAll,
ID_EnablePreview,
ID_About
};
BEGIN_EVENT_TABLE(ArchiveViewer, wxFrame)
EVT_MENU(wxID_OPEN, ArchiveViewer::OnOpen)
EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, ArchiveViewer::OnMRUFile)
EVT_MENU(wxID_EXIT, ArchiveViewer::OnQuit)
EVT_MENU(ID_ExtractSelected, ArchiveViewer::OnExtractSelected)
EVT_MENU(ID_ExtractAll, ArchiveViewer::OnExtractAll)
EVT_MENU(ID_EnablePreview, ArchiveViewer::OnEnablePreview)
EVT_MENU(ID_About, ArchiveViewer::OnAbout)
EVT_CLOSE(ArchiveViewer::OnClose)
END_EVENT_TABLE()
//////////////////////////////////////////////////////////////////////////
class FilterTextCtrl : public wxTextCtrl
{
public:
FilterTextCtrl(wxWindow* parent, ArchiveViewer* archViewWin, const wxSize& size)
: wxTextCtrl(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, size),
m_archViewWin(archViewWin) {}
private:
void OnChange(wxCommandEvent& WXUNUSED(event))
{
m_archViewWin->SetFilter(GetValue());
}
ArchiveViewer* m_archViewWin;
DECLARE_EVENT_TABLE();
};
BEGIN_EVENT_TABLE(FilterTextCtrl, wxTextCtrl)
EVT_TEXT(wxID_ANY, FilterTextCtrl::OnChange)
END_EVENT_TABLE()
class FileListCtrl : public wxListCtrl
{
public:
FileListCtrl(wxWindow* parent, ArchiveViewer* archViewWin)
: wxListCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT),
m_archViewWin(archViewWin) {}
void OnSelect(wxListEvent& event)
{
m_archViewWin->UpdatePreview(event.GetIndex());
}
private:
ArchiveViewer* m_archViewWin;
DECLARE_EVENT_TABLE();
};
BEGIN_EVENT_TABLE(FileListCtrl, wxListCtrl)
EVT_LIST_ITEM_SELECTED(wxID_ANY, FileListCtrl::OnSelect)
END_EVENT_TABLE()
//////////////////////////////////////////////////////////////////////////
// Allow drag-and-drop of files onto the window, as a convenient way of opening them
//class DropTarget : public wxFileDropTarget
//{
//public:
// DropTarget(ColourTesterImageCtrl* imgctrl)
// : m_ImageCtrl(imgctrl)
// {}
//
// bool OnDropFiles(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxArrayString& filenames)
// {
// if (filenames.GetCount() >= 1)
// m_ImageCtrl->SetImageFile(filenames[0]);
// return true;
// }
//private:
// ColourTesterImageCtrl* m_ImageCtrl;
//};
ArchiveViewer::ArchiveViewer(wxWindow* parent)
: wxFrame(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(600, 371))
, m_FileHistory(_T("Archive Viewer"))
, m_WindowTitle(wxString::Format(_("%s - Archive Viewer"), g_ProgramNameVersion.c_str()))
, m_BARStream(NULL), m_BARReader(NULL), m_PreviewEnabled(false)
{
SetIcon(wxIcon(_T("ICON_ArchiveViewer")));
wxToolTip::Enable(true);
wxMenuBar* menuBar = new wxMenuBar;
SetMenuBar(menuBar);
wxMenu *menuFile = new wxMenu;
menuBar->Append(menuFile, _("&File"));
{
menuFile->Append(wxID_OPEN, _("&Open..."));
menuFile->AppendSeparator();//-----------
menuFile->Append(wxID_EXIT, _("E&xit"));
m_FileHistory.UseMenu(menuFile);//-------
m_FileHistory.AddFilesToMenu();
}
wxMenu *menuView = new wxMenu;
menuBar->Append(menuView, _("&View"));
{
menuView->AppendCheckItem(ID_EnablePreview, _("&Preview"));
}
wxMenu *menuExtract = new wxMenu;
menuBar->Append(menuExtract, _("&Extract"));
{
menuExtract->Append(ID_ExtractAll, _("&All files..."));
menuExtract->Append(ID_ExtractSelected, _("&Selected..."));
}
wxMenu *menuHelp = new wxMenu;
menuBar->Append(menuHelp, _("&Help"));
{
menuHelp->Append(ID_About, _("&About"));
}
m_FileHistory.Load(*wxConfigBase::Get());
m_Splitter = new SnapSplitterWindow(this, wxSP_NOBORDER | wxSP_3DSASH);
wxPanel* leftPanel = new wxPanel(m_Splitter);
//////////////////////////////////////////////////////////////////////////
// Set up sizers:
wxBoxSizer* vertSizer = new wxBoxSizer(wxVERTICAL);
leftPanel->SetSizer(vertSizer);
wxBoxSizer* filterSizer = new wxBoxSizer(wxHORIZONTAL);
//////////////////////////////////////////////////////////////////////////
// Add things to sizers:
m_FileListCtrl = new FileListCtrl(leftPanel, this);
m_FileListCtrl->InsertColumn(0, _("Filename"), wxLIST_FORMAT_LEFT, 300);
m_FileListCtrl->InsertColumn(1, _("File size (bytes)"), wxLIST_FORMAT_RIGHT, 100);
m_FileListCtrl->InsertColumn(2, _("Last modified date"), wxLIST_FORMAT_LEFT, 150);
vertSizer->Add(m_FileListCtrl, wxSizerFlags().Expand().Proportion(1).Border(wxALL, 5));
vertSizer->Add(filterSizer,
wxSizerFlags().Expand().Border(wxLEFT|wxRIGHT|wxBOTTOM, 5));
m_PreviewWindow = new FilePreviewer(m_Splitter);
m_PreviewWindow->Hide();
m_Splitter->Initialize(leftPanel);
filterSizer->Add(new wxStaticText(leftPanel, wxID_ANY, _("&Search for file:")),
wxSizerFlags().Centre().Border(wxALL, 5));
FilterTextCtrl* filterTextCtrl = new FilterTextCtrl(leftPanel, this, wxSize(150, -1));
filterTextCtrl->SetToolTip(_("You may use * to match any sequence characters, and ? to match a single character"));
filterSizer->Add(filterTextCtrl, wxSizerFlags().Border(wxALL, 5));
//////////////////////////////////////////////////////////////////////////
SetCurrentFilename();
}
void ArchiveViewer::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox(wxString::Format(_("%s - created by Philip Taylor (philip@wildfiregames.com / philip@zaynar.demon.co.uk)"), g_ProgramNameVersion.c_str()),
_("About"), wxOK|wxCENTRE|wxICON_INFORMATION);
}
ArchiveViewer::~ArchiveViewer()
{
delete m_BARStream;
delete m_BARReader;
}
void ArchiveViewer::OnClose(wxCloseEvent& event)
{
event.Skip();
m_FileHistory.Save(*wxConfigBase::Get());
}
//struct compare_bar {
// bool operator()(const BAREntry& x, const BAREntry& y) { return (x.filename < y.filename); }
//};
void ArchiveViewer::RedrawFileList(bool keepSelection)
{
if (!m_BARReader || !m_BARStream)
// No BAR file loaded
return;
std::vector<bool> filesSelected;
filesSelected.resize(m_CachedFileData.size(), false);
// If desired, remember a list of selected and focussed items
int focussed = -1;
if (keepSelection)
{
// Iterate through selected items
long item = m_FileListCtrl->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
while (item != -1)
{
filesSelected[ m_FileListCtrl->GetItemData(item) ] = true;
item = m_FileListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
}
// Remember single focussed item
item = m_FileListCtrl->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
if (item != -1)
focussed = m_FileListCtrl->GetItemData(item);
}
wxString filter;
enum { NONE, SUBSTRING, WILDCARD } filterType = NONE; // attempt to use most efficient matching system
if (m_Filter.Len())
{
if (m_Filter.Contains(_T("*")) || m_Filter.Contains(_T("?")))
{
filterType = WILDCARD;
filter = _T("*") + m_Filter.Lower() + _T("*"); // match any substring, and case insensitive
}
else
{
filterType = SUBSTRING;
filter = m_Filter.Lower();
}
}
m_FileListCtrl->Freeze();
m_FileListCtrl->DeleteAllItems();
for (size_t i = 0; i < m_CachedFileData.size(); ++i)
{
if ( (filterType == SUBSTRING && !m_CachedFileData[i].NameLower.Contains(filter))
|| (filterType == WILDCARD && !m_CachedFileData[i].NameLower.Matches(filter)))
continue;
wxListItem info;
info.SetText(m_CachedFileData[i].Name);
info.SetData((long)i);
info.SetId((long)i);
if (keepSelection)
{
int state = (filesSelected[i] ? wxLIST_STATE_SELECTED : 0) | (focussed == (int)i ? wxLIST_STATE_FOCUSED : 0);
if (state)
{
info.SetState(state);
info.SetStateMask(wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
}
}
long idx = m_FileListCtrl->InsertItem(info);
wxASSERT(idx != -1);
m_FileListCtrl->SetItem(idx, 1, m_CachedFileData[i].Size);
m_FileListCtrl->SetItem(idx, 2, m_CachedFileData[i].Date);
}
m_FileListCtrl->Thaw();
}
void ArchiveViewer::UpdateFileList()
{
if (!m_BARReader || !m_BARStream)
// No BAR file loaded
return;
wxRegEx commas (_T("(\\d+)(\\d{3})"), wxRE_ADVANCED); // for comma-ising filesizes
// Get list of all files
// std::vector<BAREntry> files = m_BARReader->GetFileList(); // non-constref copy, so we can sort it
// std::sort(files.begin(), files.end(), compare_bar());
const std::vector<BAREntry>& files = m_BARReader->GetFileList();
m_CachedFileData.clear();
m_CachedFileData.resize(files.size());
for (size_t i = 0; i < files.size(); ++i)
{
m_CachedFileData[i].Name = wxString( utf16tow(files[i].filename).c_str() );
m_CachedFileData[i].NameLower = m_CachedFileData[i].Name.Lower();
m_CachedFileData[i].Size = wxString::Format(_T("%d"), files[i].filesize);
while (commas.Replace(&m_CachedFileData[i].Size, _T("\\1,\\2"))) ;
if (files[i].modified.year == 0)
m_CachedFileData[i].Date = _("Unknown");
else
{
wxDateTime date (files[i].modified.day, (wxDateTime::Month)(wxDateTime::Jan + files[i].modified.month-1), files[i].modified.year,
files[i].modified.hour, files[i].modified.minute, files[i].modified.second, files[i].modified.msecond);
m_CachedFileData[i].Date = wxString::Format(
_T("%s %s.%03d"),
date.FormatISODate().c_str(),
date.FormatISOTime().c_str(),
date.GetMillisecond());
}
}
}
void ArchiveViewer::OpenFile(const wxString& filename)
{
wxFFileInputStream* fileStream = new wxFFileInputStream(filename);
if (! fileStream->Ok())
{
wxLogError(_("Failed to open file"));
delete fileStream;
return;
}
SeekableInputStream* stream = new SeekableInputStreamFromWx(fileStream);
BARReader* reader = new BARReader(*stream);
if (! reader->Initialise())
{
wxLogError(_("Failed to read BAR file"));
delete reader;
delete stream;
return;
}
// Delete old data, replace with new data
delete m_BARStream;
delete m_BARReader;
m_BARStream = stream;
m_BARReader = reader;
UpdateFileList();
RedrawFileList(false);
m_FileHistory.AddFileToHistory(filename);
SetCurrentFilename(filename);
}
void ArchiveViewer::OnExtractSelected(wxCommandEvent& WXUNUSED(event))
{
ExtractFiles(true);
}
void ArchiveViewer::OnExtractAll(wxCommandEvent& WXUNUSED(event))
{
ExtractFiles(false);
}
void ArchiveViewer::ExtractFiles(bool onlySelected)
{
long item = -1;
if (onlySelected)
{
// Find the first selected item, and make sure there is actually a selection
item = m_FileListCtrl->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (item == -1)
{
wxMessageBox(_("Please select one or more files to extract."), _("No files selected"), wxICON_INFORMATION);
return;
}
}
// Work out where to extract the files to:
// Assume same as last place, else default (from registry), else cwd
wxString dir = m_LastExtractDir;
if (! dir.Len())
{
dir = GetDefaultOpenDirectory();
if (! dir.Len())
dir = wxFileName::GetCwd();
}
// Let user choose final location
wxDirDialog dlg(this, wxDirSelectorPromptStr, dir);
if (dlg.ShowModal() != wxID_OK)
return;
// Remember the selection
dir = dlg.GetPath();
dir += wxFileName::GetPathSeparator();
m_LastExtractDir = dir;
wxFileName rootDir (dir);
// Construct a list of items to extract:
const std::vector<BAREntry>& files = m_BARReader->GetFileList();
std::vector<int> selection;
if (onlySelected)
{
while (item != -1)
{
selection.push_back(m_FileListCtrl->GetItemData(item)); // item was set at top of function
item = m_FileListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
}
}
else
{
// Extract all files
for (int i = 0; i < (int)files.size(); ++i)
selection.push_back(i);
}
bool aborted = false;
{
// Create the required directory structure:
// Extract the list of all directories:
std::set<std::wstring> dirs;
for (size_t sel = 0; sel < selection.size(); ++sel)
{
const BAREntry& file = files[selection[sel]];
wxString filename = wxString( utf16tow(file.filename).c_str() );
int lastSlash = filename.Find(_T('\\'), true);
if (lastSlash != -1)
dirs.insert(filename.Mid(0, lastSlash+1).wc_str());
}
// Construct the directory tree:
for (std::set<std::wstring>::iterator it = dirs.begin(); it != dirs.end(); ++it)
{
// Append name-in-archive to target root directory, one dir
// at a time, calling mkdir at each step if necessary
wxFileName fullFilePath (rootDir);
wxFileName filePath (it->c_str(), wxPATH_WIN);
const wxArrayString& filePathDirs = filePath.GetDirs();
for (size_t i = 0; i < filePathDirs.Count(); ++i)
{
fullFilePath.AppendDir(filePathDirs[i]);
if (! wxDirExists(fullFilePath.GetPath()))
wxMkdir(fullFilePath.GetPath());
}
}
// Create progress display
wxProgressDialog progress (_("Extracting files"), _("Please wait"), (int)selection.size(), this,
wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME | wxPD_REMAINING_TIME | wxPD_SMOOTH);
// Repeat for each selection file
for (size_t sel = 0; sel < selection.size(); ++sel)
{
const BAREntry& file = files[selection[sel]];
if (! progress.Update((int)sel, wxString::Format(_("Extracting %s"), file.filename.c_str())))
{
aborted = true;
break;
}
// Append name-in-archive to target root directory, one dir
// at a time, calling mkdir at each step if necessary
wxFileName filePath (wxString( utf16tow(file.filename).c_str() ), wxPATH_WIN);
filePath.MakeAbsolute(rootDir.GetPath());
// Output to disk
wxFFileOutputStream outStream(filePath.GetFullPath());
if (! outStream.Ok())
wxLogError(wxString::Format(_("Error opening output file %s"), filePath.GetFullPath().c_str()));
else
{
SeekableOutputStreamFromWx str (outStream);
m_BARReader->TransferFile(file, str);
outStream.Close();
// Set the file's timestamps to match the one specified in the archive
if (file.modified.year != 0)
{
wxDateTime date (file.modified.day, (wxDateTime::Month)(wxDateTime::Jan + file.modified.month-1), file.modified.year,
file.modified.hour, file.modified.minute, file.modified.second, file.modified.msecond);
filePath.SetTimes(NULL, &date, &date);
}
}
}
}
if (aborted)
wxMessageBox(_("Extraction aborted."), _("Stopped"));
else
wxMessageBox(_("Extraction complete."), _("Finished"));
}
void ArchiveViewer::OnEnablePreview(wxCommandEvent& event)
{
m_PreviewEnabled = event.IsChecked();
if (m_PreviewEnabled)
{
// Make sure the window's not far too small
if (GetSize().GetWidth() < 700)
SetSize(-1, -1, 900, -1); // nobody is still using 800x600, are they?
m_Splitter->SetDefaultSashPosition(600);
m_Splitter->SplitVertically(m_Splitter->GetWindow1(), m_PreviewWindow);
}
else
m_Splitter->Unsplit();
UpdatePreview();
}
void ArchiveViewer::UpdatePreview(long item)
{
if (! m_PreviewEnabled)
return;
// If the user opens a large archive file, enables the preview, selects the
// bottom file, and presses shift+home, it attempts to redraw the preview
// for every single file in sequence. That takes forever; so provide a way
// to abort the preview update.
if (wxGetKeyState(WXK_ESCAPE))
return;
// If none is specified, preview the first selected item
if (item == -1)
item = m_FileListCtrl->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (item == -1) // none selected
return;
const BAREntry& file = m_BARReader->GetFileList()[ m_FileListCtrl->GetItemData(item) ];
SeekableInputStream* str = m_BARReader->GetFile(file);
m_PreviewWindow->PreviewFile(wxString(utf16tow(file.filename).c_str()), *str);
delete str;
}
void ArchiveViewer::OnOpen(wxCommandEvent& WXUNUSED(event))
{
wxString path, name;
if (GetCurrentFilename().IsOk())
{
path = GetCurrentFilename().GetPath();
name = GetCurrentFilename().GetFullName();
}
else
{
path = GetDefaultOpenDirectory();
}
wxFileDialog dlg (this, _("Select archive file to open"), path, name, _("BAR files (*.bar)|*.bar|All files (*.*)|*.*"), wxOPEN);
if (dlg.ShowModal() != wxID_OK)
return;
OpenFile(dlg.GetPath());
}
void ArchiveViewer::OnMRUFile(wxCommandEvent& event)
{
wxString file (m_FileHistory.GetHistoryFile(event.GetId() - wxID_FILE1));
if (file.Len())
OpenFile(file);
}
void ArchiveViewer::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close();
}
void ArchiveViewer::SetCurrentFilename(wxFileName filename)
{
m_CurrentFilename = filename;
if (filename.IsOk())
SetTitle(m_WindowTitle + _T(" - ") + filename.GetFullName());
else
SetTitle(m_WindowTitle);
}
wxString ArchiveViewer::GetDefaultOpenDirectory()
{
// TODO
/*
wxRegKey key (_T("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft Games\\Age of Empires 3\\1.0"));
if (key.Exists())
{
wxString dir;
// The path might be the default value under the AppPath key, or it
// might be the AppPath value; so check both.
wxRegKey subkey (key, _T("AppPath"));
if (subkey.Exists())
{
if (subkey.QueryValue(_T(""), dir)) // default value
return dir;
}
else
{
if (key.HasValue(_T("AppPath")) && key.QueryValue(_T("AppPath"), dir))
return dir;
}
}
*/
return _T("");
}
void ArchiveViewer::SetFilter(const wxString& filter)
{
m_Filter = filter;
RedrawFileList(true);
}

View File

@ -1,92 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FileHistory/FileHistory.h"
#include "SnapSplitterWindow/SnapSplitterWindow.h"
#include "FilePreviewer.h"
#include "wx/filename.h"
#include "wx/listctrl.h"
#include <vector>
namespace DatafileIO
{
class BARReader;
struct BAREntry;
class SeekableInputStream;
}
class ArchiveViewer : public wxFrame
{
public:
ArchiveViewer(wxWindow* parent);
~ArchiveViewer();
void OnOpen(wxCommandEvent& event);
void OnMRUFile(wxCommandEvent& event);
void OnQuit(wxCommandEvent& event);
void OnExtractSelected(wxCommandEvent& event);
void OnExtractAll(wxCommandEvent& event);
void OnEnablePreview(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnClose(wxCloseEvent& event);
void SetFilter(const wxString& filter);
void UpdatePreview(long index = -1);
private:
void OpenFile(const wxString& filename);
void UpdateFileList(); // must be called after opening a new file
void RedrawFileList(bool keepSelection);
void ExtractFiles(bool onlySelected);
void SetCurrentFilename(wxFileName filename = wxString());
wxFileName GetCurrentFilename() { return m_CurrentFilename; }
wxString GetDefaultOpenDirectory();
wxFileName m_CurrentFilename;
wxString m_WindowTitle;
wxString m_Filter;
bool m_PreviewEnabled;
FilePreviewer* m_PreviewWindow;
SnapSplitterWindow* m_Splitter;
wxString m_LastExtractDir;
// wxStatusBar* m_StatusBar;
wxListCtrl* m_FileListCtrl;
DatafileIO::SeekableInputStream* m_BARStream;
DatafileIO::BARReader* m_BARReader;
struct FileData {
wxString NameLower; // for filtering
wxString Name;
wxString Size;
wxString Date;
};
std::vector<FileData> m_CachedFileData;
FileHistory m_FileHistory;
DECLARE_EVENT_TABLE();
};

View File

@ -1,259 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "FilePreviewer.h"
#include "DatafileIO/XMB/XMB.h"
#include "DatafileIO/DDT/DDT.h"
#include "wx/sound.h"
#include "wx/image.h"
using namespace DatafileIO;
class ImagePanel : public /*wxPanel*/wxScrolledWindow
{
public:
ImagePanel(wxWindow* parent, const wxImage& img)
: m_Bmp(img),
// wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(img.GetWidth(), img.GetHeight()))
wxScrolledWindow(parent)
{
SetScrollbars(1, 1, img.GetWidth(), img.GetHeight());
}
void OnPaint(wxPaintEvent& WXUNUSED(event))
{
wxPaintDC dc(this);
dc.Clear();
if (m_Bmp.Ok())
{
dc.DrawBitmap(m_Bmp, CalcScrolledPosition(wxPoint(0, 0)));
}
}
private:
wxBitmap m_Bmp;
DECLARE_EVENT_TABLE();
};
BEGIN_EVENT_TABLE(ImagePanel, /*wxPanel*/wxScrolledWindow)
EVT_PAINT(ImagePanel::OnPaint)
END_EVENT_TABLE()
//////////////////////////////////////////////////////////////////////////
FilePreviewer::FilePreviewer(wxWindow* parent)
: wxPanel(parent), m_ContentPanel(NULL)
{
m_MainSizer = new wxBoxSizer(wxVERTICAL);
SetSizer(m_MainSizer);
}
enum FileType
{
UNKNOWN,
XMB,
XML,
DDT,
WAV,
UNKNOWN_TEXT
};
void FilePreviewer::PreviewFile(const wxString& filename, SeekableInputStream& stream)
{
if (m_ContentPanel)
{
m_MainSizer->Detach(m_ContentPanel);
m_ContentPanel->Destroy();
}
Freeze();
m_ContentPanel = new wxPanel(this);
m_MainSizer->Add(m_ContentPanel, wxSizerFlags().Expand().Proportion(1));
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
wxStaticText* fileInfo = new wxStaticText(m_ContentPanel, wxID_ANY, wxString::Format(_("Filename: %s"), filename.c_str()));
sizer->Add(fileInfo, wxSizerFlags().Border(wxALL, 5));
m_ContentPanel->SetSizer(sizer);
FileType type = UNKNOWN;
wxString extn;
int dot = filename.Find(_T('.'), true);
if (dot != -1)
extn = filename.Mid(dot).Lower();
#define X(x) extn==_T(x)
if (X(".xmb"))
type = XMB;
else if (X(".xml") || X(".lgt") || X(".dtd") || X(".shp"))
type = XML;
else if (X(".ddt"))
type = DDT;
else if (X(".wav"))
type = WAV;
else if (X(".txt") || X(".xs") || X(".psh") || X(".vsh") || X(".hlsl") || X(".inc"))
type = UNKNOWN_TEXT;
#undef X
wxString extraFileInfo;
if (type == XMB)
{
DatafileIO::XMBFile* file = DatafileIO::XMBFile::LoadFromXMB(stream);
std::wstring text = file->SaveAsXML();
delete file;
wxString wtext (text.c_str(), text.length());
wtext = L"<!-- converted from XMB to XML -->\n" + wtext;
sizer->Add(new wxTextCtrl(m_ContentPanel, wxID_ANY, wtext, wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE | wxTE_READONLY | wxHSCROLL | wxTE_RICH), // use RICH so we can display big files
wxSizerFlags().Expand().Proportion(1).Border(wxALL, 5));
extraFileInfo = _("Format: XMB");
}
else if (type == XML || type == UNKNOWN_TEXT)
{
void* buf;
size_t bufSize;
if (! stream.AcquireBuffer(buf, bufSize))
{
wxFAIL_MSG(_T("Buffer acquisition failed"));
}
else
{
// Assume UTF8, and convert to wxString
wxString wtext ((char*)buf, wxConvUTF8, bufSize);
sizer->Add(new wxTextCtrl(m_ContentPanel, wxID_ANY, wtext, wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE | wxTE_READONLY | wxHSCROLL),
wxSizerFlags().Expand().Proportion(1).Border(wxALL, 5));
if (type == XML)
extraFileInfo = _("Format: XML");
else
extraFileInfo = _("Format: unidentified text");
}
}
else if (type == DDT)
{
DDTFile file(stream);
if (! file.Read(DDTFile::DDT))
{
wxLogError(_("Failed to read DDT file"));
}
else
{
wxArrayString formatStrings;
switch (file.m_Type_Usage) {
case DDTFile::BUMP: formatStrings.Add(_("normal map")); break;
case DDTFile::CUBE: formatStrings.Add(_("cube map")); break;
}
switch (file.m_Type_Alpha) {
case DDTFile::NONE: formatStrings.Add(_("no alpha")); break;
// case DDTFile::PLAYER: formatStrings.Add(_("player colour")); break;
// case DDTFile::TRANS: formatStrings.Add(_("transparency")); break;
case DDTFile::BLEND: formatStrings.Add(_("terrain blend")); break;
}
switch (file.m_Type_Format) {
case DDTFile::BGRA: formatStrings.Add(_("32-bit BGRA")); break;
case DDTFile::DXT1: formatStrings.Add(_("DXT1")); break;
case DDTFile::GREY: formatStrings.Add(_("8-bit grey")); break;
case DDTFile::DXT3: formatStrings.Add(_("DXT3")); break;
case DDTFile::NORMSPEC: formatStrings.Add(_("specular+normal")); break;
}
wxString formatString;
for (size_t i = 0; i < formatStrings.GetCount(); ++i)
formatString += (i ? _T(", ") : _T("")) + formatStrings[i];
if (! formatString.Len())
formatString = _("unknown");
extraFileInfo = wxString::Format(_("Format: DDT texture\nSubformat: %d %d %d (%s)"),
file.m_Type_Usage, file.m_Type_Alpha, file.m_Type_Format, formatString.c_str());
void* buffer;
int width, height;
if (! file.GetImageData(buffer, width, height, false))
{
extraFileInfo += _("\n(Unrecognised format - unable to display)");
}
else
{
sizer->Add(new ImagePanel(m_ContentPanel, wxImage(width, height, (unsigned char*)buffer)),
wxSizerFlags().Expand().Proportion(1).Border(wxALL, 5));
}
}
}
else if (type == WAV)
{
void* buf;
size_t bufSize;
if (! stream.AcquireBuffer(buf, bufSize))
{
wxFAIL_MSG(_T("Buffer acquisition failed"));
}
else
{
// HACK: If we destroy the sound object before it's finished playing,
// it deallocates the audio data and fails to play (or crashes).
// (That's assuming we fix wxSound to not just leak the memory.)
// So, just use a static object, and hope it stops playing before
// the program is exited.
// The wxSound-from memory constructor does not exist on OS X, so
// just show a warning there.
#ifdef __APPLE__
wxFAIL_MSG(_T("WAV playback not available on Mac OS X"));
#else
static wxSound snd;
snd.Stop();
// HACK, FIXME, XXX: I'd like to call the wx people idiots for
// having different API:s on different platforms, as well as for
// having public non-API methods.
#if __APPLE__
snd.~wxSound();
new (&snd) wxSound((int)bufSize, (const wxByte*)buf);
#else
snd.Create((int)bufSize, (const wxByte*)buf);
#endif
snd.Play();
#endif
stream.ReleaseBuffer(buf);
}
extraFileInfo = _("Format: WAV audio");
}
fileInfo->SetLabel(fileInfo->GetLabel() + _T("\n") + extraFileInfo);
m_MainSizer->Layout();
Thaw();
}

View File

@ -1,31 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "DatafileIO/Stream/Stream.h"
class FilePreviewer : public wxPanel
{
public:
FilePreviewer(wxWindow* parent);
// stream can be deleted by callers after this function returns
void PreviewFile(const wxString& filename, DatafileIO::SeekableInputStream& stream);
private:
wxPanel* m_ContentPanel; // gets deleted and rebuilt when previewing a new file
wxSizer* m_MainSizer;
};

View File

@ -1,367 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "FileConverter.h"
#include "Misc/Version.h"
#include "AtlasObject/AtlasObject.h"
#include "DatafileIO/XMB/XMB.h"
#include "DatafileIO/DDT/DDT.h"
#include "DatafileIO/Stream/wx.h"
#include "DatafileIO/Stream/Memory.h"
#include "wx/wfstream.h"
#include "wx/progdlg.h"
#include "wx/config.h"
#include "wx/regex.h"
using namespace DatafileIO;
//#define QUIET
enum FileType { XMB, XML, DDT, TGA };
const wxChar* xmlExtensions[] = {
_T("amt"), _T("blueprint"), _T("d3dconfig"), _T("dmg"), _T("effect"), _T("impacteffect"),
_T("lgt"), _T("multieffect"), _T("multips"), _T("multirs"),_T("multitechnique"),
_T("multitss"), _T("multivs"), _T("particle"), _T("physics"), _T("ps"), _T("rs"),
_T("tactics"), _T("technique"), _T("tss"), _T("vs"), _T("xml"),
NULL };
bool IsXMLExtension(const wxString& str)
{
const wxChar** e = xmlExtensions;
while (*e)
if (str == wxString(_T(".")) + *e++)
return true;
return false;
}
bool ConvertFiles(const wxArrayString& files, wxWindow* parent);
bool ConvertFile(const wxString& sourceFilename, FileType sourceType,
const wxString& targetFilename, FileType targetType,
XMLReader* io);
FileConverter::FileConverter(wxWindow* parent)
: wxFrame(parent, wxID_ANY, wxString::Format(_("%s - File Converter"), g_ProgramNameVersion.c_str()))
{
SetIcon(wxIcon(_T("ICON_FileConverter")));
m_Transient = true;
bool succeeded = false;
wxApp* app = wxTheApp;
if (app->argc > 1)
{
wxArrayString files;
for (int i = 1; i < app->argc; ++i)
files.Add(app->argv[i]);
succeeded = ConvertFiles(files, this);
}
else
{
wxConfigBase* cfg = wxConfigBase::Get(false);
wxString defaultDir;
if (cfg)
cfg->Read(_T("File Converter/OpenDir"), &defaultDir);
wxString extns = _("Recognised files");
extns += _T(" (*.xmb, *.ddt, *.xml, *.tga)|*.xmb;*.ddt;*.xml;*.tga");
// Add all the extra XML types
const wxChar** e = xmlExtensions;
while (*e)
{
extns += _T(";*.");
extns += *e++;
}
extns += wxString(_T("|")) + _("All files") + _T(" (*.*)|*.*");
wxFileDialog dlg (this, _("Select file(s) to convert"), defaultDir, _T(""),
extns, wxOPEN|/*wxFILE_MUST_EXIST|*/wxMULTIPLE); // for some reason, it complains that files don't exist when they actually do...
if (dlg.ShowModal() == wxID_OK)
{
wxArrayString files;
dlg.GetPaths(files);
succeeded = ConvertFiles(files, this);
if (cfg)
cfg->Write(_T("File Converter/OpenDir"), dlg.GetDirectory());
}
else
{
succeeded = false;
}
}
wxLog::FlushActive(); // ensure errors are displayed before the "finished" message
#ifndef QUIET
if (succeeded)
wxMessageBox(_("Conversion complete."), _("Finished"), wxOK|wxICON_INFORMATION);
#endif
Destroy();
}
bool FileConverter::Show(bool show)
{
if (m_Transient)
return true;
else
return wxFrame::Show(show);
}
bool ConvertFiles(const wxArrayString& files, wxWindow* parent)
{
XMLReader io; // TODO: don't create this unless necessary, because Xerces is slow
wxProgressDialog progress(_("Converting files"), _("Please wait"), (int)files.GetCount(), parent,
wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME | wxPD_REMAINING_TIME | wxPD_SMOOTH);
for (size_t i = 0; i < files.GetCount(); ++i)
{
wxString sourceFilename = files[i];
wxString targetFilename;
FileType sourceType, targetType;
if (! progress.Update((int)i, wxString::Format(_("Converting %s"), sourceFilename.c_str())))
return false;
wxString sourceExtn, sourceName;
{
int dot = sourceFilename.Find(_T('.'), true);
if (dot == -1)
{
wxLogError(_("No file extension for %s - don't know how to convert"), sourceFilename.c_str());
continue;
}
else
{
sourceExtn = sourceFilename.Mid(dot).Lower();
sourceName = sourceFilename.Mid(0, dot); // no extension
}
}
if (sourceExtn == _T(".xmb"))
{
sourceType = XMB;
targetType = XML;
// Ignore trailing .xmb
targetFilename = sourceName;
}
else if (sourceExtn == _T(".ddt"))
{
sourceType = DDT;
targetType = TGA; // TODO: allow BMP
targetFilename = sourceName + _T(".tga");
}
else if (sourceExtn == _T(".tga"))
{
sourceType = TGA; // TODO: allow BMP
targetType = DDT;
targetFilename = sourceName + _T(".ddt");
}
else if (IsXMLExtension(sourceExtn))
{
sourceType = XML;
targetType = XMB;
// Add a trailing .xmb (in addition to the normal .xml/etc)
targetFilename = sourceFilename + _T(".xmb");
}
else
{
wxLogError(_("Unknown file extension for %s - don't know how to convert"), sourceFilename.c_str());
continue;
}
#ifndef QUIET
// Warn about overwriting files
if (wxFile::Exists(targetFilename))
{
int ret = wxMessageBox(wxString::Format(_("Output file already exists: %s\nOverwrite file?"), targetFilename.c_str()), _("Overwrite?"), wxYES_NO|wxCANCEL);
if (ret == wxCANCEL) return false;
else if (ret == wxNO) continue;
else { /* carry on converting */ }
}
#endif
// Do the actual conversion
ConvertFile(sourceFilename, sourceType, targetFilename, targetType, &io);
}
return true;
}
bool ConvertFile(const wxString& sourceFilename, FileType sourceType,
const wxString& targetFilename, FileType targetType,
XMLReader* io)
{
// Open input file (in binary read mode)
wxFFileInputStream file (sourceFilename);
if (! file.Ok())
{
wxLogError(_("Failed to open input file %s"), sourceFilename.c_str());
return false;
}
// Decompress input file if necessary (for any file type)
//std::auto_ptr<InputStream> inStream (new Maybel33tInputStream(new SeekableInputStreamFromWx(file)));
Maybel33tInputStream inStream (new SeekableInputStreamFromWx(file));
if (! inStream.IsOk())
{
wxLogError(_("Failed to decompress input file %s"), sourceFilename.c_str());
return false;
}
// Handle XMB<->XML conversions
if (sourceType == XMB || sourceType == XML)
{
std::auto_ptr<XMBFile> data (NULL);
// Read data with the appropriate format
if (sourceType == XML)
{
// if (! io) io = new XMLReader(); // TODO - see earlier comment
data.reset(io->LoadFromXML(inStream));
data->format = XMBFile::AOE3; // TODO: let users control this?
}
else if (sourceType == XMB)
{
data.reset(XMBFile::LoadFromXMB(inStream));
}
// Write data with the appropriate format
if (targetType == XML)
{
std::wstring xml = data->SaveAsXML();
wxFFileOutputStream out(targetFilename, _T("w")); // open in text mode
if (! out.Ok())
{
wxLogError(_("Failed to open output file %s"), targetFilename.c_str());
return false;
}
// Output with UTF-8 encoding
xml = L"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + xml;
wxCharBuffer buf = wxString(xml.c_str()).mb_str(wxConvUTF8);
out.Write(buf.data(), strlen(buf.data()));
}
else if (targetType == XMB)
{
wxFFileOutputStream out (targetFilename, _T("wb"));
if (! out.Ok())
{
wxLogError(_("Failed to open output file %s"), targetFilename.c_str());
return false;
}
SeekableOutputStreamFromWx out2 (out);
data->SaveAsXMB(out2);
}
}
else if (sourceType == DDT)
{
DDTFile ddt(inStream);
if (! ddt.Read(DDTFile::DDT))
{
wxLogError(_("Failed to read DDT file %s"), sourceFilename.c_str());
return false;
}
// Stick some format-identifying data just before the extension
// part of the filename:
wxRegEx re (_T("(.*)\\."), wxRE_ADVANCED);
wxString newFilename = targetFilename;
re.ReplaceFirst(&newFilename,
wxString::Format(_T("\\1.(%d,%d,%d,%d)."),
ddt.m_Type_Usage, ddt.m_Type_Alpha, ddt.m_Type_Format, ddt.m_Type_Levels));
wxFFileOutputStream out(newFilename, _T("wb"));
if (! out.Ok())
{
wxLogError(_("Failed to open output file %s"), newFilename.c_str());
return false;
}
SeekableOutputStreamFromWx out2 (out);
ddt.SaveFile(out2, DDTFile::TGA);
}
else if (sourceType == TGA)
{
DDTFile ddt(inStream);
if (! ddt.Read(DDTFile::TGA))
{
wxLogError(_("Failed to read TGA file %s"), sourceFilename.c_str());
return false;
}
// Extract the format-identifying data from just before the extension
// part of the filename:
wxRegEx re (_T("\\.\\((\\d+),(\\d+),(\\d+),(\\d+)\\)\\."), wxRE_ADVANCED); // regexps in C++ are ugly :-(
wxString newFilename = targetFilename;
if (re.Matches(newFilename.c_str()))
{
wxASSERT(re.GetMatchCount() == 5);
long l0 = 0, l1 = 0, l2 = 0, l3 = 0;
if (re.GetMatch(newFilename, 1).ToLong(&l0)
&& re.GetMatch(newFilename, 2).ToLong(&l1)
&& re.GetMatch(newFilename, 3).ToLong(&l2)
&& re.GetMatch(newFilename, 4).ToLong(&l3))
{
ddt.m_Type_Usage = (DDTFile::Type_Usage)l0;
ddt.m_Type_Alpha = (DDTFile::Type_Alpha)l1;
ddt.m_Type_Format = (DDTFile::Type_Format)l2;
ddt.m_Type_Levels = l3;
}
else
{
// TODO: ask the user for settings? or at least be more helpful
wxLogError(_("Invalid filename - should be something.(n,n,n,n).tga"));
return false;
}
// Remove the format-identifying part when constructing the DDT filename
re.ReplaceFirst(&newFilename, _T("."));
}
else
{
wxLogError(_("Invalid filename - should be something.(n,n,n,n).tga"));
return false;
}
wxFFileOutputStream out(newFilename, _T("wb"));
if (! out.Ok())
{
wxLogError(_("Failed to open output file %s"), newFilename.c_str());
return false;
}
SeekableOutputStreamFromWx out2 (out);
ddt.SaveFile(out2, DDTFile::DDT);
}
else
{
wxFAIL_MSG(_T("TODO"));
return false;
}
return true;
}

View File

@ -1,26 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
class FileConverter : public wxFrame
{
public:
FileConverter(wxWindow* parent);
virtual bool Show(bool);
private:
bool m_Transient; // if true, the window won't be shown (since it's assumed to have been destroyed immediately)
};

View File

@ -24,8 +24,6 @@
#include "General/Datafile.h"
#include "ActorEditor/ActorEditor.h"
#include "ArchiveViewer/ArchiveViewer.h"
#include "FileConverter/FileConverter.h"
#include "ScenarioEditor/ScenarioEditor.h"
#include "ErrorReporter/ErrorReporter.h"
@ -203,15 +201,11 @@ public:
// Display the appropriate window
wxFrame* frame;
#define MAYBE(t) if (g_InitialWindowType == _T(#t)) frame = new t(NULL); else
MAYBE(ActorEditor)
#ifdef USE_AOE3ED
MAYBE(ArchiveViewer)
MAYBE(FileConverter)
#endif
#undef MAYBE
// else
if (g_InitialWindowType == _T("ScenarioEditor"))
if (g_InitialWindowType == _T("ActorEditor"))
{
frame = new ActorEditor(NULL);
}
else if (g_InitialWindowType == _T("ScenarioEditor"))
{
m_ScriptInterface = new ScriptInterface(&ScenarioEditorSubmitCommand);
frame = new ScenarioEditor(NULL, *m_ScriptInterface);

View File

@ -1,18 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
const wxString g_ProgramNameVersion = _("AoE3Ed v0.9");

View File

@ -1,142 +0,0 @@
/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "BAR.h"
#include "Util.h"
#include "Stream/Stream.h"
#include "Stream/Memory.h"
#include <cassert>
#include <cstdio>
#include <cstring>
using namespace DatafileIO;
BARReader::BARReader(SeekableInputStream& stream)
: m_Stream(stream)
{
}
#define CHECK(expr) if (!(expr)) { assert(!(expr)); return false; }
bool BARReader::Initialise()
{
assert(m_FileList.size() == 0); // Only call Init once
char head[4];
m_Stream.Read(head, 4);
CHECK(strncmp(head, "ESPN", 4) == 0);
uint32_t unknown;
m_Stream.Read(&unknown, 4);
CHECK(unknown == 2);
m_Stream.Read(&unknown, 4);
CHECK(unknown == 0x44332211);
for (int i = 0; i < 66; ++i)
{
m_Stream.Read(&unknown, 4);
CHECK(unknown == 0);
}
m_Stream.Read(&unknown, 4); // TODO: checksum?
uint32_t numFiles, filetableOffset;
m_Stream.Read(&numFiles, 4);
m_Stream.Read(&filetableOffset, 4);
m_Stream.Read(&unknown, 4);
// 0 in AoE3
// Non-zero (e.g. 466a800a, 8df1e438) in AoEO; purpose unknown
m_Stream.Seek(filetableOffset, Stream::FROM_START);
utf16string rootName = ReadUString(m_Stream);
uint32_t numRootFiles;
m_Stream.Read(&numRootFiles, 4);
CHECK(numRootFiles == numFiles);
m_FileList.reserve(numFiles);
for (uint32_t i = 0; i < numFiles; ++i)
{
BAREntry file;
uint32_t offset, length0, length1;
m_Stream.Read(&offset, 4);
m_Stream.Read(&length0, 4);
m_Stream.Read(&length1, 4);
CHECK(length0 == length1); // ??
file.offset = offset;
file.filesize = length0;
// Ranges: 1995-2005, 1-12, 0-5, 1-31, 0+10-23, 0-59, 0-59, 0-999
m_Stream.Read(&file.modified.year, 2);
m_Stream.Read(&file.modified.month, 2);
m_Stream.Read(&file.modified.dayofweek, 2);
m_Stream.Read(&file.modified.day, 2);
m_Stream.Read(&file.modified.hour, 2);
m_Stream.Read(&file.modified.minute, 2);
m_Stream.Read(&file.modified.second, 2);
m_Stream.Read(&file.modified.msecond, 2);
if (file.modified.year == 0xCCCC) // no date specified
memset(&file.modified, 0, sizeof(file.modified));
file.filename = rootName + ReadUString(m_Stream);
m_FileList.push_back(file);
}
// TODO: check this is really EOF
return true;
}
struct buffer_releaser
{
SeekableInputStream* stream;
};
SeekableInputStream* BARReader::GetFile(const BAREntry& file) const
{
void* buffer;
size_t size;
m_Stream.Seek((off_t)file.offset, Stream::FROM_START);
m_Stream.AcquireBuffer(buffer, size, file.filesize);
return new SeekableInputStream_mem((char*)buffer, size, new SeekableInputStream_mem::Releaser_StreamBuffer(&m_Stream));
}
void BARReader::TransferFile(const BAREntry& file, OutputStream& stream) const
{
m_Stream.Seek((off_t)file.offset, Stream::FROM_START);
const size_t bufSize = 128*1024; // people
static char* buffer[bufSize];
size_t bytesLeft = file.filesize;
while (bytesLeft)
{
size_t bytesRead = m_Stream.Read(buffer, std::min(bufSize, bytesLeft));
stream.Write(buffer, bytesRead);
bytesLeft -= bytesRead;
if (bytesRead == 0)
break;
}
}

View File

@ -1,67 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string>
#include <vector>
#include "../Util.h"
namespace DatafileIO
{
class SeekableInputStream;
class OutputStream;
struct BAREntry
{
utf16string filename; // includes root name - e.g. "Data\tactics\warwagon.tactics.xmb"
size_t filesize; // in bytes
struct {
unsigned short year, month, day, dayofweek; // 2005 etc, 1..12, 1..31, 0..6 (from Sunday)
unsigned short hour, minute, second, msecond; // 1..24, 0..59, 0..59, 0..999
// ...unless there's no date specified, in which case these will all be zero
} modified;
private: // implementation details
friend class BARReader;
size_t offset; // (assume all BARs are <4GB)
};
class BARReader
{
public:
BARReader(SeekableInputStream& stream);
// Read the header and file table.
bool Initialise();
// Get list of files.
const std::vector<BAREntry>& GetFileList() const { return m_FileList; }
// Get a seekable input stream for the specified file.
// Multiple file streams can be open at the same time.
SeekableInputStream* GetFile(const BAREntry& file) const;
// Copy a file's contents from the archive to an output stream
void TransferFile(const BAREntry& file, OutputStream& stream) const;
private:
SeekableInputStream& m_Stream;
std::vector<BAREntry> m_FileList;
BARReader& operator=(const BARReader&);
};
}

View File

@ -1,467 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "DDT.h"
#include "Stream/Stream.h"
#include "Util.h"
#include "IL/il.h"
#include "IL/ilu.h"
#include <cassert>
#include <string.h>
#include <stdlib.h>
using namespace DatafileIO;
DDTFile::DDTFile(SeekableInputStream& stream)
: m_Stream(stream)
{
// TODO: allow multiple nested DDTFiles, with ref-counted init
ilInit();
ilGenImages(1, &m_Image);
}
DDTFile::~DDTFile()
{
ilDeleteImages(1, &m_Image);
ilShutDown();
}
struct DDTImage
{
int width, height;
off_t offset;
size_t length;
};
#ifdef USE_DEVIL_DXT
static void LoadDXT(int dxtType, unsigned char* oldData);
static void SaveDXT(int dxtType); // saves the currently bound image
static void SwizzleAGBR();
#endif
#ifdef USE_HACKED_DEVIL
static void ToggleOrigin(); // urgh
#endif
bool DDTFile::Read(FileType type)
{
ilBindImage(m_Image);
if (type == DDT)
{
char head[4];
m_Stream.Read(head, 4);
if (strncmp(head, "RTS3", 4) != 0)
{
// TODO: report helpful error message
return false;
}
char format[3];
m_Stream.Read(format, 3);
m_Type_Usage = (Type_Usage)format[0];
m_Type_Alpha = (Type_Alpha)format[1];
m_Type_Format = (Type_Format)format[2];
char mipmapLevels;
m_Stream.Read(&mipmapLevels, 1);
m_Type_Levels = mipmapLevels;
uint32_t baseWidth, baseHeight;
m_Stream.Read(&baseWidth, 4);
m_Stream.Read(&baseHeight, 4);
int numImagesPerLevel = (m_Type_Usage == CUBE ? 6 : 1);
int numImages = mipmapLevels * numImagesPerLevel;
std::vector<DDTImage> Images;
Images.resize(numImages);
for (int i = 0; i < numImages; ++i)
{
int width = baseWidth >> (i/numImagesPerLevel); if (width < 1) width = 1;
int height = baseHeight >> (i/numImagesPerLevel); if (height < 1) height = 1;
uint32_t offset, length;
m_Stream.Read(&offset, 4);
m_Stream.Read(&length, 4);
Images[i].width = width;
Images[i].height = height;
Images[i].offset = offset;
Images[i].length = length;
}
// Read the first image. (TODO: cubemaps)
int w = Images[0].width;
int h = Images[0].height;
ilTexImage(w,h,1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL);
unsigned char* newData = (unsigned char*)ilGetData();
switch (m_Type_Format)
{
case BGRA:
{
unsigned char* oldData = new unsigned char[w*h*4];
m_Stream.Read(oldData, w*h*4);
for (int i = 0; i < w*h; ++i)
{
newData[i*4+0] = oldData[i*4+2];
newData[i*4+1] = oldData[i*4+1];
newData[i*4+2] = oldData[i*4+0];
newData[i*4+3] = oldData[i*4+3];
}
delete[] oldData;
}
break;
#ifdef USE_DEVIL_DXT
case DXT1:
case DXT3:
case NORMSPEC:
{
int dxtType = (m_Type_Format == DXT1 ? 1 : m_Type_Format == DXT3 ? 3 : 5);
int pixPerByte = (m_Type_Format == DXT1 ? 2 : 1);
unsigned char* oldData = new unsigned char[w*h/pixPerByte];
m_Stream.Read(oldData, w*h/pixPerByte);
LoadDXT(dxtType, oldData);
if (m_Type_Format == NORMSPEC)
SwizzleAGBR();
delete[] oldData;
}
break;
#endif
case GREY:
{
unsigned char* oldData = new unsigned char[w*h];
m_Stream.Read(oldData, w*h);
for (int i = 0; i < w*h; ++i)
{
newData[i*4+0] =
newData[i*4+1] =
newData[i*4+2] = oldData[i];
newData[i*4+3] = 255;
}
delete[] oldData;
}
break;
default:
//assert(! "Unhandled format");
ilClearColour(1.0f, 0.0f, 1.0f, 1.0f);
ilClearImage();
break;
}
#ifdef USE_HACKED_DEVIL
ToggleOrigin(); // use this instead of iluFlip because we don't want to change the actual data
#endif
}
else if (type == TGA)
{
void* buffer;
size_t size;
m_Stream.AcquireBuffer(buffer, size);
ilLoadL(IL_TGA, buffer, (ILuint)size);
m_Stream.ReleaseBuffer(buffer);
ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
iluFlipImage();
}
else
{
assert(! "Invalid type");
}
return true;
}
bool DDTFile::GetImageData(void*& buffer, int& width, int& height, bool realAlpha)
{
ilBindImage(m_Image);
width = ilGetInteger(IL_IMAGE_WIDTH);
height = ilGetInteger(IL_IMAGE_HEIGHT);
if (realAlpha)
{
buffer = malloc(width*height * 4);
memcpy(buffer, ilGetData(), width*height * 4);
}
else
{
buffer = malloc(width*height * 3 * 2);
unsigned char* newData = (unsigned char*)buffer;
unsigned char* oldData = (unsigned char*)ilGetData();
for (int i = 0; i < width*height; ++i)
{
newData[i*3+0] = oldData[i*4+0];
newData[i*3+1] = oldData[i*4+1];
newData[i*3+2] = oldData[i*4+2];
}
for (int i = 0; i < width*height; ++i)
{
newData[(i+width*height)*3+0] =
newData[(i+width*height)*3+1] =
newData[(i+width*height)*3+2] = oldData[i*4+3];
}
}
height *= 2;
return true;
}
//////////////////////////////////////////////////////////////////////////
// DevIL code: (slightly nasty, since DevIL doesn't seem to be flexible enough
// to do what I need it to do...)
struct ILOutputStream
{
static OutputStream* stream;
static ILHANDLE ILAPIENTRY Open(const ILstring)
{
return (void*)-1;
}
static void ILAPIENTRY Close(ILHANDLE)
{
}
static ILint ILAPIENTRY Putc(ILubyte c, ILHANDLE)
{
stream->Write(&c, 1);
return c;
}
static ILint ILAPIENTRY Seek(ILHANDLE, ILint /*offset*/, ILint /*whence*/)
{
assert(! "Not implemented");
return 0;
}
static ILint ILAPIENTRY Tell(ILHANDLE)
{
return stream->Tell();
}
static ILint ILAPIENTRY Write(const void* data, ILuint size, ILuint count, ILHANDLE)
{
if (size*count)
stream->Write(data, size*count);
return count;
}
};
OutputStream* ILOutputStream::stream = NULL;
extern "C" {
extern ILboolean ilSaveTargaF(ILHANDLE File);
// because DevIL doesn't want to write to things that aren't
// really files, so we have to use its internal writing functions
extern void iSetOutputFile(ILHANDLE File);
}
bool DDTFile::SaveFile(OutputStream& stream, FileType outputType)
{
ilBindImage(m_Image);
ilSetWrite(&ILOutputStream::Open, &ILOutputStream::Close, &ILOutputStream::Putc,
&ILOutputStream::Seek, &ILOutputStream::Tell, &ILOutputStream::Write);
iSetOutputFile(NULL); // make sure it's using the right output functions
ILOutputStream::stream = &stream;
if (outputType == TGA)
{
ilSaveTargaF(NULL);
}
else if (outputType == DDT)
{
int bpp;
switch (m_Type_Format)
{
case BGRA: bpp = 32; break;
case GREY: bpp = 8; break;
case DXT1: bpp = 4; break;
case DXT3: bpp = 8; break;
case NORMSPEC: bpp = 8; break;
default: assert(! "Invalid format"); return false;
}
stream.Write("RTS3", 4);
char format[4];
format[0] = (char)m_Type_Usage;
format[1] = (char)m_Type_Alpha;
format[2] = (char)m_Type_Format;
format[3] = (char)m_Type_Levels;
stream.Write(format, 4);
uint32_t baseWidth, baseHeight;
baseWidth = ilGetInteger(IL_IMAGE_WIDTH);
baseHeight = ilGetInteger(IL_IMAGE_HEIGHT);
stream.Write(&baseWidth, 4);
stream.Write(&baseHeight, 4);
int numImagesPerLevel = 1; // TODO: cubemaps
int numImages = m_Type_Levels * numImagesPerLevel;
uint32_t imgOffset = 16 + 8*numImages;
for (int i = 0; i < numImages; ++i)
{
int width = baseWidth >> (i/numImagesPerLevel); if (width < 1) width = 1;
int height = baseHeight >> (i/numImagesPerLevel); if (height < 1) height = 1;
uint32_t length = width*height * bpp / 8;
stream.Write(&imgOffset, 4);
stream.Write(&length, 4);
imgOffset += length;
}
for (int i = 0; i < numImages; ++i)
{
int width = baseWidth >> (i/numImagesPerLevel); if (width < 1) width = 1;
int height = baseHeight >> (i/numImagesPerLevel); if (height < 1) height = 1;
ilBindImage(m_Image);
ILuint img = ilCloneCurImage();
ilBindImage(img);
iluImageParameter(ILU_FILTER, ILU_SCALE_BOX); // TODO - proper mipmapping
iluScale(width, height, 1);
switch (m_Type_Format)
{
case BGRA:
{
unsigned char* newData = new unsigned char[width*height*4];
unsigned char* oldData = (unsigned char*)ilGetData();
for (int i = 0; i < width*height; ++i)
{
newData[i*4+0] = oldData[i*4+2];
newData[i*4+1] = oldData[i*4+1];
newData[i*4+2] = oldData[i*4+0];
newData[i*4+3] = oldData[i*4+3];
}
stream.Write(newData, width*height*4);
delete[] newData;
break;
}
case GREY:
{
unsigned char* newData = new unsigned char[width*height];
unsigned char* oldData = (unsigned char*)ilGetData();
for (int i = 0; i < width*height; ++i)
{
newData[i] = oldData[i*4+0];
}
stream.Write(newData, width*height);
delete[] newData;
break;
}
#ifdef USE_DEVIL_DXT
case DXT1:
SaveDXT(1);
break;
case DXT3:
SaveDXT(3);
break;
case NORMSPEC:
SwizzleAGBR();
SaveDXT(5);
break;
#endif
}
ilDeleteImages(1, &img);
}
}
ilResetWrite();
return true;
}
// Evilness:
#ifdef USE_HACKED_DEVIL
#include "IL/devil_internal_exports.h"
extern "C"
{
extern ILboolean DecompressDXT1();
extern ILboolean DecompressDXT3();
extern ILboolean DecompressDXT5();
extern ILuint Compress(ILimage* Image, ILenum DXTCFormat);
extern ILimage* iCurImage;
}
static void ToggleOrigin()
{
iCurImage->Origin = (iCurImage->Origin == IL_ORIGIN_UPPER_LEFT ? IL_ORIGIN_LOWER_LEFT : IL_ORIGIN_UPPER_LEFT);
}
#endif
#ifdef USE_DEVIL_DXT
extern "C"
{
extern ILubyte* CompData;
extern ILint Depth, Width, Height;
extern ILimage* Image;
}
static void LoadDXT(int dxtType, unsigned char* oldData)
{
// More evilness, that assumes a lot about DevIL's internals:
CompData = (ILubyte*)oldData;
Image = iCurImage;
Width = Image->Width;
Height = Image->Height;
Depth = Image->Depth;
switch (dxtType)
{
case 1: DecompressDXT1(); break;
case 3: DecompressDXT3(); break;
case 5: DecompressDXT5(); break;
default: assert(0);
}
CompData = NULL;
Image = NULL;
}
static void SwizzleAGBR()
{
ILubyte* data = ilGetData();
ILint pixels = ilGetInteger(IL_IMAGE_WIDTH)*ilGetInteger(IL_IMAGE_HEIGHT);
for (ILint i = 0; i < pixels; ++i)
{
ILubyte t = data[i*4+0];
data[i*4+0] = data[i*4+3];
data[i*4+3] = t;
}
}
static void SaveDXT(int dxtType)
{
Compress(ilGetCurImage(), dxtType==1 ? IL_DXT1 : dxtType==3 ? IL_DXT3 : IL_DXT5);
}
#endif

View File

@ -1,91 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include <vector>
typedef unsigned int ILuint;
namespace DatafileIO
{
class SeekableInputStream;
class OutputStream;
class DDTFile
{
public:
enum FileType { TGA, BMP, DDT };
// Initialises the file, but doesn't actually read anything
DDTFile(SeekableInputStream& stream);
~DDTFile();
// Attempts to read the file, and returns true on success
bool Read(FileType type);
bool SaveFile(OutputStream& stream, FileType outputType);
// All arguments are outputs. buffer is allocated by malloc, and
// must be freed by the caller. If realAlpha is true, the buffer
// will be RGBA, else it'll be RGB (with height doubled and the alpha
// stuck on the bottom)
bool GetImageData(void*& buffer, int& width, int& height, bool realAlpha);
enum Type_Usage {
UNK0 = 0, // ??
UNK1 = 1, // ??
BUMP = 6,
UNK2 = 7, // ??
CUBE = 8
};
enum Type_Alpha {
NONE = 0, // ??
PLAYER = 1, // ?? }
TRANS = 4, // ?? } these names are completely incorrect
BLEND = 8, // mostly unused
};
enum Type_Format {
BGRA = 1,
DXT1 = 4,
GREY = 7,
DXT3 = 8,
NORMSPEC = 9 // DXT5, with spec in R channel, XYZ in AGB channels.
// (See e.g. http://www.ati.com/developer/NormalMapCompression.pdf)
};
// (These values are not guaranteed to actually be in the enums)
Type_Usage m_Type_Usage;
Type_Alpha m_Type_Alpha;
Type_Format m_Type_Format;
int m_Type_Levels; // of mipmaps
// struct Image
// {
// int width, height;
// off_t offset;
// size_t length;
// };
// std::vector<Image> m_Images;
ILuint m_Image;
private:
SeekableInputStream& m_Stream;
DDTFile& operator=(const DDTFile&);
};
}

View File

@ -1,148 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "Memory.h"
#include "../Util.h"
#include "zlib.h"
#include <algorithm>
#include <cassert>
#include <memory.h>
using namespace DatafileIO;
SeekableInputStream_mem::SeekableInputStream_mem(char* data, size_t size, Releaser* releaser)
: m_Data(data), m_Size(size), m_Cursor(0), m_Releaser(releaser)
{
}
SeekableInputStream_mem::~SeekableInputStream_mem()
{
m_Releaser->release(m_Data);
delete m_Releaser;
}
off_t SeekableInputStream_mem::Tell() const
{
return m_Cursor;
}
bool SeekableInputStream_mem::IsOk() const
{
return true;
}
void SeekableInputStream_mem::Seek(off_t pos, Stream::whence mode)
{
if (mode == FROM_START)
m_Cursor = pos;
else if (mode == FROM_CURRENT)
m_Cursor += pos;
else if (mode == FROM_END)
m_Cursor = (off_t)m_Size - pos;
}
size_t SeekableInputStream_mem::Read(void* buffer, size_t size)
{
if (m_Cursor >= (off_t)m_Size)
return 0;
size_t amount = size;
if (m_Cursor + amount > m_Size)
amount = m_Size - m_Cursor;
std::copy(m_Data+m_Cursor, m_Data+m_Cursor+amount, (char*)buffer);
m_Cursor += (off_t)amount;
return amount;
}
bool SeekableInputStream_mem::AcquireBuffer(void*& buffer, size_t& size, size_t max_size)
{
buffer = m_Data + m_Cursor;
size = m_Size - m_Cursor;
if (size > max_size) size = max_size;
return true;
}
void SeekableInputStream_mem::ReleaseBuffer(void* /*buffer*/)
{
/* do nothing */
}
//////////////////////////////////////////////////////////////////////////
Maybel33tInputStream::Maybel33tInputStream(SeekableInputStream* stream)
: m_Stream(NULL)
{
char head[8];
size_t bytes = stream->Read(head, 8);
if (bytes == 8 && strncmp(head, "l33t", 4) == 0)
{
uint32_t uncompressedSize;
memcpy(&uncompressedSize, &head[4], 4);
void* buffer;
size_t size;
if (! stream->AcquireBuffer(buffer, size))
{
assert(!"Buffer acquisition unsuccessful");
}
else
{
char* uncompressedBuffer = new char[uncompressedSize];
uLongf newUncomprSize = (uLongf)uncompressedSize;
int err = uncompress((Bytef*)uncompressedBuffer, &newUncomprSize, (Bytef*)buffer, (uLong)size);
if (err != Z_OK)
{
assert(!"Decompression failed");
delete[] uncompressedBuffer;
}
else
{
assert(newUncomprSize == uncompressedSize);
m_Stream = new SeekableInputStream_mem(uncompressedBuffer, uncompressedSize, new SeekableInputStream_mem::Releaser_NewArray);
}
stream->ReleaseBuffer(buffer);
}
delete stream;
}
else
{
stream->Seek(-(off_t)bytes, FROM_CURRENT);
m_Stream = stream;
}
}
Maybel33tInputStream::~Maybel33tInputStream()
{
delete m_Stream;
}
bool Maybel33tInputStream::IsOk() const
{
return (m_Stream != NULL);
}
off_t Maybel33tInputStream::Tell() const { return m_Stream->Tell(); }
void Maybel33tInputStream::Seek(off_t pos, Stream::whence mode) { m_Stream->Seek(pos, mode); }
size_t Maybel33tInputStream::Read(void* buffer, size_t size) { return m_Stream->Read(buffer, size); }
bool Maybel33tInputStream::AcquireBuffer(void*& buffer, size_t& size, size_t max_size) { return m_Stream->AcquireBuffer(buffer, size, max_size); }
void Maybel33tInputStream::ReleaseBuffer(void* buffer) { m_Stream->ReleaseBuffer(buffer); }

View File

@ -1,81 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Stream.h"
namespace DatafileIO
{
class SeekableInputStream_mem : public SeekableInputStream
{
public:
// 'Release' provides common buffer-release mechanisms, called
// when this stream is destroyed
struct Releaser {
virtual ~Releaser() {}
virtual void release(char* buffer) = 0;
};
struct Releaser_None : public Releaser {
virtual void release(char* /*buffer*/) {};
};
struct Releaser_StreamBuffer : public Releaser {
Releaser_StreamBuffer(InputStream* s) : stream(s) {}
InputStream* stream;
virtual void release(char* buffer) {
stream->ReleaseBuffer(buffer);
}
};
struct Releaser_NewArray : public Releaser {
virtual void release(char* buffer) {
delete[] buffer;
}
};
SeekableInputStream_mem(char* data, size_t size, Releaser* releaser);
~SeekableInputStream_mem();
virtual off_t Tell() const;
virtual bool IsOk() const;
virtual void Seek(off_t pos, Stream::whence mode);
virtual size_t Read(void* buffer, size_t size);
virtual bool AcquireBuffer(void*& buffer, size_t& size, size_t max_size);
virtual void ReleaseBuffer(void* buffer);
private:
Releaser* m_Releaser;
char* m_Data;
size_t m_Size;
off_t m_Cursor;
};
// Magically decompresses l33t-compressed files.
class Maybel33tInputStream : public SeekableInputStream
{
public:
// Take ownership of a SeekableInputStream
Maybel33tInputStream(SeekableInputStream* stream);
~Maybel33tInputStream();
virtual off_t Tell() const;
virtual bool IsOk() const;
virtual void Seek(off_t pos, Stream::whence mode);
virtual size_t Read(void* buffer, size_t size);
virtual bool AcquireBuffer(void*& buffer, size_t& size, size_t max_size);
virtual void ReleaseBuffer(void* buffer);
private:
SeekableInputStream* m_Stream;
};
}

View File

@ -1,52 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "Stream.h"
#include <cassert>
#include <string>
#include <memory.h>
using namespace DatafileIO;
bool InputStream::AcquireBuffer(void*& buffer, size_t& size, size_t max_size)
{
std::string data;
const size_t tempBufSize = 65536;
static char tempBuffer[tempBufSize];
size = 0;
size_t bytesLeft = max_size;
size_t bytesRead;
while (bytesLeft > 0 && (bytesRead = Read(tempBuffer, std::min(bytesLeft, tempBufSize))) != 0)
{
size += bytesRead;
bytesLeft -= bytesRead;
data += std::string(tempBuffer, bytesRead);
}
buffer = new char[size];
memcpy(buffer, data.data(), size);
return true;
}
void InputStream::ReleaseBuffer(void* buffer)
{
delete[] (char*)buffer;
}

View File

@ -1,90 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_STREAM
#define INCLUDED_STREAM
/*
Stream: A system for input/output of data, particularly with chained streams
(e.g. file -> zlib decompressor -> data processor).
Similar to wxWidget's streams, but rewritten so that code can use this without
requiring wx.
TODO: This concept might not actually be any good; consider alternatives.
*/
#include <sys/types.h>
#include <limits>
namespace DatafileIO
{
class Stream
{
public:
enum whence { FROM_START, FROM_END, FROM_CURRENT };
virtual ~Stream() {}
virtual off_t Tell() const = 0;
virtual bool IsOk() const = 0;
};
class SeekableStream
{
public:
virtual ~SeekableStream() {}
virtual void Seek(off_t pos, Stream::whence mode) = 0;
};
class InputStream : public Stream
{
public:
// Try to read up to 'size' bytes into buffer, and return the amount
// actually read.
virtual size_t Read(void* buffer, size_t size) = 0;
// Sets 'buffer' and 'size' to point to the data from the current cursor
// position up to max_size bytes (or the end of the file, whichever is
// reached first) and returns true if successful.
// If a derived stream doesn't implement these, a default (which just
// calls Read to get all the data) will be used instead. (It is implemented
// in e.g. streams that already have a pointer to all the data, so they
// don't need to do any memory copying.)
virtual bool AcquireBuffer(void*& buffer, size_t& size, size_t max_size = std::numeric_limits<size_t>::max());
virtual void ReleaseBuffer(void* buffer);
};
class OutputStream : public Stream
{
public:
virtual void Write(const void* buffer, size_t size) = 0;
};
// Specialisations to indicate that a stream allows seeking.
class SeekableInputStream : public InputStream, public SeekableStream
{
};
class SeekableOutputStream : public OutputStream, public SeekableStream
{
};
}
#endif // INCLUDED_STREAM

View File

@ -1,115 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Stream.h"
#include "wx/mstream.h"
#include "wx/zstream.h"
namespace DatafileIO
{
// Wrappers around wx streams, so they can be used as [non-wx] Streams.
// (This code is all inline so that the project can be compiled without
// requiring wxWidgets.)
class SeekableInputStreamFromWx : public SeekableInputStream
{
public:
// Take ownership of a wxInputStream
SeekableInputStreamFromWx(wxInputStream* stream)
: m_Stream(stream), m_Owner(true) {}
// Use an externally-owned wxInputStream
SeekableInputStreamFromWx(wxInputStream& stream)
: m_Stream(&stream), m_Owner(false) {}
~SeekableInputStreamFromWx()
{
if (m_Owner)
delete m_Stream;
}
virtual off_t Tell() const { return m_Stream->TellI(); }
virtual bool IsOk() const { return m_Stream->IsOk(); }
virtual void Seek(off_t pos, Stream::whence mode)
{
m_Stream->SeekI(pos,
mode==Stream::FROM_START ? wxFromStart
: mode==Stream::FROM_END ? wxFromEnd
: /*mode==Stream::FROM_CURRENT*/ wxFromCurrent);
}
virtual size_t Read(void* buffer, size_t size)
{
m_Stream->Read(buffer, size);
return m_Stream->LastRead();
}
private:
wxInputStream* m_Stream;
bool m_Owner;
};
class SeekableOutputStreamFromWx : public SeekableOutputStream
{
public:
// Take ownership of a wxInputStream
SeekableOutputStreamFromWx(wxOutputStream* stream)
: m_Stream(stream), m_Owner(true) {}
// Use an externally-owned wxInputStream
SeekableOutputStreamFromWx(wxOutputStream& stream)
: m_Stream(&stream), m_Owner(false) {}
~SeekableOutputStreamFromWx()
{
if (m_Owner)
delete m_Stream;
}
virtual off_t Tell() const
{
return m_Stream->TellO();
}
virtual bool IsOk() const
{
return m_Stream->IsOk();
}
virtual void Seek(off_t pos, Stream::whence mode)
{
m_Stream->SeekO(pos,
mode==Stream::FROM_START ? wxFromStart
: mode==Stream::FROM_END ? wxFromEnd
: /*mode==Stream::FROM_CURRENT*/ wxFromCurrent);
}
virtual void Write(const void* buffer, size_t size)
{
m_Stream->Write(buffer, size);
}
private:
wxOutputStream* m_Stream;
bool m_Owner;
};
}

View File

@ -1,57 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "Util.h"
#include "Stream/Stream.h"
using namespace DatafileIO;
utf16string DatafileIO::ReadUString(InputStream& stream)
{
uint32_t length;
stream.Read(&length, 4);
utf16string ret;
ret.resize(length);
stream.Read(&ret[0], length*2);
return ret;
}
void DatafileIO::WriteUString(OutputStream& stream, const utf16string& string)
{
uint32_t length = (uint32_t)string.length();
stream.Write(&length, 4);
stream.Write((utf16_t*)&string[0], length*2);
}
#ifndef _WIN32
// TODO In reality, these two should be able to de/encode UTF-16 to/from UCS-4
// instead of just treating UTF-16 as UCS-2
std::wstring DatafileIO::utf16tow(const utf16string &str)
{
return std::wstring(str.begin(), str.end());
}
utf16string DatafileIO::wtoutf16(const std::wstring &str)
{
return utf16string(str.begin(), str.end());
}
#endif

View File

@ -1,64 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_UTIL
#define INCLUDED_UTIL
#include <string>
#include <cassert>
#include <stdint.h>
#ifndef C_ASSERT
#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
#endif
namespace DatafileIO
{
#ifdef _WIN32
// TODO: proper portability
typedef int int32_t;
typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef std::wstring utf16string;
typedef wchar_t utf16_t;
#else
typedef uint16_t utf16_t;
typedef std::basic_string<utf16_t> utf16string;
#endif
C_ASSERT(sizeof(int32_t) == 4);
C_ASSERT(sizeof(uint32_t) == 4);
C_ASSERT(sizeof(uint16_t) == 2);
C_ASSERT(sizeof(utf16_t) == 2);
class InputStream;
class OutputStream;
// Read/write 4-byte length + UCS-2 string
utf16string ReadUString(InputStream& stream);
void WriteUString(OutputStream& stream, const utf16string& string);
#ifdef _WIN32
# define utf16tow(_str) _str
# define wtoutf16(_str) _str
#else
std::wstring utf16tow(const utf16string &str);
utf16string wtoutf16(const std::wstring &str);
#endif
}
#endif // INCLUDED_UTIL

View File

@ -1,672 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "XMB.h"
#include "Stream/Stream.h"
#include <cassert>
#include <set>
#include <map>
#include <stack>
#ifdef _MSC_VER // shut up about Xerces headers
# pragma warning(disable: 4127) // conditional expression is constant
# pragma warning(disable: 4671) // the copy constructor is inaccessible
# pragma warning(disable: 4673) // throwing 'x' the following types will not be considered at the catch site
# pragma warning(disable: 4244) // 'return' : conversion from '__w64 int' to 'unsigned long', possible loss of data
# pragma warning(disable: 4267) // 'argument' : conversion from 'size_t' to 'const unsigned int', possible loss of data
#endif
#include <xercesc/sax/ErrorHandler.hpp>
#include <xercesc/sax/InputSource.hpp>
#include <xercesc/sax/Locator.hpp>
#include <xercesc/sax/SAXParseException.hpp>
#include <xercesc/sax2/Attributes.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include <xercesc/sax2/DefaultHandler.hpp>
#include <xercesc/util/BinInputStream.hpp>
#include <xercesc/util/XMLString.hpp>
XERCES_CPP_NAMESPACE_USE
using namespace DatafileIO;
//////////////////////////////////////////////////////////////////////////
// XMBFile functions:
static void DeallocateElement(XMLElement* el)
{
size_t i;
for (i = 0; i < el->childs.size(); ++i)
DeallocateElement(el->childs[i]);
delete el;
}
XMBFile::XMBFile()
: root(NULL)
{
}
XMBFile::~XMBFile()
{
DeallocateElement(root);
}
// XMLReader init/shutdown:
DatafileIO::XMLReader::XMLReader()
{
XMLPlatformUtils::Initialize();
}
DatafileIO::XMLReader::~XMLReader()
{
XMLPlatformUtils::Terminate();
}
//////////////////////////////////////////////////////////////////////////
// Input utility functions:
#define READ(type, name) type name; stream.Read(&name, sizeof(type))
#define READARRAY(type, n, name) type name[n]; stream.Read(&name, sizeof(type)*n)
#define CHECK(expr, ret) if (!(expr)) { assert(!(expr)); return (ret); }
static void StringReplace(std::wstring& s, const std::wstring& pattern, const std::wstring& replacement)
{
size_t pos = 0;
while (pos != s.npos)
{
pos = s.find(pattern, pos);
if (pos != s.npos)
{
s.replace(pos, pattern.length(), replacement);
pos += replacement.length();
}
}
}
//////////////////////////////////////////////////////////////////////////
// XMB reading:
static XMLElement* ParseNode(InputStream& stream, XMBFile* file, const std::vector<utf16string>& ElementNames, const std::vector<utf16string>& AttributeNames)
{
READARRAY(char, 2, Head); CHECK(strncmp(Head, "XN", 2) == 0, NULL);
READ(int32_t, Length);
XMLElement* node = new XMLElement;
node->text = ReadUString(stream);
READ(int32_t, Name);
node->name = ElementNames[Name];
if (file->format == XMBFile::AOE3)
{
READ(int32_t, LineNumber);
node->linenum = LineNumber;
}
READ(int32_t, NumAttributes);
node->attrs.reserve(NumAttributes);
for (int32_t i = 0; i < NumAttributes; ++i)
{
READ(int32_t, AttrID);
XMLAttribute attr;
attr.name = AttributeNames[AttrID];
attr.value = ReadUString(stream);
node->attrs.push_back(attr);
}
READ(int32_t, NumChildren);
node->childs.reserve(NumChildren);
for (int32_t i = 0; i < NumChildren; ++i)
{
XMLElement* child = ParseNode(stream, file, ElementNames, AttributeNames);
if (! child)
{
DeallocateElement(node);
return NULL;
}
node->childs.push_back(child);
}
return node;
}
static bool ParseXMB(InputStream& stream, XMBFile* file)
{
READARRAY(char, 2, Header); CHECK(strncmp(Header, "X1", 2) == 0, false);
READ(int32_t, DataLength);
READARRAY(char, 2, RootHeader); CHECK(strncmp(RootHeader, "XR", 2) == 0, false);
READARRAY(int32_t, 2, Unknown);
CHECK(Unknown[0] == 4, false);
if (Unknown[1] == 7)
file->format = XMBFile::AOM;
else if (Unknown[1] == 8)
file->format = XMBFile::AOE3;
else
{
// wxLogWarning(_("Unrecognised XMB format - assuming AoE3"));
assert(! "Unrecognised format");
file->format = XMBFile::AOE3;
}
std::vector<utf16string> ElementNames;
READ(int, NumElements);
ElementNames.reserve(NumElements);
for (int i = 0; i < NumElements; ++i)
ElementNames.push_back(ReadUString(stream));
std::vector<utf16string> AttributeNames;
READ(int, NumAttributes);
AttributeNames.reserve(NumAttributes);
for (int i = 0; i < NumAttributes; ++i)
AttributeNames.push_back(ReadUString(stream));
XMLElement* root = ParseNode(stream, file, ElementNames, AttributeNames);
if (! root)
return false;
file->root = root;
return true;
}
XMBFile* XMBFile::LoadFromXMB(InputStream& stream)
{
XMBFile* file = new XMBFile();
if (! ParseXMB(stream, file))
{
delete file;
return NULL;
}
return file;
}
//////////////////////////////////////////////////////////////////////////
// XMB writing:
typedef std::map<utf16string, uint32_t> StringTable;
static void ExtractStrings(XMLElement* node, StringTable& elements, StringTable& attributes)
{
if (elements.find(node->name) == elements.end())
elements.insert(std::make_pair(node->name, (uint32_t)elements.size()));
for (size_t i = 0; i < node->attrs.size(); ++i)
if (attributes.find(node->attrs[i].name) == attributes.end())
attributes.insert(std::make_pair(node->attrs[i].name, (uint32_t)attributes.size()));
for (size_t i = 0; i < node->childs.size(); ++i)
ExtractStrings(node->childs[i], elements, attributes);
}
static void WriteNode(SeekableOutputStream& stream, XMBFile* file, XMLElement* node, const StringTable& elements, const StringTable& attributes)
{
stream.Write("XN", 2);
off_t Length_off = stream.Tell();
stream.Write("????", 4);
WriteUString(stream, node->text);
uint32_t Name = elements.find(node->name)->second;
stream.Write(&Name, 4);
if (file->format == XMBFile::AOE3)
{
int32_t lineNum = node->linenum;
stream.Write(&lineNum, 4);
}
uint32_t NumAttributes = (uint32_t)node->attrs.size();
stream.Write(&NumAttributes, 4);
for (uint32_t i = 0; i < NumAttributes; ++i)
{
uint32_t n = attributes.find(node->attrs[i].name)->second;
stream.Write(&n, 4);
WriteUString(stream, node->attrs[i].value);
}
uint32_t NumChildren = (uint32_t)node->childs.size();
stream.Write(&NumChildren, 4);
for (uint32_t i = 0; i < NumChildren; ++i)
WriteNode(stream, file, node->childs[i], elements, attributes);
off_t NodeEnd = stream.Tell();
stream.Seek(Length_off, Stream::FROM_START);
int Length = NodeEnd - (Length_off+4);
stream.Write(&Length, 4);
stream.Seek(NodeEnd, Stream::FROM_START);
}
void XMBFile::SaveAsXMB(SeekableOutputStream& stream)
{
stream.Write("X1", 2);
off_t Length_off = stream.Tell();
stream.Write("????", 4);
stream.Write("XR", 2);
int version[2] = { 4, -1 };
if (format == XMBFile::AOM)
version[1] = 7;
else if (format == XMBFile::AOE3)
version[1] = 8;
else
{
// wxLogWarning(_("Unknown XMB format - assuming AoE3"));
format = XMBFile::AOE3;
version[1] = 8;
}
stream.Write(version, 8);
// Get the list of element/attribute names, sorted by first appearance
StringTable ElementNames;
StringTable AttributeNames;
ExtractStrings(root, ElementNames, AttributeNames);
// Convert into handy vector format for outputting
std::vector<utf16string> ElementNamesByID;
ElementNamesByID.resize(ElementNames.size());
for (StringTable::iterator it = ElementNames.begin(); it != ElementNames.end(); ++it)
ElementNamesByID[it->second] = it->first;
// Output element names
uint32_t NumElements = (uint32_t)ElementNamesByID.size();
stream.Write(&NumElements, 4);
for (uint32_t i = 0; i < NumElements; ++i)
WriteUString(stream, ElementNamesByID[i]);
// Convert into handy vector format for outputting
std::vector<utf16string> AttributeNamesByID;
AttributeNamesByID.resize(AttributeNames.size());
for (StringTable::iterator it = AttributeNames.begin(); it != AttributeNames.end(); ++it)
AttributeNamesByID[it->second] = it->first;
// Output attribute names
uint32_t NumAttributes = (uint32_t)AttributeNamesByID.size();
stream.Write(&NumAttributes, 4);
for (uint32_t i = 0; i < NumAttributes; ++i)
WriteUString(stream, AttributeNamesByID[i]);
// Output root node, plus all descendants
WriteNode(stream, this, root, ElementNames, AttributeNames);
// Fill in data-length field near the beginning
off_t DataEnd = stream.Tell();
stream.Seek(Length_off, Stream::FROM_START);
int Length = DataEnd - (Length_off+4);
stream.Write(&Length, 4);
stream.Seek(DataEnd, Stream::FROM_START);
}
//////////////////////////////////////////////////////////////////////////
// XML writing:
const wchar_t* in = L"\t";
void OutputNode(std::wstring& output, const XMLElement* node, const std::wstring& indent)
{
// Build up strings using lots of += instead of +, because it gives
// a significant (>30%) performance increase.
output += L"\n";
output += indent;
output += L"<";
output += utf16tow(node->name);
for (size_t i = 0; i < node->attrs.size(); ++i)
{
std::wstring value = utf16tow(node->attrs[i].value);
// Escape funny characters
if (value.find_first_of(L"&<>\"") != value.npos)
{
StringReplace(value, L"&", L"&amp;");
StringReplace(value, L"<", L"&lt;");
StringReplace(value, L">", L"&gt;");
StringReplace(value, L"\"", L"&quot;");
}
output += L" ";
output += utf16tow(node->attrs[i].name);
output += L"=\"";
output += value;
output += L"\"";
}
// Output the element's contents, in an attemptedly nice readable format:
std::wstring name = utf16tow(node->name);
if (node->text.length())
{
std::wstring text = utf16tow(node->text);
// Wrap text in CDATA when necessary. (Maybe we should use &lt; etc
// in some cases?)
if (text.find_first_of(L"<>&") != text.npos)
{
// (According to the XML spec, ">" is allowed in non-CDATA non-escaped
// content, but we avoid that because it's confusing.)
StringReplace(text, L"]]>", L"]]>]]&gt;<![CDATA["); // paranoia
std::wstring newtext = L"<![CDATA[\n";
newtext += indent;
newtext += in;
newtext += text;
newtext += L"\n"; // (All this extra whitespace will be trimmed during XML->XMB)
newtext += indent;
newtext += L"]]>";
std::swap(newtext, text);
}
if (node->childs.size())
{
/* <el>
Text
<child>...
</el> */
output += L">\n";
output += indent;
output += in;
output += text;
std::wstring nextIndent = indent + in;
for (size_t i = 0; i < node->childs.size(); ++i)
OutputNode(output, node->childs[i], nextIndent);
output += L"\n";
output += indent;
output += L"</";
output += name;
output += L">";
}
else
{
/* <el>Text</el> */
output += L">";
output += text;
output += L"</";
output += name;
output += L">";
}
}
else
{
if (node->childs.size())
{
/* <el>
<child>...
</el> */
output += L">";
std::wstring nextIndent = indent + in;
for (size_t i = 0; i < node->childs.size(); ++i)
OutputNode(output, node->childs[i], nextIndent);
output += L"\n";
output += indent;
output += L"</";
output += name;
output += L">";
}
else
{
/* <el/> */
output += L"/>";
}
}
}
std::wstring XMBFile::SaveAsXML()
{
std::wstring output;
OutputNode(output, root, L"");
return output;
}
//////////////////////////////////////////////////////////////////////////
// XML reading:
class XeroHandler : public DefaultHandler
{
public:
XeroHandler() : Root(NULL), m_locator(NULL) {}
~XeroHandler() { if (Root) DeallocateElement(Root); }
// SAX2 event handlers:
virtual void startDocument();
virtual void endDocument();
virtual void startElement(const XMLCh* const uri, const XMLCh* const localname, const XMLCh* const qname, const Attributes& attrs);
virtual void endElement(const XMLCh* const uri, const XMLCh* const localname, const XMLCh* const qname);
virtual void characters(const XMLCh* const chars, const unsigned int length);
// Locator, for determining line numbers of elements
const Locator* m_locator;
virtual void setDocumentLocator(const Locator* const locator) {
m_locator = locator;
}
// Return and remove the root element from this object (so it won't get deleted)
XMLElement* ReleaseRoot() { XMLElement* t = Root; Root = NULL; return t; }
private:
XMLElement* Root;
std::stack<XMLElement*> ElementStack; // so the event handlers can be aware of the current element
};
class XeroErrorHandler : public ErrorHandler
{
public:
XeroErrorHandler() : sawErrors(false) {}
~XeroErrorHandler() {}
void warning(const SAXParseException& err) { complain(err, L"warning"); }
void error(const SAXParseException& err) { complain(err, L"error"); }
void fatalError(const SAXParseException& err) { complain(err, L"fatal error"); };
void resetErrors() { sawErrors = false; }
bool getSawErrors() const { return sawErrors; }
utf16string getErrorText() { return errorText; }
private:
bool sawErrors;
utf16string errorText;
void complain(const SAXParseException& err, const wchar_t* severity) {
sawErrors = true;
C_ASSERT(sizeof(utf16_t) == sizeof(XMLCh));
errorText += wtoutf16(L"XML ");
errorText += wtoutf16(severity);
errorText += wtoutf16(L": ");
errorText += (utf16_t*)err.getSystemId();
errorText += wtoutf16(L" / ");
errorText += (utf16_t*)err.getMessage();
}
};
class XeroBinInputStream : public BinInputStream
{
public:
XeroBinInputStream(InputStream& stream) : m_stream(stream) {}
virtual XMLFilePos curPos () const
{
return m_stream.Tell();
}
virtual XMLSize_t readBytes (XMLByte *const toFill, const XMLSize_t maxToRead)
{
return (unsigned int)m_stream.Read(toFill, (unsigned int)maxToRead);
}
virtual const XMLCh* getContentType() const
{
return NULL;
}
private:
InputStream& m_stream;
};
class XeroInputSource : public InputSource
{
public:
XeroInputSource(InputStream& stream) : m_stream(stream) {}
virtual BinInputStream *makeStream() const
{
return new XeroBinInputStream(m_stream);
}
private:
InputStream& m_stream;
};
XMBFile* DatafileIO::XMLReader::LoadFromXML(InputStream& stream)
{
XMBFile* ret = new XMBFile();
// I don't like Xerces :-(
SAX2XMLReader* Parser = XMLReaderFactory::createXMLReader();
// DTD validation:
// Parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
// Parser->setFeature(XMLUni::fgXercesDynamic, true);
XeroHandler handler;
Parser->setContentHandler(&handler);
XeroErrorHandler errorHandler;
Parser->setErrorHandler(&errorHandler);
// Build the XMLElement tree inside the XeroHandler
XeroInputSource src(stream);
Parser->parse(src);
delete Parser;
if (errorHandler.getSawErrors())
{
//wxLogError(_("Error in XML file %s"), filename);
// TODO URGENT: report errors
delete ret;
return NULL;
}
else
{
XMLElement* root = handler.ReleaseRoot();
ret->root = root->childs[0];
delete root;
}
return ret;
}
void XeroHandler::startDocument()
{
Root = new XMLElement;
ElementStack.push(Root);
}
void XeroHandler::endDocument()
{
}
void XeroHandler::startElement(const XMLCh* const /*uri*/, const XMLCh* const localname, const XMLCh* const /*qname*/, const Attributes& attrs)
{
utf16string elementName = (utf16_t*)localname;
// Create a new element
XMLElement* e = new XMLElement;
e->name = elementName;
e->linenum = m_locator->getLineNumber();
// Store all the attributes in the new element
for (unsigned int i = 0; i < attrs.getLength(); ++i)
{
utf16string attrName = (utf16_t*)attrs.getLocalName(i);
XMLAttribute attr;
attr.name = attrName;
attr.value = (utf16_t*)attrs.getValue(i);
e->attrs.push_back(attr);
}
// Add the element to its parent
ElementStack.top()->childs.push_back(e);
// Set as parent of following elements
ElementStack.push(e);
}
void XeroHandler::endElement(const XMLCh* const /*uri*/, const XMLCh* const /*localname*/, const XMLCh* const /*qname*/)
{
// Trim whitespace around the element's contents
std::string whitespaceA = " \t\r\n";
utf16string whitespace (whitespaceA.begin(), whitespaceA.end());
XMLElement* el = ElementStack.top();
// Find the start of the non-whitespace section
size_t first = el->text.find_first_not_of(whitespace);
if (first == el->text.npos)
// Entirely whitespace - easy to handle
el->text = utf16string();
else
{
// Count the number of \n being cut off,
// and add them to the line number
// utf16string trimmed (el->text.begin(), el->text.begin()+first);
// el->linenum += (int)std::count(trimmed.begin(), trimmed.end(), (utf16_t)'\n');
// (Only use this when the line number should point to the start of the
// content, rather than the element tag. TODO: enable it in that situation.)
// Find the end of the non-whitespace section,
// and trim off everything else
size_t last = el->text.find_last_not_of(whitespace);
el->text = el->text.substr(first, 1+last-first);
}
ElementStack.pop();
}
void XeroHandler::characters(const XMLCh* const chars, const unsigned int length)
{
ElementStack.top()->text += utf16string((utf16_t*)chars, length);
}

View File

@ -1,70 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string>
#include <vector>
#include "../Util.h"
namespace DatafileIO
{
class InputStream;
class SeekableOutputStream;
// Convenient storage for the internal tree
struct XMLAttribute {
utf16string name;
utf16string value;
};
struct XMLElement {
utf16string name;
int linenum;
utf16string text;
std::vector<XMLElement*> childs;
std::vector<XMLAttribute> attrs;
};
struct XMBFile;
// Enforces initialisation/termination the XML system
struct XMLReader {
XMLReader();
~XMLReader();
XMBFile* LoadFromXML(InputStream& stream);
};
struct XMBFile {
XMLElement* root;
enum { UNKNOWN, AOM, AOE3 } format;
XMBFile();
~XMBFile();
// This does *not* understand l33t-compressed data. Please
// decompress them first.
static XMBFile* LoadFromXMB(InputStream& stream);
// Caller should convert the returned data to some encoding, and
// prepend "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" (or whatever
// is appropriate for that encoding)
std::wstring SaveAsXML();
void SaveAsXMB(SeekableOutputStream& stream);
};
};

View File

@ -1,18 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"

View File

@ -1,37 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
// Precompiled headers:
#ifdef _MSC_VER
# define _SCL_SECURE_NO_DEPRECATE // shut up, std::copy isn't deprecated
#endif
#ifdef USING_PCH
// Exclude rarely-used stuff from Windows headers
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
#endif
#include <vector>
#include <string>
#include <set>
#include <stack>
#include <map>
#endif // USING_PCH