Skip to content

Commit 3e89922

Browse files
authored
Merge pull request #134 from rust3ds/improve/docs
Improve documentation and examples
2 parents 54c6359 + 869cd50 commit 3e89922

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+3066
-791
lines changed

.github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
matrix:
2222
toolchain:
2323
# Run against a "known good" nightly
24-
- nightly-2023-01-13
24+
- nightly-2023-05-31
2525
# Check for breakage on latest nightly
2626
- nightly
2727

@@ -57,7 +57,7 @@ jobs:
5757
strategy:
5858
matrix:
5959
toolchain:
60-
- nightly-2023-01-13
60+
- nightly-2023-05-31
6161
- nightly
6262
continue-on-error: ${{ matrix.toolchain == 'nightly' }}
6363
runs-on: ubuntu-latest

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ Cargo.lock
44

55
# IDE files
66
.idea
7+
.vscode

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[workspace]
22
members = ["ctru-rs", "ctru-sys", "ctru-sys/bindgen-ctru-sys"]
33
default-members = ["ctru-rs", "ctru-sys"]
4+
resolver = "2"
45

56
[patch.'https://github.com/rust3ds/ctru-rs']
67
# Make sure all dependencies use the local ctru-sys package

README.md

+13-19
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,27 @@
11
# ctru-rs
22

3-
A Rust wrapper library for smealum's [ctrulib](https://github.com/smealum/ctrulib).
3+
This repository is home of the `ctru-rs` project, which aims to bring full control of the Nintendo 3DS console to homebrew developers using Rust.
44

55
## Structure
66

77
This repository is organized as follows:
88

