Initial public source release
Split reusable rendering and format support into vectorail-core and vectorail-gc.
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace openroller::psp {
|
||||
|
||||
enum class AudioEffect : std::uint8_t {
|
||||
Adlib = 0,
|
||||
Tap1 = 1,
|
||||
Tap2 = 2,
|
||||
};
|
||||
|
||||
bool startAudioPlayer(
|
||||
const char* bgmPath,
|
||||
const char* shotPath,
|
||||
const char* effectDirectory);
|
||||
void stopAudioPlayer();
|
||||
bool audioPlayerRunning();
|
||||
bool audioPlayerFinished();
|
||||
std::uint32_t audioPlayerTimeMs();
|
||||
void setAudioPlayerPaused(bool paused);
|
||||
void seekAudioPlayer(std::uint32_t timeMs);
|
||||
void setAudioPlayerShotMuted(bool muted);
|
||||
void playAudioPlayerEffect(AudioEffect effect);
|
||||
|
||||
} // namespace openroller::psp
|
||||
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "StageRuntime.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace openroller::psp {
|
||||
|
||||
enum class Judgment : std::uint8_t {
|
||||
// Values 0..3 match the original game's recovered enum.
|
||||
Miss = 0,
|
||||
Good = 1,
|
||||
Cool = 2,
|
||||
Great = 3,
|
||||
Pending = 0xff,
|
||||
};
|
||||
|
||||
struct GameplayState {
|
||||
struct NoteRuntime {
|
||||
std::uint8_t judgment = static_cast<std::uint8_t>(Judgment::Pending);
|
||||
std::uint8_t holding = 0;
|
||||
std::uint8_t shotMuteApplied = 0;
|
||||
std::uint8_t reserved = 0;
|
||||
float inputStartTimeMs = -1.0f;
|
||||
float lastInputTimeMs = -1.0f;
|
||||
std::uint32_t inputMask = 0;
|
||||
std::uint32_t lastInputBit = 0;
|
||||
};
|
||||
|
||||
NoteRuntime* notes = nullptr;
|
||||
std::uint32_t noteCount = 0;
|
||||
std::uint32_t nextPending = 0;
|
||||
std::uint32_t combo = 0;
|
||||
std::uint32_t maximumCombo = 0;
|
||||
std::uint32_t greatCount = 0;
|
||||
std::uint32_t coolCount = 0;
|
||||
std::uint32_t goodCount = 0;
|
||||
std::uint32_t missCount = 0;
|
||||
float previousClockMs = 0.0f;
|
||||
float lastJudgmentClockMs = -10000.0f;
|
||||
std::int32_t lastJudgedNote = -1;
|
||||
Judgment lastJudgment = Judgment::Pending;
|
||||
bool shotMuted = false;
|
||||
};
|
||||
|
||||
bool initializeGameplay(const StageView& stage, GameplayState* gameplay);
|
||||
void destroyGameplay(GameplayState* gameplay);
|
||||
void seekGameplay(const StageView& stage, GameplayState* gameplay, float clockMs);
|
||||
void updateGameplay(const StageView& stage, GameplayState* gameplay, float clockMs);
|
||||
Judgment tapGameplay(const StageView& stage, GameplayState* gameplay, float clockMs);
|
||||
Judgment pressGameplay(
|
||||
const StageView& stage,
|
||||
GameplayState* gameplay,
|
||||
float clockMs,
|
||||
std::uint32_t inputBit);
|
||||
Judgment releaseGameplay(
|
||||
const StageView& stage,
|
||||
GameplayState* gameplay,
|
||||
float clockMs,
|
||||
std::uint32_t inputBit);
|
||||
Judgment noteJudgment(const GameplayState& gameplay, std::uint32_t noteIndex);
|
||||
|
||||
} // namespace openroller::psp
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "openroller/psp/SongCatalog.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace openroller::psp {
|
||||
|
||||
struct SongMenu {
|
||||
void* catalogStorage = nullptr;
|
||||
std::size_t catalogSize = 0;
|
||||
const SongCatalogHeader* header = nullptr;
|
||||
const SongCatalogRecord* songs = nullptr;
|
||||
int selection = 0;
|
||||
int difficulty = 0;
|
||||
bool difficultyMode = false;
|
||||
void* jacketStorage = nullptr;
|
||||
std::size_t jacketSize = 0;
|
||||
const std::uint16_t* jacketPixels = nullptr;
|
||||
std::uint16_t jacketWidth = 0;
|
||||
std::uint16_t jacketHeight = 0;
|
||||
char rootPath[256]{};
|
||||
};
|
||||
|
||||
bool loadSongMenu(const char* catalogPath, SongMenu* menu, char* error, std::size_t errorCapacity);
|
||||
void unloadSongMenu(SongMenu* menu);
|
||||
bool moveSongSelection(SongMenu* menu, int delta);
|
||||
bool moveDifficultySelection(SongMenu* menu, int delta);
|
||||
const SongCatalogRecord* selectedSong(const SongMenu& menu);
|
||||
bool selectedSongPath(const SongMenu& menu, char* output, std::size_t capacity);
|
||||
bool selectedAudioPath(const SongMenu& menu, char* output, std::size_t capacity);
|
||||
bool selectedShotAudioPath(const SongMenu& menu, char* output, std::size_t capacity);
|
||||
|
||||
} // namespace openroller::psp
|
||||
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "openroller/psp/StagePackage.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace openroller::psp {
|
||||
|
||||
struct Vec3 {
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float z = 0.0f;
|
||||
};
|
||||
|
||||
struct CameraState {
|
||||
Vec3 eye;
|
||||
Vec3 target;
|
||||
Vec3 up{0.0f, 1.0f, 0.0f};
|
||||
float projectionBlend = 0.0f;
|
||||
};
|
||||
|
||||
struct StageView {
|
||||
void* storage = nullptr;
|
||||
std::size_t storageSize = 0;
|
||||
const StagePackageHeader* header = nullptr;
|
||||
const PackageTrackPoint* track = nullptr;
|
||||
const PackageNote* notes = nullptr;
|
||||
const PackageCameraPoint* cameras = nullptr;
|
||||
const PackageDrawDistancePoint* drawDistances = nullptr;
|
||||
const PackageBackgroundColorPoint* backgroundColors = nullptr;
|
||||
const PackageBackgroundModel* backgroundModels = nullptr;
|
||||
const PackageBackgroundVertex* backgroundVertices = nullptr;
|
||||
const PackageBackgroundObject* backgroundObjects = nullptr;
|
||||
const PackageVisibilityKey* visibilityKeys = nullptr;
|
||||
const PackageTransformKey* transformKeys = nullptr;
|
||||
const PackageObjectColorKey* objectColorKeys = nullptr;
|
||||
const PackageParticlePoint* particles = nullptr;
|
||||
const PackageVisualizerPoint* visualizer = nullptr;
|
||||
const PackageBpmPoint* bpmChanges = nullptr;
|
||||
};
|
||||
|
||||
struct BackgroundColors {
|
||||
std::uint32_t topRight = 0;
|
||||
std::uint32_t topLeft = 0;
|
||||
std::uint32_t bottomRight = 0;
|
||||
std::uint32_t bottomLeft = 0;
|
||||
};
|
||||
|
||||
bool loadStagePackage(const char* path, StageView* stage, char* error, std::size_t errorCapacity);
|
||||
void unloadStagePackage(StageView* stage);
|
||||
|
||||
Vec3 trackPositionAt(const StageView& stage, float timeMs);
|
||||
Vec3 trackTangentAt(const StageView& stage, float timeMs);
|
||||
CameraState evaluateCamera(const StageView& stage, float timeMs);
|
||||
BackgroundColors evaluateBackground(const StageView& stage, float timeMs);
|
||||
float evaluateDrawAhead(const StageView& stage, float timeMs);
|
||||
float evaluateBeatDurationMs(const StageView& stage, float timeMs);
|
||||
|
||||
} // namespace openroller::psp
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
namespace openroller::psp {
|
||||
|
||||
constexpr int kScreenWidth = 480;
|
||||
constexpr int kScreenHeight = 272;
|
||||
constexpr int kLogicalWidth = 720;
|
||||
constexpr int kLogicalHeight = 1280;
|
||||
constexpr float kLogicalScale = 3.0f / 8.0f;
|
||||
constexpr int kScaledWidth = 270;
|
||||
constexpr int kBorder = (kScreenHeight - kScaledWidth) / 2;
|
||||
|
||||
enum class TateSide {
|
||||
Clockwise,
|
||||
CounterClockwise,
|
||||
};
|
||||
|
||||
struct Point {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
inline Point toScreen(float logicalX, float logicalY, TateSide side) {
|
||||
if (side == TateSide::Clockwise) {
|
||||
return {
|
||||
static_cast<float>(kScreenWidth) - logicalY * kLogicalScale,
|
||||
static_cast<float>(kBorder) + logicalX * kLogicalScale,
|
||||
};
|
||||
}
|
||||
return {
|
||||
logicalY * kLogicalScale,
|
||||
static_cast<float>(kBorder + kScaledWidth) - logicalX * kLogicalScale,
|
||||
};
|
||||
}
|
||||
|
||||
inline Point screenDirectionToLogical(float screenX, float screenY, TateSide side) {
|
||||
if (side == TateSide::Clockwise) {
|
||||
return {screenY, -screenX};
|
||||
}
|
||||
return {-screenY, screenX};
|
||||
}
|
||||
|
||||
} // namespace openroller::psp
|
||||
Reference in New Issue
Block a user