Initial site

TWiLight wiki + NightScript's DS Index in English
and a couple pages in Japanese for testing
This commit is contained in:
Pk11 2020-12-20 22:18:48 -06:00
parent 1b61ba8747
commit 163e81a3c7
82 changed files with 1989 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*.DS_Store
*_site
*.sass-cache
*.jekyll-cache
*.jekyll-metadata
*Gemfile.lock

10
404.md Normal file
View File

@ -0,0 +1,10 @@
---
title: Error 404
description: Oh no! This page doesn't exist!
permalink: /404.html
layout: default
---
# Error! 404!
Return to the [home page](/) or <span class="a" onclick="window.history.back()">go back</span> to the previous page.

30
Gemfile Normal file
View File

@ -0,0 +1,30 @@
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "jekyll", "~> 4.2.0"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.12"
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
# and associated library.
install_if -> { RUBY_PLATFORM =~ %r!mingw|mswin|java! } do
gem "tzinfo", "~> 1.2"
gem "tzinfo-data"
end
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.0", :install_if => Gem.win_platform?

18
_config.yml Normal file
View File

@ -0,0 +1,18 @@
title : "DS-Homebrew Wiki"
description : "Wikis for DS-Homebrew projects"
repo : "DS-Homebrew/wiki"
color : "#072f4f"
image : "https://avatars1.githubusercontent.com/u/46971470?s=200&v=4"
collections_dir: pages
collections:
en-US:
output: true
permalink: /:path:output_ext
ja-JP:
output: true
lang-names:
en-US: English
ja-JP: 日本語

14
_data/en-US/nav.json Normal file
View File

@ -0,0 +1,14 @@
[
{
"title": "Home",
"url": "/"
},
{
"title": "TWiLight Menu++",
"url": "/twilightmenu"
},
{
"title": "DS Index",
"url": "/ds-index"
}
]

8
_data/en-US/strings.json Normal file
View File

@ -0,0 +1,8 @@
{
"title": "DS-Homebrew Wiki",
"description": "Wikis for DS-Homebrew projects",
"discord-server": "Discord server (English only)",
"source": "Source",
"by": "By: $1",
"published-with": "Published with <a href=\"https://pages.github.com\">GitHub Pages</a>, view <a href=\"https://github.com/$1\">the source</a> on GitHub."
}

14
_data/ja-JP/nav.json Normal file
View File

@ -0,0 +1,14 @@
[
{
"title": "ホーム",
"url": "/ja-JP"
},
{
"title": "TWiLight Menu++",
"url": "/ja-JP/twilightmenu"
},
{
"title": "DSインデックス",
"url": "/ja-JP/ds-index"
}
]

8
_data/ja-JP/strings.json Normal file
View File

@ -0,0 +1,8 @@
{
"title": "DS-Homebrew ウィキ",
"description": "DS-Homebrewのプロジェクトためのウィキ",
"discord-server": "Discordサーバ英語のみ",
"source": "ソース",
"by": "$1による",
"published-with": "<a href=\"https://pages.github.com\">GitHub Pages</a>で公開しています、GitHubに<a href=\"https://github.com/$1\">ソース</a>を表示します。"
}

View File

@ -0,0 +1,110 @@
{% capture headingsWorkspace %}
{% comment %}
Version 1.0.6
https://github.com/allejo/jekyll-anchor-headings
"Be the pull request you wish to see in the world." ~Ben Balter
Usage:
{% include anchor_headings.html html=content %}
Parameters:
* html (string) - the HTML of compiled markdown generated by kramdown in Jekyll
Optional Parameters:
* beforeHeading (bool) : false - Set to true if the anchor should be placed _before_ the heading's content
* anchorAttrs (string) : '' - Any custom HTML attributes that will be added to the `<a>` tag; you may NOT use `href`, `class` or `title`;
the `%heading%` placeholder is available
* anchorBody (string) : '' - The content that will be placed inside the anchor; the `%heading%` placeholder is available
* anchorClass (string) : '' - The class(es) that will be used for each anchor. Separate multiple classes with a space
* anchorTitle (string) : '' - The `title` attribute that will be used for anchors
* h_min (int) : 1 - The minimum header level to build an anchor for; any header lower than this value will be ignored
* h_max (int) : 6 - The maximum header level to build an anchor for; any header greater than this value will be ignored
* bodyPrefix (string) : '' - Anything that should be inserted inside of the heading tag _before_ its anchor and content
* bodySuffix (string) : '' - Anything that should be inserted inside of the heading tag _after_ its anchor and content
Output:
The original HTML with the addition of anchors inside of all of the h1-h6 headings.
{% endcomment %}
{% assign minHeader = include.h_min | default: 1 %}
{% assign maxHeader = include.h_max | default: 6 %}
{% assign beforeHeading = include.beforeHeading %}
{% assign nodes = include.html | split: '<h' %}
{% capture edited_headings %}{% endcapture %}
{% for _node in nodes %}
{% capture node %}{{ _node | strip }}{% endcapture %}
{% if node == "" %}
{% continue %}
{% endif %}
{% assign nextChar = node | replace: '"', '' | strip | slice: 0, 1 %}
{% assign headerLevel = nextChar | times: 1 %}
<!-- If the level is cast to 0, it means it's not a h1-h6 tag, so let's see if we need to fix it -->
{% if headerLevel == 0 %}
<!-- Split up the node based on closing angle brackets and get the first one. -->
{% assign firstChunk = node | split: '>' | first %}
<!-- If the first chunk does NOT contain a '<', that means we've broken another HTML tag that starts with 'h' -->
{% unless firstChunk contains '<' %}
{% capture node %}<h{{ node }}{% endcapture %}
{% endunless %}
{% capture edited_headings %}{{ edited_headings }}{{ node }}{% endcapture %}
{% continue %}
{% endif %}
{% assign _workspace = node | split: '</h' %}
{% assign _idWorkspace = _workspace[0] | split: 'id="' %}
{% assign _idWorkspace = _idWorkspace[1] | split: '"' %}
{% assign html_id = _idWorkspace[0] %}
{% capture _hAttrToStrip %}{{ _workspace[0] | split: '>' | first }}>{% endcapture %}
{% assign header = _workspace[0] | replace: _hAttrToStrip, '' %}
<!-- Build the anchor to inject for our heading -->
{% capture anchor %}{% endcapture %}
{% if html_id and headerLevel >= minHeader and headerLevel <= maxHeader %}
{% capture anchor %}href="#{{ html_id }}"{% endcapture %}
{% if include.anchorClass %}
{% capture anchor %}{{ anchor }} class="{{ include.anchorClass }}"{% endcapture %}
{% endif %}
{% if include.anchorTitle %}
{% capture anchor %}{{ anchor }} title="{{ include.anchorTitle | replace: '%heading%', header }}"{% endcapture %}
{% endif %}
{% if include.anchorAttrs %}
{% capture anchor %}{{ anchor }} {{ include.anchorAttrs | replace: '%heading%', header }}{% endcapture %}
{% endif %}
{% capture anchor %}<a {{ anchor }}>{{ include.anchorBody | replace: '%heading%', header | default: '' }}</a>{% endcapture %}
<!-- In order to prevent adding extra space after a heading, we'll let the 'anchor' value contain it -->
{% if beforeHeading %}
{% capture anchor %}{{ anchor }} {% endcapture %}
{% else %}
{% capture anchor %} {{ anchor }}{% endcapture %}
{% endif %}
{% endif %}
{% capture new_heading %}
<h{{ _hAttrToStrip }}
{{ include.bodyPrefix }}
{% if beforeHeading %}
{{ anchor }}{{ header }}
{% else %}
{{ header }}{{ anchor }}
{% endif %}
{{ include.bodySuffix }}
</h{{ _workspace | last }}
{% endcapture %}
{% capture edited_headings %}{{ edited_headings }}{{ new_heading }}{% endcapture %}
{% endfor %}
{% endcapture %}{% assign headingsWorkspace = '' %}{{ edited_headings | strip }}

1
_includes/common-js.html Normal file
View File

@ -0,0 +1 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>

17
_includes/favicon.html Normal file
View File

@ -0,0 +1,17 @@
<link rel="apple-touch-icon" sizes="57x57" href="/assets/images/favicon/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/assets/images/favicon/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/assets/images/favicon/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/assets/images/favicon/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/assets/images/favicon/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/assets/images/favicon/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/assets/images/favicon/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/assets/images/favicon/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/assets/images/favicon/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="/assets/images/favicon/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/assets/images/favicon/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/images/favicon/favicon-16x16.png">
<link rel="manifest" href="/assets/images/favicon/manifest.json">
<meta name="msapplication-TileColor" content="{{ page.color | default: site.color }}">
<meta name="msapplication-TileImage" content="/assets/images/favicon/ms-icon-144x144.png">
<meta name="theme-color" content="{{ page.color | default: site.color }}">

16
_includes/footer.html Normal file
View File

@ -0,0 +1,16 @@
<footer class="bg-dark">
<div class="container">
<p class="text-light">
{{ site.data[page.lang].strings.by | replace: "$1", '<a href="https://github.com/DS-Homebrew/" class="link">DS-Homebrew</a>'}} •
<a href="https://discord.gg/yD3spjv" title="{{ site.data[page.lang].strings.discord-server }}" class="clean">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-discord" viewBox="0 0 16 16">
<path d="M6.552 6.712c-.456 0-.816.4-.816.888s.368.888.816.888c.456 0 .816-.4.816-.888.008-.488-.36-.888-.816-.888zm2.92 0c-.456 0-.816.4-.816.888s.368.888.816.888c.456 0 .816-.4.816-.888s-.36-.888-.816-.888z"/>
<path d="M13.36 0H2.64C1.736 0 1 .736 1 1.648v10.816c0 .912.736 1.648 1.64 1.648h9.072l-.424-1.48 1.024.952.968.896L15 16V1.648C15 .736 14.264 0 13.36 0zm-3.088 10.448s-.288-.344-.528-.648c1.048-.296 1.448-.952 1.448-.952-.328.216-.64.368-.92.472-.4.168-.784.28-1.16.344a5.604 5.604 0 0 1-2.072-.008 6.716 6.716 0 0 1-1.176-.344 4.688 4.688 0 0 1-.584-.272c-.024-.016-.048-.024-.072-.04-.016-.008-.024-.016-.032-.024-.144-.08-.224-.136-.224-.136s.384.64 1.4.944c-.24.304-.536.664-.536.664-1.768-.056-2.44-1.216-2.44-1.216 0-2.576 1.152-4.664 1.152-4.664 1.152-.864 2.248-.84 2.248-.84l.08.096c-1.44.416-2.104 1.048-2.104 1.048s.176-.096.472-.232c.856-.376 1.536-.48 1.816-.504.048-.008.088-.016.136-.016a6.521 6.521 0 0 1 4.024.752s-.632-.6-1.992-1.016l.112-.128s1.096-.024 2.248.84c0 0 1.152 2.088 1.152 4.664 0 0-.68 1.16-2.448 1.216z"/>
</svg>
</a>
<br>
{{ site.data[page.lang].strings.published-with | replace: "$1", site.repo }}
</p>
</div>
</footer>

20
_includes/head.html Normal file
View File

