From 3946800de6c7047db47dbbbe892e1cf7e09b6ffe Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 13:45:39 +0100 Subject: [PATCH 01/22] renamed ScoreManager to Score q --- .gitignore | 3 ++- source/GameplayElements/Lifebar.h | 1 - source/GameplayElements/{ScoreManager.cpp => Score.cpp} | 6 +++--- source/GameplayElements/{ScoreManager.h => Score.h} | 8 ++++---- source/Graphics/GfxInfo.h | 3 +++ source/HitObjects/HitObject.h | 2 +- source/Modes/Player.h | 2 +- source/Rulesets/Ruleset.cpp | 6 +++--- source/Rulesets/Ruleset.h | 4 ++-- source/Rulesets/RulesetOsu.cpp | 2 +- 10 files changed, 20 insertions(+), 17 deletions(-) rename source/GameplayElements/{ScoreManager.cpp => Score.cpp} (81%) rename source/GameplayElements/{ScoreManager.h => Score.h} (83%) diff --git a/.gitignore b/.gitignore index 8b887bf..0592167 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ .idea cmake-build-debug -build \ No newline at end of file +build +.vscode \ No newline at end of file diff --git a/source/GameplayElements/Lifebar.h b/source/GameplayElements/Lifebar.h index d182d42..c6852e6 100644 --- a/source/GameplayElements/Lifebar.h +++ b/source/GameplayElements/Lifebar.h @@ -1,7 +1,6 @@ #include #include -#include "ScoreManager.h" #include "System/GameClock.h" #include "Graphics/SpriteContainer.h" #include "Beatmaps/BeatmapManager.h" diff --git a/source/GameplayElements/ScoreManager.cpp b/source/GameplayElements/Score.cpp similarity index 81% rename from source/GameplayElements/ScoreManager.cpp rename to source/GameplayElements/Score.cpp index eb7f9c9..403aa13 100644 --- a/source/GameplayElements/ScoreManager.cpp +++ b/source/GameplayElements/Score.cpp @@ -1,12 +1,12 @@ -#include "ScoreManager.h" +#include "Score.h" -ScoreManager::ScoreManager() +Score::Score() { mScore = 0; mCombo = 0; } -void ScoreManager::Add(ScoreType score, bool forceNoCombo) +void Score::Add(ScoreType score, bool forceNoCombo) { if (score == SCORE_MISS) { diff --git a/source/GameplayElements/ScoreManager.h b/source/GameplayElements/Score.h similarity index 83% rename from source/GameplayElements/ScoreManager.h rename to source/GameplayElements/Score.h index 1fcfde3..d747d7f 100644 --- a/source/GameplayElements/ScoreManager.h +++ b/source/GameplayElements/Score.h @@ -17,15 +17,15 @@ typedef enum { SCORE_MISS = 0 } ScoreType; -class ScoreManager +class Score { public: - ScoreManager(); + Score(); void Add(ScoreType score, bool forceNoCombo = false); - u32 Score() { return mScore; } - u32 Combo() { return mCombo; } + u32 CurrentScore() { return mScore; } + u32 CurrentCombo() { return mCombo; } protected: u32 mScore; diff --git a/source/Graphics/GfxInfo.h b/source/Graphics/GfxInfo.h index 362c0a9..d3e789d 100644 --- a/source/Graphics/GfxInfo.h +++ b/source/Graphics/GfxInfo.h @@ -42,6 +42,9 @@ #include "white_bin.h" +#include +#include + //#include "songbg_osu_bin.h" typedef enum { diff --git a/source/HitObjects/HitObject.h b/source/HitObjects/HitObject.h index c26e21b..28629d3 100644 --- a/source/HitObjects/HitObject.h +++ b/source/HitObjects/HitObject.h @@ -3,7 +3,7 @@ #include "Beatmaps/BeatmapElements.h" #include "Beatmaps/DifficultyManager.h" -#include "GameplayElements/ScoreManager.h" +#include "GameplayElements/Score.h" #include "Graphics/pSprite.h" #include "Graphics/pAnimation.h" #include "Graphics/GfxInfo.h" diff --git a/source/Modes/Player.h b/source/Modes/Player.h index 399aaa8..7ae53fa 100644 --- a/source/Modes/Player.h +++ b/source/Modes/Player.h @@ -4,7 +4,7 @@ #include "System/GameClock.h" -#include "GameplayElements/ScoreManager.h" +#include "GameplayElements/Score.h" #include "Graphics/SpriteManager.h" #include "Helpers/AudioManager.h" #include "GameplayElements/Lifebar.h" diff --git a/source/Rulesets/Ruleset.cpp b/source/Rulesets/Ruleset.cpp index 9677738..acb1de8 100644 --- a/source/Rulesets/Ruleset.cpp +++ b/source/Rulesets/Ruleset.cpp @@ -45,10 +45,10 @@ void Ruleset::Update() TextManager::Bottom().SetFont(FONT_SCORE); - TextManager::Bottom().PrintLocate(635, 5, ORIGIN_TOPRIGHT, " %08i", mScoreManager.Score()); + TextManager::Bottom().PrintLocate(635, 5, ORIGIN_TOPRIGHT, " %08i", mCurrentScore.CurrentScore()); - if (mScoreManager.Combo() > 0) - TextManager::Bottom().PrintLocate(5, 475, ORIGIN_BOTTOMLEFT, "%ix ", mScoreManager.Combo()); + if (mCurrentScore.CurrentCombo() > 0) + TextManager::Bottom().PrintLocate(5, 475, ORIGIN_BOTTOMLEFT, "%ix ", mCurrentScore.CurrentCombo()); else TextManager::Bottom().PrintLocate(5, 475, ORIGIN_BOTTOMLEFT, " "); } diff --git a/source/Rulesets/Ruleset.h b/source/Rulesets/Ruleset.h index 92e41bf..40044fb 100644 --- a/source/Rulesets/Ruleset.h +++ b/source/Rulesets/Ruleset.h @@ -2,7 +2,7 @@ #include #include "Beatmaps/BeatmapManager.h" -#include "GameplayElements/ScoreManager.h" +#include "GameplayElements/Score.h" #include "Graphics/SpriteManager.h" #include "GameplayElements/Lifebar.h" #include "GameplayElements/HitObjectManager.h" @@ -25,7 +25,7 @@ class Ruleset virtual void HandleInput(); protected: - ScoreManager mScoreManager; + Score mCurrentScore; HitObjectManager mHitObjectManager; SpriteManager mSpriteManager; Lifebar mLifebar; diff --git a/source/Rulesets/RulesetOsu.cpp b/source/Rulesets/RulesetOsu.cpp index 6a931c2..1ccb8d3 100644 --- a/source/Rulesets/RulesetOsu.cpp +++ b/source/Rulesets/RulesetOsu.cpp @@ -75,7 +75,7 @@ void RulesetOsu::IncreaseScore(ScoreType score, bool forceNoCombo, bool forceNoA break; } - mScoreManager.Add(score, forceNoCombo); + mCurrentScore.Add(score, forceNoCombo); mLifebar.Increase(hpIncrease); if (!forceNoAnimation) From 1e649c50405077e46c1b3fd635e51914767fc615 Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 13:53:21 +0100 Subject: [PATCH 02/22] no more using namespace std; --- source/Beatmaps/Beatmap.cpp | 6 ++-- source/Beatmaps/Beatmap.h | 32 +++++++++++----------- source/Beatmaps/BeatmapElements.h | 8 +++--- source/Beatmaps/BeatmapManager.cpp | 2 +- source/Beatmaps/BeatmapManager.h | 8 +++--- source/GameplayElements/HitObjectManager.h | 6 ++-- source/Graphics/SpriteContainer.h | 6 ++-- source/Graphics/SpriteManager.cpp | 4 +-- source/Graphics/SpriteManager.h | 12 ++++---- source/Graphics/pSprite.h | 6 ++-- source/Helpers/AudioManager.cpp | 2 +- source/Helpers/AudioManager.h | 4 +-- source/Helpers/FileReader.cpp | 6 ++-- source/Helpers/FileReader.h | 6 ++-- source/HitObjects/HitSlider.cpp | 4 +-- source/HitObjects/HitSlider.h | 8 +++--- source/Rulesets/Ruleset.cpp | 2 +- source/System/ICallback.h | 2 +- source/System/TextManager.cpp | 2 +- source/System/TextManager.h | 2 +- 20 files changed, 64 insertions(+), 64 deletions(-) diff --git a/source/Beatmaps/Beatmap.cpp b/source/Beatmaps/Beatmap.cpp index f706eed..1f5317f 100644 --- a/source/Beatmaps/Beatmap.cpp +++ b/source/Beatmaps/Beatmap.cpp @@ -126,7 +126,7 @@ Beatmap::~Beatmap() delete mReader; } -void Beatmap::Buffer(list& hitObjectList) +void Beatmap::Buffer(std::list& hitObjectList) { if (!fReady) { @@ -166,7 +166,7 @@ void Beatmap::Buffer(list& hitObjectList) u32 lengthtime = mReader->ReadInt32(); u32 pointcount = mReader->ReadVarInt(); - vector points; + std::vector points; points.reserve(pointcount); for (u32 i=0; i& hitObjectList) } u32 tickcount = mReader->ReadVarInt(); - vector ticks; + std::vector ticks; ticks.reserve(tickcount); for (u32 i=0; i::iterator hitObjectIterator; @@ -34,17 +34,17 @@ class Beatmap void Initialize(); void CleanUp(); - void Buffer(list& hitObjectList); + void Buffer(std::list& hitObjectList); bool GameOver() { return mHitObjectRead == mHitObjectCount && GameClock::Clock().Time() >= mLastObjectEndTime + 3000; } - string& Filename() { return mFilename; } - string& Title() { return mTitle; } - string& Artist() { return mArtist; } - string& Creator() { return mCreator; } - string& Version() { return mVersion; } - string& AudioFilename() { return mAudioFilename; } + std::string& Filename() { return mFilename; } + std::string& Title() { return mTitle; } + std::string& Artist() { return mArtist; } + std::string& Creator() { return mCreator; } + std::string& Version() { return mVersion; } + std::string& AudioFilename() { return mAudioFilename; } - string& BaseDir() { return mBaseDir; } + std::string& BaseDir() { return mBaseDir; } s32 SkipTime() { return mSkipTime; } s32 StartTime() { return mFirstObjectTime; } @@ -65,14 +65,14 @@ class Beatmap bool fReady, fLoadable; - string mFilename; - string mTitle; - string mArtist; - string mCreator; - string mVersion; - string mAudioFilename; + std::string mFilename; + std::string mTitle; + std::string mArtist; + std::string mCreator; + std::string mVersion; + std::string mAudioFilename; - string mBaseDir; + std::string mBaseDir; }; #endif diff --git a/source/Beatmaps/BeatmapElements.h b/source/Beatmaps/BeatmapElements.h index 003f67e..7c183dd 100644 --- a/source/Beatmaps/BeatmapElements.h +++ b/source/Beatmaps/BeatmapElements.h @@ -7,7 +7,7 @@ #ifndef __BEATMAPELEMENTS_H__ #define __BEATMAPELEMENTS_H__ -using namespace std; + typedef struct { s32 Time; @@ -39,9 +39,9 @@ class BeatmapElements protected: static BeatmapElements sInstance; - vector mTimingPoints; - vector mBreakPoints; - vector mColours; + std::vector mTimingPoints; + std::vector mBreakPoints; + std::vector mColours; u32 mCurrentColour; private: diff --git a/source/Beatmaps/BeatmapManager.cpp b/source/Beatmaps/BeatmapManager.cpp index 201cd12..5b7bd32 100644 --- a/source/Beatmaps/BeatmapManager.cpp +++ b/source/Beatmaps/BeatmapManager.cpp @@ -1,7 +1,7 @@ #include "BeatmapManager.h" Beatmap* BeatmapManager::mBeatmapCurrent = NULL; -vector BeatmapManager::mBeatmaps; +std::vector BeatmapManager::mBeatmaps; void BeatmapManager::Load(u32 index) { diff --git a/source/Beatmaps/BeatmapManager.h b/source/Beatmaps/BeatmapManager.h index d545038..401a53d 100644 --- a/source/Beatmaps/BeatmapManager.h +++ b/source/Beatmaps/BeatmapManager.h @@ -13,9 +13,9 @@ #ifndef __BEATMAPMANAGER_H__ #define __BEATMAPMANAGER_H__ -using namespace std; -typedef vector::iterator beatmapIterator; + +typedef std::vector::iterator beatmapIterator; class BeatmapManager { @@ -27,12 +27,12 @@ class BeatmapManager static u32 MapCount(); static u32 SongCount(); - static vector& Beatmaps() { return mBeatmaps; } + static std::vector& Beatmaps() { return mBeatmaps; } protected: static Beatmap* mBeatmapCurrent; - static vector mBeatmaps; + static std::vector mBeatmaps; }; #endif diff --git a/source/GameplayElements/HitObjectManager.h b/source/GameplayElements/HitObjectManager.h index 79c57aa..4af67ce 100644 --- a/source/GameplayElements/HitObjectManager.h +++ b/source/GameplayElements/HitObjectManager.h @@ -11,9 +11,9 @@ #ifndef __HITOBJECTMANAGER_H__ #define __HITOBJECTMANAGER_H__ -using namespace std; -typedef list::iterator hitObjectIterator; + +typedef std::list::iterator hitObjectIterator; class HitObjectManager { @@ -24,7 +24,7 @@ class HitObjectManager void HandleInput(); protected: - list mHitObjects; + std::list mHitObjects; }; #endif diff --git a/source/Graphics/SpriteContainer.h b/source/Graphics/SpriteContainer.h index 229f0d1..e5ea239 100644 --- a/source/Graphics/SpriteContainer.h +++ b/source/Graphics/SpriteContainer.h @@ -8,9 +8,9 @@ #ifndef __SPRITECONTAINER_H__ #define __SPRITECONTAINER_H__ -using namespace std; -typedef vector::iterator spriteIterator; + +typedef std::vector::iterator spriteIterator; /* a generic base class for all objects that require sprites * sprite cleanup is automatically handled @@ -22,7 +22,7 @@ class SpriteContainer void AddToSpriteManager(SpriteManager& spriteManager); protected: - vector mSprites; + std::vector mSprites; private: bool mSpriteOwner; diff --git a/source/Graphics/SpriteManager.cpp b/source/Graphics/SpriteManager.cpp index 4d7e828..129914f 100644 --- a/source/Graphics/SpriteManager.cpp +++ b/source/Graphics/SpriteManager.cpp @@ -16,7 +16,7 @@ SpriteManager::~SpriteManager() void SpriteManager::Draw() { u32 i = 0; - vector list; + std::vector list; for (spriteIterator it = mSprites.begin(); it != mSprites.end(); ++it, ++i) { @@ -69,7 +69,7 @@ void SpriteManager::Add(pSprite* spr) mSprites.push_back(spr); } -void SpriteManager::Add(const vector& spr) +void SpriteManager::Add(const std::vector& spr) { for (spriteIteratorConst it = spr.begin(); it != spr.end(); ++it) { diff --git a/source/Graphics/SpriteManager.h b/source/Graphics/SpriteManager.h index 199f9be..fba6e22 100644 --- a/source/Graphics/SpriteManager.h +++ b/source/Graphics/SpriteManager.h @@ -7,10 +7,10 @@ #ifndef __SPRITEMANAGER_H__ #define __SPRITEMANAGER_H__ -using namespace std; -typedef vector::iterator spriteIterator; -typedef vector::const_iterator spriteIteratorConst; + +typedef std::vector::iterator spriteIterator; +typedef std::vector::const_iterator spriteIteratorConst; class SpriteManager { @@ -21,12 +21,12 @@ class SpriteManager void Draw(); void Add(pSprite* spr); - void Add(const vector& spr); + void Add(const std::vector& spr); - vector& Sprites() { return mSprites; } + std::vector& Sprites() { return mSprites; } protected: - vector mSprites; + std::vector mSprites; }; #endif diff --git a/source/Graphics/pSprite.h b/source/Graphics/pSprite.h index de3ad78..149c96f 100644 --- a/source/Graphics/pSprite.h +++ b/source/Graphics/pSprite.h @@ -7,9 +7,9 @@ #ifndef __PSPRITE_H__ #define __PSPRITE_H__ -using namespace std; -typedef vector::iterator transformIterator; + +typedef std::vector::iterator transformIterator; class pSprite { @@ -94,7 +94,7 @@ class pSprite FieldType mFieldType; Texture mTexture; */ - vector mTransformations; + std::vector mTransformations; void Transform(Transformation* transform); }; diff --git a/source/Helpers/AudioManager.cpp b/source/Helpers/AudioManager.cpp index 1059f52..3b78907 100644 --- a/source/Helpers/AudioManager.cpp +++ b/source/Helpers/AudioManager.cpp @@ -113,7 +113,7 @@ void MusicTimerHandler() AudioManager::Engine().fFill = true; } -int AudioManager::MusicPlay(string& filename) +int AudioManager::MusicPlay(std::string& filename) { if (mChannel != -1) MusicStop(); diff --git a/source/Helpers/AudioManager.h b/source/Helpers/AudioManager.h index 8a8dcd4..e2e35dd 100644 --- a/source/Helpers/AudioManager.h +++ b/source/Helpers/AudioManager.h @@ -26,7 +26,7 @@ #include "spinnerbonus_bin.h" #include "spinnerspin_bin.h" -using namespace std; + typedef enum { SND_NORMAL = 1, @@ -72,7 +72,7 @@ class AudioManager //music friend void MusicTimerHandler(); - int MusicPlay(string& filename); + int MusicPlay(std::string& filename); int MusicSkipTo(u32 milliseconds); void MusicStop(); void MusicUpdate(); //must be called frequently diff --git a/source/Helpers/FileReader.cpp b/source/Helpers/FileReader.cpp index 327dcb9..299aa8f 100644 --- a/source/Helpers/FileReader.cpp +++ b/source/Helpers/FileReader.cpp @@ -7,7 +7,7 @@ FileReader::FileReader(u8* source) Init(NULL, source); } -FileReader::FileReader(string& filename) +FileReader::FileReader(std::string& filename) { FILE* handle = fopen(filename.c_str(), "rb"); Init(handle, NULL); @@ -129,7 +129,7 @@ u32 FileReader::ReadVarInt() const } -string FileReader::ReadString() const +std::string FileReader::ReadString() const { u32 l = ReadVarInt(); if (l == 0) @@ -142,7 +142,7 @@ string FileReader::ReadString() const c[i] = mBuffer[pos++]; c[l] = '\0'; - string s(c); + std::string s(c); return s; } diff --git a/source/Helpers/FileReader.h b/source/Helpers/FileReader.h index efd9cd5..cbdd592 100644 --- a/source/Helpers/FileReader.h +++ b/source/Helpers/FileReader.h @@ -6,13 +6,13 @@ #ifndef __FILEREADER_H__ #define __FILEREADER_H__ -using namespace std; + class FileReader { public: FileReader(u8* source); - FileReader(string& filename); + FileReader(std::string& filename); FileReader(const char* filename); ~FileReader(); @@ -21,7 +21,7 @@ class FileReader u32 ReadInt32() const; float ReadFloat() const; u32 ReadVarInt() const; - string ReadString() const; + std::string ReadString() const; bool Ready() const { return fReady; } diff --git a/source/HitObjects/HitSlider.cpp b/source/HitObjects/HitSlider.cpp index 8352c50..1764ec8 100644 --- a/source/HitObjects/HitSlider.cpp +++ b/source/HitObjects/HitSlider.cpp @@ -1,6 +1,6 @@ #include "HitSlider.h" -HitSlider::HitSlider(s32 x, s32 y, s32 time, u32 lengthtime, vector& points, vector& ticks, u32 repeats, HitObjectType type, HitObjectSound sound) +HitSlider::HitSlider(s32 x, s32 y, s32 time, u32 lengthtime, std::vector& points, std::vector& ticks, u32 repeats, HitObjectType type, HitObjectSound sound) : HitObject(x, y, time, type, sound) { fTouching = false; @@ -516,7 +516,7 @@ void HitSlider::Hit() mHit = true; } -void HitSlider::MapSliderPath(pSprite* spr, vector& points, s32 time, u32 lengthtime, u32 repeats) +void HitSlider::MapSliderPath(pSprite* spr, std::vector& points, s32 time, u32 lengthtime, u32 repeats) { u32 timeperpoint = lengthtime / points.size(); diff --git a/source/HitObjects/HitSlider.h b/source/HitObjects/HitSlider.h index 6c11819..37f8c87 100644 --- a/source/HitObjects/HitSlider.h +++ b/source/HitObjects/HitSlider.h @@ -5,9 +5,9 @@ #ifndef __HITSLIDER_H__ #define __HITSLIDER_H__ -using namespace std; -typedef vector::iterator pointIterator; + +typedef std::vector::iterator pointIterator; typedef struct { pSprite* Tick; @@ -17,7 +17,7 @@ typedef struct { class HitSlider : public HitObject { public: - HitSlider(s32 x, s32 y, s32 time, u32 lengthtime, vector& points, vector& ticks, u32 repeats, HitObjectType type, HitObjectSound sound); + HitSlider(s32 x, s32 y, s32 time, u32 lengthtime, std::vector& points, std::vector& ticks, u32 repeats, HitObjectType type, HitObjectSound sound); ~HitSlider(); bool InBounds(s32 x, s32 y); @@ -31,7 +31,7 @@ class HitSlider : public HitObject void Hit(); protected: - static void MapSliderPath(pSprite* spr, vector& points, s32 time, u32 lengthtime, u32 repeats); + static void MapSliderPath(pSprite* spr, std::vector& points, s32 time, u32 lengthtime, u32 repeats); bool fTouching, fStarted, fFinished; TickSprites* mTicks; diff --git a/source/Rulesets/Ruleset.cpp b/source/Rulesets/Ruleset.cpp index acb1de8..c86ca1b 100644 --- a/source/Rulesets/Ruleset.cpp +++ b/source/Rulesets/Ruleset.cpp @@ -28,7 +28,7 @@ void Ruleset::OnGameOver() void Ruleset::Update() { - list hitObjectList; + std::list hitObjectList; BeatmapManager::Current().Buffer(hitObjectList); for (hitObjectIterator it = hitObjectList.begin(); it != hitObjectList.end(); ++it) diff --git a/source/System/ICallback.h b/source/System/ICallback.h index 46db8a2..e3fd4a7 100644 --- a/source/System/ICallback.h +++ b/source/System/ICallback.h @@ -8,7 +8,7 @@ #define ARGS_PUSH(array, id, argument) array[id] = (void*)(&argument); #define ARGS_POP(array, id, type) *((type*)array[id]) -using namespace std; + class ICallback { diff --git a/source/System/TextManager.cpp b/source/System/TextManager.cpp index d137118..5c777c0 100644 --- a/source/System/TextManager.cpp +++ b/source/System/TextManager.cpp @@ -96,7 +96,7 @@ void TextManager::PrintLocate(int x, int y, DrawOrigin origin, char* format, ... va_end(args); // for calculating width - vector lines; + std::vector lines; lines.reserve(10); // height depends on the number of new lines diff --git a/source/System/TextManager.h b/source/System/TextManager.h index 787c1a0..d5e5038 100644 --- a/source/System/TextManager.h +++ b/source/System/TextManager.h @@ -23,7 +23,7 @@ typedef enum { FONT_VERDANA } FONT; -using namespace std; + class TextManager { From 7d25914def9df8ab84e7467ed804ac12d3b344a5 Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 15:25:16 +0100 Subject: [PATCH 03/22] add to hit counters in score, aswell as prepare some stuff for making a beatmap checksum --- .gitignore | 3 +- source/Beatmaps/Beatmap.cpp | 7 +- source/Beatmaps/Beatmap.h | 5 + source/GameplayElements/Score.cpp | 49 +++- source/GameplayElements/Score.h | 38 +++- source/Helpers/MD5.cpp | 362 ++++++++++++++++++++++++++++++ source/Helpers/MD5.h | 93 ++++++++ 7 files changed, 548 insertions(+), 9 deletions(-) create mode 100644 source/Helpers/MD5.cpp create mode 100644 source/Helpers/MD5.h diff --git a/.gitignore b/.gitignore index 0592167..ec4f67f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ .idea cmake-build-debug build -.vscode \ No newline at end of file +.vscode +source/defines.h diff --git a/source/Beatmaps/Beatmap.cpp b/source/Beatmaps/Beatmap.cpp index 1f5317f..2b99d37 100644 --- a/source/Beatmaps/Beatmap.cpp +++ b/source/Beatmaps/Beatmap.cpp @@ -7,6 +7,8 @@ Beatmap::Beatmap(const char* filename, const char* basedir) mFilename = filename; mBaseDir = basedir; mReader = NULL; + + mChecksumString = ""; FileReader r(filename); @@ -242,4 +244,7 @@ void Beatmap::ReadNextObject() } - +std::string& Beatmap::BeatmapChecksum() { + //TODO: figure out some way to uniquely identify every beatmap without it being too intensive + return ""; +} \ No newline at end of file diff --git a/source/Beatmaps/Beatmap.h b/source/Beatmaps/Beatmap.h index f032f53..596e7b7 100644 --- a/source/Beatmaps/Beatmap.h +++ b/source/Beatmaps/Beatmap.h @@ -48,6 +48,8 @@ class Beatmap s32 SkipTime() { return mSkipTime; } s32 StartTime() { return mFirstObjectTime; } + + std::string& BeatmapChecksum(); protected: FileReader* mReader; @@ -73,6 +75,9 @@ class Beatmap std::string mAudioFilename; std::string mBaseDir; + private: + std::string mChecksumString; + std::string mBeatmapChecksum; }; #endif diff --git a/source/GameplayElements/Score.cpp b/source/GameplayElements/Score.cpp index 403aa13..ca6aff6 100644 --- a/source/GameplayElements/Score.cpp +++ b/source/GameplayElements/Score.cpp @@ -4,13 +4,25 @@ Score::Score() { mScore = 0; mCombo = 0; + mScore = 0; + mCombo = 0; + mMaxCombo = 0; + mCount300 = 0; + mCount100 = 0; + mCount50 = 0; + mCountMiss = 0; + mCountGeki = 0; + mCountKatu = 0; + mBeatmapChecksum = ""; } -void Score::Add(ScoreType score, bool forceNoCombo) +void Score::Add(ScoreType score, bool forceNoCombo, bool gekiKatu) { if (score == SCORE_MISS) { mCombo = 0; + + this->mCountMiss++; } else if (score == SCORE_SPIN_100 || score == SCORE_SPIN_1000) { @@ -22,14 +34,45 @@ void Score::Add(ScoreType score, bool forceNoCombo) else if (score == SCORE_TICK_30 || score == SCORE_TICK_10) { mScore += score; - if (!forceNoCombo) + + if (!forceNoCombo) { ++mCombo; + + //Increase max combo if mCombo is greater than it + if(mCombo > mMaxCombo) + mMaxCombo = mCombo; + } } else { mScore += score + MathHelper::Max(0, mCombo-1) * (score/25) * DifficultyManager::DifficultyPeppyStars; - if (!forceNoCombo) + + if (!forceNoCombo) { ++mCombo; + + //Increase max combo if mCombo is greater than it + if(mCombo > mMaxCombo) + mMaxCombo = mCombo; + } + + //Increase the respective count + switch(score) { + case ScoreType::SCORE_100: + if(gekiKatu) + this->mCountKatu++; + else + this->mCount100++; + break; + case ScoreType::SCORE_300: + if(gekiKatu) + this->mCountGeki++; + else + this->mCount300++; + break; + case ScoreType::SCORE_50: + this->mCount50++; + break; + } } } diff --git a/source/GameplayElements/Score.h b/source/GameplayElements/Score.h index d747d7f..45ff2da 100644 --- a/source/GameplayElements/Score.h +++ b/source/GameplayElements/Score.h @@ -1,5 +1,7 @@ #include #include +#include + #include "Helpers/MathHelper.h" #include "Beatmaps/DifficultyManager.h" @@ -8,11 +10,13 @@ typedef enum { SCORE_300 = 300, + SCORE_GEKI = 301, SCORE_100 = 100, + SCORE_KATU = 102, SCORE_50 = 50, SCORE_TICK_30 = 30, SCORE_TICK_10 = 10, - SCORE_SPIN_100 = 101,//should be 100 but conflicts with SCORE_100 + SCORE_SPIN_100 = 101, //should be 100 but conflicts with SCORE_100 SCORE_SPIN_1000 = 1000, SCORE_MISS = 0 } ScoreType; @@ -22,14 +26,40 @@ class Score public: Score(); - void Add(ScoreType score, bool forceNoCombo = false); + void Add(ScoreType score, bool forceNoCombo = false, bool gekiKatu = false); - u32 CurrentScore() { return mScore; } - u32 CurrentCombo() { return mCombo; } + u32 CurrentScore() { return mScore; } + u32 CurrentCombo() { return mCombo; } + u32 MaxCombo() { return mMaxCombo; } + u32 Count300() { return mCount300; } + u32 Count100() { return mCount100; } + u32 Count50() { return mCount50; } + u32 CountMiss() { return mCountMiss; } + u32 CountGeki() { return mCountGeki; } + u32 CountKatu() { return mCountKatu; } + std::string BeatmapChecksum() { return mBeatmapChecksum; } protected: + //The Final score u32 mScore; + //The Ending combo u32 mCombo; + //The Maximum combo achieved + u32 mMaxCombo; + //Amount of 300s + u32 mCount300; + //Amount of 100s + u32 mCount100; + //Amount of 50s + u32 mCount50; + //Amount of Misses + u32 mCountMiss; + //Amount of Gekis + u32 mCountGeki; + //Amount of Katus + u32 mCountKatu; + //Checksum of the Map this play belongs to + std::string mBeatmapChecksum; }; #endif diff --git a/source/Helpers/MD5.cpp b/source/Helpers/MD5.cpp new file mode 100644 index 0000000..aff9645 --- /dev/null +++ b/source/Helpers/MD5.cpp @@ -0,0 +1,362 @@ +/* MD5 + converted to C++ class by Frank Thilo (thilo@unix-ag.org) + for bzflag (http://www.bzflag.org) + + based on: + + md5.h and md5.c + reference implemantion of RFC 1321 + + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + +*/ + +/* interface header */ +#include "md5.h" + +/* system implementation headers */ +#include + + +// Constants for MD5Transform routine. +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +/////////////////////////////////////////////// + +// F, G, H and I are basic MD5 functions. +inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) { + return x&y | ~x&z; +} + +inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) { + return x&z | y&~z; +} + +inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) { + return x^y^z; +} + +inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) { + return y ^ (x | ~z); +} + +// rotate_left rotates x left n bits. +inline MD5::uint4 MD5::rotate_left(uint4 x, int n) { + return (x << n) | (x >> (32-n)); +} + +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +// Rotation is separate from addition to prevent recomputation. +inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a+ F(b,c,d) + x + ac, s) + b; +} + +inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + G(b,c,d) + x + ac, s) + b; +} + +inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + H(b,c,d) + x + ac, s) + b; +} + +inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + I(b,c,d) + x + ac, s) + b; +} + +////////////////////////////////////////////// + +// default ctor, just initailize +MD5::MD5() +{ + init(); +} + +////////////////////////////////////////////// + +// nifty shortcut ctor, compute MD5 for string and finalize it right away +MD5::MD5(const std::string &text) +{ + init(); + update(text.c_str(), text.length()); + finalize(); +} + +////////////////////////////// + +void MD5::init() +{ + finalized=false; + + count[0] = 0; + count[1] = 0; + + // load magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; +} + +////////////////////////////// + +// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4. +void MD5::decode(uint4 output[], const uint1 input[], size_type len) +{ + for (unsigned int i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | + (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); +} + +////////////////////////////// + +// encodes input (uint4) into output (unsigned char). Assumes len is +// a multiple of 4. +void MD5::encode(uint1 output[], const uint4 input[], size_type len) +{ + for (size_type i = 0, j = 0; j < len; i++, j += 4) { + output[j] = input[i] & 0xff; + output[j+1] = (input[i] >> 8) & 0xff; + output[j+2] = (input[i] >> 16) & 0xff; + output[j+3] = (input[i] >> 24) & 0xff; + } +} + +////////////////////////////// + +// apply MD5 algo on a block +void MD5::transform(const uint1 block[blocksize]) +{ + uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + decode (x, block, blocksize); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset(x, 0, sizeof x); +} + +////////////////////////////// + +// MD5 block update operation. Continues an MD5 message-digest +// operation, processing another message block +void MD5::update(const unsigned char input[], size_type length) +{ + // compute number of bytes mod 64 + size_type index = count[0] / 8 % blocksize; + + // Update number of bits + if ((count[0] += (length << 3)) < (length << 3)) + count[1]++; + count[1] += (length >> 29); + + // number of bytes we need to fill in buffer + size_type firstpart = 64 - index; + + size_type i; + + // transform as many times as possible. + if (length >= firstpart) + { + // fill buffer first, transform + memcpy(&buffer[index], input, firstpart); + transform(buffer); + + // transform chunks of blocksize (64 bytes) + for (i = firstpart; i + blocksize <= length; i += blocksize) + transform(&input[i]); + + index = 0; + } + else + i = 0; + + // buffer remaining input + memcpy(&buffer[index], &input[i], length-i); +} + +////////////////////////////// + +// for convenience provide a verson with signed char +void MD5::update(const char input[], size_type length) +{ + update((const unsigned char*)input, length); +} + +////////////////////////////// + +// MD5 finalization. Ends an MD5 message-digest operation, writing the +// the message digest and zeroizing the context. +MD5& MD5::finalize() +{ + static unsigned char padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (!finalized) { + // Save number of bits + unsigned char bits[8]; + encode(bits, count, 8); + + // pad out to 56 mod 64. + size_type index = count[0] / 8 % 64; + size_type padLen = (index < 56) ? (56 - index) : (120 - index); + update(padding, padLen); + + // Append length (before padding) + update(bits, 8); + + // Store state in digest + encode(digest, state, 16); + + // Zeroize sensitive information. + memset(buffer, 0, sizeof buffer); + memset(count, 0, sizeof count); + + finalized=true; + } + + return *this; +} + +////////////////////////////// + +// return hex representation of digest as string +std::string MD5::hexdigest() const +{ + if (!finalized) + return ""; + + char buf[33]; + for (int i=0; i<16; i++) + sprintf(buf+i*2, "%02x", digest[i]); + buf[32]=0; + + return std::string(buf); +} + +////////////////////////////// + +std::ostream& operator<<(std::ostream& out, MD5 md5) +{ + return out << md5.hexdigest(); +} + +////////////////////////////// + +std::string md5(const std::string str) +{ + MD5 md5 = MD5(str); + + return md5.hexdigest(); +} \ No newline at end of file diff --git a/source/Helpers/MD5.h b/source/Helpers/MD5.h new file mode 100644 index 0000000..d57b2c6 --- /dev/null +++ b/source/Helpers/MD5.h @@ -0,0 +1,93 @@ +/* MD5 + converted to C++ class by Frank Thilo (thilo@unix-ag.org) + for bzflag (http://www.bzflag.org) + + based on: + + md5.h and md5.c + reference implementation of RFC 1321 + + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + +*/ + +#ifndef BZF_MD5_H +#define BZF_MD5_H + +#include +#include + + +// a small class for calculating MD5 hashes of strings or byte arrays +// it is not meant to be fast or secure +// +// usage: 1) feed it blocks of uchars with update() +// 2) finalize() +// 3) get hexdigest() string +// or +// MD5(std::string).hexdigest() +// +// assumes that char is 8 bit and int is 32 bit +class MD5 +{ +public: + typedef unsigned int size_type; // must be 32bit + + MD5(); + MD5(const std::string& text); + void update(const unsigned char *buf, size_type length); + void update(const char *buf, size_type length); + MD5& finalize(); + std::string hexdigest() const; + friend std::ostream& operator<<(std::ostream&, MD5 md5); + +private: + void init(); + typedef unsigned char uint1; // 8bit + typedef unsigned int uint4; // 32bit + enum {blocksize = 64}; // VC6 won't eat a const static int here + + void transform(const uint1 block[blocksize]); + static void decode(uint4 output[], const uint1 input[], size_type len); + static void encode(uint1 output[], const uint4 input[], size_type len); + + bool finalized; + uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk + uint4 count[2]; // 64bit counter for number of bits (lo, hi) + uint4 state[4]; // digest so far + uint1 digest[16]; // the result + + // low level logic operations + static inline uint4 F(uint4 x, uint4 y, uint4 z); + static inline uint4 G(uint4 x, uint4 y, uint4 z); + static inline uint4 H(uint4 x, uint4 y, uint4 z); + static inline uint4 I(uint4 x, uint4 y, uint4 z); + static inline uint4 rotate_left(uint4 x, int n); + static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); +}; + +std::string md5(const std::string str); + +#endif From f4f4a8067d26cb777ddee89bbcdd2162d6806825 Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 16:12:11 +0100 Subject: [PATCH 04/22] fix compile error in Beatmap --- source/Beatmaps/Beatmap.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/Beatmaps/Beatmap.cpp b/source/Beatmaps/Beatmap.cpp index 2b99d37..8032122 100644 --- a/source/Beatmaps/Beatmap.cpp +++ b/source/Beatmaps/Beatmap.cpp @@ -245,6 +245,7 @@ void Beatmap::ReadNextObject() std::string& Beatmap::BeatmapChecksum() { + std::string checksum = ""; //TODO: figure out some way to uniquely identify every beatmap without it being too intensive - return ""; + return checksum; } \ No newline at end of file From 03b7ca8cd3cc0dc17e632a335fa1328f7cebc8fe Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 16:44:40 +0100 Subject: [PATCH 05/22] Working towards making pSprites clickable, making our lives easier --- source/Beatmaps/Beatmap.cpp | 7 +----- source/Beatmaps/BeatmapManager.cpp | 2 -- source/Graphics/SpriteManager.cpp | 38 +++++++++++++++++++++++++----- source/Graphics/SpriteManager.h | 2 ++ source/Graphics/pSprite.h | 4 ++++ source/Helpers/FileReader.cpp | 1 - source/Libraries/gfxconsole.c | 4 ---- source/Modes/SongSelect.cpp | 11 +++++---- 8 files changed, 46 insertions(+), 23 deletions(-) diff --git a/source/Beatmaps/Beatmap.cpp b/source/Beatmaps/Beatmap.cpp index 8032122..d9a932b 100644 --- a/source/Beatmaps/Beatmap.cpp +++ b/source/Beatmaps/Beatmap.cpp @@ -56,7 +56,6 @@ void Beatmap::Initialize() mCreator = mReader->ReadString(); mVersion = mReader->ReadString(); mAudioFilename = mReader->ReadString(); - nocashMessage(mAudioFilename.c_str()); DifficultyManager::DifficultyHpDrain = mReader->ReadInt8(); DifficultyManager::DifficultyCircleSize = mReader->ReadInt8(); @@ -77,10 +76,8 @@ void Beatmap::Initialize() BeatmapElements::Element().AddTimingPoint(time, beattime, samplesetid); } - nocashMessage("hio\n"); - u32 breakcount = mReader->ReadVarInt(); - nocashMessage(std::to_string(breakcount).c_str()); + for (u32 j=0; jReadInt32(); @@ -89,8 +86,6 @@ void Beatmap::Initialize() BeatmapElements::Element().AddBreakPoint(starttime, endtime); } - nocashMessage("hio\n"); - iprintf("\x1b[2J"); mHitObjectCount = mReader->ReadVarInt(); mHitObjectRead = 0; diff --git a/source/Beatmaps/BeatmapManager.cpp b/source/Beatmaps/BeatmapManager.cpp index 5b7bd32..f4593ad 100644 --- a/source/Beatmaps/BeatmapManager.cpp +++ b/source/Beatmaps/BeatmapManager.cpp @@ -47,8 +47,6 @@ void BeatmapManager::BuildCollection() if (length < 4) continue; - nocashMessage(ext); - //ext is now the extension of the current file ext += length - 4; diff --git a/source/Graphics/SpriteManager.cpp b/source/Graphics/SpriteManager.cpp index 129914f..c15cc0d 100644 --- a/source/Graphics/SpriteManager.cpp +++ b/source/Graphics/SpriteManager.cpp @@ -1,5 +1,8 @@ #include "SpriteManager.h" +#include +#include + SpriteManager::SpriteManager() { } @@ -16,7 +19,7 @@ SpriteManager::~SpriteManager() void SpriteManager::Draw() { u32 i = 0; - std::vector list; + std::vector deadSprites; for (spriteIterator it = mSprites.begin(); it != mSprites.end(); ++it, ++i) { @@ -25,7 +28,7 @@ void SpriteManager::Draw() //if for some reason sprite is nonexistent then mark for deletion if (spr == NULL) { - list.push_back(i); + deadSprites.push_back(i); continue; } @@ -34,7 +37,7 @@ void SpriteManager::Draw() //if sprite is dead then mark for deletion if (spr->Draw() == false) { - list.push_back(i); + deadSprites.push_back(i); continue; } @@ -52,16 +55,18 @@ void SpriteManager::Draw() } //delete dead sprites - while (list.size() > 0) + while (deadSprites.size() > 0) { - spriteIterator it = mSprites.begin() + list.back(); + spriteIterator it = mSprites.begin() + deadSprites.back(); if (*it != NULL) delete *it; mSprites.erase(it); - list.pop_back(); + deadSprites.pop_back(); } + + this->HandleTouchInput(); } void SpriteManager::Add(pSprite* spr) @@ -76,3 +81,24 @@ void SpriteManager::Add(const std::vector& spr) Add(*it); } } + +void SpriteManager::HandleTouchInput() { + if (!InputHelper::KeyDown(KEY_TOUCH)) + return; + + touchPosition touchPos = InputHelper::TouchRead(); + + std::vector sprites = this->mSprites; + + std::sort(sprites.begin(), sprites.end(), [](const pSprite* first, const pSprite* second) { + return first->Z > second->Z; + }); + + for(int i = 0; i != sprites.size(); i++) { + pSprite* current = sprites[i]; + + if(current->InBounds(touchPos.px, touchPos.py)) { + + } + } +} \ No newline at end of file diff --git a/source/Graphics/SpriteManager.h b/source/Graphics/SpriteManager.h index fba6e22..855cffb 100644 --- a/source/Graphics/SpriteManager.h +++ b/source/Graphics/SpriteManager.h @@ -3,6 +3,7 @@ #include "pSprite.h" #include "GraphicsManager.h" +#include "Helpers/InputHelper.h" #ifndef __SPRITEMANAGER_H__ #define __SPRITEMANAGER_H__ @@ -19,6 +20,7 @@ class SpriteManager virtual ~SpriteManager(); void Draw(); + void HandleTouchInput(); void Add(pSprite* spr); void Add(const std::vector& spr); diff --git a/source/Graphics/pSprite.h b/source/Graphics/pSprite.h index 149c96f..c6584f2 100644 --- a/source/Graphics/pSprite.h +++ b/source/Graphics/pSprite.h @@ -1,5 +1,7 @@ #include #include +#include + #include "GraphicsManager.h" #include "Transformation.h" #include "System/GameClock.h" @@ -73,6 +75,8 @@ class pSprite s32 Angle; float Z; u32* UV; + + std::string tag; DrawOrigin Origin; FieldType Field; diff --git a/source/Helpers/FileReader.cpp b/source/Helpers/FileReader.cpp index 299aa8f..cdad308 100644 --- a/source/Helpers/FileReader.cpp +++ b/source/Helpers/FileReader.cpp @@ -124,7 +124,6 @@ u32 FileReader::ReadVarInt() const ++i; } while ((b & 0x80) > 0); - nocashMessage((std::string(" ") + std::to_string(value)).c_str()); return value; } diff --git a/source/Libraries/gfxconsole.c b/source/Libraries/gfxconsole.c index a4b47be..c2b90f5 100644 --- a/source/Libraries/gfxconsole.c +++ b/source/Libraries/gfxconsole.c @@ -205,11 +205,7 @@ ssize_t gfxnocash_write(struct _reent *r, int fd, const char *ptr, size_t len) { while(count < len) { - - nocashMessage(ptr + count); - count += (len - count) > 80 ? 80 : len - count; - } return len; diff --git a/source/Modes/SongSelect.cpp b/source/Modes/SongSelect.cpp index ee2587f..5a73ffd 100644 --- a/source/Modes/SongSelect.cpp +++ b/source/Modes/SongSelect.cpp @@ -4,7 +4,7 @@ SongSelect::SongSelect() { for (int i=0; i<8; ++i) { - pSprite* spr = new pSprite(TX_WHITE, 0, 0, 160, 120, ORIGIN_TOPLEFT, FIELD_SCREEN, RGB15(4,4,4), 20); + pSprite* spr = new pSprite(TX_WHITE, 0, 0, 160, 120, ORIGIN_TOPLEFT, FIELD_SCREEN, RGB15(4,4,4), 20 + i); mSpriteManager.Add(spr); } @@ -67,8 +67,8 @@ void SongSelect::HandleInput() if (mSpriteManager.Sprites()[index]->Alpha == 31) { // load beatmap - BeatmapManager::Load(index + mColCurrent*2); // take scrolling offset into account - ChangeMode(MODE_PLAYER); + //BeatmapManager::Load(index + mColCurrent*2); // take scrolling offset into account + //ChangeMode(MODE_PLAYER); return; } } @@ -105,7 +105,10 @@ void SongSelect::Update() if (index >= BeatmapManager::SongCount()) break; Beatmap* map = BeatmapManager::Beatmaps()[index]; - + + spr->tag = map->Title(); + spr->Z = j + i; + TextManager::Bottom().SetFont(FONT_CONSOLE); TextManager::Bottom().PrintLocate( From 4e133cef96eef167ab47bc76afe19a0a9bf80c82 Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 16:48:29 +0100 Subject: [PATCH 06/22] pSprites now have the ability to be clicked --- source/Graphics/SpriteManager.cpp | 4 ++-- source/Graphics/pSprite.h | 2 ++ source/Modes/SongSelect.cpp | 7 ++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/source/Graphics/SpriteManager.cpp b/source/Graphics/SpriteManager.cpp index c15cc0d..d8be366 100644 --- a/source/Graphics/SpriteManager.cpp +++ b/source/Graphics/SpriteManager.cpp @@ -97,8 +97,8 @@ void SpriteManager::HandleTouchInput() { for(int i = 0; i != sprites.size(); i++) { pSprite* current = sprites[i]; - if(current->InBounds(touchPos.px, touchPos.py)) { - + if(current->InBounds(touchPos.px, touchPos.py) && current->OnClick != NULL) { + current->OnClick(touchPos.px, touchPos.py); } } } \ No newline at end of file diff --git a/source/Graphics/pSprite.h b/source/Graphics/pSprite.h index c6584f2..634dcc2 100644 --- a/source/Graphics/pSprite.h +++ b/source/Graphics/pSprite.h @@ -81,6 +81,8 @@ class pSprite DrawOrigin Origin; FieldType Field; TextureType Texture; + + void(*OnClick)(u16 x, u16 y); protected: u32 mOrigWidth, mOrigHeight; diff --git a/source/Modes/SongSelect.cpp b/source/Modes/SongSelect.cpp index 5a73ffd..d86c725 100644 --- a/source/Modes/SongSelect.cpp +++ b/source/Modes/SongSelect.cpp @@ -67,8 +67,8 @@ void SongSelect::HandleInput() if (mSpriteManager.Sprites()[index]->Alpha == 31) { // load beatmap - //BeatmapManager::Load(index + mColCurrent*2); // take scrolling offset into account - //ChangeMode(MODE_PLAYER); + BeatmapManager::Load(index + mColCurrent*2); // take scrolling offset into account + ChangeMode(MODE_PLAYER); return; } } @@ -106,9 +106,6 @@ void SongSelect::Update() break; Beatmap* map = BeatmapManager::Beatmaps()[index]; - spr->tag = map->Title(); - spr->Z = j + i; - TextManager::Bottom().SetFont(FONT_CONSOLE); TextManager::Bottom().PrintLocate( From 9e3e75dcddd98b4d43dc9fba31de5954440023b8 Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 17:18:22 +0100 Subject: [PATCH 07/22] Fix bad jump when onclick isnt set --- source/Graphics/SpriteManager.cpp | 2 +- source/Graphics/pSprite.cpp | 1 + source/Graphics/pSprite.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/source/Graphics/SpriteManager.cpp b/source/Graphics/SpriteManager.cpp index d8be366..b567f94 100644 --- a/source/Graphics/SpriteManager.cpp +++ b/source/Graphics/SpriteManager.cpp @@ -97,7 +97,7 @@ void SpriteManager::HandleTouchInput() { for(int i = 0; i != sprites.size(); i++) { pSprite* current = sprites[i]; - if(current->InBounds(touchPos.px, touchPos.py) && current->OnClick != NULL) { + if(current->InBounds(touchPos.px, touchPos.py) && current->Clickable) { current->OnClick(touchPos.px, touchPos.py); } } diff --git a/source/Graphics/pSprite.cpp b/source/Graphics/pSprite.cpp index 72ed97d..4c7f623 100644 --- a/source/Graphics/pSprite.cpp +++ b/source/Graphics/pSprite.cpp @@ -15,6 +15,7 @@ pSprite::pSprite(TextureType texture, s32 x, s32 y, u32 width, u32 height, DrawO Angle = 0; UV = NULL; Z = z; + Clickable = false; } pSprite::~pSprite() diff --git a/source/Graphics/pSprite.h b/source/Graphics/pSprite.h index 634dcc2..25ffedb 100644 --- a/source/Graphics/pSprite.h +++ b/source/Graphics/pSprite.h @@ -83,6 +83,7 @@ class pSprite TextureType Texture; void(*OnClick)(u16 x, u16 y); + bool Clickable; protected: u32 mOrigWidth, mOrigHeight; From 999016710bd02219329b4dd7e0265602e9a1ecf2 Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 17:29:49 +0100 Subject: [PATCH 08/22] pDrawables!! --- source/Graphics/SpriteManager.cpp | 2 +- source/Graphics/pDrawable.cpp | 176 +++++++++++++++++++++++++++++ source/Graphics/pDrawable.h | 111 ++++++++++++++++++ source/Graphics/pSprite.cpp | 179 +----------------------------- source/Graphics/pSprite.h | 109 +----------------- 5 files changed, 298 insertions(+), 279 deletions(-) create mode 100644 source/Graphics/pDrawable.cpp create mode 100644 source/Graphics/pDrawable.h diff --git a/source/Graphics/SpriteManager.cpp b/source/Graphics/SpriteManager.cpp index b567f94..9ca3564 100644 --- a/source/Graphics/SpriteManager.cpp +++ b/source/Graphics/SpriteManager.cpp @@ -35,7 +35,7 @@ void SpriteManager::Draw() spr->Update(); //if sprite is dead then mark for deletion - if (spr->Draw() == false) + if (spr->Alive() == false) { deadSprites.push_back(i); continue; diff --git a/source/Graphics/pDrawable.cpp b/source/Graphics/pDrawable.cpp new file mode 100644 index 0000000..606c6f5 --- /dev/null +++ b/source/Graphics/pDrawable.cpp @@ -0,0 +1,176 @@ +#include "pDrawable.h" + +pDrawable::~pDrawable() +{ + for (transformIterator it = mTransformations.begin(); it != mTransformations.end(); ++it) + { + if (*it != NULL) + delete *it; + } + + if (UV != NULL) + delete UV; +} + +void pDrawable::Update() +{ + for (transformIterator it = mTransformations.begin(); it != mTransformations.end(); ++it) + { + Transformation* tr = (*it); + tr->Update(); + + if (tr->Active()) + { + switch (tr->Type()) + { + case TR_FADE: + Alpha = tr->Value(); + break; + case TR_MOVEX: + X = tr->Value(); + break; + case TR_MOVEY: + Y = tr->Value(); + break; + case TR_SCALEX: + Width = tr->Value(); + break; + case TR_SCALEY: + Height = tr->Value(); + break; + case TR_ROTATE: + Angle = tr->Value(); + break; + case TR_KILL: + mAlive = false; + break; + } + } + } +} + +bool pDrawable::InBounds(s32 x, s32 y) +{ + if (Field == FIELD_PLAY) + { + x -= GraphicsManager::PlayXOffset; + y -= GraphicsManager::PlayYOffset; + } + + switch (Origin) + { + case ORIGIN_TOPLEFT: + { + return x >= X && x <= X+Width + && y >= Y && y <= Y+Height; + } + + case ORIGIN_CENTER: + { + s32 halfWidth = Width>>1; + s32 halfHeight = Height>>1; + + return x >= X-halfWidth && x <= X+halfWidth + && y >= Y-halfHeight && y <= Y+halfHeight; + } + + case ORIGIN_BOTTOMLEFT: + { + return x >= X && x <= X+Width + && y >= Y-Height && y <= Y; + } + + default: + return false; + } +} + +void pDrawable::Kill(s32 time) +{ + Transform(TR_KILL, time, time, 0, 0); +} + +void pDrawable::ClearTransforms() +{ + for (transformIterator it = mTransformations.begin(); it != mTransformations.end(); ++it) + { + if (*it != NULL) + delete *it; + } + + mTransformations.clear(); +} + +void pDrawable::Transform(Transformation* transform) +{ + mTransformations.push_back(transform); +} + +void pDrawable::Transform(TransformType type, s32 starttime, s32 endtime, s32 startvalue, s32 endvalue) +{ + Transform(new Transformation(type, starttime, endtime, startvalue, endvalue)); +} + +void pDrawable::Scale(s32 starttime, s32 endtime, float start, float end) +{ + Transform(TR_SCALEX, starttime, endtime, mOrigWidth*start, mOrigWidth*end); + Transform(TR_SCALEY, starttime, endtime, mOrigHeight*start, mOrigHeight*end); +} + +void pDrawable::Move(s32 starttime, s32 endtime, s32 startx, s32 starty, s32 endx, s32 endy) +{ + Transform(TR_MOVEX, starttime, endtime, startx, endx); + Transform(TR_MOVEY, starttime, endtime, starty, endy); +} + +void pDrawable::Move(s32 starttime, s32 endtime, s32 endx, s32 endy) +{ + Move(starttime, endtime, X, Y, endx, endy); +} + +void pDrawable::Move(s32 endx, s32 endy) +{ + X = endx; + Y = endy; +} + +void pDrawable::Rotate(s32 starttime, s32 endtime, s32 starta, s32 enda) +{ + Transform(TR_ROTATE, starttime, endtime, starta, enda); +} + +void pDrawable::Rotate(s32 angle) +{ + Transform(TR_ROTATE, GameClock::Clock().Time(), GameClock::Clock().Time(), angle, angle); +} + +void pDrawable::Show() +{ + Show(GameClock::Clock().Time()); +} + +void pDrawable::Show(s32 time) +{ + Transform(TR_FADE, time, time, 31, 31); +} + +void pDrawable::Show(s32 starttime, s32 endtime) +{ + Transform(TR_FADE, starttime, endtime, 0, 31); +} + +void pDrawable::Hide() +{ + Hide(GameClock::Clock().Time()); +} + +void pDrawable::Hide(s32 time) +{ + Transform(TR_FADE, time, time, 0, 0); +} + +void pDrawable::Hide(s32 starttime, s32 endtime) +{ + Transform(TR_FADE, starttime, endtime, 31, 0); +} + diff --git a/source/Graphics/pDrawable.h b/source/Graphics/pDrawable.h new file mode 100644 index 0000000..5359dec --- /dev/null +++ b/source/Graphics/pDrawable.h @@ -0,0 +1,111 @@ +#include +#include +#include + +#include "GraphicsManager.h" +#include "Transformation.h" +#include "System/GameClock.h" + +#ifndef __PDRAWABLE_H__ +#define __PDRAWABLE_H__ + + + +typedef std::vector::iterator transformIterator; + +class pDrawable +{ + public: + virtual ~pDrawable(); + + virtual void Update(); + bool InBounds(s32 x, s32 y); + void Kill(s32 time); + void ClearTransforms(); + + void Transform(TransformType type, s32 starttime, s32 endtime, s32 startvalue, s32 endvalue); + void Scale(s32 starttime, s32 endtime, float start, float end); + void Move(s32 starttime, s32 endtime, s32 startx, s32 starty, s32 endx, s32 endy); + void Move(s32 starttime, s32 endtime, s32 endx, s32 endy); + void Move(s32 x, s32 y); + void Rotate(s32 starttime, s32 endtime, s32 starta, s32 enda); + void Rotate(s32 angle); + + void Show(); + void Show(s32 time); + void Show(s32 starttime, s32 endtime); + void Hide(); + void Hide(s32 time); + void Hide(s32 starttime, s32 endtime); + + /* + s32 x() { return mX; } + s32 y() { return mY; } + u32 width() { return mWidth; } + u32 height() { return mHeight; } + rgb color() { return mColor; } + u32 alpha() { return mAlpha; } + s32 angle() { return mAngle; } + float deltaz() { return mDeltaZ; } + u32* uv() { return mUV; } + + void SetTexture(Texture tex) { mTexture = tex; } + + //for spinners... a bit hacky but meh -.- + s32& Angle() { return mAngle; } + void SetCustomBounds(u32* uv) { mUV = uv; } + void SetHeight(s32 height) { mHeight = height; } + void SetWidth(s32 width) { mWidth = width; } + + //for score sprites (more hax) + void SetDeltaZ(float z) { mDeltaZ = z; } + u32& Alpha() { return mAlpha; } + + DrawOrigin origin() { return mOrigin; } + FieldType fieldType() { return mFieldType; } + Texture texture() { return mTexture; } + */ + bool Alive() { return mAlive; } + + virtual void Draw() = 0; + + s32 X, Y; + u32 Width, Height; + rgb Color; + u32 Alpha; + s32 Angle; + float Z; + u32* UV; + + std::string tag; + + DrawOrigin Origin; + FieldType Field; + TextureType Texture; + + void(*OnClick)(u16 x, u16 y); + bool Clickable; + + protected: + u32 mOrigWidth, mOrigHeight; + bool mAlive; + /* + s32 mX, mY; + u32 mWidth, mHeight; + rgb mColor; + u32 mAlpha; + s32 mAngle; + float mDeltaZ; + u32* mUV; + + DrawOrigin mOrigin; + FieldType mFieldType; + Texture mTexture; + */ + std::vector mTransformations; + + void Transform(Transformation* transform); +}; + +#endif + diff --git a/source/Graphics/pSprite.cpp b/source/Graphics/pSprite.cpp index 4c7f623..f2fb69e 100644 --- a/source/Graphics/pSprite.cpp +++ b/source/Graphics/pSprite.cpp @@ -11,184 +11,13 @@ pSprite::pSprite(TextureType texture, s32 x, s32 y, u32 width, u32 height, DrawO Field = fieldtype; Color = color; Alpha = alpha; - mDraw = true; + mAlive = true; Angle = 0; UV = NULL; Z = z; Clickable = false; } -pSprite::~pSprite() -{ - for (transformIterator it = mTransformations.begin(); it != mTransformations.end(); ++it) - { - if (*it != NULL) - delete *it; - } - - if (UV != NULL) - delete UV; -} - -void pSprite::Update() -{ - for (transformIterator it = mTransformations.begin(); it != mTransformations.end(); ++it) - { - Transformation* tr = (*it); - tr->Update(); - - if (tr->Active()) - { - switch (tr->Type()) - { - case TR_FADE: - Alpha = tr->Value(); - break; - case TR_MOVEX: - X = tr->Value(); - break; - case TR_MOVEY: - Y = tr->Value(); - break; - case TR_SCALEX: - Width = tr->Value(); - break; - case TR_SCALEY: - Height = tr->Value(); - break; - case TR_ROTATE: - Angle = tr->Value(); - break; - case TR_KILL: - mDraw = false; - break; - } - } - } -} - -bool pSprite::InBounds(s32 x, s32 y) -{ - if (Field == FIELD_PLAY) - { - x -= GraphicsManager::PlayXOffset; - y -= GraphicsManager::PlayYOffset; - } - - switch (Origin) - { - case ORIGIN_TOPLEFT: - { - return x >= X && x <= X+Width - && y >= Y && y <= Y+Height; - } - - case ORIGIN_CENTER: - { - s32 halfWidth = Width>>1; - s32 halfHeight = Height>>1; - - return x >= X-halfWidth && x <= X+halfWidth - && y >= Y-halfHeight && y <= Y+halfHeight; - } - - case ORIGIN_BOTTOMLEFT: - { - return x >= X && x <= X+Width - && y >= Y-Height && y <= Y; - } - - default: - return false; - } -} - -void pSprite::Kill(s32 time) -{ - Transform(TR_KILL, time, time, 0, 0); -} - -void pSprite::ClearTransforms() -{ - for (transformIterator it = mTransformations.begin(); it != mTransformations.end(); ++it) - { - if (*it != NULL) - delete *it; - } - - mTransformations.clear(); -} - -void pSprite::Transform(Transformation* transform) -{ - mTransformations.push_back(transform); -} - -void pSprite::Transform(TransformType type, s32 starttime, s32 endtime, s32 startvalue, s32 endvalue) -{ - Transform(new Transformation(type, starttime, endtime, startvalue, endvalue)); -} - -void pSprite::Scale(s32 starttime, s32 endtime, float start, float end) -{ - Transform(TR_SCALEX, starttime, endtime, mOrigWidth*start, mOrigWidth*end); - Transform(TR_SCALEY, starttime, endtime, mOrigHeight*start, mOrigHeight*end); -} - -void pSprite::Move(s32 starttime, s32 endtime, s32 startx, s32 starty, s32 endx, s32 endy) -{ - Transform(TR_MOVEX, starttime, endtime, startx, endx); - Transform(TR_MOVEY, starttime, endtime, starty, endy); -} - -void pSprite::Move(s32 starttime, s32 endtime, s32 endx, s32 endy) -{ - Move(starttime, endtime, X, Y, endx, endy); -} - -void pSprite::Move(s32 endx, s32 endy) -{ - X = endx; - Y = endy; -} - -void pSprite::Rotate(s32 starttime, s32 endtime, s32 starta, s32 enda) -{ - Transform(TR_ROTATE, starttime, endtime, starta, enda); -} - -void pSprite::Rotate(s32 angle) -{ - Transform(TR_ROTATE, GameClock::Clock().Time(), GameClock::Clock().Time(), angle, angle); -} - -void pSprite::Show() -{ - Show(GameClock::Clock().Time()); -} - -void pSprite::Show(s32 time) -{ - Transform(TR_FADE, time, time, 31, 31); -} - -void pSprite::Show(s32 starttime, s32 endtime) -{ - Transform(TR_FADE, starttime, endtime, 0, 31); -} - -void pSprite::Hide() -{ - Hide(GameClock::Clock().Time()); -} - -void pSprite::Hide(s32 time) -{ - Transform(TR_FADE, time, time, 0, 0); -} - -void pSprite::Hide(s32 starttime, s32 endtime) -{ - Transform(TR_FADE, starttime, endtime, 31, 0); -} - +void pSprite::Draw() { + +} \ No newline at end of file diff --git a/source/Graphics/pSprite.h b/source/Graphics/pSprite.h index 25ffedb..5f36c31 100644 --- a/source/Graphics/pSprite.h +++ b/source/Graphics/pSprite.h @@ -1,110 +1,13 @@ -#include -#include -#include - -#include "GraphicsManager.h" -#include "Transformation.h" -#include "System/GameClock.h" +#include "pDrawable.h" #ifndef __PSPRITE_H__ #define __PSPRITE_H__ +class pSprite : public pDrawable { +public: + pSprite(TextureType texture, s32 x, s32 y, u32 width, u32 height, DrawOrigin origin, FieldType fieldtype, rgb color, u32 alpha, float z = 0); - -typedef std::vector::iterator transformIterator; - -class pSprite -{ - public: - pSprite(TextureType texture, s32 x, s32 y, u32 width, u32 height, DrawOrigin origin, FieldType fieldtype, rgb color, u32 alpha, float z = 0); - virtual ~pSprite(); - - virtual void Update(); - bool InBounds(s32 x, s32 y); - void Kill(s32 time); - void ClearTransforms(); - - void Transform(TransformType type, s32 starttime, s32 endtime, s32 startvalue, s32 endvalue); - void Scale(s32 starttime, s32 endtime, float start, float end); - void Move(s32 starttime, s32 endtime, s32 startx, s32 starty, s32 endx, s32 endy); - void Move(s32 starttime, s32 endtime, s32 endx, s32 endy); - void Move(s32 x, s32 y); - void Rotate(s32 starttime, s32 endtime, s32 starta, s32 enda); - void Rotate(s32 angle); - - void Show(); - void Show(s32 time); - void Show(s32 starttime, s32 endtime); - void Hide(); - void Hide(s32 time); - void Hide(s32 starttime, s32 endtime); - - /* - s32 x() { return mX; } - s32 y() { return mY; } - u32 width() { return mWidth; } - u32 height() { return mHeight; } - rgb color() { return mColor; } - u32 alpha() { return mAlpha; } - s32 angle() { return mAngle; } - float deltaz() { return mDeltaZ; } - u32* uv() { return mUV; } - - void SetTexture(Texture tex) { mTexture = tex; } - - //for spinners... a bit hacky but meh -.- - s32& Angle() { return mAngle; } - void SetCustomBounds(u32* uv) { mUV = uv; } - void SetHeight(s32 height) { mHeight = height; } - void SetWidth(s32 width) { mWidth = width; } - - //for score sprites (more hax) - void SetDeltaZ(float z) { mDeltaZ = z; } - u32& Alpha() { return mAlpha; } - - DrawOrigin origin() { return mOrigin; } - FieldType fieldType() { return mFieldType; } - Texture texture() { return mTexture; } - */ - bool Draw() { return mDraw; } - - s32 X, Y; - u32 Width, Height; - rgb Color; - u32 Alpha; - s32 Angle; - float Z; - u32* UV; - - std::string tag; - - DrawOrigin Origin; - FieldType Field; - TextureType Texture; - - void(*OnClick)(u16 x, u16 y); - bool Clickable; - - protected: - u32 mOrigWidth, mOrigHeight; - bool mDraw; - /* - s32 mX, mY; - u32 mWidth, mHeight; - rgb mColor; - u32 mAlpha; - s32 mAngle; - float mDeltaZ; - u32* mUV; - - DrawOrigin mOrigin; - FieldType mFieldType; - Texture mTexture; - */ - std::vector mTransformations; - - void Transform(Transformation* transform); + void Draw() override; }; -#endif - +#endif \ No newline at end of file From 1cb2ed056d4d38cfc8335f1e9f9c25a80bdba554 Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 17:34:40 +0100 Subject: [PATCH 09/22] pDrawables can now decide how they wanna be drawn! --- source/Graphics/SpriteManager.cpp | 10 ++-------- source/Graphics/SpriteManager.h | 14 ++++++-------- source/Graphics/pSprite.cpp | 9 ++++++++- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/source/Graphics/SpriteManager.cpp b/source/Graphics/SpriteManager.cpp index 9ca3564..ca167ae 100644 --- a/source/Graphics/SpriteManager.cpp +++ b/source/Graphics/SpriteManager.cpp @@ -23,7 +23,7 @@ void SpriteManager::Draw() for (spriteIterator it = mSprites.begin(); it != mSprites.end(); ++it, ++i) { - pSprite* spr = *it; + pDrawable* spr = *it; //if for some reason sprite is nonexistent then mark for deletion if (spr == NULL) @@ -45,13 +45,7 @@ void SpriteManager::Draw() if (spr->Width == 0 || spr->Height == 0 || spr->Alpha == 0) continue; - GraphicsManager::Graphics().Draw( spr->Texture, - spr->X, spr->Y, - spr->Width, spr->Height, - spr->Origin, spr->Field, - spr->Color, spr->Alpha, spr->Angle, - spr->Z, spr->UV); - + spr->Draw(); } //delete dead sprites diff --git a/source/Graphics/SpriteManager.h b/source/Graphics/SpriteManager.h index 855cffb..7fbf788 100644 --- a/source/Graphics/SpriteManager.h +++ b/source/Graphics/SpriteManager.h @@ -8,10 +8,8 @@ #ifndef __SPRITEMANAGER_H__ #define __SPRITEMANAGER_H__ - - -typedef std::vector::iterator spriteIterator; -typedef std::vector::const_iterator spriteIteratorConst; +typedef std::vector::iterator spriteIterator; +typedef std::vector::const_iterator spriteIteratorConst; class SpriteManager { @@ -22,13 +20,13 @@ class SpriteManager void Draw(); void HandleTouchInput(); - void Add(pSprite* spr); - void Add(const std::vector& spr); + void Add(pDrawable* spr); + void Add(const std::vector& spr); - std::vector& Sprites() { return mSprites; } + std::vector& Sprites() { return mSprites; } protected: - std::vector mSprites; + std::vector mSprites; }; #endif diff --git a/source/Graphics/pSprite.cpp b/source/Graphics/pSprite.cpp index f2fb69e..1866534 100644 --- a/source/Graphics/pSprite.cpp +++ b/source/Graphics/pSprite.cpp @@ -19,5 +19,12 @@ pSprite::pSprite(TextureType texture, s32 x, s32 y, u32 width, u32 height, DrawO } void pSprite::Draw() { - + GraphicsManager::Graphics().Draw(this->Texture, + this->X, this->Y, + this->Width, this->Height, + this->Origin, this->Field, + this->Color, this->Alpha, this->Angle, + this->Z, + this->UV + ); } \ No newline at end of file From dede4aa3fc6cd0866c7e3e426d090aa1c84a57dd Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 17:47:57 +0100 Subject: [PATCH 10/22] Added pText and fixed Lifebar --- source/GameplayElements/Lifebar.cpp | 4 ++-- source/Graphics/pText.cpp | 17 +++++++++++++++++ source/Graphics/pText.h | 20 ++++++++++++++++++++ source/Modes/SongSelect.cpp | 10 +++++----- 4 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 source/Graphics/pText.cpp create mode 100644 source/Graphics/pText.h diff --git a/source/GameplayElements/Lifebar.cpp b/source/GameplayElements/Lifebar.cpp index 27408bf..2bcc60c 100644 --- a/source/GameplayElements/Lifebar.cpp +++ b/source/GameplayElements/Lifebar.cpp @@ -34,8 +34,8 @@ void Lifebar::Initialize() mFillRate = MAXHP/((mFillTime-700)/(float)1000*60); for (u32 time = BeatmapManager::Current().StartTime() - mFillTime; - time < BeatmapManager::Current().StartTime()-700; time += 150) - { + time < MathHelper::Max(BeatmapManager::Current().StartTime(), 701)-700; time += 150) + { mSprites[2]->Scale(time, time+90, 1.5, 1); } } diff --git a/source/Graphics/pText.cpp b/source/Graphics/pText.cpp new file mode 100644 index 0000000..8637d97 --- /dev/null +++ b/source/Graphics/pText.cpp @@ -0,0 +1,17 @@ +#include "pText.h" + +pText::pText(std::string text, FONT font, u16 x, u16 y) { + this->X = x; + this->Y = y; + this->Text = text; + this->Font = font; +} + +void pText::Draw() { + TextManager::Bottom().SetFont(this->Font); + + TextManager::Bottom().PrintLocate( + this->X + 2, this->Y + this->Height, this->Origin, + (char*) this->Text.c_str() + ); +} \ No newline at end of file diff --git a/source/Graphics/pText.h b/source/Graphics/pText.h new file mode 100644 index 0000000..e0ae3bf --- /dev/null +++ b/source/Graphics/pText.h @@ -0,0 +1,20 @@ +#include +#include + +#include "pDrawable.h" +#include "System/TextManager.h" + +#ifndef __PTEXT_H__ +#define __PTEXT_H__ + +class pText : public pDrawable { +public: + std::string Text; + FONT Font; + + pText(std::string text, FONT font, u16 x, u16 y); + + void Draw() override; +}; + +#endif \ No newline at end of file diff --git a/source/Modes/SongSelect.cpp b/source/Modes/SongSelect.cpp index d86c725..ef3f5e2 100644 --- a/source/Modes/SongSelect.cpp +++ b/source/Modes/SongSelect.cpp @@ -99,7 +99,7 @@ void SongSelect::Update() for (int j=0; j<2; ++j) { int index = i*2 + j; - pSprite* spr = mSpriteManager.Sprites()[index]; + //pSprite* spr = mSpriteManager.Sprites()[index]; index += mColCurrent*2; if (index >= BeatmapManager::SongCount()) @@ -108,10 +108,10 @@ void SongSelect::Update() TextManager::Bottom().SetFont(FONT_CONSOLE); - TextManager::Bottom().PrintLocate( - spr->X + 2, spr->Y + spr->Height, ORIGIN_BOTTOMLEFT, - "%s\n%s\n%s", map->Artist().c_str(), map->Title().c_str(), map->Version().c_str() - ); + //TextManager::Bottom().PrintLocate( + // spr->X + 2, spr->Y + spr->Height, ORIGIN_BOTTOMLEFT, + // "%s\n%s\n%s", map->Artist().c_str(), map->Title().c_str(), map->Version().c_str() + //); } } } From 4310cf7db4bda00e122e951c337724a4a21c0f91 Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 17:53:34 +0100 Subject: [PATCH 11/22] Fix compile errors and things --- source/Graphics/SpriteContainer.h | 4 ++-- source/Graphics/SpriteManager.cpp | 10 +++++----- source/HitObjects/HitCircle.cpp | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/source/Graphics/SpriteContainer.h b/source/Graphics/SpriteContainer.h index e5ea239..b853f36 100644 --- a/source/Graphics/SpriteContainer.h +++ b/source/Graphics/SpriteContainer.h @@ -10,7 +10,7 @@ -typedef std::vector::iterator spriteIterator; +typedef std::vector::iterator spriteIterator; /* a generic base class for all objects that require sprites * sprite cleanup is automatically handled @@ -22,7 +22,7 @@ class SpriteContainer void AddToSpriteManager(SpriteManager& spriteManager); protected: - std::vector mSprites; + std::vector mSprites; private: bool mSpriteOwner; diff --git a/source/Graphics/SpriteManager.cpp b/source/Graphics/SpriteManager.cpp index ca167ae..ba38713 100644 --- a/source/Graphics/SpriteManager.cpp +++ b/source/Graphics/SpriteManager.cpp @@ -63,12 +63,12 @@ void SpriteManager::Draw() this->HandleTouchInput(); } -void SpriteManager::Add(pSprite* spr) +void SpriteManager::Add(pDrawable* spr) { mSprites.push_back(spr); } -void SpriteManager::Add(const std::vector& spr) +void SpriteManager::Add(const std::vector& spr) { for (spriteIteratorConst it = spr.begin(); it != spr.end(); ++it) { @@ -82,14 +82,14 @@ void SpriteManager::HandleTouchInput() { touchPosition touchPos = InputHelper::TouchRead(); - std::vector sprites = this->mSprites; + std::vector sprites = this->mSprites; - std::sort(sprites.begin(), sprites.end(), [](const pSprite* first, const pSprite* second) { + std::sort(sprites.begin(), sprites.end(), [](const pDrawable* first, const pDrawable* second) { return first->Z > second->Z; }); for(int i = 0; i != sprites.size(); i++) { - pSprite* current = sprites[i]; + pDrawable* current = sprites[i]; if(current->InBounds(touchPos.px, touchPos.py) && current->Clickable) { current->OnClick(touchPos.px, touchPos.py); diff --git a/source/HitObjects/HitCircle.cpp b/source/HitObjects/HitCircle.cpp index 6175ddf..524c5f5 100644 --- a/source/HitObjects/HitCircle.cpp +++ b/source/HitObjects/HitCircle.cpp @@ -57,7 +57,7 @@ void HitCircle::Hit() //too early, give the hitcircle a shake for (spriteIterator it = mSprites.begin(); it != mSprites.end(); ++it) { - pSprite* spr = *it; + pDrawable* spr = *it; spr->Move(now, now+20, mX+5, mY); spr->Move(now+20, now+40, mX-5, mY); @@ -72,7 +72,7 @@ void HitCircle::Hit() //if within the window for 50, the person hit it for (u32 i=0; i<2; ++i) { - pSprite* spr = mSprites[i]; + pDrawable* spr = mSprites[i]; //circle explosion spr->Transform(TR_FADE, now, now+200, 31, 10); From eaa71fdab6b967fe93960fa82b9186e804bf7f6a Mon Sep 17 00:00:00 2001 From: Eevee Date: Mon, 10 Jan 2022 19:37:30 +0100 Subject: [PATCH 12/22] Text doesnt like drawing but other than that the new menu is done aside from scrolling but fuck that fornow --- source/Beatmaps/Beatmap.cpp | 6 +- source/Graphics/SpriteManager.cpp | 6 +- source/Graphics/pDrawable.h | 6 +- source/Graphics/pText.cpp | 10 +- source/Modes/SongSelect.cpp | 171 +++++++----------------------- 5 files changed, 58 insertions(+), 141 deletions(-) diff --git a/source/Beatmaps/Beatmap.cpp b/source/Beatmaps/Beatmap.cpp index d9a932b..0f63940 100644 --- a/source/Beatmaps/Beatmap.cpp +++ b/source/Beatmaps/Beatmap.cpp @@ -18,6 +18,7 @@ Beatmap::Beatmap(const char* filename, const char* basedir) char id[4] = { r.ReadInt8(), r.ReadInt8(), r.ReadInt8(), 0 }; if (strcmp(id, "ODS") == 0) { + u8 odsver = r.ReadInt8(); mTitle = r.ReadString(); @@ -25,8 +26,9 @@ Beatmap::Beatmap(const char* filename, const char* basedir) mCreator = r.ReadString(); mVersion = r.ReadString(); mAudioFilename = r.ReadString(); - + fLoadable = true; + } else { } } @@ -40,7 +42,7 @@ void Beatmap::Initialize() if (!fLoadable) { iprintf("\x1b[0;0Hcannot load this file"); - return; + //return; } chdir(mBaseDir.c_str()); diff --git a/source/Graphics/SpriteManager.cpp b/source/Graphics/SpriteManager.cpp index ba38713..8767a9e 100644 --- a/source/Graphics/SpriteManager.cpp +++ b/source/Graphics/SpriteManager.cpp @@ -20,6 +20,10 @@ void SpriteManager::Draw() { u32 i = 0; std::vector deadSprites; + + std::sort(mSprites.begin(), mSprites.end(), [](const pDrawable* first, const pDrawable* second) { + return first->Z > second->Z; + }); for (spriteIterator it = mSprites.begin(); it != mSprites.end(); ++it, ++i) { @@ -92,7 +96,7 @@ void SpriteManager::HandleTouchInput() { pDrawable* current = sprites[i]; if(current->InBounds(touchPos.px, touchPos.py) && current->Clickable) { - current->OnClick(touchPos.px, touchPos.py); + current->OnClick(current, touchPos.px, touchPos.py); } } } \ No newline at end of file diff --git a/source/Graphics/pDrawable.h b/source/Graphics/pDrawable.h index 5359dec..547d74c 100644 --- a/source/Graphics/pDrawable.h +++ b/source/Graphics/pDrawable.h @@ -9,7 +9,7 @@ #ifndef __PDRAWABLE_H__ #define __PDRAWABLE_H__ - +#include typedef std::vector::iterator transformIterator; @@ -77,13 +77,13 @@ class pDrawable float Z; u32* UV; - std::string tag; + void* Tag; DrawOrigin Origin; FieldType Field; TextureType Texture; - void(*OnClick)(u16 x, u16 y); + void(*OnClick)(pDrawable* self, u16 x, u16 y); bool Clickable; protected: diff --git a/source/Graphics/pText.cpp b/source/Graphics/pText.cpp index 8637d97..75d0300 100644 --- a/source/Graphics/pText.cpp +++ b/source/Graphics/pText.cpp @@ -5,13 +5,21 @@ pText::pText(std::string text, FONT font, u16 x, u16 y) { this->Y = y; this->Text = text; this->Font = font; + this->Clickable = false; + this->mAlive = true; + this->Alpha = 100; + this->Width = 1; + this->Height = 1; + UV = NULL; } void pText::Draw() { TextManager::Bottom().SetFont(this->Font); TextManager::Bottom().PrintLocate( - this->X + 2, this->Y + this->Height, this->Origin, + this->X + 2, this->Y, this->Origin, (char*) this->Text.c_str() ); + + nocashMessage(this->Text.c_str()); } \ No newline at end of file diff --git a/source/Modes/SongSelect.cpp b/source/Modes/SongSelect.cpp index ef3f5e2..ba440f3 100644 --- a/source/Modes/SongSelect.cpp +++ b/source/Modes/SongSelect.cpp @@ -1,23 +1,39 @@ #include "SongSelect.h" +#include "Graphics/pText.h" + +void OnMapSpriteClick(pDrawable* self, u16 x, u16 y) { + int index = (int) self->Tag; + + BeatmapManager::Load(index); + ChangeMode(MODE_PLAYER); +} + SongSelect::SongSelect() { - for (int i=0; i<8; ++i) - { - pSprite* spr = new pSprite(TX_WHITE, 0, 0, 160, 120, ORIGIN_TOPLEFT, FIELD_SCREEN, RGB15(4,4,4), 20 + i); - mSpriteManager.Add(spr); + + for(int i = 0; i != BeatmapManager::SongCount(); i++) { + pSprite* sprite = new pSprite(TX_WHITE, 16, 16 + (i * 75), 608, 60, ORIGIN_TOPLEFT, FIELD_SCREEN, RGB15(4,4,4), 80); + + Beatmap* map = BeatmapManager::Beatmaps()[i]; + + sprite->OnClick = OnMapSpriteClick; + sprite->Clickable = true; + sprite->Tag = (void*) i; + sprite->Z = 5; + + mSpriteManager.Add(sprite); + + std::string mapString = map->Artist() + " - " + map->Title() + " [" + map->Version() + "]"; + + pText* mapText = new pText(mapString, FONT_CONSOLE, 16, 32 + (i * 75)); + mapText->Z = 0; + + std::string debugString = mapString + ":::: Y:" + std::to_string(mapText->Y); + nocashMessage(debugString.c_str()); + + mSpriteManager.Add(mapText); } - - mCurrentX = 0; - mDeltaX = 0; - mIndex = -1; - - mColTarget = 0; - mColCurrent = 0; - mColMax = BeatmapManager::SongCount() / 2; - mColSpill = (BeatmapManager::SongCount() % 6) % 2; - - MoveSongList(mCurrentX); } SongSelect::~SongSelect() @@ -26,57 +42,13 @@ SongSelect::~SongSelect() void SongSelect::HandleInput() { - if (InputHelper::KeyDown(KEY_LEFT)) - { - MoveSongListLeft(); - } - else if (InputHelper::KeyDown(KEY_RIGHT)) - { - MoveSongListRight(); - } - else if (InputHelper::KeyDown(KEY_TOUCH)) - { - touchPosition pos = InputHelper::TouchRead(); - - // scrolling by touching the edge of the screen - if (pos.py > 120 && pos.py < 360) - { - if (pos.px < 30) - { - MoveSongListLeft(); - } - else if (pos.px > 610) - { - MoveSongListRight(); - } - } - - // calculate vector index (determined by lower right bounding point) - u32 x = (pos.px - mCurrentX) / kSongListSpacing; - u32 y = pos.py / kSongListSpacing; - u32 index = x*2+y; - - // calculate upper left bounding point - u32 left = x * kSongListSpacing + kSongListXOffset + mCurrentX; - u32 top = y * kSongListSpacing + kSongListYOffset; - - // check bounds - if (pos.px >= left && pos.py >= top) - { - // check validity of click - if (mSpriteManager.Sprites()[index]->Alpha == 31) - { - // load beatmap - BeatmapManager::Load(index + mColCurrent*2); // take scrolling offset into account - ChangeMode(MODE_PLAYER); - return; - } - } - } + } void SongSelect::Update() { + TextManager::Bottom().Clear(); + if (mDeltaX != 0) { u32 delta = mDeltaX / 6; @@ -85,95 +57,26 @@ void SongSelect::Update() delta = MathHelper::Sgn(mDeltaX); mDeltaX -= delta; - MoveSongList(delta); + //MoveSongList(delta); } mSpriteManager.Draw(); // beatmap names - - TextManager::Bottom().Clear(); - - for (int i=0; i<4; ++i) - { - for (int j=0; j<2; ++j) - { - int index = i*2 + j; - //pSprite* spr = mSpriteManager.Sprites()[index]; - - index += mColCurrent*2; - if (index >= BeatmapManager::SongCount()) - break; - Beatmap* map = BeatmapManager::Beatmaps()[index]; - - TextManager::Bottom().SetFont(FONT_CONSOLE); - - //TextManager::Bottom().PrintLocate( - // spr->X + 2, spr->Y + spr->Height, ORIGIN_BOTTOMLEFT, - // "%s\n%s\n%s", map->Artist().c_str(), map->Title().c_str(), map->Version().c_str() - //); - } - } } void SongSelect::MoveSongList(s32 dx) { - mCurrentX += dx; - - if (mCurrentX > 0) // scrolled 1 column left - { - mCurrentX -= 200; - mColCurrent -= 1; - } - else if (mCurrentX <= -200) // scrolled 1 column right - { - mCurrentX += 200; - mColCurrent += 1; - } - - // reset visibility - for (int i=0; i<8; i++) - { - mSpriteManager.Sprites()[i]->Alpha = 31; - } - // if we're on the last page, hide the final icons - if (mColMax - mColCurrent <= 3) - { - for (int i=(mColMax-mColCurrent)*2+mColSpill; i<8; i++) - { - mSpriteManager.Sprites()[i]->Alpha = 0; - } - } - - // calculate positions for each box - for (int i=0; i<4; ++i) - { - for (int j=0; j<2; ++j) - { - mSpriteManager.Sprites()[i*2+j]->Move( - kSongListXOffset + mCurrentX + (i * kSongListSpacing), - kSongListYOffset + (j * kSongListSpacing) - ); - } - } } void SongSelect::MoveSongListLeft() { - if (mColTarget > 0) - { - mDeltaX += 600; - mColTarget -= 3; - } + } void SongSelect::MoveSongListRight() { - if (mColTarget + 3 < mColMax + mColSpill) - { - mDeltaX -= 600; - mColTarget += 3; - } + } From 54d1e904ccea6ded0d8ddfbe517e174fc469fcb0 Mon Sep 17 00:00:00 2001 From: KonPet <45455208+KonPet@users.noreply.github.com> Date: Thu, 13 Jan 2022 21:03:47 +0100 Subject: [PATCH 13/22] Add Backgrounds for Player Uses bitmap backgrounds. Backgrounds are stored right before the hitobjects to make it easy to load the background and preload the first ten hitobjects --- Makefile | 20 ++++++++++-- gfx/menuBG.grit | 7 ++++ gfx/menuBG.png | Bin 0 -> 11937 bytes source/Beatmaps/Beatmap.cpp | 49 +++++++++++++++++----------- source/Beatmaps/Beatmap.h | 3 ++ source/GameplayElements/Lifebar.cpp | 10 +++--- source/Graphics/GraphicsManager.cpp | 6 ++-- source/Helpers/AudioManager.cpp | 5 +-- source/Helpers/FileReader.cpp | 6 ++++ source/Helpers/FileReader.h | 1 + source/Modes/Player.cpp | 23 +++++++------ source/System/TextManager.cpp | 6 ++++ 12 files changed, 96 insertions(+), 40 deletions(-) create mode 100644 gfx/menuBG.grit create mode 100644 gfx/menuBG.png diff --git a/Makefile b/Makefile index ee85ce6..18059f2 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ include $(DEVKITARM)/ds_rules # INCLUDES is a list of directories containing extra header files # MAXMOD_SOUNDBANK contains a directory of music and sound effect files #--------------------------------------------------------------------------------- +GRIT := grit TARGET := osuNDS BUILD := build SOURCES := source \ @@ -26,7 +27,8 @@ SOURCES := source \ source/GameplayElements \ source/HitObjects \ source/Rulesets \ - source/Modes + source/Modes \ + build DATA := data/textures \ data/sounds INCLUDES := source \ @@ -73,7 +75,8 @@ export OUTPUT := $(CURDIR)/$(TARGET) export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ - $(foreach dir,$(FONTS),$(CURDIR)/$(dir)) + $(foreach dir,$(FONTS),$(CURDIR)/$(dir)) \ + $(foreach dir, $(GRAPHICS), $(CURDIR)/$(dir)) export DEPSDIR := $(CURDIR)/$(BUILD) @@ -82,6 +85,7 @@ CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) FONTFILES := $(foreach dir,$(FONTS),$(notdir $(wildcard $(dir)/*.bmf))) +GFXFILES := $(foreach dir, $(GRAPHICS), $(notdir $(wildcard $(dir)/*.png))) #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C @@ -99,6 +103,7 @@ endif export OFILES := $(addsuffix .o,$(BINFILES)) \ $(addsuffix .o,$(FONTFILES)) \ + $(GFXFILES:.png=.o) \ $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ @@ -135,6 +140,17 @@ $(OUTPUT).elf : $(OFILES) @echo $(notdir $<) @$(bin2o) + +# With matching grit-file +%.c %.h : %.png %.grit + @echo $< + + $(GRIT) $< + +# No grit-file: try using dir.grit +# %.c %.h : %.png +# $(GRIT) $< -ff $(d2a~Jcsz?3Gn+6i^n5!LES|@e?%0C8MwSAJVfY&`edFA+~@@}1v6@ihbBKge0 zPp64X#b>q~JWwvWvno{wVQF9f5%5`i(m%v;O6)pTO%xn^?$i!t6o#!b>S5+DgEu^` zoZrrH(fykDCd%t=l85F5>jF+_Svb_)Yfg#Xhry0nJRTQS-SZgP zHqB?tg`)!8oTNfkilD(qwYwobvc)1($DsPtT7{WbKZ+zDshY0c^B*;zx1>%rRDH`< zSB8H^c;o0P6PvgOW)Oy_i4rSJwDR<_Rs;R7MwBuv~_FBT@^;f8nHS z^OULihi7l2=3hq;84$YV<4n_|(vLRr5;5Do<9t$3=VY17#qQ$eT;~yv71!K(>DTP< zXbYCo?TbhHWviuKxzsa%JQR~GCryeZ->{Y~0eX=1x?S8pEagv&@i9Il5~Z;+OFoyG zZJWyNKYO?h)~4&kygaes-e2h zJiqO|w^5O1s~23M75$3K^KT6yiC({OCzAEQZXun&mJ|2r(9^!KY=wgCSR-o!JzK@b znb~z=7P~B@qN791HA2&wdXlKrZ?noc7FnzVyka*zwh_lp=R7F;^sw7mRAU)-?iE#6 zc#{Qszcb~z#X{n~q~JE6upo|G1nRK+r+cw{hP|fHdf%wAP{R(|E7@Cb!|lqBCz(3m z&6{>aPUC_r%IRR9XAzWH|Ig6OUVh_ubOPkA`~ls{7>l8@&g98UFzL4kwMf2Mn~Mk! zk~{O+C%xnL<;Gnj+h7I`vrW^NZNZ89E$Q$n(v%p(-DY6?#OC_+3>0*$e%5blUytl% z!4BCIT2SERibW43VOV^8lQAW|ee#qal z?z2`s8;}DToK9n@$ZpC;Z#&g|E~RP6YCL^XQ0ofSp=j_vH~e^Eh$}%{mut}?q~yF1 z8G;Q%+kCF5TtPPBS(e4URWIazuS>Sz_IXoYhzgqvSAJkA zyEPw7D&fsRVd$2HTYE>>SWqHAYpsdeYRLv`8YrNzH`L8R*?N^6y;SIYB zzbbBXLH~?SQ{%m!DC}0972Inma~y>Xa~hUBT8?Ha6hTwnJIgu8$w9k!AO=#G6FKjx zmo|`XD!9Y`Q~iWQ-D&W;F=bXJgohTk*L%n5P4lPQvrmTEz}K~MX7(0JPa6ZBjz29R$9rc?RDMM=@1WW)+&t1q;k;s4_ndiOm8ooijhWrTlWCU9AudG_dpH%z z+#vVfhbgF%4NcOl-Tni7&Y$#y-^!e`xUoqPI?z8_OL)oJ1@4#u&kjRnc>5>2k0E4V zcq3#nC=yjafuLqL9M{5(@U7)cyfGQ;fujQoQUNL3y*iUOFYmP?G4U-%1`#4`%=iU- zcs^Syj4gyyH|g9)efUmi%0A%Xv=<5D-*8Ap<3NHv{p#`ZFm#kI!Qau;W5-~y*bbv1u znGCmV2KA;Gu0}N-A>P2Pv=@A3c!NO5C9!{r%ipUW7ubuoy8|7=ako(!Xm;(zN+Neb z7X%ug#Nqd5yF-5jnS08IjkoXS#?5_nkYVM0LaqmaEJC3W+qn=JbYK79#@UmMZ>1}y ztnt%LGI_687Tm-~Sq~g-G*UF}z^awz2m)E0?yt{-xDR_ zgv-fp&c%^f)1=zAYvn7PbGRFP^dIm={FV-UqHh@Df~%wJKoDoWFe3PUd`xr}CC@kg z{=`>xUQMr2h#sG9o8mzGZV0Ce?A^OtpK-L(aBo=jfZ%7AMmtxNG=u|B%{KGU&9dA7 zxQqXqhMyjYl3a=&!)7w-gMp_itrGK8IdpoA5Lp4S%fZ;!QJARiJoEd87%99G8Z1>Y+R z4M)v%7<823G7WR!b52gtD03;;Zty0G7BBqp5k^vK;xA+2q#GJfP|^ zUJ`csY?g^#@3rS1^pwnJ$}Koz&rKEm*zJ%>j%a7}JBTE%A85^mkOYS0(!6F~w6~>I z;k_J<(B85P`$|Vvka*JK+ed*1L1P~F%!)8jXwTcRNTsZjjZB5cQ1&U%3w>Nymc6{Z zfAcXbmMOR2d%hdzSI~KJu26Lp<|b}TK`H8=1^`I&TQ$WM04Voub{?k&f{yG-a)=mk z=eUKVmXj>=)Njv04rRfNAlQOZ(Q>#^^S0^1Nzj=b-2NTzxF$u|gXLclIJ)PrgyLI0 zZKGl_Vd3$Q1alJ#JK&M2?CtLC6843Gp!yvEEmImwO-V~`_qpo04O2xo8)tPP0!M0s&9}nGbVtp94O~Z7JNyo9hio&xyNDwz)dc@6cKa&!vBP zqO>Exd!ivCWCpnDhW-PT69zk&Fg2cH{b3a>9%#_gc=nv*?0X70we-QVIe4ojowMYA z1=N?II6bV<-J{v+Di(a+O@M-#^*biV^cwvmH^dGYHIPsMdXV!bTDBxnCS@19XZ7|# zh1(23`aIGaO(d@oG5^8f(S~BlVs~h_IPM5|L*jVlvGN;i=)-iu-rt7+K=wZn+Gy`S0xwbAj~Yl_ zv2qbRGQ9r}))}9c)KntaN#$RW9~xr0Z!20QqpK^li`U~;3gdbwJ(A3h?KGrJphZz} z5IrG@FP6IEb#A5ZJ0}ZybSN_|7bPEDDLPe)R@))ffa4Ejq0}+K&n`U)&~3@4KDBNlsl3 z>?ZEwPTX2QoiWnqq`8ip43GODL`j1{AvA<{%Gzacu32bN!RdMqTyi1Im7c%bj=o~i zkbMlh@LeSxbsa$0Ly?z$l@U!`p|@%^7FDp8AvyH#4$x#~XpjDCrMBlKK{)OarCajk z-NF0r_NrcT8(p1H7q2#KG+A}WtU8w&-Cd#wK+{ZDwTUZuQ(>(z7)@+vtURSj)N|u5 zk=>=Aiswb?*G2OzM<=aW1X1YC7FRp0s)0bL37fe4-OlL0#?nFrO`neh1;~BH}-Pp|MILL zU+SHn@7iAaY)3#}Wu#Fev*GIm*d2`sC?*^OAIQ6I@kpk)EJJ0i5&#?w$WCuhbJsCa}JD6GpOPB*R=;MUQciS&R! zvi2(l5aTn?rE9WQp8}uy(I9ySK};HtBSii!mB!q1SeG8Y=rzHOU9tTe;bmuUIE zhI+=}V3Yd1aGJUBRt^6$@9I|}zfS6DO-M*JKJvP7(c!57IT|xxucp5yB<8t=%=dSZ z(Kk_|jTw*S<4f8syNtaDUYJtPZGkvgGJ~s~8%}3-%hRetubvoi{L$e1C%35g;MZxx zWBltGeRVhj10Fwbd(Lo;R{S-RFk3Rj5+eO*dV2Sn{nUn~Hf+X^EuEV*Yv{k|?Q=5) z5ceVibno@y#vDh`Ey20yW5QFOkW2HRs_{2xW*-G8VN)9`>qN{==N@F0vTr|rQ$^3o zi#Z_&nkacQv?Mo8$@tt;^3a=Bf2Y;{vtYB=bTURL}kH2 z$|GW|5KMY<@F^dx^*UVp{+*kC1$XmP$2c>!a)*UCaw2(g;Zv)9vCe7O$c}l*R(q+* z&nIV~6(GyMg2SLN_Rq4n07b#kIDH2su?|o<(1zX{LxLXwDY4T$f;!Ogap=`FPgHbu zC)e8qZ+*VHbVZT8*{Mwr&&hZmw#O{4e@w=a$eKT1*jrZC@e^m*a@=~dYvKIeO0Lh23hiP)4`0{5kC;8X` zM%roz+$l-2`nC}_IoiwznZLxdJo!94EjGGs%PfDDBHvODyD*pc?KFS>7WB=X_J@*V zM@6KgGeZ|S2`ApW#RU>jx)>JKMH#<)gtD3$UmO?^^?aaaj@@x2&h=UHVrU#_Cr!y4m`N`Aa##1KE zi;R}--ZWS7RA_?wCBdIFT40jjePdffP*hH4L`i9-mKRH{%_<%n2vD-P1UM!q;b+Y0gng)~{UP9i# zh%=U0O4CtxF!}!mdEaROq!ag08~eq_3#W`xnvM#c;0IafvddtTr#=mx8s9RcSiAC9 zL3E@UdLzhg7Yq}_@^Wsx15j1!!-g`PXji78GDKgAgm{|m)@dx-=D3ya!TIZ*F|}dA zRUEDdPm=Le1ec-3D{WkUlw#R|{6NIKzRR61$ ztE{gAo-JV_2cE9^4H)d_mv4~Wd+w($Yp_698YvUI+FDD^xr5C^(+$PQyKdr#xp5V< zdP`+_7nPD6dnu%=*}*C{C2oezIkFLqj?Ix;z!sbI7Las% zIVOAK*WKGKs&~FRK+7@2Ehnys&+5}e-SBx!ja0+1Du04wfr{f=?1+$qNP+|SbLJw#y%^{oeDs00rZM6YK=GEV%nXZqKESm z2E+Kt>C4>>VcxX1f=u8AKFDdn!oYo$gy~Kx5ZmNZ=%?EDrrBreoinh_?NOWj(<~>V zu}U;Q-{S_ZS@VxLwq1Ni%}soP97VI7 zSDgA)$4SEC3nL(z5<`u}bYl(Whkx=-zb>o{n#56)Ot|e8PIu7YYg^e5%J4V-)>xh` zE#>M(`PDwo#Q&+el2T>R3tCSKUEx$V#w`<8wI1DG^ib93c{guks%EpuUTQom&8-gv zUj=9T+OmU$9vxRsV8rKaLO85O_h+A$eo+Q{9e7)WmkVZTM0jWxtZjB5Xb-bgbAJR_ zd(2||WNen@&4GsDE_AQG{O|S3F@Y&Dd!uf3sPPecI45RMSm@{5)iw8DcWSz0;>h}* zS@Z9%k_&3lQDlgeZG3gy-T4|mwRc})_OYn3))5~v<~yA}-dwkOVf%2cag=yZ`3ucY zJZZC4-e{0j0G|sTORyo{?RJWwGS132PNoO_2&dnna2T?~oM-Sj&+Sp&rzDPeEfyW+cU;TylEuzlH@ceT{t!ns#(<2fY zVzXLq)87&jm=<9H#!Ooe3T~}%yKH1YEdiF0JzeOT9DJhb3gYScyEVzb`o-@(nug3} zqu)Fo#uezre;&24q*uxQOhZf*B~urH5t{kxNBF={Z)znc%g2cLh{UP4{v27%=3Wsr z=>oU=2grNqz4NcYx?AObk)QgChFBjLfX(PsV;lF;!b?{x8Itz8xb@>`%)IV{LB&*rWXi@NaYUX#iF(^}5?lWN?q@UKyI#HEYu)nvY30ydIS z&bPtwr9dq&(Y~z!Ny8eh4jTLW<*?wG?~wp~9yfFMChYOo6Iw!rZtAOjdBlGvg>#8M z*cVhH=er_5|0^T9R6w7s+YZd{k=Pd8&aT5}n}gEyc}hbwja8Fw^k5@D_G;HT=Z>Bu zFBPI4_*KJ=;a@Vo@51z`I&a9XyILu7LZ|6c66zY%Epy$4Sz5>nP<$82Tyar^&5(|t zy))<~CkHz4U2M%QSMRj5Wy}!`w0{0Nqv+DDVuj}2oG`Mk8SXA{G5lIwl_`tgV_y>3x#93wEj}zo4l(Q%zc8}^r`9X=7A&(4z+nV zG)!UUoHGHRVU^8Mb0t_$)(xV?Xf*0Cp%EYVV*7MKcPaTk(zlso?yj-HZBP=Mv1({8 zHC{+3t_N+X3}MlO=NXV&EC!svoc)$QatBx(*nruOP;(d6@&?7n37_yZfSBC?4)>Ji zjIW5LHY5sPm}lU3pEh2q@eK)@21id1y`Z^CP6Pi6`#Ps)Nz+UBtZ55;l{^{*`fV(n z(s(WCdDi90&z?6l_w<3i5Nv~+LQp|vh%?WI`Z~F%?Y5HQGtWP-n)0uEzVmAU4{4XK zB;9xw{m3%6H2OYQ5PqmuZUc2+DcJv)&vtiHBD2qHeR{I4Sx|*8-!iR`8hdkC0uE@R zfGMyxqp85=Gs0V*TfFYaINxq!9Rt}wu9=ew8E2AIUlbRV=Nk1!A1yP z;5Bj{dd_Lj$nO_^HuS_5UQb#Qwv7Wcy(T>FQ!8Jx;`YeZZt^s774y`GTG8m zxIUi)K%BPf7bn}BgHbSC4C#?>z4?D=it3!;^+SNBC>9eWzh-mb&y@ft(cJ}YwdPb9 zEu#i(dhUBxaWoS@Z`*h+(083gCJyh&p!OckQUQ%uZk4UWAK;X=cuPhDuJDx@b z&sWkZ5Eo%6%8zefSvz{WZF||mwYaxtHM4wwu#Qi$=odK(|1)X}s3a*abU_P0keC-? zkhJ>EEb7H=`D2YQb<2%dc9nP{%FHmgHuV@`dl(AV98nF-@#PSw{+#h4p< ze|J4nNJS~|OSW7EY0p46c4r_Sa3-&+NH;et=AS7)6m~Pt;FaiCkJUs;+Hzn_>q0*^ z_s{({_MYbZJN!1LD`e$yirj27fT~wrID)6g0K&_%$3n;B;=PEhzL94U^v4diZkVhL z9fv1MF5B*$9H2KX+LjMV!Wb6xfaVGSlU1b-tSYirihaY$UNO5gyYjwGOxcvO5~-4a2ixMadYYJAcL zCm%1VxsdS}n*V!)0pVE27znfhww48O6E7A`y^4;4#DPJJrz8U2g$SdR>RZkvwiGDj z`jFsc>hSUmEYdRhxX_p09xO(NtT3SwTny1~whkvg7Z>?rQIQ203K)Oj#NKhqUb|` zEvKWOnAkn(IrBM3FRRWxsMS`=tdW0hJc2_@E=gnMJOV#su&Fj68nAg+~5Y z=&AJ6`cx9Y%l4B8=oR|3MaaKP%!`gHcF^ck=!lO#nZ}vL*$TTtx@2~3jUv|I z$A|3amI#>hqr}6}&crYAIrzztkz8Z2^y-B&-!PxK7LQ>WYfTO;lD>3pkvRv{7;wog z9EBR7FuzDR(DNlGb&A-o!YrUfQzya&1EiyXb^P!mKj`29Wqo2`);{M^<4;Yg%l}kj zIu5%ZvoJCR8f{24jO#Vb4VJHP1icb1Yy5eC(7)%!Mil3qb}=+04#~a)!;Bx{$Ju$q zw*`tOHsDxv?tcFm`0#Tn+h^rBES{}4oUzIbF+`+oyV*k<@tWl4^}mq z<8uX+Hu0;du&3Y)@^{9vHdS{|cJZMpJJvaJ5S)2d51uK7gdcs*qUiEUy)kNqhlFPx z4;7M>mP;1SgiZstE}%>!1P#~>)aGyMc1m&KzAKc- z>d~HfXN+%%bU_Qx?LkZ+EA^t_h4jidh|cqOqh(}rUg?@elRPeqZ)H(1t!PJbPlX)b zfNp|7y_o<6^UHSB*-FHjzZ4@W>d-~4H(B4s_0C5J@SZ}3DR-hbKqWVBFWEP)5r(L9 zfTDl_tFyL~%+}qO7^m0 zvLfs_MkDk%*=EmLn8PNEu4_Mv-@{a82tI1JxM>QxMTO5+O1fd=fer-!==v&`fJ4QF zQn3GIT!h}V-I^A-CQC{b}R_wJMabo=k(O8BWP%K!^4Qia2)D&SJIMU5CjIzpdB zKuAh;a{0Vu2Ll)JSKzrBnR%R~)R=xm=yJ9lVa?LUyr!SORt%Q^aMqQOrhGu3x4t>v zKN|3=cOg)`ovT3jW93)u<=^pxOP|V|TnG3of3oABzu3iu;YB-Sf3d2ACZRaGt~K-e zKJeq%upiH{cmt%v+}hT?Oc zQ$=U#sTY;_JE+-GAmrm4HrGT_jHv%mHvh%)vzl%M&Z$`XR3r>CVT`10E%N_2*JJaH zejXnYcaF>uk+=;;T&*ZBqhP)+B*xT%llEa;}m9l;jid%MsNCd(~WEKi{}o> zHqYr_PGVZwYZffz7e^MEM)wJfv&dLs+Qk>ipS$?G%$dj?UP)~S_QO8-h~Oo6EGiM; zLFj0#L#j>q0DoH3)s>Krae$=(7TT9_f51RHiRoaULLM5>WQHV8j_>D-R&@lKS=bz`vVXRY#(9a!FsGg`wvj3AUWseMT zA>S9hVeJK0)QRFX4~q~1pJKJ%OhvtER;1iV#{|E>*NF-qt#l3=pb--D8Saby!9Y++ z);msH?=+6?GxOf3cVEY+m3`BM<9_%4;r}f65+(!w*}{9*PmQ^_)-Sig&0NZrZX6MZ%1YDd`a1>7ig z*lv_!DDND54jOC9qB{@(J+W1v`Cyq_qvJ0Ohz62rksEUG8NO}$MaEKJ*9@zlmi08v z4{{suJ)Bobp})r-q`wgzb|9=%1-fGC%1-|8a=RjeC4NNb-QH=6hM=_|o0r4H^3+qP446&fcp}dp``#cKD_Z8*#_2`@4KFw{tLfSxZ1$j+gWbU$+f?JJHH>ZY!_ z)mcEQ?1?wLxABzax}O@tFcwpJdq?>Y$AoccH)<2b6^%7Z`Zp@02k)|XYO{6|uM0h} z*8Viqe!e%v+3`*|5O_YAErn+FOQVH*Ddt+)#)@V=)tiI-vU9*GWX1L`DJjx;GHm@SZlWmco$*$crQDf zeR9~}n)>dhO2@-xf+%tOhqY_G&G9=YUGv{~pmVvK%tvl{dRI21J{!4)x^5ZE(`Tc& z+b#~{44Bo(8;k^9sLkWD0}q-NV8E-5g<&mygt8<}j=DFHf72Y_gN5aa71l&n2#K?6 zbHKB+!r5pCSWjqnF0NN+Gp5WDFG5sAMpBD09s|C9vHDRy?@xu5vX_me>Q?@mG^io( z+7XUU2Pwnv8@r$Z{h7huEHWqiz7{X77CTwnHKYLqF0mWg#^CIIJAYQ<>)2^CTd#(&l`i7QZFL> zb-Zbxmu7Wh4F>+SByfXvegg>0f)OW-WE0N+Y+c?7r0TXZA0iVcs@GC=K~=}abrhzq( z08W#I?2VZt&1<+Ss$b}jOj$!#6=ZK%#csy|&aDsJQf^?cQUCQC@uM>5OnR}6+{Ce) zYr2H0(BV&z+o%7xfjJtEO<^;tiD?aNJ>QReIx_)Q)zIUykdv(IdD37%Q+th!OoVsf zAiUWVlEzuRr__XAiTYZM2B7XCCnO+lR; z`ZfvV2rjv-r%yak*5^%CCH?-N4UJaY>CW}hg4&#}w>pEm80Ph*AB{b7b^!0bwnu0C z5+lL(#_Qj2_%|}>zUb$X1%w9M@;f;hfzI>Ik!WwPrkAWu^aE z?4F-cnH20TIK7RM?mD@r!|3+BL~kEc3E_PmkjBq{_KpLxdzS@*Gwb}V`LCUy(S3UF z187i~x~%7`oRR5E540o93^#7`kHk{SNJ#+8Tv`3rH-Vfu9QF?I#X%mf$6P88T}=F6 D!#?^= literal 0 HcmV?d00001 diff --git a/source/Beatmaps/Beatmap.cpp b/source/Beatmaps/Beatmap.cpp index 0f63940..8190659 100644 --- a/source/Beatmaps/Beatmap.cpp +++ b/source/Beatmaps/Beatmap.cpp @@ -51,7 +51,7 @@ void Beatmap::Initialize() //skip header mReader->Skip(3); - u8 odsver = mReader->ReadInt8(); + odsver = mReader->ReadInt8(); mTitle = mReader->ReadString(); mArtist = mReader->ReadString(); @@ -89,23 +89,6 @@ void Beatmap::Initialize() } iprintf("\x1b[2J"); - mHitObjectCount = mReader->ReadVarInt(); - mHitObjectRead = 0; - mLastObjectEndTime = 0; - mForceNewCombo = true; - - //read ahead - ReadNextObject(); - mFirstObjectTime = mNextObjectTime; - - //the time to skip to is the first object - 8 beats - mSkipTime = MathHelper::Max(0, (s32)mNextObjectTime - (BeatmapElements::Element().GetTimingPoint(mNextObjectTime).BeatTime*8)); - - //strangely calling this in ctor of BeatmapElements causes game to not load :/ - BeatmapElements::Element().ResetColours(true); - - //now we can play this map - fReady = true; } } @@ -125,7 +108,35 @@ Beatmap::~Beatmap() delete mReader; } -void Beatmap::Buffer(std::list& hitObjectList) +void Beatmap::InitBG() { + if (odsver > 1) { + for (int i = 0; i < 256 * 192; i++) { + *(u16 *) (BG_BMP_RAM(8) + i) = mReader->ReadInt16(); + } + bgUpdate(); + bgSetPriority(2, 1); + } + + mHitObjectCount = mReader->ReadVarInt(); + mHitObjectRead = 0; + mLastObjectEndTime = 0; + mForceNewCombo = true; + + //read ahead + ReadNextObject(); + mFirstObjectTime = mNextObjectTime; + + //the time to skip to is the first object - 8 beats + mSkipTime = MathHelper::Max(0, (s32)mNextObjectTime - (BeatmapElements::Element().GetTimingPoint(mNextObjectTime).BeatTime*8)); + + //strangely calling this in ctor of BeatmapElements causes game to not load :/ + BeatmapElements::Element().ResetColours(true); + + //now we can play this map + fReady = true; +} + +void Beatmap::Buffer(list& hitObjectList) { if (!fReady) { diff --git a/source/Beatmaps/Beatmap.h b/source/Beatmaps/Beatmap.h index 596e7b7..837d117 100644 --- a/source/Beatmaps/Beatmap.h +++ b/source/Beatmaps/Beatmap.h @@ -33,6 +33,8 @@ class Beatmap void Initialize(); void CleanUp(); + + void InitBG(); void Buffer(std::list& hitObjectList); bool GameOver() { return mHitObjectRead == mHitObjectCount && GameClock::Clock().Time() >= mLastObjectEndTime + 3000; } @@ -73,6 +75,7 @@ class Beatmap std::string mCreator; std::string mVersion; std::string mAudioFilename; + u8 odsver; std::string mBaseDir; private: diff --git a/source/GameplayElements/Lifebar.cpp b/source/GameplayElements/Lifebar.cpp index 2bcc60c..8d8a1f2 100644 --- a/source/GameplayElements/Lifebar.cpp +++ b/source/GameplayElements/Lifebar.cpp @@ -28,15 +28,15 @@ void Lifebar::Initialize() mHpLossPerMs = DifficultyManager::DifficultyHpDrainRate * 2; //units are hp/ms based off a 200 point scale mHpCurrent = 0; mHpDisplay = 0; - + mTimeLastUpdate = GameClock::Clock().Time(); mFillTime = MathHelper::Min(10000, BeatmapManager::Current().StartTime()); mFillRate = MAXHP/((mFillTime-700)/(float)1000*60); - + for (u32 time = BeatmapManager::Current().StartTime() - mFillTime; - time < MathHelper::Max(BeatmapManager::Current().StartTime(), 701)-700; time += 150) - { - mSprites[2]->Scale(time, time+90, 1.5, 1); + time < MathHelper::Max(BeatmapManager::Current().StartTime(), 701) - 700; time += 150) + { + mSprites[2]->Scale(time, time + 90, 1.5, 1); } } diff --git a/source/Graphics/GraphicsManager.cpp b/source/Graphics/GraphicsManager.cpp index b5a0427..5ceadac 100644 --- a/source/Graphics/GraphicsManager.cpp +++ b/source/Graphics/GraphicsManager.cpp @@ -51,17 +51,18 @@ GraphicsManager::GraphicsManager() videoSetModeSub(MODE_5_2D); vramSetBankA(VRAM_A_TEXTURE); + vramSetBankB(VRAM_B_MAIN_BG_0x06020000); vramSetBankC(VRAM_C_SUB_BG); vramSetBankD(VRAM_D_MAIN_BG_0x06000000); vramSetBankE(VRAM_E_TEX_PALETTE); - REG_BG0CNT = 1; + REG_BG0CNT = 1; glInit(); glEnable(GL_BLEND | GL_TEXTURE_2D | GL_ANTIALIAS); // setup the rear plane - glClearColor(20,20,31,31); + glClearColor(20,20,31,0); glClearPolyID(63); glClearDepth(0x7FFF); @@ -260,6 +261,7 @@ void GraphicsManager::Draw(TextureType tex, s32 x, s32 y, u32 width, u32 height, glVertex2lu1f(x1, y2, z); glEnd(); +// glClearColor() glPopMatrix(1); } diff --git a/source/Helpers/AudioManager.cpp b/source/Helpers/AudioManager.cpp index 3b78907..c3e6dbf 100644 --- a/source/Helpers/AudioManager.cpp +++ b/source/Helpers/AudioManager.cpp @@ -119,9 +119,10 @@ int AudioManager::MusicPlay(std::string& filename) MusicStop(); mFile = fopen(filename.c_str(), "rb"); - if (mFile == NULL) + if (mFile == NULL) { return -1; - + } + MusicBuffer(); return mChannel; diff --git a/source/Helpers/FileReader.cpp b/source/Helpers/FileReader.cpp index cdad308..f621d35 100644 --- a/source/Helpers/FileReader.cpp +++ b/source/Helpers/FileReader.cpp @@ -145,6 +145,12 @@ std::string FileReader::ReadString() const return s; } +void FileReader::ReadData(void* ptr, u32 size) const +{ + dmaCopyAsynch(&mBuffer[pos], ptr, size); + pos += size; +} + void FileReader::Reset() const { if (mHandle == NULL) diff --git a/source/Helpers/FileReader.h b/source/Helpers/FileReader.h index cbdd592..a66b378 100644 --- a/source/Helpers/FileReader.h +++ b/source/Helpers/FileReader.h @@ -22,6 +22,7 @@ class FileReader float ReadFloat() const; u32 ReadVarInt() const; std::string ReadString() const; + void ReadData(void* ptr, u32 size) const; bool Ready() const { return fReady; } diff --git a/source/Modes/Player.cpp b/source/Modes/Player.cpp index 820b4c8..efdf26a 100644 --- a/source/Modes/Player.cpp +++ b/source/Modes/Player.cpp @@ -1,14 +1,16 @@ #include "Player.h" +#include "menuBG.h" Player::Player() { //initialisation mRuleset.Initialize(); - + //load audio + BeatmapManager::Current().InitBG(); ChangeToSongDir(); AudioManager::Engine().MusicPlay(BeatmapManager::Current().AudioFilename()); - + //set player to process gameplay mPlayState = PLAYSTATE_PLAY; } @@ -17,6 +19,7 @@ Player::~Player() { //delete mBaseDir; AudioManager::Engine().MusicStop(); + memcpy(BG_BMP_RAM(8), menuBGBitmap, menuBGBitmapLen); } void Player::Update() @@ -26,39 +29,39 @@ void Player::Update() case PLAYSTATE_PLAY: { mRuleset.Update(); - + if (BeatmapManager::Current().GameOver()) { mPlayState = PLAYSTATE_GAMEOVER; mRuleset.OnGameOver(); } - + break; } - + case PLAYSTATE_GAMEOVER: { iprintf("\x1b[0;0HGame over"); break; } - + default: break; } - + AudioManager::Engine().MusicUpdate(); } void Player::HandleInput() { mRuleset.HandleInput(); - + //handle play mode input if (InputHelper::KeyDown(KEY_A)) - { + { mRuleset.Skip(); } - + if (InputHelper::KeyDown(KEY_SELECT)) { ChangeMode(MODE_SONGSELECT); diff --git a/source/System/TextManager.cpp b/source/System/TextManager.cpp index 5c777c0..ff3a5e0 100644 --- a/source/System/TextManager.cpp +++ b/source/System/TextManager.cpp @@ -1,4 +1,5 @@ #include "TextManager.h" +#include "menuBG.h" TextManager TextManager::sTop; TextManager TextManager::sBottom; @@ -19,6 +20,10 @@ void TextManager::Init() AddFont(FONT_SCORE, gomics_bmf); AddFont(FONT_NUMBERING, _370_bmf); AddFont(FONT_VERDANA, ver08_bmf); + + bgInit(2, BgType_Bmp16, BgSize_B16_256x256, 8, 0); + bgSetPriority(2, 1); + memcpy(BG_BMP_RAM(8), menuBGBitmap, menuBGBitmapLen); } void TextManager::AddFont(FONT font, const u8* data) @@ -45,6 +50,7 @@ void TextManager::SetFont(FONT font) gfxConsoleSetFont(mConsole, mFonts[font]); } + void TextManager::PrintFloat(char* format, ...) { gfxConsoleSelect(mConsole); From c2cad2673568d428d131017dca59d740dbd8a776 Mon Sep 17 00:00:00 2001 From: Elisson Eric da Silva Andrade Date: Tue, 12 Nov 2024 01:21:29 +0100 Subject: [PATCH 14/22] Fixed infered int type issues --- source/Libraries/gfxconsole.c | 7 ++++--- source/Libraries/nitrofs.c | 9 +++++---- source/Libraries/nitrofs.h | 8 ++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/source/Libraries/gfxconsole.c b/source/Libraries/gfxconsole.c index a4b47be..9e64088 100644 --- a/source/Libraries/gfxconsole.c +++ b/source/Libraries/gfxconsole.c @@ -197,8 +197,9 @@ static void gfxConsoleClearLine(char mode) { } //--------------------------------------------------------------------------------- -ssize_t gfxnocash_write(struct _reent *r, int fd, const char *ptr, size_t len) { +ssize_t gfxnocash_write(struct _reent *r, void* fd,const char *ptr, size_t len) { //--------------------------------------------------------------------------------- + int count = 0; if(!ptr || len <= 0) return -1; @@ -217,9 +218,9 @@ ssize_t gfxnocash_write(struct _reent *r, int fd, const char *ptr, size_t len) { //--------------------------------------------------------------------------------- -ssize_t gfxcon_write(struct _reent *r,int fd,const char *ptr, size_t len) { +ssize_t gfxcon_write(struct _reent *r,void* fd,const char *ptr, size_t len) { //--------------------------------------------------------------------------------- - + int fd_int = (int)(intptr_t)fd; char chr; int i, count = 0; diff --git a/source/Libraries/nitrofs.c b/source/Libraries/nitrofs.c index 8e5846e..66d81e2 100644 --- a/source/Libraries/nitrofs.c +++ b/source/Libraries/nitrofs.c @@ -318,11 +318,12 @@ int nitroFSOpen(struct _reent *r, void *fileStruct, const char *path,int flags,i return(-1); //teh fail } -int nitroFSClose(struct _reent *r,int fd) { +int nitroFSClose(struct _reent *r,void *fd) { return(0); } -int nitroFSRead(struct _reent *r,int fd,char *ptr,int len) { +int nitroFSRead(struct _reent *r,void *fd,char *ptr, unsigned int len) { + struct nitroFSStruct *fatStruct=(struct nitroFSStruct *)fd; unsigned int *npos=&fatStruct->pos; if(*npos+len > fatStruct->end) @@ -332,7 +333,7 @@ int nitroFSRead(struct _reent *r,int fd,char *ptr,int len) { return(nitroSubRead(npos,ptr,len)); } -int nitroFSSeek(struct _reent *r,int fd,int pos,int dir) { +long long int nitroFSSeek(struct _reent *r,void *fd,long long int pos,int dir) { //need check for eof here... struct nitroFSStruct *fatStruct=(struct nitroFSStruct *)fd; unsigned int *npos=&fatStruct->pos; @@ -346,7 +347,7 @@ int nitroFSSeek(struct _reent *r,int fd,int pos,int dir) { return(*npos-fatStruct->start); } -int nitroFSFstat(struct _reent *r,int fd,struct stat *st) { +int nitroFSFstat(struct _reent *r,void *fd,struct stat *st) { struct nitroFSStruct *fatStruct=(struct nitroFSStruct *)fd; st->st_size=fatStruct->end-fatStruct->start; return(0); diff --git a/source/Libraries/nitrofs.h b/source/Libraries/nitrofs.h index 630fd0c..fc33875 100644 --- a/source/Libraries/nitrofs.h +++ b/source/Libraries/nitrofs.h @@ -54,10 +54,10 @@ int nitroDirReset(struct _reent *r, DIR_ITER *dirState); int nitroFSDirNext(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st); int nitroFSDirClose(struct _reent *r, DIR_ITER *dirState); int nitroFSOpen(struct _reent *r, void *fileStruct, const char *path,int flags,int mode); -int nitroFSClose(struct _reent *r,int fd); -int nitroFSRead(struct _reent *r,int fd,char *ptr,int len); -int nitroFSSeek(struct _reent *r,int fd,int pos,int dir); -int nitroFSFstat(struct _reent *r,int fd,struct stat *st); +int nitroFSClose(struct _reent *r,void *fd); +int nitroFSRead(struct _reent *r,void *fd,char *ptr,unsigned int len); +long long int nitroFSSeek(struct _reent *r,void *fd,long long int pos,int dir); +int nitroFSFstat(struct _reent *r,void *fd,struct stat *st); int nitroFSstat(struct _reent *r,const char *file,struct stat *st); int nitroFSChdir(struct _reent *r,const char *name); #define LOADERSTR "PASS" //look for this From fd90fb874fecdc95842619e277499cf25830b468 Mon Sep 17 00:00:00 2001 From: Elisson Eric da Silva Andrade Date: Thu, 14 Nov 2024 01:56:17 +0100 Subject: [PATCH 15/22] Converter can now read format file 14 --- formart_downgrade/BinaryFileWriter.cpp | 39 +++++++++ formart_downgrade/BinaryFileWriter.hpp | 26 ++++++ formart_downgrade/Makefile | 26 ++++++ formart_downgrade/OldOsuExporter.cpp | 76 +++++++++++++++++ formart_downgrade/OldOsuExporter.hpp | 30 +++++++ formart_downgrade/TreeNode.cpp | 68 +++++++++++++++ formart_downgrade/TreeNode.hpp | 37 +++++++++ formart_downgrade/main_readfile.cpp | 24 ++++++ formart_downgrade/read_file.cpp | 109 +++++++++++++++++++++++++ formart_downgrade/read_file.h | 11 +++ 10 files changed, 446 insertions(+) create mode 100644 formart_downgrade/BinaryFileWriter.cpp create mode 100644 formart_downgrade/BinaryFileWriter.hpp create mode 100644 formart_downgrade/Makefile create mode 100644 formart_downgrade/OldOsuExporter.cpp create mode 100644 formart_downgrade/OldOsuExporter.hpp create mode 100644 formart_downgrade/TreeNode.cpp create mode 100644 formart_downgrade/TreeNode.hpp create mode 100644 formart_downgrade/main_readfile.cpp create mode 100644 formart_downgrade/read_file.cpp create mode 100644 formart_downgrade/read_file.h diff --git a/formart_downgrade/BinaryFileWriter.cpp b/formart_downgrade/BinaryFileWriter.cpp new file mode 100644 index 0000000..1268bd1 --- /dev/null +++ b/formart_downgrade/BinaryFileWriter.cpp @@ -0,0 +1,39 @@ +#include "BinaryFileWriter.hpp" +#include +#include + +// Construtor +BinaryFileWriter::BinaryFileWriter(const std::string& filePath) : filePath(filePath) {} + +// Método para definir o caminho do arquivo +void BinaryFileWriter::setFilePath(const std::string& filePath) { + this->filePath = filePath; +} + +// Método para obter o caminho atual do arquivo +std::string BinaryFileWriter::getFilePath() const { + return filePath; +} + +// Método para escrever dados binários no arquivo +bool BinaryFileWriter::write(const std::vector& data) { + // Abre o arquivo em modo binário + std::ofstream outFile(filePath, std::ios::binary); + if (!outFile) { + std::cerr << "Erro ao abrir o arquivo para escrita!" << std::endl; + return false; + } + + // Escreve os dados binários no arquivo + outFile.write(reinterpret_cast(data.data()), data.size()); + + // Verifica se a escrita foi bem-sucedida + if (!outFile.good()) { + std::cerr << "Erro ao escrever dados no arquivo!" << std::endl; + return false; + } + + // Fecha o arquivo + outFile.close(); + return true; +} diff --git a/formart_downgrade/BinaryFileWriter.hpp b/formart_downgrade/BinaryFileWriter.hpp new file mode 100644 index 0000000..b969569 --- /dev/null +++ b/formart_downgrade/BinaryFileWriter.hpp @@ -0,0 +1,26 @@ +#ifndef BINARY_FILE_WRITER_H +#define BINARY_FILE_WRITER_H + +#include +#include +#include + +class BinaryFileWriter { +public: + // Construtor que aceita o caminho do arquivo + BinaryFileWriter(const std::string& filePath); + + // Método para escrever dados binários no arquivo + bool write(const std::vector& data); + + // Método para definir o caminho do arquivo + void setFilePath(const std::string& filePath); + + // Método para obter o caminho atual do arquivo + std::string getFilePath() const; + +private: + std::string filePath; +}; + +#endif // BINARY_FILE_WRITER_H diff --git a/formart_downgrade/Makefile b/formart_downgrade/Makefile new file mode 100644 index 0000000..65161cd --- /dev/null +++ b/formart_downgrade/Makefile @@ -0,0 +1,26 @@ +# Variáveis do compilador +CC = g++ +CFLAGS = -Wall -std=c++17 +LDFLAGS = -static # Adiciona o flag para compilação estática + +# Nome do executável +TARGET = format_downgrader + +# Arquivos fonte +SOURCES = main_readfile.cpp read_file.cpp TreeNode.cpp BinaryFileWriter.cpp OldOsuExporter.cpp +# Arquivos objeto +OBJECTS = $(SOURCES:.cpp=.o) + +# Regras +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(OBJECTS) -o $(TARGET) $(LDFLAGS) + +# Regra de compilação +%.o: %.cpp + $(CC) $(CFLAGS) -c $< -o $@ + +# Limpeza +clean: + rm -f $(OBJECTS) $(TARGET) diff --git a/formart_downgrade/OldOsuExporter.cpp b/formart_downgrade/OldOsuExporter.cpp new file mode 100644 index 0000000..de54ac2 --- /dev/null +++ b/formart_downgrade/OldOsuExporter.cpp @@ -0,0 +1,76 @@ +#include "OldOsuExporter.hpp" +#include +#include + +// Construtor +OldOsuExporter::OldOsuExporter(const std::string& filePath) : filePath(filePath) {} + +// Função auxiliar para converter uma string em bytes +std::vector OldOsuExporter::stringToBytes(const std::string& str) { + std::vector bytes(str.begin(), str.end()); + bytes.push_back('\0'); // Adiciona o caractere nulo para finalizar a string + return bytes; +} + +// Função auxiliar para converter um double em bytes +std::vector OldOsuExporter::doubleToBytes(double value) { + std::vector bytes(sizeof(double)); + std::memcpy(bytes.data(), &value, sizeof(double)); + return bytes; +} + +// Função auxiliar para escrever um nó no arquivo +void OldOsuExporter::writeNode(std::ofstream& outFile, const std::shared_ptr& node) { + if (!node) return; + + // Escreve a chave + auto keyBytes = stringToBytes(node->key); + uint32_t keySize = keyBytes.size(); + outFile.write(reinterpret_cast(&keySize), sizeof(keySize)); + outFile.write(reinterpret_cast(keyBytes.data()), keySize); + + // Escreve o tipo do nó + uint32_t nodeType = static_cast(node->type); + outFile.write(reinterpret_cast(&nodeType), sizeof(nodeType)); + + // Escreve o valor do nó baseado no tipo + switch (node->type) { + case NodeType::STRING: { + auto valueBytes = stringToBytes(std::get(node->value)); + uint32_t valueSize = valueBytes.size(); + outFile.write(reinterpret_cast(&valueSize), sizeof(valueSize)); + outFile.write(reinterpret_cast(valueBytes.data()), valueSize); + break; + } + case NodeType::NUMBER: { + auto valueBytes = doubleToBytes(std::get(node->value)); + outFile.write(reinterpret_cast(valueBytes.data()), valueBytes.size()); + break; + } + case NodeType::OBJECT: + case NodeType::ARRAY: { + const auto& children = std::get>>(node->value); + uint32_t childrenCount = children.size(); + outFile.write(reinterpret_cast(&childrenCount), sizeof(childrenCount)); + + // Escreve recursivamente cada filho + for (const auto& child : children) { + writeNode(outFile, child); + } + break; + } + } +} + +// Método para exportar a árvore para um arquivo binário +bool OldOsuExporter::exportTree(const std::shared_ptr& root) { + std::ofstream outFile(filePath, std::ios::binary); + if (!outFile) { + std::cerr << "Erro ao abrir o arquivo para exportação!" << std::endl; + return false; + } + + writeNode(outFile, root); + outFile.close(); + return true; +} diff --git a/formart_downgrade/OldOsuExporter.hpp b/formart_downgrade/OldOsuExporter.hpp new file mode 100644 index 0000000..93a9a95 --- /dev/null +++ b/formart_downgrade/OldOsuExporter.hpp @@ -0,0 +1,30 @@ +#ifndef OLDOSUEXPORTER_HPP +#define OLDOSUEXPORTER_HPP + +#include "TreeNode.hpp" +#include +#include +#include + +class OldOsuExporter { +public: + // Construtor que recebe o caminho para o arquivo de exportação + OldOsuExporter(const std::string& filePath); + + // Método para exportar a árvore para um arquivo binário + bool exportTree(const std::shared_ptr& root); + +private: + std::string filePath; + + // Função auxiliar para escrever um nó + void writeNode(std::ofstream& outFile, const std::shared_ptr& node); + + // Função para converter uma string para bytes + std::vector stringToBytes(const std::string& str); + + // Função para converter um número para bytes + std::vector doubleToBytes(double value); +}; + +#endif // OLDOSUEXPORTER_HPP diff --git a/formart_downgrade/TreeNode.cpp b/formart_downgrade/TreeNode.cpp new file mode 100644 index 0000000..78590e8 --- /dev/null +++ b/formart_downgrade/TreeNode.cpp @@ -0,0 +1,68 @@ +#include "TreeNode.hpp" + +// Construtores para inicializar os diferentes tipos de nós +TreeNode::TreeNode(const std::string& k, const std::string& v) + : key(k), type(NodeType::STRING), value(v) {} + +TreeNode::TreeNode(const std::string& k, double v) + : key(k), type(NodeType::NUMBER), value(v) {} + +TreeNode::TreeNode(const std::string& k, NodeType t) + : key(k), type(t), value(std::vector>{}) {} + +// Função para adicionar um filho +void TreeNode::addChild(std::shared_ptr child) { + if (type == NodeType::OBJECT || type == NodeType::ARRAY) { + std::get>>(value).push_back(child); + } +} + +// Função recursiva para imprimir a árvore +void TreeNode::printTree(int depth) const { + std::string indent(depth * 2, ' '); + + if (!key.empty()) std::cout << indent << "\"" << key << "\": "; + + switch (type) { + case NodeType::STRING: + std::cout << "\"" << std::get(value) << "\"\n"; + break; + case NodeType::NUMBER: + std::cout << std::get(value) << "\n"; + break; + case NodeType::OBJECT: + case NodeType::ARRAY: { + std::cout << "{\n"; + for (const auto& child : std::get>>(value)) { + child->printTree(depth + 1); + } + std::cout << indent << "}\n"; + break; + } + } +} + +// Função para criar uma estrutura JSON-like de exemplo +std::shared_ptr createSampleJSON() { + auto root = std::make_shared("", NodeType::OBJECT); + + // Adicionando chave-valor (string) + root->addChild(std::make_shared("name", "John")); + + // Adicionando chave-valor (número) + root->addChild(std::make_shared("age", 30)); + + // Adicionando um array + auto hobbiesNode = std::make_shared("hobbies", NodeType::ARRAY); + hobbiesNode->addChild(std::make_shared("", "reading")); + hobbiesNode->addChild(std::make_shared("", "chess")); + root->addChild(hobbiesNode); + + // Adicionando um objeto aninhado + auto addressNode = std::make_shared("address", NodeType::OBJECT); + addressNode->addChild(std::make_shared("city", "New York")); + addressNode->addChild(std::make_shared("zip", "10001")); + root->addChild(addressNode); + + return root; +} diff --git a/formart_downgrade/TreeNode.hpp b/formart_downgrade/TreeNode.hpp new file mode 100644 index 0000000..11d3498 --- /dev/null +++ b/formart_downgrade/TreeNode.hpp @@ -0,0 +1,37 @@ +#ifndef TREENODE_HPP +#define TREENODE_HPP + +#include +#include +#include +#include +#include + +// Enum para definir o tipo do nó +enum class NodeType { STRING, NUMBER, OBJECT, ARRAY }; + +// Definições dos tipos possíveis para os nós +using NodeValue = std::variant>>; + +// Estrutura do nó da árvore +struct TreeNode { + std::string key; // Chave (opcional para arrays) + NodeType type; // Tipo do nó + NodeValue value; // Valor do nó (string, número ou vetor de filhos) + + // Construtores + TreeNode(const std::string& k, const std::string& v); + TreeNode(const std::string& k, double v); + TreeNode(const std::string& k, NodeType t); + + // Função para adicionar filhos + void addChild(std::shared_ptr child); + + // Função para exibir a árvore (recursiva) + void printTree(int depth = 0) const; +}; + +// Função para criar um exemplo de JSON-like +std::shared_ptr createSampleJSON(); + +#endif // TREENODE_HPP diff --git a/formart_downgrade/main_readfile.cpp b/formart_downgrade/main_readfile.cpp new file mode 100644 index 0000000..6901be6 --- /dev/null +++ b/formart_downgrade/main_readfile.cpp @@ -0,0 +1,24 @@ +#include "read_file.h" +#include +#include +#include +#include + +int main(int argc, char* argv[]) { + if (argc < 2) { + std::cerr << "Uso: " << argv[0] << " " << std::endl; + return 1; + } + + std::string filePath = argv[1]; + + auto root = std::make_shared("root", NodeType::OBJECT); + + // Preenche a árvore a partir do arquivo + populateTreeFromFile(filePath, root); + + std::cout << "Estrutura da árvore carregada::" << std::endl; + root->printTree(); + + return 0; +} \ No newline at end of file diff --git a/formart_downgrade/read_file.cpp b/formart_downgrade/read_file.cpp new file mode 100644 index 0000000..3cf9a37 --- /dev/null +++ b/formart_downgrade/read_file.cpp @@ -0,0 +1,109 @@ +#include "read_file.h" +#include +#include +#include + +// Função que divide a string com base no delimitador +std::vector split(const std::string &str, char delimiter) { + std::vector tokens; + std::string token; + std::istringstream tokenStream(str); + + // Utiliza std::getline para dividir a string + while (std::getline(tokenStream, token, delimiter)) { + tokens.push_back(token); + } + + return tokens; +} + +// Função utilitária para remover espaços extras +std::string trim(const std::string &str) { + if(str.empty()) + return ""; + size_t first = str.find_first_not_of(" \t"); + size_t last = str.find_last_not_of(" \t"); + return str.substr(first, (last - first + 1)); +} + +// Função para identificar o tipo de valor (número ou string) +NodeValue parseValue(const std::string &value) { + if (std::isdigit(value[0]) || (value[0] == '-' && std::isdigit(value[1]))) { + return std::stod(value); // Valor numérico + } else { + return value; // Valor string + } +} + +// Função para ler o arquivo e preencher a árvore +void populateTreeFromFile(const std::string& filename, std::shared_ptr root) { + std::ifstream file(filename); + std::string line; + + if (!file.is_open()) { + std::cerr << "Erro ao abrir o arquivo: " << filename << "\n"; + return; + } + + // Usando pilha para controlar a profundidade de objetos e arrays + std::vector> nodeStack; + nodeStack.push_back(root); + + while (std::getline(file, line)) { + line = trim(line); + if (line.find("osu file format 14") == 0) continue; // Ignora cabeçalho + + // Separar chave e valor (esperando um formato "key: value") + size_t delimiterPos = line.find(":"); + //if (delimiterPos == std::string::npos) continue; + + std::string key = delimiterPos == std::string::npos ?"":trim(line.substr(0, delimiterPos)); + std::string value = delimiterPos == std::string::npos ?"":trim(line.substr(delimiterPos + 1)); + // Identificar se é um objeto ou array + + if (line.find("[") == 0 ) {//|| line.find("//")== 0 + + // Início de um objeto + size_t endTitle = line.find("]"); + std::string title = endTitle == std::string::npos ? + line.substr(2) : + line.substr(1, endTitle-1); + auto newNode = std::make_shared(title, NodeType::OBJECT); + nodeStack.back()->addChild(newNode); + nodeStack.push_back(newNode); + } else if (line.find(",") != std::string::npos) { + // Início de um array + auto newNode = std::make_shared("", NodeType::ARRAY); + std::vector result = split(line, ','); + // Imprime os resultados + for (const auto &token : result) { + // Adicionando chave-valor + NodeValue nodeValue = parseValue(token);// Determina o tipo de nó e cria o novo nó + std::shared_ptr newArrayEntry; + if (std::holds_alternative(nodeValue)) { + newArrayEntry = std::make_shared("", std::get(nodeValue)); + } else { + newArrayEntry = std::make_shared("", std::get(nodeValue)); + } + newNode->addChild(newArrayEntry); + } + nodeStack.back()->addChild(newNode); + //nodeStack.push_back(newNode); + } else if (line.empty() && nodeStack.size() > 1) { + // Fim de um objeto ou array + nodeStack.pop_back(); + } else if (delimiterPos != std::string::npos) { + // Adicionando chave-valor + NodeValue nodeValue = parseValue(value);// Determina o tipo de nó e cria o novo nó + std::shared_ptr newNode; + if (std::holds_alternative(nodeValue)) { + newNode = std::make_shared(key, std::get(nodeValue)); + } else { + newNode = std::make_shared(key, std::get(nodeValue)); + } + nodeStack.back()->addChild(newNode); + } + } + + file.close(); +} \ No newline at end of file diff --git a/formart_downgrade/read_file.h b/formart_downgrade/read_file.h new file mode 100644 index 0000000..98e4431 --- /dev/null +++ b/formart_downgrade/read_file.h @@ -0,0 +1,11 @@ +#ifndef READ_FILE_H +#define READ_FILE_H + +#include "TreeNode.hpp" +#include +#include + +// Função para ler um arquivo e preencher a árvore +void populateTreeFromFile(const std::string& filename, std::shared_ptr root); + +#endif From cebd60883185728e21f9d959adc9e39827aa3064 Mon Sep 17 00:00:00 2001 From: Elisson Eric da Silva Andrade Date: Sun, 17 Nov 2024 00:16:40 +0100 Subject: [PATCH 16/22] Included mp3 converter, tested more formats --- formart_downgrade/Makefile | 8 +- formart_downgrade/Mp3ToRawConverter.cpp | 100 +++++++++++++ formart_downgrade/Mp3ToRawConverter.h | 34 +++++ formart_downgrade/OldOsuExporter.cpp | 177 +++++++++++++++++++++++- formart_downgrade/OldOsuExporter.hpp | 13 ++ formart_downgrade/TreeNode.cpp | 52 ++++++- formart_downgrade/TreeNode.hpp | 9 +- formart_downgrade/main_readfile.cpp | 41 +++++- formart_downgrade/read_file.cpp | 22 ++- 9 files changed, 440 insertions(+), 16 deletions(-) create mode 100644 formart_downgrade/Mp3ToRawConverter.cpp create mode 100644 formart_downgrade/Mp3ToRawConverter.h diff --git a/formart_downgrade/Makefile b/formart_downgrade/Makefile index 65161cd..c6c0ea1 100644 --- a/formart_downgrade/Makefile +++ b/formart_downgrade/Makefile @@ -1,13 +1,15 @@ # Variáveis do compilador CC = g++ CFLAGS = -Wall -std=c++17 +LIBS = -L/mingw64/lib -lmpg123 -lsamplerate -lshlwapi LDFLAGS = -static # Adiciona o flag para compilação estática +INCLUDE = -I/mingw64/include # Nome do executável TARGET = format_downgrader # Arquivos fonte -SOURCES = main_readfile.cpp read_file.cpp TreeNode.cpp BinaryFileWriter.cpp OldOsuExporter.cpp +SOURCES = main_readfile.cpp read_file.cpp TreeNode.cpp BinaryFileWriter.cpp OldOsuExporter.cpp Mp3ToRawConverter.cpp # Arquivos objeto OBJECTS = $(SOURCES:.cpp=.o) @@ -15,11 +17,11 @@ OBJECTS = $(SOURCES:.cpp=.o) all: $(TARGET) $(TARGET): $(OBJECTS) - $(CC) $(OBJECTS) -o $(TARGET) $(LDFLAGS) + $(CC) $(OBJECTS) -o $(TARGET) $(LDFLAGS) $(LIBS) # Regra de compilação %.o: %.cpp - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -c $< -o $@ $(INCLUDE) # Limpeza clean: diff --git a/formart_downgrade/Mp3ToRawConverter.cpp b/formart_downgrade/Mp3ToRawConverter.cpp new file mode 100644 index 0000000..e922d28 --- /dev/null +++ b/formart_downgrade/Mp3ToRawConverter.cpp @@ -0,0 +1,100 @@ +#include "Mp3ToRawConverter.h" +#include +#include +#include +#include +#include +#include +#include + +Mp3ToRawConverter::Mp3ToRawConverter() { + mpgHandle = nullptr; + initializeDecoder(); +} + +Mp3ToRawConverter::~Mp3ToRawConverter() { + cleanupDecoder(); +} + +bool Mp3ToRawConverter::initializeDecoder() { + if (mpg123_init() != MPG123_OK) { + std::cerr << "Erro ao inicializar a biblioteca mpg123!" << std::endl; + return false; + } + mpgHandle = mpg123_new(nullptr, nullptr); + if (!mpgHandle) { + std::cerr << "Erro ao criar o manipulador mpg123!" << std::endl; + return false; + } + mpg123_param(mpgHandle, MPG123_ADD_FLAGS, MPG123_FORCE_MONO, 0); + return true; +} + +void Mp3ToRawConverter::cleanupDecoder() { + if (mpgHandle) { + mpg123_close(mpgHandle); + mpg123_delete(mpgHandle); + mpg123_exit(); + } +} + +int8_t Mp3ToRawConverter::convertTo8BitSigned(float sample) { + sample = std::clamp(sample, -1.0f, 1.0f); + return static_cast(std::round(sample * 127)); +} + +bool Mp3ToRawConverter::convert(const std::string& inputFilePath, const std::string& outputFilePath) { + if (mpg123_open(mpgHandle, inputFilePath.c_str()) != MPG123_OK) { + std::cerr << "Falha ao abrir o arquivo de entrada: " << inputFilePath << std::endl; + return false; + } + + if (mpg123_getformat(mpgHandle, &sampleRate, &channels, &encoding) != MPG123_OK) { + std::cerr << "Falha ao obter formato de áudio!" << std::endl; + return false; + } + + std::vector buffer(4096); + std::vector samples; + std::ofstream outputFile(outputFilePath, std::ios::binary); + size_t bytesRead; + int error; + + SRC_STATE* srcState = src_new(SRC_SINC_FASTEST, channels, &error); + if (!srcState) { + std::cerr << "Erro ao inicializar o conversor de taxa de amostragem!" << std::endl; + return false; + } + + SRC_DATA srcData = {}; + std::vector srcBuffer(4096); + + while (mpg123_read(mpgHandle, buffer.data(), buffer.size(), &bytesRead) == MPG123_OK) { + for (size_t i = 0; i < bytesRead; i += channels * 2) { + int16_t sample = (buffer[i + 1] << 8) | buffer[i]; + samples.push_back(static_cast(sample) / 32768.0f); + } + + srcData.data_in = samples.data(); + srcData.input_frames = samples.size() / channels; + srcData.data_out = srcBuffer.data(); + srcData.output_frames = srcBuffer.size() / channels; + srcData.src_ratio = static_cast(targetSampleRate) / sampleRate; + + if (src_process(srcState, &srcData) != 0) { + std::cerr << "Erro durante a conversão de taxa de amostragem!" << std::endl; + return false; + } + + for (int i = 0; i < srcData.output_frames_gen; ++i) { + int8_t outSample = convertTo8BitSigned(srcBuffer[i]); + outputFile.write(reinterpret_cast(&outSample), sizeof(int8_t)); + } + + samples.clear(); + } + + src_delete(srcState); + outputFile.close(); + return true; +} diff --git a/formart_downgrade/Mp3ToRawConverter.h b/formart_downgrade/Mp3ToRawConverter.h new file mode 100644 index 0000000..61ae031 --- /dev/null +++ b/formart_downgrade/Mp3ToRawConverter.h @@ -0,0 +1,34 @@ +#ifndef MP3_TO_RAW_CONVERTER_H +#define MP3_TO_RAW_CONVERTER_H + +#include +#include +#include + +class Mp3ToRawConverter { +public: + Mp3ToRawConverter(); + ~Mp3ToRawConverter(); + + // Método para converter MP3 para RAW + bool convert(const std::string& inputFilePath, const std::string& outputFilePath); + +private: + // Inicializar e limpar o decodificador mpg123 + bool initializeDecoder(); + void cleanupDecoder(); + + // Conversão de amostra para 8-bit signed + int8_t convertTo8BitSigned(float sample); + + // Manipulador do mpg123 + mpg123_handle *mpgHandle; + int channels, encoding; + long sampleRate; + + // Definições de taxa de amostragem + static constexpr int targetSampleRate = 22050; + static constexpr int targetChannels = 1; // Mono +}; + +#endif // MP3_TO_RAW_CONVERTER_H diff --git a/formart_downgrade/OldOsuExporter.cpp b/formart_downgrade/OldOsuExporter.cpp index de54ac2..1e4f6b2 100644 --- a/formart_downgrade/OldOsuExporter.cpp +++ b/formart_downgrade/OldOsuExporter.cpp @@ -1,6 +1,7 @@ #include "OldOsuExporter.hpp" #include #include +#include // Construtor OldOsuExporter::OldOsuExporter(const std::string& filePath) : filePath(filePath) {} @@ -8,7 +9,7 @@ OldOsuExporter::OldOsuExporter(const std::string& filePath) : filePath(filePath) // Função auxiliar para converter uma string em bytes std::vector OldOsuExporter::stringToBytes(const std::string& str) { std::vector bytes(str.begin(), str.end()); - bytes.push_back('\0'); // Adiciona o caractere nulo para finalizar a string + //bytes.push_back('\0'); // Adiciona o caractere nulo para finalizar a string return bytes; } @@ -19,6 +20,50 @@ std::vector OldOsuExporter::doubleToBytes(double value) { return bytes; } +std::string OldOsuExporter::changeExtensionTo(const std::string& filename,const std::string& extension) { + // Encontrar a posição do último ponto na string + size_t dotPosition = filename.find_last_of("."); + + // Se houver um ponto, corta a extensão existente, caso contrário, usa o nome inteiro + std::string baseName = (dotPosition != std::string::npos) + ? filename.substr(0, dotPosition) + : filename; + + // Adiciona a nova extensão ".ods" + return baseName + "."+ extension; +} + +void OldOsuExporter::WriteVarLength(std::ofstream& outFile, int length) { + unsigned char temp = static_cast(length & 0x7F); + + // Continua enquanto o comprimento for maior que 0 após o desvio de 7 bits + while ((length >>= 7) > 0) { + temp |= 0x80; // Marca o byte como parte de uma sequência + outFile.write(reinterpret_cast(&temp), sizeof(temp)); + temp = static_cast(length & 0x7F); + } + + // Escreve o último byte + outFile.write(reinterpret_cast(&temp), sizeof(temp)); +} + + +void OldOsuExporter::WriteVarString(std::ofstream& outFile, const std::string& str){ + auto strData = stringToBytes(str); + int strSize = strData.size(); + if(strSize>0){ + WriteVarLength(outFile,strSize); + outFile.write(reinterpret_cast(strData.data()), strSize); + } else {//osuDS crashes with empty strings + const std::string space = " "; + auto strSpace = stringToBytes(space); + int spaceSize = strSpace.size(); + WriteVarLength(outFile,spaceSize); + outFile.write(reinterpret_cast(strSpace.data()), spaceSize); + + } +} + // Função auxiliar para escrever um nó no arquivo void OldOsuExporter::writeNode(std::ofstream& outFile, const std::shared_ptr& node) { if (!node) return; @@ -62,6 +107,134 @@ void OldOsuExporter::writeNode(std::ofstream& outFile, const std::shared_ptr& node) { + if (!node) return; + + auto formatHeader = stringToBytes("ODS"); + outFile.write(reinterpret_cast(formatHeader.data()), formatHeader.size()); + + outFile.write(reinterpret_cast(&VERSION_ODS), sizeof(VERSION_ODS)); + auto meta = node->getChild("Metadata"); + auto title = meta->getChild("TitleUnicode"); + if(title.use_count() == 0){ + title = meta->getChild("Title"); + } + std::string strTitle = std::get(title->value); + WriteVarString(outFile, strTitle); + + auto artist = meta->getChild("ArtistUnicode"); + if(artist.use_count() == 0){ + artist = meta->getChild("Artist"); + } + std::string strArtist = std::get(artist->value); + WriteVarString(outFile, strArtist); + + auto creator = meta->getChild("Creator"); + std::string strCreator = std::get(creator->value); + WriteVarString(outFile, strCreator); + + auto version = meta->getChild("Version"); + std::string strVersion = std::get(version->value); + WriteVarString(outFile, strVersion); + + auto general = node->getChild("General"); + auto audioFile = general->getChild("AudioFilename"); + std::string strAudioFile = std::get(audioFile->value); + strAudioFile.erase(0, strAudioFile.find_first_not_of(' ')); + + WriteVarString(outFile, OldOsuExporter::changeExtensionTo(strAudioFile,"raw")); + + std::cout << "Reached here" <getChild("Difficulty"); + + const uint8_t hpDrain = std::round(std::get(difficulty->getChild("HPDrainRate")->value)); + outFile.write(reinterpret_cast(&hpDrain), sizeof(hpDrain)); + const uint8_t circleSize = std::round(std::get(difficulty->getChild("CircleSize")->value)); + outFile.write(reinterpret_cast(&hpDrain), sizeof(circleSize)); + const uint8_t diffOverall = std::round(std::get(difficulty->getChild("OverallDifficulty")->value)); + outFile.write(reinterpret_cast(&hpDrain), sizeof(diffOverall)); + + const float sliderMulti = std::get(difficulty->getChild("SliderMultiplier")->value); + outFile.write(reinterpret_cast(&sliderMulti), sizeof(sliderMulti)); + const float sliderTick = std::get(difficulty->getChild("SliderTickRate")->value); + outFile.write(reinterpret_cast(&sliderTick), sizeof(sliderTick)); + const float hpDrop = 5.0; + outFile.write(reinterpret_cast(&hpDrop), sizeof(hpDrop)); + const uint8_t peppyStars = 5; + outFile.write(reinterpret_cast(&peppyStars), sizeof(peppyStars)); + const float eyupStars = 5.0; + outFile.write(reinterpret_cast(&eyupStars), sizeof(eyupStars)); + + std::cout << "Reached after difficulties" <>>(node->getChild("TimingPoints")->value); + int tpCount = timingPoints.size(); + WriteVarLength(outFile,tpCount); + + std::cout << "Reached here" <( + std::get>>(timingPoints.at("0")->value).at(1)->value); + for (int i=0; i>>(timingPoints.at(strIndex)->value); + const int offset = std::get(tpProperties.at(0)->value); + outFile.write(reinterpret_cast(&offset), sizeof(offset)); + const float beatLength = std::get(tpProperties.at(1)->value); + if(beatLength > 0){ + outFile.write(reinterpret_cast(&beatLength), sizeof(beatLength)); + realBeatLength = beatLength; + }else { + const float inheritedLength = realBeatLength*(-100/beatLength); + outFile.write(reinterpret_cast(&inheritedLength), sizeof(inheritedLength)); + } + const uint8_t sampleSet = std::get(tpProperties.at(3)->value); + outFile.write(reinterpret_cast(&sampleSet), sizeof(sampleSet)); + } + + + const auto& eventsBreaks = std::get>>(node->getChild("Events")->value); + int eventsCount = eventsBreaks.size(); + WriteVarLength(outFile,eventsCount); + + std::cout << "Reached after timings" <>>(eventsBreaks.at(strIndex)->value); + const int startTime = std::get(ebProperties.at(0)->value); + outFile.write(reinterpret_cast(&startTime), sizeof(startTime)); + const int endTime = std::get(ebProperties.at(1)->value); + outFile.write(reinterpret_cast(&endTime), sizeof(endTime)); + } + + + const auto& hitObjects = std::get>>(node->getChild("HitObjects")->value); + int hitObjectsCount = hitObjects.size(); + WriteVarLength(outFile,hitObjectsCount); + + std::cout << "Reached after events" <>>(hitObjects.at(strIndex)->value); + const int startTime = std::get(hoProperties.at(2)->value); + outFile.write(reinterpret_cast(&startTime), sizeof(startTime)); + const uint8_t hoType = std::get(hoProperties.at(3)->value); + outFile.write(reinterpret_cast(&hoType), sizeof(hoType)); + const short xOsu = std::get(hoProperties.at(0)->value); + outFile.write(reinterpret_cast(&xOsu), sizeof(xOsu)); + const short yOsu = std::get(hoProperties.at(1)->value); + outFile.write(reinterpret_cast(&yOsu), sizeof(yOsu)); + const uint8_t sound = std::get(hoProperties.at(4)->value); + outFile.write(reinterpret_cast(&sound), sizeof(sound)); + if(hoType == 3){//spinners + const int endTime = std::get(hoProperties.at(5)->value); + outFile.write(reinterpret_cast(&endTime), sizeof(endTime)); + } + } + + +} // Método para exportar a árvore para um arquivo binário bool OldOsuExporter::exportTree(const std::shared_ptr& root) { std::ofstream outFile(filePath, std::ios::binary); @@ -70,7 +243,7 @@ bool OldOsuExporter::exportTree(const std::shared_ptr& root) { return false; } - writeNode(outFile, root); + writeOldOsu(outFile, root); outFile.close(); return true; } diff --git a/formart_downgrade/OldOsuExporter.hpp b/formart_downgrade/OldOsuExporter.hpp index 93a9a95..921e889 100644 --- a/formart_downgrade/OldOsuExporter.hpp +++ b/formart_downgrade/OldOsuExporter.hpp @@ -10,21 +10,34 @@ class OldOsuExporter { public: // Construtor que recebe o caminho para o arquivo de exportação OldOsuExporter(const std::string& filePath); + + // Função para trocar a extensão de um arquivo + static std::string changeExtensionTo(const std::string& filename,const std::string& extension); // Método para exportar a árvore para um arquivo binário bool exportTree(const std::shared_ptr& root); private: + int DEGRESS_IN_CIRCLE = 32768; + uint8_t VERSION_ODS = 1; + std::string filePath; // Função auxiliar para escrever um nó void writeNode(std::ofstream& outFile, const std::shared_ptr& node); + + // Função auxiliar para escrever um nó + void writeOldOsu(std::ofstream& outFile, const std::shared_ptr& node); // Função para converter uma string para bytes std::vector stringToBytes(const std::string& str); // Função para converter um número para bytes std::vector doubleToBytes(double value); + + void WriteVarLength(std::ofstream& outFile, int length); + + void WriteVarString(std::ofstream& outFile, const std::string& str); }; #endif // OLDOSUEXPORTER_HPP diff --git a/formart_downgrade/TreeNode.cpp b/formart_downgrade/TreeNode.cpp index 78590e8..c661dfd 100644 --- a/formart_downgrade/TreeNode.cpp +++ b/formart_downgrade/TreeNode.cpp @@ -8,15 +8,50 @@ TreeNode::TreeNode(const std::string& k, double v) : key(k), type(NodeType::NUMBER), value(v) {} TreeNode::TreeNode(const std::string& k, NodeType t) - : key(k), type(t), value(std::vector>{}) {} + : key(k), type(t){ + + if (type == NodeType::OBJECT) { + value = std::unordered_map>{}; + } else if (type == NodeType::ARRAY) { + value = std::vector>{}; + } else if (type == NodeType::STRING) { + value = std::string{}; // Ou um valor padrão para String + } else if (type == NodeType::NUMBER) { + value = 0.0; // Ou um valor padrão para Número + } +} // Função para adicionar um filho void TreeNode::addChild(std::shared_ptr child) { - if (type == NodeType::OBJECT || type == NodeType::ARRAY) { + if (type == NodeType::OBJECT) { + std::get>>(value)[child->key] = child; + } else if (type == NodeType::ARRAY) { std::get>>(value).push_back(child); } } +// Função para acessar um filho por chave (somente para objetos) +std::shared_ptr TreeNode::getChild(const std::string& key) { + if (type == NodeType::OBJECT) { + auto& children = std::get>>(value); + if (children.find(key) != children.end()) { + return children[key]; + } + } + return nullptr; +} + +// Função para acessar um filho por índice (somente para arrays) +std::shared_ptr TreeNode::getChildAt(size_t index) { + if (type == NodeType::ARRAY) { + auto& children = std::get>>(value); + if (index < children.size()) { + return children[index]; + } + } + return nullptr; +} + // Função recursiva para imprimir a árvore void TreeNode::printTree(int depth) const { std::string indent(depth * 2, ' '); @@ -30,13 +65,20 @@ void TreeNode::printTree(int depth) const { case NodeType::NUMBER: std::cout << std::get(value) << "\n"; break; - case NodeType::OBJECT: - case NodeType::ARRAY: { + case NodeType::OBJECT: { std::cout << "{\n"; + for (const auto& child : std::get>>(value)) { + child.second->printTree(depth + 1); + } + std::cout << indent << "}\n"; + break; + } + case NodeType::ARRAY: { + std::cout << "[\n"; for (const auto& child : std::get>>(value)) { child->printTree(depth + 1); } - std::cout << indent << "}\n"; + std::cout << indent << "]\n"; break; } } diff --git a/formart_downgrade/TreeNode.hpp b/formart_downgrade/TreeNode.hpp index 11d3498..1fb8b9c 100644 --- a/formart_downgrade/TreeNode.hpp +++ b/formart_downgrade/TreeNode.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -11,13 +12,13 @@ enum class NodeType { STRING, NUMBER, OBJECT, ARRAY }; // Definições dos tipos possíveis para os nós -using NodeValue = std::variant>>; +using NodeValue = std::variant>, std::vector>>; // Estrutura do nó da árvore struct TreeNode { std::string key; // Chave (opcional para arrays) NodeType type; // Tipo do nó - NodeValue value; // Valor do nó (string, número ou vetor de filhos) + NodeValue value; // Valor do nó (string, número, mapa de filhos ou vetor de filhos) // Construtores TreeNode(const std::string& k, const std::string& v); @@ -27,6 +28,10 @@ struct TreeNode { // Função para adicionar filhos void addChild(std::shared_ptr child); + // Função para acessar filhos + std::shared_ptr getChild(const std::string& key); + std::shared_ptr getChildAt(size_t index); + // Função para exibir a árvore (recursiva) void printTree(int depth = 0) const; }; diff --git a/formart_downgrade/main_readfile.cpp b/formart_downgrade/main_readfile.cpp index 6901be6..c9f5631 100644 --- a/formart_downgrade/main_readfile.cpp +++ b/formart_downgrade/main_readfile.cpp @@ -1,9 +1,27 @@ #include "read_file.h" +#include "OldOsuExporter.hpp" +#include "Mp3ToRawConverter.h" #include #include #include #include + +// Função para substituir o nome do arquivo em um caminho absoluto +std::string substituirNomeArquivo(const std::string& caminhoCompleto, const std::string& novoNome) { + // Encontrar a última ocorrência de '/' ou '\\' para determinar onde começa o nome do arquivo + size_t pos = caminhoCompleto.find_last_of("/\\"); + + // Se a posição não for encontrada, retornar o caminho sem alteração + if (pos == std::string::npos) { + return caminhoCompleto; + } + + // Criar o novo caminho com o nome substituído + std::string novoCaminho = caminhoCompleto.substr(0, pos + 1) + novoNome; + return novoCaminho; +} + int main(int argc, char* argv[]) { if (argc < 2) { std::cerr << "Uso: " << argv[0] << " " << std::endl; @@ -16,9 +34,28 @@ int main(int argc, char* argv[]) { // Preenche a árvore a partir do arquivo populateTreeFromFile(filePath, root); - - std::cout << "Estrutura da árvore carregada::" << std::endl; + + std::cout << "Estrutura da árvore carregada:" << std::endl; root->printTree(); + OldOsuExporter exporter(OldOsuExporter::changeExtensionTo(filePath,"ods")); + + exporter.exportTree(root); + + Mp3ToRawConverter converter; + auto general = root->getChild("General"); + auto audioFile = general->getChild("AudioFilename"); + std::string strAudioFile = std::get(audioFile->value); + + strAudioFile.erase(0, strAudioFile.find_first_not_of(' ')); + std::string inputPath = substituirNomeArquivo(filePath,strAudioFile); + std::string outputPath = OldOsuExporter::changeExtensionTo(inputPath,"raw"); + + if (converter.convert(inputPath, outputPath)) { + std::cout << "Arquivo convertido com sucesso!" << std::endl; + } else { + std::cerr << "Falha na conversão do arquivo." << std::endl; + } + return 0; } \ No newline at end of file diff --git a/formart_downgrade/read_file.cpp b/formart_downgrade/read_file.cpp index 3cf9a37..3cfb366 100644 --- a/formart_downgrade/read_file.cpp +++ b/formart_downgrade/read_file.cpp @@ -2,6 +2,7 @@ #include #include #include +#include // Função que divide a string com base no delimitador std::vector split(const std::string &str, char delimiter) { @@ -51,7 +52,7 @@ void populateTreeFromFile(const std::string& filename, std::shared_ptr while (std::getline(file, line)) { line = trim(line); - if (line.find("osu file format 14") == 0) continue; // Ignora cabeçalho + if (line.find("osu file format ") == 0) continue; // Ignora cabeçalho // Separar chave e valor (esperando um formato "key: value") size_t delimiterPos = line.find(":"); @@ -73,7 +74,24 @@ void populateTreeFromFile(const std::string& filename, std::shared_ptr nodeStack.push_back(newNode); } else if (line.find(",") != std::string::npos) { // Início de um array - auto newNode = std::make_shared("", NodeType::ARRAY); + std::string properKey = "0"; + if((nodeStack.back()->type) == NodeType::OBJECT){ + auto parentMap = std::get>>(nodeStack.back()->value); + if(parentMap.size()>0){ + std::vector keys; + for (const auto& pair : parentMap) { + keys.push_back(std::stoi(pair.first)); + } + + // Ordenar as chaves de forma alfabética + std::sort(keys.begin(), keys.end()); + + // A última chave será a última no vetor ordenado + int lastKey = keys.back(); + properKey = std::to_string(lastKey +1); + } + } + auto newNode = std::make_shared(properKey, NodeType::ARRAY); std::vector result = split(line, ','); // Imprime os resultados for (const auto &token : result) { From 3bdcd4fa1d7230fd07a46f505270ee6d31b3bc24 Mon Sep 17 00:00:00 2001 From: Elisson Eric da Silva Andrade Date: Sun, 17 Nov 2024 01:54:10 +0100 Subject: [PATCH 17/22] Fixed events other than break being added --- formart_downgrade/OldOsuExporter.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/formart_downgrade/OldOsuExporter.cpp b/formart_downgrade/OldOsuExporter.cpp index 1e4f6b2..eee4c9f 100644 --- a/formart_downgrade/OldOsuExporter.cpp +++ b/formart_downgrade/OldOsuExporter.cpp @@ -194,20 +194,29 @@ void OldOsuExporter::writeOldOsu(std::ofstream& outFile, const std::shared_ptr>>(node->getChild("Events")->value); - int eventsCount = eventsBreaks.size(); - WriteVarLength(outFile,eventsCount); + const auto& events = std::get>>(node->getChild("Events")->value); + int eventsCount = events.size(); std::cout << "Reached after timings" <>> eventsBreaks; for (int i=0; i>>(eventsBreaks.at(strIndex)->value); - const int startTime = std::get(ebProperties.at(0)->value); + const auto& ebProperties = std::get>>(events.at(strIndex)->value); + if((ebProperties.at(0)->type == NodeType::STRING && std::get(ebProperties.at(0)->value).compare("Break") == 0) || + (ebProperties.at(0)->type == NodeType::NUMBER && std::get(ebProperties.at(0)->value) == 2)){ + eventsBreaks.push_back(ebProperties); + } + } + + WriteVarLength(outFile,eventsBreaks.size()); + + for(const std::vector> &ebProperties : eventsBreaks) { + const int startTime = std::get(ebProperties.at(1)->value); outFile.write(reinterpret_cast(&startTime), sizeof(startTime)); - const int endTime = std::get(ebProperties.at(1)->value); + const int endTime = std::get(ebProperties.at(2)->value); outFile.write(reinterpret_cast(&endTime), sizeof(endTime)); } - const auto& hitObjects = std::get>>(node->getChild("HitObjects")->value); int hitObjectsCount = hitObjects.size(); From 1398fa1465852ed3fbe50f69cc01b6ff30d8174e Mon Sep 17 00:00:00 2001 From: Elisson Eric da Silva Andrade Date: Tue, 19 Nov 2024 03:51:51 +0100 Subject: [PATCH 18/22] Included linear slides to conversion --- formart_downgrade/OldOsuExporter.cpp | 191 ++++++++++++++++++++++++++- formart_downgrade/OldOsuExporter.hpp | 17 +++ formart_downgrade/read_file.cpp | 10 +- 3 files changed, 213 insertions(+), 5 deletions(-) diff --git a/formart_downgrade/OldOsuExporter.cpp b/formart_downgrade/OldOsuExporter.cpp index eee4c9f..d83cb23 100644 --- a/formart_downgrade/OldOsuExporter.cpp +++ b/formart_downgrade/OldOsuExporter.cpp @@ -1,6 +1,7 @@ #include "OldOsuExporter.hpp" #include #include +#include #include // Construtor @@ -33,6 +34,128 @@ std::string OldOsuExporter::changeExtensionTo(const std::string& filename,const return baseName + "."+ extension; } +std::vector> OldOsuExporter::parseNumberPairs(const std::string& input) { + std::vector> pairs; + + // Pular a primeira letra (X|) e começar a partir do índice 2 + std::string data = input.substr(2); + + std::stringstream ss(data); + std::string pair; + + // Separar a string pelos '|' + while (std::getline(ss, pair, '|')) { + // Encontrar o separador ':' + size_t pos = pair.find(':'); + if (pos != std::string::npos) { + // Extrair e converter x e y para inteiros + int x = std::stoi(pair.substr(0, pos)); + int y = std::stoi(pair.substr(pos + 1)); + pairs.emplace_back(x, y); + } + } + + return pairs; +} + +std::vector> OldOsuExporter::createSlider(const std::vector>& points) { + std::vector> segments; + + // Criar segmentos ligando pontos sucessivos + + const double threshold = 10; + segments.push_back(points[0]); + double total=0; + for (size_t i = 1; i < points.size(); ) { + double distance = this->calcularDistancia(segments.back(),points[i]); + if(total <= threshold ){ + total += distance; + } + if(total > threshold){ + float factor = (float)((distance+threshold-total)/distance); + segments.push_back(this->lerp(segments.back(), points[i],factor)); + total -= threshold; + } + if (((int)this->calcularDistancia(segments.back(),points[i])) <= threshold){ + i++; + } + } + if(((int)this->calcularDistancia(segments.back(),points[points.size()-1])) >0) { + segments.push_back(points[points.size()-1]); + } + + return segments; +} + +std::vector> OldOsuExporter::createTicks(const std::vector>& points, const float spatialLength, const float difficultyMultiplier, const float sliderTick) { + std::vector> ticks; + + int length = (int) (100.0*difficultyMultiplier)/sliderTick; + int maxPoints = (((int)spatialLength) -1)/length; + + double total = 0; + std::cout << "Generatin ticks for " <calcularDistancia(points[i], points[i + 1]); + std::cout << "Creating tick for " <= length){ + ticks.push_back(points[i + 1]); + total -= length; + } + } + return ticks; +} + +float OldOsuExporter::calcularDistancia(const std::pair& p1, const std::pair& p2) { + return std::sqrt(std::pow(p2.first - p1.first, 2) + std::pow(p2.second - p1.second, 2)); +} + +std::pair OldOsuExporter::lerp(const std::pair& a, const std::pair& b, float amount) { + std::pair v; + v.first = (short) (a.first + (b.first - a.first)*amount); + v.second = (short) (a.second + (b.second - a.second)*amount); + std::cout << "Estimated point (" <& node, const int startTime, const float spatialLength, const float difficultyMultiplier){ + + const auto& timingPoints = std::get>>(node->getChild("TimingPoints")->value); + int tpCount = timingPoints.size(); + // Escreve primeiro timing point + double realBeatLength = std::get( + std::get>>(timingPoints.at("0")->value).at(1)->value); + int currentTime = 0; + double inheritedLength = -1; + for (int i=0; i>>(timingPoints.at(strIndex)->value); + const int offset = std::get(tpProperties.at(0)->value); + currentTime += offset; + if(currentTime > startTime){ + break; + } + const float beatLength = std::get(tpProperties.at(1)->value); + if(beatLength > 0){ + realBeatLength = beatLength; + inheritedLength = -1; + }else { + inheritedLength = realBeatLength*(-100/beatLength); + } + + } + + if(inheritedLength < 0){ + inheritedLength = realBeatLength; + } + + return (int) inheritedLength*spatialLength/(100*difficultyMultiplier); +} + +int OldOsuExporter::calculateAngle(const std::pair& a, const std::pair& b){ + return (int)(DEGRESS_IN_CIRCLE*atan2(b.second - a.second, b.first - a.first)/(2*PI)); +} + void OldOsuExporter::WriteVarLength(std::ofstream& outFile, int length) { unsigned char temp = static_cast(length & 0x7F); @@ -115,6 +238,7 @@ void OldOsuExporter::writeOldOsu(std::ofstream& outFile, const std::shared_ptr(&VERSION_ODS), sizeof(VERSION_ODS)); auto meta = node->getChild("Metadata"); + std::cout << "Reading metadata" <getChild("TitleUnicode"); if(title.use_count() == 0){ title = meta->getChild("Title"); @@ -138,13 +262,14 @@ void OldOsuExporter::writeOldOsu(std::ofstream& outFile, const std::shared_ptrgetChild("General"); + std::cout << "Reading filename" <getChild("AudioFilename"); std::string strAudioFile = std::get(audioFile->value); strAudioFile.erase(0, strAudioFile.find_first_not_of(' ')); WriteVarString(outFile, OldOsuExporter::changeExtensionTo(strAudioFile,"raw")); - std::cout << "Reached here" <getChild("Difficulty"); @@ -236,9 +361,71 @@ void OldOsuExporter::writeOldOsu(std::ofstream& outFile, const std::shared_ptr(&yOsu), sizeof(yOsu)); const uint8_t sound = std::get(hoProperties.at(4)->value); outFile.write(reinterpret_cast(&sound), sizeof(sound)); - if(hoType == 3){//spinners + const uint8_t spinnerMask = 1<<3; + const uint8_t sliderMask = 1<<1; + + if((spinnerMask & hoType) != 0){//spinners + std::cout << "Found spinner on " <(hoProperties.at(5)->value); outFile.write(reinterpret_cast(&endTime), sizeof(endTime)); + } else if((sliderMask & hoType) != 0){//sliders + std::cout << "Found slider on " <(hoProperties.at(6)->value); + outFile.write(reinterpret_cast(&repeats), sizeof(repeats)); + + const float spatialLength = std::get(hoProperties.at(7)->value); + const int travelSpeed = calculateTravelSpeed(node,startTime,spatialLength,sliderMulti); + outFile.write(reinterpret_cast(&travelSpeed), sizeof(travelSpeed)); + + std::cout << "Calculate travel speed of " <(hoProperties.at(5)->value); + // Obter os pares de números + std::vector> points = this->parseNumberPairs(strPoints); + points.insert(points.begin(),std::pair(xOsu,yOsu)); + + // Criar segmentos + auto segments = this->createSlider(points); + const short segmentCount = segments.size() -1; + + std::cout << "Created segment vetor of size " <(&xLocal),sizeof(short)); + outFile.write(reinterpret_cast(&yLocal),sizeof(short)); + + if (i < segmentCount){ + angle = this->calculateAngle(segments[i], segments[i + 1]); + } + outFile.write(reinterpret_cast(&angle),sizeof(int)); + + std::cout << "On point (" <createTicks(segments,spatialLength,sliderMulti,sliderTick); + + size_t ticksCount = ticks.size(); + + std::cout << "Created tick vetor of size " <(&xLocal),sizeof(short)); + outFile.write(reinterpret_cast(&yLocal),sizeof(short)); + + + } } } diff --git a/formart_downgrade/OldOsuExporter.hpp b/formart_downgrade/OldOsuExporter.hpp index 921e889..84eb309 100644 --- a/formart_downgrade/OldOsuExporter.hpp +++ b/formart_downgrade/OldOsuExporter.hpp @@ -5,6 +5,7 @@ #include #include #include +#include class OldOsuExporter { public: @@ -21,6 +22,8 @@ class OldOsuExporter { int DEGRESS_IN_CIRCLE = 32768; uint8_t VERSION_ODS = 1; + const double PI = 3.141592653589793; + std::string filePath; // Função auxiliar para escrever um nó @@ -35,6 +38,20 @@ class OldOsuExporter { // Função para converter um número para bytes std::vector doubleToBytes(double value); + std::vector> parseNumberPairs(const std::string& input); + + std::vector> createSlider(const std::vector>& points); + + std::vector> createTicks(const std::vector>& points,const float spatialLength, const float difficultyMultiplier, const float sliderTick); + + float calcularDistancia(const std::pair& p1, const std::pair& p2); + + int calculateTravelSpeed(const std::shared_ptr& node,const int startTime,const float spatialLength, const float difficultyMultiplier); + + int calculateAngle(const std::pair& a, const std::pair& b); + + std::pair lerp(const std::pair& a, const std::pair& b, float amount); + void WriteVarLength(std::ofstream& outFile, int length); void WriteVarString(std::ofstream& outFile, const std::string& str); diff --git a/formart_downgrade/read_file.cpp b/formart_downgrade/read_file.cpp index 3cfb366..785f5ad 100644 --- a/formart_downgrade/read_file.cpp +++ b/formart_downgrade/read_file.cpp @@ -3,6 +3,7 @@ #include #include #include +#include // Função que divide a string com base no delimitador std::vector split(const std::string &str, char delimiter) { @@ -29,7 +30,8 @@ std::string trim(const std::string &str) { // Função para identificar o tipo de valor (número ou string) NodeValue parseValue(const std::string &value) { - if (std::isdigit(value[0]) || (value[0] == '-' && std::isdigit(value[1]))) { + std::regex pattern(R"(^\s*[-+]?\d*\.?\d+\s*$)"); + if (std::regex_match(value, pattern)) { return std::stod(value); // Valor numérico } else { return value; // Valor string @@ -108,8 +110,10 @@ void populateTreeFromFile(const std::string& filename, std::shared_ptr nodeStack.back()->addChild(newNode); //nodeStack.push_back(newNode); } else if (line.empty() && nodeStack.size() > 1) { - // Fim de um objeto ou array - nodeStack.pop_back(); + if(nodeStack.back()->type == NodeType::OBJECT){ + // Fim de um objeto ou array + nodeStack.pop_back(); + } } else if (delimiterPos != std::string::npos) { // Adicionando chave-valor NodeValue nodeValue = parseValue(value);// Determina o tipo de nó e cria o novo nó From fa75ec15a397c143b8307cc8b097756bee39a63b Mon Sep 17 00:00:00 2001 From: Elisson Eric da Silva Andrade Date: Tue, 19 Nov 2024 05:12:30 +0100 Subject: [PATCH 19/22] Included sliders taht form circle adn beizer --- formart_downgrade/OldOsuExporter.cpp | 125 ++++++++++++++++++++++++++- formart_downgrade/OldOsuExporter.hpp | 12 +++ 2 files changed, 135 insertions(+), 2 deletions(-) diff --git a/formart_downgrade/OldOsuExporter.cpp b/formart_downgrade/OldOsuExporter.cpp index d83cb23..747d5d6 100644 --- a/formart_downgrade/OldOsuExporter.cpp +++ b/formart_downgrade/OldOsuExporter.cpp @@ -7,6 +7,117 @@ // Construtor OldOsuExporter::OldOsuExporter(const std::string& filePath) : filePath(filePath) {} +// Função para calcular um ponto da curva de Bézier cúbica +Point OldOsuExporter::bezierPoint(float t, const Point& p0, const Point& p1, const Point& p2, const Point& p3) { + float x = std::pow(1 - t, 3) * p0.first + + 3 * std::pow(1 - t, 2) * t * p1.first + + 3 * (1 - t) * std::pow(t, 2) * p2.first + + std::pow(t, 3) * p3.first; + + float y = std::pow(1 - t, 3) * p0.second + + 3 * std::pow(1 - t, 2) * t * p1.second + + 3 * (1 - t) * std::pow(t, 2) * p2.second + + std::pow(t, 3) * p3.second; + + return {x, y}; +} + +// Função para gerar pontos na curva de Bézier com base nos pontos de controle +std::vector> OldOsuExporter::generateBezierCurve(const Point& p0, const Point& p1, const Point& p2, const Point& p3) { + std::vector> curvePoints; + + // Adiciona o ponto inicial + curvePoints.push_back(std::pair((int)p0.first,(int)p0.second)); + + // Incremento de t para gerar pontos ao longo da curva + float tStep = 0.01; // 100 pontos ao longo da curva + float maxDistance = 10.0; // Distância máxima entre pontos consecutivos + + Point lastPoint = p0; + for (float t = tStep; t <= 1.0; t += tStep) { + Point currentPoint = bezierPoint(t, p0, p1, p2, p3); + + // Calcula a distância euclidiana entre os pontos + float distance = std::sqrt( + std::pow(currentPoint.first - lastPoint.first, 2) + + std::pow(currentPoint.second - lastPoint.second, 2) + ); + + // Se a distância for maior que o limite, adicionar o ponto + if (distance <= maxDistance) { + curvePoints.push_back(std::pair((int)currentPoint.first,(int)currentPoint.second)); + lastPoint = currentPoint; + } + } + + // Adiciona o ponto final + curvePoints.push_back(std::pair((int)p3.first,(int)p3.second)); + + return curvePoints; +} + +std::pair OldOsuExporter::findCircle(const Point& p1, const Point& p2, const Point& p3) { + float x1 = p1.first, y1 = p1.second; + float x2 = p2.first, y2 = p2.second; + float x3 = p3.first, y3 = p3.second; + + // Calcula os determinantes + float A = x1 * (y2 - y3) - y1 * (x2 - x3) + x2 * y3 - x3 * y2; + float B = (x1 * x1 + y1 * y1) * (y3 - y2) + + (x2 * x2 + y2 * y2) * (y1 - y3) + + (x3 * x3 + y3 * y3) * (y2 - y1); + + float C = (x1 * x1 + y1 * y1) * (x2 - x3) + + (x2 * x2 + y2 * y2) * (x3 - x1) + + (x3 * x3 + y3 * y3) * (x1 - x2); + + float D = (x1 * x1 + y1 * y1) * (x3 * y2 - x2 * y3) + + (x2 * x2 + y2 * y2) * (x1 * y3 - x3 * y1) + + (x3 * x3 + y3 * y3) * (x2 * y1 - x1 * y2); + + float cx = -B / (2 * A); + float cy = -C / (2 * A); + float radius = std::sqrt((B * B + C * C - 4 * A * D) / (4 * A * A)); + + return {{cx, cy}, radius}; +} + +// Função para calcular o ângulo entre o centro e um ponto +float OldOsuExporter::angleBetween(const Point& center, const Point& point) { + return std::atan2(point.second - center.second, point.first - center.first); +} + +// Função para gerar uma curva circular a partir de três pontos +std::vector> OldOsuExporter::generateCircularCurve(const Point& p1, const Point& p2, const Point& p3, float maxDistance) { + std::vector> curvePoints; + auto [center, radius] = findCircle(p1, p2, p3); + + float startAngle = angleBetween(center, p1); + float midAngle = angleBetween(center, p2); + float endAngle = angleBetween(center, p3); + + // Ajuste dos ângulos para manter a direção correta + if (startAngle > endAngle) { + endAngle += 2 * PI; + } + if (startAngle > midAngle) { + midAngle += 2 * PI; + } + + // Incremento de ângulo para gerar pontos ao longo da curva + float angleStep = maxDistance / radius; + //angleStep = std::min(angleStep, 0.1f); // Para uma resolução alta da curva + + // Gerando os pontos ao longo do arco + for (float angle = startAngle; angle <= endAngle; angle += angleStep) { + float x = center.first + radius * std::cos(angle); + float y = center.second + radius * std::sin(angle); + curvePoints.push_back({x, y}); + } + + return curvePoints; +} + // Função auxiliar para converter uma string em bytes std::vector OldOsuExporter::stringToBytes(const std::string& str) { std::vector bytes(str.begin(), str.end()); @@ -381,12 +492,22 @@ void OldOsuExporter::writeOldOsu(std::ofstream& outFile, const std::shared_ptr(hoProperties.at(5)->value); - // Obter os pares de números + // Obter os pares de números std::vector> points = this->parseNumberPairs(strPoints); + points.insert(points.begin(),std::pair(xOsu,yOsu)); // Criar segmentos - auto segments = this->createSlider(points); + std::vector> segments; + + if(strPoints.at(0) == 'B'){ + segments = this->generateBezierCurve(points[0],points[1],points[2],points[3]); + + } else if(strPoints.at(0) == 'P'){ + segments = generateCircularCurve(points[0],points[1],points[2]); + } else { + segments = this->createSlider(points); + } const short segmentCount = segments.size() -1; std::cout << "Created segment vetor of size " < #include +using Point = std::pair; + class OldOsuExporter { public: // Construtor que recebe o caminho para o arquivo de exportação @@ -50,6 +52,16 @@ class OldOsuExporter { int calculateAngle(const std::pair& a, const std::pair& b); + Point bezierPoint(float t, const Point& p0, const Point& p1, const Point& p2, const Point& p3); + + std::vector> generateBezierCurve(const Point& p0, const Point& p1, const Point& p2, const Point& p3); + + std::vector> generateCircularCurve(const Point& p1, const Point& p2, const Point& p3, float maxDistance = 10.0f); + + float angleBetween(const Point& center, const Point& point); + + std::pair findCircle(const Point& p1, const Point& p2, const Point& p3); + std::pair lerp(const std::pair& a, const std::pair& b, float amount); void WriteVarLength(std::ofstream& outFile, int length); From 69fc2ae938c303fe1de396f07a64522747434b07 Mon Sep 17 00:00:00 2001 From: Elisson Eric da Silva Andrade Date: Wed, 20 Nov 2024 02:39:01 +0100 Subject: [PATCH 20/22] Fixed direction of circles --- formart_downgrade/OldOsuExporter.cpp | 38 +++++++++++++++++++--------- formart_downgrade/OldOsuExporter.hpp | 2 ++ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/formart_downgrade/OldOsuExporter.cpp b/formart_downgrade/OldOsuExporter.cpp index 747d5d6..42c83b1 100644 --- a/formart_downgrade/OldOsuExporter.cpp +++ b/formart_downgrade/OldOsuExporter.cpp @@ -87,33 +87,47 @@ float OldOsuExporter::angleBetween(const Point& center, const Point& point) { return std::atan2(point.second - center.second, point.first - center.first); } + +// Normaliza o ângulo para o intervalo [0, 2π] +float OldOsuExporter::normalizeAngle(float angle) { + while (angle < 0) angle += 2 * PI; + while (angle >= 2 * PI) angle -= 2 * PI; + return angle; +} + // Função para gerar uma curva circular a partir de três pontos std::vector> OldOsuExporter::generateCircularCurve(const Point& p1, const Point& p2, const Point& p3, float maxDistance) { std::vector> curvePoints; auto [center, radius] = findCircle(p1, p2, p3); - float startAngle = angleBetween(center, p1); - float midAngle = angleBetween(center, p2); - float endAngle = angleBetween(center, p3); - - // Ajuste dos ângulos para manter a direção correta - if (startAngle > endAngle) { - endAngle += 2 * PI; - } - if (startAngle > midAngle) { - midAngle += 2 * PI; - } + float startAngle = normalizeAngle(angleBetween(center, p1)); + float midAngle = normalizeAngle(angleBetween(center, p2)); + float endAngle = normalizeAngle(angleBetween(center, p3)); // Incremento de ângulo para gerar pontos ao longo da curva float angleStep = maxDistance / radius; + + // Determina a direção da curva (anti-horária ou horária) + bool clockwise = (endAngle > startAngle) ^ (midAngle > startAngle) ^ (midAngle > endAngle); + + if (clockwise) { + if (startAngle < endAngle) startAngle += 2 * PI; + angleStep = -angleStep; + //std::swap(startAngle, endAngle); + } else { + if (endAngle < startAngle) endAngle += 2 * PI; + } //angleStep = std::min(angleStep, 0.1f); // Para uma resolução alta da curva + + //curvePoints.push_back(p1); // Gerando os pontos ao longo do arco - for (float angle = startAngle; angle <= endAngle; angle += angleStep) { + for (float angle = startAngle; clockwise ? angle >= endAngle : angle <= endAngle; angle += angleStep) { float x = center.first + radius * std::cos(angle); float y = center.second + radius * std::sin(angle); curvePoints.push_back({x, y}); } + //curvePoints.push_back(p3); return curvePoints; } diff --git a/formart_downgrade/OldOsuExporter.hpp b/formart_downgrade/OldOsuExporter.hpp index 484c2e3..104468a 100644 --- a/formart_downgrade/OldOsuExporter.hpp +++ b/formart_downgrade/OldOsuExporter.hpp @@ -60,6 +60,8 @@ class OldOsuExporter { float angleBetween(const Point& center, const Point& point); + float normalizeAngle(float angle); + std::pair findCircle(const Point& p1, const Point& p2, const Point& p3); std::pair lerp(const std::pair& a, const std::pair& b, float amount); From ab25dea360c2a6bd60a4c829e3caf233695b9469 Mon Sep 17 00:00:00 2001 From: Elisson Eric da Silva Andrade Date: Sun, 1 Dec 2024 23:36:23 +0100 Subject: [PATCH 21/22] Updated README.md with up to date instructions, merged other contributtor improvments --- README.md | 32 +++++++++++++++++++ .../BinaryFileWriter.cpp | 0 .../BinaryFileWriter.hpp | 0 .../Makefile | 0 .../Mp3ToRawConverter.cpp | 0 .../Mp3ToRawConverter.h | 0 .../OldOsuExporter.cpp | 0 .../OldOsuExporter.hpp | 0 .../TreeNode.cpp | 0 .../TreeNode.hpp | 0 .../main_readfile.cpp | 0 .../read_file.cpp | 0 .../read_file.h | 0 source/Beatmaps/Beatmap.cpp | 2 +- 14 files changed, 33 insertions(+), 1 deletion(-) rename {formart_downgrade => format_downgrade}/BinaryFileWriter.cpp (100%) rename {formart_downgrade => format_downgrade}/BinaryFileWriter.hpp (100%) rename {formart_downgrade => format_downgrade}/Makefile (100%) rename {formart_downgrade => format_downgrade}/Mp3ToRawConverter.cpp (100%) rename {formart_downgrade => format_downgrade}/Mp3ToRawConverter.h (100%) rename {formart_downgrade => format_downgrade}/OldOsuExporter.cpp (100%) rename {formart_downgrade => format_downgrade}/OldOsuExporter.hpp (100%) rename {formart_downgrade => format_downgrade}/TreeNode.cpp (100%) rename {formart_downgrade => format_downgrade}/TreeNode.hpp (100%) rename {formart_downgrade => format_downgrade}/main_readfile.cpp (100%) rename {formart_downgrade => format_downgrade}/read_file.cpp (100%) rename {formart_downgrade => format_downgrade}/read_file.h (100%) diff --git a/README.md b/README.md index 0e42df7..3e90fab 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,38 @@ As part of an effort to open source the full osu! stack, I (peppy) am splitting No support is provided for this. +# Compiling + +You need to install the [devkitPRO](https://devkitpro.org/wiki/Getting_Started) on your machine. +Download or clone this repository in a directory of your choice (let's call it "osu-ds"). +Open the "osu-ds" directory and, if you are on windows, simply execute the file `build.bat`. If you are not, simply run `make` on a terminal open "osu-ds" directory. +Wait for the process to finish and if everything goes right, at the end you will have a file called `osuNDS.nds` on the "osu-ds" directory. + +# Runing + +If you want to run the game on a emulator, you need to enable DLDI on the emulator and set up the direcoty/file from which the files(aka, songs) will be read from. +On the emulator melonDS(0.9.5 or higher), you can do that by going into the menu Config -> Emu Setting -> Choosing the "DLDI" tab -> click on the "Enable DLDI(for homebrew)" checkbox -> click on the "Sync SD to folder" checkbox -> Choose a folder where you will put the songs.(let's call it "songs") +Now load the `osuNDS.nds` on the emulator and the game should start, even if you have no musics to pick from yet. +If you want to run this on original hardware, you will need a flash cart and the DLDI patch for the said cart. Apply the DLDI patch on the `osuNDS.nds` and copy the file to the SD card that will go on the flash cart. +Warning: the latest version of this homebrew has not been tested on any flash cart yet. Any feedback in this process is appreciatted. + +# Converting songs + +To convert songs from the base Osu! game, you need to compile the content of `format_downgrade` directory first. +It's a C++(17) application, so check if your compiler has support to this version.The make application is also used, so check if this application is installed as well. You also need to have the libraries `mpg123`, `samplerate` and `shlwapi` installed. Those libraries can be installed through pacman on windows. +Once those libraries and a compatible compiler are installed, the application can be compiled by runing the command `make` on the `format_downgrade` directory. This command will generate a file called `format_downgrader.exe` on windows. You can use `format_downgrader.exe` to convert songs to a format that can be played on osu-ds. + +To convert a song, you will need two files: the .osu file of the song on the difficulty you want, and the corresponding mp3 music file(.ogg files and others are not supported yet). +Now, simple grab the .osu file and drop over the `format_downgrader.exe` file. This will generate two files: a .ods file and .raw file on the same directory where the .osu file was. +Those two files are compatible with the format that the osuNDS.nds can read. + +As a alternative, you can also check this [other converter being created by other contributors of this project](https://github.com/KonPet/osu-ds-convert). + +# Adding songs + +Remenber the "songs" folder? Create a subdirectory called "osuds" there. Now, put the files .ods and .raw in this subdirectory. If you run the emulator, you should be able to see the song, and by selecting it, you can play it. + + ## License This is released under the [BSD 2-Clause license](LICENSE). diff --git a/formart_downgrade/BinaryFileWriter.cpp b/format_downgrade/BinaryFileWriter.cpp similarity index 100% rename from formart_downgrade/BinaryFileWriter.cpp rename to format_downgrade/BinaryFileWriter.cpp diff --git a/formart_downgrade/BinaryFileWriter.hpp b/format_downgrade/BinaryFileWriter.hpp similarity index 100% rename from formart_downgrade/BinaryFileWriter.hpp rename to format_downgrade/BinaryFileWriter.hpp diff --git a/formart_downgrade/Makefile b/format_downgrade/Makefile similarity index 100% rename from formart_downgrade/Makefile rename to format_downgrade/Makefile diff --git a/formart_downgrade/Mp3ToRawConverter.cpp b/format_downgrade/Mp3ToRawConverter.cpp similarity index 100% rename from formart_downgrade/Mp3ToRawConverter.cpp rename to format_downgrade/Mp3ToRawConverter.cpp diff --git a/formart_downgrade/Mp3ToRawConverter.h b/format_downgrade/Mp3ToRawConverter.h similarity index 100% rename from formart_downgrade/Mp3ToRawConverter.h rename to format_downgrade/Mp3ToRawConverter.h diff --git a/formart_downgrade/OldOsuExporter.cpp b/format_downgrade/OldOsuExporter.cpp similarity index 100% rename from formart_downgrade/OldOsuExporter.cpp rename to format_downgrade/OldOsuExporter.cpp diff --git a/formart_downgrade/OldOsuExporter.hpp b/format_downgrade/OldOsuExporter.hpp similarity index 100% rename from formart_downgrade/OldOsuExporter.hpp rename to format_downgrade/OldOsuExporter.hpp diff --git a/formart_downgrade/TreeNode.cpp b/format_downgrade/TreeNode.cpp similarity index 100% rename from formart_downgrade/TreeNode.cpp rename to format_downgrade/TreeNode.cpp diff --git a/formart_downgrade/TreeNode.hpp b/format_downgrade/TreeNode.hpp similarity index 100% rename from formart_downgrade/TreeNode.hpp rename to format_downgrade/TreeNode.hpp diff --git a/formart_downgrade/main_readfile.cpp b/format_downgrade/main_readfile.cpp similarity index 100% rename from formart_downgrade/main_readfile.cpp rename to format_downgrade/main_readfile.cpp diff --git a/formart_downgrade/read_file.cpp b/format_downgrade/read_file.cpp similarity index 100% rename from formart_downgrade/read_file.cpp rename to format_downgrade/read_file.cpp diff --git a/formart_downgrade/read_file.h b/format_downgrade/read_file.h similarity index 100% rename from formart_downgrade/read_file.h rename to format_downgrade/read_file.h diff --git a/source/Beatmaps/Beatmap.cpp b/source/Beatmaps/Beatmap.cpp index 8190659..4546068 100644 --- a/source/Beatmaps/Beatmap.cpp +++ b/source/Beatmaps/Beatmap.cpp @@ -136,7 +136,7 @@ void Beatmap::InitBG() { fReady = true; } -void Beatmap::Buffer(list& hitObjectList) +void Beatmap::Buffer(std::list& hitObjectList) { if (!fReady) { From 4408e7b17a1f7fab56f68a9e2d2c7c0b0228b082 Mon Sep 17 00:00:00 2001 From: Elisson Eric da Silva Andrade Date: Mon, 2 Dec 2024 03:11:46 +0100 Subject: [PATCH 22/22] Adjusted hp default drain value --- format_downgrade/OldOsuExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/format_downgrade/OldOsuExporter.cpp b/format_downgrade/OldOsuExporter.cpp index 42c83b1..b9d6689 100644 --- a/format_downgrade/OldOsuExporter.cpp +++ b/format_downgrade/OldOsuExporter.cpp @@ -409,7 +409,7 @@ void OldOsuExporter::writeOldOsu(std::ofstream& outFile, const std::shared_ptr(&sliderMulti), sizeof(sliderMulti)); const float sliderTick = std::get(difficulty->getChild("SliderTickRate")->value); outFile.write(reinterpret_cast(&sliderTick), sizeof(sliderTick)); - const float hpDrop = 5.0; + const float hpDrop = 0.005; outFile.write(reinterpret_cast(&hpDrop), sizeof(hpDrop)); const uint8_t peppyStars = 5; outFile.write(reinterpret_cast(&peppyStars), sizeof(peppyStars));