ja2export is not vendored, we own that + fix errors

stop lying about it by keeping it in ext/
fix three errors in clang-cl
This commit is contained in:
Marco Antonio J. Costa
2026-07-27 13:07:29 -03:00
committed by majcosta
parent fc1c1dfe77
commit fd47a422b5
30 changed files with 6 additions and 6 deletions
+29
View File
@@ -0,0 +1,29 @@
option(BUILD_JA2EXPORT "Build the Ja2Export tool." ON)
if(BUILD_JA2EXPORT)
message(STATUS "Configuring Ja2Export")
add_executable(Ja2Export
init_vfs.cpp
main.cpp
progress_bar.cpp
ja2/himage.cpp
ja2/XMLWriter.cpp
export/jsd/export_jsd.cpp
export/jsd/structure.cpp
export/slf/export_slf.cpp
export/sti/export_sti.cpp
export/sti/Image.cpp
export/sti/stci_image_utils.cpp
export/sti/STCI_lib.cpp
)
target_include_directories(Ja2Export PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}"
)
target_link_libraries(Ja2Export PUBLIC bfVFS libpng)
set_target_properties(Ja2Export PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)
else()
message(STATUS "BUILD_JA2EXPORT set to \"OFF\", not configuring Ja2Export")
endif()
+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()()).c_str());
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 = vfs::String(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_
+554
View File
@@ -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);
}
*/
+46
View File
@@ -0,0 +1,46 @@
#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);
};
#endif // _STCI_IMAGE_UTILS_H_
+19
View File
@@ -0,0 +1,19 @@
#ifndef _EXPORTER_BASE_H_
#define _EXPORTER_BASE_H_
#include <list>
#include <string>
namespace ja2xp
{
class IExporterBase
{
public:
typedef std::list<std::wstring> param_list_t;
virtual void handleCommand(std::list<std::wstring> const& params) = 0;
virtual void printHelp() = 0;
};
};
#endif // _EXPORTER_BASE_H_
+211
View File
@@ -0,0 +1,211 @@
#include <init_vfs.h>
#include <vfs/Core/vfs_os_functions.h>
#include <vfs/Core/vfs_init.h>
#include <vfs/Tools/vfs_property_container.h>
#include <stack>
#include <iostream>
ja2xp::InitVFS::InitVFS()
{
}
ja2xp::InitVFS& ja2xp::InitVFS::instance()
{
static ja2xp::InitVFS singleton;
return singleton;
}
void ja2xp::InitVFS::checkParameters(ja2xp::IExporterBase::param_list_t const& params)
{
ja2xp::IExporterBase::param_list_t::const_iterator cit = params.begin();
for(; cit != params.end(); ++cit)
{
if( vfs::StrCmp::Equal(*cit, L"-lib") )
{
this->src_lib = true;
cit++;
if(cit != params.end())
{
// get library path
this->src_path = vfs::Path(*cit);
this->has_src = true;
cit++;
if(cit != params.end())
{
this->src_pattern = vfs::Path(*cit);
continue;
}
}
std::wcout << L"error " << std::endl;
}
else if( vfs::StrCmp::Equal(*cit, L"-create_dst") )
{
this->dst_create = true;
continue;
}
else if(!cit->empty() && cit->at(0) == L'-')
{
//ignore unknown options
continue;
}
if(!this->has_src)
{
this->src_path = vfs::Path(*cit);
this->has_src = true;
}
else if(this->has_src && !this->has_dst)
{
this->dst_path = vfs::Path(*cit);
this->has_dst = true;
}
}
}
static void SplitPath(vfs::Path const& path, vfs::Path& root, vfs::Path& pattern)
{
vfs::String::str_t sSrc = path();
if(sSrc.empty())
{
return;
}
// remove enclosing ""
if(sSrc.at(0) == L'\"' && sSrc.at(sSrc.length()-1) == L'\"')
{
sSrc = sSrc.substr(1,sSrc.length()-2);
}
// has * in path
size_t pos = sSrc.find_first_of(L"*");
if(pos != std::wstring::npos)
{
vfs::Path temp_root, temp_pattern;
// get directory
vfs::Path temp(sSrc.substr(0,pos+1));
temp.splitLast(temp_root, temp_pattern);
// correct pattern
temp_pattern = vfs::Path(temp_pattern.c_wcs() + sSrc.substr(pos+1,sSrc.length()-pos-1));
root = vfs::Path(temp_root);
pattern = vfs::Path(temp_pattern);
}
else
{
path.splitLast(root,pattern);
}
}
//bool InitVFS(vfs::Path const& sSrcPath, vfs::Path const& sDstPath,
// vfs::Path& src_pattern, vfs::Path& dst_pattern,
// bool bSourceAsLib, bool bCreateDstDirectory)
bool ja2xp::InitVFS::init()
{
if( !this->has_src || !this->has_dst )
{
return false;
}
vfs::Path src_root, dst_root;
if( this->src_pattern.empty() && !this->src_lib )
{
SplitPath(this->src_path, src_root, this->src_pattern);
if(src_root.empty()) src_root = L".";
}
else
{
src_root = this->src_path;
}
SplitPath(this->dst_path, dst_root, this->dst_pattern);
if(dst_root.empty()) dst_root = L".";
vfs::String ext_test;
if(!this->dst_pattern.extension(ext_test))
{
// output pattern has no extension and is probably not a directory name
dst_root += this->dst_pattern;
this->dst_pattern = L".";
}
if(!this->src_lib && !vfs::OS::checkRealDirectory(src_root))
{
std::wcout << L"Source directory \"" << src_root() << L"\" does not exist" << std::endl;
return false;
}
if(!vfs::OS::checkRealDirectory(dst_root))
{
if(!this->dst_create)
{
std::wcout << L"Destination directory \"" << dst_root() << L"\" does not exist" << std::endl;
return false;
}
std::stack<vfs::Path> dirs;
vfs::Path left = dst_root, right, temp;
while(!left.empty() && !vfs::OS::checkRealDirectory(left))
{
dirs.push(left);
left.splitLast(temp,right);
left = temp;
}
while(!dirs.empty())
{
if(!vfs::OS::createRealDirectory(dirs.top()))
{
std::wcout << L"Could not create directory \"" << dirs.top().c_wcs() << std::endl;
return false;
}
dirs.pop();
}
}
vfs_init::Location src_loc;
if(this->src_lib)
{
src_loc.m_type = L"library";
}
else
{
src_loc.m_type = L"directory";
}
src_loc.m_path = src_root;
vfs_init::Profile src_prof;
src_prof.m_name = L"Source";
src_prof.addLocation(&src_loc);
vfs_init::Location dst_loc;
dst_loc.m_type = L"directory";
dst_loc.m_path = dst_root;
vfs_init::Profile dst_prof;
dst_prof.m_name = L"Destination";
dst_prof.addLocation(&dst_loc);
dst_prof.m_writable = true;
vfs_init::VfsConfig conf;
conf.addProfile(&src_prof);
conf.addProfile(&dst_prof);
try
{
vfs_init::initVirtualFileSystem(conf);
}
catch(vfs::Exception& ex)
{
std::wcout << ex.m_CallStack.front().message.c_wcs() << std::endl;
return false;
}
return true;
}
vfs::Path const& ja2xp::InitVFS::srcPattern()
{
return this->src_pattern;
}
vfs::Path const& ja2xp::InitVFS::dstPattern()
{
return this->dst_pattern;
}
+33
View File
@@ -0,0 +1,33 @@
#ifndef _INIT_VFS_H_
#define _INIT_VFS_H_
#include <vfs/Core/vfs_path.h>
#include <exporter_base.h>
namespace ja2xp
{
class InitVFS
{
public:
static InitVFS& instance();
void checkParameters(IExporterBase::param_list_t const& params);
bool init();
vfs::Path const& srcPattern();
vfs::Path const& dstPattern();
private:
InitVFS();
bool has_src, has_dst;
bool src_lib, dst_create;
vfs::Path src_path, dst_path;
vfs::Path src_pattern, dst_pattern;
};
}
//bool InitVFS(vfs::Path const& sSrcPath, vfs::Path const& sDstPath,
// vfs::Path& src_pattern, vfs::Path& dst_pattern,
// bool bSourceAsLib, bool bCreateDstDirectory);
#endif // _INIT_VFS_H_
+243
View File
@@ -0,0 +1,243 @@
#ifndef __STRUCTURE_INTERNAL_H
#define __STRUCTURE_INTERNAL_H
//
// If you wish to use the structure database functions, include
// structure_extern.h, not structure.h!
//
#include "types.h"
#include "himage.h"
// A few words about the overall structure scheme:
//
// Large structures are split into multiple sections,
// one for each tile.
//
// Each section is treated as a separate object,
// except that it does NOT record information about
// hit points, but instead stores a pointer to the
// base object (section).
//
// Each section has a line of sight profile. These
// profiles are split into 5 in each horizontal direction
// and 4 vertically, forming 100 "cubes". In real
// world terms, each section represents a volume
// with a height of 8 feet (and width and length
// of what?)
//
// It is important to note that the vertical
// position of each section is measured in individual
// cubes (rather than, as it were, groups of 4 vertical
// cubes)
#define PROFILE_X_SIZE 5
#define PROFILE_Y_SIZE 5
#define PROFILE_Z_SIZE 4
// these values should be compared for less than rather than less
// than or equal to
#define STRUCTURE_ON_GROUND 0
#define STRUCTURE_ON_ROOF PROFILE_Z_SIZE
#define STRUCTURE_ON_GROUND_MAX PROFILE_Z_SIZE
#define STRUCTURE_ON_ROOF_MAX PROFILE_Z_SIZE * 2
typedef UINT8 PROFILE[PROFILE_X_SIZE][PROFILE_Y_SIZE];
extern UINT8 AtHeight[PROFILE_Z_SIZE];
// MAP_ELEMENT may get later:
// PROFILE * CombinedLOSProfile;
// PROFILE * CombinedProtectionProfile;
//
// LEVELNODE gets a pointer to a STRUCTURE or
// a union between its soldier pointer and a
// STRUCTURE pointer
// if (fFlags & STRUCTURE_BASE_TILE)
// then the structure is the "base" of the object
// and its hitpoint value is the one for the object
//
// vv generic flags for all structures
// vvv type flags
//
// how to handle explodable structures
// NOT used in DB structures!
#define STRUCTURE_BASE_TILE 0x00000001
#define STRUCTURE_OPEN 0x00000002
#define STRUCTURE_OPENABLE 0x00000004
// synonyms for STRUCTURE_OPENABLE
#define STRUCTURE_CLOSEABLE 0x00000004
#define STRUCTURE_SEARCHABLE 0x00000004
#define STRUCTURE_HIDDEN 0x00000008
#define STRUCTURE_MOBILE 0x00000010
// STRUCTURE_PASSABLE is set for each structure instance where
// the tile flag TILE_PASSABLE is set
#define STRUCTURE_PASSABLE 0x00000020
#define STRUCTURE_EXPLOSIVE 0x00000040
#define STRUCTURE_TRANSPARENT 0x00000080
#define STRUCTURE_GENERIC 0x00000100
#define STRUCTURE_TREE 0x00000200
#define STRUCTURE_FENCE 0x00000400
#define STRUCTURE_WIREFENCE 0x00000800
#define STRUCTURE_HASITEMONTOP 0x00001000 // ATE: HASITEM: struct has item on top of it
#define STRUCTURE_SPECIAL 0x00002000
#define STRUCTURE_LIGHTSOURCE 0x00004000
#define STRUCTURE_VEHICLE 0x00008000
#define STRUCTURE_WALL 0x00010000
#define STRUCTURE_WALLNWINDOW 0x00020000
#define STRUCTURE_SLIDINGDOOR 0x00040000
#define STRUCTURE_DOOR 0x00080000
// a "multi" structure (as opposed to multitiled) is composed of multiple graphics & structures
#define STRUCTURE_MULTI 0x00100000
#define STRUCTURE_CAVEWALL 0x00200000
#define STRUCTURE_DDOOR_LEFT 0x00400000
#define STRUCTURE_DDOOR_RIGHT 0x00800000
#define STRUCTURE_NORMAL_ROOF 0x01000000
#define STRUCTURE_SLANTED_ROOF 0x02000000
#define STRUCTURE_TALL_ROOF 0x04000000
#define STRUCTURE_SWITCH 0x08000000
#define STRUCTURE_ON_LEFT_WALL 0x10000000
#define STRUCTURE_ON_RIGHT_WALL 0x20000000
#define STRUCTURE_CORPSE 0x40000000
#define STRUCTURE_PERSON 0x80000000
// COMBINATION FLAGS
#define STRUCTURE_ANYFENCE 0x00000C00
#define STRUCTURE_ANYDOOR 0x00CC0000
#define STRUCTURE_OBSTACLE 0x00008F00
#define STRUCTURE_WALLSTUFF 0x00CF0000
#define STRUCTURE_BLOCKSMOVES 0x00208F00
#define STRUCTURE_TYPE_DEFINED 0x8FEF8F00
#define STRUCTURE_ROOF 0x07000000
#define TILE_ON_ROOF 0x01
#define TILE_PASSABLE 0x02
typedef struct TAG_STRUCTURE_TILE
{
INT16 sPosRelToBase; // "single-axis"
INT8 bXPosRelToBase;
INT8 bYPosRelToBase;
PROFILE Shape; // 25 bytes
UINT8 fFlags;
UINT8 ubVehicleHitLocation;
BYTE bUnused[1];
} DB_STRUCTURE_TILE; // 32 bytes
#define BASE_TILE 0
#define NO_PARTNER_STRUCTURE 0
typedef struct TAG_DB_STRUCTURE
{
UINT8 ubArmour;
UINT8 ubHitPoints;
UINT8 ubDensity;
UINT8 ubNumberOfTiles;
UINT32 fFlags;
UINT16 usStructureNumber;
UINT8 ubWallOrientation;
INT8 bDestructionPartner; // >0 = debris number (bDP - 1), <0 = partner graphic
INT8 bPartnerDelta; // opened/closed version, etc... 0 for unused
INT8 bZTileOffsetX;
INT8 bZTileOffsetY;
BYTE bUnused[1];
} DB_STRUCTURE; // 16 bytes
typedef struct TAG_DB_STRUCTURE_REF
{
DB_STRUCTURE * pDBStructure;
DB_STRUCTURE_TILE ** ppTile; // dynamic array
} DB_STRUCTURE_REF; // 8 bytes
//dnl ch46 031009
typedef struct TAG_STRUCTURE
{
struct TAG_STRUCTURE* pPrev;
struct TAG_STRUCTURE* pNext;
DB_STRUCTURE_REF* pDBStructureRef;
PROFILE* pShape;
UINT32 fFlags;// need to have something to indicate base tile/not
INT32 sGridNo;
union
{
struct
{
UINT8 ubHitPoints;
UINT8 ubLockStrength;
};
INT32 sBaseGridNo;
};
UINT16 usStructureID;
INT16 sCubeOffset;// height of bottom of object in profile "cubes"
UINT8 ubWallOrientation;
UINT8 ubVehicleHitLocation;
UINT8 ubStructureHeight;// if 0, then unset; otherwise stores height of structure when last calculated
UINT8 ubUnused;
}STRUCTURE;// 36 bytes
typedef struct TAG_STRUCTURE_FILE_REF
{
struct TAG_STRUCTURE_FILE_REF * pPrev;
struct TAG_STRUCTURE_FILE_REF * pNext;
AuxObjectData * pAuxData;
RelTileLoc * pTileLocData;
UINT8 * pubStructureData;
DB_STRUCTURE_REF * pDBStructureRef; // dynamic array
UINT16 usNumberOfStructures;
UINT16 usNumberOfStructuresStored;
} STRUCTURE_FILE_REF; // 24 bytes
// IMPORTANT THING TO REMEMBER
//
// Although the number of structures and images about which information
// may be stored in a file, the two are stored very differently.
//
// The structure data stored amounts to a sparse array, with no data
// saved for any structures that are not defined.
//
// For image information, however, an array is stored with every entry
// filled regardless of whether there is non-zero data defined for
// that graphic!
typedef struct TAG_STRUCTURE_FILE_HEADER
{
CHAR8 szId[4];
union
{
//struct
//{
UINT16 usNumberOfStructures;
//};
//struct
//{
UINT16 usNumberOfImages;
//};
};
UINT16 usNumberOfStructuresStored;
UINT16 usStructureDataSize;
UINT8 fFlags;
UINT8 bUnused[3];
UINT16 usNumberOfImageTileLocsStored;
} STRUCTURE_FILE_HEADER; // 16 bytes
// "J2SD" = Jagged 2 Structure Data
#define STRUCTURE_FILE_ID "J2SD"
#define STRUCTURE_FILE_ID_LEN 4
#define STRUCTURE_SCRIPT_FILE_EXTENSION "JSS"
#define STRUCTURE_FILE_EXTENSION "JSD"
#define STRUCTURE_FILE_CONTAINS_AUXIMAGEDATA 0x01
#define STRUCTURE_FILE_CONTAINS_STRUCTUREDATA 0x02
#endif
+175
View File
@@ -0,0 +1,175 @@
#include "XMLWriter.h"
#include <vfs/Core/vfs_file_raii.h>
#include <vfs/Core/File/vfs_file.h>
#include <iostream>
void XMLWriter::addValue(vfs::String const& key)
{
m_ssBuffer << indent() << "<" << key.utf8();
insertAttributesIntoBuffer();
m_ssBuffer << " />\n";
}
void XMLWriter::addComment(vfs::String const& comment)
{
m_ssBuffer << indent() << "<!-- " << comment.utf8() << " -->\n";
}
void XMLWriter::addFlag(UINT32 const& flags, UINT32 const& flag, vfs::String strFlag)
{
if( ( flags & flag) == flag )
{
this->addValue(strFlag);
}
}
void XMLWriter::openNode(vfs::String const& key)
{
std::string utf8key = key.utf8();
m_ssBuffer << indent() << "<" << utf8key;
insertAttributesIntoBuffer();
m_ssBuffer << ">\n";
m_iIndentLevel += 1;
m_stOpenNodes.push(utf8key);
}
bool XMLWriter::closeNode()
{
if(m_iIndentLevel < 1)
{
// there is nothing to close
return false;
}
if(m_stOpenNodes.empty())
{
return false;
}
m_iIndentLevel -= 1;
m_ssBuffer << indent() << "</" << m_stOpenNodes.top() << ">\n";
m_stOpenNodes.pop();
return true;
}
bool XMLWriter::writeToFile(vfs::Path const& sFileName)
{
try
{
vfs::COpenWriteFile file(sFileName,true,true);
return writeToFile( &file.file() );
}
catch(vfs::Exception& ex)
{
std::wcout << ex.getExceptionString() << std::endl;
vfs::CFile file(sFileName);
if(file.openWrite(true,true))
{
return writeToFile(vfs::tWritableFile::cast(&file));
}
}
return false;
}
bool XMLWriter::writeToFile(vfs::tWritableFile* pFile)
{
try
{
vfs::COpenWriteFile file(pFile);
const std::string str = m_ssBuffer.str();
pFile->write(str.c_str(), str.length() * sizeof(std::string::value_type));
return true;
}
catch(vfs::Exception& ex)
{
std::wcout << ex.getLastEntryString() << std::endl;
return false;
}
}
std::string XMLWriter::indent()
{
std::string indent_string;
for(int i=0; i < m_iIndentLevel; ++i)
{
indent_string += "\t";
}
return indent_string;
}
void XMLWriter::insertAttributesIntoBuffer()
{
if(!m_stNextValAttributes.empty())
{
std::vector<attribute_type>::iterator it = m_stNextValAttributes.begin();
for(; it != m_stNextValAttributes.end(); ++it)
{
m_ssBuffer << " " << it->first << "=\"" << it->second << "\"";
}
}
m_stNextValAttributes.clear();
}
std::string XMLWriter::handleSpecialCharacters(std::string const& str)
{
std::stringstream ss;
unsigned int current = 0, old = 0;
while( current < str.length() )
{
char const& c = str.at(current);
if( c == '&' )
{
ss << str.substr(old, current-old) << "&amp;";
old = current + 1;
}
else if( c == '<' )
{
ss << str.substr(old, current-old) << "&lt;";
old = current + 1;
}
else if( c == '>' )
{
ss << str.substr(old, current-old) << "&gt;";
old = current + 1;
}
else if( c == '\"' )
{
ss << str.substr(old, current-old) << "&quot;";
old = current + 1;
}
else if( c == '\'' )
{
ss << str.substr(old, current-old) << "&apos;";
old = current + 1;
}
current++;
}
if(old)
{
ss << str.substr(old, current-old);
return ss.str();
}
return str;
}
void testMXLWriter()
{
//XMLWriter<char> xmlw;
XMLWriter xmlw;
//xmlw.openNode(L"root");
xmlw.openNode("root");
xmlw.addAttributeToNextValue("attr1",10);
xmlw.addAttributeToNextValue("attr2","string");
//xmlw.AddValue(L"val1",10);
xmlw.addValue("val1",10);
xmlw.addAttributeToNextValue("node_attr",17);
xmlw.addComment("bbb -->\n <a> comment</a> <!-- aaa");
xmlw.openNode("test");
//xmlw.addValue(L"val2",10.5);
xmlw.addValue("val2",10.5);
xmlw.closeNode();
xmlw.closeNode();
//xmlw.WriteToFile(WideString("xml_output/test.xml")());
xmlw.writeToFile("xml_output/test.xml");
}
+75
View File
@@ -0,0 +1,75 @@
#ifndef _XMLWRITER_H_
#define _XMLWRITER_H_
#include <vfs/Core/Interface/vfs_file_interface.h>
#include <vfs/Core/vfs_string.h>
#include <stack>
#include <string>
#include <sstream>
#include <vector>
class XMLWriter
{
public:
typedef std::pair<std::string, std::string> attribute_type;
public:
XMLWriter() : m_iIndentLevel(0)
{
m_ssBuffer << "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" ;
};
~XMLWriter()
{};
template<typename ValueType>
void addAttributeToNextValue(vfs::String const& attribute, ValueType const& value)
{
std::stringstream temp_buffer;
temp_buffer << value;
m_stNextValAttributes.push_back( attribute_type(attribute.utf8(),temp_buffer.str()) );
}
template<typename ValueType>
void addValue(vfs::String const& key, ValueType const& value)
{
std::string utf8key = key.utf8();
m_ssBuffer << indent() << "<" << utf8key;
insertAttributesIntoBuffer();
m_ssBuffer << ">" << value << "</" << utf8key << ">\n";
}
template<>
void addValue<std::string>(vfs::String const& key, std::string const& value)
{
std::string utf8key = key.utf8();
m_ssBuffer << indent() << "<" << utf8key;
insertAttributesIntoBuffer();
m_ssBuffer << ">" << handleSpecialCharacters(value) << "</" << utf8key << ">\n";
}
void addValue(vfs::String const& key);
void addComment(vfs::String const& comment);
void addFlag(vfs::UInt32 const& flags, vfs::UInt32 const& flag, vfs::String strFlag);
void openNode(vfs::String const& key);
bool closeNode();
bool writeToFile(vfs::Path const& sFileName);
bool writeToFile(vfs::tWritableFile* pFile);
private:
std::string indent();
std::string handleSpecialCharacters(std::string const& str);
void insertAttributesIntoBuffer();
private:
std::stringstream m_ssBuffer;
std::stack<std::string> m_stOpenNodes;
std::vector<attribute_type> m_stNextValAttributes;
int m_iIndentLevel;
};
void testMXLWriter();
#endif // _XMLWRITER_H_
+217
View File
@@ -0,0 +1,217 @@
#include <cmath>
#include <cstdlib>
#include "types.h"
#include "string.h"
#include "himage.h"
// This is the color substituted to keep a 24bpp->16bpp color
// from going transparent (0x0000) -- DB
#define BLACK_SUBSTITUTE 0x0001
//UINT16 gusAlphaMask = 0;
//UINT16 gusRedMask = 0;
//UINT16 gusGreenMask = 0;
//UINT16 gusBlueMask = 0;
//INT16 gusRedShift = 0;
//INT16 gusBlueShift = 0;
//INT16 gusGreenShift = 0;
UINT16 gusAlphaMask = 0;
UINT16 gusRedMask = 0xF800;
UINT16 gusGreenMask = 0x07E0;
UINT16 gusBlueMask = 0x001F;
INT16 gusRedShift = 8;
INT16 gusBlueShift = -3;
INT16 gusGreenShift = 3;
// this funky union is used for fast 16-bit pixel format conversions
union SplitUINT32
{
struct
{
UINT16 usLower;
UINT16 usHigher;
};
UINT32 uiValue;
};
// Convert from RGB to 16 bit value
UINT16 Get16BPPColor( UINT32 RGBValue )
{
UINT16 r16, g16, b16, usColor = 0;
UINT8 r,g,b;
r = SGPGetRValue( RGBValue );
g = SGPGetGValue( RGBValue );
b = SGPGetBValue( RGBValue );
if(gusRedShift < 0)
r16=((UINT16)r>>abs(gusRedShift));
else
r16=((UINT16)r<<gusRedShift);
if(gusGreenShift < 0)
g16=((UINT16)g>>abs(gusGreenShift));
else
g16=((UINT16)g<<gusGreenShift);
if(gusBlueShift < 0)
b16=((UINT16)b>>abs(gusBlueShift));
else
b16=((UINT16)b<<gusBlueShift);
usColor=(r16&gusRedMask)|(g16&gusGreenMask)|(b16&gusBlueMask);
// if our color worked out to absolute black, and the original wasn't
// absolute black, convert it to a VERY dark grey to avoid transparency
// problems
if(usColor==0)
{
if(RGBValue!=0)
usColor=BLACK_SUBSTITUTE | gusAlphaMask;
}
else
usColor |= gusAlphaMask;
return(usColor);
}
// Convert from 16 BPP to RGBvalue
UINT32 GetRGBColor( UINT16 Value16BPP )
{
UINT16 r16, g16, b16;
UINT32 r,g,b,val;
r16 = Value16BPP & gusRedMask;
g16 = Value16BPP & gusGreenMask;
b16 = Value16BPP & gusBlueMask;
if(gusRedShift < 0)
r=((UINT32)r16<<abs(gusRedShift));
else
r=((UINT32)r16>>gusRedShift);
if(gusGreenShift < 0)
g=((UINT32)g16<<abs(gusGreenShift));
else
g=((UINT32)g16>>gusGreenShift);
if(gusBlueShift < 0)
b=((UINT32)b16<<abs(gusBlueShift));
else
b=((UINT32)b16>>gusBlueShift);
r &= 0x000000ff;
g &= 0x000000ff;
b &= 0x000000ff;
val = FROMRGB(r,g,b);
return(val);
}
void ConvertRGBDistribution565To555( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
{
UINT16 * pPixel;
UINT32 uiLoop;
SplitUINT32 Pixel;
pPixel = p16BPPData;
for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
{
// If the pixel is completely black, don't bother converting it -- DB
if(*pPixel!=0)
{
// we put the 16 pixel bits in the UPPER word of uiPixel, so that we can
// right shift the blue value (at the bottom) into the LOWER word to protect it
Pixel.usHigher = *pPixel;
Pixel.uiValue >>= 5;
// get rid of the least significant bit of green
Pixel.usHigher >>= 1;
// now shift back into the upper word
Pixel.uiValue <<= 5;
// and copy back
*pPixel = Pixel.usHigher | gusAlphaMask;
}
pPixel++;
}
}
void ConvertRGBDistribution565To655( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
{
UINT16 * pPixel;
UINT32 uiLoop;
SplitUINT32 Pixel;
pPixel = p16BPPData;
for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
{
// we put the 16 pixel bits in the UPPER word of uiPixel, so that we can
// right shift the blue value (at the bottom) into the LOWER word to protect it
Pixel.usHigher = *pPixel;
Pixel.uiValue >>= 5;
// get rid of the least significant bit of green
Pixel.usHigher >>= 1;
// shift to the right some more...
Pixel.uiValue >>= 5;
// so we can left-shift the red value alone to give it an extra bit
Pixel.usHigher <<= 1;
// now shift back and copy
Pixel.uiValue <<= 10;
*pPixel = Pixel.usHigher;
pPixel++;
}
}
void ConvertRGBDistribution565To556( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
{
UINT16 * pPixel;
UINT32 uiLoop;
SplitUINT32 Pixel;
pPixel = p16BPPData;
for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
{
// we put the 16 pixel bits in the UPPER word of uiPixel, so that we can
// right shift the blue value (at the bottom) into the LOWER word to protect it
Pixel.usHigher = *pPixel;
Pixel.uiValue >>= 5;
// get rid of the least significant bit of green
Pixel.usHigher >>= 1;
// shift back into the upper word
Pixel.uiValue <<= 5;
// give blue an extra bit (blank in the least significant spot)
Pixel.usHigher <<= 1;
// copy back
*pPixel = Pixel.usHigher;
pPixel++;
}
}
void ConvertRGBDistribution565ToAny( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
{
UINT16 * pPixel;
UINT32 uiRed, uiGreen, uiBlue, uiTemp, uiLoop;
pPixel = p16BPPData;
for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
{
// put the 565 RGB 16-bit value into a 32-bit RGB value
uiRed = (*pPixel) >> 11;
uiGreen = (*pPixel & 0x07E0) >> 5;
uiBlue = (*pPixel & 0x001F);
uiTemp = FROMRGB(uiRed,uiGreen,uiBlue);
// then convert the 32-bit RGB value to whatever 16 bit format is used
*pPixel = Get16BPPColor( uiTemp );
pPixel++;
}
}
+206
View File
@@ -0,0 +1,206 @@
#ifndef __IMAGE_H
#define __IMAGE_H
#include "imgfmt.h"
#define FROMRGB(r, g ,b) ((UINT32) (((UINT8) (r) | ((UINT16) (g) << 8)) | (((UINT32) (UINT8) (b)) << 16)))
// The HIMAGE module provides a common interface for managing image data. This module
// includes:
// - A set of data structures representing image data. Data can be 8 or 16 bpp and/or
// compressed
// - A set of file loaders which load specific file formats into the internal data format
// - A set of blitters which blt the data to memory
// - A comprehensive automatic blitter which blits the appropriate type based on the
// image header.
// Defines for type of file readers
#define PCX_FILE_READER 0x1
#define TGA_FILE_READER 0x2
#define STCI_FILE_READER 0x4
#define TRLE_FILE_READER 0x8
#define UNKNOWN_FILE_READER 0x200
// Defines for buffer bit depth
#define BUFFER_8BPP 0x1
#define BUFFER_16BPP 0x2
// Defines for image charactoristics
#define IMAGE_COMPRESSED 0x0001
#define IMAGE_TRLECOMPRESSED 0x0002
#define IMAGE_PALETTE 0x0004
#define IMAGE_BITMAPDATA 0x0008
#define IMAGE_APPDATA 0x0010
#define IMAGE_ALLIMAGEDATA 0x000C
#define IMAGE_ALLDATA 0x001C
// Palette structure, mimics that of Win32
typedef struct tagSGPPaletteEntry
{
UINT8 peRed;
UINT8 peGreen;
UINT8 peBlue;
UINT8 peFlags;
} SGPPaletteEntry;
#define AUX_FULL_TILE 0x01
#define AUX_ANIMATED_TILE 0x02
#define AUX_DYNAMIC_TILE 0x04
#define AUX_INTERACTIVE_TILE 0x08
#define AUX_IGNORES_HEIGHT 0x10
#define AUX_USES_LAND_Z 0x20
typedef struct
{
UINT8 ubWallOrientation;
UINT8 ubNumberOfTiles;
UINT16 usTileLocIndex;
UINT8 ubUnused1[3];
UINT8 ubCurrentFrame;
UINT8 ubNumberOfFrames;
UINT8 fFlags;
UINT8 ubUnused[6];
} AuxObjectData;
typedef struct
{
INT8 bTileOffsetX;
INT8 bTileOffsetY;
} RelTileLoc; // relative tile location
// TRLE subimage structure, mirroring that of ST(C)I
typedef struct tagETRLEObject
{
UINT32 uiDataOffset;
UINT32 uiDataLength;
INT16 sOffsetX;
INT16 sOffsetY;
UINT16 usHeight;
UINT16 usWidth;
} ETRLEObject;
typedef struct tagETRLEData
{
PTR pPixData;
UINT32 uiSizePixData;
ETRLEObject * pETRLEObject;
UINT16 usNumberOfObjects;
} ETRLEData;
// Image header structure
typedef struct
{
UINT16 usWidth;
UINT16 usHeight;
UINT8 ubBitDepth;
UINT16 fFlags;
SGPFILENAME ImageFile;
UINT32 iFileLoader;
SGPPaletteEntry * pPalette;
UINT16 * pui16BPPPalette;
UINT8 * pAppData;
UINT32 uiAppDataSize;
// This union is used to describe each data type and is flexible to include the
// data strucutre of the compresssed format, once developed.
union
{
PTR pImageData;
PTR pCompressedImageData;
UINT8* p8BPPData;
UINT16* p16BPPData;
struct
{
UINT8* pPixData8;
UINT32 uiSizePixData;
ETRLEObject* pETRLEObject;
UINT16 usNumberOfObjects;
};
};
} image_type, *HIMAGE;
#define SGPGetRValue(rgb) ((BYTE) (rgb))
#define SGPGetBValue(rgb) ((BYTE) ((rgb) >> 16))
#define SGPGetGValue(rgb) ((BYTE) (((UINT16) (rgb)) >> 8))
// *****************************************************************************
//
// Function prototypes
//
// *****************************************************************************
#ifdef __cplusplus
extern "C" {
#endif
// This function will return NULL if it fails, and call SetLastError() to set
// error information
HIMAGE CreateImage( SGPFILENAME ImageFile, UINT16 fContents );
// This function destroys the HIMAGE structure as well as its contents
BOOLEAN DestroyImage( HIMAGE hImage );
// This function releases data allocated to various parts of the image based
// on the contents flags passed as a parameter. If a contents flag is given
// and the image does not contain that data, no error is raised
BOOLEAN ReleaseImageData( HIMAGE hImage, UINT16 fContents );
// This function will attept to Load data from an existing image object's filename
// In this way, dynamic loading of image data can be done
BOOLEAN LoadImageData( HIMAGE hImage, UINT16 fContents );
// This function will run the appropriate copy function based on the type of HIMAGE object
BOOLEAN CopyImageToBuffer( HIMAGE hImage, UINT32 fBufferType, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect );
// The following blitters are used by the function above as well as clients
#ifndef NO_ZLIB_COMPRESSION
BOOLEAN Copy8BPPCompressedImageTo8BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect );
BOOLEAN Copy8BPPCompressedImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect );
BOOLEAN Copy16BPPCompressedImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect );
// This function will extract a compressed image into a non-compressed buffer
BOOLEAN Extract8BPPCompressedImageToBuffer( HIMAGE hImage, BYTE *pDestBuf );
BOOLEAN Extract16BPPCompressedImageToBuffer( HIMAGE hImage, BYTE *pDestBuf );
#endif
BOOLEAN Copy8BPPImageTo8BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect );
BOOLEAN Copy8BPPImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect );
BOOLEAN Copy16BPPImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect );
// This function will create a buffer in memory of ETRLE data, excluding palette
BOOLEAN GetETRLEImageData( HIMAGE hImage, ETRLEData *pBuffer );
// UTILITY FUNCTIONS
// Used to create a 16BPP Palette from an 8 bit palette, found in himage.c
UINT16 *Create16BPPPaletteShaded( SGPPaletteEntry *pPalette, UINT32 rscale, UINT32 gscale, UINT32 bscale, BOOLEAN mono);
UINT16 *Create16BPPPalette( SGPPaletteEntry *pPalette );
UINT16 Get16BPPColor( UINT32 RGBValue );
UINT32 GetRGBColor( UINT16 Value16BPP );
SGPPaletteEntry *ConvertRGBToPaletteEntry(UINT8 sbStart, UINT8 sbEnd, UINT8 *pOldPalette);
extern UINT16 gusAlphaMask;
extern UINT16 gusRedMask;
extern UINT16 gusGreenMask;
extern UINT16 gusBlueMask;
extern INT16 gusRedShift;
extern INT16 gusBlueShift;
extern INT16 gusGreenShift;
// used to convert 565 RGB data into different bit-formats
void ConvertRGBDistribution565To555( UINT16 * p16BPPData, UINT32 uiNumberOfPixels );
void ConvertRGBDistribution565To655( UINT16 * p16BPPData, UINT32 uiNumberOfPixels );
void ConvertRGBDistribution565To556( UINT16 * p16BPPData, UINT32 uiNumberOfPixels );
void ConvertRGBDistribution565ToAny( UINT16 * p16BPPData, UINT32 uiNumberOfPixels );
#ifdef __cplusplus
}
#endif
#endif
+92
View File
@@ -0,0 +1,92 @@
#if !defined( STCI_H )
#define STCI_H
// Sir-Tech's Crazy Image (STCI) file format specifications. Each file is composed of:
// 1 ImageFileHeader, uncompressed
// * Palette (STCI_INDEXED, size = uiNumberOfColours * PALETTE_ELEMENT_SIZE), uncompressed
// * SubRectInfo's (usNumberOfRects > 0, size = usNumberOfSubRects * sizeof(SubRectInfo) ), uncompressed
// * Bytes of image data, possibly compressed
#include "types.h"
#define STCI_ID_STRING "STCI"
#define STCI_ID_LEN 4
#define STCI_ETRLE_COMPRESSED 0x0020
#define STCI_ZLIB_COMPRESSED 0x0010
#define STCI_INDEXED 0x0008
#define STCI_RGB 0x0004
#define STCI_ALPHA 0x0002
#define STCI_TRANSPARENT 0x0001
// ETRLE defines
#define COMPRESS_TRANSPARENT 0x80
#define COMPRESS_NON_TRANSPARENT 0x00
#define COMPRESS_RUN_LIMIT 0x7F
// NB if you're going to change the header definition:
// - make sure that everything in this header is nicely aligned
// - don't exceed the 64-byte maximum
typedef struct
{
UINT8 cID[STCI_ID_LEN];
UINT32 uiOriginalSize;
UINT32 uiStoredSize; // equal to uiOriginalSize if data uncompressed
UINT32 uiTransparentValue;
UINT32 fFlags;
UINT16 usHeight;
UINT16 usWidth;
union
{
struct
{
UINT32 uiRedMask;
UINT32 uiGreenMask;
UINT32 uiBlueMask;
UINT32 uiAlphaMask;
UINT8 ubRedDepth;
UINT8 ubGreenDepth;
UINT8 ubBlueDepth;
UINT8 ubAlphaDepth;
} RGB;
struct
{ // For indexed files, the palette will contain 3 separate bytes for red, green, and blue
UINT32 uiNumberOfColours;
UINT16 usNumberOfSubImages;
UINT8 ubRedDepth;
UINT8 ubGreenDepth;
UINT8 ubBlueDepth;
UINT8 cIndexedUnused[11];
} Indexed;
};
UINT8 ubDepth; // size in bits of one pixel as stored in the file
UINT32 uiAppDataSize;
UINT8 cUnused[15];
} STCIHeader;
#define STCI_HEADER_SIZE 64
typedef struct
{
UINT32 uiDataOffset;
UINT32 uiDataLength;
INT16 sOffsetX;
INT16 sOffsetY;
UINT16 usHeight;
UINT16 usWidth;
} STCISubImage;
#define STCI_SUBIMAGE_SIZE 16
typedef struct
{
UINT8 ubRed;
UINT8 ubGreen;
UINT8 ubBlue;
} STCIPaletteElement;
#define STCI_PALETTE_ELEMENT_SIZE 3
#define STCI_8BIT_PALETTE_SIZE 768
#endif
+83
View File
@@ -0,0 +1,83 @@
#ifndef _SGP_AUTO_MEMORY_H_
#define _SGP_AUTO_MEMORY_H_
namespace sgp
{
/************************************************************/
template<typename T>
class TAutoArray
{
public:
T& operator[](unsigned int index)
{
return _array[index];
}
T* operator()()
{
return _array;
}
T& operator*()
{
return *_array;
}
bool operator!()
{
// NULL == _array
return !_array;
}
T* release()
{
T* tmp = _array;
_array = NULL;
return tmp;
}
protected:
T* _array;
};
/************************************************************/
template<typename T>
class AutoArray : public TAutoArray<T>
{
public:
AutoArray(unsigned int size)
{
_array = new T[size];
}
~AutoArray()
{
if(_array)
{
delete[] _array;
}
}
};
/************************************************************/
template<typename T, typename void*(*Alloc)(size_t) = malloc, typename void(*Dealloc)(void*) = free>
class AutoCArray : public TAutoArray<T>
{
public:
AutoCArray(unsigned int size = 1)
{
_array = (T*)Alloc( size * sizeof(T) );
}
~AutoCArray()
{
if(_array)
{
Dealloc(_array);
}
}
};
/************************************************************/
} // namespace sgp
#endif // _SGP_AUTO_MEMORY_H_
+103
View File
@@ -0,0 +1,103 @@
#ifndef __TYPES_
#define __TYPES_
#include <wchar.h> // for wide-character strings
// *** SIR-TECH TYPE DEFINITIONS ***
// These two types are defined by VC6 and were causing redefinition
// problems, but JA2 is compiled with VC5
// HEY WIZARDRY DUDES, JA2 ISN'T THE ONLY PROGRAM WE COMPILE! :-)
typedef unsigned int UINT32;
typedef signed int INT32;
// integers
typedef unsigned char UINT8;
typedef signed char INT8;
typedef unsigned short UINT16;
typedef signed short INT16;
// floats
typedef float FLOAT;
typedef double DOUBLE;
// strings
typedef char CHAR8;
typedef wchar_t CHAR16;
typedef CHAR8 * STR;
typedef CHAR8 * STR8;
typedef CHAR16 * STR16;
// flags (individual bits used)
typedef unsigned char FLAGS8;
typedef unsigned short FLAGS16;
typedef unsigned long FLAGS32;
// other
typedef unsigned char BOOLEAN;
typedef void * PTR;
typedef unsigned short HNDL;
typedef UINT8 BYTE;
typedef CHAR8 STRING512[512];
typedef UINT32 HWFILE;
#define SGPFILENAME_LEN 100
typedef CHAR8 SGPFILENAME[SGPFILENAME_LEN];
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define BAD_INDEX -1
#define NULL_HANDLE 65535
#define PI 3.1415926
#ifndef NULL
#define NULL 0
#endif
typedef struct
{
INT32 iLeft;
INT32 iTop;
INT32 iRight;
INT32 iBottom;
} SGPRect;
typedef struct
{
INT32 iX;
INT32 iY;
} SGPPoint;
typedef struct
{
INT32 Min;
INT32 Max;
} SGPRange;
typedef FLOAT VECTOR2[2]; // 2d vector (2x1 matrix)
typedef FLOAT VECTOR3[3]; // 3d vector (3x1 matrix)
typedef FLOAT VECTOR4[4]; // 4d vector (4x1 matrix)
typedef INT32 IVECTOR2[2]; // 2d vector (2x1 matrix)
typedef INT32 IVECTOR3[3]; // 3d vector (3x1 matrix)
typedef INT32 IVECTOR4[4]; // 4d vector (4x1 matrix)
typedef VECTOR3 MATRIX3[3]; // 3x3 matrix
typedef VECTOR4 MATRIX4[4]; // 4x4 matrix
//typedef VECTOR3 ANGLE; // angle return array //lal removed
typedef VECTOR4 COLOR; // rgba color array
#endif
+115
View File
@@ -0,0 +1,115 @@
#include <iostream>
#include <map>
#include <export/sti/export_sti.h>
#include <export/slf/export_slf.h>
#include <export/jsd/export_jsd.h>
#include <exporter_base.h>
static const char* VERSION_STRING = "1.1.1";
typedef std::map<vfs::String, ja2xp::IExporterBase*, vfs::String::Less> CommandMap_t;
CommandMap_t g_command_map;
class HelpCommand : public ja2xp::IExporterBase
{
public:
typedef ja2xp::IExporterBase::param_list_t param_list_t;
static const wchar_t* commandString;// = L"help";
virtual void handleCommand(param_list_t const& params)
{
param_list_t::const_iterator cit = params.begin();
for(; cit != params.end(); ++cit)
{
CommandMap_t::const_iterator comm_it = g_command_map.find(*cit);
if(comm_it != g_command_map.end())
{
this->printBasicUsage();
comm_it->second->printHelp();
return;
}
}
this->printBasicUsage();
this->printHelp();
}
void printBasicUsage()
{
std::wcout
<< L"*** ja2export : version " << VERSION_STRING << " ***" << std::endl
<< std::endl
<< L"Usage : ja2export command [OPTIONS] source destination" << std::endl
<< std::endl
<< L" converts file(s) specified by \"source\" and outputs according to filename" << std::endl
<< L" specified by \"destination\"" << std::endl
<< std::endl;
}
virtual void printHelp()
{
std::wcout
<< L" * if \"source\" is a file pattern with the wildcard *, then all files that" << std::endl
<< L" match this pattern will be converted" << std::endl
<< L" * if \"destination\" is a file name, the converted file will take exactly " << std::endl
<< L" this name" << std::endl
<< L" * if \"destination\" is a directory name, then the converted file will be" << std::endl
<< L" written in this directory and its extension will be modified according" << std::endl
<< L" to the command specification" << std::endl
<< std::endl
<< L" commands :" << std::endl
<< L" help : print this message, use help [command] to print specific help message" << std::endl
<< L" sti : convert STI image file(s) to a series of png images in a 7z archive" << std::endl
<< L" slf : convert SLF archive(s) to uncompressed 7z archive(s)" << std::endl
<< L" jsd : convert JSD file(s) to XML file(s)" << std::endl
<< std::endl
<< L" options :" << std::endl
<< L" -create_dst : creates destination directory if it doesn't exist" << std::endl
<< L" -lib : when set, the next two paramers are treated as" << std::endl
<< L" 'source path' and 'source file pattern'" << std::endl;
}
};
const wchar_t* HelpCommand::commandString = L"help";
int wmain(int argc, wchar_t **argv)
{
std::list<std::wstring> param_list;
argv++;
while(*argv)
{
param_list.push_back(*argv++);
};
auto cmd_help{ std::make_unique<HelpCommand>() };
g_command_map[HelpCommand::commandString] = cmd_help.get();
auto cmd_sti{ std::make_unique<ja2xp::CExportSTI>() };
g_command_map[ja2xp::CExportSTI::commandString] = cmd_sti.get();
auto cmd_slf{ std::make_unique<ja2xp::CExportSLF>() };
g_command_map[ja2xp::CExportSLF::commandString] = cmd_slf.get();
auto cmd_jsd{ std::make_unique<ja2xp::CExportJSD>() };
g_command_map[ja2xp::CExportJSD::commandString] = cmd_jsd.get();
if(!param_list.empty())
{
ja2xp::IExporterBase* command = g_command_map[param_list.front()];
if(command)
{
std::list<std::wstring> command_params(++param_list.begin(), param_list.end());
command->handleCommand(command_params);
return 1;
}
else
{
std::wcout << L"Unknown command \"" << param_list.front() << "\"";
return 0;
}
}
cmd_help->printBasicUsage();
cmd_help->printHelp();
return 1;
}
+32
View File
@@ -0,0 +1,32 @@
#include <progress_bar.h>
ja2xp::ProgressBar::ProgressBar(int size, int numElements)
: iSIZE(size), num_elements(numElements), count(0)
{
empty_str.resize(iSIZE);
for(int i=0; i<iSIZE; ++i)
{
empty_str[i] = L' ';
}
};
void ja2xp::ProgressBar::Next(vfs::String const& message)
{
count++;
float percent = (float)count/float(num_elements);
wchar_t bar[21] = L" ";
int bar_end = (int)(20*percent);
bar_end = std::min<int>(20,bar_end);
for(int i=0; i < bar_end; ++i)
{
bar[i] = L'=';
}
std::vector<wchar_t> infoZ(iSIZE+1);
std::wstring str = message.c_wcs();
int start = std::min<int>(iSIZE,(int)str.length());
wcsncpy(&infoZ[0],str.c_str(),start);
memcpy(&infoZ[start],&empty_str[0],(iSIZE-start)*sizeof(wchar_t));
infoZ[iSIZE] = 0;
wprintf(L"\r[%.20s] - %.54s", bar, &infoZ[0]);
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef _PROGRESSBAR_H_
#define _PROGRESSBAR_H_
#include <vector>
#include <vfs/Core/vfs_string.h>
namespace ja2xp
{
class ProgressBar
{
public:
ProgressBar(int size, int numElements);
void Next(vfs::String const& message);
private:
const int iSIZE;
const int num_elements;
int count;
std::vector<wchar_t> empty_str;
};
};
#endif // _PROGRESSBAR_H_