Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added mutability checks for Gfx #22

Merged
merged 15 commits into from
Jan 22, 2022
3 changes: 3 additions & 0 deletions ctru-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ pthread-3ds = { git = "https://github.com/Meziu/pthread-3ds.git" }
libc = { git = "https://github.com/Meziu/libc.git" }
bitflags = "1.0.0"
widestring = "0.2.2"

[dev-dependencies]
ferris-says = "0.2.1"
4 changes: 2 additions & 2 deletions ctru-rs/examples/buttons.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ctru::console::Console;
use ctru::gfx::{Gfx, Screen};
use ctru::gfx::Gfx;
use ctru::services::apt::Apt;
use ctru::services::hid::{Hid, KeyPad};

Expand All @@ -9,7 +9,7 @@ fn main() {
let apt = Apt::init().unwrap();
let hid = Hid::init().unwrap();
let gfx = Gfx::default();
let console = Console::init(&gfx, Screen::Top);
let console = Console::init(gfx.top_screen.borrow_mut());

println!("Hi there! Try pressing a button");
println!("\x1b[29;16HPress Start to exit");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
extern crate ctru;

use ctru::console::Console;
use ctru::gfx::Screen;
use ctru::services::hid::KeyPad;
use ctru::services::{Apt, Hid};
use ctru::Gfx;
Expand All @@ -11,7 +8,7 @@ fn main() {
let apt = Apt::init().unwrap();
let hid = Hid::init().unwrap();
let gfx = Gfx::default();
let _console = Console::init(&gfx, Screen::Top);
let mut console = Console::init(gfx.top_screen.borrow_mut());

println!("Press A to enable/disable wide screen mode.");

Expand All @@ -23,7 +20,13 @@ fn main() {
}

if hid.keys_down().contains(KeyPad::KEY_A) {
gfx.set_wide_mode(!gfx.get_wide_mode());
drop(console);

let wide_mode = gfx.top_screen.borrow().get_wide_mode();
gfx.top_screen.borrow_mut().set_wide_mode(!wide_mode);

console = Console::init(gfx.top_screen.borrow_mut());
println!("Press A to enable/disable wide screen mode.");
}

gfx.flush_buffers();
Expand Down
6 changes: 3 additions & 3 deletions ctru-rs/examples/hello-both-screens.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ctru::console::Console;
use ctru::gfx::{Gfx, Screen};
use ctru::gfx::Gfx;
use ctru::services::apt::Apt;
use ctru::services::hid::{Hid, KeyPad};

Expand All @@ -11,11 +11,11 @@ fn main() {
let gfx = Gfx::default();

// Start a console on the top screen
let top_screen = Console::init(&gfx, Screen::Top);
let top_screen = Console::init(gfx.top_screen.borrow_mut());

// Start a console on the bottom screen.
// The most recently initialized console will be active by default
let bottom_screen = Console::init(&gfx, Screen::Bottom);
let bottom_screen = Console::init(gfx.bottom_screen.borrow_mut());

// Let's print on the top screen first
top_screen.select();
Expand Down
59 changes: 22 additions & 37 deletions ctru-rs/examples/hello-world.rs
Original file line number Diff line number Diff line change
@@ -1,56 +1,41 @@
use ctru::console::Console;
use ctru::gfx::{Gfx, Screen};
use ctru::gfx::Gfx;
use ctru::services::apt::Apt;
use ctru::services::hid::{Hid, KeyPad};

use std::io::BufWriter;

fn main() {
// Initialize ctrulib service handles.
// Service handles are internally reference-counted. When all instances of a
// service handle go out of scope, the service will be closed.
ctru::init();

// The APT service handles application management functions, such as enabling sleep
// mode and jumping to the home menu or to other applications
let apt = Apt::init().unwrap();

// The HID service handles button and touch screen inputs.
let hid = Hid::init().unwrap();

// The GFX service manages the framebuffers for the top and bottom screens.
let gfx = Gfx::default();
let hid = Hid::init().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller");
let _console = Console::init(gfx.top_screen.borrow_mut());

// Initialize a ctrulib console and direct standard output to it.
// Consoles can be initialized on both the top and bottom screens.
let _console = Console::init(&gfx, Screen::Top);
let out = b"Hello fellow Rustaceans, I'm on the Nintendo 3DS!";
let width = 24;

// Now we can print to stdout!
println!("Hello, world!");
let mut writer = BufWriter::new(Vec::new());
ferris_says::say(out, width, &mut writer).unwrap();

// We can use escape sequences to move the cursor around the terminal.
// The following text will be moved down 29 rows and right 16 characters
// before printing begins.
println!("\x1b[29;16HPress Start to exit");
println!(
"\x1b[0;0H{}",
String::from_utf8_lossy(&writer.into_inner().unwrap())
);

// Main application loop.
// Main loop
while apt.main_loop() {
// Flushes and swaps the framebuffers when double-buffering
// is enabled
gfx.flush_buffers();
gfx.swap_buffers();

// Wait for the next frame to begin
gfx.wait_for_vblank();

// Scan for user input.
//Scan all the inputs. This should be done once for each frame
hid.scan_input();

// Check if the user has pressed the given button on this frame.
// If so, break out of the loop.
if hid.keys_down().contains(KeyPad::KEY_START) {
break;
}
}
// Flush and swap framebuffers
gfx.flush_buffers();
gfx.swap_buffers();

// All of our service handles will drop out of scope at this point,
// triggering the end of our application.
//Wait for VBlank
gfx.wait_for_vblank();
}
}
65 changes: 65 additions & 0 deletions ctru-rs/examples/network-sockets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use ctru::console::Console;
use ctru::gfx::Gfx;
use ctru::services::apt::Apt;
use ctru::services::hid::{Hid, KeyPad};
use ctru::services::soc::Soc;

use std::io::{Read, Write};
use std::net::{Shutdown, TcpListener};
use std::time::Duration;

fn main() {
ctru::init();
let gfx = Gfx::default();
let _console = Console::init(gfx.top_screen.borrow_mut());
let hid = Hid::init().unwrap();
let apt = Apt::init().unwrap();

println!("\nlibctru sockets demo\n");

let soc = Soc::init().unwrap();

let server = TcpListener::bind("0.0.0.0:80").unwrap();
server.set_nonblocking(true).unwrap();

println!("Point your browser to http://{}/\n", soc.host_address());

while apt.main_loop() {
gfx.wait_for_vblank();

match server.accept() {
Ok((mut stream, socket_addr)) => {
println!("Got connection from {}", socket_addr);

let mut buf = [0u8; 4096];
match stream.read(&mut buf) {
Ok(_) => {
let req_str = String::from_utf8_lossy(&buf);
println!("{}", req_str);
}
Err(e) => println!("Unable to read stream: {}", e),
}

let response = b"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n<html><body>Hello world</body></html>\r\n";

if let Err(e) = stream.write(response) {
println!("Error writing http response: {}", e);
}

stream.shutdown(Shutdown::Both).unwrap();
}
Err(e) => match e.kind() {
std::io::ErrorKind::WouldBlock => {}
_ => {
println!("Error accepting connection: {}", e);
std::thread::sleep(Duration::from_secs(2));
}
},
}

hid.scan_input();
if hid.keys_down().contains(KeyPad::KEY_START) {
break;
};
}
}
4 changes: 2 additions & 2 deletions ctru-rs/examples/software-keyboard.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use ctru::applets::swkbd::{Button, Swkbd};
use ctru::console::Console;
use ctru::gfx::{Gfx, Screen};
use ctru::gfx::Gfx;
use ctru::services::apt::Apt;
use ctru::services::hid::{Hid, KeyPad};

Expand All @@ -9,7 +9,7 @@ fn main() {
let apt = Apt::init().unwrap();
let hid = Hid::init().unwrap();
let gfx = Gfx::default();
let _console = Console::init(&gfx, Screen::Top);
let _console = Console::init(gfx.top_screen.borrow_mut());

println!("Press A to enter some text or press Start to quit");

Expand Down
19 changes: 8 additions & 11 deletions ctru-rs/src/console.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
use std::cell::RefMut;
use std::default::Default;
use std::marker::PhantomData;

use ctru_sys::{consoleClear, consoleInit, consoleSelect, consoleSetWindow, PrintConsole};

use crate::gfx::{Gfx, Screen};
use crate::gfx::Screen;

pub struct Console<'gfx> {
pub struct Console<'screen> {
context: Box<PrintConsole>,
_gfx: PhantomData<&'gfx ()>,
screen: RefMut<'screen, dyn Screen>,
}

impl<'gfx> Console<'gfx> {
impl<'screen> Console<'screen> {
/// Initialize a console on the chosen screen, overwriting whatever was on the screen
/// previously (including other consoles). The new console is automatically selected for
/// printing.
pub fn init(_gfx: &'gfx Gfx, screen: Screen) -> Self {
pub fn init(screen: RefMut<'screen, dyn Screen>) -> Self {
let mut context = Box::new(PrintConsole::default());

unsafe { consoleInit(screen.into(), context.as_mut()) };
unsafe { consoleInit(screen.as_raw(), context.as_mut()) };

Console {
context,
_gfx: PhantomData,
}
Console { context, screen }
}

/// Select this console as the current target for stdout
Expand Down
Loading