- Added missing projects "VFS" & "export" to SVN

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@4447 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2011-05-26 11:25:04 +00:00
parent 6e2bdd557c
commit be95a2a7b1
203 changed files with 44525 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
#include <export/jsd/export_jsd.h>
#include <init_vfs.h>
#include <progress_bar.h>
#include <vfs/Core/vfs.h>
#include <vfs/Core/vfs_file_raii.h>
#include <vfs/Core/File/vfs_buffer_file.h>
#include <vfs/Ext/slf/vfs_slf_library.h>
#include <vfs/Ext/7z/vfs_create_7z_library.h>
#include <iostream>
#include <export/jsd/structure.h>
bool ja2xp::convertJSDtoXML(vfs::Path const& sSrc, vfs::Path const& sDst)
{
vfs::CVirtualFileSystem::Iterator it = getVFS()->begin(sSrc);
int file_counter = 0;
for(; !it.end(); it.next())
{
file_counter++;
vfs::String::str_t fname = it.value()->getPath().c_wcs();
if( !vfs::StrCmp::Equal( fname.substr(fname.length()-4,4), L".jsd") )
{
std::wcout << L"\"" << fname << L"\" " << L"is not an .jsd file" << std::endl;
continue;
}
if(!it.value()->openRead())
{
std::wcout << L"Could not open file \"" << sSrc() << L"\"" << std::endl;
continue;
}
vfs::String::str_t new_fname = fname.substr(0,fname.length()-4) + L".jsd.xml";
vfs::Path out_name;
if(vfs::StrCmp::Equal(sDst(), L"."))
{
out_name = vfs::Path(new_fname);
}
else
{
out_name = sDst;
}
std::wcout << L"Converting file \"" << it.value()->getPath().c_wcs() << L"\"" << std::endl;
vfs::COpenWriteFile wfile(out_name,true,true);
if(!ConvertStructure(it.value(), &wfile.file()))
{
printf("Error converting file : %s", vfs::String::as_utf8(it.value()->getPath()()));
continue;
}
}
if(file_counter == 0)
{
std::wcout << L"Nothing to convert!" << std::endl;
}
return true;
}
/**********************************************************************************************/
const wchar_t* ja2xp::CExportJSD::commandString = L"jsd";
void ja2xp::CExportJSD::handleCommand(param_list_t const& params)
{
//param_list_t::const_iterator cit = params.begin();
//for(; cit != params.end(); ++cit)
//{
//}
ja2xp::InitVFS& vfs = ja2xp::InitVFS::instance();
vfs.checkParameters(params);
if(!vfs.init())
{
return;
}
try
{
convertJSDtoXML(vfs.srcPattern(), vfs.dstPattern());
}
catch(vfs::Exception& msg)
{
std::wcout << msg.getLastEntryString().c_str() << std::endl;
}
}
void ja2xp::CExportJSD::printHelp()
{
std::wcout
<< L" convert JSD to XML file(s)" << std::endl
<< L" * if \"destination\" is a directory, then the filename's extension will be" << std::endl
<< L" replaced with \".jsd.xml\"" << std::endl
<< std::endl;
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef _EXPORT_JSD_H_
#define _EXPORT_SLF_H_
#include <vfs/Core/vfs_path.h>
#include <vfs/Core/Interface/vfs_file_interface.h>
#include <exporter_base.h>
namespace ja2xp
{
class CExportJSD : public IExporterBase
{
public:
typedef IExporterBase::param_list_t param_list_t;
static const wchar_t* commandString;// = L"jsd";
virtual void handleCommand(param_list_t const& params);
virtual void printHelp();
};
bool convertJSDtoXML(vfs::Path const& sSrc, vfs::Path const& sDst);
};
#endif // _EXPORT_SLF_H_
+293
View File
@@ -0,0 +1,293 @@
#include <export/jsd/structure.h>
#include <vfs/Core/vfs_file_raii.h>
#include <vfs/Tools/vfs_tools.h>
#include <Types.h>
#include <XMLWriter.h>
#include <sgp_auto_memory.h>
#include <Structure Internals.h>
bool ja2xp::ConvertStructure(vfs::tReadableFile* pStructureFile, vfs::tWritableFile* pOutputFile)
{
vfs::tReadableFile *pFile = pStructureFile;
if(!pFile)
{
return false;
}
vfs::COpenReadFile rfile(pFile);
XMLWriter xmlw;
xmlw.addAttributeToNextValue( "filename", vfs::String::as_utf8( rfile->getPath()() ) );
xmlw.openNode("STRUCTURE_FILE");
// Read Header
STRUCTURE_FILE_HEADER Header;
rfile->read((vfs::Byte*)&Header, sizeof( STRUCTURE_FILE_HEADER ));
// Write Header data
xmlw.openNode("HEADER");
xmlw.addValue("szId", std::string(Header.szId,0,4));
xmlw.addValue("usNumberOfStructures", Header.usNumberOfStructures);
xmlw.addValue("usNumberOfImages", Header.usNumberOfImages);
xmlw.addValue("usNumberOfStructuresStored", Header.usNumberOfStructuresStored);
xmlw.addValue("usNumberOfImageTileLocsStored", Header.usNumberOfImageTileLocsStored);
xmlw.addValue("usStructureDataSize", Header.usStructureDataSize);
if(Header.fFlags > 0)
{
xmlw.addAttributeToNextValue("uint",(void*)((UINT32)Header.fFlags));
xmlw.openNode("flags");
xmlw.addFlag(Header.fFlags, STRUCTURE_FILE_CONTAINS_AUXIMAGEDATA, "STRUCTURE_FILE_CONTAINS_AUXIMAGEDATA");
xmlw.addFlag(Header.fFlags, STRUCTURE_FILE_CONTAINS_STRUCTUREDATA, "STRUCTURE_FILE_CONTAINS_STRUCTUREDATA");
xmlw.closeNode();
}
else
{
xmlw.addValue("flags");
}
xmlw.closeNode();
if (Header.fFlags & STRUCTURE_FILE_CONTAINS_AUXIMAGEDATA)
{
UINT32 uiDataSize = sizeof( AuxObjectData ) * Header.usNumberOfImages;
sgp::AutoArray<AuxObjectData> pAuxData(uiDataSize);
VFS_THROW_IFF( pAuxData(), L"" );
// Read AuxImage data
VFS_THROW_IFF( uiDataSize == rfile->read( (vfs::Byte*)pAuxData(), uiDataSize ), L"" );
// Write AuxImage data
xmlw.addAttributeToNextValue("number_of", Header.usNumberOfImages);
xmlw.openNode("AUXIMAGE_DATA");
for(int i = 0; i < Header.usNumberOfImages; ++i)
{
xmlw.addAttributeToNextValue("index",i);
xmlw.openNode("auximage");
AuxObjectData& auximage = pAuxData[i];
xmlw.addValue("tile_loc_index", (int)auximage.usTileLocIndex);
xmlw.addValue("wall_orientation", (int)auximage.ubWallOrientation);
xmlw.addValue("number_of_tiles", (int)auximage.ubNumberOfTiles);
xmlw.addValue("current_frame", (int)auximage.ubCurrentFrame);
xmlw.addValue("number_of_frames", (int)auximage.ubNumberOfFrames);
if(auximage.fFlags > 0)
{
xmlw.addAttributeToNextValue("uint", (void*)((UINT32)auximage.fFlags));
xmlw.openNode("flags");
xmlw.addFlag(auximage.fFlags, AUX_FULL_TILE, "AUX_FULL_TILE");
xmlw.addFlag(auximage.fFlags, AUX_ANIMATED_TILE, "AUX_ANIMATED_TILE");
xmlw.addFlag(auximage.fFlags, AUX_DYNAMIC_TILE, "AUX_DYNAMIC_TILE");
xmlw.addFlag(auximage.fFlags, AUX_INTERACTIVE_TILE, "AUX_INTERACTIVE_TILE");
xmlw.addFlag(auximage.fFlags, AUX_IGNORES_HEIGHT, "AUX_IGNORES_HEIGHT");
xmlw.addFlag(auximage.fFlags, AUX_USES_LAND_Z, "AUX_USES_LAND_Z");
xmlw.closeNode();
}
else
{
xmlw.addValue("flags");
}
xmlw.closeNode();
}
xmlw.closeNode(); // auximage_data
xmlw.addAttributeToNextValue("number_of", Header.usNumberOfImageTileLocsStored);
xmlw.openNode("TILE_OFFSETS");
if (Header.usNumberOfImageTileLocsStored > 0)
{
uiDataSize = sizeof( RelTileLoc ) * Header.usNumberOfImageTileLocsStored;
sgp::AutoArray<RelTileLoc> pTileLocData(Header.usNumberOfImageTileLocsStored);
VFS_THROW_IFF( pTileLocData(), L"" );
VFS_THROW_IFF( uiDataSize == rfile->read((vfs::Byte*)pTileLocData(), uiDataSize), L"" );
for(int i = 0; i < Header.usNumberOfImageTileLocsStored; ++i)
{
RelTileLoc& off = pTileLocData[i];
xmlw.addAttributeToNextValue("index",i);
xmlw.addAttributeToNextValue("x",(int)off.bTileOffsetX);
xmlw.addAttributeToNextValue("y",(int)off.bTileOffsetY);
xmlw.addValue("offset");
}
}
xmlw.closeNode();
}
else
{
xmlw.addAttributeToNextValue("number_of", 0);
xmlw.addValue("AUXIMAGE_DATA");
xmlw.addAttributeToNextValue("number_of", Header.usNumberOfImageTileLocsStored);
xmlw.addValue("TILE_OFFSETS");
}
if (Header.fFlags & STRUCTURE_FILE_CONTAINS_STRUCTUREDATA)
{
UINT32 usNumberOfStructuresStored = Header.usNumberOfStructuresStored;
UINT32 uiDataSize = Header.usStructureDataSize;
// Determine the size of the data, from the header just read,
// allocate enough memory and read it in
sgp::AutoArray<UINT8> pubStructureData( uiDataSize );
VFS_THROW_IFF(pubStructureData(), L"");
VFS_THROW_IFF( uiDataSize == rfile->read((vfs::Byte*)pubStructureData(), uiDataSize), L"" );
xmlw.addAttributeToNextValue("number_of", Header.usNumberOfStructures);
if(Header.usNumberOfStructures != Header.usNumberOfStructuresStored)
{
xmlw.addAttributeToNextValue("stored", Header.usNumberOfStructuresStored);
}
xmlw.openNode("STRUCTURE_DATA");
UINT8* p_current = pubStructureData();
UINT8* p_end = pubStructureData() + uiDataSize;
for(unsigned int i = 0; i < usNumberOfStructuresStored; ++i)
{
if (p_current + sizeof( DB_STRUCTURE ) > p_end)
{
// gone past end of file block?!
// freeing of memory will occur outside of the function
break;
}
DB_STRUCTURE* structure = ((DB_STRUCTURE*)p_current);
p_current += sizeof( DB_STRUCTURE );
//xmlw.addAttributeToNextValue("index", i);
xmlw.addAttributeToNextValue("index", (int)structure->usStructureNumber);
xmlw.openNode("STRUCTURE");
//xmlw.addValue("usStructureNumber", (int)structure->usStructureNumber);
xmlw.addValue("ubArmour", (int)structure->ubArmour);
xmlw.addValue("ubHitPoints", (int)structure->ubHitPoints);
xmlw.addValue("ubDensity", (int)structure->ubDensity);
xmlw.addValue("ubWallOrientation", (int)structure->ubWallOrientation);
xmlw.addValue("bDestructionPartner",(int)structure->bDestructionPartner);
xmlw.addValue("bPartnerDelta", (int)structure->bPartnerDelta);
xmlw.addValue("bZTileOffsetX", (int)structure->bZTileOffsetX);
xmlw.addValue("bZTileOffsetY", (int)structure->bZTileOffsetY);
if(structure->fFlags > 0)
{
xmlw.addAttributeToNextValue("uint",(void*)((UINT32)structure->fFlags));
xmlw.openNode("flags");
xmlw.addFlag(structure->fFlags, STRUCTURE_BASE_TILE, "STRUCTURE_BASE_TILE");
xmlw.addFlag(structure->fFlags, STRUCTURE_OPEN, "STRUCTURE_OPEN");
xmlw.addFlag(structure->fFlags, STRUCTURE_OPENABLE, "STRUCTURE_OPENABLE");
// synonyms for STRUCTURE_OPENABLE
xmlw.addFlag(structure->fFlags, STRUCTURE_CLOSEABLE, "STRUCTURE_CLOSEABLE");
xmlw.addFlag(structure->fFlags, STRUCTURE_SEARCHABLE, "STRUCTURE_SEARCHABLE");
xmlw.addFlag(structure->fFlags, STRUCTURE_HIDDEN, "STRUCTURE_HIDDEN");
xmlw.addFlag(structure->fFlags, STRUCTURE_MOBILE, "STRUCTURE_MOBILE");
// STRUCTURE_PASSABLE is set for each structure instance where
// the tile flag TILE_PASSABLE is set
xmlw.addFlag(structure->fFlags, STRUCTURE_PASSABLE, "STRUCTURE_PASSABLE");
xmlw.addFlag(structure->fFlags, STRUCTURE_EXPLOSIVE, "STRUCTURE_EXPLOSIVE");
xmlw.addFlag(structure->fFlags, STRUCTURE_TRANSPARENT, "STRUCTURE_TRANSPARENT");
xmlw.addFlag(structure->fFlags, STRUCTURE_GENERIC, "STRUCTURE_GENERIC");
xmlw.addFlag(structure->fFlags, STRUCTURE_TREE, "STRUCTURE_TREE");
xmlw.addFlag(structure->fFlags, STRUCTURE_FENCE, "STRUCTURE_FENCE");
xmlw.addFlag(structure->fFlags, STRUCTURE_WIREFENCE, "STRUCTURE_WIREFENCE");
xmlw.addFlag(structure->fFlags, STRUCTURE_HASITEMONTOP, "STRUCTURE_HASITEMONTOP");
xmlw.addFlag(structure->fFlags, STRUCTURE_SPECIAL, "STRUCTURE_SPECIAL");
xmlw.addFlag(structure->fFlags, STRUCTURE_LIGHTSOURCE, "STRUCTURE_LIGHTSOURCE");
xmlw.addFlag(structure->fFlags, STRUCTURE_VEHICLE, "STRUCTURE_VEHICLE");
xmlw.addFlag(structure->fFlags, STRUCTURE_WALL, "STRUCTURE_WALL");
xmlw.addFlag(structure->fFlags, STRUCTURE_WALLNWINDOW, "STRUCTURE_WALLNWINDOW");
xmlw.addFlag(structure->fFlags, STRUCTURE_SLIDINGDOOR, "STRUCTURE_SLIDINGDOOR");
xmlw.addFlag(structure->fFlags, STRUCTURE_DOOR, "STRUCTURE_DOOR");
// a "multi" structure (as opposed to multitiled) is composed of multiple graphics & structures
xmlw.addFlag(structure->fFlags, STRUCTURE_MULTI, "STRUCTURE_MULTI");
xmlw.addFlag(structure->fFlags, STRUCTURE_CAVEWALL, "STRUCTURE_CAVEWALL");
xmlw.addFlag(structure->fFlags, STRUCTURE_DDOOR_LEFT, "STRUCTURE_DDOOR_LEFT");
xmlw.addFlag(structure->fFlags, STRUCTURE_DDOOR_RIGHT, "STRUCTURE_DDOOR_RIGHT");
xmlw.addFlag(structure->fFlags, STRUCTURE_NORMAL_ROOF, "STRUCTURE_NORMAL_ROOF");
xmlw.addFlag(structure->fFlags, STRUCTURE_SLANTED_ROOF, "STRUCTURE_SLANTED_ROOF");
xmlw.addFlag(structure->fFlags, STRUCTURE_TALL_ROOF, "STRUCTURE_TALL_ROOF");
xmlw.addFlag(structure->fFlags, STRUCTURE_SWITCH, "STRUCTURE_SWITCH");
xmlw.addFlag(structure->fFlags, STRUCTURE_ON_LEFT_WALL, "STRUCTURE_ON_LEFT_WALL");
xmlw.addFlag(structure->fFlags, STRUCTURE_ON_RIGHT_WALL, "STRUCTURE_ON_RIGHT_WALL");
xmlw.addFlag(structure->fFlags, STRUCTURE_CORPSE, "STRUCTURE_CORPSE");
xmlw.addFlag(structure->fFlags, STRUCTURE_PERSON, "STRUCTURE_PERSON");
// COMBINATION FLAGS
xmlw.addFlag(structure->fFlags, STRUCTURE_ANYFENCE, "STRUCTURE_ANYFENCE");
xmlw.addFlag(structure->fFlags, STRUCTURE_ANYDOOR, "STRUCTURE_ANYDOOR");
xmlw.addFlag(structure->fFlags, STRUCTURE_OBSTACLE, "STRUCTURE_OBSTACLE");
xmlw.addFlag(structure->fFlags, STRUCTURE_WALLSTUFF, "STRUCTURE_WALLSTUFF");
xmlw.addFlag(structure->fFlags, STRUCTURE_BLOCKSMOVES, "STRUCTURE_BLOCKSMOVES");
xmlw.addFlag(structure->fFlags, STRUCTURE_TYPE_DEFINED, "STRUCTURE_TYPE_DEFINED");
xmlw.addFlag(structure->fFlags, STRUCTURE_ROOF, "STRUCTURE_ROOF");
xmlw.closeNode();
}
else
{
xmlw.addValue("flags");
}
xmlw.addValue("ubNumberOfTiles", (int)structure->ubNumberOfTiles);
xmlw.addAttributeToNextValue("number_of", (int)structure->ubNumberOfTiles);
xmlw.openNode("TILES");
for(int i = 0; i < structure->ubNumberOfTiles; ++i)
{
if (p_current + sizeof( DB_STRUCTURE_TILE ) > p_end)
{
// gone past end of file block?!
// freeing of memory will occur outside of the function
break;
}
DB_STRUCTURE_TILE* structTile = ((DB_STRUCTURE_TILE*)p_current);
p_current += sizeof( DB_STRUCTURE_TILE );
xmlw.addAttributeToNextValue("index", i);
xmlw.openNode("STRUCTURE_TILE");
xmlw.addValue("bXPosRelToBase", (int)structTile->bXPosRelToBase);
xmlw.addValue("bYPosRelToBase", (int)structTile->bYPosRelToBase);
xmlw.addValue("sPosRelToBase", (int)structTile->sPosRelToBase);
xmlw.addValue("ubVehicleHitLocation", (int)structTile->ubVehicleHitLocation);
if(structTile->fFlags > 0)
{
xmlw.addAttributeToNextValue("uint", (void*)((UINT32)structTile->fFlags));
xmlw.openNode("flags");
xmlw.addFlag(structTile->fFlags, TILE_ON_ROOF, "TILE_ON_ROOF");
xmlw.addFlag(structTile->fFlags, TILE_PASSABLE, "TILE_PASSABLE");
xmlw.closeNode();
}
else
{
xmlw.addValue("flags");
}
xmlw.openNode("profile");
for(int y=PROFILE_Y_SIZE-1; y >= 0; y--)
{
std::stringstream ss;
for(int x = 0; x < PROFILE_X_SIZE - 1; ++x)
{
ss << (int)structTile->Shape[y][x] << ",";
}
ss << (int)structTile->Shape[y][PROFILE_X_SIZE-1];
xmlw.addValue("y"+vfs::toString<char>(y), ss.str());
}
xmlw.closeNode();
xmlw.closeNode();
}
xmlw.closeNode();
xmlw.closeNode();
}
xmlw.closeNode();
}
else
{
xmlw.addAttributeToNextValue("number_of", Header.usNumberOfStructuresStored);
xmlw.addValue("STRUCTURE_DATA");
}
xmlw.closeNode(); // root
xmlw.writeToFile(pOutputFile);
return true;
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef _STRUCTURE_H_
#define _STRUCTURE_H_
#include <vfs/Core/Interface/vfs_file_interface.h>
namespace ja2xp
{
bool ConvertStructure(vfs::tReadableFile* pStructureFile, vfs::tWritableFile* pOutputFile);
};
#endif // _STRUCTURE_H_
+182
View File
@@ -0,0 +1,182 @@
#include <export/slf/export_slf.h>
#include <export/sti/export_sti.h>
#include <init_vfs.h>
#include <progress_bar.h>
#include <vfs/Core/vfs.h>
#include <vfs/Core/vfs_file_raii.h>
#include <vfs/Core/File/vfs_buffer_file.h>
#include <vfs/Ext/slf/vfs_slf_library.h>
#include <vfs/Ext/7z/vfs_create_7z_library.h>
#include <iostream>
bool ja2xp::convertSLFto7z(vfs::tReadableFile* pInFile, vfs::tWritableFile *pOutFile, bool bConvertSTIs, bool bPngOffsets)
{
vfs::CSLFLibrary src_lib(pInFile,"");
if(!src_lib.init())
{
std::wcout << L"Could not init SLF Library \"" << pInFile->getPath().c_wcs() << L"\"" << std::endl;
return false;
}
vfs::CCreateUncompressed7zLibrary create7zLib;
vfs::CSLFLibrary::Iterator it = src_lib.begin();
int count = 0;
while(!it.end())
{
count++;
it.next();
}
ProgressBar pbar(54,count);
it = src_lib.begin();
for(; !it.end(); it.next())
{
count++;
vfs::CBufferFile* temp_file = NULL;
vfs::tReadableFile *file = vfs::tReadableFile::cast(it.value());
if(bConvertSTIs)
{
vfs::Path filename = it.value()->getPath();
if(vfs::StrCmp::Equal(filename().substr(filename().length()-4,4), L".sti"))
{
vfs::Path path = filename().substr(0,filename.length()-4) + L".jpc.7z";
temp_file = new vfs::CBufferFile(path);
if(convertSTItoJPC(vfs::tReadableFile::cast(it.value()), vfs::tWritableFile::cast(temp_file), bPngOffsets, false))
{
file = vfs::tReadableFile::cast( temp_file );
}
}
}
if(create7zLib.addFile(file))
{
pbar.Next(it.value()->getPath()());
}
else
{
std::wcout << L"Adding file '" << it.value()->getPath().c_wcs() << L"' failed!" << std::endl;
}
if(temp_file)
{
delete temp_file;
}
}
std::wstringstream wss;
wss << L"Writing file \"" << pOutFile->getPath().c_wcs() << L"\"";
pbar.Next(wss.str());
if(!create7zLib.writeLibrary(pOutFile))
{
wss.str(L"");
wss << L"Could not write file \"" << pOutFile->getPath().c_wcs() << L"\"";
pbar.Next(wss.str());
return false;
}
return true;
}
bool ja2xp::convertSLFto7z(vfs::Path const& sSrc, vfs::Path const& sDst, bool bConvertSTIs, bool bPngOffsets)
{
vfs::CVirtualFileSystem::Iterator it = getVFS()->begin(sSrc);
int file_counter = 0;
for(; !it.end(); it.next())
{
file_counter++;
vfs::String::str_t fname = it.value()->getPath().c_wcs();
if( !vfs::StrCmp::Equal( fname.substr(fname.length()-4,4), L".slf") )
{
std::wcout << L"\"" << fname << L"\" " << L"is not an .slf file" << std::endl;
continue;
}
if(!it.value()->openRead())
{
std::wcout << L"Could not open file \"" << sSrc() << L"\"" << std::endl;
continue;
}
vfs::String::str_t new_fname = fname.substr(0,fname.length()-4) + L".jdc.7z";
vfs::Path out_name;
if(vfs::StrCmp::Equal(sDst(), L"."))
{
out_name = vfs::Path(new_fname);
}
else
{
out_name = sDst;
}
std::wcout << L"Converting file \"" << it.value()->getPath().c_wcs() << L"\"" << std::endl;
vfs::COpenWriteFile wfile(out_name,true,true);
if(!convertSLFto7z(it.value(), &wfile.file(), bConvertSTIs, bPngOffsets))
{
printf("\n");
continue;
}
printf("\n");
}
if(file_counter == 0)
{
std::wcout << L"Nothing to convert!" << std::endl;
}
return true;
}
/**********************************************************************************************/
const wchar_t* ja2xp::CExportSLF::commandString = L"slf";
void ja2xp::CExportSLF::handleCommand(param_list_t const& params)
{
bool opt_Sti2Png = false, opt_PngOffsets = false;
param_list_t vfs_params;
param_list_t::const_iterator cit = params.begin();
for(; cit != params.end(); ++cit)
{
if( vfs::StrCmp::Equal(*cit, L"-sti2png") )
{
opt_Sti2Png = true;
continue;
}
else if( vfs::StrCmp::Equal(*cit, L"-png_offsets") )
{
opt_PngOffsets = true;
continue;
}
else
{
vfs_params.push_back(*cit);
}
}
ja2xp::InitVFS& vfs = ja2xp::InitVFS::instance();
vfs.checkParameters(vfs_params);
if(!vfs.init())
{
return;
}
try
{
convertSLFto7z(vfs.srcPattern(), vfs.dstPattern(), opt_Sti2Png, opt_PngOffsets);
}
catch(vfs::Exception& msg)
{
std::wcout << msg.getLastEntryString().c_str() << std::endl;
}
}
void ja2xp::CExportSLF::printHelp()
{
std::wcout
<< L" convert SLF archive(s) to uncompressed 7z archive(s)" << std::endl
<< L" * if \"destination\" is a directory, then the filename's extension will be" << std::endl
<< L" replaced with \".jdc.7z\"" << std::endl
<< std::endl
<< L" options :" << std::endl
<< L" -sti2png : all sti files in the archive will be converted to" << std::endl
<< L" \".jpc.7z\" files" << std::endl
<< L" -png_offsets : if option \"sti2png\" is enabled, offsets of the png" << std::endl
<< L" subimages will be written int the \"appdata.xml\" file" << std::endl;
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef _EXPORT_SLF_H_
#define _EXPORT_SLF_H_
#include <vfs/Core/vfs_path.h>
#include <vfs/Core/Interface/vfs_file_interface.h>
#include <exporter_base.h>
namespace ja2xp
{
class CExportSLF : public IExporterBase
{
public:
typedef IExporterBase::param_list_t param_list_t;
static const wchar_t* commandString;// = L"slf";
virtual void handleCommand(param_list_t const& params);
virtual void printHelp();
};
bool convertSLFto7z(vfs::tReadableFile* pInFile, vfs::tWritableFile *pOutFile, bool bConvertSTIs=false, bool bPngOffsets=false);
bool convertSLFto7z(vfs::Path const& sSrc, vfs::Path const& sDst, bool bConvertSTIs=false, bool bPngOffsets=false);
};
#endif // _EXPORT_SLF_H_
File diff suppressed because it is too large Load Diff
+68
View File
@@ -0,0 +1,68 @@
#ifndef _IMAGE_H_
#define _IMAGE_H_
#include "Types.h"
#include "himage.h"
#include <vfs/Core/vfs_types.h>
#include <vfs/Core/File/vfs_file.h>
#include <vector>
namespace ja2xp
{
class CImage
{
public:
enum EImageType
{
IT_NONE,
IT_BITMAP,
IT_COMPRESSED,
};
public:
CImage(vfs::Path const& sFileName);
CImage(vfs::tReadableFile *pFile);
~CImage();
EImageType GetImageType();
bool GetSize(UINT32 uiSubImage, UINT32 &uiWidth, UINT32 &uiHeight);
bool GetPosition(UINT32 uiSubImage, INT32 &uiX, INT32 &uiY);
SGPPaletteEntry* GetPalette();
// use when image type is 'BITMAP'
void* GetDataPointer(UINT32 &uiSize);
bool GetRawDataOfSubImage(UINT32 uiSubImage, void* pData, UINT32 uiMaxSize, UINT32 &uiFilledSize);
// use when image type is 'COMPRESSED' unless you know how to 'decompress'
UINT32 FillData(UINT32 uiSubImage, UINT8* pData, UINT32 uiMaxSize, bool rgba = false);
bool Unpack16BppImageToRGBBuffer(UINT16* pSrc, UINT8* pDst, UINT32 uiWidth, UINT32 uiHeight);
UINT32 GetNumberOfSubImages();
bool LoadData();
bool DeleteData();
void LoadBMP();
//bool WriteAsBMPs(vfs_string sOutPathName);
bool WriteAsPNGs(vfs::tWritableFile* outFile, bool bWriteOffsets=false, bool rgba=false );
bool WriteAsPNGs(vfs::Path outpath, bool bWriteOffsets=false, bool rgba=false);
bool WriteFirstPNG(vfs::tWritableFile* outFile, bool rgba=false);
//bool WriteAsSTIs(vfs_string sOutPathName);
protected:
bool writeSubImageToPNGFile(int i, vfs::tWritableFile* file, bool rgba = false);
bool writeImageToPNGFile(vfs::tWritableFile* file, bool rgba = false);
bool writeSTIAppData(std::vector<bool> const& write_image, bool bWriteOffsets, vfs::tWritableFile* file);
private:
vfs::tReadableFile* m_pImageFile;
EImageType m_eImageType;
image_type* m_pRawImage;
bool m_bImageLoaded;
};
};
#endif // _IMAGE_H_
+426
View File
@@ -0,0 +1,426 @@
#include <vfs/Core/vfs_types.h>
#include "STCI_lib.h"
#include "imgfmt.h"
#include "himage.h"
#include "Types.h"
#include <vfs/Core/vfs_file_raii.h>
#include <vfs/Core/vfs_debug.h>
#include <string>
#include <cassert>
#include <iostream>
namespace ja2xp
{
BOOLEAN STCILoadRGB(vfs::tReadableFile *pFile, HIMAGE hImage, UINT16 fContents, STCIHeader * pHeader );
BOOLEAN STCILoadIndexed(vfs::tReadableFile *pFile, HIMAGE hImage, UINT16 fContents, STCIHeader * pHeader );
BOOLEAN STCISetPalette(vfs::tReadableFile *pFile, PTR pSTCIPalette, HIMAGE hImage );
};
BOOLEAN ja2xp::LoadSTCIFileToImage(vfs::tReadableFile *pFile, HIMAGE hImage, UINT16 fContents )
{
STCIHeader Header;
image_type TempImage;
// Check that hImage is valid, and that the file in question exists
assert( hImage != NULL );
TempImage = *hImage;
if(pFile == NULL)
{
return FALSE;
}
// Open the file and read the header
vfs::COpenReadFile file(pFile);
VFS_THROW_IFF( STCI_HEADER_SIZE == pFile->read((vfs::Byte*)&Header,STCI_HEADER_SIZE), L"" );
VFS_THROW_IFF( memcmp( Header.cID, STCI_ID_STRING, STCI_ID_LEN ) == 0, L"" );
// Determine from the header the data stored in the file. and run the appropriate loader
if (Header.fFlags & STCI_RGB)
{
if( !STCILoadRGB(pFile, &TempImage, fContents, &Header ) )
{
pFile->close();
std::cout << ".. loading bitmap image failed .." << std::endl;
return( FALSE );
}
}
else if (Header.fFlags & STCI_INDEXED)
{
if( !STCILoadIndexed(pFile, &TempImage, fContents, &Header ) )
{
pFile->close();
std::cout << ".. loading compressed image failed .." << std::endl;
return( FALSE );
}
}
else
{ // unsupported type of data, or the right flags weren't set!
pFile->close();
return( FALSE );
}
// Requested data loaded successfully.
pFile->close();
// Set some more flags in the temporary image structure, copy it so that hImage points
// to it, and return.
if (Header.fFlags & STCI_ZLIB_COMPRESSED)
{
TempImage.fFlags |= IMAGE_COMPRESSED;
}
TempImage.usWidth = Header.usWidth;
TempImage.usHeight = Header.usHeight;
TempImage.ubBitDepth = Header.ubDepth;
*hImage = TempImage;
return( TRUE );
}
BOOLEAN ja2xp::STCILoadRGB(vfs::tReadableFile *pFile, HIMAGE hImage, UINT16 fContents, STCIHeader * pHeader )
{
if (fContents & IMAGE_PALETTE && !(fContents & IMAGE_ALLIMAGEDATA))
{
// RGB doesn't have a palette!
std::cout << "RGB doesn't have a palette!" << std::endl;
return( FALSE );
}
if (fContents & IMAGE_BITMAPDATA)
{
// Allocate memory for the image data and read it in
hImage->pImageData = new char[ pHeader->uiStoredSize ];
if (hImage->pImageData == NULL)
{
return( FALSE );
}
try
{
vfs::size_t size = pHeader->uiStoredSize;
VFS_THROW_IFF( size == pFile->read( (vfs::Byte*)hImage->pImageData, size ), L"" );
}
catch(vfs::Exception& ex)
{
delete[] hImage->pImageData;
return( FALSE );
}
hImage->fFlags |= IMAGE_BITMAPDATA;
if( pHeader->ubDepth == 16)
{
// ASSUMPTION: file data is 565 R,G,B
if (gusRedMask != (UINT16) pHeader->RGB.uiRedMask || gusGreenMask != (UINT16) pHeader->RGB.uiGreenMask || gusBlueMask != (UINT16) pHeader->RGB.uiBlueMask )
{
// colour distribution of the file is different from hardware! We have to change it!
// Convert the image to the current hardware's specifications
if (gusRedMask > gusGreenMask && gusGreenMask > gusBlueMask)
{
// hardware wants RGB!
if (gusRedMask == 0x7C00 && gusGreenMask == 0x03E0 && gusBlueMask == 0x001F)
{ // hardware is 555
ConvertRGBDistribution565To555( hImage->p16BPPData, pHeader->usWidth * pHeader->usHeight );
return( TRUE );
}
else if (gusRedMask == 0xFC00 && gusGreenMask == 0x03E0 && gusBlueMask == 0x001F)
{
ConvertRGBDistribution565To655( hImage->p16BPPData, pHeader->usWidth * pHeader->usHeight );
return( TRUE );
}
else if (gusRedMask == 0xF800 && gusGreenMask == 0x07C0 && gusBlueMask == 0x003F)
{
ConvertRGBDistribution565To556( hImage->p16BPPData, pHeader->usWidth * pHeader->usHeight );
return( TRUE );
}
else
{
// take the long route
ConvertRGBDistribution565ToAny( hImage->p16BPPData, pHeader->usWidth * pHeader->usHeight );
return( TRUE );
}
}
else
{
// hardware distribution is not R-G-B so we have to take the long route!
ConvertRGBDistribution565ToAny( hImage->p16BPPData, pHeader->usWidth * pHeader->usHeight );
return( TRUE );
}
}
}
}
return( TRUE );
}
BOOLEAN ja2xp::STCILoadIndexed(vfs::tReadableFile *pFile, HIMAGE hImage, UINT16 fContents, STCIHeader * pHeader )
{
UINT32 uiFileSectionSize;
PTR pSTCIPalette;
if (fContents & IMAGE_PALETTE)
{
// Allocate memory for reading in the palette
if (pHeader->Indexed.uiNumberOfColours != 256)
{
return( FALSE );
}
uiFileSectionSize = pHeader->Indexed.uiNumberOfColours * STCI_PALETTE_ELEMENT_SIZE;
pSTCIPalette = new char[uiFileSectionSize];
if (pSTCIPalette == NULL)
{
pFile->close();
return( FALSE );
}
memset( pSTCIPalette, 0, uiFileSectionSize );
// Read in the palette
try
{
VFS_THROW_IFF( uiFileSectionSize == pFile->read( (vfs::Byte*)pSTCIPalette, uiFileSectionSize ), L"" );
}
catch(vfs::Exception& ex)
{
pFile->close();
delete[] pSTCIPalette;
return( FALSE );
}
if (!STCISetPalette(pFile, pSTCIPalette, hImage ))
{
pFile->close();
delete[] pSTCIPalette;
return( FALSE );
}
hImage->fFlags |= IMAGE_PALETTE;
// Free the temporary buffer
delete[] pSTCIPalette;
}
else if (fContents & (IMAGE_BITMAPDATA | IMAGE_APPDATA))
{ // seek past the palette
uiFileSectionSize = pHeader->Indexed.uiNumberOfColours * STCI_PALETTE_ELEMENT_SIZE;
try
{
pFile->setReadPosition( uiFileSectionSize, vfs::IBaseFile::SD_CURRENT);
}
catch(vfs::Exception& ex)
{
pFile->close();
return( FALSE );
}
}
if (fContents & IMAGE_BITMAPDATA)
{
if (pHeader->fFlags & STCI_ETRLE_COMPRESSED)
{
// load data for the subimage (object) structures
assert( sizeof( ETRLEObject ) == STCI_SUBIMAGE_SIZE );
hImage->usNumberOfObjects = pHeader->Indexed.usNumberOfSubImages;
uiFileSectionSize = hImage->usNumberOfObjects * STCI_SUBIMAGE_SIZE;
hImage->pETRLEObject = (ETRLEObject *) new char[uiFileSectionSize];
if (hImage->pETRLEObject == NULL)
{
pFile->close();
if (fContents & IMAGE_PALETTE)
{
delete[] hImage->pPalette;
}
return( FALSE );
}
try
{
VFS_THROW_IFF(uiFileSectionSize == pFile->read((vfs::Byte*)hImage->pETRLEObject, uiFileSectionSize), L"")
}
catch(vfs::Exception& ex)
{
//FileClose( hFile );
pFile->close();
if (fContents & IMAGE_PALETTE)
{
delete[] hImage->pPalette;
}
delete[] hImage->pETRLEObject;
return( FALSE );
}
hImage->uiSizePixData = pHeader->uiStoredSize;
hImage->fFlags |= IMAGE_TRLECOMPRESSED;
}
// allocate memory for and read in the image data
hImage->pImageData = new char[pHeader->uiStoredSize];
if (hImage->pImageData == NULL)
{
pFile->close();
if (fContents & IMAGE_PALETTE)
{
delete[] hImage->pPalette;
}
if (hImage->usNumberOfObjects > 0)
{
delete[] hImage->pETRLEObject;
}
return( FALSE );
}
try
{
VFS_THROW_IFF(pHeader->uiStoredSize == pFile->read( (vfs::Byte*)hImage->pImageData, pHeader->uiStoredSize), L"");
}
catch(vfs::Exception& ex)
{ // Problem reading in the image data!
pFile->close();
delete[] hImage->pImageData;
if (fContents & IMAGE_PALETTE)
{
delete[] hImage->pPalette;
}
if (hImage->usNumberOfObjects > 0)
{
delete[] hImage->pETRLEObject;
}
return( FALSE );
}
hImage->fFlags |= IMAGE_BITMAPDATA;
}
else if (fContents & IMAGE_APPDATA) // then there's a point in seeking ahead
{
try
{
pFile->setReadPosition( pHeader->uiStoredSize, vfs::IBaseFile::SD_CURRENT);
}
catch(vfs::Exception& ex)
{
//FileClose( hFile );
pFile->close();
return( FALSE );
}
}
if (/*fContents & IMAGE_APPDATA &&*/ pHeader->uiAppDataSize > 0)
{
// load application-specific data
hImage->pAppData = new UINT8[pHeader->uiAppDataSize];
if (hImage->pAppData == NULL)
{
pFile->close();
delete[] hImage->pAppData;
if (fContents & IMAGE_PALETTE)
{
delete[] hImage->pPalette;
}
if (fContents & IMAGE_BITMAPDATA)
{
delete[] hImage->pImageData;
}
if (hImage->usNumberOfObjects > 0)
{
delete[] hImage->pETRLEObject;
}
return( FALSE );
}
try
{
VFS_THROW_IFF(pHeader->uiAppDataSize == pFile->read( (vfs::Byte*)hImage->pAppData, pHeader->uiAppDataSize), L"");
}
catch(vfs::Exception& ex)
{
pFile->close();
delete[] hImage->pAppData;
if (fContents & IMAGE_PALETTE)
{
delete[] hImage->pPalette;
}
if (fContents & IMAGE_BITMAPDATA)
{
delete[] hImage->pImageData;
}
if (hImage->usNumberOfObjects > 0)
{
delete[] hImage->pETRLEObject;
}
return( FALSE );
}
hImage->uiAppDataSize = pHeader->uiAppDataSize;
for(int i=0; i<pHeader->Indexed.usNumberOfSubImages; ++i)
{
AuxObjectData *pAOD = (AuxObjectData*)(&(hImage->pAppData[i*16]));
pAOD->ubUnused[0] = pAOD->ubUnused[0];
}
hImage->fFlags |= IMAGE_APPDATA;
}
else
{
hImage->pAppData = NULL;
hImage->uiAppDataSize = 0;
}
return( TRUE );
}
BOOLEAN ja2xp::STCISetPalette(vfs::tReadableFile *pFile, PTR pSTCIPalette, HIMAGE hImage )
{
UINT16 usIndex;
STCIPaletteElement * pubPalette;
pubPalette = (STCIPaletteElement *) pSTCIPalette;
// Allocate memory for palette
hImage->pPalette = (SGPPaletteEntry *) new char[ sizeof( SGPPaletteEntry ) * 256];
memset( hImage->pPalette, 0, ( sizeof( SGPPaletteEntry ) * 256 ) );
if ( hImage->pPalette == NULL )
{
return( FALSE );
}
// Initialize the proper palette entries
for (usIndex = 0; usIndex < 256; usIndex++)
{
hImage->pPalette[ usIndex ].peRed = pubPalette->ubRed;
hImage->pPalette[ usIndex ].peGreen = pubPalette->ubGreen;
hImage->pPalette[ usIndex ].peBlue = pubPalette->ubBlue;
hImage->pPalette[ usIndex ].peFlags = 0;
pubPalette ++;
}
return TRUE;
}
BOOLEAN ja2xp::IsSTCIETRLEFile(vfs::tReadableFile *pFile, CHAR8 * ImageFile )
{
// HWFILE hFile;
STCIHeader Header;
if(pFile == NULL)
{
return FALSE;
}
//CHECKF( FileExists( ImageFile ) );
vfs::Path filename(ImageFile);
try
{
VFS_THROW_IFF(STCI_HEADER_SIZE == pFile->read( (vfs::Byte*)&Header, STCI_HEADER_SIZE), L"");
VFS_THROW_IFF( memcmp( Header.cID, STCI_ID_STRING, STCI_ID_LEN ) == 0, L"" );
}
catch(vfs::Exception& ex)
{
pFile->close();
return( FALSE );
}
pFile->close();
if (Header.fFlags & STCI_ETRLE_COMPRESSED)
{
return( TRUE );
}
else
{
return( FALSE );
}
}
+11
View File
@@ -0,0 +1,11 @@
#include "Types.h"
#include "himage.h"
#include <vfs/Core/File/vfs_file.h>
namespace ja2xp
{
BOOLEAN LoadSTCIFileToImage(vfs::tReadableFile *pFile, HIMAGE hImage, UINT16 fContents );
BOOLEAN IsSTCIETRLEFile(vfs::tReadableFile *pFile, CHAR8 * ImageFile );
};
+207
View File
@@ -0,0 +1,207 @@
#include "export_sti.h"
#include "Image.h"
#include <init_vfs.h>
#include <vfs/Core/vfs.h>
#include <vfs/Core/vfs_file_raii.h>
#include <iostream>
bool ja2xp::convertSTItoJPC(vfs::tReadableFile *pFile, vfs::tWritableFile *pOutFile, bool bOffsets, bool rgba)
{
if(!pFile)
{
std::wcout << L"file to read from is NULL" << std::endl;
}
if(!pOutFile)
{
std::wcout << L"file to write to is NULL" << std::endl;
}
CImage image(pFile);
if(image.LoadData())
{
return image.WriteAsPNGs(pOutFile, bOffsets, rgba);
}
std::wcout << L"could not load data from STI file" << std::endl;
return false;
}
bool ja2xp::convertSTItoJPC(vfs::tReadableFile *pFile, vfs::Path const base_out_path, bool bOffsets, bool rgba)
{
if(!pFile)
{
std::wcout << L"file to read from is NULL" << std::endl;
}
CImage image(pFile);
if(image.LoadData())
{
return image.WriteAsPNGs(base_out_path, bOffsets, rgba);
}
std::wcout << L"could not load data from STI file" << std::endl;
return false;
}
bool ja2xp::convertSTItoPNG(vfs::tReadableFile *pFile, vfs::tWritableFile *pOutFile, bool rgba)
{
if(!pFile)
{
std::wcout << L"file to read from is NULL" << std::endl;
}
CImage image(pFile);
if(image.LoadData())
{
return image.WriteFirstPNG(pOutFile, rgba);
}
std::wcout << L"could not load data from STI file" << std::endl;
return false;
}
bool ja2xp::convertSTItoJPC(vfs::Path const& sSrc, vfs::Path const& sDst, bool bPacked, bool bOffsets, bool bOnePng, bool rgba)
{
vfs::CVirtualFileSystem::Iterator it = getVFS()->begin(sSrc);
int file_counter = 0;
for(; !it.end(); it.next())
{
file_counter++;
vfs::String::str_t fname = it.value()->getPath().c_wcs();
if( !vfs::StrCmp::Equal( fname.substr(fname.length()-4,4), L".sti") )
{
std::wcout << L"\"" << fname << L"\" is not an .sti file" << std::endl;
continue;
}
if(!it.value()->openRead())
{
std::wcout << L"Could not open file \"" << sSrc() << L"\"" << std::endl;
continue;
}
vfs::String::str_t fname_base = fname.substr(0,fname.length()-4);
std::wcout << L"Converting file \"" << fname << L"\"" << std::endl;
if(bOnePng)
{
vfs::Path out_name;
if(vfs::StrCmp::Equal(sDst(), L"."))
{
out_name = vfs::Path(fname_base + L".png");
}
else
{
out_name = sDst;
}
vfs::COpenWriteFile wfile(out_name,true,true);
if( !convertSTItoPNG( it.value(), &(wfile.file()), rgba ) )
{
std::wcout << L"error : could not convert sti image" << std::endl;
continue;
}
}
else if(bPacked)
{
vfs::Path out_name;
if(vfs::StrCmp::Equal(sDst(), L"."))
{
out_name = vfs::Path(fname_base + L".jpc.7z");
}
else
{
out_name = sDst;
}
vfs::COpenWriteFile wfile(out_name,true,true);
if( !convertSTItoJPC( it.value(), &(wfile.file()), bOffsets, rgba ) )
{
std::wcout << L"error : could not convert sti image" << std::endl;
continue;
}
}
else
{
if( !convertSTItoJPC( it.value(), vfs::Path(fname_base), bOffsets, rgba ) )
{
std::wcout << L"error : could not convert sti image" << std::endl;
continue;
}
}
}
if(file_counter == 0)
{
std::wcout << L"Nothing to convert!" << std::endl;
}
return true;
}
/**********************************************************************************************/
const wchar_t* ja2xp::CExportSTI::commandString = L"sti";
void ja2xp::CExportSTI::handleCommand(CExportSTI::param_list_t const& params)
{
bool opt_Packed = true,
opt_ExportOffsets = false,
opt_OnePng = false,
opt_Rgba = false;
param_list_t vfs_params;
param_list_t::const_iterator cit = params.begin();
for(; cit != params.end(); ++cit)
{
if( vfs::StrCmp::Equal(*cit, L"-unpack") )
{
opt_Packed = false;
}
else if( vfs::StrCmp::Equal(*cit, L"-offsets") )
{
opt_ExportOffsets = true;
}
else if( vfs::StrCmp::Equal(*cit, L"-onepng") )
{
opt_OnePng = true;
}
else if( vfs::StrCmp::Equal(*cit, L"-rgba") )
{
opt_Rgba = true;
}
else
{
vfs_params.push_back(*cit);
}
}
ja2xp::InitVFS& vfs = ja2xp::InitVFS::instance();
vfs.checkParameters(vfs_params);
if(!vfs.init())
{
return;
}
try
{
convertSTItoJPC(vfs.srcPattern(), vfs.dstPattern(), opt_Packed, opt_ExportOffsets, opt_OnePng, opt_Rgba);
}
catch(vfs::Exception& msg)
{
std::wcout << msg.getLastEntryString().c_wcs() << std::endl;
}
}
void ja2xp::CExportSTI::printHelp()
{
std::wcout
<< L" convert STI image file(s) to a series of png images (as 7z archive)" << std::endl
<< L" * if \"destination\" is a directory, then the filename's extension will be" << std::endl
<< L" replaced with \".jpc.7z\"" << std::endl
<< std::endl
<< L" options :" << std::endl
<< L" -unpack : if set, no 7z archive will be created. Instead," << std::endl
<< L" for an image 'path/image.sti',subimages will be" << std::endl
<< L" written into the directory \"path/image/.\"" << std::endl
<< L" -offsets : offsets of all subimages will we written in the" << std::endl
<< L" \"appdata.xml\" file" << std::endl
<< L" -onepng : creates one png image instead of a jpc.7z archive." << std::endl
<< L" If there are multiple subimages, only the first one" << std::endl
<< L" will be converted." << std::endl;
}
+30
View File
@@ -0,0 +1,30 @@
#ifndef _EXPORT_STI_H_
#define _EXPORT_STI_H_
#include <vfs/Core/vfs_path.h>
#include <vfs/Core/Interface/vfs_file_interface.h>
#include <exporter_base.h>
namespace ja2xp
{
class CExportSTI : public IExporterBase
{
public:
typedef IExporterBase::param_list_t param_list_t;
static const wchar_t* commandString;// = L"sti";
virtual void handleCommand(param_list_t const& params);
virtual void printHelp();
};
bool convertSTItoJPC(vfs::tReadableFile *pFile, vfs::tWritableFile *pOutFile, bool bOffsets, bool rgba);
bool convertSTItoJPC(vfs::tReadableFile *pFile, vfs::Path const base_out_path, bool bOffsets, bool rgba);
bool convertSTItoPNG(vfs::tReadableFile *pFile, vfs::tWritableFile *pOutFile, bool rgba);
bool convertSTItoJPC(vfs::Path const& sSrc, vfs::Path const& sDst,
bool bPacked=true, bool bOffsets=false, bool bOnePng=false, bool rgba=false);
};
#endif // _EXPORT_STI_H_
@@ -0,0 +1,554 @@
#include "stci_image_utils.h"
#include "himage.h"
#include <cassert>
const int iCOMPRESS_TRANSPARENT = 0x80;
const int iCOMPRESS_RUN_MASK = 0x7F;
UINT32 ja2xp::UnpackETRLEImageToBuffer(UINT8 *pBuffer, image_type *pImage, UINT16 usETRLEIndex)
{
if(!pImage || !pBuffer)
{
return 0;
}
ETRLEObject *pETRLEObject = &(pImage->pETRLEObject[usETRLEIndex]);
if(!pETRLEObject)
{
return 0;
}
UINT8 *pCurrent;
pCurrent = &((UINT8 *)pImage->pPixData8)[pETRLEObject->uiDataOffset];
unsigned int uiImageSize = pETRLEObject->usHeight * pETRLEObject->usWidth;
unsigned int uiBufferPos = 0;
unsigned char ubCount;
while(uiBufferPos < uiImageSize)
{
ubCount = *pCurrent & iCOMPRESS_RUN_MASK;
if(*pCurrent & iCOMPRESS_TRANSPARENT)
{
pCurrent++;
uiBufferPos += ubCount;
}
else
{
pCurrent++;
memcpy(&pBuffer[uiBufferPos], pCurrent, ubCount);
pCurrent += ubCount;
uiBufferPos += ubCount;
}
}
return uiBufferPos;
}
UINT32 ja2xp::UnpackETRLEImageToRGBABuffer(UINT8 *pBuffer, image_type *pImage, UINT16 usETRLEIndex)
{
if(!pImage || !pBuffer)
{
return 0;
}
ETRLEObject *pETRLEObject = &(pImage->pETRLEObject[usETRLEIndex]);
if(!pETRLEObject)
{
return 0;
}
SGPPaletteEntry* palette = pImage->pPalette;
if(!palette)
{
return 0;
}
UINT8 *pCurrent;
pCurrent = &((UINT8 *)pImage->pPixData8)[pETRLEObject->uiDataOffset];
unsigned int uiImageSize = pETRLEObject->usHeight * pETRLEObject->usWidth;
unsigned int uiBufferPos = 0;
unsigned char ubCount;
while(uiBufferPos < (4*uiImageSize))
{
ubCount = *pCurrent & iCOMPRESS_RUN_MASK;
if(*pCurrent & iCOMPRESS_TRANSPARENT)
{
pCurrent++;
uiBufferPos += 4 * (int)ubCount;
pBuffer += 4 * (int)ubCount;
}
else
{
pCurrent++;
int count = ubCount;
while(count--)
{
UINT8 cur = *pCurrent++;
*pBuffer++ = palette[cur].peRed;
*pBuffer++ = palette[cur].peGreen;
*pBuffer++ = palette[cur].peBlue;
*pBuffer++ = 255; // alpha
}
uiBufferPos += 4 * (int)ubCount;
}
}
return uiBufferPos;
}
ja2xp::CIndexedSTIImage::CIndexedSTIImage()
{
memset(&_header, 0, sizeof(STCIHeader));
}
ja2xp::CIndexedSTIImage::~CIndexedSTIImage()
{
if(_palette)
{
delete[] _palette;
}
for(unsigned int i=0; i < _compressed_images.size(); ++i)
{
delete[] _compressed_images[i];
}
}
bool ja2xp::CIndexedSTIImage::SetPalette(SGPPaletteEntry *pPal, int iSize)
{
if(iSize < 0 ||iSize > 1024)
{
return false;
}
_pal_size = iSize;
_palette = new STCIPaletteElement[iSize];
for(int i=0; i<iSize;++i)
{
_palette[i].ubBlue = pPal[i].peBlue;
_palette[i].ubGreen = pPal[i].peGreen;
_palette[i].ubRed = pPal[i].peRed;
}
return true;
}
bool ja2xp::CIndexedSTIImage::AddCompressedImage(UINT8 *data, UINT32 data_size, UINT32 image_width, UINT32 image_height, INT32 image_offset_x, INT32 image_offset_y)
{
if(!data || (data_size < 0) )
{
return false;
}
STCISubImage subimage;
subimage.sOffsetX = image_offset_x;
subimage.sOffsetY = image_offset_y;
subimage.usWidth = image_width;
subimage.usHeight = image_height;
UINT8 *compressed = new UINT8[data_size];
memcpy(compressed,data,data_size);
subimage.uiDataLength = data_size;
_header.uiStoredSize += data_size;
_images.push_back(subimage);
_compressed_images.push_back(compressed);
_header.uiOriginalSize += image_width * image_height;
_header.Indexed.usNumberOfSubImages += 1;
return true;
}
bool ja2xp::CIndexedSTIImage::AddImage(UINT8 *data, UINT32 data_size, UINT32 image_width, UINT32 image_height, INT32 image_offset_x, INT32 image_offset_y, UINT8 *original_compressed, UINT32 iriginal_compressed_size)
{
if(!data || (data_size != image_width*image_height) )
{
return false;
}
STCISubImage subimage;
subimage.sOffsetX = image_offset_x;
subimage.sOffsetY = image_offset_y;
subimage.usWidth = image_width;
subimage.usHeight = image_height;
UINT8 *compressed = new UINT8[2*data_size];
UINT8 *compressed_start = compressed;
memset(compressed,0,data_size);
UINT32 compressed_size = 0;
unsigned int uiBufferPos = 0;
bool bZeroRun = false;
UINT8 uiRunLength = 0;
UINT8 *uiRunStartPosition = data;
if(*data == 0)
{
bZeroRun = true;
}
bool done = false;
UINT32 scanline = 0;
while(!done)
{
if(bZeroRun)
{
while((*data == 0) && (uiRunLength < 128) && (uiBufferPos < data_size) && (scanline < image_width))
{
data++;
uiRunLength++;
uiBufferPos++;
scanline++;
}
uiRunStartPosition = compressed;
*compressed++ = uiRunLength | iCOMPRESS_TRANSPARENT;
compressed_size += 1;
}
else
{
uiRunStartPosition = compressed++;
while((*data != 0) && (uiRunLength < 128) && (uiBufferPos < data_size) && (scanline < image_width))
{
*compressed++ = *data++;
uiRunLength++;
uiBufferPos++;
scanline++;
}
*uiRunStartPosition = uiRunLength;
compressed_size += uiRunLength+1;
}
// prepare next run
uiRunLength = 0;
bZeroRun = (*data != 0) ? false : true;
if(scanline == image_width)
{
scanline = 0;
// "close" scanline with a zero
*compressed++ = 0;
compressed_size += 1;
}
if(uiBufferPos >= data_size)
{
done = true;
}
}
subimage.uiDataLength = compressed_size;
_header.uiStoredSize += compressed_size;
_images.push_back(subimage);
_compressed_images.push_back(compressed_start);
_header.uiOriginalSize += data_size;
_header.Indexed.usNumberOfSubImages += 1;
return true;
}
bool ja2xp::CIndexedSTIImage::WriteImage(vfs::tWritableFile* pFile)
{
if(!pFile || !pFile->openWrite())
{
return false;
}
strncpy((char*)&(_header.cID[0]),"STCI",4);
_header.uiOriginalSize = _compressed_images.size() * 640 * 480;
//_header.uiStoredSize += 64 + 768 + _header.Indexed.usNumberOfSubImages*16; // equal to uiOriginalSize if data uncompressed
_header.uiTransparentValue = 0;
_header.fFlags = STCI_ETRLE_COMPRESSED | STCI_INDEXED | STCI_TRANSPARENT;
_header.usHeight = 480;
_header.usWidth = 640;
_header.ubDepth = 8;
_header.uiAppDataSize = _compressed_images.size() * 16;
_header.Indexed.ubRedDepth = 8;
_header.Indexed.ubGreenDepth = 8;
_header.Indexed.ubBlueDepth = 8;
_header.Indexed.uiNumberOfColours = 256;
_header.Indexed.usNumberOfSubImages = _compressed_images.size();
pFile->write((vfs::Byte*)&_header,STCI_HEADER_SIZE);
pFile->write((vfs::Byte*)_palette,_pal_size*sizeof(STCIPaletteElement));
UINT32 offset=0;
// write sub-image headers
for(unsigned int i=0; i<_images.size(); ++i)
{
_images[i].uiDataOffset = offset;
pFile->write((vfs::Byte*)&_images[i],STCI_SUBIMAGE_SIZE);
offset += _images[i].uiDataLength;
}
// write sub-images
for(unsigned int i=0; i<_compressed_images.size(); ++i)
{
pFile->write((vfs::Byte*)_compressed_images[i],_images[i].uiDataLength);
}
// write application data
int frames = _compressed_images.size()/8; // 8 = number of directions
for(unsigned int i=0; i<_compressed_images.size(); ++i)
{
AuxObjectData aod;
memset(&aod,0,sizeof(AuxObjectData));
if((frames+1) % (i+1) == 0)
{
aod.ubNumberOfFrames = frames;
aod.fFlags = AUX_ANIMATED_TILE;
}
pFile->write((vfs::Byte*)&aod,sizeof(AuxObjectData));
}
pFile->close();
return true;
}
bool ja2xp::CIndexedSTIImage::WriteToHIMAGE(HIMAGE pImage)
{
if(!pImage)
{
return false;
}
pImage->usNumberOfObjects = _compressed_images.size();
pImage->usWidth = 640;
pImage->usHeight = 480;
pImage->ubBitDepth = 8;
pImage->fFlags = STCI_ETRLE_COMPRESSED | STCI_INDEXED | STCI_TRANSPARENT;;
strncat(pImage->ImageFile,"test",4);
pImage->iFileLoader = -1;
pImage->pui16BPPPalette = NULL;
pImage->pPalette = new SGPPaletteEntry[256];
for(int j=0; j<256; ++j)
{
pImage->pPalette[j].peRed = _palette[j].ubRed;
pImage->pPalette[j].peGreen = _palette[j].ubGreen;
pImage->pPalette[j].peBlue = _palette[j].ubBlue;
pImage->pPalette[j].peFlags = 0;
}
pImage->pETRLEObject = new ETRLEObject[pImage->usNumberOfObjects];
UINT32 offset=0; // == size
for(unsigned int i=0; i<_images.size(); ++i)
{
pImage->pETRLEObject[i].sOffsetX = _images[i].sOffsetX;
pImage->pETRLEObject[i].sOffsetY = _images[i].sOffsetY;
pImage->pETRLEObject[i].usHeight = _images[i].usHeight;
pImage->pETRLEObject[i].usWidth = _images[i].usWidth;
pImage->pETRLEObject[i].uiDataOffset = offset;
pImage->pETRLEObject[i].uiDataLength = _images[i].uiDataLength;
offset += _images[i].uiDataLength;
}
pImage->uiSizePixData = offset;
pImage->pPixData8 = new UINT8[offset];
// write sub-images
for(unsigned int i=0; i<_compressed_images.size(); ++i)
{
memcpy(
&pImage->pPixData8[pImage->pETRLEObject[i].uiDataOffset],
_compressed_images[i],
pImage->pETRLEObject[i].uiDataLength);
}
pImage->uiAppDataSize = pImage->usNumberOfObjects * sizeof(AuxObjectData);
pImage->pAppData = (UINT8*)(new AuxObjectData[pImage->usNumberOfObjects]);
memset(pImage->pAppData,0,pImage->uiAppDataSize);
// write application data
int frames = _compressed_images.size()/8; // 8 = number of directions
for(unsigned int i=0; i<pImage->usNumberOfObjects; ++i)
{
if(i % frames == 0)
{
AuxObjectData &aod = *((AuxObjectData*)(&pImage->pAppData[i*sizeof(AuxObjectData)]));
aod.ubNumberOfFrames = frames;
aod.fFlags = AUX_ANIMATED_TILE;
}
}
return true;
}
//BOOLEAN GetETRLEPixelValue( UINT8 * pDest, HVOBJECT hVObject, UINT16 usETRLEIndex, UINT16 usX, UINT16 usY )
BOOLEAN ja2xp::GetETRLEPixelValue( UINT8 * pDest, image_type *hImage, UINT16 usETRLEIndex, UINT16 usX, UINT16 usY )
{
UINT8 * pCurrent;
UINT16 usLoopX = 0;
UINT16 usLoopY = 0;
UINT16 ubRunLength;
ETRLEObject * pETRLEObject;
// Do a bunch of checks
assert( hImage != NULL );
assert( usETRLEIndex < hImage->usNumberOfObjects );
pETRLEObject = &(hImage->pETRLEObject[usETRLEIndex]);
assert( usX < pETRLEObject->usWidth );
assert( usY < pETRLEObject->usHeight );
// Assuming everything's okay, go ahead and look...
pCurrent = &((UINT8 *)hImage->pPixData8)[pETRLEObject->uiDataOffset];
// Skip past all uninteresting scanlines
while( usLoopY < usY )
{
while( *pCurrent != 0 )
{
if (*pCurrent & iCOMPRESS_TRANSPARENT)
{
pCurrent++;
}
else
{
pCurrent += *pCurrent & iCOMPRESS_RUN_MASK;
}
}
usLoopY++;
}
// Now look in this scanline for the appropriate byte
do
{
ubRunLength = *pCurrent & iCOMPRESS_RUN_MASK;
if (*pCurrent & iCOMPRESS_TRANSPARENT)
{
if (usLoopX + ubRunLength >= usX)
{
*pDest = 0;
return( TRUE );
}
else
{
pCurrent++;
}
}
else
{
if (usLoopX + ubRunLength >= usX)
{
// skip to the correct byte; skip at least 1 to get past the byte defining the run
pCurrent += (usX - usLoopX) + 1;
*pDest = *pCurrent;
return( TRUE );
}
else
{
pCurrent += ubRunLength + 1;
}
}
usLoopX += ubRunLength;
}
while( usLoopX < usX );
// huh???
return( FALSE );
}
/*
BOOLEAN Blt8BPPDataTo8BPPBuffer( UINT8 *pBuffer, UINT32 uiDestPitchBYTES, image_type *hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex )
{
static UINT32 uiOffset;
static UINT32 usHeight, usWidth;
static UINT8 *SrcPtr, *DestPtr;
static UINT32 LineSkip;
static ETRLEObject *pTrav;
static INT32 iTempX, iTempY;
// Assertions
Assert( hSrcVObject != NULL );
Assert( pBuffer != NULL );
// Get Offsets from Index into structure
pTrav = &(hSrcVObject->pETRLEObject[ usIndex ] );
usHeight = (UINT32)pTrav->usHeight;
usWidth = (UINT32)pTrav->usWidth;
uiOffset = pTrav->uiDataOffset;
// Add to start position of dest buffer
iTempX = iX + pTrav->sOffsetX;
iTempY = iY + pTrav->sOffsetY;
// Validations
CHECKF( iTempX >= 0 );
CHECKF( iTempY >= 0 );
SrcPtr= (UINT8 *)hSrcVObject->pPixData8 + uiOffset;
DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*iTempY) + (iTempX);
LineSkip=(uiDestPitchBYTES-(usWidth));
__asm {
mov esi, SrcPtr
mov edi, DestPtr
xor eax, eax
xor ebx, ebx
xor ecx, ecx
BlitDispatch:
mov cl, [esi]
inc esi
or cl, cl
js BlitTransparent
jz BlitDoneLine
//BlitNonTransLoop:
clc
rcr cl, 1
jnc BlitNTL2
movsb
BlitNTL2:
clc
rcr cl, 1
jnc BlitNTL3
movsw
BlitNTL3:
or cl, cl
jz BlitDispatch
xor ebx, ebx
//BlitNTL4:
rep movsd
jmp BlitDispatch
BlitTransparent:
and ecx, 07fH
xor al, al
rep stosb
jmp BlitDispatch
BlitDoneLine:
dec usHeight
jz BlitDone
add edi, LineSkip
jmp BlitDispatch
BlitDone:
}
return(TRUE);
}
*/
@@ -0,0 +1,51 @@
#ifndef _STCI_IMAGE_UTILS_H_
#define _STCI_IMAGE_UTILS_H_
#include "Types.h"
#include "himage.h"
#include <vfs/Core/vfs_types.h>
#include <vfs/Core/File/vfs_file.h>
#include <vector>
namespace ja2xp
{
class CIndexedSTIImage
{
public:
CIndexedSTIImage();
~CIndexedSTIImage();
bool SetPalette(SGPPaletteEntry *pPal, int iSize);
bool AddImage(UINT8 *data, UINT32 data_size, UINT32 image_width, UINT32 image_height, INT32 image_offset_x, INT32 image_offset_y, UINT8 *original_compressed=NULL, UINT32 iriginal_compressed_size=0);
bool AddCompressedImage(UINT8 *data, UINT32 data_size, UINT32 image_width, UINT32 image_height, INT32 image_offset_x, INT32 image_offset_y);
bool WriteImage(vfs::tWritableFile* pFile);
bool WriteToHIMAGE(HIMAGE pImage);
private:
STCIHeader _header;
STCIPaletteElement *_palette;
int _pal_size;
std::vector<STCISubImage> _images;
std::vector<UINT8*> _compressed_images;
};
void SplitSTIImage(vfs::String const&, vfs::String &file, vfs::String &ext);
/**
* BUG: this function gives wrong results
*/
BOOLEAN GetETRLEPixelValue( UINT8 * pDest, image_type *hImage, UINT16 usETRLEIndex, UINT16 usX, UINT16 usY );
UINT32 UnpackETRLEImageToBuffer(UINT8 *pBuffer, image_type *pImage, UINT16 ueETRLEIndex);
UINT32 UnpackETRLEImageToRGBABuffer(UINT8 *pBuffer, image_type *pImage, UINT16 ueETRLEIndex);
/**
* NOTE: implemented in msvc inline assembler
* does not work with gcc -> use 'UnpackETRLEImageToBuffer'
*/
BOOLEAN Blt8BPPDataTo8BPPBuffer( UINT8 *pBuffer, UINT32 uiDestPitchBYTES, image_type *hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex );
};
#endif // _STCI_IMAGE_UTILS_H_