9-
* `ctru-rs`: Safe, idiomatic wrapper around `ctru-sys`
9+
* [`ctru-rs`](./ctru-rs/) - Safe, idiomatic wrapper around [`ctru-sys`](./ctru-sys/).
10+
* [`ctru-sys`](./ctru-sys/) - Low-level, unsafe bindings to [`libctru`](https://github.com/devkitPro/libctru).
1011

11-
* `ctru-sys`: Low-level, unsafe bindings to ctrulib.
12+
## Getting Started
1213

13-
This crate's version changes according to the version of `libctru`
14-
used to generate the bindings, with the following convention:
15-
16-
* `libctru` version `X.Y.Z-W`
17-
* `ctru-sys` version `XY.Z.P+X.Y.Z-W`
18-
19-
where `P` is usually 0 but may be incremented for fixes in e.g.
20-
binding generation, `libc` dependency bump, etc.
21-
22-
It may be possible to build this crate against a different version of `libctru`,
23-
but you may encounter linker errors or ABI issues. A build-time Cargo warning
24-
(displayed when built with `-vv`) will be issued if the build script detects
25-
a mismatch or is unable to check the installed `libctru` version.
14+
Specific information about how to use the crates is present in the individual README for each package.
15+
Have a look at `ctru-rs`' [README.md](./ctru-rs/README.md) for a broad overview.
2616

2717
## Original version
2818

29-
This project is based on the efforts the original authors:
30-
* [Eidolon](https://github.com/HybridEidolon)
31-
* [FenrirWolf](https://github.com/FenrirWolf)
19+
This project is based on the efforts of the original authors:
20+
* [Eidolon](https://github.com/HybridEidolon)
21+
* [FenrirWolf](https://github.com/FenrirWolf)
3222

3323
The old version is archived [here](https://github.com/rust3ds/ctru-rs-old).
24+
25+
## License
26+
27+
This project is distributed under the Zlib license.

ctru-rs/Cargo.toml

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
[package]
2-
authors = ["Rust3DS Org", "Ronald Kinard <[email protected]>"]
3-
description = "A safe wrapper around smealum's ctrulib."
4-
license = "Zlib"
52
name = "ctru-rs"
63
version = "0.7.1"
4+
authors = ["Rust3DS Org", "Ronald Kinard <[email protected]>"]
5+
description = "A safe wrapper around libctru"
6+
repository = "https://github.com/rust3ds/ctru-rs"
7+
keywords = ["3ds", "libctru"]
8+
categories = ["os", "api-bindings", "hardware-support"]
9+
exclude = ["examples"]
10+
license = "Zlib"
711
edition = "2021"
8-
rust-version = "1.64"
12+
rust-version = "1.70"
913

1014
[lib]
1115
crate-type = ["rlib"]
@@ -18,7 +22,7 @@ const-zero = "0.1.0"
1822
shim-3ds = { git = "https://github.com/rust3ds/shim-3ds.git" }
1923
pthread-3ds = { git = "https://github.com/rust3ds/pthread-3ds.git" }
2024
libc = "0.2.121"
21-
bitflags = "1.0.0"
25+
bitflags = "2.3.3"
2226
widestring = "0.2.2"
2327

2428
[build-dependencies]
@@ -45,6 +49,11 @@ std-threads = []
4549
[package.metadata.cargo-3ds]
4650
romfs_dir = "examples/romfs"
4751

52+
[package.metadata.docs.rs]
53+
default-target = "armv6k-nintendo-3ds"
54+
targets = []
55+
cargo-args = ["-Z", "build-std"]
56+
4857
[[example]]
4958
name = "thread-basic"
5059
required-features = ["std-threads"]

ctru-rs/README.md

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# ctru-rs
2+
3+
Safe and idiomatic Rust wrapper around [`libctru`](https://github.com/devkitPro/libctru).
4+
5+
## Getting Started
6+
7+
Thoroughly read the [`ctru-rs` wiki](https://github.com/rust3ds/ctru-rs/wiki/Getting-Started) to meet the requirements
8+
and to understand what it takes to develop homebrew software on the Nintendo 3DS family of consoles.
9+
After that, you can simply add the crate as a dependency to your project and build your final binary by using [`cargo-3ds`](https://github.com/rust3ds/cargo-3ds)
10+
or by manually compiling for the `armv6k-nintendo-3ds` target.
11+
12+
## Examples
13+
14+
Many examples to demonstrate the `ctru-rs` functionality are available in the [`examples`](./examples/) folder. Simply run them via
15+
16+
```bash
17+
cargo 3ds run --example <example-name>
18+
```
19+
20+
## License
21+
22+
This project is distributed under the Zlib license.

ctru-rs/examples/audio-filters.rs

+28-11
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
1+
//! Audio Filters example.
2+
//!
3+
//! This example showcases basic audio functionality using [`Ndsp`].
4+
15
#![feature(allocator_api)]
26

37
use std::f32::consts::PI;
48

59
use ctru::linear::LinearAllocator;
610
use ctru::prelude::*;
711
use ctru::services::ndsp::{
8-
wave::{Wave, WaveStatus},
12+
wave::{Status, Wave},
913
AudioFormat, AudioMix, InterpolationType, Ndsp, OutputMode,
1014
};
1115

16+
// Configuration for the NDSP process and channels.
1217
const SAMPLE_RATE: usize = 22050;
1318
const SAMPLES_PER_BUF: usize = SAMPLE_RATE / 10; // 2205
1419
const BYTES_PER_SAMPLE: usize = AudioFormat::PCM16Stereo.size();
1520
const AUDIO_WAVE_LENGTH: usize = SAMPLES_PER_BUF * BYTES_PER_SAMPLE;
1621

17-
// Note Frequencies
22+
// Note frequencies.
1823
const NOTEFREQ: [f32; 7] = [220., 440., 880., 1760., 3520., 7040., 14080.];
1924

20-
// The audio format is Stereo PCM16
21-
// As such, a sample is made up of 2 "Mono" samples (2 * i16 = u32), one for each channel (left and right)
2225
fn fill_buffer(audio_data: &mut [u8], frequency: f32) {
26+
// The audio format is Stereo PCM16.
27+
// As such, a sample is made up of 2 "Mono" samples (2 * i16), one for each channel (left and right).
2328
let formatted_data = bytemuck::cast_slice_mut::<_, [i16; 2]>(audio_data);
2429

2530
for (i, chunk) in formatted_data.iter_mut().enumerate() {
@@ -44,8 +49,7 @@ fn main() {
4449

4550
let mut note: usize = 4;
4651

47-
// Filters
48-
52+
// Filter names to display.
4953
let filter_names = [
5054
"None",
5155
"Low-Pass",
@@ -60,19 +64,26 @@ fn main() {
6064
// We set up two wave buffers and alternate between the two,
6165
// effectively streaming an infinitely long sine wave.
6266

67+
// We create a buffer on the LINEAR memory that will hold our audio data.
68+
// It's necessary for the buffer to live on the LINEAR memory sector since it needs to be accessed by the DSP processor.
6369
let mut audio_data1 = Box::new_in([0u8; AUDIO_WAVE_LENGTH], LinearAllocator);
70+
71+
// Fill the buffer with the first set of data. This simply writes a sine wave into the buffer.
6472
fill_buffer(audio_data1.as_mut_slice(), NOTEFREQ[4]);
6573

74+
// Clone the original buffer to obtain an equal buffer on the LINEAR memory used for double buffering.
6675
let audio_data2 = audio_data1.clone();
6776

77+
// Setup two wave info objects with the correct configuration and ownership of the audio data.
6878
let mut wave_info1 = Wave::new(audio_data1, AudioFormat::PCM16Stereo, false);
6979
let mut wave_info2 = Wave::new(audio_data2, AudioFormat::PCM16Stereo, false);
7080

71-
let mut ndsp = Ndsp::new().expect("Couldn't obtain NDSP controller");
81+
// Setup the NDSP service and its configuration.
7282

73-
// This line isn't needed since the default NDSP configuration already sets the output mode to `Stereo`
83+
let mut ndsp = Ndsp::new().expect("Couldn't obtain NDSP controller");
7484
ndsp.set_output_mode(OutputMode::Stereo);
7585

86+
// Channel configuration. We use channel zero but any channel would do just fine.
7687
let mut channel_zero = ndsp.channel(0).unwrap();
7788
channel_zero.set_interpolation(InterpolationType::Linear);
7889
channel_zero.set_sample_rate(SAMPLE_RATE as f32);
@@ -82,6 +93,7 @@ fn main() {
8293
let mix = AudioMix::default();
8394
channel_zero.set_mix(&mix);
8495

96+
// First set of queueing for the two buffers. The second one will only play after the first one has ended.
8597
channel_zero.queue_wave(&mut wave_info1).unwrap();
8698
channel_zero.queue_wave(&mut wave_info2).unwrap();
8799

@@ -93,6 +105,8 @@ fn main() {
93105
filter_names[filter as usize]
94106
);
95107

108+
println!("\x1b[29;16HPress Start to exit");
109+
96110
let mut altern = true; // true is wave_info1, false is wave_info2
97111

98112
while apt.main_loop() {
@@ -101,14 +115,16 @@ fn main() {
101115

102116
if keys_down.contains(KeyPad::START) {
103117
break;
104-
} // break in order to return to hbmenu
118+
}
105119

120+
// Note frequency controller using the buttons.
106121
if keys_down.intersects(KeyPad::DOWN) {
107122
note = note.saturating_sub(1);
108123
} else if keys_down.intersects(KeyPad::UP) {
109124
note = std::cmp::min(note + 1, NOTEFREQ.len() - 1);
110125
}
111126

127+
// Filter controller using the buttons.
112128
let mut update_params = false;
113129
if keys_down.intersects(KeyPad::LEFT) {
114130
filter -= 1;
@@ -139,22 +155,23 @@ fn main() {
139155
}
140156
}
141157

158+
// Double buffer alternation depending on the one used.
142159
let current: &mut Wave = if altern {
143160
&mut wave_info1
144161
} else {
145162
&mut wave_info2
146163
};
147164

165+
// If the current buffer has finished playing, we can refill it with new data and re-queue it.
148166
let status = current.status();
149-
if let WaveStatus::Done = status {
167+
if let Status::Done = status {
150168
fill_buffer(current.get_buffer_mut().unwrap(), NOTEFREQ[note]);
151169

152170
channel_zero.queue_wave(current).unwrap();
153171

154172
altern = !altern;
155173
}
156174

157-
//Wait for VBlank
158175
gfx.wait_for_vblank();
159176
}
160177
}

ctru-rs/examples/buttons.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
//! Buttons example.
2+
//!
3+
//! This example showcases how to retrieve button inputs from the console's HID.
4+
15
use ctru::prelude::*;
26

37
fn main() {
@@ -18,28 +22,28 @@ fn main() {
1822
// Scan for user input on the current frame.
1923
hid.scan_input();
2024

21-
// Get information about which keys were held down on this frame
25+
// Get information about which keys were held down on this frame.
2226
let keys = hid.keys_held();
2327

2428
// We only want to print when the keys we're holding now are different
25-
// from what they were on the previous frame
29+
// from what they were on the previous frame.
2630
if keys != old_keys {
27-
// Clear the screen
31+
// Clear the screen.
2832
console.clear();
2933

30-
// We print these again because we just cleared the screen above
34+
// We print these again because we just cleared the screen above.
3135
println!("Hi there! Try pressing a button");
3236
println!("\x1b[29;16HPress Start to exit");
3337

34-
// Move the cursor back to the top of the screen
38+
// Move the cursor back to the top of the screen.
3539
println!("\x1b[3;0H");
3640

3741
// Print to the screen depending on which keys were held.
3842
//
39-
// The .contains() method checks for all of the provided keys,
40-
// and the .intersects() method checks for any of the provided keys.
43+
// The `.contains()` method checks for all of the provided keys,
44+
// and the `.intersects()` method checks for any of the provided keys.
4145
//
42-
// You can also use the .bits() method to do direct comparisons on
46+
// You can also use the `.bits()` method to do direct comparisons on
4347
// the underlying bits
4448

4549
if keys.contains(KeyPad::A) {
@@ -54,13 +58,13 @@ fn main() {
5458
if keys.intersects(KeyPad::L | KeyPad::R | KeyPad::ZL | KeyPad::ZR) {
5559
println!("You held a shoulder button!");
5660
}
57-
if keys.intersects(KeyPad::START) {
61+
if keys.contains(KeyPad::START) {
5862
println!("See ya!");
5963
break;
6064
}
6165
}
6266

63-
// Save our current key presses for the next frame
67+
// Save our current key presses for the next frame.
6468
old_keys = keys;
6569

6670
gfx.wait_for_vblank();

0 commit comments

Comments
 (0)