@ -0,0 +1,20 @@
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,maximum-scale=2">
<title>
{% if site.data[page.lang].strings.title != page.title %}
{{ page.title }} |
{% endif %}
{{ site.data[page.lang].strings.title }}
</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" media="screen" href="/assets/css/style.css">
{% include favicon.html %}
{% include seo.html %}
</head>

62
_includes/nav.html Normal file
View File

@ -0,0 +1,62 @@
<nav class="navbar navbar-expand-sm navbar-dark bg-primary">
<div class="container-fluid maxwidth">
<span class="navbar-brand">
<a class="navbar-brand mb-0 h1" href="{{ site.data[page.lang].nav[0].url }}">{{ site.data[page.lang].strings.title }}</a>
</span>
<button class="navbar-toggler mr-4" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav">
{% for item in site.data[page.lang].nav %}
{% if item.url %}
<li class="nav-item">
<a class="nav-link {% if item.title == page.title %} active {% endif %}" href="{{ item.url }}">{{ item.title }}</a>
</li>
{% endif %}
{% if item.items %}
<li class="nav-item dropdown">
<a class="nav-link
{% for entry in item.items %}
{% if entry.page_title == page.title %} active {% endif %}
{% endfor %}
dropdown-toggle" href="#" id="navbar-dropdown-menu-link-{{ item.title }}" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ item.title }}</a>
<div class="dropdown-menu hover-content" aria-labelledby="navbar-dropdown-menu-link-{{ item.title }}">
{% for entry in item.items %}
<a class="dropdown-item{% if entry.page_title == page.title %} active {% endif %}" href="{{ entry.url }}">{{ entry.title }}</a>
{% endfor %}
</div>
</li>
{% endif %}
{% endfor %}
<li class="nav-item">
<a class="nav-link" href="https://github.com/{{ page.repo | default: site.repo }}">{{ site.data[page.lang].strings.source}}</a>
</li>
</ul>
<div class="btn-group language-dropdown">
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-globe" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855A7.97 7.97 0 0 0 5.145 4H7.5V1.077zM4.09 4H2.255a7.025 7.025 0 0 1 3.072-2.472 6.7 6.7 0 0 0-.597.933c-.247.464-.462.98-.64 1.539zm-.582 3.5h-2.49c.062-.89.291-1.733.656-2.5H3.82a13.652 13.652 0 0 0-.312 2.5zM4.847 5H7.5v2.5H4.51A12.5 12.5 0 0 1 4.846 5zM8.5 5v2.5h2.99a12.495 12.495 0 0 0-.337-2.5H8.5zM4.51 8.5H7.5V11H4.847a12.5 12.5 0 0 1-.338-2.5zm3.99 0V11h2.653c.187-.765.306-1.608.338-2.5H8.5zM5.145 12H7.5v2.923c-.67-.204-1.335-.82-1.887-1.855A7.97 7.97 0 0 1 5.145 12zm.182 2.472a6.696 6.696 0 0 1-.597-.933A9.268 9.268 0 0 1 4.09 12H2.255a7.024 7.024 0 0 0 3.072 2.472zM3.82 11H1.674a6.958 6.958 0 0 1-.656-2.5h2.49c.03.877.138 1.718.312 2.5zm6.853 3.472A7.024 7.024 0 0 0 13.745 12H11.91a9.27 9.27 0 0 1-.64 1.539 6.688 6.688 0 0 1-.597.933zM8.5 12h2.355a7.967 7.967 0 0 1-.468 1.068c-.552 1.035-1.218 1.65-1.887 1.855V12zm3.68-1h2.146c.365-.767.594-1.61.656-2.5h-2.49a13.65 13.65 0 0 1-.312 2.5zm2.802-3.5h-2.49A13.65 13.65 0 0 0 12.18 5h2.146c.365.767.594 1.61.656 2.5zM11.27 2.461c.247.464.462.98.64 1.539h1.835a7.024 7.024 0 0 0-3.072-2.472c.218.284.418.598.597.933zM10.855 4H8.5V1.077c.67.204 1.335.82 1.887 1.855.173.324.33.682.468 1.068z"/>
</svg>
</button>
<ul class="dropdown-menu dropdown-menu-end-sm">
{% assign ref = page.url | split: page.lang | last %}
{% for collection in site.collections %}
{% for item in site[collection.label] %}
{% assign itemRef = item.url | split: item.lang | last %}
{% if itemRef == ref %}
<li><a class="dropdown-item{% if item.lang == page.lang %} active {% endif %}" href="{{ item.url }}">{{ site.lang-names[item.lang] }}</a></li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
</div>
</div>
</div>
<script>
/* Remove hover classes */
Array.from(document.getElementsByClassName("hover-content")).forEach(r => {
r.classList.remove("hover-content");
});
</script>
</nav>

16
_includes/seo.html Normal file
View File

@ -0,0 +1,16 @@
<link rel="canonical" href="{{ site.url | append: page.url }}" />
<meta name="description" content="{{ page.description | default: site.data[page.lang].strings.description | escape }}" />
<meta property="og:title" content="{{ page.title | default: site.data[page.lang].strings.title | escape }}" />
<meta property="og:locale" content="{{ page.lang | default: "en_US"}}" />
<meta property="og:url" content="{{ site.url | append: page.url }}" />
<meta property="og:site_name" content="{{ site.data[page.lang].strings.title | escape }}" />
<meta property="og:image" content="{{ page.image | default: site.image }}">
<meta property="og:description" content="{{ page.description | default: site.data[page.lang].strings.description | escape }}" />
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="{{ page.title | default: site.data[page.lang].strings.title | escape }}">
<meta name="twitter:description" content="{{ page.description | default: site.data[page.lang].strings.description | escape }}">
<meta name="twitter:image" content="{{ page.image | default: site.image }}">
<meta name="theme-color" content="{{ page.color | default: site.color }}"/>
<meta name="msapplication-navbutton-color" content="{{ page.color | default: site.color }}">
<meta name="twitter:widgets:link-color" content="{{ page.color | default: site.color }}">
<meta name="twitter:widgets:border-color" content="{{ page.color | default: site.color }}">

10
_layouts/compress.html Normal file
View File

@ -0,0 +1,10 @@
---
# Jekyll layout that compresses HTML
# v3.1.0
# http://jch.penibelst.de/
# © 20142015 Anatol Broder
# MIT License
---
{% capture _LINE_FEED %}
{% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment or site.compress_html.ignore.envs == "all" %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}</{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "<!-- -->" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "<pre" %}{% assign _content = "" %}{% for _pre_before in _pre_befores %}{% assign _pres = _pre_before | split: "</pre>" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "</pre>" %}<pre{{ _pres.first }}</pre>{% endif %}{% unless _pre_before contains "</pre>" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " <e;<e; </e>;</e>;</e> ;</e>" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %} <table id="compress_html_profile_{{ site.time | date: "%Y%m%d" }}" class="compress_html_profile"> <thead> <tr> <td>Step <td>Bytes <tbody> <tr> <td>raw <td>{{ content | size }}{% if _profile_endings %} <tr> <td>endings <td>{{ _profile_endings }}{% endif %}{% if _profile_startings %} <tr> <td>startings <td>{{ _profile_startings }}{% endif %}{% if _profile_comments %} <tr> <td>comments <td>{{ _profile_comments }}{% endif %}{% if _profile_collapse %} <tr> <td>collapse <td>{{ _profile_collapse }}{% endif %}{% if _profile_clippings %} <tr> <td>clippings <td>{{ _profile_clippings }}{% endif %} </table>{% endif %}{% endif %}

29
_layouts/default.html Normal file
View File

@ -0,0 +1,29 @@
---
layout: compress
---
<!DOCTYPE html>
<html lang="{{ page.lang | default: "en-US" }}">
{% include head.html%}
<body>
<div class="content">
{% include nav.html %}
<main>
<div class="container-fluid">
<div class="row pt-5">
<div class="col-sm-2"></div>
<div class="col-sm-8">
{% include anchor-headings.html html=content anchorBody="<small>#</small>" anchorClass="header-anchor" %}
</div>
</div>
</div>
</main>
</div>
{% include footer.html %}
{% include common-js.html %}
</body>
</html>

63
_layouts/wiki.html Normal file
View File

@ -0,0 +1,63 @@
---
layout: compress
---
<!DOCTYPE html>
<html lang="{{ page.lang | default: "en-US" }}">
{% include head.html%}
<body>
<div class="content">
{% include nav.html %}
<main>
<div class="container-fluid">
<div class="row pt-5">
<div class="col-md-1"></div>
<div class="col-md-3">
{% assign items = site[page.collection] | where: "section", page.section | sort: "category" %}
<ul class="list-unstyled">
<!-- First check for index -->
{% for item in items %}
{% if item.url contains "index.html" %}
<li {% unless item contains category %}class="li-bullet"{% endunless %}><a href="{{ item.url }}">{{ item.title }}</a></li>
{% endif %}
{% endfor %}
{% for item in items %}
{% unless item.url contains "index.html" %}
{% if item.category and category != item.category %}
{% if category %}
</ul>
</li>
</details>
{% endif %}
{% assign category = item.category %}
<li>
<details {% if page.category == category %}open{% endif %}>
<summary>{{ category }}</summary>
<ul>
{% endif %}
<li {% unless item contains category %}class="li-bullet"{% endunless %}><a href="{{ item.url }}">{{ item.title }}</a></li>
{% endunless %}
{% endfor %}
{% if category %}
</ul>
</details>
{% endif %}
<div class="d-md-none"><hr></div>
</div>
<div class="col-md-7">
<h1>{{ page.title }}</h1>
<hr>
{% include anchor-headings.html html=content anchorBody="<small>#</small>" anchorClass="header-anchor" %}
</div>
</div>
</div>
</main>
</div>
{% include footer.html %}
{% include common-js.html %}
</body>
</html>

35
assets/css/dark.scss Executable file
View File

@ -0,0 +1,35 @@
---
---
:root {
// Main contents
--main-bg: #333;
--main-color: #ccc;
--header-color: #ddd;
--borders: #555;
--blockquote-color: #999;
--code-bg: #3f3f3f;
--code-color: #ddd;
--a-color: #0366d6;
--small-color: gray;
--carousel-caption-bg: #333b;
--table-alt-bg: #2a2a2a;
// Cards
--card-background: #444;
--card-edges-background: rgba(0, 0, 0, 0.15);
// Modal
--modal-borders: 1px solid rgba(0, 0, 0, 0.2);
// Nav
--nav-link-color: rgba(255, 255, 255, 0.7);
--nav-link-color-hover: rgba(255, 255, 255, 0.5);
--nav-link-color-active: rgba(255, 255, 255, 1);
--dropdown-item-bg-hover: rgba(0, 0, 0, 0.3);
--primary: {{ page.color | default: site.color }};
--dark: #f8f9fa;
--light: #3f3f3f;
--light-border: #292929;
--light-placeholder: #999;
}

43
assets/css/light.scss Executable file
View File

