From 0a0cb3b0d8ffa69e26f3d92969be6b6a5aec9005 Mon Sep 17 00:00:00 2001 From: Dev-Sams1012 Date: Tue, 28 Jul 2026 20:30:32 -0300 Subject: [PATCH 1/2] feat(core): add console identification system - Add `ConsoleIdentifier` to identify consoles from file headers. - Introduce `IConsoleDetector` interface for signature-based detection. - Add `Ps1Detector` and `GameCubeDetector` implementations. - Add `Console` enum with supported consoles and `Desconhecido` fallback. - Reuse `BinaryFileReader` for safe header inspection. --- .../identification/ConsoleIdentifier.hpp | 20 +++++++++++++++++ .../identification/IConsoleDetector.hpp | 20 +++++++++++++++++ .../detectors/GameCubeDetector.hpp | 13 +++++++++++ .../identification/detectors/Ps1Detector.hpp | 13 +++++++++++ core/include/retroforge/models/Console.hpp | 6 +++++ core/src/identification/ConsoleIdentifier.cpp | 20 +++++++++++++++++ .../detectors/GameCubeDetector.cpp | 21 ++++++++++++++++++ .../identification/detectors/Ps1Detector.cpp | 22 +++++++++++++++++++ 8 files changed, 135 insertions(+) create mode 100644 core/include/retroforge/identification/ConsoleIdentifier.hpp create mode 100644 core/include/retroforge/identification/IConsoleDetector.hpp create mode 100644 core/include/retroforge/identification/detectors/GameCubeDetector.hpp create mode 100644 core/include/retroforge/identification/detectors/Ps1Detector.hpp create mode 100644 core/include/retroforge/models/Console.hpp create mode 100644 core/src/identification/ConsoleIdentifier.cpp create mode 100644 core/src/identification/detectors/GameCubeDetector.cpp create mode 100644 core/src/identification/detectors/Ps1Detector.cpp diff --git a/core/include/retroforge/identification/ConsoleIdentifier.hpp b/core/include/retroforge/identification/ConsoleIdentifier.hpp new file mode 100644 index 0000000..ebef120 --- /dev/null +++ b/core/include/retroforge/identification/ConsoleIdentifier.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "retroforge/identification/IConsoleDetector.hpp" +#include "retroforge/io/BinaryFileReader.hpp" + +#include + +namespace retroforge::identification { + +class ConsoleIdentifier { + public: + void register_detector(std::unique_ptr detector); + Console identify(retroforge ::io ::BinaryFileReader &leitor) const; + + private: + static constexpr size_t TAMANHO_CABECALHO = 32; + std ::vector> detectores_; +}; + +} // namespace retroforge::identification \ No newline at end of file diff --git a/core/include/retroforge/identification/IConsoleDetector.hpp b/core/include/retroforge/identification/IConsoleDetector.hpp new file mode 100644 index 0000000..5019c41 --- /dev/null +++ b/core/include/retroforge/identification/IConsoleDetector.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "retroforge/models/Console.hpp" + +#include +#include + +namespace retroforge::identification { + +using retroforge::models::Console; + +class IConsoleDetector { + + public: + virtual ~IConsoleDetector() = default; + virtual bool matches(const std::vector &cabecalho) const = 0; + virtual Console console() const = 0; +}; + +} // namespace retroforge::identification \ No newline at end of file diff --git a/core/include/retroforge/identification/detectors/GameCubeDetector.hpp b/core/include/retroforge/identification/detectors/GameCubeDetector.hpp new file mode 100644 index 0000000..9944aff --- /dev/null +++ b/core/include/retroforge/identification/detectors/GameCubeDetector.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "retroforge/identification/IConsoleDetector.hpp" + +namespace retroforge::identification::detectors { + +class GameCubeDetector : public IConsoleDetector { + public: + bool matches(const std::vector &cabecalho) const override; + Console console() const override { return Console::GameCube; } +}; + +} // namespace retroforge::identification::detectors \ No newline at end of file diff --git a/core/include/retroforge/identification/detectors/Ps1Detector.hpp b/core/include/retroforge/identification/detectors/Ps1Detector.hpp new file mode 100644 index 0000000..bb985de --- /dev/null +++ b/core/include/retroforge/identification/detectors/Ps1Detector.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "retroforge/identification/IConsoleDetector.hpp" + +namespace retroforge::identification::detectors { + +class Ps1Detector : public IConsoleDetector { + public: + bool matches(const std::vector &cabecalho) const override; + Console console() const override { return Console::PS1; } +}; + +} // namespace retroforge::identification::detectors \ No newline at end of file diff --git a/core/include/retroforge/models/Console.hpp b/core/include/retroforge/models/Console.hpp new file mode 100644 index 0000000..c64c74a --- /dev/null +++ b/core/include/retroforge/models/Console.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace retroforge::models { + +enum class Console { PS1, PS2, PSP, GameCube, Dreamcast, MegaDrive, SNES, Desconhecido }; +} // namespace retroforge::models diff --git a/core/src/identification/ConsoleIdentifier.cpp b/core/src/identification/ConsoleIdentifier.cpp new file mode 100644 index 0000000..93adc75 --- /dev/null +++ b/core/src/identification/ConsoleIdentifier.cpp @@ -0,0 +1,20 @@ +#include "retroforge/identification/ConsoleIdentifier.hpp" + +namespace retroforge::identification { +void ConsoleIdentifier::register_detector(std::unique_ptr detector) { + detectores_.push_back(std ::move(detector)); +} + +Console ConsoleIdentifier::identify(retroforge::io::BinaryFileReader &leitor) const { + auto cabecalho = leitor.read_at(0, TAMANHO_CABECALHO); + + for (const auto &detector : detectores_) { + if (detector->matches(cabecalho)) { + return detector->console(); + } + } + + return Console::Desconhecido; +} + +} // namespace retroforge::identification \ No newline at end of file diff --git a/core/src/identification/detectors/GameCubeDetector.cpp b/core/src/identification/detectors/GameCubeDetector.cpp new file mode 100644 index 0000000..f5bae15 --- /dev/null +++ b/core/src/identification/detectors/GameCubeDetector.cpp @@ -0,0 +1,21 @@ +#include "retroforge/identification/detectors/GameCubeDetector.hpp" + +namespace retroforge::identification::detectors { + +bool GameCubeDetector::matches(const std::vector &cabecalho) const { + constexpr size_t OFFSET_ASSINATURA = 0x1C; + constexpr uint32_t MAGIC_GAMECUBE = 0xC2339F3D; + + if (cabecalho.size() < OFFSET_ASSINATURA + 4) { + return false; + } + + uint32_t valor = (static_cast(cabecalho[OFFSET_ASSINATURA]) << 24) | + (static_cast(cabecalho[OFFSET_ASSINATURA + 1]) << 16) | + (static_cast(cabecalho[OFFSET_ASSINATURA + 2]) << 8) | + (static_cast(cabecalho[OFFSET_ASSINATURA + 3])); + + return valor == MAGIC_GAMECUBE; +} + +} // namespace retroforge::identification::detectors \ No newline at end of file diff --git a/core/src/identification/detectors/Ps1Detector.cpp b/core/src/identification/detectors/Ps1Detector.cpp new file mode 100644 index 0000000..7774593 --- /dev/null +++ b/core/src/identification/detectors/Ps1Detector.cpp @@ -0,0 +1,22 @@ +#include "retroforge/identification/detectors/Ps1Detector.hpp" +#include +#include + +namespace retroforge::identification::detectors { + +bool Ps1Detector::matches(const std::vector &cabecalho) const { + if (cabecalho.empty()) { + return false; + } + + std::string conteudo(cabecalho.begin(), cabecalho.end()); + + std::transform(conteudo.begin(), conteudo.end(), conteudo.begin(), ::toupper); + + bool temFile = conteudo.find("FILE") != std::string::npos; + bool temMode2 = conteudo.find("MODE2/2352") != std::string::npos; + + return temFile && temMode2; +} + +} // namespace retroforge::identification::detectors \ No newline at end of file From c859a7eea35250a36fde3011f75244112a036cc7 Mon Sep 17 00:00:00 2001 From: Dev-Sams1012 Date: Tue, 28 Jul 2026 20:37:10 -0300 Subject: [PATCH 2/2] chore: apply code style --- .../retroforge/identification/ConsoleIdentifier.hpp | 6 +++--- .../retroforge/identification/IConsoleDetector.hpp | 3 +-- .../identification/detectors/GameCubeDetector.hpp | 2 +- .../identification/detectors/Ps1Detector.hpp | 2 +- core/include/retroforge/io/BinaryFileReader.hpp | 10 +++++----- .../retroforge/process/ExternalProcessHandle.hpp | 2 +- core/src/identification/ConsoleIdentifier.cpp | 5 +++-- core/src/identification/detectors/GameCubeDetector.cpp | 2 +- core/src/identification/detectors/Ps1Detector.cpp | 2 +- core/src/io/BinaryFileReader.cpp | 2 +- core/src/process/ExternalProcessHandle.cpp | 2 +- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/core/include/retroforge/identification/ConsoleIdentifier.hpp b/core/include/retroforge/identification/ConsoleIdentifier.hpp index ebef120..68f7c72 100644 --- a/core/include/retroforge/identification/ConsoleIdentifier.hpp +++ b/core/include/retroforge/identification/ConsoleIdentifier.hpp @@ -10,11 +10,11 @@ namespace retroforge::identification { class ConsoleIdentifier { public: void register_detector(std::unique_ptr detector); - Console identify(retroforge ::io ::BinaryFileReader &leitor) const; + Console identify(retroforge::io::BinaryFileReader &leitor) const; private: static constexpr size_t TAMANHO_CABECALHO = 32; - std ::vector> detectores_; + std::vector> detectores_; }; -} // namespace retroforge::identification \ No newline at end of file +} // namespace retroforge::identification diff --git a/core/include/retroforge/identification/IConsoleDetector.hpp b/core/include/retroforge/identification/IConsoleDetector.hpp index 5019c41..333d6e1 100644 --- a/core/include/retroforge/identification/IConsoleDetector.hpp +++ b/core/include/retroforge/identification/IConsoleDetector.hpp @@ -10,11 +10,10 @@ namespace retroforge::identification { using retroforge::models::Console; class IConsoleDetector { - public: virtual ~IConsoleDetector() = default; virtual bool matches(const std::vector &cabecalho) const = 0; virtual Console console() const = 0; }; -} // namespace retroforge::identification \ No newline at end of file +} // namespace retroforge::identification diff --git a/core/include/retroforge/identification/detectors/GameCubeDetector.hpp b/core/include/retroforge/identification/detectors/GameCubeDetector.hpp index 9944aff..71da349 100644 --- a/core/include/retroforge/identification/detectors/GameCubeDetector.hpp +++ b/core/include/retroforge/identification/detectors/GameCubeDetector.hpp @@ -10,4 +10,4 @@ class GameCubeDetector : public IConsoleDetector { Console console() const override { return Console::GameCube; } }; -} // namespace retroforge::identification::detectors \ No newline at end of file +} // namespace retroforge::identification::detectors diff --git a/core/include/retroforge/identification/detectors/Ps1Detector.hpp b/core/include/retroforge/identification/detectors/Ps1Detector.hpp index bb985de..0c25ee6 100644 --- a/core/include/retroforge/identification/detectors/Ps1Detector.hpp +++ b/core/include/retroforge/identification/detectors/Ps1Detector.hpp @@ -10,4 +10,4 @@ class Ps1Detector : public IConsoleDetector { Console console() const override { return Console::PS1; } }; -} // namespace retroforge::identification::detectors \ No newline at end of file +} // namespace retroforge::identification::detectors diff --git a/core/include/retroforge/io/BinaryFileReader.hpp b/core/include/retroforge/io/BinaryFileReader.hpp index 0248c54..1351f35 100644 --- a/core/include/retroforge/io/BinaryFileReader.hpp +++ b/core/include/retroforge/io/BinaryFileReader.hpp @@ -5,21 +5,21 @@ #include #include -namespace retroforge ::io { +namespace retroforge::io { class BinaryFileReader { public: - explicit BinaryFileReader(const std ::string &caminho); + explicit BinaryFileReader(const std::string &caminho); - std::vector read_at(std ::streamoff offset, size_t quantidade); + std::vector read_at(std::streamoff offset, size_t quantidade); std::vector read_next_chunk(size_t tamanho_maximo); bool eof() const; - std ::uintmax_t tamanho_total() const { return tamanho_total_; } + std::uintmax_t tamanho_total() const { return tamanho_total_; } private: std::ifstream arquivo_; std::uintmax_t tamanho_total_; }; -} // namespace retroforge::io \ No newline at end of file +} // namespace retroforge::io diff --git a/core/include/retroforge/process/ExternalProcessHandle.hpp b/core/include/retroforge/process/ExternalProcessHandle.hpp index fc689c0..cf6c383 100644 --- a/core/include/retroforge/process/ExternalProcessHandle.hpp +++ b/core/include/retroforge/process/ExternalProcessHandle.hpp @@ -22,4 +22,4 @@ class ExternalProcessHandle { std::unique_ptr handle_; }; -} // namespace retroforge::process \ No newline at end of file +} // namespace retroforge::process diff --git a/core/src/identification/ConsoleIdentifier.cpp b/core/src/identification/ConsoleIdentifier.cpp index 93adc75..f1a4fd0 100644 --- a/core/src/identification/ConsoleIdentifier.cpp +++ b/core/src/identification/ConsoleIdentifier.cpp @@ -1,8 +1,9 @@ #include "retroforge/identification/ConsoleIdentifier.hpp" namespace retroforge::identification { + void ConsoleIdentifier::register_detector(std::unique_ptr detector) { - detectores_.push_back(std ::move(detector)); + detectores_.push_back(std::move(detector)); } Console ConsoleIdentifier::identify(retroforge::io::BinaryFileReader &leitor) const { @@ -17,4 +18,4 @@ Console ConsoleIdentifier::identify(retroforge::io::BinaryFileReader &leitor) co return Console::Desconhecido; } -} // namespace retroforge::identification \ No newline at end of file +} // namespace retroforge::identification diff --git a/core/src/identification/detectors/GameCubeDetector.cpp b/core/src/identification/detectors/GameCubeDetector.cpp index f5bae15..cf687c9 100644 --- a/core/src/identification/detectors/GameCubeDetector.cpp +++ b/core/src/identification/detectors/GameCubeDetector.cpp @@ -18,4 +18,4 @@ bool GameCubeDetector::matches(const std::vector &cabecalho) const { return valor == MAGIC_GAMECUBE; } -} // namespace retroforge::identification::detectors \ No newline at end of file +} // namespace retroforge::identification::detectors diff --git a/core/src/identification/detectors/Ps1Detector.cpp b/core/src/identification/detectors/Ps1Detector.cpp index 7774593..b9d7cb2 100644 --- a/core/src/identification/detectors/Ps1Detector.cpp +++ b/core/src/identification/detectors/Ps1Detector.cpp @@ -19,4 +19,4 @@ bool Ps1Detector::matches(const std::vector &cabecalho) const { return temFile && temMode2; } -} // namespace retroforge::identification::detectors \ No newline at end of file +} // namespace retroforge::identification::detectors diff --git a/core/src/io/BinaryFileReader.cpp b/core/src/io/BinaryFileReader.cpp index b9dc63b..a2f256d 100644 --- a/core/src/io/BinaryFileReader.cpp +++ b/core/src/io/BinaryFileReader.cpp @@ -40,4 +40,4 @@ std::vector BinaryFileReader::read_next_chunk(size_t tamanho_maximo) { bool BinaryFileReader::eof() const { return arquivo_.eof(); } -} // namespace retroforge::io \ No newline at end of file +} // namespace retroforge::io diff --git a/core/src/process/ExternalProcessHandle.cpp b/core/src/process/ExternalProcessHandle.cpp index cc15137..1e399c9 100644 --- a/core/src/process/ExternalProcessHandle.cpp +++ b/core/src/process/ExternalProcessHandle.cpp @@ -26,4 +26,4 @@ bool ExternalProcessHandle::read_line(std::string &linha_destino) { return true; } -} // namespace retroforge::process \ No newline at end of file +} // namespace retroforge::process