Skip to content

Commit

Permalink
Add input infrastructure
Browse files Browse the repository at this point in the history
  • Loading branch information
malleoz authored and vabold committed Mar 16, 2024
1 parent 27f3195 commit 9882b44
Show file tree
Hide file tree
Showing 21 changed files with 856 additions and 73 deletions.
3 changes: 3 additions & 0 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from glob import glob
import io
import os
import shutil
import sys
from vendor.ninja_syntax import Writer

Expand Down Expand Up @@ -147,3 +148,5 @@
with open('build.ninja', 'w') as out_file:
out_file.write(out_buf.getvalue())
n.close()

shutil.copytree("samples", "out/Tests", dirs_exist_ok=True)
87 changes: 87 additions & 0 deletions include/Common.hh
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,93 @@ enum class Character {
Max = 48,
};

enum class WeightClass {
Invalid = -1,
Light = 0,
Medium = 1,
Heavy = 2,
};

static constexpr WeightClass CharacterToWeight(Character character) {
switch (character) {
case Character::Baby_Peach:
case Character::Baby_Daisy... Character::Baby_Mario:
case Character::Toad:
case Character::Baby_Luigi... Character::Koopa_Troopa:
case Character::Small_Mii_Outfit_A_Male... Character::Small_Mii_Outfit_C_Female:
case Character::Small_Mii:
return WeightClass::Light;
case Character::Mario:
case Character::Luigi:
case Character::Yoshi:
case Character::Daisy... Character::Diddy_Kong:
case Character::Bowser_Jr:
case Character::Medium_Mii_Outfit_A_Male... Character::Medium_Mii_Outfit_C_Female:
case Character::Medium_Mii:
case Character::Peach_Biker_Outfit:
case Character::Daisy_Biker_Outfit:
return WeightClass::Medium;
case Character::Waluigi:
case Character::Bowser:
case Character::Donkey_Kong:
case Character::Wario:
case Character::King_Boo:
case Character::Dry_Bowser... Character::Rosalina:
case Character::Large_Mii_Outfit_A_Male... Character::Large_Mii_Outfit_C_Female:
case Character::Large_Mii:
case Character::Rosalina_Biker_Outfit:
return WeightClass::Heavy;
default:
return WeightClass::Invalid;
}
}

static constexpr WeightClass VehicleToWeight(Vehicle vehicle) {
switch (vehicle) {
case Vehicle::Standard_Kart_S:
case Vehicle::Baby_Booster:
case Vehicle::Mini_Beast:
case Vehicle::Cheep_Charger:
case Vehicle::Tiny_Titan:
case Vehicle::Blue_Falcon:
case Vehicle::Standard_Bike_S:
case Vehicle::Bullet_Bike:
case Vehicle::Bit_Bike:
case Vehicle::Quacker:
case Vehicle::Magikruiser:
case Vehicle::Jet_Bubble:
return WeightClass::Light;
case Vehicle::Standard_Kart_M:
case Vehicle::Classic_Dragster:
case Vehicle::Wild_Wing:
case Vehicle::Super_Blooper:
case Vehicle::Daytripper:
case Vehicle::Sprinter:
case Vehicle::Standard_Bike_M:
case Vehicle::Mach_Bike:
case Vehicle::Sugarscoot:
case Vehicle::Zip_Zip:
case Vehicle::Sneakster:
case Vehicle::Dolphin_Dasher:
return WeightClass::Medium;
case Vehicle::Standard_Kart_L:
case Vehicle::Offroader:
case Vehicle::Flame_Flyer:
case Vehicle::Piranha_Prowler:
case Vehicle::Jetsetter:
case Vehicle::Honeycoupe:
case Vehicle::Standard_Bike_L:
case Vehicle::Flame_Runner:
case Vehicle::Wario_Bike:
case Vehicle::Shooting_Star:
case Vehicle::Spear:
case Vehicle::Phantom:
return WeightClass::Heavy;
default:
return WeightClass::Invalid;
}
}

