void CheckDir(GString path) { struct stat st; if (stat(path.c_str(), &st)) { #if (defined WIN32) && !(defined MINGW) _mkdir(path.c_str()); #else mkdir(path.c_str(), S_IWUSR); #endif } }
std::wstring Widen(GString Line) { wchar_t u16s[2048]; // Ought to be enough for everyone. #ifndef WIN32 mbstowcs(u16s, Line.c_str(), 2048); #else memset(u16s, 0, sizeof(wchar_t) * 2048); size_t len = MultiByteToWideChar(CP_UTF8, 0, Line.c_str(), Line.length(), u16s, 2048); #endif return std::wstring(u16s); }
void Output(Directory PathOut) { Directory Sn = Song->SongName; Sn.Normalize(true); GString name = Utility::Format("%s/ %s (%s) - %s.bms", PathOut.c_path(), Sn.c_path(), Parent->Name, Parent->Author); #ifndef _WIN32 std::ofstream out(name.c_str()); #else std::ofstream out(Utility::Widen(name).c_str()); #endif try { if (!out.is_open()) throw std::exception( (Utility::Format("failed to open file %S", name).c_str() ) ); if (BPS.size() == 0) throw std::exception("There are no timing points!"); WriteBMSOutput(); out << OutFile.str(); } catch (std::exception &e) { Log::Printf("Error while converting: %s\n", e.what()); } }
SongDatabase::SongDatabase(GString Database) { int ret = sqlite3_open_v2(Database.c_str(), &db, SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); if (ret != SQLITE_OK) Log::Printf("Unable to open song database file."); else { char* err; // Do the "create tables" query. const char* tail; SC(sqlite3_exec(db, DatabaseQuery, NULL, NULL, &err)); // And not just that, also the statements. SC(sqlite3_prepare_v2(db, InsertSongQuery, strlen(InsertSongQuery), &st_SngInsertQuery, &tail)); SC(sqlite3_prepare_v2(db, InsertDifficultyQuery, strlen(InsertDifficultyQuery), &st_DiffInsertQuery, &tail)); SC(sqlite3_prepare_v2(db, GetFilenameIDQuery, strlen(GetFilenameIDQuery), &st_FilenameQuery, &tail)); SC(sqlite3_prepare_v2(db, InsertFilenameQuery, strlen(InsertFilenameQuery), &st_FilenameInsertQuery, &tail)); SC(sqlite3_prepare_v2(db, GetLMTQuery, strlen(GetLMTQuery), &st_LMTQuery, &tail)); SC(sqlite3_prepare_v2(db, GetSongInfo, strlen(GetSongInfo), &st_GetSongInfo, &tail)); SC(sqlite3_prepare_v2(db, GetDiffInfo, strlen(GetDiffInfo), &st_GetDiffInfo, &tail)); SC(sqlite3_prepare_v2(db, GetFileInfo, strlen(GetFileInfo), &st_GetFileInfo, &tail)); SC(sqlite3_prepare_v2(db, UpdateLMT, strlen(UpdateLMT), &st_UpdateLMT, &tail)); SC(sqlite3_prepare_v2(db, GetDiffIDFileID, strlen(GetDiffIDFileID), &st_GetDiffIDFile, &tail)); SC(sqlite3_prepare_v2(db, UpdateDiff, strlen(UpdateDiff), &st_DiffUpdateQuery, &tail)); SC(sqlite3_prepare_v2(db, GetDiffFilename, strlen(GetDiffFilename), &st_GetDiffFilename, &tail)); SC(sqlite3_prepare_v2(db, GetSongIDFromFilename, strlen(GetSongIDFromFilename), &st_GetSIDFromFilename, &tail)); SC(sqlite3_prepare_v2(db, GetLatestSongID, strlen(GetLatestSongID), &st_GetLastSongID, &tail)); SC(sqlite3_prepare_v2(db, GetAuthorOfDifficulty, strlen(GetAuthorOfDifficulty), &st_GetDiffAuthor, &tail)); SC(sqlite3_prepare_v2(db, GetPreviewOfSong, strlen(GetPreviewOfSong), &st_GetPreviewInfo, &tail)); SC(sqlite3_prepare_v2(db, sGetStageFile, strlen(sGetStageFile), &st_GetStageFile, &tail)); } }
int Require(lua_State *L) { LuaManager *Lua = GetObjectFromState<LuaManager>(L, "Luaman"); GString Request = luaL_checkstring(L, 1); GString File = GameState::GetInstance().GetSkinScriptFile(Request.c_str()); lua_pushboolean(L, Lua->Require(File)); return 1; }
vector<GString> TokenSplit(const GString& str, const GString &token, bool compress) { vector<GString> ret; size_t len = str.length(); auto it = &str[0]; auto next = strpbrk(str.c_str(), token.c_str()); // next token instance for (; next != nullptr; next = strpbrk(it, token.c_str())) { if (!compress || it - next != 0) ret.push_back(GString(it, next)); it = next + 1; } if (it != next && len) ret.push_back(GString(it, &str[len])); return ret; }
// Inserts a filename, if it already exists, updates it. // Returns the ID of the filename. int SongDatabase::InsertFilename(Directory Fn) { int ret; int idOut; int lmt; SC(sqlite3_bind_text(st_FilenameQuery, 1, Fn.c_path(), Fn.path().length(), SQLITE_STATIC)); if (sqlite3_step(st_FilenameQuery) == SQLITE_ROW) { idOut = sqlite3_column_int(st_FilenameQuery, 0); lmt = sqlite3_column_int(st_FilenameQuery, 1); int lastLmt = Utility::GetLMT(Fn.path()); // Update the last-modified-time of this file, and its hash if it has changed. if (lmt != lastLmt) { GString Hash = Utility::GetSha256ForFile(Fn); SC(sqlite3_bind_int(st_UpdateLMT, 1, lastLmt)); SC(sqlite3_bind_text(st_UpdateLMT, 2, Hash.c_str(), Hash.length(), SQLITE_STATIC)); SC(sqlite3_bind_text(st_UpdateLMT, 3, Fn.c_path(), Fn.path().length(), SQLITE_STATIC)); SCS(sqlite3_step(st_UpdateLMT)); SC(sqlite3_reset(st_UpdateLMT)); } }else { GString Hash = Utility::GetSha256ForFile(Fn); // There's no entry, got to insert it. SC(sqlite3_bind_text(st_FilenameInsertQuery, 1, Fn.c_path(), Fn.path().length(), SQLITE_STATIC)); SC(sqlite3_bind_int(st_FilenameInsertQuery, 2, Utility::GetLMT(Fn.path()))); SC(sqlite3_bind_text(st_FilenameInsertQuery, 3, Hash.c_str(), Hash.length(), SQLITE_STATIC)); SCS(sqlite3_step(st_FilenameInsertQuery)); // This should not fail. Otherwise, there are bigger problems to worry about... SC(sqlite3_reset(st_FilenameInsertQuery)); // okay, then return the ID. SC(sqlite3_reset(st_FilenameQuery)); SC(sqlite3_bind_text(st_FilenameQuery, 1, Fn.c_path(), Fn.path().length(), SQLITE_STATIC)); sqlite3_step(st_FilenameQuery); idOut = sqlite3_column_int(st_FilenameQuery, 0); } SC(sqlite3_reset(st_FilenameQuery)); return idOut; }
bool FileExists(GString Fn) { #if !(defined WIN32) || (defined MINGW) struct stat st; return (stat(Fn.c_str(), &st) != -1); #else return _waccess( Utility::Widen(Fn).c_str(), 00 ) != -1; #endif }
int GetLMT(GString Path) { struct stat st; if (stat(Path.c_str(), &st) != -1) { return st.st_mtime; } else return 0; }
GString SJIStoU8 (GString Line) { #ifdef WIN32 wchar_t u16s[MAX_STRING_SIZE]; char mbs[MAX_STRING_SIZE]; size_t len = MultiByteToWideChar(932, 0, Line.c_str(), Line.length(), u16s, MAX_STRING_SIZE); len = WideCharToMultiByte(CP_UTF8, 0, u16s, len, mbs, MAX_STRING_SIZE, NULL, NULL); mbs[len] = 0; return GString(mbs); #elif defined(DARWIN) // Note: for OS X/Darwin/More than likely most BSD variants, iconv behaves a bit differently. iconv_t conv; char buf[MAX_STRING_SIZE]; char* out = buf; size_t srcLength = Line.length(); size_t dstLength = MAX_STRING_SIZE; const char* in = Line.c_str(); conv = iconv_open("UTF-8", "SHIFT_JIS"); iconv(conv, (char**)&in, &srcLength, (char**)&out, &dstLength); iconv_close(conv); // We have to use buf instead of out here. For whatever reason, iconv on Darwin doesn't get us what we would expect if we just use out. return GString(buf); #else char buf[MAX_STRING_SIZE]; iconv_t conv; char** out = &buf; const char* in = Line.c_str(); size_t BytesLeftSrc = Line.length(); size_t BytesLeftDst = MAX_STRING_SIZE; conv = iconv_open("UTF-8", "SHIFT_JIS"); bool success = (iconv(conv, (char **)&in, &BytesLeftSrc, out, &BytesLeftDst) > -1); iconv_close(conv); if (success) return GString(*out); else { Log::Printf("Failure converting character sets."); return GString(); } #endif }
GString Format(GString str, ...) { char r[1024]; int bfsize; va_list vl; va_start(vl,str); bfsize = vsnprintf(r, 1024, str.c_str(), vl); if (bfsize < 0) { Utility::DebugBreak(); va_end(vl); return ""; } vector<char> fmt(bfsize + 1); vsnprintf(&fmt[0], bfsize, str.c_str(), vl); va_end(vl); return GString(fmt.data()); }
int KeyTranslate(GString K) { for (uint32 i = 0; i < SpecialKeys.size(); i++) { GString Key = K; Utility::ToLower(Key); GString Target = GString(SpecialKeys.at(i).KeyString); Utility::ToLower(Target); if (Key == Target) return SpecialKeys.at(i).boundkey; } if (K.length()) { if (Utility::IsNumeric(K.c_str())) return atoi(K.c_str()); else return (int)K[0]; } else return 0; }
int GetTracksByMode(GString mode) { for (auto v: ModeTracks) { if (mode == v.name) return v.tracks; } Log::LogPrintf("Unknown track mode: %s, skipping difficulty\n", mode.c_str()); return 0; }
// 初始化表情数据 bool TextureFontInfo::Init(IGraphic* pGraphic, uint32 idx, GString texname, CFRect pos, GWString des) { ITexture* pTexture = NULL; SafeRelease(EmtImg.pTexture); if ( texname.c_str() && texname[0] ) { HRESULT hr = pGraphic->CreateTexture( PATH_ALIAS_GUITEX.c_str(), texname.c_str(), &pTexture ); // szTextName if(FAILED(hr)) OutputDebugString(texname.c_str()); if ( !pTexture ) return false; } EmtImg.pTexture = pTexture; EmtImg.texRt = pos; EmtIdx = idx; EmtTexName = texname; EmtDes = des; return true; }
void ReadDifficulty (GString line, OsuLoadInfo* Info) { GString Command = line.substr(0, line.find_first_of(":")); // Lines are Information:Content GString Content = line.substr(line.find_first_of(":") + 1, line.length() - line.find_first_of(":")); Utility::Trim(Content); // We ignore everything but the key count! if (Command == "CircleSize") { Info->Diff->Channels = atoi(Content.c_str()); }else if (Command == "SliderMultiplier") { Info->SliderVelocity = latof(Content.c_str()) * 100; } else if (Command == "HPDrainRate") { Info->TimingInfo->HP = latof(Content.c_str()); } else if (Command == "OverallDifficulty") { Info->TimingInfo->OD = latof(Content.c_str()); } }
bool ReadGeneral (GString line, OsuLoadInfo* Info) { GString Command = line.substr(0, line.find_first_of(" ")); // Lines are Information:<space>Content GString Content = line.substr(line.find_first_of(":") + 1); Content = Content.substr(Content.find_first_not_of(" ")); if (Command == "AudioFilename:") { if (Content == "virtual") { Info->Diff->IsVirtual = true; return true; } else { #ifdef VERBOSE_DEBUG printf("Audio filename found: %s\n", Content.c_str()); #endif Utility::Trim(Content); Info->OsuSong->SongFilename = Content; Info->OsuSong->SongPreviewSource = Content; } }else if (Command == "Mode:") { Info->ReadAModeTag = true; if (Content != "3") // It's not a osu!mania chart, so we can't use it. return false; }else if (Command == "SampleSet:") { Utility::ToLower(Content); Utility::Trim(Content); Info->DefaultSampleset = Content; } else if (Command == "PreviewTime:") { if (Content != "-1") { if (Info->OsuSong->PreviewTime == 0) Info->OsuSong->PreviewTime = latof(Content) / 1000; } } else if (Command == "SpecialStyle:") { if (Content == "1") Info->Diff->Data->Turntable = true; } return true; }
// returns if difficulty exists in the database. And difficulty ID. bool SongDatabase::DifficultyExists(int FileID, GString DifficultyName, int *IDOut) { int ret; SC(sqlite3_bind_int (st_GetDiffIDFile, 1, FileID)); SC(sqlite3_bind_text(st_GetDiffIDFile, 2, DifficultyName.c_str(), DifficultyName.length(), SQLITE_STATIC)); int r = sqlite3_step(st_GetDiffIDFile); if (IDOut) { if (r == SQLITE_ROW) *IDOut = sqlite3_column_int(st_GetDiffIDFile, 0); else *IDOut = 0; } SC(sqlite3_reset(st_GetDiffIDFile)); return r == SQLITE_ROW; }
void ConvertToNPSGraph(VSRG::Song *Sng, Directory PathOut) { for (auto i = 0; i < Sng->Difficulties.size(); i++) { std::ofstream out; auto Diff = Sng->GetDifficulty(i); Directory Sn = Sng->SongName; Sn.Normalize(true); GString name = Utility::Format("%s/ %s (%s) - %s.svg", PathOut.c_path(), Sn.c_path(), Diff->Name, Diff->Author); out.open(name.c_str()); double interv = CfgValNPS("IntervalTime", 1); double margin = CfgValNPS("PeakMargin", 1.2f); out << NPSGraph(Sng).GetSVGText(i, interv, margin); } }
GString GetSha256ForFile(GString Filename) { SHA256 SHA; #ifndef WIN32 std::ifstream InStream(Filename.c_str()); #else std::ifstream InStream(Utility::Widen(Filename).c_str()); #endif unsigned char tmpbuf[256]; if (!InStream.is_open()) return ""; while (!InStream.eof()) { InStream.read((char*)tmpbuf, 256); size_t cnt = InStream.gcount(); SHA.add(tmpbuf, cnt); } return GString(SHA.getHash()); }
int GetFallbackFile(lua_State *L) { GString Out = GameState::GetInstance().GetFallbackSkinFile(GString(luaL_checkstring(L, 1))); lua_pushstring(L, Out.c_str()); return 1; }
void LoadBmFont(BitmapFont* B, GString Fn, float CellWidth, float CellHeight, float CharWidth, float CharHeight, int startChar) { Vec2 Size(CharWidth, CharHeight); Vec2 CellSize(CellWidth, CellHeight); B->LoadSkinFontImage(Fn.c_str(), Size, CellSize, Size, startChar); }
bool CDx9FragmentProgram::load(const GString str) { return load(str.c_str(),str.length()); }
// Wrapper functions void SetImage(Sprite *O, GString dir) { O->SetImage(GameState::GetInstance().GetSkinImage(dir)); if (O->GetImage() == nullptr) Log::Printf("File %s could not be loaded.\n", dir.c_str()); }
void NoteLoaderOM::LoadObjectsFromFile(GString filename, GString prefix, Song *Out) { #if (!defined _WIN32) || (defined STLP) std::ifstream filein (filename.c_str()); #else std::ifstream filein (Utility::Widen(filename).c_str()); #endif std::regex versionfmt("osu file format v(\\d+)"); if (!filein.is_open()) throw std::exception("Could not open file."); auto Diff = make_shared<Difficulty>(); OsuLoadInfo Info; Info.TimingInfo = make_shared<OsuManiaTimingInfo>(); Info.OsuSong = Out; Info.SliderVelocity = 1.4; Info.Diff = Diff; Info.last_sound_index = 1; Diff->Data = make_shared<DifficultyLoadInfo>(); Diff->Data->TimingInfo = Info.TimingInfo; // osu! stores bpm information as the time in ms that a beat lasts. Diff->BPMType = Difficulty::BT_BEATSPACE; Out->SongDirectory = prefix; Diff->Filename = filename; Out->SongDirectory = prefix + "/"; /* Just like BMS, osu!mania charts have timing data separated by files and a set is implied using folders. */ GString Line; getline(filein, Line); int version = -1; std::smatch sm; // "search" was picked instead of "match" since a line can have a bunch of // junk before the version declaration if (regex_search(Line.cbegin(), Line.cend(), sm, versionfmt)) version = atoi(sm[1].str().c_str()); else throw std::exception("Invalid .osu file."); // "osu file format v" if (version < 10) // why throw std::exception(Utility::Format("Unsupported osu! file version (%d < 10)", version).c_str()); Info.Version = version; osuReadingMode ReadingMode = RNotKnown, ReadingModeOld = RNotKnown; try { while (filein) { Info.Line++; getline(filein, Line); Utility::ReplaceAll(Line, "\r", ""); if (!Line.length()) continue; SetReadingMode(Line, ReadingMode); if (ReadingMode != ReadingModeOld || ReadingMode == RNotKnown) // Skip this line since it changed modes, or it's not a valid section yet { if (ReadingModeOld == RTiming) stable_sort(Info.HitsoundSections.begin(), Info.HitsoundSections.end()); if (ReadingModeOld == RGeneral) if (!Info.ReadAModeTag) throw std::exception("Not an osu!mania chart."); ReadingModeOld = ReadingMode; continue; } switch (ReadingMode) { case RGeneral: if (!ReadGeneral(Line, &Info)) // don't load charts that we can't work with { throw std::exception("osu! file unusable on raindrop."); } break; case RMetadata: ReadMetadata(Line, &Info); break; case RDifficulty: ReadDifficulty(Line, &Info); break; case REvents: ReadEvents(Line, &Info); break; case RTiming: ReadTiming(Line, &Info); break; case RHitobjects: ReadObjects(Line, &Info); break; default: break; } } if (Diff->TotalObjects) { // Calculate an alleged offset Offsetize(&Info); // Okay then, convert timing data into a measure-based format raindrop can use. MeasurizeFromTimingData(&Info); CopyTimingData(&Info); // Then copy notes into these measures. PushNotesToMeasures(&Info); // Copy all sounds we registered for (auto i : Info.Sounds) Diff->SoundList[i.second] = i.first; // Calculate level as NPS Diff->Level = Diff->TotalScoringObjects / Diff->Duration; Out->Difficulties.push_back(Diff); } } catch (std::exception &e) { // rethrow with line info throw std::exception(Utility::Format("Line %d: %s", Info.Line, e.what()).c_str()); } }
const char* CSkeletalFrame::GetSkeletalName( uint32 SkeletalID ) { static GString str = ""; return SkeletalID < m_SkeletalList.size() ? m_SkeletalList[SkeletalID]->m_pSkeletal->GetName() : str.c_str(); }