Example #1
0
PakFileHandle * PakReader::open(const res::path & name) {
	
	PakFile * f = getFile(name);
	if(!f) {
		return NULL;
	}
	
	return f->open();
}
Example #2
0
bool initLocalisation() {
	
	LogDebug("Starting localization");
	
	localisation.clear();
	
	PakFile * file;
	
	if(config.language.empty()) {
		file = autodetectLanguage();
	} else {
		
		LogInfo << "Using language from config file: " << config.language;
		
		// Attempt to load localisation for the configured language.
		std::string filename = "localisation/utext_" + config.language + ".ini";
		file = resources->getFile(filename);
		
		if(!file) {
			LogWarning << "Localisation file " << filename << " not found, autodetecting language.";
			/*
			 * TODO we might want to keep the old config.language setting as there could be
			 * localized audio for that language even if there is no localized text.
			 */
			file = autodetectLanguage();
		}
	}
	
	if(!file) {
		return false;
	}
	
	arx_assert(!config.language.empty());
	
	char * data = file->readAlloc();
	if(!data) {
		return false;
	}
	
	LogDebug("Loaded localisation file of size " << file->size());
	std::string out = util::convertUTF16LEToUTF8(data, data + file->size());
	LogDebug("Converted to UTF8 string of length " << out.size());
	
	if(!out.empty()) {
		LogDebug("Preparing to parse localisation file");
		std::istringstream iss(out);
		if(!::localisation.read(iss)) {
			LogWarning << "Error parsing localisation file localisation/utext_"
			           << config.language << ".ini";
		}
	}
	
	free(data);
	
	return true;
}
Example #3
0
char * PakReader::readAlloc(const res::path & name, size_t & sizeRead) {
	
	PakFile * f = getFile(name);
	if(!f) {
		return NULL;
	}
	
	sizeRead = f->size();
	
	return f->readAlloc();
}
Example #4
0
bool PakReader::read(const res::path & name, void * buf) {
	
	PakFile * f = getFile(name);
	if(!f) {
		return false;
	}
	
	f->read(buf);
	
	return true;
}
Example #5
0
void MiniMap::loadOffsets(PakReader *pakRes) {
	
	std::string iniMiniOffsets = "graph/levels/mini_offsets.ini";
	
	PakFile *file = pakRes->getFile(iniMiniOffsets.c_str());
	
	if(!file) {
		LogError << "Missing " << iniMiniOffsets;
		return;
	}
	
	size_t fileSize = file->size();
	char *dat = new char[fileSize + 2];
	dat[fileSize + 1] = '\0';
	
	file->read(dat);
	
	if(dat) {
		
		size_t pos = 0;
		
		for(int i = 0; i < 29; i++) { // Why 29?
			
			char t[512];
			int nRead = sscanf(dat + pos, "%s %f %f", t, &m_miniOffsetX[i], &m_miniOffsetY[i]);
			
			if(nRead != 3) {
				LogError << "Error parsing line " << i << " of mini_offsets.ini: read " << nRead;
			}
			
			while((pos < fileSize) && (dat[pos] != '\n')) {
				pos++;
			}
			
			pos++;
			
			if(pos >= fileSize) {
				break;
			}
		}
		
		delete[] dat;
	}
	
	m_miniOffsetX[0] = 0;
	m_miniOffsetY[0] = -0.5;
	m_miniOffsetX[1] = 0;
	m_miniOffsetY[1] = 0;
	m_miniOffsetX[14] = 130;
	m_miniOffsetY[14] = 0;
	m_miniOffsetX[15] = 31;
	m_miniOffsetY[15] = -3.5;
}
Example #6
0
void Resources::openPackage(const Common::String &fileName) {
	debugC(1, kDebugResource, "openPackage(%s)", fileName.c_str());

	Common::File file;
	bool opened = file.open(fileName);

	if (!opened)
		return;

	PakFile *pakFile = new PakFile();
	pakFile->open(&file, fileName);

	file.close();

	_pakFiles.push_back(pakFile);
}
static void dump(PakDirectory & dir, const fs::path & dirname = fs::path()) {
	
	if(!fs::create_directories(dirname)) {
		LogWarning << "Failed to create target directory";
	}
	
	for(PakDirectory::files_iterator i = dir.files_begin(); i != dir.files_end(); ++i) {
		
		fs::path filenameISO = dirname / i->first;
		
		PakFile * file = i->second;
		
#if ARX_PLATFORM == ARX_PLATFORM_WIN32
		std::string filename = filenameISO.string();
#else
		std::string filename = util::convert<util::ISO_8859_1, util::UTF8>(filenameISO.string().c_str());
#endif
		
		printf("%s\n", filename.c_str());
		
		fs::ofstream ofs(filename, fs::fstream::out | fs::fstream::binary | fs::fstream::trunc);
		if(!ofs.is_open()) {
			printf("error opening file for writing: %s\n", filename.c_str());
			exit(1);
		}
		
		if(file->size() > 0) {
			
			char * data = (char*)file->readAlloc();
			arx_assert(data != NULL);
			
			if(ofs.write(data, file->size()).fail()) {
				printf("error writing to file: %s\n", filename.c_str());
				exit(1);
			}
			
			free(data);
			
		}
		
	}
	
	for(PakDirectory::dirs_iterator i = dir.dirs_begin(); i != dir.dirs_end(); ++i) {
		dump(i->second, dirname / i->first);
	}
	
}
Example #8
0
void dump(PakDirectory & dir, const fs::path & dirname = fs::path()) {
	
	fs::create_directories(dirname);
	
	for(PakDirectory::files_iterator i = dir.files_begin(); i != dir.files_end(); ++i) {
		
		fs::path filename = dirname / i->first;
		
		PakFile * file = i->second;
		
		printf("%s\n", filename.string().c_str());
		
		fs::ofstream ofs(filename, fs::fstream::out | fs::fstream::binary | fs::fstream::trunc);
		if(!ofs.is_open()) {
			printf("error opening file for writing: %s\n", filename.string().c_str());
			exit(1);
		}
		
		if(file->size() > 0) {
			
			char * data = (char*)file->readAlloc();
			arx_assert(data != NULL);
			
			if(ofs.write(data, file->size()).fail()) {
				printf("error writing to file: %s\n", filename.string().c_str());
				exit(1);
			}
			
			free(data);
			
		}
		
	}
	
	for(PakDirectory::dirs_iterator i = dir.dirs_begin(); i != dir.dirs_end(); ++i) {
		dump(i->second, dirname / i->first);
	}
	
}
Example #9
0
EERIE_3DOBJ * ARX_FTL_Load(const res::path & file) {
	
	// Creates FTL file name
	res::path filename = (res::path("game") / file).set_ext("ftl");
	
	// Checks for FTL file existence
	PakFile * pf = resources->getFile(filename);
	if(!pf) {
		return NULL;
	}
	
	size_t compressedSize = 0;
	char * compressedData = MCache_Pop(filename, compressedSize);
	LogDebug("File name check " << filename);
	
	bool NOrelease = true;
	if(!compressedData) {
		compressedData = pf->readAlloc();
		compressedSize = pf->size();
		NOrelease = MCache_Push(filename, compressedData, compressedSize) ? 1 : 0;
	}
	
	if(!compressedData) {
		LogError << "ARX_FTL_Load: error loading from PAK/cache " << filename;
		return NULL;
	}
	
	size_t allocsize; // The size of the data TODO size ignored
	char * dat = blastMemAlloc(compressedData, compressedSize, allocsize);
	if(!dat) {
		LogError << "ARX_FTL_Load: error decompressing " << filename;
		return NULL;
	}
	
	if(!NOrelease) {
		free(compressedData);
	}
	
	size_t pos = 0; // The position within the data
	
	// Pointer to Primary Header
	const ARX_FTL_PRIMARY_HEADER * afph = reinterpret_cast<const ARX_FTL_PRIMARY_HEADER *>(dat + pos);
	pos += sizeof(ARX_FTL_PRIMARY_HEADER);
	
	// Verify FTL file Signature
	if(afph->ident[0] != 'F' || afph->ident[1] != 'T' || afph->ident[2] != 'L') {
		LogError << "ARX_FTL_Load: wrong magic number in " << filename;
		free(dat);
		return NULL;
	}
	
	// Verify FTL file version
	if(afph->version != CURRENT_FTL_VERSION) {
		LogError << "ARX_FTL_Load: wring version " << afph->version << ", expected "
		         << CURRENT_FTL_VERSION << " in " << filename;
		free(dat);
		return NULL;
	}
	
	// Increases offset by checksum size
	pos += 512;
	
	// Pointer to Secondary Header
	const ARX_FTL_SECONDARY_HEADER * afsh;
	afsh = reinterpret_cast<const ARX_FTL_SECONDARY_HEADER *>(dat + pos);
	if(afsh->offset_3Ddata == -1) {
		LogError << "ARX_FTL_Load: error loading data from " << filename;
		free(dat);
		return NULL;
	}
	pos = afsh->offset_3Ddata;
	
	// Available from here in whole function
	EERIE_3DOBJ * obj = new EERIE_3DOBJ();
	
	const ARX_FTL_3D_DATA_HEADER * af3Ddh;
	af3Ddh = reinterpret_cast<const ARX_FTL_3D_DATA_HEADER *>(dat + pos);
	pos += sizeof(ARX_FTL_3D_DATA_HEADER);
	
	obj->vertexlist.resize(af3Ddh->nb_vertex);
	obj->facelist.resize(af3Ddh->nb_faces);
	obj->texturecontainer.resize(af3Ddh->nb_maps);
	obj->nbgroups = af3Ddh->nb_groups;
	obj->actionlist.resize(af3Ddh->nb_action);
	obj->selections.resize(af3Ddh->nb_selections);
	obj->origin = af3Ddh->origin;
	obj->file = res::path::load(safestring(af3Ddh->name));
	
	// Alloc'n'Copy vertices
	if(!obj->vertexlist.empty()) {
		
		// Copy the vertex data in
		for(size_t ii = 0; ii < obj->vertexlist.size(); ii++) {
			
			// Vertices stored as EERIE_OLD_VERTEX, copy in to new one
			obj->vertexlist[ii] = *reinterpret_cast<const EERIE_OLD_VERTEX *>(dat + pos);
			pos += sizeof(EERIE_OLD_VERTEX);
			
			obj->vertexlist[ii].vert.color = 0xFF000000;
		}
		
		// Set the origin point of the mesh
		obj->point0 = obj->vertexlist[obj->origin].v;
		
		obj->vertexlist3 = obj->vertexlist;
	}
	
	// Alloc'n'Copy faces
	if(!obj->facelist.empty()) {
		
		// Copy the face data in
		for(long ii = 0; ii < af3Ddh->nb_faces; ii++) {
			
			const EERIE_FACE_FTL * eff = reinterpret_cast<const EERIE_FACE_FTL*>(dat + pos);
			pos += sizeof(EERIE_FACE_FTL); 
			
			obj->facelist[ii].facetype = PolyType::load(eff->facetype);
			obj->facelist[ii].texid = eff->texid;
			obj->facelist[ii].transval = eff->transval;
			obj->facelist[ii].temp = eff->temp;
			obj->facelist[ii].norm = eff->norm;
			
			// Copy in all the texture and normals data
			BOOST_STATIC_ASSERT(IOPOLYVERT_FTL == IOPOLYVERT);
			for(size_t kk = 0; kk < IOPOLYVERT_FTL; kk++) {
				obj->facelist[ii].nrmls[kk] = eff->nrmls[kk];
				obj->facelist[ii].vid[kk] = eff->vid[kk];
				obj->facelist[ii].u[kk] = eff->u[kk];
				obj->facelist[ii].v[kk] = eff->v[kk];
				obj->facelist[ii].ou[kk] = eff->ou[kk];
				obj->facelist[ii].ov[kk] = eff->ov[kk];
			}
			
		}
	}
	
	// Alloc'n'Copy textures
	if(af3Ddh->nb_maps > 0) {
		
		// Copy in the texture containers
		for(long i = 0; i < af3Ddh->nb_maps; i++) {
			
			const Texture_Container_FTL * tex;
			tex = reinterpret_cast<const Texture_Container_FTL *>(dat + pos);
			pos += sizeof(Texture_Container_FTL);
			
			if(tex->name[0] == '\0') {
				// Some object files contain textures with empty names
				// Don't bother trying to load them as that will just generate an error message
				obj->texturecontainer[i] = NULL;
			} else {
				// Create the texture and put it in the container list
				res::path name = res::path::load(safestring(tex->name)).remove_ext();
				obj->texturecontainer[i] = TextureContainer::Load(name, TextureContainer::Level);
			}
		}
	}
	
	// Alloc'n'Copy groups
	if(obj->nbgroups > 0) {
		
		// Alloc the grouplists
		obj->grouplist = new EERIE_GROUPLIST[obj->nbgroups];
		
		// Copy in the grouplist data
		for(long i = 0 ; i < obj->nbgroups ; i++) {
			
			const EERIE_GROUPLIST_FTL* group = reinterpret_cast<const EERIE_GROUPLIST_FTL *>(dat + pos);
			pos += sizeof(EERIE_GROUPLIST_FTL);
			
			obj->grouplist[i].name = toLowercase(safestring(group->name));
			obj->grouplist[i].origin = group->origin;
			obj->grouplist[i].indexes.resize(group->nb_index);
			obj->grouplist[i].siz = group->siz;
			
		}
		
		// Copy in the group index data
		for(long i = 0; i < obj->nbgroups; i++) {
			if(!obj->grouplist[i].indexes.empty()) {
				size_t oldpos = pos;
				pos += sizeof(s32) * obj->grouplist[i].indexes.size(); // Advance to the next index block
				std::copy((const s32 *)(dat+oldpos), (const s32 *)(dat + pos), obj->grouplist[i].indexes.begin());
			}
		}
	}
	
	// Copy in the action points data
	for(size_t i = 0 ; i < obj->actionlist.size(); i++) {
		obj->actionlist[i] = *reinterpret_cast<const EERIE_ACTIONLIST_FTL *>(dat + pos);
		pos += sizeof(EERIE_ACTIONLIST_FTL);
	}
	
	// Copy in the selections data
	for(size_t i = 0 ; i < obj->selections.size(); i++) {
		
		const EERIE_SELECTIONS_FTL * selection = reinterpret_cast<const EERIE_SELECTIONS_FTL *>(dat + pos);
		pos += sizeof(EERIE_SELECTIONS_FTL);
		
		obj->selections[i].name = toLowercase(safestring(selection->name));
		obj->selections[i].selected.resize(selection->nb_selected);
	}
	
	// Copy in the selections selected data
	for(long i = 0; i < af3Ddh->nb_selections; i++) {
		std::copy((const s32 *)(dat + pos), (const s32 *)(dat + pos) + obj->selections[i].selected.size(), obj->selections[i].selected.begin() );
		pos += sizeof(s32) * obj->selections[i].selected.size(); // Advance to the next selection data block
	}
	
	obj->pbox = NULL; // Reset physics
	
	// Alloc'n'Copy Collision Spheres Data
	if(afsh->offset_collision_spheres != -1) {
		
		// Cast to header
		pos = afsh->offset_collision_spheres;
		const ARX_FTL_COLLISION_SPHERES_DATA_HEADER * afcsdh;
		afcsdh = reinterpret_cast<const ARX_FTL_COLLISION_SPHERES_DATA_HEADER*>(dat + pos);
		pos += sizeof(ARX_FTL_COLLISION_SPHERES_DATA_HEADER);
		
		// Alloc the collision sphere data object
		obj->sdata = new COLLISION_SPHERES_DATA();
		obj->sdata->spheres.resize(afcsdh->nb_spheres);
		
		// Alloc the collision speheres
		const COLLISION_SPHERE_FTL * begin = reinterpret_cast<const COLLISION_SPHERE_FTL *>(dat + pos);
		pos += sizeof(COLLISION_SPHERE_FTL) * obj->sdata->spheres.size();
		const COLLISION_SPHERE_FTL * end = reinterpret_cast<const COLLISION_SPHERE_FTL *>(dat + pos);
		std::copy(begin, end, obj->sdata->spheres.begin());
	}
	
	// Alloc'n'Copy Progressive DATA
	if(afsh->offset_progressive_data != -1) {
		// Progressive data ignored.
	}
	
	// Alloc'n'Copy Clothes DATA
	if(afsh->offset_clothes_data != -1) {
		
		obj->cdata = new CLOTHES_DATA();
		
		const ARX_FTL_CLOTHES_DATA_HEADER * afcdh;
		afcdh = reinterpret_cast<const ARX_FTL_CLOTHES_DATA_HEADER*>(dat + afsh->offset_clothes_data);
		obj->cdata->nb_cvert = (short)afcdh->nb_cvert;
		obj->cdata->springs.resize(afcdh->nb_springs);
		size_t pos = afsh->offset_clothes_data;
		pos += sizeof(ARX_FTL_CLOTHES_DATA_HEADER);
		
		// now load cvert
		obj->cdata->cvert = new CLOTHESVERTEX[obj->cdata->nb_cvert];
		obj->cdata->backup = new CLOTHESVERTEX[obj->cdata->nb_cvert];
		std::copy(reinterpret_cast<const CLOTHESVERTEX_FTL *>(dat + pos), reinterpret_cast<const CLOTHESVERTEX_FTL *>(dat + pos) + obj->cdata->nb_cvert, obj->cdata->cvert);
		memcpy(obj->cdata->backup, obj->cdata->cvert, sizeof(CLOTHESVERTEX)*obj->cdata->nb_cvert);
		pos += sizeof(CLOTHESVERTEX_FTL) * obj->cdata->nb_cvert;
		
		// now load springs
		const EERIE_SPRINGS_FTL * begin = reinterpret_cast<const EERIE_SPRINGS_FTL *>(dat + pos);
		pos += sizeof(EERIE_SPRINGS_FTL) * obj->cdata->springs.size();
		const EERIE_SPRINGS_FTL * end = reinterpret_cast<const EERIE_SPRINGS_FTL *>(dat + pos);
		std::copy(begin, end, obj->cdata->springs.begin());
	}
	
	// Free the loaded file memory
	free(dat);
	
	EERIE_OBJECT_CenterObjectCoordinates(obj);
	EERIE_CreateCedricData(obj);
	// Now we can release our cool FTL file
	EERIE_Object_Precompute_Fast_Access(obj);
	
	LogDebug("ARX_FTL_Load: loaded object " << filename);
	
	return obj;
}
Example #10
0
// All threads start execution here.
int main()
{
    void *frameBuffer;
    if (get_current_thread_id() != 0)
        worker_thread();

    // Set up render context
    frameBuffer = init_vga(VGA_MODE_640x480);
    RenderContext *context = new RenderContext(0x1000000);
    RenderTarget *renderTarget = new RenderTarget();
    Surface *colorBuffer = new Surface(FB_WIDTH, FB_HEIGHT, Surface::RGBA8888,
        (void*) frameBuffer);
    Surface *zBuffer = new Surface(FB_WIDTH, FB_HEIGHT, Surface::FLOAT);
    renderTarget->setColorBuffer(colorBuffer);
    renderTarget->setDepthBuffer(zBuffer);
    context->bindTarget(renderTarget);
    context->enableDepthBuffer(true);
    context->bindShader(new TextureShader());

    // Read resources
    PakFile pak;
    pak.open("pak0.pak");
    pak.readBspFile("maps/e1m1.bsp");
    Texture *atlasTexture = pak.getTextureAtlasTexture();

    LevelRenderer renderer;
    renderer.setBspData(pak.getBspTree(), pak.getPvsList(), pak.getBspTree()
                        + pak.getNumInteriorNodes(), pak.getNumLeaves(),
                        atlasTexture, pak.getLightmapAtlasTexture());
    Entity *ent = pak.findEntityByClassName("info_player_start");
    if (!ent)
    {
        printf("Error, couldn't find start position\n");
        return 1;
    }

    float facingAngle = float(atoi(ent->getAttribute("angle"))) / 360.0 * M_PI * 2;
    gCameraOrientationMatrix = Matrix::lookAt(Vec3(0, 0, 0), Vec3(cos(facingAngle),
                               sin(facingAngle), 0), kUpVector);

    float coords[3];
    parseCoordinateString(ent->getAttribute("origin"), coords);
    for (int i = 0; i < 3; i++)
        gCameraPos[i] = coords[i];

    printf("position %g %g %g angle %g\n", coords[0], coords[1], coords[2], facingAngle);

    // Start worker threads
    start_all_threads();

    TextureUniforms uniforms;
    Matrix projectionMatrix = Matrix::getProjectionMatrix(FB_WIDTH, FB_HEIGHT);

    for (int frame = 0; ; frame++)
    {
        processKeyboardEvents();

        context->enableWireframeMode(gWireframeRendering);
        atlasTexture->enableBilinearFiltering(gBilinearFiltering);

        // Set up uniforms
        Matrix viewMatrix = gCameraOrientationMatrix * Matrix::getTranslationMatrix(-gCameraPos);
        uniforms.fMVPMatrix = projectionMatrix * viewMatrix;
        uniforms.enableLightmap = gEnableLightmap;
        uniforms.enableTexture = gEnableTexture;

        context->bindUniforms(&uniforms, sizeof(uniforms));

        renderer.render(context, gCameraPos);

        clock_t startTime = clock();
        context->finish();
        printf("rendered frame in %d uS\n", clock() - startTime);
    }
}
bool initLocalisation() {
	
	LogDebug("Starting localization");
	
	localisation.clear();
	
	PakFile * file;
	
	if(config.language.empty()) {
		file = autodetectLanguage();
	} else {
		
		// Attempt to load localisation for the configured language.
		std::string filename = "localisation/utext_" + config.language + ".ini";
		file = resources->getFile(filename);
		
		if(!file) {
			LogWarning << "Localisation file " << filename << " not found, autodetecting language.";
			/*
			 * TODO we might want to keep the old config.language setting as there could be
			 * localized audio for that language even if there is no localized text.
			 */
			file = autodetectLanguage();
		}
	}
	
	if(!file) {
		return false;
	}
	
	arx_assert(!config.language.empty());
	
	u16 * localisation = reinterpret_cast<u16 *>(file->readAlloc());
	u16 * toFree = localisation;
	
	// Scale the loaded size to new stride of uint16_t vs char
	size_t loc_file_size = file->size() / sizeof(*localisation);
	
	// Ignore any byte order mark.
	if(loc_file_size >= 1 && *localisation == 0xfeff) {
		loc_file_size--, localisation++;
	}

	LogDebug("Loaded localisation file of size " << loc_file_size);
	size_t nchars = GetUTF16Length(localisation, &localisation[loc_file_size]);
	ARX_UNUSED(nchars);
	LogDebug("UTF-16 size is " << nchars);
	std::string out;
	out.reserve(loc_file_size);
	UTF16ToUTF8(localisation, &localisation[loc_file_size], std::back_inserter(out));
	LogDebug("Converted to UTF8 string of length " << out.size());

	if(localisation && loc_file_size) {
		LogDebug("Preparing to parse localisation file");
		std::istringstream iss( out );
		if(!::localisation.read(iss)) {
			LogWarning << "Error parsing localisation file localisation/utext_"
			           << config.language << ".ini";
		}
		
	}
	
	free(toFree);
	
	return true;
}
Example #12
0
long DanaeLoadLevel(const res::path & file) {
	
	LogInfo << "Loading Level " << file;
	
	ClearCurLoadInfo();
	CURRENTLEVEL = GetLevelNumByName(file.string());
	
	res::path lightingFileName = res::path(file).set_ext("llf");

	LogDebug("fic2 " << lightingFileName);
	LogDebug("fileDlf " << file);

	size_t FileSize = 0;
	char * dat = resources->readAlloc(file, FileSize);
	if(!dat) {
		LogError << "Unable to find " << file;
		return -1;
	}
	
	PakFile * lightingFile = resources->getFile(lightingFileName);
	
	PROGRESS_BAR_COUNT += 1.f;
	LoadLevelScreen();
	
	size_t pos = 0;
	
	DANAE_LS_HEADER dlh;
	memcpy(&dlh, dat + pos, sizeof(DANAE_LS_HEADER));
	pos += sizeof(DANAE_LS_HEADER);
	
	LogDebug("dlh.version " << dlh.version << " header size " << sizeof(DANAE_LS_HEADER));
	
	if(dlh.version > DLH_CURRENT_VERSION) {
		LogError << "Unexpected level file version: " << dlh.version << " for " << file;
		free(dat);
		dat = NULL;
		return -1;
	}
	
	// using compression
	if(dlh.version >= 1.44f) {
		char * torelease = dat;
		dat = blastMemAlloc(dat + pos, FileSize - pos, FileSize);
		free(torelease);
		pos = 0;
		if(!dat) {
			LogError << "STD_Explode did not return anything " << file;
			return -1;
		}
	}
	
	loddpos = subj.pos = dlh.pos_edit;
	player.desiredangle = player.angle = subj.angle = dlh.angle_edit;
	
	if(strcmp(dlh.ident, "DANAE_FILE")) {
		LogError << "Not a valid file " << file << ": \"" << safestring(dlh.ident) << '"';
		return -1;
	}
	
	LogDebug("Loading Scene");
	
	// Loading Scene
	if(dlh.nb_scn > 0) {
		
		const DANAE_LS_SCENE * dls = reinterpret_cast<const DANAE_LS_SCENE *>(dat + pos);
		pos += sizeof(DANAE_LS_SCENE);
		
		res::path scene = (FAKE_DIR) ? file.parent() : res::path::load(safestring(dls->name));
		FAKE_DIR = 0;
		
		if(FastSceneLoad(scene)) {
			LogDebug("done loading scene");
			FASTmse = 1;
		} else {
#ifdef BUILD_EDIT_LOADSAVE
			LogDebug("fast loading scene failed");
			ARX_SOUND_PlayCinematic("editor_humiliation", false);
			mse = PAK_MultiSceneToEerie(scene);
			PROGRESS_BAR_COUNT += 20.f;
			LoadLevelScreen();
#else
			LogError << "fast loading scene failed";
#endif
		}
		
		EERIEPOLY_Compute_PolyIn();
		LastLoadedScene = scene;
	}
	
	Vec3f trans;
	if(FASTmse) {
		trans = Mscenepos;
		player.pos = loddpos + trans;
	}
#ifdef BUILD_EDIT_LOADSAVE
	else if(mse != NULL) {
		Mscenepos.x = -mse->cub.xmin - (mse->cub.xmax - mse->cub.xmin) * ( 1.0f / 2 ) + ((float)ACTIVEBKG->Xsize * (float)ACTIVEBKG->Xdiv) * ( 1.0f / 2 );
		Mscenepos.z = -mse->cub.zmin - (mse->cub.zmax - mse->cub.zmin) * ( 1.0f / 2 ) + ((float)ACTIVEBKG->Zsize * (float)ACTIVEBKG->Zdiv) * ( 1.0f / 2 );
		float t1 = (float)(long)(mse->point0.x / BKG_SIZX);
		float t2 = (float)(long)(mse->point0.z / BKG_SIZZ);
		t1 = mse->point0.x - t1 * BKG_SIZX;
		t2 = mse->point0.z - t2 * BKG_SIZZ;
		Mscenepos.x = (float)((long)(Mscenepos.x / BKG_SIZX)) * BKG_SIZX + (float)BKG_SIZX * ( 1.0f / 2 );
		Mscenepos.z = (float)((long)(Mscenepos.z / BKG_SIZZ)) * BKG_SIZZ + (float)BKG_SIZZ * ( 1.0f / 2 );
		mse->pos.x = Mscenepos.x = Mscenepos.x + BKG_SIZX - t1;
		mse->pos.z = Mscenepos.z = Mscenepos.z + BKG_SIZZ - t2;
		mse->pos.y = Mscenepos.y = -mse->cub.ymin - 100.f - mse->point0.y;
		lastteleport.x = mapcam.pos.x = player.pos.x = subj.pos.x = moveto.x = mse->pos.x + mse->point0.x;
		lastteleport.z = mapcam.pos.z = player.pos.z = subj.pos.z = moveto.z = mse->pos.z + mse->point0.z;
		lastteleport.y                = player.pos.y = subj.pos.y = moveto.y = mse->pos.y + mse->point0.y;
		lastteleport.y -= 180.f;
		player.pos.y = subj.pos.y -= 180.f;
		trans = mse->pos;
	}
#endif // BUILD_EDIT_LOADSAVE
	else
	{
		lastteleport.x = 0.f;
		lastteleport.y = PLAYER_BASE_HEIGHT;
		lastteleport.z = 0.f;
		trans.x = 0;
		trans.y = 0;
		trans.z = 0;
		Mscenepos = trans;
	}
	
	MSP = trans;
	
	ClearCurLoadInfo();
	
	float increment = 0;
	if(dlh.nb_inter > 0) {
		increment = (60.f / (float)dlh.nb_inter);
	} else {
		PROGRESS_BAR_COUNT += 60;
		LoadLevelScreen();
	}
	
	for(long i = 0 ; i < dlh.nb_inter ; i++) {
		
		PROGRESS_BAR_COUNT += increment;
		LoadLevelScreen();
		
		const DANAE_LS_INTER * dli = reinterpret_cast<const DANAE_LS_INTER *>(dat + pos);
		pos += sizeof(DANAE_LS_INTER);
		if(!DONT_LOAD_INTERS) {
			
			string pathstr = toLowercase(safestring(dli->name));
			
			size_t pos = pathstr.find("graph");
			if(pos != std::string::npos) {
				pathstr = pathstr.substr(pos);
			}
			
			LoadInter_Ex(res::path::load(pathstr), dli->ident, dli->pos, dli->angle, trans);
		}
	}
	
	if(dlh.lighting) {
		
		const DANAE_LS_LIGHTINGHEADER * dll = reinterpret_cast<const DANAE_LS_LIGHTINGHEADER *>(dat + pos);
		pos += sizeof(DANAE_LS_LIGHTINGHEADER);
		long bcount = dll->nb_values;
		
		if(!lightingFile) {
			
			LastLoadedLightningNb = bcount;
			if(LastLoadedLightning != NULL) {
				free(LastLoadedLightning);
				LastLoadedLightning = NULL;
			}
			
			//DANAE_LS_VLIGHTING
			u32 * ll = LastLoadedLightning = (u32 *)malloc(sizeof(u32) * bcount);
			
			if(dlh.version > 1.001f) {
				std::copy((u32*)(dat + pos), (u32*)(dat + pos) + bcount, LastLoadedLightning);
				pos += sizeof(u32) * bcount;
			} else {
				while(bcount) {
					const DANAE_LS_VLIGHTING * dlv = reinterpret_cast<const DANAE_LS_VLIGHTING *>(dat + pos);
					pos += sizeof(DANAE_LS_VLIGHTING);
					*ll = 0xff000000L | ((dlv->r & 255) << 16) | ((dlv->g & 255) << 8) | (dlv->b & 255);
					ll++;
					bcount--;
				}
			}
			
		} else {
			pos += sizeof(u32) * bcount;
		}
		
		ModeLight = LightMode::load(dll->ModeLight); // TODO save/load flags
		ViewMode = ViewModeFlags::load(dll->ViewMode); // TODO save/load flags
		ViewMode &= ~VIEWMODE_WIRE;
	}
	
	PROGRESS_BAR_COUNT += 1;
	LoadLevelScreen();
	
	long nb_lights = (dlh.version < 1.003f) ? 0 : dlh.nb_lights;
	
	if(!lightingFile) {
		
		if(nb_lights != 0) {
			EERIE_LIGHT_GlobalInit();
		}
		
		for(long i = 0; i < nb_lights; i++) {
			
			const DANAE_LS_LIGHT * dlight = reinterpret_cast<const DANAE_LS_LIGHT *>(dat + pos);
			pos += sizeof(DANAE_LS_LIGHT);
			
			long j = EERIE_LIGHT_Create();
			if(j >= 0) {
				EERIE_LIGHT * el = GLight[j];
				
				el->exist = 1;
				el->treat = 1;
				el->fallend = dlight->fallend;
				el->fallstart = dlight->fallstart;
				el->falldiff = el->fallend - el->fallstart;
				el->falldiffmul = 1.f / el->falldiff;
				el->intensity = dlight->intensity;
				el->pos = dlight->pos;
				el->rgb = dlight->rgb;
				
				el->extras = checked_range_cast<short>(dlight->extras);
				
				el->ex_flicker = dlight->ex_flicker;
				el->ex_radius = dlight->ex_radius;
				el->ex_frequency = dlight->ex_frequency;
				el->ex_size = dlight->ex_size;
				el->ex_speed = dlight->ex_speed;
				el->tl = -1;
				el->sample = audio::INVALID_ID;
				
				if((el->extras & EXTRAS_SPAWNFIRE)) {
					el->extras |= EXTRAS_FLARE;
					if(el->extras & EXTRAS_FIREPLACE) {
						el->ex_flaresize = 95.f;
					} else {
						el->ex_flaresize = 40.f;
					}
				}
			}
		}
		
	} else {
		pos += sizeof(DANAE_LS_LIGHT) * nb_lights;
	}
	
	ClearCurLoadInfo();
	LogDebug("Loading FOGS");
	ARX_FOGS_Clear();
	
	for(long i = 0; i < dlh.nb_fogs; i++) {
		
		const DANAE_LS_FOG * dlf = reinterpret_cast<const DANAE_LS_FOG *>(dat + pos);
		pos += sizeof(DANAE_LS_FOG);
		
		long n = ARX_FOGS_GetFree();
		if(n > -1) {
			
			FOG_DEF * fd = &fogs[n];
			fd->exist = 1;
			fd->rgb = dlf->rgb;
			fd->angle = dlf->angle;
			fd->pos.x = dlf->pos.x + trans.x;
			fd->pos.y = dlf->pos.y + trans.y;
			fd->pos.z = dlf->pos.z + trans.z;
			fd->blend = dlf->blend;
			fd->frequency = dlf->frequency;
			fd->rotatespeed = dlf->rotatespeed;
			fd->scale = dlf->scale;
			fd->size = dlf->size;
			fd->special = dlf->special;
			fd->speed = dlf->speed;
			fd->tolive = dlf->tolive;
			fd->move.x = 1.f;
			fd->move.y = 0.f;
			fd->move.z = 0.f;
			Vec3f out;
			float ta = radians(MAKEANGLE(fd->angle.b));
			_YRotatePoint(&fd->move, &out, EEcos(ta), EEsin(ta));
			float tb = radians(MAKEANGLE(fd->angle.a));
			_XRotatePoint(&out, &fd->move, EEcos(tb), EEsin(tb));
		}
	}
	
	PROGRESS_BAR_COUNT += 2.f;
	LoadLevelScreen();
	
	ClearCurLoadInfo();
	LogDebug("Loading Nodes");
	ClearNodes();
	
	long nb_nodes = (dlh.version < 1.001f) ? 0 : dlh.nb_nodes;
	for(long i = 0; i < nb_nodes; i++) {
		
		nodes.nodes[i].exist = 1;
		nodes.nodes[i].selected = 0;
		const DANAE_LS_NODE * dln = reinterpret_cast<const DANAE_LS_NODE *>(dat + pos);
		pos += sizeof(DANAE_LS_NODE);
		
		strcpy(nodes.nodes[i].name, toLowercase(safestring(dln->name)).c_str());
		nodes.nodes[i].pos = (Vec3f)dln->pos + trans;
		
		for(long j = 0; j < dlh.nb_nodeslinks; j++) {
			if(dat[pos] != '\0') {
				strcpy(nodes.nodes[i].lnames[j], toLowercase(safestring(dat + pos, 64)).c_str());
			}
			pos += 64;
		}
	}
	
	RestoreNodeNumbers();
	
	ClearCurLoadInfo();
	LogDebug("Loading Paths");
	ARX_PATH_ReleaseAllPath();
	
	if(dlh.nb_paths) {
		ARXpaths = (ARX_PATH **)malloc(sizeof(ARX_PATH *) * dlh.nb_paths);
		nbARXpaths = dlh.nb_paths;
	}
	
	for(long i = 0; i < dlh.nb_paths; i++) {
		
		const DANAE_LS_PATH * dlp = reinterpret_cast<const DANAE_LS_PATH *>(dat + pos);
		pos += sizeof(DANAE_LS_PATH);
		
		Vec3f ppos = Vec3f(dlp->initpos) + trans;
		ARX_PATH * ap = ARXpaths[i] = new ARX_PATH(toLowercase(safestring(dlp->name)), ppos);
		
		ap->flags = PathFlags::load(dlp->flags); // TODO save/load flags
		ap->pos = Vec3f(dlp->pos) + trans;
		ap->nb_pathways = dlp->nb_pathways;
		ap->height = dlp->height;
		ap->ambiance = res::path::load(safestring(dlp->ambiance));
		
		ap->amb_max_vol = dlp->amb_max_vol;
		if(ap->amb_max_vol <= 1.f) {
			ap->amb_max_vol = 100.f;
		}
		
		ap->farclip = dlp->farclip;
		ap->reverb = dlp->reverb;
		ap->rgb = dlp->rgb;
		
		ARX_PATHWAY * app = ap->pathways = (ARX_PATHWAY *)malloc(sizeof(ARX_PATHWAY) * dlp->nb_pathways);
		memset(app, 0, sizeof(ARX_PATHWAY)*dlp->nb_pathways);
		
		for(long j = 0; j < dlp->nb_pathways; j++) {
			
			const DANAE_LS_PATHWAYS * dlpw = reinterpret_cast<const DANAE_LS_PATHWAYS *>(dat + pos);
			pos += sizeof(DANAE_LS_PATHWAYS);
			
			app[j].flag = (PathwayType)dlpw->flag; // save/load enum
			app[j].rpos = dlpw->rpos;
			app[j]._time = static_cast<float>(dlpw->time);
		}
	}
	
	ARX_PATH_ComputeAllBoundingBoxes();
	PROGRESS_BAR_COUNT += 5.f;
	LoadLevelScreen();
	
	
	//Now LOAD Separate LLF Lighting File
	
	free(dat);
	pos = 0;
	dat = NULL;
	
	if(lightingFile) {
		
		ClearCurLoadInfo();
		LogDebug("Loading LLF Info");
		
		// using compression
		if(dlh.version >= 1.44f) {
			char * compressed = lightingFile->readAlloc();
			dat = (char*)blastMemAlloc(compressed, lightingFile->size(), FileSize);
			free(compressed);
		} else {
			dat = lightingFile->readAlloc();
			FileSize = lightingFile->size();
		}
	}
	// TODO size ignored
	
	if(!dat) {
		LOADEDD = 1;
		FASTmse = 0;
		USE_PLAYERCOLLISIONS = 1;
		LogInfo << "Done loading level";
		return 1;
	}
	
	const DANAE_LLF_HEADER * llh = reinterpret_cast<DANAE_LLF_HEADER *>(dat + pos);
	pos += sizeof(DANAE_LLF_HEADER);
	
	PROGRESS_BAR_COUNT += 4.f;
	LoadLevelScreen();
	
	if(llh->nb_lights != 0) {
		EERIE_LIGHT_GlobalInit();
	}
	
	for(int i = 0; i < llh->nb_lights; i++) {
		
		const DANAE_LS_LIGHT * dlight = reinterpret_cast<const DANAE_LS_LIGHT *>(dat + pos);
		pos += sizeof(DANAE_LS_LIGHT);
		
		long j = EERIE_LIGHT_Create();
		if(j >= 0) {
			EERIE_LIGHT * el = GLight[j];
			
			el->exist = 1;
			el->treat = 1;
			el->fallend = dlight->fallend;
			el->fallstart = dlight->fallstart;
			el->falldiff = el->fallend - el->fallstart;
			el->falldiffmul = 1.f / el->falldiff;
			el->intensity = dlight->intensity;
			
			if(FASTmse) {
				el->pos.x = dlight->pos.x + trans.x;
				el->pos.y = dlight->pos.y + trans.y;
				el->pos.z = dlight->pos.z + trans.z;
			} else {
				el->pos = dlight->pos;
			}
			
			el->rgb = dlight->rgb;
			
			el->extras = checked_range_cast<short>(dlight->extras);
			
			el->ex_flicker = dlight->ex_flicker;
			el->ex_radius = dlight->ex_radius;
			el->ex_frequency = dlight->ex_frequency;
			el->ex_size = dlight->ex_size;
			el->ex_speed = dlight->ex_speed;
			el->ex_flaresize = dlight->ex_flaresize;
			
			el->status = (el->extras & EXTRAS_STARTEXTINGUISHED) ? 0 : 1;
			
			if((el->extras & EXTRAS_SPAWNFIRE) && (!(el->extras & EXTRAS_FLARE))) {
				el->extras |= EXTRAS_FLARE;
				if(el->extras & EXTRAS_FIREPLACE) {
					el->ex_flaresize = 95.f;
				} else {
					el->ex_flaresize = 80.f;
				}
			}
			
			el->tl = -1;
			el->sample = audio::INVALID_ID;
		}
	}
	
	PROGRESS_BAR_COUNT += 2.f;
	LoadLevelScreen();
	
	const DANAE_LS_LIGHTINGHEADER * dll = reinterpret_cast<const DANAE_LS_LIGHTINGHEADER *>(dat + pos);
	pos += sizeof(DANAE_LS_LIGHTINGHEADER);
	
	long bcount = dll->nb_values;
	LastLoadedLightningNb = bcount;
	if(LastLoadedLightning != NULL) {
		free(LastLoadedLightning);
		LastLoadedLightning = NULL;
	}
	
	//DANAE_LS_VLIGHTING
	u32 * ll;
	ll = LastLoadedLightning = (u32 *)malloc(sizeof(u32) * bcount);
	if(dlh.version > 1.001f) {
		std::copy((u32*)(dat + pos), (u32*)(dat + pos) + bcount, LastLoadedLightning);
		pos += sizeof(u32) * bcount;
	} else {
		while(bcount) {
			const DANAE_LS_VLIGHTING * dlv = reinterpret_cast<const DANAE_LS_VLIGHTING *>(dat + pos);
			pos += sizeof(DANAE_LS_VLIGHTING);
			*ll = 0xff000000L | ((dlv->r & 255) << 16) | ((dlv->g & 255) << 8) | (dlv->b & 255);
			ll++;
			bcount--;
		}
	}
	
	arx_assert(pos <= FileSize);
	
	ModeLight = LightMode::load(dll->ModeLight); // TODO save/load flags
	ViewMode = ViewModeFlags::load(dll->ViewMode); // TODO save/load flags
	ViewMode &= ~VIEWMODE_WIRE;
	
	free(dat);
	
	PROGRESS_BAR_COUNT += 1.f;
	LoadLevelScreen();
	
	LOADEDD = 1;
	FASTmse = 0;
	USE_PLAYERCOLLISIONS = 1;
	
	LogInfo << "Done loading level";
	
	return 1;
	
}