Example #1
0
void ReadMetadata (GString line, OsuLoadInfo* Info)
{
	auto Command = line.substr(0, line.find_first_of(":")); // Lines are Information:Content
	auto Content = line.substr(line.find_first_of(":") + 1, line.length() - line.find_first_of(":"));

#ifdef VERBOSE_DEBUG
	printf("Command found: %s | Contents: %s\n", Command.c_str(), Content.c_str());
#endif

	Utility::Trim(Content);
	if (Command == "Title")
	{
		Info->OsuSong->SongName = Content;
	}else if (Command == "Artist")
	{
		Info->OsuSong->SongAuthor = Content;
	}else if (Command == "Version")
	{
		Info->Diff->Name = Content;
	}else if (Command == "TitleUnicode")
	{
		if (Content.length() > 1)
			Info->OsuSong->SongName = Content;
	}else if (Command == "ArtistUnicode")
	{
		if (Content.length() > 1)
			Info->OsuSong->SongAuthor = Content;
	}
	else if (Command == "Creator")
	{
		Info->Diff->Author = Content;
	}
}
Example #2
0
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;
}
GString SP2::GGeneralEventHandler::ReplaceNextPattern(GString in_sSentence, GString in_ReplacingString, GString in_sPattern) const
{
	UINT32 l_iCurrentPosition = 0;
	UINT32 l_iStartPosition = 0;

	bool l_bSuccess = false;

	for(UINT32 i=0; i<in_sSentence.size(); i++)
	{
		if(in_sSentence.at(i) == in_sPattern.at(l_iCurrentPosition))
		{
			if(l_iCurrentPosition == 0)
				l_iStartPosition = i;			
			l_iCurrentPosition++;
			if(l_iCurrentPosition == in_sPattern.size())
			{
				l_bSuccess = true;
				break;
			}
		}
		else
		{
			if(l_iCurrentPosition > 0)
			{
				l_iCurrentPosition = 0;
				i = l_iStartPosition + 1;
			}
		}			
	}
	if(l_bSuccess)
	{
		GString l_Results;
		l_Results += in_sSentence.substr(0,l_iStartPosition);
		l_Results += in_ReplacingString;
		l_Results += in_sSentence.substr(l_iStartPosition+in_sPattern.size(),in_sSentence.size());
		return l_Results;
	}
	return L"";
}
Example #4
0
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());
	}

}
Example #5
0
bool LoadTracksSM(Song *Out, Difficulty *Diff, GString line)
{
	GString CommandContents = line.substr(line.find_first_of(":") + 1);

	/* Remove newlines and comments */
	CommandContents = RemoveComments(CommandContents);

	/* Split contents */
	auto Mainline = Utility::TokenSplit(CommandContents, ":");

	if (Mainline.size() < 6) // No, like HELL I'm loading this.
	{
		// The first time I found this it was because a ; was used as a separator instead of a :
		// Which means a rewrite is what probably should be done to fix that particular case.
		wprintf(L"Corrupt simfile (%d entries instead of 6)", Mainline.size());
		return false;
	}

	/* What we'll work with */
	GString NoteString = Mainline[5];
	int Keys = GetTracksByMode(Mainline[0]);

	if (!Keys)
		return false;

	Diff->Level = atoi(Mainline[3].c_str());
	Diff->Channels = Keys;
	Diff->Name = Mainline[2] + "(" + Mainline[0] + ")";

	/* Now we should have our notes within NoteGString.
	We'll split them by measure using , as a separator.*/
	auto MeasureText = Utility::TokenSplit(NoteString);

	LoadNotesSM(Out, Diff, MeasureText);

	/*
		Through here we can make a few assumptions.
		->The measures are in order from start to finish
		->Each measure has all potential playable tracks, even if that track is empty during that measure.
		->Measures are internally ordered
		*/
	return true;
}
Example #6
0
GCallStack::GCallStack(HANDLE hThread, CONTEXT& c)
{
	if (!_bLockInit) // only init the single instance of the CRITICAL_SECTION 1 time for the many instances of GCallStack
	{
		InitializeCriticalSection(&_DbgHelpLock);
		_bLockInit = true;
	}

	DWORD imageType = IMAGE_FILE_MACHINE_I386;
	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
	int frameNum = 0; // counts walked frames
	int MAX_STACK_FRAMES = 7777; // in C# the maximum stack frames imposed by the language is 1000.  Arbitrary limit to guarantee no condition of infinate walking in corrupted memory.
	DWORD offsetFromLine; // tells us line number in the source file
#if defined(_LINUX64) || defined(_WIN64) || defined(_IOS)
	unsigned __int64 offsetFromSymbol; // tells us how far from the symbol we were
#else
	DWORD offsetFromSymbol; // tells us how far from the symbol we were
#endif

	DWORD symOptions; // symbol handler settings
	IMAGEHLP_SYMBOL *pSym = (IMAGEHLP_SYMBOL *) malloc( IMGSYMLEN + MAXNAMELEN );

	GString strStackName(MAXNAMELEN + 512); // undecorated method/function name + Source file and line number

	IMAGEHLP_MODULE Module;
	IMAGEHLP_LINE Line;
	STACKFRAME64 s; // in/out stackframe
	memset( &s, '\0', sizeof s );

//  note: converted code from [std::string symSearchPath] to [GString symSearchPath] so it will compile with the _UNICODE build flag - 8/18/2014
	GString symSearchPath;

#ifdef _UNICODE
	wchar_t *tt = 0, *p;
	tt = new wchar_t[TTBUFLEN];
#else
	char *tt = 0, *p;
	tt = new char[TTBUFLEN];
#endif

	// build symbol search path from:
	symSearchPath = "";
	// current directory
	if (GetCurrentDirectory(TTBUFLEN, tt))
		symSearchPath << tt << "; ";
	// dir with executable
	if ( GetModuleFileName( 0, tt, TTBUFLEN ) )
	{
#ifdef _UNICODE
		for (p = tt + wcslen(tt) - 1; p >= tt; --p)
#else
		for (p = tt + strlen(tt) - 1; p >= tt; --p)	// VC6 does not have a _tcsclen() and we still support VC6
#endif
		{
			// locate the rightmost path separator
			if ( *p == '\\' || *p == '/' || *p == ':' )
				break;
		}
		// if we found one, p is pointing at it; if not, tt only contains an exe name (no path), and p points before its first byte
		if ( p != tt ) // path sep found?
		{
			if ( *p == ':' ) // we leave colons in place
				++ p;
			*p = '\0'; // eliminate the exe name and last path sep
			symSearchPath << tt << "; "; 
		}
	}
	// environment variable _NT_SYMBOL_PATH
	GString g("_NT_SYMBOL_PATH");
	if (GetEnvironmentVariable(g, tt, TTBUFLEN))
		symSearchPath << tt << "; ";
	// environment variable _NT_ALTERNATE_SYMBOL_PATH
	g = "_NT_ALTERNATE_SYMBOL_PATH";
	if (GetEnvironmentVariable(g, tt, TTBUFLEN))
		symSearchPath << tt << "; ";
	// environment variable SYSTEMROOT
	g = "SYSTEMROOT";
	if (GetEnvironmentVariable(g, tt, TTBUFLEN))
		symSearchPath << tt << "; ";

	if ( symSearchPath.size() > 0 ) // if we added anything, we have a trailing semicolon
		symSearchPath = symSearchPath.substr( 0, symSearchPath.size() - 1 );

	// 8/20/2014 note: In older Windows API's SymInitialize()'s 2nd argument was not defined as "const char *", it was only "char *" 
	// Although "const" was not defined, the API call is "const" in behavior.  In newer versions of the Windows API this has been fixed.
	// In newer versions - SymInitialize's 2nd argument may resolve to either "const char *" OR "const wchar_t *", and in those builds the
	// GString has a default conversion to the correct string type, however in the older build configurations, GString does not (and should not)
	// know how to resolve to a "char *" by default, so in that case the preprocessor directive isolates the code needed to convert to "char *" 

#if defined(_MSC_VER) && _MSC_VER <= 1200
	if (!SymInitialize(hProcess, symSearchPath.Buf(),	false))	// symSearchPath == (char *)
#else
	if (!SymInitialize(hProcess, symSearchPath,			true))  // symSearchPath == (const char *)  --OR--  (const wchar_t *) depending on the _UNICODE preprocessor definition
#endif
	{
		goto tagCleanUp;
	}

	symOptions = SymGetOptions();
	symOptions |= SYMOPT_LOAD_LINES;
	symOptions &= ~SYMOPT_UNDNAME;
	SymSetOptions( symOptions );

	enumAndLoadModuleSymbols( hProcess, GetCurrentProcessId() );

	// init STACKFRAME for first call, definitions found in ImageHlp.h
#ifdef _M_IX86
	imageType = IMAGE_FILE_MACHINE_I386;
	s.AddrPC.Offset = c.Eip;
	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Offset = c.Ebp;
	s.AddrFrame.Mode = AddrModeFlat;
	s.AddrStack.Offset = c.Esp;
	s.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
	imageType = IMAGE_FILE_MACHINE_AMD64;
	s.AddrPC.Offset = c.Rip;
	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Offset = c.Rsp;
	s.AddrFrame.Mode = AddrModeFlat;
	s.AddrStack.Offset = c.Rsp;
	s.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
	imageType = IMAGE_FILE_MACHINE_IA64;
	s.AddrPC.Offset = c.StIIP;
	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Offset = c.IntSp;
	s.AddrFrame.Mode = AddrModeFlat;
	s.AddrBStore.Offset = c.RsBSP;
	s.AddrBStore.Mode = AddrModeFlat;
	s.AddrStack.Offset = c.IntSp;
	s.AddrStack.Mode = AddrModeFlat;
#endif

	memset( pSym, '\0', IMGSYMLEN + MAXNAMELEN );
	pSym->SizeOfStruct = IMGSYMLEN;
	pSym->MaxNameLength = MAXNAMELEN;

	memset( &Line, '\0', sizeof Line );
	Line.SizeOfStruct = sizeof Line;

	memset( &Module, '\0', sizeof Module );
	Module.SizeOfStruct = sizeof Module;

	offsetFromSymbol = 0;

	
	//	DbgHelp is single threaded, so acquire a lock.
	EnterCriticalSection(&_DbgHelpLock);

	while ( frameNum < MAX_STACK_FRAMES )
	{
		// get next stack frame (StackWalk(), SymFunctionTableAccess(), SymGetModuleBase())
		// if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can
		// assume that either you are done, or that the stack is so hosed that the next deeper frame could not be found.
#ifdef _WIN64
		if (!StackWalk64(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
#else
		if (!StackWalk(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL))
#endif
			break;  // Maybe it failed, maybe we have finished walking the stack

		if ( s.AddrPC.Offset != 0 )
		{ 
			// Most likely a valid stack rame
			
			// show procedure info 
			if ( ! SymGetSymFromAddr64( hProcess, s.AddrPC.Offset, &offsetFromSymbol, pSym ) )
			{
				break;
			}
			else
			{
				// UnDecorateSymbolName() to get the Class::Method or function() name in tyhe callstack
				strStackName.Empty();
 				UnDecorateSymbolName(pSym->Name, strStackName._str, MAXNAMELEN, UNDNAME_COMPLETE);
				strStackName.SetLength(strlen(strStackName._str));

				// SymGetLineFromAddr() to get the source.cpp and the line number 
				IMAGEHLP_LINE64 Line;
				if (SymGetLineFromAddr64(hProcess, s.AddrPC.Offset, &offsetFromLine, &Line) != FALSE)
				{
					GString g(Line.FileName);  // Line.FileName conains the "c:\Full\Path\TO\Source.cpp"
					
					// Builds string "Foo::Bar[Source.cpp]@777"
					strStackName << "[" << g.StartingAt(g.ReverseFind("\\") + 1) << "]@" << Line.LineNumber; 
				}

				// add the GString to the GStringList, do not add frame 0 because it will always be GException::GSeception where we divided by 0
				if (frameNum > 0)
					_stk += strStackName;
			}
		}
		else
		{
			// base reached
			SetLastError(0);
			break;
		}

		++frameNum;
	}
	
	LeaveCriticalSection(&_DbgHelpLock);


	// de-init symbol handler etc. (SymCleanup())
	SymCleanup( hProcess );
	free( pSym );
tagCleanUp:;	
	delete [] tt;
	CloseHandle(hProcess);
}
shared_ptr<osb::SpriteList> ReadOSBEvents(std::istream& event_str)
{
	auto list = make_shared<osb::SpriteList>();
	int previous_lead = 100;
	shared_ptr<osb::BGASprite> sprite = nullptr;
	shared_ptr<osb::Loop> loop = nullptr;
	bool readingLoop = false;

	GString line;
	while (std::getline(event_str, line))
	{
		int lead_spaces;
		line = line.substr(line.find("//")); // strip comments
		lead_spaces = line.find_first_not_of("\t _");
		line = line.substr(lead_spaces, line.length() - lead_spaces + 1);

		vector<GString> split_result;
		boost::split(split_result, line, boost::is_any_of(","));
		for (auto &&s : split_result) boost::algorithm::to_lower(s);

		if (!line.length() || !split_result.size()) continue;

		if (lead_spaces < previous_lead && !readingLoop)
		{
			if (split_result[0] == "sprite")
			{
				Vec2 new_position(latof(split_result[3]), latof(split_result[4]));
				sprite = make_shared<osb::BGASprite>(split_result[1], OriginFromString(split_result[2]), new_position);
				list->push_back(sprite);
			}
		} else {
			if (!sprite)
				throw std::runtime_error("OSB command unpaired with sprite.");

			// If it's a loop, check if we're out of it.
			// If we're out of it, read a regular event, otherwise, read an event to the loop
			if (readingLoop)
			{
				if (lead_spaces < previous_lead) {
					readingLoop = false;

					// We're done reading the loop - unroll it.
					auto loop_events = loop->Unroll();
					for (auto i = 0; i < osb::EVT_COUNT; i++)
						for (auto evt : (*loop_events)[i])
							sprite->AddEvent(evt);
				}
				else
					loop->AddEvent(ParseEvent(split_result));
			}
			
			// It's not a command on the loop, or we weren't reading a loop in the first place.
			// Read a regular command.

			// Not "else" because we do want to execute this if we're no longer reading the loop.
			if (!readingLoop) {
				auto ev = ParseEvent(split_result);

				// A loop began - set that we are reading a loop and set this loop as where to add the following commands.
				if (ev->GetEventType() == osb::EVT_LOOP)
				{
					loop = static_pointer_cast<osb::Loop>(ev);
					readingLoop = true;
				}else // add this event, if not a loop to this sprite. It'll be unrolled once outside.
					sprite->AddEvent(ev);
			}
		}

		previous_lead = lead_spaces;
	}

	return list;
}
Example #8
0
	GString RemoveExtension(GString Fn)
	{
		return Fn.substr(0, Fn.find_last_of("."));
	}
Example #9
0
	GString RelativeToPath(GString Filename)
	{
		return Filename.substr(Filename.find_last_of("/"));
	}
Example #10
0
	GString GetExtension(GString Filename)
	{
		return Filename.substr(Filename.find_last_of(".")+1);
	}
Example #11
0
void LoadNotes(Song* Out, Difficulty * Diff, GString line)
{
	// get the object GString (all between a colon and a semicolon.
	GString objectString = line.substr(line.find_first_of(":") + 1);
	std::vector< GString > splitvec;
	bool invert = false;

	Diff->Name = Out->SongName; // todo: change this.
	Diff->TotalNotes = Diff->TotalHolds = Diff->TotalObjects = 0;

	// Remove whitespace.
	Utility::ReplaceAll(objectString, "[\n\r]", "");

	splitvec = Utility::TokenSplit(objectString); // Separate measures!
	for(GString objectlist: splitvec) // for each measure
	{
		std::vector< GString > splitobjects;
		Measure Msr;
		invert = false;

		if ( objectlist.length() == 0 )
		{
			Diff->Measures.push_back(Msr);
			continue;
		}

		/* Mirror command. */
		if ( objectlist[0] == 'M')
		{
			invert = true;
			Utility::ReplaceAll(objectlist, "M", "");
		}

		splitobjects = Utility::TokenSplit(objectlist, "{}", true);
		size_t SoSize = 0;
		size_t CurObj = 0;

		for(GString object_description: splitobjects) // Count total valid objects
		{
			if (object_description.length() != 0)
				SoSize += 1;
		}

		for(GString object_description: splitobjects) // For all objects in measure
		{
			std::vector< GString > object_parameters;

			if (object_description.length() == 0) // we must have at least a plain "0"
				continue;

			object_parameters = Utility::TokenSplit(object_description, " :");
			if (object_parameters.size() > 0) // We got a position
			{
				int32 xpos = 0;
				float hold_duration = 0;
				int32 sound = 0;

				if (object_parameters[0].length() > 0) // does it have length?
					xpos = latof (object_parameters[0].c_str()); // assign it
				

				if (object_parameters.size() > 1) // We got a hold note parameter
				{
					if (object_parameters[1].length() > 0) // length?
						hold_duration = latof (object_parameters[1].c_str()); // load it in

					if (object_parameters.size() > 2) // We got a sound parameter
					{
						if (object_parameters[2].length() > 0) // got a valid sound?
							sound = latof (object_parameters[2].c_str()); // cast it in
					}
				}

				if (invert)
				{
					if (xpos != 0)
						xpos = PlayfieldWidth - xpos;
				}

				GameObject Temp;

				if (xpos != 0)
				{
					Temp.SetPositionX(xpos);
					Diff->TotalObjects++;

					if (hold_duration)
						Diff->TotalHolds++;
					else
						Diff->TotalNotes++;
				}
				else
				{
					/* Position 0 is a special X constant that will make the note invisible 
					as well as making it not emit any kind of judgment in-game. It's filler. */
					Temp.SetPositionX(0);
				}

				Temp.Assign(hold_duration, Diff->Measures.size(), (double)CurObj / SoSize);
				Msr.push_back(Temp);

			} // got a position
			CurObj++;
		} // foreach object in measure

		Diff->Measures.push_back(Msr);

	} // foreach measure

	Out->Difficulties.push_back(Diff); 
}
Example #12
0
Song* NoteLoader::LoadObjectsFromFile(GString filename, GString prefix)
{
	std::ifstream filein;
	filein.open(filename.c_str(), std::ios::in);
	Song *Out = new Song();
	Difficulty *Diff = new Difficulty();

	if (!filein.is_open())
	{
		throw std::exception(Utility::Format("Unable to open %s for reading!", filename.c_str()).c_str());
	}

	Out->SongDirectory = prefix;

	// get lines separating with ; token
	GString line;
	while (filein)
	{
		std::getline(filein, line, ';'); 
		GString command = line.substr(0, line.find_first_of(":"));

#define OnCommand(x) if(command.find(#x)!=GString::npos)
		
		GString CommandContents = line.substr(line.find_first_of(":") + 1);

		// First, metadata.
		OnCommand(#NAME)
		{
			Out->SongName = CommandContents;
		}

		OnCommand(#AUTHOR)
		{
			Out->SongAuthor = CommandContents;
		}

		OnCommand(#MLEN)
		{
			std::stringstream str (CommandContents);
			str >> Out->MeasureLength;
		}

		// Then, Timing data.
		OnCommand(#BPM)
		{
			LoadTimingList(Diff->Timing, line);
		}

		OnCommand(#OFFSET)
		{
			std::stringstream str (CommandContents);
			str >> Diff->Offset;
			Diff->Offset += Configuration::GetConfigf("OffsetDC");
		}

		// Then, file info.
		OnCommand(#SONG)
		{
			Out->SongFilename = CommandContents;
		}

		OnCommand(#BACKGROUNDIMAGE)
		{
			Out->BackgroundFilename = CommandContents;
		}

		OnCommand(#LEADIN)
		{
			std::stringstream str (CommandContents);
			str >> Out->LeadInTime;
		}

		OnCommand(#SOUNDS)
		{
			vector<GString> SoundList;
			GString CmdLine = CommandContents;
			// Diff->SoundList = Utility::TokenSplit(CmdLine, ",");
		}

		// Then, the charts.
		OnCommand(#NOTES) // current command is notes?
		{
			LoadNotes(Out, Diff, line);			
			Diff = new Difficulty();
		}// command == #notes
#undef OnCommand
	}
	delete Diff; // There will always be an extra copy.

	// at this point the objects are sorted! by measure and within the measure, by fraction.
	Out->Process();
	return Out;
}