extern const char *const COURSE_NAMES[59];
extern const char *const VEHICLE_NAMES[36];

Expand Down
Binary file added samples/rmc3-rta-1-17-843.krkg
Binary file not shown.
Binary file added samples/rmc3-rta-1-17-843.rkg
Binary file not shown.
6 changes: 0 additions & 6 deletions source/game/kart/KartParam.hh
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,6 @@ public:
Inside_Drift_Bike = 2,
};

enum class WeightClass {
Light = 0,
Medium = 1,
Heavy = 2,
};

Stats();
Stats(EGG::RamStream &stream);

Expand Down
6 changes: 3 additions & 3 deletions source/game/scene/GameScene.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "GameScene.hh"

#include "game/system/InputManager.hh"
#include "game/system/KPadDirector.hh"

#include <egg/core/SceneManager.hh>

Expand All @@ -13,7 +13,7 @@ GameScene::GameScene() {
GameScene::~GameScene() = default;

void GameScene::calc() {
System::InputManager::Instance()->calc();
System::KPadDirector::Instance()->calc();
calcEngines();
}

Expand All @@ -40,6 +40,7 @@ void GameScene::appendResource(System::MultiDvdArchive * /*arc*/, s32 /*id*/) {}

void GameScene::initScene() {
createEngines();
System::KPadDirector::Instance()->reset();
initEngines();
}

Expand All @@ -49,7 +50,6 @@ void GameScene::deinitScene() {
}

destroyEngines();
System::InputManager::Instance()->clear();
}

} // namespace Scene
5 changes: 2 additions & 3 deletions source/game/scene/RootScene.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "RootScene.hh"

#include "game/system/InputManager.hh"
#include "game/system/KPadDirector.hh"
#include "game/system/RaceConfig.hh"
#include "game/system/ResourceManager.hh"

Expand All @@ -21,13 +21,12 @@ void RootScene::enter() {

void RootScene::allocate() {
System::ResourceManager::CreateInstance();
System::InputManager::CreateInstance();
System::KPadDirector::CreateInstance();
System::RaceConfig::CreateInstance();
}

void RootScene::init() {
System::RaceConfig::Instance()->init();
System::InputManager::Instance()->init();
}

} // namespace Scene
163 changes: 163 additions & 0 deletions source/game/system/GhostFile.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#include "GhostFile.hh"

#include <egg/core/Decomp.hh>

#include <cstring>