@ -0,0 +1,43 @@
---
---
:root {
// Main contents
--main-bg: #fff;
--main-color: #222;
--header-color: #222;
--borders: #bbb;
--blockquote-color: #666;
--code-bg: #e9e9e9;
--code-color: #333;
--a-color: #0366d6;
--small-color: gray;
--carousel-caption-bg: #fffb;
--table-alt-bg: #f0f0f0;
// Cards
--card-background: var(--main-bg);
--card-edges-background: rgba(0,0,0,.03);
// Modal
--modal-borders: 1px solid #dee2e6;
// Nav
--nav-link-color: rgba(255, 255, 255, 0.7);
--nav-link-color-hover: rgba(255, 255, 255, 0.5);
--nav-link-color-active: rgba(255, 255, 255, 1);
--dropdown-item-bg-hover: rgba(0, 0, 0, 0.3);
--primary: {{ page.color | default: site.color }};
--dark: #343a40;
--light: #f8f9fa;
--light-border: #ced4da;
--light-placeholder: darkgray;
}
.carousel-dark-when-light .carousel-control-next-icon, .carousel-dark-when-light .carousel-control-prev-icon {
filter: invert(1) grayscale(100);
}
.carousel-dark-when-light .carousel-indicators li {
background-color: #000;
}

368
assets/css/style.scss Normal file
View File

