Random UI and README tweaks (#653)

This commit is contained in:
doop
2026-05-04 00:02:09 -04:00
committed by GitHub
parent c4b2e2e501
commit 95e6ac54cf
4 changed files with 88 additions and 44 deletions
+27 -16
View File
@@ -1,37 +1,48 @@
![DuskLogo](res/logo-mascot.png)
<div align="center">
<img src="res/logo-mascot.png" alt="Logo" width="640">
- ### **[Official Website](https://twilitrealm.dev)**
- ### **[Discord](https://discord.gg/QACynxeyna)**
<p align="center">
<a href="https://twilitrealm.dev">Official Website</a>
<a href="https://discord.gg/QACynxeyna">Discord</a>
</p>
</div>
# Overview
Dusk is a reverse-engineered reimplementation of Twilight Princess.
It aims to be as accurate as possible to the original while also providing new options, enhancements, and tools to customize your experience.
# Setup
**⚠️ Dusk does NOT provide any copyrighted assets. You must provide your own copy of the game.**
### 1. Verify your ROM dump
First make sure your dump of the game is clean and supported by Dusk. You can do this by checking the sha1 hash of your dump against this list of supported versions.
> [!IMPORTANT]
> Dusk does *not* provide any copyrighted assets. You must provide your own copy of the original game.
| Version | sha1 hash |
|--------------| ---------------------------------------- |
| GameCube USA | 75edd3ddff41f125d1b4ce1a40378f1b565519e7 |
| GameCube PAL | 2601822a488eeb86fb89db16ca8f29c2c953e1ca |
### 1. Verify your dump
First, make sure your dump of the game is clean and supported by Dusk. You can do this by checking the SHA-1 hash of your dump against this list of supported versions:
| Version | SHA-1 hash |
|--------------| ------------------------------------------ |
| GameCube USA | `75edd3ddff41f125d1b4ce1a40378f1b565519e7` |
| GameCube EUR | `2601822a488eeb86fb89db16ca8f29c2c953e1ca` |
### 2. Download [Dusk](https://github.com/TwilitRealm/dusk/releases)
### 3. Setup the game
- Extract the zip folder
- Launch Dusk
- Select Options, then set the ISO Path to your supported game dump
- Press Start Game to play!
![Dusk options](assets/dusk_options.png)
- Extract the .zip file
- Launch Dusk
- Press **Select Disc Image**, navigate to your game dump, and select the file
- Press **Start Game** to play!
# Building
If you'd like to build Dusk from source, please read the [build instructions](docs/building.md).
Pull Requests are welcomed! Note that we do not accept contributions that are primarily AI generated and will close your PR if we suspect as much.
Pull requests are welcomed! Note that we do not accept contributions that are primarily AI-generated and will close your PR if we suspect as much.
# Credits
Special thanks to the [TP decompilation](https://github.com/zeldaret/tp) team, the GC/Wii decompilation community, the [Aurora](https://github.com/encounter/aurora) developers, the [TP speedrunning community](https://zsrtp.link), and all [contributors](https://github.com/TwilitRealm/dusk/graphs/contributors).
Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

+34 -10
View File
@@ -104,13 +104,14 @@ hero img {
decorator: horizontal-gradient(#FEE685FF #FEE68500);
}
disk-status {
disc-info {
position: absolute;
left: 96dp;
bottom: 72dp;
display: flex;
flex-direction: column;
gap: 8dp;
gap: 12dp;
font-size: 24dp;
}
version-info {
@@ -119,30 +120,53 @@ version-info {
bottom: 72dp;
display: flex;
flex-direction: column;
gap: 8dp;
gap: 12dp;
text-align: right;
}
.status,
.version {
font-size: 24dp;
}
.status,
.update {
#disc-status {
display: flex;
align-items: center;
gap: 8dp;
}
#disc-status[status=good] {
color: #D8F999;
}
.status[bad] {
#disc-status[status=bad] {
color: #FFC9C9;
}
#disc-status icon {
display: block;
width: 24dp;
height: 24dp;
font-family: "Material Symbols Rounded";
font-weight: normal;
font-size: 24dp;
}
#disc-status[status=good] icon {
decorator: text("&#xe5ca;" center center);
}
#disc-status[status=bad] icon {
decorator: text("&#xe5cd;" center center);
}
#disc-version {
font-size: 20dp;
}
/* TODO: Hidden until an actual update checker is introduced */
.update {
display: none;
font-size: 16dp;
font-weight: bold;
cursor: pointer;
color: #D8F999;
}
.detail,
+27 -18
View File
@@ -28,10 +28,13 @@ const Rml::String kDocumentSource = R"RML(
</hero>
<div id="menu-list" />
</menu>
<disk-status class="intro-item delay-4">
<span id="status" class="status" />
<span id="detail" class="detail" />
</disk-status>
<disc-info class="intro-item delay-4">
<div id="disc-status">
<icon />
<span id="disc-status-label" />
</div>
<span id="disc-version" class="detail" />
</disc-info>
<version-info class="intro-item delay-5">
<div class="version">Version <span id="version-text"></span></div>
<div class="update"><span>Update available!</span> Download</div>
@@ -113,7 +116,7 @@ Prelaunch::Prelaunch() : Document(kDocumentSource), mRoot(mDocument->GetElementB
if (auto* menuList = mDocument->GetElementById("menu-list")) {
const bool hasValidPath = is_selected_path_valid();
mMenuButtons.push_back(
std::make_unique<Button>(menuList, hasValidPath ? "Start Game" : "Select Disk Image"));
std::make_unique<Button>(menuList, hasValidPath ? "Start Game" : "Select Disc Image"));
mMenuButtons.back()->on_pressed([this] {
if (!is_selected_path_valid()) {
open_iso_picker();
@@ -133,8 +136,8 @@ Prelaunch::Prelaunch() : Document(kDocumentSource), mRoot(mDocument->GetElementB
apply_intro_animation(mMenuButtons.back()->root(), "delay-3");
}
mDiscStatus = mDocument->GetElementById("status");
mDiscDetail = mDocument->GetElementById("detail");
mDiscStatus = mDocument->GetElementById("disc-status");
mDiscDetail = mDocument->GetElementById("disc-version");
mVersion = mDocument->GetElementById("version-text");
listen(mDocument, Rml::EventId::Transitionend, [this](Rml::Event& event) {
@@ -185,27 +188,34 @@ void Prelaunch::update() {
}
if (!mMenuButtons.empty()) {
mMenuButtons[0]->set_text(hasValidPath ? "Start Game" : "Select Disk Image");
mMenuButtons[0]->set_text(hasValidPath ? "Start Game" : "Select Disc Image");
}
if (mDiscStatus != nullptr) {
const auto discStatusLabel = mDiscStatus->GetElementById("disc-status-label");
if (mDiscStatus != nullptr && discStatusLabel != nullptr) {
if (hasValidPath) {
mDiscStatus->RemoveAttribute("bad");
mDiscStatus->SetInnerRML("Disc Ready");
mDiscStatus->SetAttribute("status", "good");
discStatusLabel->SetInnerRML("Disc ready.");
} else {
mDiscStatus->SetAttribute("bad", "");
mDiscStatus->SetInnerRML("Disk Not Found");
mDiscStatus->SetAttribute("status", "bad");
discStatusLabel->SetInnerRML("Disc not found.");
}
}
if (mDiscDetail != nullptr) {
if (hasValidPath) {
mDiscDetail->SetProperty(Rml::PropertyId::Display, Rml::Style::Display::Block);
mDiscDetail->SetInnerRML(state.isPal ? "GameCube • PAL" : "GameCube • USA");
mDiscDetail->SetInnerRML(state.isPal ? "GameCube • EUR" : "GameCube • USA");
} else {
mDiscDetail->SetProperty(Rml::PropertyId::Display, Rml::Style::Display::None);
}
}
if (mVersion != nullptr) {
mVersion->SetInnerRML(escape(DUSK_WC_DESCRIBE));
std::string_view versionStr(DUSK_WC_DESCRIBE);
if (versionStr[0] == 'v') {
versionStr = versionStr.substr(1);
}
mVersion->SetInnerRML(escape(versionStr));
}
Document::update();
@@ -239,9 +249,8 @@ bool Prelaunch::handle_nav_command(Rml::Event& event, NavCommand cmd) {
break;
}
}
const auto buttonCount = static_cast<int>(mMenuButtons.size());
int i = (focusedButton + direction) % buttonCount;
if (i < 0) i += buttonCount;
const auto n = static_cast<int>(mMenuButtons.size());
int i = ((focusedButton + direction) % n + n) % n;
while (i >= 0 && i < mMenuButtons.size()) {
if (mMenuButtons[i]->focus()) {
event.StopPropagation();