Skip to content

Commit

Permalink
Support multiple test cases in one instance
Browse files Browse the repository at this point in the history
  • Loading branch information
malleoz committed Apr 18, 2024
1 parent 8b0db73 commit 850c43f
Show file tree
Hide file tree
Showing 30 changed files with 185 additions and 67 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Kinoko

[![Luke's rMC3 RTA WR](<https://vabold.github.io/Kinoko/Luke rMC3 RTA WR.svg>)](<https://vabold.github.io/Kinoko/Luke rMC3 RTA WR.svg>)
[![Luke's rMC3 RTA WR](<https://vabold.github.io/Kinoko/Luke rMC3 RTA WR.svg>)](https://www.youtube.com/watch?v=6H6UnSDPPdI)
[![Kasey's LC RTA WR](<https://vabold.github.io/Kinoko/Kasey LC RTA WR.svg>)](https://www.youtube.com/watch?v=HPcvNS8QFVI)

Kinoko is a reimplementation of Mario Kart Wii's physics engine in C++. This project is a spiritual continuation of [stblr/Hanachan](https://github.com/stblr/Hanachan). Like Hanachan, the goal of this reimplementation is to reach perfectly accurate ghost replay.

Expand Down
Binary file added samples/lc-rta-1-08-733.krkg
Binary file not shown.
Binary file added samples/lc-rta-1-08-733.rkg
Binary file not shown.
14 changes: 14 additions & 0 deletions source/abstract/List.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,18 @@ void List::append(void *data) {
m_tail = node;
}

void List::remove(Node *node) {
if (m_head == node) {
m_head = node->m_next;
} else {
node->m_prev->m_next = node->m_next;
}

if (!node->m_next) {
m_tail = node->m_prev;
} else {
node->m_next->m_prev = node->m_prev;
}
}

} // namespace Abstract
1 change: 1 addition & 0 deletions source/abstract/List.hh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public:
Node *getNext(Node *node) const;

void append(void *data);
void remove(Node *node);

private:
Node *m_head;
Expand Down
8 changes: 5 additions & 3 deletions source/egg/core/Archive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace EGG {

Archive::~Archive() = default;
Archive::~Archive() {
s_archiveList.erase(s_archiveList.begin() + m_vectorIdx);
}

void Archive::unmount() {
if (--m_refCount == 0) {
Expand Down Expand Up @@ -42,13 +44,13 @@ Archive *Archive::Mount(void *archiveStart) {
archive->m_refCount++;
} else {
// Create a new archive and add it to the vector
archive = new Archive(archiveStart);
archive = new Archive(archiveStart, s_archiveList.size());
s_archiveList.push_back(archive);
}

return archive;
}

Archive::Archive(void *archiveStart) : m_handle(archiveStart) {}
Archive::Archive(void *archiveStart, size_t idx) : m_handle(archiveStart), m_vectorIdx(idx) {}

} // namespace EGG
4 changes: 2 additions & 2 deletions source/egg/core/Archive.hh
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ public:
static Archive *Mount(void *archiveStart);

private:
Archive(void *archiveStart);
Archive(void *archiveStart, size_t idx);

Abstract::ArchiveHandle m_handle;
size_t m_vectorIdx = -1;
size_t m_vectorIdx;
s32 m_refCount = 1;
};

Expand Down
4 changes: 4 additions & 0 deletions source/egg/util/Stream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ void RamStream::setBufferAndSize(void *buffer, u32 size) {
m_size = size;
}

u8 *RamStream::data() {
return m_buffer;
}

RamStream RamStream::split(u32 size) {
RamStream stream = RamStream(m_buffer + m_index, size);
m_index += size;
Expand Down
1 change: 1 addition & 0 deletions source/egg/util/Stream.hh
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public:
std::string read_string();
RamStream split(u32 size);
void setBufferAndSize(void *buffer, u32 size);
u8 *data();

private:
u8 *m_buffer;
Expand Down
1 change: 1 addition & 0 deletions source/game/kart/KartMove.cc
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,7 @@ void KartMoveBike::init(bool b1, bool b2) {
m_leanRotCap = 0.0f;
m_leanRotInc = 0.0f;
m_wheelieRot = 0.0f;
m_maxWheelieRot = 0.0f;
m_wheelieCooldown = 0;
}

Expand Down
4 changes: 3 additions & 1 deletion source/game/kart/KartObjectManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ KartObjectManager::KartObjectManager() {
}
}

KartObjectManager::~KartObjectManager() = default;
KartObjectManager::~KartObjectManager() {
KartParamFileManager::DestroyInstance();
}

KartObjectManager *KartObjectManager::s_instance = nullptr;

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

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

#include <egg/core/SceneManager.hh>

Expand All @@ -24,10 +25,11 @@ void GameScene::enter() {

void GameScene::exit() {
deinitScene();
unmountResources();
}

void GameScene::reinit() {
deinitScene();
exit();
if (m_nextSceneId < 0) {
onReinit();
initScene();
Expand All @@ -36,7 +38,10 @@ void GameScene::reinit() {
}
}

void GameScene::appendResource(System::MultiDvdArchive * /*arc*/, s32 /*id*/) {}
void GameScene::appendResource(System::MultiDvdArchive *archive, s32 id) {
Resource *resource = new Resource(archive, id);
m_resources.append(resource);
}

void GameScene::initScene() {
createEngines();
Expand All @@ -53,4 +58,15 @@ void GameScene::deinitScene() {
System::KPadDirector::Instance()->clear();
}

void GameScene::unmountResources() {
auto *resourceManager = System::ResourceManager::Instance();
for (Abstract::Node *node = m_resources.head(); node; node = m_resources.getNext(node)) {
Resource *resource = node->data<Resource>();
if (resource->id == 1) {
resourceManager->unmount(resource->archive);
m_resources.remove(node);
}
}
}

} // namespace Scene
6 changes: 4 additions & 2 deletions source/game/scene/GameScene.hh
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ public:
virtual void onReinit() {}

protected:
void appendResource(System::MultiDvdArchive *arc, s32 id);
void appendResource(System::MultiDvdArchive *archive, s32 id);

private:
struct Resource : private Abstract::Node {
struct Resource {
System::MultiDvdArchive *archive;
s32 id;
};

void initScene();
void deinitScene();
void unmountResources();

Abstract::List m_resources;
int m_nextSceneId;
Expand Down
6 changes: 4 additions & 2 deletions source/game/scene/RaceScene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "game/item/ItemDirector.hh"
#include "game/kart/KartObjectManager.hh"
#include "game/system/CourseMap.hh"
#include "game/system/KPadDirector.hh"
#include "game/system/RaceConfig.hh"
#include "game/system/RaceManager.hh"
#include "game/system/ResourceManager.hh"
Expand Down Expand Up @@ -37,9 +38,10 @@ void RaceScene::calcEngines() {
}

void RaceScene::destroyEngines() {
System::KPadDirector::Instance()->endGhostProxies();
Kart::KartObjectManager::DestroyInstance();
Field::CollisionDirector::DestroyInstance();
// Item::ItemDirector::DestroyInstance();
Item::ItemDirector::DestroyInstance();
System::RaceManager::DestroyInstance();
System::CourseMap::DestroyInstance();
}
Expand All @@ -58,7 +60,7 @@ void RaceScene::configure() {
}

void RaceScene::onReinit() {
System::RaceConfig::Instance()->initRace();
configure();
}

} // namespace Scene
2 changes: 1 addition & 1 deletion source/game/system/DvdArchive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void DvdArchive::clearArchive() {
}

void DvdArchive::clearFile() {
if (m_fileStart) {
if (!m_fileStart) {
return;
}

Expand Down
24 changes: 19 additions & 5 deletions source/game/system/GhostFile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

namespace System {

GhostFile::GhostFile(RawGhostFile *raw) {
u8 *streamPtr = const_cast<u8 *>(raw->buffer());
GhostFile::GhostFile(const RawGhostFile &raw) {
u8 *streamPtr = const_cast<u8 *>(raw.buffer());
EGG::RamStream stream(streamPtr, RKG_HEADER_SIZE);
read(stream);
m_inputs = raw->buffer() + RKG_HEADER_SIZE;
m_inputs = raw.buffer() + RKG_HEADER_SIZE;
}

GhostFile::~GhostFile() = default;
Expand Down Expand Up @@ -75,7 +75,23 @@ bool GhostFile::driftIsAuto() const {
return m_driftIsAuto;
}

RawGhostFile::RawGhostFile() {
memset(m_buffer, 0, RKG_UNCOMPRESSED_FILE_SIZE);
}

RawGhostFile::RawGhostFile(const u8 *rkg) {
init(rkg);
}

RawGhostFile::~RawGhostFile() = default;

RawGhostFile &RawGhostFile::operator=(const u8 *rkg) {
init(rkg);

return *this;
}

void RawGhostFile::init(const u8 *rkg) {
if (!isValid(rkg)) {
K_PANIC("Invalid RKG header");
}
Expand All @@ -89,8 +105,6 @@ RawGhostFile::RawGhostFile(const u8 *rkg) {
}
}

RawGhostFile::~RawGhostFile() = default;

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

Expand Down
6 changes: 5 additions & 1 deletion source/game/system/GhostFile.hh
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ static constexpr size_t RKG_MII_DATA_SIZE = 0x4A;

class RawGhostFile {
public:
RawGhostFile();
RawGhostFile(const u8 *rkg);
~RawGhostFile();

RawGhostFile &operator=(const u8 *rkg);

void init(const u8 *rkg);
bool decompress(const u8 *rkg);
bool isValid(const u8 *rkg) const;

Expand All @@ -42,7 +46,7 @@ static_assert(sizeof(RawGhostFile) == RKG_UNCOMPRESSED_FILE_SIZE);

class GhostFile {
public:
GhostFile(RawGhostFile *raw);
GhostFile(const RawGhostFile &raw);
~GhostFile();

void read(EGG::RamStream &stream);
Expand Down
10 changes: 10 additions & 0 deletions source/game/system/KPadController.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ void KPadGhostController::reset(bool driftIsAuto) {
m_raceInputState.reset();

for (auto &stream : m_buttonsStreams) {
stream->currentSequence = 0;
stream->readSequenceFrames = 0;
stream->state = 1;
}
Expand Down Expand Up @@ -237,4 +238,13 @@ void KPadPlayer::startGhostProxy() {
ghostController->setAcceptingInputs(true);
}

void KPadPlayer::endGhostProxy() {
if (!m_controller || m_controller->controlSource() != ControlSource::Ghost) {
return;
}

KPadGhostController *ghostController = reinterpret_cast<KPadGhostController *>(m_controller);
ghostController->setAcceptingInputs(false);
}

} // namespace System
1 change: 1 addition & 0 deletions source/game/system/KPadController.hh
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ public:
void setGhostController(KPadGhostController *controller, const u8 *inputs, bool driftIsAuto);

void startGhostProxy();
void endGhostProxy();

private:
u8 m_ghostBuffer[RKG_UNCOMPRESSED_INPUT_DATA_SECTION_SIZE];
Expand Down
4 changes: 4 additions & 0 deletions source/game/system/KPadDirector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ void KPadDirector::startGhostProxies() {
m_playerInput.startGhostProxy();
}

void KPadDirector::endGhostProxies() {
m_playerInput.endGhostProxy();
}

const KPadPlayer &KPadDirector::playerInput() const {
return m_playerInput;
}
Expand Down
1 change: 1 addition & 0 deletions source/game/system/KPadDirector.hh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public:
void clear();
void reset();
void startGhostProxies();
void endGhostProxies();

const KPadPlayer &playerInput() const;

Expand Down
2 changes: 1 addition & 1 deletion source/game/system/MultiDvdArchive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ MultiDvdArchive::~MultiDvdArchive() {
void *MultiDvdArchive::getFile(const char *filename, size_t *size) const {
void *file = nullptr;

for (u16 i = 0; i < m_archiveCount; i++) {
for (u16 i = m_archiveCount; i-- > 0; ) {
const DvdArchive &archive = m_archives[i];

if (!archive.isLoaded()) {
Expand Down
28 changes: 12 additions & 16 deletions source/game/system/RaceConfig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,26 @@ void RaceConfig::init() {
void RaceConfig::initRace() {
// Normally we copy the menu scenario into the race scenario
// There's no menu scenario in Kinoko, so instead we initialize values here
// TODO: read from parameter file
// For now, we want to initialize solely based off the ghost file.
m_raceScenario.playerCount = 1;
m_raceScenario.course = Course::SNES_Mario_Circuit_3;
Player &player = m_raceScenario.players[0];
player.character = Character::Daisy;
player.vehicle = Vehicle::Mach_Bike;
player.type = Player::Type::Ghost;

size_t size;
const auto *testDirector = Host::KSystem::Instance().testDirector();
u8 *rkg = Abstract::File::Load(testDirector->testCase().rkgPath.data(), size);
m_raceScenario.ghost = new RawGhostFile(rkg);

initControllers();
}
m_ghost = rkg;
delete[] rkg;
GhostFile ghost(m_ghost);

void RaceConfig::initControllers() {
// No need for raw validation, as we already do this
GhostFile ghost(m_raceScenario.ghost);
m_raceScenario.course = ghost.course();
Player &player = m_raceScenario.players[0];
player.character = ghost.character();
player.vehicle = ghost.vehicle();
player.type = Player::Type::Ghost;

if (ghost.course() != m_raceScenario.course) {
K_PANIC("Ghost is playing on wrong track! %u", ghost.course());
}
initControllers(ghost);
}

void RaceConfig::initControllers(const GhostFile &ghost) {
KPadDirector::Instance()->setGhostPad(ghost.inputs(), ghost.driftIsAuto());
}

Expand Down
Loading

0 comments on commit 850c43f

Please sign in to comment.