mirror of
https://github.com/1dot13/source.git
synced 2026-08-12 14:10:23 +02:00
- 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:
@@ -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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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_
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 );
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
Reference in New Issue
Block a user