namespace System {

GhostFile::GhostFile(RawGhostFile *raw) {
read(raw);
}

GhostFile::~GhostFile() = default;

void GhostFile::read(RawGhostFile *raw) {
readHeader(raw);
m_inputSize = raw->parseAt<u16>(0xE);
m_inputs = raw->buffer() + RKG_HEADER_SIZE;
}

void GhostFile::readHeader(RawGhostFile *raw) {
memcpy(m_userData.data(), raw->buffer() + RKG_USER_DATA_OFFSET, RKG_USER_DATA_SIZE);
m_userData[10] = L'\0';

u32 data = raw->parseAt<u32>(0x8);
m_year = (data >> 0xD) & 0x7F;
m_month = (data >> 0x9) & 0xF;
m_day = (data >> 0x4) & 0x1F;

memcpy(m_miiData.data(), raw->buffer() + RKG_MII_DATA_OFFSET, RKG_MII_DATA_SIZE);

m_lapCount = raw->parseAt<u8>(0x10);

// TODO: Do we want to add a bounds check here?
for (u8 lap = 0; lap < m_lapCount; ++lap) {
m_lapTimes[lap] = Timer(raw->parseAt<u32>(0x11 + lap * 3));
}

m_raceTime = Timer(raw->parseAt<u32>(0x4));

m_course = static_cast<Course>(raw->parseAt<u32>(0x4) >> 0x2 & 0x3F);
m_character = static_cast<Character>(raw->parseAt<u16>(0x8) >> 0x4 & 0x3F);
m_vehicle = static_cast<Vehicle>(raw->parseAt<u8>(0x8) >> 0x2);
m_controllerId = raw->parseAt<u8>(0xB) & 0xF;
m_type = raw->parseAt<u16>(0xC) >> 0x2 & 0x7F;
m_location = raw->parseAt<u32>(0x34);
m_driftIsAuto = raw->parseAt<u8>(0xD) >> 1 & 0x1;
}

Character GhostFile::character() const {
return m_character;
}

Vehicle GhostFile::vehicle() const {
return m_vehicle;
}

Course GhostFile::course() const {
return m_course;
}

const u8 *GhostFile::inputs() const {
return m_inputs;
}

bool GhostFile::driftIsAuto() const {
return m_driftIsAuto;
}

RawGhostFile::RawGhostFile(const u8 *rkg) {
if (!isValid(rkg)) {
K_PANIC("Invalid RKG header");
}

if (compressed(rkg)) {
if (!decompress(rkg)) {
K_PANIC("Failed to decompress RKG!");
}
} else {
memcpy(m_buffer, rkg, RKG_UNCOMPRESSED_FILE_SIZE);
}
}

RawGhostFile::~RawGhostFile() = default;

bool RawGhostFile::decompress(const u8 *rkg) {
memcpy(m_buffer, rkg, RKG_HEADER_SIZE);

// Unset compressed flag
*(m_buffer + 0xC) &= 0xF7;

// Get uncompressed size. Skip past 0x4 bytes which represents the size of the compressed data
s32 uncompressedSize = EGG::Decomp::GetExpandSize(rkg + RKG_HEADER_SIZE + 0x4);

if (uncompressedSize <= 0 ||
static_cast<u32>(uncompressedSize) > RKG_UNCOMPRESSED_INPUT_DATA_SECTION_SIZE) {
return false;
}

EGG::Decomp::DecodeSZS(rkg + RKG_HEADER_SIZE + 0x4, m_buffer + RKG_HEADER_SIZE);

// Set input data section length
*reinterpret_cast<u16 *>(m_buffer + 0xE) = static_cast<u16>(uncompressedSize);

return true;
}

bool RawGhostFile::isValid(const u8 *rkg) const {
if (strncmp(reinterpret_cast<const char *>(rkg), "RKGD", 4) != 0) {
K_PANIC("RKG header malformed");
return false;
}

u32 ids = parse<u32>(*reinterpret_cast<const u32 *>(rkg + 0x8));
Vehicle vehicle = static_cast<Vehicle>(ids >> 0x1a);
Character character = static_cast<Character>((ids >> 0x14) & 0x3f);
u8 year = (ids >> 0xd) & 0x7f;
u8 day = (ids >> 0x4) & 0x1f;
u8 month = (ids >> 0x9) & 0xf;

if (vehicle >= Vehicle::Max || character >= Character::Max) {
return false;
}

if (year >= 100 || day >= 32 || month > 12) {
return false;
}

// Validate weight class match
WeightClass charWeight = CharacterToWeight(character);
WeightClass vehicleWeight = VehicleToWeight(vehicle);

if (charWeight == WeightClass::Invalid) {
K_PANIC("Invalid character weight class!");
}
if (vehicleWeight == WeightClass::Invalid) {
K_PANIC("Invalid vehicle weight class!");
}
if (charWeight != vehicleWeight) {
K_PANIC("Character/Bike weight class mismatch!");
}

// TODO:
// - Check for valid controller type??
// - Check lap times sum to race time??

return true;
}

const u8 *RawGhostFile::buffer() const {
return m_buffer;
}

template <typename T>
T RawGhostFile::parseAt(size_t offset) const {
return parse<T>(*reinterpret_cast<const T *>(m_buffer + offset));
}

bool RawGhostFile::compressed(const u8 *rkg) const {
return ((*(rkg + 0xC) >> 3) & 1) == 1;
}

} // namespace System
Loading

0 comments on commit 9882b44

Please sign in to comment.