@ -0,0 +1,368 @@
---
---
@import url("light.css");
@import url("dark.css") (prefers-color-scheme: dark);
// For the bottom aligned footer
html, body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
}
.content {
flex: 1 0 auto;
}
footer {
flex-shrink: 0;
padding-top: 20px;
}
body {
color: var(--main-color);
background-color: var(--main-bg);
}
h1, h2, h3, h4, h5, h6 {
color: var(--header-color);
}
h2 {
border-bottom: 1px solid var(--borders);
}
blockquote {
color: var(--blockquote-color);
margin-bottom: 20px;
padding: 0 0 0 20px;
border-left: 3px solid var(--borders);
}
code {
color: var(--code-color);
background-color: var(--code-bg);
padding: 3px;
border-radius: 0.25rem;
}
// .a is for making other things look like <a>s
a, .a {
text-decoration: none;
text-decoration-thickness: 1px;
color: var(--a-color);
cursor: pointer;
}
a:hover, .a:hover {
text-decoration: underline;
}
a.clean {
text-decoration: none;
}
footer a {
color: inherit;
font-weight: bold;
text-decoration: underline;
}
footer a:hover {
color: inherit;
opacity: 50%;
}
small {
font-size: 75%;
color: var(--small-color);
}
img {
max-width: 100%;
height: auto;
}
.btn, .btn a {
text-decoration: none;
}
div .btn-primary:hover {
background-color: inherit;
opacity: inherit;
}
// Override bootstraps primary color
.bg-primary {
background-color: var(--primary)!important;
}
.btn-primary, .btn-primary:focus {
color: var(--nav-link-color);
background-color: var(--primary)!important;
border-color: var(--primary)!important;
}
.btn-primary:hover, .btn-primary:active {
color: var(--nav-link-color)!important;
opacity: 0.8;
}
.btn-outline-primary {
color: var(--primary);
border-color: var(--primary);
}
.btn-outline-primary:hover, .btn-outline-primary:active {
background-color: var(--primary)!important;
border-color: var(--primary)!important;
}
.text-primary {
background-color: var(--primary)!important;
}
// Override the secondary text color
.btn-outline-secondary {
color: var(--main-color);
}
.alert-secondary {
color: var(--code-color);
background-color: var(--code-bg);
border-color: var(--code-bg);
}
// Override the dark text too
.text-dark {
color: var(--dark)!important;
}
// And the light bg
.bg-light {
background-color: var(--light)!important;
border-color: var(--light-border)!important;
}
.bg-light::placeholder {
color: var(--light-placeholder);
}
// No underline on navbar links
.navbar a {
text-decoration: none;
}
// Dim navbar-brand on hover
.navbar a.navbar-brand:hover {
opacity: 0.5;
}
// Override nav-link color
.navbar .nav-link {
color: var(--nav-link-color)!important;
}
.navbar .nav-link:hover {
color: var(--nav-link-color-hover)!important;
}
// And the active nav-link color
.navbar .nav-link.active {
color: var(--nav-link-color-active)!important;
}
.navbar .nav-link.active:hover {
color: var(--nav-link-color-hover)!important;
}
// Make dropdowns site-colored and animated
.dropdown-menu, .dropdown .hover-content {
background-color: var(--primary);
-webkit-transition: 300ms ease;
transition: 300ms ease;
display: block;
height: 0;
padding: 0;
overflow: hidden;
visibility: hidden;
line-height: 0;
margin: 0;
}
.dropdown .hover-content {
display: none;
}
.dropdown-menu.show, .dropdown:hover .hover-content {
display: block;
height: inherit;
line-height: inherit;
padding: 0.5rem 0;
visibility: visible;
}
.dropdown-item {
color: var(--nav-link-color);
}
.dropdown-item.active {
background-color: unset;
}
.dropdown-item:hover, .dropdown-item:active, .dropdown-item:focus {
background-color: var(--dropdown-item-bg-hover);
color: var(--nav-link-color-hover);
}
// Make images smaller
.img-small {
max-width: 250px;
max-height: 250px;
}
.btn-back {
position: absolute;
left: 5px;
margin: 5px 0;
font-size: 8pt;
padding: 5px;
z-index: 10;
}
// Input box
.input-group-text {
color: var(--light-placeholder);
background-color: var(--light);
border-color: var(--light-border);
}
.form-control, .form-control:focus, .form-control::placeholder {
color: var(--light-placeholder);
background-color: var(--light);
border-color: var(--light-border);
}
// Cards
.card {
background-color: inherit;
}
.card a {
text-decoration: none;
font-weight: normal;
}
.card:hover a h4 {
color: inherit;
}
.card-footer a {
text-decoration: underline;
}
.card-image {
max-height: 128px;
}
.card-image-header {
height: 145px;
display: flex;
align-items: center;
justify-content: center;
}
.card {
background-color: var(--card-background);
}
.card-header, .card-footer {
background-color: var(--card-edges-background);
}
.pointer {
cursor: pointer;
}
.qr-image {
border-radius: 1rem;
}
.modal-content {
background-color: var(--main-bg);
}
.modal-header {
border-bottom: var(--modal-borders);
}
.modal-footer {
border-top: var(--modal-borders);
}
.carousel-label {
background-color: var(--carousel-caption-bg);
border-radius: 10px;
}
.li-bullet {
list-style: disc;
margin-left: 1em;
}
// Hide header anchors unless hovering the header
.header-anchor {
text-decoration: none;
display: none;
}
h1:hover .header-anchor,
h2:hover .header-anchor,
h3:hover .header-anchor,
h4:hover .header-anchor,
h5:hover .header-anchor,
h6:hover .header-anchor {
display: inline;
text-decoration: none;
}
// Tables
table {
margin-bottom: 1em;
}
table th {
text-align: center;
}
table th, table td {
padding: 6px 13px;
border: 1px solid var(--borders);
}
table tr:nth-child(2n) {
background-color: var(--table-alt-bg);
}
@media only screen and (min-width: 576px) {
// Only right align language dropdown when sm+
.language-dropdown {
position: absolute;
right: 5px;
}
.dropdown-menu-end-sm {
--bs-position: end;
right: 0;
left: auto;
}
}
@media only screen and (min-width: 1024px) {
.main-content {
max-width: 1024px;
}
}
@media only screen and (min-width: 1200px) {
.main-content {
max-width: 1200px;
}
}
@media only screen and (min-width: 1600px) {
.main-content {
max-width: 75%;
}
}
@media only screen and (max-width: 757px) {
.dropdown-menu {
border: 0;
}
.dropdown-item {
font-weight: bold;
}
.dropdown-item:hover {
background-color: inherit;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -0,0 +1,41 @@
{
"name": "App",
"icons": [
{
"src": "\/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "\/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "\/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "\/android-icon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "\/android-icon-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "\/android-icon-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

19
assets/js/relativeTime.js Normal file
View File

@ -0,0 +1,19 @@
const lengths = [1, 60, 3600, 86400, 604800, 2592000, 31536000, Infinity];
const labels = ["", "second", "minute", "hour", "day", "week", "month", "year"];
function timeDifference(now, then) {
let dif = Math.round((now - then) / 1000);
for(let i in lengths) {
if(dif < lengths[i]) {
return Math.round(dif / lengths[i - 1]) + " " + labels[i] + (Math.round(dif / lengths[i - 1]) == 1 ? "" : "s") + " ago";
}
}
}
for(let i = 0; i < document.getElementsByTagName("time").length; i++) {
let elem = document.getElementsByTagName("time")[i];
let date = new Date(elem.dateTime);
elem.innerText = timeDifference(new Date(), date);
elem.title = date.toLocaleString();
}

12
assets/js/rescript.js Normal file
View File

@ -0,0 +1,12 @@
Array.from(document.getElementsByClassName("back-link")).forEach(r => {
if(window.history.length > 1)
r.href = "javascript:window.history.back()";
});
Array.from(document.getElementsByClassName("qr-link")).forEach(r => {
r.href = "javascript:void(0);";
});
Array.from(document.getElementsByClassName("script-show")).forEach(r => {
r.classList.remove("d-none");
});

11
assets/js/search.js Normal file
View File

@ -0,0 +1,11 @@
let item
function search(query) {
Array.from(document.getElementById("card-container").children).forEach(function(r) {
let card = r.children[0];
for(let item in card.dataset) {
if(card.dataset[item].toLowerCase().includes(query.toLowerCase()))
return r.classList.remove("d-none");
}
r.classList.add("d-none");
});
}

37
assets/js/sort.js Normal file
View File

@ -0,0 +1,37 @@
if(!localStorage.sortDirection)
localStorage.sortDirection = 1;
if(!localStorage.sortProp)
localStorage.sortProp = "updated";
document.getElementById("sort-" + localStorage.sortProp).classList.add("btn-secondary");
document.getElementById("sort-" + localStorage.sortProp).classList.remove("btn-outline-secondary");
document.getElementById("sort-direction").innerText = parseInt(localStorage.sortDirection) ? "Descending" : "Ascending";
sort();
function toggleSortDirection() {
localStorage.sortDirection ^= 1;
document.getElementById("sort-direction").innerText = parseInt(localStorage.sortDirection) ? "Descending" : "Ascending";
sort();
}
function sort(prop) {
if(prop) {
document.getElementById("sort-" + prop).classList.remove("btn-outline-secondary");
document.getElementById("sort-" + prop).classList.add("btn-secondary");
document.getElementById("sort-" + localStorage.sortProp).classList.add("btn-outline-secondary");
document.getElementById("sort-" + localStorage.sortProp).classList.remove("btn-secondary");
localStorage.sortProp = prop;
}
let sorted = Array.from(document.getElementsByClassName("card")).sort(function(l, r) {
return ((l.dataset[localStorage.sortProp].toLowerCase() < r.dataset[localStorage.sortProp].toLowerCase()) ^ localStorage.sortDirection) ? -1 : 1;
});
let container = document.getElementById("card-container");
container.innerHTML = "";
sorted.forEach(function(r) {
let col = document.createElement("div");
col.classList = "col mb-3";
col.appendChild(r);
container.appendChild(col);
});
}

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,46 @@
---
lang: en-US
layout: wiki
section: ds-index
title: Nintendo DSi / Nintendo 3DS TWL_FIRM
description: The complete guide to modding the Nintendo DS
---
### Setting-up CFW
While most of the benefits of Custom Firmware are for the Nintendo DSi and the Nintendo 3DS family of systems, it allows you to unlock your consoles possibilities. Installing Custom Firmware is quite easy, and in most cases, all you need is a (micro)SD Card. We have the best of guides for you to follow, with step-by-step instructions.
- [3DS Hacking Guide](https://3ds.hacks.guide)
- Lightning command: `mod 3ds`
- Kuriisu command: `guide 3ds`
- [DSi Hacking Guide](https://dsi.cfw.guide)
- Lightning command: `mod dsi cfw`
- Kuriisu command: `guide dsi`
### CPU Speeds
The Nintendo DS shipped with a 67Mhz processor in 2004. The Nintendo DSi shipped with an 133Mhz processor in 2009. Most games of the Nintendo DS library were made before the Nintendo DSi came out, and as such the only processor available to them was 67Mhz. Some applications tied themselves to that clock speed and as a result, would not work well with a higher clock speed. Most games, however, would outperform the original with a higher clock speed.
nds-bootstrap has TWL Clock Speed as an option, but it will not try to adjust the ROM to work with the higher clock speed. That's on the application itself, and applications not working with a higher clock speed is NOT a bug on the nds-bootstrap end.
### Nintendo DSi System Menu
The Nintendo DSi System Menu uses a signed 32-bit integer to determine the free space on the NAND. Using the actual NAND, amount will never go above 128 MB so it was safe. However, when we redirect the NAND to the SD Card, it goes above the 32-bit integer limit, which makes it overflow to a negative number. The negative number of free space will unfortunately cause an "An error has occurred" error message, not letting you boot into the menu. Fortunately, this can be fixed by making a dummy file to put it in a positive number.
The positive and negative numbers are determined by pairs of two. For example, 1-2 GB of free space is allowed while 3-4 isn't. 5-6 GB of free space is allowed while 7-8 isn't.
In version 1.4.0, RSA signatures in the DS Cart Whitelist aren't verified.there is an exploit regarding a vulnerability in the Nintendo DSi Flashcart whitelist that allows you to take access over the ARM9 processor, It requires version 1.4.0 (it was patched in future versions and didn't exist in prior versions) and a flashcart with a modified ROM
### Nintendo DSi Slot-1 Access & Blockout
Slot-1 access is blocked when launching applications from the System Menu, except if said applications is either the Slot-1 launcher itself or System Settings. In order to launch normally unlaunchable slot-1 cartridges, you'll need to either make a System Settings exploit or install Unlaunch. Without either of those, you cannot launch unlaunchable flashcarts and you cannot dump ROMs to your SD card.
The flashcart white list is checked via RSA signatures are contained via RSA keys on every firmware expect 1.4.0. This means that people can white list their own carts
Before 1.4.0, the white list used to contain only two sections. In 1.4.0, they've introduced a third section which was made to block flashcarts that got around the first two. The third section loads up to eight different section of the rom and checks them with a hash to see if the rom has been tampered with. However, due to the forgetfullness of putting any sanity check, we can overflow into the exception vector/interrupt address using a large enough value. Best of all, this runs on ARM7 (aka the security processor) so this makes it the first exploit for the ARM7 processor. Since this happens before the lock out of the SFCG registers, we could run advanced homebrew (such as Slot-1 dumpers & external slot-1 dumpers)
Unfortunately, the requirements are tight. It requires version 1.4.0 and a flashcart with a modified ROM. Also, the expoit never officially came out, due to Unlaunch being much simpler to install and having less requirements (just a way to get into homebrew) with the same advantages.
### Nintendo DSi Camera
The Nintendo DSi Camera application has the ability to take pictures in the JPEG and save them to either the System Memory or the SD card. The way it's loaded restricts it to only DSi made images, due to lacking the proper HMAC stored inside a custom EXIF tag. Any custom images are not readable on the DSi, wther its PC taken or PC edited.
A `pit.bin` file is used in order to load images. However, the header size at offset 0x16 is unchecked, so a big enough header size value can exceed boundaries and cause the buffer to overwrite and jump to unsigned code. This is how Memory Pit is powered.
### Nintendo DSi Bootstage 2
The second bootstage of the Nintendo DSi loads launcher's "title.tmd" into memory. However, they do not specify a filesize limit check, meaning that the first 80k bytes are loaded into RAM while the rest can be a custom payload. This is the basis of Unlaunch exploit.

View File

@ -0,0 +1,14 @@
---
lang: en-US
layout: wiki
section: ds-index
title: Hardmod
description: The complete guide to modding the Nintendo DS
---
Hardmodding is when you physically solder the motherboard of the Nintendo DSi to an SD card adapter in order to be read on a computer. This is useful for restoring NAND backups, viewing NAND on your PC, etc...
### Nintendo DS
![](https://media.discordapp.net/attachments/547986366357700620/736370094392999947/mobo_pinout.png?width=893&height=603)
### Nintendo DSi
Follow the "Hardware NAND Mod Guide" and "Decrypting your NAND" of [this](https://gbatemp.net/threads/dsi-downgrading-the-complete-guide.393682/) guide

View File

@ -0,0 +1,45 @@
---
lang: en-US
layout: wiki
section: ds-index
title: Homebrew
description: The complete guide to modding the Nintendo DS
---
### Development
Developing Nintendo DS Homebrew typically uses devKitPro tools, such as devKitARM, libnds, and libfat. However, there is the possibility to branch out and use alternative software:
- **SD Card libraries:** devKitPro recommends libfat. We recommend using libslim instead, as it allows usage of different partitions, quicker speeds and non-blocking.
- **Graphic Library:** We recommend using easyGL2D, which comes shipped with libnds. However, you could use NightFox Lib.
- **Entire Toolchains:** We recommend using devKitARM and libnds, as it includes DSi compatibility and has a larger ecosystem. However, if your target is exclusively flashcarts on a Nintendo DS, feel free to use ToolchainGenericDS.
### Flashcards
DS mode flashcards are a slot-1 method of running Nintendo DS applications. Flashcarts have the advantages of keeping console files and portable files separate, the ability to be used without modding your system and are usable on DS Phat/Lite consoles. However, unlike modding the actual console, there are multiple flashcarts on the market, each with different kernel requirements. The kernel you use is the most important.
[There is a **work in progress** flashcart index](https://nightyoshi370.github.io/mm-github-pages-starter/), which has kernels, firmware, reviews and purchase links.
### DLDI
Different SD card slots have different hardware (most of the time) and code written for one card won't necessarily work for another card. DLDI (short for Dynamically Linked Device Interface) attempts to solve this by having the SD card handling code patched in externally. Loaders like YSMenu, Wood R4 and TWiLight Menu++ can automatically DLDI patch a homebrew, but if you need to manually patch it in, feel free to use a [DLDI Patcher](https://www.chishm.com/DLDI#tools) depending on your device.
### Time Bomb
A time bomb is a expiration date on flashcart kernels that manufacturers use to force users to buy a new card. Once your system clock goes beyond a certain date, the kernel will refuse to boot past the expiration screen. Thankfully, a flag is not set anywhere and it's handled in the flashcart firmware, giving us two options for work arounds:
- Since it relies on the system clock, you could set back the date. This will break any game that uses your system clock, but it will allow you to use the default kernel.
- Since it relies on the kernel and not the firmware, you could switch to an alternative kernel. There are two options available:
- [YSmenu](https://gbatemp.net/threads/retrogamefan-updates-releases.267243/) -- The menu is quite ugly and only displays `.nds` files, but it has far better game support, cheat support and no memory pak requirement.
- [TWiLight Menu++](https://github.com/DS-Homebrew/TWiLightMenu) with B4DS -- This is useful if you'd like to have all your ROMs in the same menu that you could launch NES, GBA and other console titles too. However, it does require a Memory Expansion Pak for extended game compatibility and does not support cheats.
We recommend YSMenu due to the higher compatibility, cheats and lack of need for a Memory Expansion Pak. If you want to setup YSMenu, DeadSkullzJr has made a [Dropbox repo](https://www.dropbox.com/sh/egadrhxj8gimu5t/AACv2KqWmeXEHkxoYRluobxha?dl=0) with all the primary boot kernels set up for your flashcart. All it requires is a drag and drop to your SD card root and you have completed.
- You could still lanuch into TWiLight Menu++ for an all-in-one menu for emulators, but you can't launch into YSMenu from TWiLight Menu++.
In order to test whether your flashcart has a timebomb, set the date on your system to the latest value possible and launch the flashcart.
### ARGV Support
ARGV is an information transmitter between two homebrew Nintendo DS applications. It could be used for forwarders or alternative menus.
- The homebrew needs to be programmed in order to take advantage of it. For example, GBARunner2, NesDS and GameYob all have ARGV implementation
- There also needs to have a way to set the ARGV variables. TWiLight Menu++ and HBMenu allow setting ARGV arguments

View File

@ -0,0 +1,11 @@
---
lang: en-US
layout: wiki
section: ds-index
title: Nintendo DS Modding Index
description: The complete guide to modding the Nintendo DS
---
Welcome to the resources for Nintendo DS modding. This will attempt to explain most things related to Nintendo DS modding as well as be a basic introduction to the NTR firmware of the Nintendo DS, the TWL firmware of the Nintendo DSi and TWL_FIRM of the Nintendo 3DS
If you need help, ask the <a href="https://discord.gg/yD3spjv">DS<sup>(i)</sup> Mode Hacking!</a> Discord server.'

View File

@ -0,0 +1,73 @@
---
lang: en-US
layout: wiki
section: ds-index
title: Retail ROMs
description: The complete guide to modding the Nintendo DS
---
### Anti-Piracy
AP (short for anti-piracy) is a method used by developers to enforce legitimate purchases and prevent piracy. This can be circumvented either from the loader or the ROM itself.
- For nds-bootstrap's purposes, you could load a `.IPS` file in order to circumvent said patches. This `.IPS` file will be patched inside nds-bootstrap, so you could keep the ROM files intact. A pack of `.IPS` files are automatically included with TWiLight Menu++.
- For Wood R4 purposes, these patches are included in the software itself. You will not need to modify the ROM itself.
In case there isn't a `.IPS` file for your ROM or your software didn't patch your ROM, you could try directly modifying the ROM itself using [nds-scene tool](https://gbatemp.net/download/retrogamefan-nds-rom-tool-v1-0_b1215.35735/)
### CloneBoot
Cloneboot is when a game sends it's own loaded arm9/arm7 binary to another console. It is used for DS Download Play, for single-card multiplayer. Not all games that have single-card multiplayer uses cloneboot though.
Currently, nds-bootstrap's cloneboot patches is broken due to arm9/7 binaries being patched, which makes the RSA signatures invalid.
### Thumb instructions
Instead of the 32-bit regular ARM instructions, THUMB use 16-bit instructions. This is useful when memory bandwidth is a bottleneck.
### Save Files
Nintendo DS cartridges have 4 known save types:
- EEPROM - Electrically Erasable Programmable Read-Only Memory
- FLASH
- FRAM - Ferroelectric Random-Access Memory
- NAND - NOT-AND
Though rare, there are DS Cartridges with NAND based saves: WarioWare DIY & Jam with the Band (USA)/Daigasso Band Brothers
There are different formats to use depending on the loader, but nds-bootstrap uses the raw `.sav` format. If you use a different format, here is a website you can use to convert it: http://www.shunyweb.info/convert.php
### Card Read DMA
Card DMA (stands for Direct Memory Access) is a more efficient way to read catridge data than by software. When there isn't any data available, code can still execute. In software catridge data reads, polling the register to see if there is new data wastes times. It is the preferred way of accessing data.
You can spot a game that uses dma via no$gba by enabling the DMA log on ARM9. A DMA access to the card uses AF000001 as the third parameter.
- For example: `DMA2: 04100010 023C18C0 AF000001`
### Donor ROM
In previous nds-bootstrap versions, a Mario Kart DS ROM was needed for SDK3-4 games to work or save.
The ROM acted as a Donor ROM. nds-bootstrap grabs the donor's arm7 binary, replacing the original ROM's arm7 binary, in order for the save patches to work, and there was a few side effects as a result.
In later nds-bootstrap versions, a Donor ROM is needed for certain THUMB or SDK5 games to boot, as well as save.
### Action Replay Cheats
Action Replay cheat codes are codes that allow you to make low-level programmable changes in the memory region of your favorite game(s). These changes range from simple value tweaks to extremely advanced ASM tweaks, both of which could alter the experience of the game(s) being played altogether.
Flashcarts can take advantage of cheat codes by using cheat databases. Cheat functionality is integrated within the flashcart kernel respectively. The following kernels can utilize cheats:
- Wood R4 (`usrcheat.dat`)
- YSMenu (`usrcheat.dat`)
Homebrew/digital based solutions can also take advantage of the cheat databases, the software currently available can use the following:
- NitroHax (`cheats.xml`)
- The engine used here loads the entire cheats.xml database into the Nintendo DS's limited RAM and trys to manage things from there. This imposes a serious limit on how many cheats you can have, as NitroHax will not load a cheats.xml file past 2.4 MB
- TWiLight Menu++ (`usrcheat.dat`)
- TWiLight Menu++ reads the `usrcheat.dat` and sends off the enabled cheat values to another file, which nds-bootstrap picks up
- The cheat engine used in nds-bootstrap is based on the one used in NitroHax. However, due to the cheat file containing only enabled cheats for that specific title, the cheats file does not have a real limit.
- Bootstrap 4 DS (aka the nds-bootstrap version used on flashcarts) does not support cheats, due to not having enough RAM and the limitations of the Memory Expansion Pack.
For the most complete cheat database, we recommend using the one made by DeadSkullzJr titled [DeadSkullzJr's Cheat Database](https://gbatemp.net/threads/deadskullzjrs-nds-cheat-databases.488711/page-38#post-9090779)
Cheat codes generally have types A through E, and here is a description of them:
- The 0xE code type is a 32-bit code type that allows you to make multiple writes in many consecutives addresses all at once. Essentially, it is like the basic 32-bit RAM write code type (0x0), except this doesn't have addresses listed next the the values you want to write. Instead, the 0xE code type is programmed to automatically branch from a starting address, then determine the addresses to write to. From there, you just have to tack in the amount to write to in order for it to do the job.
Credits: (`DeadSkullzJr`)

View File

@ -0,0 +1,24 @@
---
lang: en-US
layout: wiki
section: ds-index
title: Wi-Fi
description: The complete guide to modding the Nintendo DS
---
- On Nintendo DS applications, you could only use WEP and Open WiFi
- On Nintendo DSi enhanced/exclusive applications, you have the addition of WPA2 support.
Hotspots are usable, so you don't need to change your router configuration
### Nintendo DS WFC Restoration
1. Launch the Nintendo WFC settings.
2. Connect to your access point.
3. Set your Primary DNS value as one of the values below, depending on which service you want to use.
* **Wiimmfi** - `164.132.44.106`
* **AltWFC/WFCZwei** - `172.104.88.237` or `104.131.93.87`
* **BenFi** - `24.218.177.103`
* **Twilit WFC** - `34.66.49.81`
4. Set `1.1.1.1` as your secondary DNS.
5. You might need to NoSSL patch your game at this point, depending on the game.

9
pages/_en-US/index.md Normal file
View File

@ -0,0 +1,9 @@
---
lang: en-US
layout: default
title: Home
---
# Welcome to the DS-Homebrew Wiki!
TODO: Write an index page... ;P

View File

@ -0,0 +1,27 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Creating RAM Disks
category: Other
---
NOTE: You do not need to follow this if you're using a flashcard.
To make a RAM disk, download [this](http://memory.dataram.com/products-and-services/software/ramdisk#freeware) tool (click `Download Software`), and follow the instructions below.
Instructions by @Dakkon7, modified by me:
1. Run RAMDisk
1. Click **View** -> **Advanced**
1. For **Disk Size**, type `12` for DSi, or `28` for 3DS, above **Max 1023 MB**.
1. Un-mark **Create TEMP Directory**, if it's already marked.
1. Click **Load/Save**
1. Click `Start RAMDisk`, and a new window for your .img should appear.
1. Place any file and/or folder the homebrew expects there, and/or file(s) you want to use.
1. In the RAMDisk program, click `Save Disk Image Now`.
1. Save `romname.img` to a folder called `ramdisks` in the .nds file location.
1. Click `Stop RAMDisk` when you're done.
1. In TWiLight Menu++, open per-game settings for your homebrew.
1. Set RAM disk to 0.
1. Launch your homebrew, and it should read your RAM disk.

View File

@ -0,0 +1,18 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Custom Boot Splashes
category: Customization
---
You can use custom GIF files to have custom splash screens while booting TWiLight Menu++. They need to be named `splashtop.gif` and `splashbottom.gif` and be in `sd:/_nds/TWiLightMenu/extras`, then set `DSi Splash Screen` to `Custom` in TWiLight Menu++ settings.
Most GIF files up to 256x192 should work, with a few exceptions:
- GIF files over 1MiB (DSi Mode) or 256KiB (DS Mode) may not play at full speed as they will be decompressed on the fly
- Between the two, the GIFs must be less than about 10MB (DSi Mode) or about 2MB (DS Mode)
- If both GIFs are set to loop forever then they will show for 3 seconds, so set a loop count on at least one to control the time
- The user input flag is supported so set it and a long delay on a frame if you want to show a splash and wait like the defaults
- Only the GIF waiting for input will be paused, so the other can continue animating
- If using Local Color Tables the whole frame must be overwritten as it will replace the whole screen's palette, not just the current frame
- Interlaced and text frames will not work

View File

@ -0,0 +1,51 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: DSi / 3DS skins - Custom SFX
category: Customization
---
TWiLightMenu supports custom sound files in themes. Place your sound files under the `sound` subdirectory in your theme folder, for example for the `white` theme, you would place the files at `themes/white/sound/sfx.bin` and `themes/sound/bgm.pcm.raw` respectively. Both files are optional, if one is missing the default music will be used. You should then also set the music option in settings to "Theme".
These instructions assume you have devkitPro installed with mmutil. You can get devkitPro at the [devkitPro website](https://devkitpro.org/wiki/Getting_Started).
## Sound Effect Bank
The sound effect bank contains sound effects such as the icon select sound, etc.
|File |Description|
|----------|-----------|
|startup.wav|Played on startup. See the section on [Startup sound](#startup-sound) for more details|
|back.wav |Back |
|launch.wav|Played when launching a game|
|select.wav|Played when moving the select cursor|
|wrong.wav|Played when reaching the end of the page|
|switch.wav|Played when switching pages|
|stop.wav|Played on the DSi Theme when the select cursor stops moving|
|menu.wav|Not part of the soundbank. See the section on [Menu BGM](#menu-bgm) for more details|
You can then run `make` to make the sound effect bank. All files listed above, except *menu.wav* are required, but you can make them silent.
Your resulting *sfx.bin* **must be under 512000B = 512KB**. Any larger will result in either crashes or some sounds not playing fully.
### Startup sound
While the other sound effects will work with any WAV file, the startup sound must be in a specific format in order to work properly, otherwise there will be a gap between when the startup sound stops and the background music begins.
The startup.wav file must be **16-bit 16kHz**. You can use [Audacity](https://www.audacityteam.org/download/) for example to convert to this format. Once the file is loaded in Audacity, change the **Project Rate (Hz)** to **16000**, then press **Shift+M**, and change the **Format** to **16-bit PCM**.
If your file is in Stereo, you should also go to **Tracks > Mix > Mix Stereo down to Mono**.
You must set `PlayStartupJingle=1` in your `theme.ini` for the startup jingle to play.
## Menu BGM
To create custom menu BGM, you will need to install [SoX](https://sourceforge.net/projects/sox/files/sox/14.4.2/sox-14.4.2-win32.exe/download).
Menu BGM is created from **menu.wav**, which must be **16-bit 16kHz Mono**. You can use [Audacity](https://www.audacityteam.org/download/) for example to convert to this format. Once the file is loaded in Audacity, change the **Project Rate (Hz)** to **16000**, then press **Shift+M**, and change the **Format** to **16-bit PCM**.
If your file is in Stereo, you should also go to **Tracks > Mix > Mix Stereo down to Mono**.
If SoX is installed, once you run `make`, you will get a `bgm.pcm.raw` file, that can be copied to the *sound* subfolder in your theme folder.
Unlike sfx.bin, *bgm.pcm.raw* can be arbitrarily large.

View File

@ -0,0 +1,134 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: How to create DSi / 3DS skins
category: Customization
---
The easiest way of customizing a theme is by editing the png textures in a theme's `ui`, `battery`, and/or `volume` folders. These files can be any png with one minor caveat in that only pixels that are 100% transparent will be rendered transparently, any other opacity will be drawn as fully opaque. Also, any part that is transparent in one of a set (ex. all the battery icons) should be transparent in all since transparent pixels are simply skipped rather than reverted to the background, so any part that is transparent in only some should have the background texture rather than transparency. These textures are allowed to vary in size, but may require tweaking of the theme configuration to render correctly (see below).
Changes to paletted textures are more involved. Within the `grit` and `background_grit` folders of a theme, the various image files may be edited. You will also require [devkitPro's toolchains](https://devkitpro.org) with GRIT installed. Once you have finished editing your files, you must run
```bash
$ make
```
in order to compile your themes into Grit RIFF Format. This will compile your paletted textures into **.grf** format in the `grf` folder. Do not make changes to the `.grit` files until you have read the advanced theming section below.
Be aware the paletted textures come with more restrictions than BMP textures, the primary being an absolute maximum of 16 colors per texture. However, some textures may have even tighter default palette restrictions, which can be modified at the risk of running out of palette memory (see below).
## Theme file descriptions
The `volume` and `battery` textures are self explanatory.
### Background textures (`background_grit` folder)
| Texture | Description |
| ---------------- | ------------------------------------------------------------------------------------------------- |
| bottom | The bottom background texture when not hovering over an icon |
| bottom_bubble | The bottom background texture when hovering over an icon |
| bottom_ds | For the 3DS theme, the bottom background texture when not hovering over an icon when on a DS lite |
| bottom_bubble_ds | For the 3DS theme, the bottom background texture when hovering over an icon when on a DS lite |
| top | The top background |
### Paletted textures (`grit` folder)
| Texture | Description | Palette Restrictions (if less than 16) |
| ------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| bips | The bips displayed on the bottom of the scrollbar (DSi Theme) | |
| box | The box texture, containing both full and empty textures (for DSi Theme) | |
| box_empty | The texture displayed for an empty box (3DS Theme) | On the 3DS theme, the transparent color is `#E0DAD9` by default |
| box_full | The texture displayed for a box with an icon (3DS Theme) | On the 3DS theme, the transparent color is `#E0DAD9` by default |
| brace | The brace texture shown past the first and last icon (DSi theme) | 4 Colors |
| bubble | The bottom bit of the bubble that draws over the start border or icon box | 8 Colors |
| button_arrow | The textures for the arrows on either side of bottom scrollbar (DSi Theme) | |
| cornerbutton | The buttons that are displayed on the SELECT menu (DSi Menu) (The name is based on an old use) | |
| cursor | The border with animation frames that indicate the selected icon (3DS Theme) | |
| dialogbox | The background of the dialog box that slides down | |
| folder | The icon for folders | |
| icon_gb | The icon for Game Boy games | |
| icon_gba | The icon for GBA games (All themes) and the top icon to launch GBARunner2 (3DS Theme) | The default transparent color is `#00FF00` |
| icon_gbamode | The icon for native GBA Mode | |
| icon_gg | The icon for Game Gear games | |
| icon_manual | The icon for the manual | |
| icon_md | The icon for Mega Drive games | |
| icon_nes | The icon for NES games | |
| icon_plg | The icon for DSTWO plugins | |
| icon_settings | The icon for Nintendo DSi Settings | |
| icon_sms | The icon for Sega Master System games | |
| icon_snes | The icon for SNES games | |
| icon_unk | The icon displayed when a game is missing an icon | |
| launch_dot | The dots displayed when a game is launched (DSi Theme) | |
| moving_arrow | The arrow displayed when a game is being moved (DSi Theme) | |
| progress | The progress loading animation with 8 frames | 9 Colors |
| scroll_window | The part of the scrollbar that indicates the icons that are in view | 7 Colors |
| small_cart | The icons displayed along the top (3DS Theme) and in the SELECT menu (DSi Theme) | |
| start_border | The border with animation frames that indicates the selected icon (DSi Theme) | |
| start_text | The text displayed for the start border on the (DSi Theme) | 4 Colors |
| wirelessicons | The icons displayed to indicate a game has wireless support | 7 Colors |
### UI textures (`ui` folder)
| Texture | Description |
| ---------------- | --------------------------------------------------------|
| date_time_font | The font to display the date and time |
| Lshoulder | The left shoulder |
| Lshoulder_greyed | The left shoulder when there are no pages to the left |
| Rshoulder | The right shoulder |
| Rshoulder_greyed | The right shoulder when there are no pages to the right |
### Video texture (`video` folder)
`3dsRotatingCubes.rvid` is a Rocket Video file. For more information on converting videos to rvid, read [Converting a video to .rvid](https://github.com/RocketRobz/Vid2RVID/wiki/Converting-a-video-to-.rvid) on the Vid2RVID wiki. If you don't want this to be drawn you can simply delete it.
### Fonts (`font` folder)
You can add custom fonts in NFTR (Nitro FonT Resource) format, these are not in the example themes, but you can download the default fonts from [here](https://github.com/DS-Homebrew/TWiLightMenu/tree/master/romsel_dsimenutheme/nitrofiles/graphics/font). One utility you can use to edit NFTR files is Pk11's [nftr-editor](https://pk11.us/nftr-editor/) (works in any modern browser).
| File | Description |
| ---------- | ----------------------------------------- |
| large.nftr | The large font used for titles |
| small.nftr | The smaller font used for most other text |
## Theme configuration
You may configure various options on how the theme is drawn in the `theme.ini` to accommodate larger sprites or textures.
| Value | Description | Default (3DS) | Default (DSi) |
| ------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------- | ------------- |
| `StartBorderRenderY` | The initial Y position of the Start Border | 92 | 81 |
| `StartBorderSpriteW` | The width of the start border sprite. Note that the start border texture is exactly half of the full border. | 32 | 32 |
| `StartBorderSpriteH` | The height of the start border sprite | 64 | 80 |
| `TitleboxRenderY` | The initial Y position of the title text drawn | 96 | 85 |
| `BubbleTipRenderY` | The Y position of the tip of the bubble that is drawn over the start border | 98 | 80 |
| `BubbleTipRenderX` | The X position of the tip of the bubble that is drawn over the start border | 125 | 22 |
| `BubbleTipSpriteH` | The height of the bubble tip sprite | 7 | 8 |
| `BubbleTipSpriteW` | The width of the bubble tip sprite | 7 | 11 |
| `RotatingCubesRenderY` | The Y position on the top screen to draw the rotating cubes | 78 | N/A |
| `ShoulderLRenderY` | The Y position on the top screen to draw the left shoulder | 172 | 172 |
| `ShoulderLRenderX` | The X position on the top screen to draw the left shoulder | 0 | 0 |
| `ShoulderRRenderY` | The Y position on the top screen to draw the right shoulder | 172 | 172 |
| `ShoulderRRenderX` | The X position on the top screen to draw the right shoulder | 178 | 178 |
| `VolumeRenderX` | The X position on the top screen to draw the right shoulder | 4 | 4 |
| `VolumeRenderY` | The Y position on the top screen to draw the volume icon | 16 | 16 |
| `BatteryRenderY` | The Y position on the top screen to draw the battery icon | 5 | 5 |
| `BatteryRenderX` | The X position on the top screen to draw the battery icon | 235 | 235 |
| `RenderPhoto` | Whether or not to draw a photo on the top screen | 0 | 1 |
| `StartTextUserPalette` | Assign the DSi Profile Theme to the palette of the start text | N/A | 1 |
| `StartBorderUserPalette` | Assign the DSi Profile Theme Palette to the palette of the start border | N/A | 1 |
| `ButtonArrowUserPalette` | Assign the DSi Profile Theme Palette to the palette of the arrow buttons on the bottom of the screen | N/A | 1 |
| `MovingArrowUserPalette` | Assign the DSi Profile Theme Palette to the palette of the arrow shown when moving icons | N/A | 1 |
| `LaunchDotsUserPalette` | Assign the DSi Profile Theme Palette to the palette of the launch dots | N/A | 1 |
| `DialogBoxUserPalette` | Assign the DSi Profile Theme Palette to the palette of the dialog box | N/A | 1 |
## Advanced theming
Occasionally, you may require more than the default number of colors for some paletted textures. In such cases, you may modify the `.grit` compilation file for the texture to increase the size of the palette.
For example, in `scroll_window.grit`, you may edit `-pn7` and change `7` to `16` for 16 colors. Be aware that if you remove the entire `-pn` line, you may encounter unexpected results.
Also note that the absolute maximum of 16 colors per texture is enforced in code and can not be modified. Even if you increase the number of palettes to above 16, no more than 16 colors worth of palette data will be loaded. With the amount of textures loaded in, there may not be enough palette memory to hold 16 colors worth of palettes for every texture. Keep this in mind when adjusting palette sizes.
Additionally, paletted textures must have dimensions that are a multiple of 2. Paletted textures sizes can not be changed except for `bubble` and `start_border`, which can have configurable sprite dimensions in `theme.ini`. However, note that doing so may have unexpected consequences.
Paletted textures are not checked for validity. An invalid texture should be rare if created with the provided makefile, but in certain cases a corrupted texture will cause the menu to not load at all.
## Custom background music and sound fonts.
The DSi Menu and 3DS themes also support custom music. See [Adding custom music / SFX](Adding-custom-music-sfx) for more details.

View File

@ -0,0 +1,49 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Custom Unlaunch Backgrounds
category: Customization
---
Using TWiLight Menu++ you can patch the Unlaunch installer to have a custom background image. This needs to be a 256 x 192 GIF, with a few restrictions:
- Only the first frame will be shown, no animated backgrounds
- The file must be less than or equal to 15,472 bytes
- GIFs with more than 31 colors require specially made palettes to prevent breaking the text
### Installing
1. Copy the GIF file to `sd:/_nds/TWiLightMenu/unlaunch/backgrounds`
1. Download the [latest Unlaunch installer](https://problemkaputt.de/unlaunch.zip) and extract `UNLAUNCH.DSI` to your SD card
1. Open TWiLight Menu++ Settings, switch to the `Unlaunch settings` page, and click on `Background`, then select the one you want
1. Exit settings and launch `Unlaunch DSi Installer`
- It should use your custom image, if it does not then turn off your console and make sure your GIF conforms with the requirements above
1. Choose `Install Now`
### Using GIFs with more than 31 colors
As the GIF's palette is loaded to the same area of VRAM as the text palettes it will overwrite them if the palette gets too large, however this can be worked around by including the text palettes in the GIF's palettes. Using this with different colors would also let you have different text colors, should you want that. These instructions will be for [GIMP](https://gimp.org), but any image editor capable of rearranging the palette of an image will work.
1. Open your image in GIMP and make sure it's 256 x 192 pixels
1. In the menu bar at the top, select `Image` -> `Mode` -> `Indexed...`
1. Select `Generate optimum palette` and set the maximum colors to anything up to 226 colors
1. Select a dithering pattern from the `Color dithering` dropdown
- Images without dithering generally compress best, but with it will generally look better, try and see which looks best for the size
1. Click `Convert`
1. In the menu bar at the top, select `File` -> `Export As...`, give it a name with the extension `.gif`, and click `Export`
- If it gives any warnings, click the accept button
1. In the next popup, disable the `GIF comment` and click `Export`
1. Check the size of the exported file, if it's 15,472 bytes or less, then skip to step 13
1. If your GIF is too large, then using either [gifsicle](http://www.lcdf.org/gifsicle/) or [ezgif.com](https://ezgif.com/optimize) you can try optimizing it
- These instructions will use ezgif as its simpler, being a website
1. Open https://ezgif.com/optimize, and upload your GIF
1. Try different compression levels until you find the best one under 15,472 bytes (15.11KiB), ideally a bit under as GIMP may increase the size a bit
1. Save the optimized GIF and open it in GIMP
1. In the menu bar at the top, select `Windows` -> `Dockable Dialogs` -> `Colormap`
1. Change your current `Foreground color` to #080808 and add 14 new colors with the `+` button
- If your image doesn't have at least 133 colors you will also need to add filler colors to arrange the text colors in the correct spots
1. Right click a color in the Colormap and select `Rearrange Colormap...`
1. Arrange your new colors so they match these: (The 2nd and 3rd columns starting at index 49)<br>
![Palette with correct text colors](https://cdn.discordapp.com/attachments/614278143527878658/770777177904906240/unlaunch-palette.png)
1. Use the color picker to make your new colors match those in the above image
1. In the menu bar at the top, select `File` -> `Export As...`, give it a name with the extension `.gif`, and click `Export`
1. In the next popup, make sure `GIF comment` is off and click `Export`
1. Ensure the image is still under 15,472 bytes, if it's gotten too big then repeat from step 10 using a higher compression level
1. You're done! Follow the [installing](#installing) section above to use your image!

View File

@ -0,0 +1,26 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Download Play / Pictochat in DS Classic Menu
category: Other
---
If you're using a DSi console, you should already be able to launch those apps.
Otherwise, if you have a 3DS, proceed below.
In GodMode9:
- Press R+A on SYSNAND TWLN.
- Select `Search for titles`.
- Select `DS Download Play (NTR-HNDA).tmd`.
- Select `TMD file options...`.
- Select `Dump CXI/NDS file`.
- Done. It should be under `sdmc:/gm9/out/`, as `DS Download Play (NTR-HNDA).nds`.
Copy to `sd:/_nds/`, and rename to `dlplay.nds`.
The above steps will increase DLP boot speed.
To run Pictochat on 3DS (DSi required):
- Copy `pictochat.nds` from `sd:/_nds/` on the DSi SD card, on the 3DS SD card, also in `sd:/_nds/`.
You must first access the DS Classic Menu in TWiLight Menu++ on the DSi.

View File

@ -0,0 +1,40 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: FAQ & Troubleshooting
category: Other
---
For more FAQs, please visit the [GBAtemp thread](https://gbatemp.net/threads/ds-i-3ds-twilight-menu-gui-for-ds-i-games-and-ds-i-menu-replacement.472200/).
### Q: Why is my 3DS/2DS stuck on black screens when launching TWiLight Menu++, or why is my 3DS/2DS powering off when launching TWiLight Menu++?
A: TWL_FIRM might've somehow got corrupted.
Follow this guide to fix the issue: https://3ds.hacks.guide/troubleshooting#dsi--ds-functionality-is-broken-after-completing-the-guide
### Q: I get a white screen when booting TWiLight Menu++. How do I fix this?
A:
- First, try putting the console in sleep mode (e.g. closing the console's lid, or pressing the sleep button on the O2DS), then wake up the console from it.
- If that doesn't work, format your SD card to FAT32 with 32kb cluster/allocation size.
- If that also doesn't work, try a different SD card.
### Q: Why do I get a white screen when trying to load a game from SD Card?
A:
- First, check [the nds-bootstrap compatibility list](https://docs.google.com/spreadsheets/d/1LRTkXOUXraTMjg1eedz_f7b5jiuyMv2x6e_jY_nyHSc/htmlview#gid=0) and make sure your game is compatible.
- If the game that's attempted to be launched is a DSi Enhanced game, then make sure that TWiLight Menu++ is set to use `DS Mode`.
- If it worked before, delete the `fatTable` and `patchOffsetCache` folders in sd:/_nds/nds-bootstrap/
### Q: How do I use cheats?
A: You need to have a cheat DB in the form of a `usrcheat.dat` file in the `sd:/_nds/TWiLightMenu/extras/` folder. The most updated cheat database is [DeadSkullzJr's](https://gbatemp.net/threads/deadskullzjrs-flashcart-cheat-databases.488711/). Alternatively, you can use [r4cce](http://hp.vector.co.jp/authors/VA013928/soft_en.html) to create your own cheat DB.
### Q: How do I show a custom picture on the top screen of the DSi theme?
A: A random `.png` image in `sd:/_nds/TWiLightMenu/dsimenu/photos/` will be shown each time the menu is loaded.
- The file(s) must be no bigger than 208x156.
- If you have errors, it's most likely an error with the image size. Please use tinypng to reduce the size.
### Q: Why isn't touch input working on sudokuhax?
A: Depending on the save file of sudokuhax, the touch screen inputs may not work.
### Q: Can The Biggest Loser boot TWiLight Menu++?
A: No. As The Biggest Loser is a Slot-1 game, and not a DSiWare game, SD access is disabled when running Slot-1 cards.

View File

@ -0,0 +1,49 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: How to Get Box Art
category: Other
---
### 3DS
1. Install [KirovAir's TWiLight Menu++ Updater fork](https://github.com/KirovAir/TWiLightMenu-Updater/releases)
- This will replace the normal TWiLight Menu++ Updater, so use Universal-Updater instead for updating TWiLight Menu++
1. Select `Extras`, `Boxart`, then press <kbd>X</kbd> to scan the full SD card or <kbd>A</kbd> to select a folder to scan
1. Choose a boxart size
1. Choose a border style
1. Make sure box art is set to be shown in TWiLight Menu++ settings
### Windows
1. Download the latest version of [TWiLightBoxart](https://github.com/KirovAir/TwilightBoxart/releases)
1. Extract `TwilightBoxart-Windows-UX.zip` and run `TwilightBoxart.exe`
1. Click `Detect SD`
- If it doesn't find the correct SD card click `Browse...` and select the right one
1. Change the size, border, etc options to your liking
1. Click `Start`
1. On your DS, make sure box art is set to be shown in TWiLight Menu++ settings
### macOS/Linux
1. Download the latest version of [TWiLightBoxart](https://github.com/KirovAir/TwilightBoxart/releases)
1. Extract the `.zip`
1. Open `TwilightBoxart.ini` in the extracted folder in a text editor, then save the file
1. Type the path to your SD card after `SdRoot=`
- On macOS this is `/Volumes/` then the name of your SD card
1. Open the terminal
1. In the terminal, type `cd ` then drag drop the folder with `TwilightBoxart.CLI` in it onto your terminal
1. Run `chmod +x TwilightBoxart.CLI `
1. Run `./TwilightBoxart.CLI` file by drag dropping it onto your terminal
1. Say `Yes` if it shows your SD path correctly
1. On your DS, make sure box art is set to be shown in TWiLight Menu++ settings
### Manual
1. Download a png box art pack from [GameTDB](https://www.gametdb.com/DS/Downloads#cover_packs)
1. Extract the .png files to `sd:/_nds/TWiLightMenu/boxart`
1. On your DS, make sure box art is set to be shown in TWiLight Menu++ settings
**To add your own box art:**
Place them in `sd:/_nds/TWiLightMenu/boxart`.
Can either have the game's TID (ex. `ASME.png`), or the filename (ex. `SM64DS.nds.png`).
Must be in `.png` format, with the recommended size of 128x115 and maximum of 208x143
Individual box art can also be downloaded from GameTDB, under the **S Covers (png)** category.

View File

@ -0,0 +1,11 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Home
---
# Welcome to the TWiLight Menu++ wiki!
TWiLight Menu++ is an open-source DSi Menu upgrade/replacement, and frontend for nds-bootstrap for DSi, 3DS, and flashcards.
For info on how to install, click on the page in the sidebar for your console in the Installing section.

View File

@ -0,0 +1,15 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Installing (3DS, Manual)
category: Installing
---
### Installing
1. Download the latest version of `TWiLightMenu-3DS.7z` from [the releases page](https://github.com/DS-Homebrew/TWiLightMenu/releases)
1. Extract `TWiLightMenu-3DS.7z`
1. Copy the `_nds` folder to your SD card root
1. Copy the `BOOT.NDS` file to your SD card root
1. Copy the `roms` folder to your SD card root
1. Copy the two `.cia` files to your SD card root
1. On your 3DS, install the two CIAs with FBI

View File

@ -0,0 +1,13 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Installing (3DS, Universal-Updater)
category: Installing
---
### Installing
1. Install [Universal-Updater](https://github.com/Universal-Team/Universal-Updater/releases)
1. Open Universal-Updater and find TWiLight Menu++ in the app grid, you can search for it if your having trouble finding it
- It has this icon: ![TWiLight Menu++ icon](https://raw.githubusercontent.com/DS-Homebrew/TWiLightMenu/master/booter/icon.bmp)
1. Press `A` or tap the download icon in the sidebar and select `TWiLight Menu++` to install it
- This will take a while

View File

@ -0,0 +1,33 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Installing (3DS)
category: Installing
---
### Requirements
* The latest version of [FBI](https://github.com/Steveice10/FBI/releases)
* The latest version of [Luma3DS](https://github.com/lumateam/luma3ds/releases)
### Installing (Working Camera)
1. Open FBI and select `Remote Install`, then `Scan QR Code`
1. Scan this QR code to install the latest version of the [TWiLight Menu++ Updater](https://github.com/RocketRobz/TWiLightMenu-Updater)
<br>![TWiLight Menu++ Updater QR code](https://db.universal-team.net/assets/images/qr/twilightmenu-updater.cia.png)
1. Close FBI and Launch the TWiLight Menu++ Updater
- If it doesn't show up on your home menu, reboot your 3DS
1. Select `Release` next to `TWLMenu++`
- This will take a while
1. Select `Release` next to `nds-bootstrap`
### Installing (Non-Working Camera)
1. Download the `TWiLightMenu-Updater.cia` file from the [TWiLight Menu++ Updater release page](https://github.com/RocketRobz/TWiLightMenu-Updater/releases)
1. Place the `TWiLightMenu-Updater.cia` file anywhere on your SD card
1. Launch FBI on your Nintendo 3DS
1. In FBI, go to the place you pasted the `TWiLightMenu-Updater.cia` file
1. Select the `TWiLightMenu-Updater.cia` file and hit "Install & Delete"
1. Close FBI and Launch the TWiLight Menu++ Updater
- If it doesn't show up on your home menu, reboot your 3DS
1. Select `Release` next to `TWLMenu++`
- This will take a while
1. Select `Release` next to `nds-bootstrap`

View File

@ -0,0 +1,19 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Installing (DSi)
category: Installing
---
### Installing
1. Download the latest `TWiLightMenu-DSi.7z` from [the releases page](https://github.com/DS-Homebrew/TWiLightMenu/releases)
1. Extract `TWiLightMenu-DSi.7z`
1. Copy the `_nds` folder to your SD card root
1. Copy the `BOOT.NDS` file to your SD card root
1. Copy the `roms` folder to your SD card root
1. **hiyaCFW users:** Copy the `title` folder to your SD card root
### Autobooting with Unlaunch
1. Turn on your DSi while holding <kbd>A</kbd> and <kbd>B</kbd>
1. In the Unlaunch menu, go to `OPTIONS`
1. Set `NO BUTTON` or a button of your choice to the `TWiLight Menu++` that says `BOOT.NDS` on the bottom screen

View File

@ -0,0 +1,46 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Installing (Flashcard)
category: Installing
---
### Installing
1. Download the latest version of `TWiLightMenu-Flashcard.7z` from [the releases page](https://github.com/DS-Homebrew/TWiLightMenu/releases)
1. Extract `TWiLightMenu-Flashcard.7z`
1. Copy the `_nds` folder to your flashcard's microSD card root
1. Copy the `BOOT.NDS` file to your flashcard's microSD card root
1. Copy the `roms` folder to your flashcard's microSD card root
1. If you already have save data, move your `.sav` files, which are in your DS ROM location, to a new folder called `saves`, which also goes in the DS ROM location.
1.
1. **DS Phat/lite users:** If booting `BOOT.NDS` causes a white screen lock-up, insert a DS Memory Expansion Pak, and try again.
1. **DSi/3DS users:** Run TWLMenu++ on the console's SD card, and turn on `SCFG access in Slot-1`
- This will let you use TWL clock speed and/or VRAM boost on your flashcard games, as well as accessing the console's SD card
### To run games using your flashcard firmware
1. Extract what's in `Flashcart Loader/(your flashcard)` to the root of the flashcard's microSD card
- If you done so, continue to step 3. If not, follow the steps below the flashcard list below.
1. For these flashcards:
- R4i-SDHC
- r4isdhc.com cards
- r4isdhc.hk cards
- R4i SDHC Upgrade Revolution
- R4DSiXL3D
- R4i Advance
- R4-IIIi
- R4 SDHC Revolution
- R4(i) Pocket
- R4i Gold (v1.4.1) (3DS)
- R4xDS
Install YSMenu from [here](https://gbatemp.net/threads/retrogamefan-updates-releases.267243/)
- Make sure you have `YSMenu.nds` and `TTMenu` folder (renamed from `YSMenu`, if existed) on the flashcard microSD root
1. Set `Use nds-bootstrap (B4DS)` to `No`, so the flashcard firmware will be used instead of nds-bootstrap
### Autobooting TWiLight Menu++
1. Extract the content(s) of `Autoboot/(your flashcard)` to the root of the flashcard's microSD card
- Skip this, if you don't see your flashcard
1. ...
- **DS Phat/DS Lite users:** Go to settings in the DS menu, and turn on auto-start, so your flashcard will start on boot
- **DSi/3DS users:** Run TWLMenu++ on the console's SD card, and turn on `Auto-start Slot-1`

View File

@ -0,0 +1,34 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Playing in Widescreen
category: Other
---
Requires an Old/New Nintendo 3DS or 2DS console.
**Preparation**
* Make sure Luma's `boot.firm` is on the SD root for this to work.
* If you used TWiLight Menu++ Updater or Universal-Updater to update, please install the latest TWiLight Menu++ CIAs using FBI.
1. Download [TWPatch](https://puu.sh/G8sEO/87b4c649e3.cia) ([GBATemp thread](https://gbatemp.net/threads/twpatcher-ds-i-mode-screen-filters-and-patches.542694/)).
1. In Luma config, enable external FIRMs and modules.
1. Install the TWPatch CIA.
1. Launch TWPatch.
1. Press X+START to generate a `TwlBg.cxi` file with widescreen.
- If the top screen doesn't indicate that wide patch is enabled, start from step 4 again.
- If widescreen still doesn't work, wait for RTCom-activated widescreen to be released.
1. In the TWiLight Menu++ settings, switch the page to `Misc settings`, and set `Screen Aspect Ratio` to `16:10`.
- This can be done per-game as well.
You're all done! Enjoy your DS games in widescreen!
**NOTE1**: Every game/app in DS(i) mode will run in widescreen, even the games that aren't compatible with widescreen.
For this to be fixed so only the widescreen-compatible games run in widescreen, wait for RTCom-activated widescreen to be released.
**NOTE2:**
Do not hold `START` or `SELECT` when launching TWLMenu++, if you don't want widescreen to look glitched.
If you don't see the screen aspect ratio setting, wait for RTCom-activated widescreen to be released.
Not every game is widescreen compatible. [We have created a list of games with widescreen](https://github.com/DS-Homebrew/TWiLightMenu/blob/master/7zfile/3DS%20-%20CFW%20users/Games%20supported%20with%20widescreen.txt)

View File

@ -0,0 +1,24 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Updating (3DS, Manual)
category: Updating
---
**NOTE:** Starting with v16.4.0, please move your `.sav` files, which are in your DS ROM location, to a new folder called `saves`, which also goes in the DS ROM location.
### Updating
1. Download the latest version of `TWiLightMenu-3DS.7z` from [the releases page](https://github.com/DS-Homebrew/TWiLightMenu/releases)
1. Extract `TWiLightMenu-3DS.7z`
1. Copy the `_nds` folder to your SD card root
1. Copy the `BOOT.NDS` file to your SD card root
1. Copy the two `.cia` files to your SD card root
1. On your 3DS, install the two CIAs with FBI
### More steps for the flashcard side
If you can switch between the SD and flashcard contents in TWLMenu++, and if the flashcard TWLMenu++ is on v16.3.0 or later, please follow these steps.
1. Go into TWLMenu++ Settings
1. Select `Update TWiLight Menu++`
1. Select `Console (micro)SD > Slot-1 microSD`

View File

@ -0,0 +1,24 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Updating (3DS, Universal-Updater)
category: Updating
---
**NOTE:** Starting with v16.4.0, please move your `.sav` files, which are in your DS ROM location, to a new folder called `saves`, which also goes in the DS ROM location.
### Updating
1. Open Universal-Updater
- If you don't have it, follow the [installing](installing-%283ds,-universal-updater%29) instructions
1. Find TWiLight Menu++ in the app grid, you can search for it if your having trouble finding it
1. Press `A` or tap the download icon in the sidebar and select `TWiLight Menu++` to install it
- This will take a while
### More steps for the flashcard side
If you can switch between the SD and flashcard contents in TWLMenu++, and if the flashcard TWLMenu++ is on v16.3.0 or later, please follow these steps.
1. Go into TWLMenu++ Settings
1. Select `Update TWiLight Menu++`
1. Select `Console (micro)SD > Slot-1 microSD`

View File

@ -0,0 +1,23 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Updating (3DS)
category: Updating
---
**NOTE:** Starting with v16.4.0, please move your `.sav` files, which are in your DS ROM location, to a new folder called `saves`, which also goes in the DS ROM location.
### Updating
1. Launch the TWiLight Menu++ Updater
- If you don't have it, follow the [installing](installing-%7C-3ds) instructions
1. Select `Release` next to `TWLMenu++`
- This will take a while
1. Select `Release` next to `nds-bootstrap`
### More steps for the flashcard side
If you can switch between the SD and flashcard contents in TWLMenu++, and if the flashcard TWLMenu++ is on v16.3.0 or later, please follow these steps.
1. Go into TWLMenu++ Settings
1. Select `Update TWiLight Menu++`
1. Select `Console (micro)SD > Slot-1 microSD`

View File

@ -0,0 +1,23 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Updating (DSi)
category: Updating
---
**NOTE:** Starting with v16.4.0, please move your `.sav` files, which are in your DS ROM location, to a new folder called `saves`, which also goes in the DS ROM location.
### Updating
1. Download the latest `TWiLightMenu-DSi.7z` from [the releases page](https://github.com/DS-Homebrew/TWiLightMenu/releases)
1. Extract `TWiLightMenu-DSi.7z`
1. Copy the `_nds` folder to your SD card root
1. Copy the `BOOT.NDS` file to your SD card root
1. **hiyaCFW users:** Copy the `title` folder to your SD card root
### More steps for the flashcard side
If you can switch between the SD and flashcard contents in TWLMenu++, and if the flashcard TWLMenu++ is on v16.3.0 or later, please follow these steps.
1. Go into TWLMenu++ Settings
1. Select `Update TWiLight Menu++`
1. Select `Console (micro)SD > Slot-1 microSD`

View File

@ -0,0 +1,22 @@
---
lang: en-US
layout: wiki
section: twilightmenu
title: Updating (Flashcard)
category: Updating
---
**NOTE:** Starting with v16.4.0, please move your `.sav` files, which are in your DS ROM location, to a new folder called `saves`, which also goes in the DS ROM location.
### Updating
1. Download the latest version of `TWiLightMenu-Flashcard.7z` from [the releases page](https://github.com/DS-Homebrew/TWiLightMenu/releases)
1. Extract `TWiLightMenu-Flashcard.7z`
1. Copy the `_nds` folder to your flashcard's microSD card root
1. Copy the `BOOT.NDS` file to your flashcard's microSD card root
### More steps for the DSi/3DS SD Card side
If you can switch between the SD and flashcard contents in TWLMenu++, and if the flashcard TWLMenu++ is on v16.3.0 or later, please follow these steps.
1. Go into TWLMenu++ Settings
1. Select `Update TWiLight Menu++`
1. Select `Slot-1 microSD > Console (micro)SD`

9
pages/_ja-JP/index.md Normal file
View File

@ -0,0 +1,9 @@
---
lang: ja-JP
layout: default
title: ホーム
---
# DS-Homebrewのウィキへようこそ
TODO: インデックスページを書く…… ;P

View File

@ -0,0 +1,11 @@
---
lang: ja-JP
layout: wiki
section: twilightmenu
title: ホーム
---
# TWiLight Menu++のウィキへようこそ!
TWiLight Menu++ is an open-source DSi Menu upgrade/replacement, and frontend for nds-bootstrap for DSi, 3DS, and flashcards.
For info on how to install, click on the page in the sidebar for your console in the Installing section.

View File

@ -0,0 +1,45 @@
---
lang: ja-JP
layout: wiki
section: twilightmenu
title: インストール(フラッシュカード)
category: インストール
---
### Installing
1. Download the latest version of `TWiLightMenu-Flashcard.7z` from [the releases page](https://github.com/DS-Homebrew/TWiLightMenu/releases)
1. Extract `TWiLightMenu-Flashcard.7z`
1. Copy the `_nds` folder to your flashcard's microSD card root
1. Copy the `BOOT.NDS` file to your flashcard's microSD card root
1. Copy the `roms` folder to your flashcard's microSD card root
1. If you already have save data, move your `.sav` files, which are in your DS ROM location, to a new folder called `saves`, which also goes in the DS ROM location.
1.
1. **DS Phat/lite users:** If booting `BOOT.NDS` causes a white screen lock-up, insert a DS Memory Expansion Pak, and try again.
1. **DSi/3DS users:** Run TWLMenu++ on the console's SD card, and turn on `SCFG access in Slot-1`
- This will let you use TWL clock speed and/or VRAM boost on your flashcard games, as well as accessing the console's SD card
### To run games using your flashcard firmware
1. Extract what's in `Flashcart Loader/(your flashcard)` to the root of the flashcard's microSD card
- If you done so, continue to step 3. If not, follow the steps below the flashcard list below.
For these flashcards:
- R4i-SDHC
- r4isdhc.com cards
- r4isdhc.hk cards
- R4i SDHC Upgrade Revolution
- R4DSiXL3D
- R4i Advance
- R4-IIIi
- R4 SDHC Revolution
- R4(i) Pocket
- R4i Gold (v1.4.1) (3DS)
- R4xDS
1. Install YSMenu from [here](https://gbatemp.net/threads/retrogamefan-updates-releases.267243/)
- Make sure you have `YSMenu.nds` and `TTMenu` folder (renamed from `YSMenu`, if existed) on the flashcard microSD root
1. Set `Use nds-bootstrap (B4DS)` to `No`, so the flashcard firmware will be used instead of nds-bootstrap
### Autobooting TWiLight Menu++
1. Extract the content(s) of `Autoboot/(your flashcard)` to the root of the flashcard's microSD card
- Skip this, if you don't see your flashcard
1. ...
- **DS Phat/DS Lite users:** Go to settings in the DS menu, and turn on auto-start, so your flashcard will start on boot
- **DSi/3DS users:** Run TWLMenu++ on the console's SD card, and turn on `Auto-start Slot-1`