bool CMNGAnimation::Load(const char* filename, IFileSystem& fs) { this->~CMNGAnimation(); // open the file m_file = fs.Open(filename, IFileSystem::read); if (m_file == NULL) { return false; } // initialize MNG playback m_stream = mng_initialize(this, CB_Allocate, CB_Free, NULL); // set all of the callbacks mng_setcb_openstream(m_stream, CB_OpenStream); mng_setcb_closestream(m_stream, CB_CloseStream); mng_setcb_readdata(m_stream, CB_ReadData); mng_setcb_processheader(m_stream, CB_ProcessHeader); mng_setcb_gettickcount(m_stream, CB_GetTickCount); mng_setcb_getcanvasline(m_stream, CB_GetCanvasLine); mng_setcb_refresh(m_stream, CB_Refresh); mng_setcb_settimer(m_stream, CB_SetTimer); // do some reading if (mng_read(m_stream) != MNG_NOERROR) { return false; } return true; }
bool CConfigFile::Load(const char* filename, IFileSystem& fs) { m_sections.erase(m_sections.begin(), m_sections.end()); // open the file IFile* file = fs.Open(filename, IFileSystem::read); if (file == NULL) { return false; } std::string current_section = ""; bool eof = false; while (!eof) { // read a line std::string line; eof = !read_line(file, line); const char* string = line.c_str(); // parse it // eliminate whitespace skip_whitespace(string); if (string[0] == '[') { // it's a section string++; current_section = ""; while (*string != ']') { current_section += *string++; } string++; } else { // it's a key=value pair // read key std::string key; while (*string != '=' && *string) { key += *string++; } if (*string == 0) { continue; // skip lines without equals } string++; // skip the '=' std::string value; while (*string) { value += *string++; } // add the item WriteString(current_section.c_str(), key.c_str(), value.c_str()); } } file->Close(); return true; }
bool sTileset::Load(const char* filename, IFileSystem& fs) { IFile* file = fs.Open(filename, IFileSystem::read); if (file == NULL) return false; bool result = LoadFromFile(file); file->Close(); return result; }
bool sTileset::Save(const char* filename, IFileSystem& fs) const { // open the file IFile* file = fs.Open(filename, IFileSystem::write); if (file == NULL) return false; bool result = SaveToFile(file); file->Close(); return result; }
bool CConfigFile::Save(const char* filename, IFileSystem& fs) const { IFile* file = fs.Open(filename, IFileSystem::write); if (file == NULL) { return false; } // find the section without a name and write that first std::map<std::string, Section>::const_iterator i; for (i = m_sections.begin(); i != m_sections.end(); i++) { if (i->first == "") { const Section& s = i->second; std::map<std::string, std::string>::const_iterator j; for (j = s.entries.begin(); j != s.entries.end(); j++) { write_string(file, j->first); file->Write("=", 1); write_string(file, j->second); file->Write("\n", 1); } file->Write("\n", 1); } } // write the rest of the sections for (i = m_sections.begin(); i != m_sections.end(); i++) { if (i->first != "") { file->Write("[", 1); write_string(file, i->first); file->Write("]\n", 2); const Section& s = i->second; std::map<std::string, std::string>::const_iterator j; for (j = s.entries.begin(); j != s.entries.end(); j++) { write_string(file, j->first); file->Write("=", 1); write_string(file, j->second); file->Write("\n", 1); } file->Write("\n", 1); } } file->Close(); return true; }
void PrintDetailedPlayerClassStats() { if ( !tf_DetailedStats.GetInt() ) return; IFileSystem *pFileSys = filesystem; FileHandle_t hFile = pFileSys->Open( "class_stats_detailed.txt", "wt", "LOGDIR" ); if ( hFile != FILESYSTEM_INVALID_HANDLE ) { // Print the header. for ( int i=TFCLASS_UNDECIDED+1; i < STATS_NUM_GROUPS; i++ ) { pFileSys->FPrintf( hFile, "%s dist\t%s dmg\t", GetGroupNameFor( i ), GetGroupNameFor( i ) ); } pFileSys->FPrintf( hFile, "\n" ); // Write out each column. int iterators[STATS_NUM_GROUPS]; for ( i=TFCLASS_UNDECIDED+1; i < STATS_NUM_GROUPS; i++ ) iterators[i] = g_ClassShotInfos[i].Head(); bool bWroteAnything; do { bWroteAnything = false; for ( int i=TFCLASS_UNDECIDED+1; i < STATS_NUM_GROUPS; i++ ) { if ( iterators[i] == g_ClassShotInfos[i].InvalidIndex() ) { pFileSys->FPrintf( hFile, "\t\t" ); } else { CShotInfo *pInfo = &g_ClassShotInfos[i][iterators[i]]; iterators[i] = g_ClassShotInfos[i].Next( iterators[i] ); pFileSys->FPrintf( hFile, "%.2f\t%d\t", pInfo->m_flDistance, pInfo->m_nDamage ); bWroteAnything = true; } } pFileSys->FPrintf( hFile, "\n" ); } while ( bWroteAnything ); pFileSys->Close( hFile ); } }
bool CMeshLoader::Load(const wchar* path, bool ignore_animation_data/*=false*/) { if (m_bLoaded) { Unload(); m_bLoaded = false; } IFileSystem* pFS = CEngine::instance()->mFilesystem(); unsigned int ltim = GetTickCount(); // open file wchar fspath[P3DMAX_PATH]; wsprintf(fspath, P3DMAX_PATH-1, _W("models/%s.rmesh"), path); FSFILE* fp = pFS->Open(fspath, _W("rb")); if (!fp) { CON(MSG_ERR, _W("MeshLoader: Can't find mesh file '%s'!"), fspath); return false; } if (fp->nLen<sizeof(sRMHeader)) { CON(MSG_ERR, _W("MeshLoader: Mesh file '%s' is corrupted!"), fspath); pFS->Close(fp); return false; } // load and check header m_rhead = new sRMHeader(); pFS->Read(m_rhead, sizeof(sRMHeader), 1, fp); if (m_rhead->magic[0]!='R' || m_rhead->magic[1]!='M') { CON(MSG_ERR, _W("MeshLoader: File '%s' is not valid RMesh!"), fspath); pFS->Close(fp); return false; } if (m_rhead->major!=RM_MAJOR) { CON(MSG_ERR, _W("MeshLoader: Mesh '%s' is version %d, but engine can load only %d!"), fspath, m_rhead->major, RM_MAJOR); pFS->Close(fp); return false; } if (m_rhead->minor!=RM_MINOR) { CON(MSG_DBG, _W("MeshLoader: Minor version warning. Mesh '%s' is minor version %d, engine can load %d."), fspath, m_rhead->minor, RM_MINOR); } m_bLoaded=true; // LOAD INFO --------------------------------------------------- m_rinfo = new sRMInfo(); pFS->Seek(fp, m_rhead->contents[RM_FILE_INFO].offset, SEEK_SET); pFS->Read(m_rinfo, sizeof(sRMInfo), 1, fp); // LOAD SUBSETS --------------------------------------------------- m_nSubsets = m_rhead->contents[RM_SUBSETS].length/sizeof(sRMSubset); m_rsubsets = new sRMSubset[m_nSubsets]; pFS->Seek(fp, m_rhead->contents[RM_SUBSETS].offset, SEEK_SET); pFS->Read(m_rsubsets, sizeof(sRMSubset), m_nSubsets, fp); // LOAD VERTICES --------------------------------------------------- m_nVerts = m_rhead->contents[RM_VERTICES].length/sizeof(sRMVertex); m_rverts = new sRMVertex[m_nVerts]; pFS->Seek(fp, m_rhead->contents[RM_VERTICES].offset, SEEK_SET); pFS->Read(m_rverts, sizeof(sRMVertex), m_nVerts, fp); // LOAD INDICES --------------------------------------------------- m_nInds = m_rhead->contents[RM_INDICES].length/sizeof(sRMIndex); m_rinds = new sRMIndex[m_nInds]; pFS->Seek(fp, m_rhead->contents[RM_INDICES].offset, SEEK_SET); pFS->Read(m_rinds, sizeof(sRMIndex), m_nInds, fp); // MAKE FACE GROUPS ----------------------------------------------- m_faceGroups = new unsigned int[m_nInds/3]; memset(m_faceGroups, 0, sizeof(unsigned int)*m_nInds/3); for (unsigned int s=0; s<m_nSubsets; s++) { // find faces which belongs to this subset unsigned int beginFace = m_rsubsets[s].firstindex/3; unsigned int endFace = (m_rsubsets[s].firstindex+m_rsubsets[s].numindices)/3; // assign face groups to this subset for (unsigned int f=beginFace; f<endFace; f++) m_faceGroups[f]=s; } // IF THIS FILE HAS ANIMATION AND IT IS LAODED MAKE SURE TO SET m_bAnimated TO TRUE m_bAnimated = false; if (!m_rinfo->idontimportanim) { // check if file contain animated content // TODO: } // close file pFS->Close(fp); ltim = GetTickCount() - ltim; if (ltim<1000) CON(MSG_INFO, _W("MeshLoader: Mesh '%s' loaded. Loading took %d miliseconds."), path, ltim); else CON(MSG_INFO, _W("MeshLoader: Mesh '%s' loaded. Loading took %d seconds."), path, ltim/1000); return true; }
void PrintPlayerClassStats() { IFileSystem *pFileSys = filesystem; FileHandle_t hFile = pFileSys->Open( "class_stats.txt", "wt", "LOGDIR" ); if ( hFile == FILESYSTEM_INVALID_HANDLE ) return; pFileSys->FPrintf( hFile, "Class\tPlayer Time (minutes)\tAvg Engagement Dist\t(OLD) Engagement Dist\n" ); for ( int i=TFCLASS_UNDECIDED+1; i < STATS_NUM_GROUPS; i++ ) { CPlayerClassStats *pStats = &g_PlayerClassStats[i]; // Figure out the average engagement distance across all classes. int j; double flAvgEngagementDist = 0; int nTotalEngagements = 0; double flTotalEngagementDist = 0; double flTotalNormalizedEngagementDist = 0; int nTotalNormalizedEngagements = 0; for ( j=TFCLASS_UNDECIDED+1; j < STATS_NUM_GROUPS; j++ ) { CInterClassStats *pInter = &g_PlayerClassStats[i].m_InterClassStats[j]; nTotalEngagements += pInter->m_nEngagements; flTotalEngagementDist += pInter->m_flTotalEngagementDist; nTotalNormalizedEngagements += pInter->m_nNormalizedEngagements; flTotalNormalizedEngagementDist += pInter->m_flTotalNormalizedEngagementDist; } flAvgEngagementDist = nTotalEngagements ? ( flTotalEngagementDist / nTotalEngagements ) : 0; double flAvgNormalizedEngagementDist = nTotalNormalizedEngagements ? (flTotalNormalizedEngagementDist / nTotalNormalizedEngagements) : 0; pFileSys->FPrintf( hFile, "%s", GetGroupNameFor( i ) ); pFileSys->FPrintf( hFile, "\t%.1f", (pStats->m_flPlayerTime / 60.0f) ); pFileSys->FPrintf( hFile, "\t%d", (int)flAvgNormalizedEngagementDist ); pFileSys->FPrintf( hFile, "\t%d", (int)flAvgEngagementDist ); pFileSys->FPrintf( hFile, "\n" ); } pFileSys->FPrintf( hFile, "\n" ); pFileSys->FPrintf( hFile, "\n" ); pFileSys->FPrintf( hFile, "Class\tTarget Class\tTotal Damage\tKills\tAvg Engagement Dist\t(OLD) Engagement Dist\n" ); for ( i=TFCLASS_UNDECIDED+1; i < STATS_NUM_GROUPS; i++ ) { CPlayerClassStats *pStats = &g_PlayerClassStats[i]; // Print the inter-class stats. for ( int j=TFCLASS_UNDECIDED+1; j < STATS_NUM_GROUPS; j++ ) { CInterClassStats *pInter = &pStats->m_InterClassStats[j]; pFileSys->FPrintf( hFile, "%s", GetGroupNameFor( i ) ); pFileSys->FPrintf( hFile, "\t%s", GetGroupNameFor( j ) ); pFileSys->FPrintf( hFile, "\t%d", (int)pInter->m_flTotalDamageInflicted ); pFileSys->FPrintf( hFile, "\t%d", pInter->m_nKills ); pFileSys->FPrintf( hFile, "\t%d", (int)(pInter->m_nNormalizedEngagements ? (pInter->m_flTotalNormalizedEngagementDist / pInter->m_nNormalizedEngagements) : 0) ); pFileSys->FPrintf( hFile, "\t%d", (int)(pInter->m_nEngagements ? (pInter->m_flTotalEngagementDist / pInter->m_nEngagements) : 0) ); pFileSys->FPrintf( hFile, "\n" ); } } pFileSys->Close( hFile ); }
bool CShaderHLSL::Create(P3D::sShaderDesc &desc) { const char *pData; ULONG fsize; IFileSystem* pFS = CRenderer::mEngine()->mFilesystem(); wchar path[P3DMAX_PATH]; wsprintf(path, P3DMAX_PATH-1, _W("shaders/%s.rshader"), desc.ShaderFile.Get()); FSFILE *fp = pFS->Load(path, (BYTE *&)pData, fsize, true); if (!fp) { CON(MSG_ERR, _W("Can't open %s.hlsl shader file from data/shaders directory!"), desc.ShaderFile.Get()); return false; } ID3D10Blob *pShaderBlob = NULL; ID3D10Blob *pErrors = NULL; UINT flags = D3D10_SHADER_DEBUG; //D3D10_SHADER_OPTIMIZATION_LEVEL3 char profile[128]; switch(desc.ShaderType) { case SHADERTYPE_VERTEX_SHADER: strcpy(profile, D3D10GetVertexShaderProfile(g_pD3ddev)); break; case SHADERTYPE_GEOMETRY_SHADER: strcpy(profile, D3D10GetGeometryShaderProfile(g_pD3ddev)); break; case SHADERTYPE_PIXEL_SHADER: strcpy(profile, D3D10GetPixelShaderProfile(g_pD3ddev)); break; default: CON(MSG_ERR, _W("Chader creation failed. No apropriate ShaderType given.")); return false; } CIncludeHandler includeHandler; D3D10_SHADER_MACRO Shader_Macros[] = { { "DX10", NULL }, { "SM4", NULL }, NULL }; if(!CheckHRResult(D3DX10CompileFromMemory( pData, fsize, NULL, Shader_Macros, &includeHandler, _W2A(desc.EntryFunction.Get()), profile, flags, 0, NULL, &pShaderBlob, &pErrors, NULL ))) { if(pErrors) CON(MSG_ERR, _W("%s"), _A2W((char*)pErrors->GetBufferPointer())); else CON(MSG_ERR, _W("Error description not given")); CON(MSG_ERR, _W("Shader %s could not be compiled"), desc.ShaderFile.Get()); SAFE_RELEASE(pErrors); return false; } pFS->UnLoad(fp, (BYTE *)pData); //save to cache fp = pFS->Open(_W("cache/shaders/hlsl"), _W("wb")); const char* cs = (const char*)pShaderBlob->GetBufferPointer(); pFS->Write(cs, 1, pShaderBlob->GetBufferSize(), fp); pFS->Close(fp); bool shaderCreated = false; switch(desc.ShaderType) { case SHADERTYPE_VERTEX_SHADER: shaderCreated = CheckHRResult(g_pD3ddev->CreateVertexShader(pShaderBlob->GetBufferPointer(), pShaderBlob->GetBufferSize(), &m_pVS)); break; case SHADERTYPE_GEOMETRY_SHADER: shaderCreated = CheckHRResult(g_pD3ddev->CreateGeometryShader(pShaderBlob->GetBufferPointer(), pShaderBlob->GetBufferSize(), &m_pGS)); break; case SHADERTYPE_PIXEL_SHADER: shaderCreated = CheckHRResult(g_pD3ddev->CreatePixelShader(pShaderBlob->GetBufferPointer(), pShaderBlob->GetBufferSize(), &m_pPS)); break; } if(!shaderCreated) { CON(MSG_ERR, _W("Shader creation error")); return false; } //if(!CheckHRResult(D3DReflect((DWORD*)pShaderBlob->GetBufferPointer(), pShaderBlob->GetBufferSize(), __uuidof(ID3D10ShaderReflection), &m_pReflection))) if(!CheckHRResult(D3D10ReflectShader(pShaderBlob->GetBufferPointer(), pShaderBlob->GetBufferSize(), &m_pReflection))) { CON(MSG_ERR, _W("Could not create a Shader reflection")); return false; } //HRESULT D3DReflect(LPCVOID pSrcData, SIZE_T SrcDataSize, REFIID pInterface, void **ppReflector); D3D10_SHADER_DESC shDesc; m_pReflection->GetDesc(&shDesc); m_numResources = shDesc.BoundResources; //not sure about this if(desc.ShaderType == SHADERTYPE_VERTEX_SHADER) m_pVertDecl = new CVertexDeclaration(CRenderer::cGraphicsManager()->GetVertexDescByID(desc.VertexDescID), pShaderBlob); SAFE_RELEASE(pShaderBlob); m_desc = desc; CON(MSG_INFO, _W("Shader '%s' created"), desc.ShaderFile); return true; }
bool CShaderHLSL::Create(P3D::sShaderDesc &desc) { const char *pData; ULONG fsize; IFileSystem* pFS = CRenderer::mEngine()->mFilesystem(); wchar path[P3DMAX_PATH]; wsprintf(path, P3DMAX_PATH-1, _W("shaders/%s.rshader"), desc.ShaderFile.Get()); FSFILE *fp = pFS->Load(path, (BYTE *&)pData, fsize, true); if (!fp) { CON(MSG_ERR, _W("Can't open %s.hlsl shader file from data/shaders directory!"), desc.ShaderFile.Get()); return false; } ID3DXBuffer *pShaderBlob = NULL; ID3DXBuffer *pErrors = NULL; DWORD flags = D3DXSHADER_DEBUG; //D3DXSHADER_OPTIMIZATION_LEVEL3 char profile[128]; switch(desc.ShaderType) { case SHADERTYPE_VERTEX_SHADER: strcpy(profile, D3DXGetVertexShaderProfile(g_pD3ddev)); break; case SHADERTYPE_PIXEL_SHADER: strcpy(profile, D3DXGetPixelShaderProfile(g_pD3ddev)); break; case SHADERTYPE_GEOMETRY_SHADER: CON(MSG_ERR, _W("DX9 does not support geometry shaders.")); return false; default: CON(MSG_ERR, _W("Chader creation failed. No apropriate ShaderType given.")); return false; } CIncludeHandler includeHandler; D3DXMACRO Shader_Macros[] = { { "DX9", NULL }, { "SM3", NULL }, NULL }; if(FAILED(D3DXCompileShader( pData, fsize, Shader_Macros, &includeHandler, _W2A(desc.EntryFunction.Get()), profile, flags, &pShaderBlob, &pErrors, &m_pConstTable ))) { if(pErrors) CON(MSG_ERR, _W("%s"), _A2W((char*)pErrors->GetBufferPointer())); else CON(MSG_ERR, _W("Error description not given")); CON(MSG_ERR, _W("Shader %s could not be compiled"), desc.ShaderFile.Get()); SAFE_RELEASE(pErrors); return false; } pFS->UnLoad(fp, (BYTE *)pData); //save to cache fp = pFS->Open(_W("cache/shaders/hlsl"), _W("wb")); const char* cs = (const char*)pShaderBlob->GetBufferPointer(); pFS->Write(cs, 1, pShaderBlob->GetBufferSize(), fp); pFS->Close(fp); bool shaderCreated = false; switch(desc.ShaderType) { case SHADERTYPE_VERTEX_SHADER: shaderCreated = SUCCEEDED(g_pD3ddev->CreateVertexShader((const DWORD*)pShaderBlob->GetBufferPointer(), &m_pVS)); break; case SHADERTYPE_PIXEL_SHADER: shaderCreated = SUCCEEDED(g_pD3ddev->CreatePixelShader((const DWORD*)pShaderBlob->GetBufferPointer(), &m_pPS)); break; } if(!shaderCreated) { CON(MSG_ERR, _W("Shader creation error")); return false; } //set constant to their default values m_pConstTable->SetDefaults(g_pD3ddev); //create vertex declaration if(desc.ShaderType == SHADERTYPE_VERTEX_SHADER) m_pVertDecl = new CVertexDeclaration(CRenderer::cGraphicsManager()->GetVertexDescByID(desc.VertexDescID), pShaderBlob); SAFE_RELEASE(pShaderBlob); m_desc = desc; CON(MSG_INFO, _W("Shader '%s' created"), desc.ShaderFile); return true; }
// ------------------------------------------------ bool CTextureLoader::Load(const wchar* path) { IFileSystem *fs = CRenderer::mEngine()->mFilesystem(); Unload(); //memset(&m_info, 0, sizeof(sRTInfo)); // make physical FS path wchar physPath[512]; wsprintf(physPath, 511, _W("textures/%s.rtex"), path); for (unsigned int i=0; i<wstrlen(physPath); i++) if (physPath[i]==',') physPath[i]='/'; FSFILE* fp; fp = fs->Open(physPath, _W("rb")); if (!fp) { return false; } m_dataLen = fp->nLen; if (m_dataLen < sizeof(sRTHeader)) { fs->Close(fp); return false; } // read header sRTHeader head; fs->Read(&head, 1, sizeof(sRTHeader), fp); // check header if (head.magic[0]!='R' || head.magic[1]!='T') { CON(MSG_ERR, _W("Texture %s is not valid rtex!"), path); fs->Close(fp); return false; } // load texture info fs->Seek(fp, head.contents[RT_FILE_INFO].offset, SEEK_SET); fs->Read(&m_info, 1, sizeof(sRTInfo), fp); // load texture data unsigned long rawDataLen = fp->nLen-head.contents[RT_IMAGE_SUBSET].offset-head.contents[RT_IMAGE_SUBSET].length; m_data = new BYTE[rawDataLen]; fs->Seek(fp, head.contents[RT_IMAGE_SUBSET].offset+head.contents[RT_IMAGE_SUBSET].length, SEEK_SET); fs->Read(m_data, 1, rawDataLen, fp); m_bLoaded=true; // load all subsets fs->Seek(fp, head.contents[RT_IMAGE_SUBSET].offset, SEEK_SET); unsigned int numSubs = head.contents[RT_IMAGE_SUBSET].length / sizeof(sRTImageSubset); for (unsigned int s = 0; s < numSubs; s++) { sImageData* ida = new sImageData(); fs->Read(&ida->subset, 1, sizeof(sRTImageSubset), fp); ida->size = ida->subset.len; ida->pData = &m_data[ida->subset.offset]; m_subs.push_back(ida); } fs->Close(fp); int i = 0; // debug return true; }
bool sTileset::Import_TST(const char* filename, IFileSystem& fs) { // TST file format created by Christoper B. Matthews for the RPG Toolkit Development System IFile* file = fs.Open(filename, IFileSystem::read); if (file == NULL) return false; // read header word version; word numtiles; word detail; file->Read(&version, 2); file->Read(&numtiles, 2); file->Read(&detail, 2); // check header for errors // only support details 2, 4, 6 if (version != 20 && (detail == 2 || detail == 4 || detail == 6)) { file->Close(); return false; } // allocate new tiles m_Tiles.clear(); m_Tiles.resize(numtiles); // read them from file for (int i = 0; i < m_Tiles.size(); i++) { sTile& tile = m_Tiles[i]; switch (detail) { case 2: // 16x16, 24-bit color { for (int ix = 0; ix < 16; ix++) for (int iy = 0; iy < 16; iy++) { RGB rgb; file->Read(&rgb, 3); byte alpha = 255; if (rgb.red == 0 && rgb.green == 1 && rgb.blue == 2) alpha = 0; tile.GetPixels()[iy * 16 + ix].red = rgb.red; tile.GetPixels()[iy * 16 + ix].green = rgb.green; tile.GetPixels()[iy * 16 + ix].blue = rgb.blue; tile.GetPixels()[iy * 16 + ix].alpha = alpha; } break; } case 4: // 16x16, 8-bit color case 6: // 16x16, 4-bit color // these two are effectively the same format { for (int ix = 0; ix < 16; ix++) for (int iy = 0; iy < 16; iy++) { byte b; file->Read(&b, 1); RGB rgb = dos_palette[b]; byte alpha = 255; if (b == 255) alpha = 0; tile.GetPixels()[iy * 16 + ix].red = rgb.red; tile.GetPixels()[iy * 16 + ix].green = rgb.green; tile.GetPixels()[iy * 16 + ix].blue = rgb.blue; tile.GetPixels()[iy * 16 + ix].alpha = alpha; } break; } } } file->Close(); return true; }
bool sTileset::Import_VSP(const char* filename, IFileSystem& fs) { IFile* file = fs.Open(filename, IFileSystem::read); if (file == NULL) return false; word version; RGB palette[256]; word numtiles; file->Read(&version, 2); file->Read(palette, 3 * 256); file->Read(&numtiles, 2); m_Tiles.clear(); m_Tiles.resize(numtiles); // decode the file if (version == 2) { for (int i = 0; i < numtiles; i++) { byte tile[256]; file->Read(tile, 256); for (int x = 0; x < 16; x++) for (int y = 0; y < 16; y++) { RGBA color; byte c = tile[y * 16 + x]; if (c == 0) { color.red = 0; color.green = 0; color.blue = 0; color.alpha = 0; } else { color.red = (byte)(palette[c].red * 4); color.green = (byte)(palette[c].green * 4); color.blue = (byte)(palette[c].blue * 4); color.alpha = 255; } m_Tiles[i].GetPixels()[y * 16 + x] = color; } } } else { // for that wierd thing aen never told me in the vsp code dword dw; file->Read(&dw, 4); // create a temporary buffer while setting up the decoding stuff... byte* buffer = (byte*)malloc(numtiles * 256); int len = numtiles * 256; int counter = 0; //start decoding! while (counter < len) { byte c; file->Read(&c, 1); // if the c was 255 then it's a compressed value if (c == 255) { byte run, color; file->Read(&run, 1); file->Read(&color, 1); for (int i = 0; i < run; i++) { buffer[counter] = color; counter++; } } else // it's a normal value { buffer[counter] = c; counter++; } } // now, tranfer the decoded stuff into the tiles' data structure for (int i = 0; i < numtiles; i++) for (int j = 0; j < 256; j++) { if (buffer[i * 256 + j] == 0) { m_Tiles[i].GetPixels()[j].red = 0; m_Tiles[i].GetPixels()[j].green = 0; m_Tiles[i].GetPixels()[j].blue = 0; m_Tiles[i].GetPixels()[j].alpha = 0; } else { m_Tiles[i].GetPixels()[j].red = (palette[buffer[i * 256 + j]].red) * 4; m_Tiles[i].GetPixels()[j].green = (palette[buffer[i * 256 + j]].green) * 4; m_Tiles[i].GetPixels()[j].blue = (palette[buffer[i * 256 + j]].blue) * 4; m_Tiles[i].GetPixels()[j].alpha = 255; } } } file->Close(); return true; }
bool sMap::Import_VergeMAP(const char* filename, const char* tilesetFilename, IFileSystem& fs) { m_MusicFile = ""; m_EntryScript = ""; m_ExitScript = ""; m_Layers.clear(); m_Entities.clear(); IFile* file = fs.Open(filename, IFileSystem::read); if (file == NULL) return false; // check for v1 maps (ver 4) and v2 maps (ver 5) char signature[6]; file->Read(signature, 6); file->Seek(0); bool success = false; if (signature[0] == 4) { V1MAP_HEADER header; file->Read(&header, sizeof(header)); word* layer_background = new word[header.layer_size_x * header.layer_size_y]; word* layer_foreground = new word[header.layer_size_x * header.layer_size_y]; file->Read(layer_background, header.layer_size_x * header.layer_size_y * sizeof(word)); file->Read(layer_foreground, header.layer_size_x * header.layer_size_y * sizeof(word)); sTileset tileset; if (strcmp_ci(tilesetFilename + strlen(tilesetFilename) - 4, ".vsp") == 0) success = tileset.Import_VSP(tilesetFilename, fs); else success = tileset.Load(tilesetFilename, fs); sLayer layer[2]; if (success) { // process map and see if the map has tiles that are out of range int highestTileIndex = 0; for (int j=0; j<header.layer_size_y; j++) for (int i=0; i<header.layer_size_x; i++) if (layer_background[j * header.layer_size_x + i] >= highestTileIndex) highestTileIndex = layer_background[j * header.layer_size_x + i]; else if (layer_foreground[j * header.layer_size_x + i] >= highestTileIndex) highestTileIndex = layer_foreground[j * header.layer_size_x + i]; if (highestTileIndex >= tileset.GetNumTiles()) success = false; // transfer data across into the sMap now... if (success) { layer[0].SetName("Background"); layer[1].SetName("Foreground"); layer[0].Resize(header.layer_size_x, header.layer_size_y); layer[1].Resize(header.layer_size_x, header.layer_size_y); for (int j=0; j<header.layer_size_y; j++) for (int i=0; i<header.layer_size_x; i++) { layer[0].SetTile(i,j, layer_background[j * header.layer_size_x + i]); if (layer_foreground[j * header.layer_size_x + i]) layer[1].SetTile(i,j, layer_foreground[j * header.layer_size_x + i]); else layer[1].SetTile(i,j, tileset.GetNumTiles()); } tileset.AppendTiles(1); memset(tileset.GetTile(tileset.GetNumTiles() - 1).GetPixels(), 0, 256 * sizeof(RGBA)); m_Tileset = tileset; AppendLayer(layer[0]); AppendLayer(layer[1]); SetMusicFile((char*)header.music_fname); SetStartX(header.x_start); SetStartX(header.y_start); SetStartDirection(4); // calculate the parallax mode for (int i=0; i<2; i++) { // FIXME (set parallax properly) // GetLayer(i).SetParallaxX(1, 1); // GetLayer(i).SetParallaxY(1, 1); // GetLayer(i).SetScrollingX(1, 1); // GetLayer(i).SetScrollingX(1, 1); } switch(header.parallax_mode) { case 0: SetStartLayer(0); break; case 1: SetStartLayer(1); break; case 2: // FIXME (set parallax properly) SetStartLayer(1); // GetLayer(0).SetParallaxX(header.parallax_multiplier, header.parallax_divisor); // GetLayer(0).SetParallaxY(header.parallax_multiplier, header.parallax_divisor); break; case 3: // FIXME (set parallax properly) SetStartLayer(0); // GetLayer(1).SetParallaxX(header.parallax_multiplier, header.parallax_divisor); // GetLayer(1).SetParallaxY(header.parallax_multiplier, header.parallax_divisor); break; } } } // cleanup delete[] layer_background; delete[] layer_foreground; } else if (strcmp(signature, "MAPù5") == 0) { V2MAP_HEADER header; V2MAP_LAYERINFO LayerInfo[7]; sTileset tileset; word *mapLayer[7]; int i,j,k; int highestTileIndex = 0; file->Read(&header, sizeof(header)); for (i=0; i<header.num_layers; i++) { file->Read(LayerInfo + i, sizeof(V2MAP_LAYERINFO)); //bug for v2's map: two bytes are added for no reason word w; file->Read(&w, 2); } // get info about map and uncompress it for (i=0; i<header.num_layers; i++) mapLayer[i] = new word[LayerInfo[i].size_x * LayerInfo[i].size_y]; for (i=0; i<header.num_layers; i++) { // god, this is so dumb. It's supposed to be the buffersize, but do I look like I need it? file->Read(&j, 4); for (j=0; j<LayerInfo[i].size_x*LayerInfo[i].size_y; j++) { word value; byte run; file->Read(&value, sizeof(word)); if ((value & 0xFF00) == 0xFF00) { run = (byte)value & 0x00FF; file->Read(&value, sizeof(word)); mapLayer[i][j] = value; for (k=1; k<run; k++) { j++; mapLayer[i][j] = value; } } else { mapLayer[i][j] = value; } } } if (strcmp_ci(tilesetFilename + strlen(tilesetFilename) - 4, ".vsp") == 0) success = tileset.Import_VSP(tilesetFilename); else success = tileset.Load(tilesetFilename); // transfer map array into the class if (success) { highestTileIndex = 0; // check for any tile index larger than the tilset's index for (i=0; i<header.num_layers; i++) for (j=0; j<LayerInfo[i].size_x*LayerInfo[i].size_y; j++) if (mapLayer[i][j] >= highestTileIndex) highestTileIndex = mapLayer[i][j]; if (highestTileIndex >= tileset.GetNumTiles()) success = false; if (success) { sLayer *layer; layer = new sLayer[header.num_layers]; for (i=0; i<header.num_layers; i++) { char Name[7]; memcpy(Name, "Layer A", 8); Name[6] += i; layer[i].SetName(Name); layer[i].Resize(LayerInfo[i].size_x, LayerInfo[i].size_y); } for (i=0; i<header.num_layers; i++) { for (j=0; j<LayerInfo[i].size_y; j++) for (k=0; k<LayerInfo[i].size_x; k++) layer[i].SetTile(k, j, mapLayer[i][(j * LayerInfo[i].size_x) + k]); // FIXME: set parallax properly // layer[i].SetParallaxX(LayerInfo[i].multx, LayerInfo[i].pdivx); // layer[i].SetParallaxY(LayerInfo[i].multy, LayerInfo[i].pdivy); // layer[i].SetScrollingX(1,1); // layer[i].SetScrollingY(1,1); } for (i=0; i<(int)strlen((char*)header.renderstring); i++) switch(header.renderstring[i]) { case '1': AppendLayer(layer[0]); j = 0; break; case '2': AppendLayer(layer[1]); j = 1; break; case '3': AppendLayer(layer[2]); j = 2; break; case '4': AppendLayer(layer[3]); j = 3; break; case '5': AppendLayer(layer[4]); j = 4; break; case '6': AppendLayer(layer[5]); j = 5; break; case 'E': SetStartLayer(j); break; } SetMusicFile((char*)header.music_name); SetStartX(header.x_start); SetStartY(header.y_start); m_Tileset = tileset; delete[] layer; } } for (i=0; i<header.num_layers; i++) delete mapLayer[i]; } file->Close(); return success; }
bool sMap::Save(const char* filename, IFileSystem& fs) { // do some preliminary checking... // the start layer should not have parallax m_Layers[m_StartLayer].EnableParallax(false); IFile* file = fs.Open(filename, IFileSystem::write); if (file == NULL) return false; // write the map header MAP_HEADER header; memset(&header, 0, sizeof(header)); memcpy(header.signature, ".rmp", 4); header.version = 1; header.num_layers = m_Layers.size(); header.num_entities = m_Entities.size(); header.startx = m_StartX; header.starty = m_StartY; header.startlayer = m_StartLayer; header.startdirection = m_StartDirection; header.num_strings = 9; file->Write(&header, sizeof(header)); // write the strings WriteMapString(file, ""); // OBSOLETE WriteMapString(file, m_MusicFile.c_str()); WriteMapString(file, ""); // OBSOLETE WriteMapString(file, m_EntryScript.c_str()); WriteMapString(file, m_ExitScript.c_str()); WriteMapString(file, m_EdgeScripts[0].c_str()); WriteMapString(file, m_EdgeScripts[1].c_str()); WriteMapString(file, m_EdgeScripts[2].c_str()); WriteMapString(file, m_EdgeScripts[3].c_str()); // write layers for (int i = 0; i < m_Layers.size(); i++) { const sLayer& layer = m_Layers[i]; const sObstructionMap& obstructions = layer.GetObstructionMap(); // write the header LAYER_HEADER lh; memset(&lh, 0, sizeof(lh)); lh.width = m_Layers[i].GetWidth(); lh.height = m_Layers[i].GetHeight(); lh.flags = (m_Layers[i].IsVisible() ? 0 : 1) | (m_Layers[i].HasParallax() ? 2 : 0); lh.parallax_x = m_Layers[i].GetXParallax(); lh.parallax_y = m_Layers[i].GetYParallax(); lh.scrolling_x = m_Layers[i].GetXScrolling(); lh.scrolling_y = m_Layers[i].GetYScrolling(); lh.num_segments = obstructions.GetNumSegments(); lh.reflective = (m_Layers[i].IsReflective() ? 1 : 0); file->Write(&lh, sizeof(lh)); // write the layer name WriteMapString(file, m_Layers[i].GetName()); // write the layer data for (int iy = 0; iy < m_Layers[i].GetHeight(); iy++) for (int ix = 0; ix < m_Layers[i].GetWidth(); ix++) { word w = m_Layers[i].GetTile(ix, iy); file->Write(&w, 2); } // write the obstruction map for (int i = 0; i < obstructions.GetNumSegments(); i++) { const sObstructionMap::Segment& s = obstructions.GetSegment(i); dword x1 = s.x1; dword y1 = s.y1; dword x2 = s.x2; dword y2 = s.y2; file->Write(&x1, sizeof(dword)); file->Write(&y1, sizeof(dword)); file->Write(&x2, sizeof(dword)); file->Write(&y2, sizeof(dword)); } } // end for layer // write entities for (int i = 0; i < m_Entities.size(); i++) { // write the header ENTITY_HEADER eh; memset(&eh, 0, sizeof(eh)); eh.mapx = m_Entities[i]->x; eh.mapy = m_Entities[i]->y; eh.layer = m_Entities[i]->layer; switch (m_Entities[i]->GetEntityType()) { case sEntity::PERSON: eh.type = 1; break; case sEntity::TRIGGER: eh.type = 2; break; } file->Write(&eh, sizeof(eh)); // write the entity data switch (m_Entities[i]->GetEntityType()) { case sEntity::PERSON: { sPersonEntity* person = (sPersonEntity*)m_Entities[i]; WriteMapString(file, person->name.c_str()); WriteMapString(file, person->spriteset.c_str()); WriteMapWord(file, 5); // four scripts // scripts WriteMapString(file, person->script_create.c_str()); WriteMapString(file, person->script_destroy.c_str()); WriteMapString(file, person->script_activate_touch.c_str()); WriteMapString(file, person->script_activate_talk.c_str()); WriteMapString(file, person->script_generate_commands.c_str()); // reserved for (int i = 0; i < 16; i++) { WriteMapByte(file, 0); } break; } case sEntity::TRIGGER: { sTriggerEntity* trigger = (sTriggerEntity*)m_Entities[i]; WriteMapString(file, trigger->script.c_str()); break; } } // end switch entity type } // end for entity // write the zones for (int i = 0; i < m_Zones.size(); i++) { ZONE_HEADER zh; memset(&zh, 0, sizeof(zh)); zh.x1 = m_Zones[i].x1; zh.y1 = m_Zones[i].y1; zh.x2 = m_Zones[i].x2; zh.y2 = m_Zones[i].y2; zh.layer = m_Zones[i].layer; zh.reactivate_in_num_steps = m_Zones[i].reactivate_in_num_steps; file->Write(&zh, sizeof(zh)); WriteMapString(file, m_Zones[i].script.c_str()); } // end for zones // save the tileset if (!m_Tileset.SaveToFile(file)) { file->Close(); return false; } file->Close(); return true; }
bool sMap::Load(const char* filename, IFileSystem& fs) { // open the file IFile* file = fs.Open(filename, IFileSystem::read); if (file == NULL) { return false; } // read the header MAP_HEADER header; file->Read(&header, sizeof(header)); // make sure it's valid if (memcmp(header.signature, ".rmp", 4) != 0 || header.version != 1 || (header.num_strings != 3 && header.num_strings != 5 && header.num_strings != 9)) { file->Close(); return false; } m_StartX = header.startx; m_StartY = header.starty; m_StartLayer = header.startlayer; m_StartDirection = header.startdirection; // read the strings (tileset, music, script) std::string tileset_file = ReadMapString(file); // OBSOLETE m_MusicFile = ReadMapString(file); ReadMapString(file); // script file if (header.num_strings == 3) { m_EntryScript = ""; m_ExitScript = ""; } else { m_EntryScript = ReadMapString(file); m_ExitScript = ReadMapString(file); } if (header.num_strings > 5) { m_EdgeScripts[0] = ReadMapString(file); m_EdgeScripts[1] = ReadMapString(file); m_EdgeScripts[2] = ReadMapString(file); m_EdgeScripts[3] = ReadMapString(file); } // delete the old layer array and allocate a new one m_Layers.clear(); m_Layers.resize(header.num_layers); // read the layers for (int i = 0; i < header.num_layers; i++) { // read the layer header LAYER_HEADER lh; file->Read(&lh, sizeof(lh)); // read the layer name std::string name = ReadMapString(file); // set all layer attributes m_Layers[i].SetName(name.c_str()); m_Layers[i].Resize(lh.width, lh.height); m_Layers[i].SetXParallax(lh.parallax_x); m_Layers[i].SetYParallax(lh.parallax_y); m_Layers[i].SetXScrolling(lh.scrolling_x); m_Layers[i].SetYScrolling(lh.scrolling_y); m_Layers[i].SetVisible((lh.flags & 1) == 0); m_Layers[i].EnableParallax((lh.flags & 2) != 0); m_Layers[i].SetReflective(lh.reflective != 0); // read the layer data for (int iy = 0; iy < lh.height; iy++) { for (int ix = 0; ix < lh.width; ix++) { word tile; file->Read(&tile, sizeof(tile)); m_Layers[i].SetTile(ix, iy, tile); } } // load the obstruction map for (int j = 0; j < lh.num_segments; j++) { dword x1; file->Read(&x1, sizeof(dword)); dword y1; file->Read(&y1, sizeof(dword)); dword x2; file->Read(&x2, sizeof(dword)); dword y2; file->Read(&y2, sizeof(dword)); m_Layers[i].GetObstructionMap().AddSegment(x1, y1, x2, y2); } } // end for layer // delete the old entities m_Entities.clear(); // read entities for (int i = 0; i < header.num_entities; i++) { ENTITY_HEADER eh; file->Read(&eh, sizeof(eh)); sEntity* entity; switch (eh.type) { // PERSON case 1: { sPersonEntity* person = new sPersonEntity; // read the person data person->name = ReadMapString(file); person->spriteset = ReadMapString(file); word num_strings = ReadMapWord(file); // strings if (num_strings >= 1) person->script_create = ReadMapString(file); if (num_strings >= 2) person->script_destroy = ReadMapString(file); if (num_strings >= 3) person->script_activate_touch = ReadMapString(file); if (num_strings >= 4) person->script_activate_talk = ReadMapString(file); if (num_strings >= 5) person->script_generate_commands = ReadMapString(file); // reserved for (int i = 0; i < 16; i++) ReadMapByte(file); entity = person; break; } // TRIGGER case 2: { sTriggerEntity* trigger = new sTriggerEntity; // read/set the trigger data trigger->script = ReadMapString(file); entity = trigger; break; } default: // unknown continue; } // end switch entity->x = eh.mapx; entity->y = eh.mapy; entity->layer = eh.layer; AddEntity(entity); } // clear the zones m_Zones.clear(); // load the zones for (int i = 0; i < header.num_zones; i++) { ZONE_HEADER zh; sZone zone; file->Read(&zh, sizeof(zh)); zone.x1 = zh.x1; zone.y1 = zh.y1; zone.x2 = zh.x2; zone.y2 = zh.y2; zone.layer = zh.layer; zone.reactivate_in_num_steps = zh.reactivate_in_num_steps; zone.script = ReadMapString(file); m_Zones.push_back(zone); } // if no tileset file was specified, it is appended to the map file if (tileset_file.length() == 0) { if (!m_Tileset.LoadFromFile(file)) { file->Close(); return false; } } else m_Tileset.Clear(); file->Close(); return true; }