From de4cca655dfce2e92611e5f7b3e890adbadfa105 Mon Sep 17 00:00:00 2001 From: Ronald Kinard Date: Tue, 9 Jun 2015 19:00:59 -0500 Subject: [PATCH] Initial commit. --- .gitignore | 4 +++ 3ds.json | 29 ++++++++++++++++++++ Cargo.toml | 14 ++++++++++ README.md | 49 ++++++++++++++++++++++++++++++++++ build.rs | 30 +++++++++++++++++++++ src/lib.rs | 29 ++++++++++++++++++++ src/raw/mod.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/raw/srv.rs | 16 +++++++++++ src/raw/svc.rs | 0 9 files changed, 243 insertions(+) create mode 100644 .gitignore create mode 100644 3ds.json create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 build.rs create mode 100644 src/lib.rs create mode 100644 src/raw/mod.rs create mode 100644 src/raw/srv.rs create mode 100644 src/raw/svc.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62c662d --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +target +Cargo.lock + +.DS_Store diff --git a/3ds.json b/3ds.json new file mode 100644 index 0000000..0e863d1 --- /dev/null +++ b/3ds.json @@ -0,0 +1,29 @@ +{ + "data-layout": "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a:0:64-n32-m:e", + "llvm-target": "arm-none-eabihf", + "linker": "arm-none-eabi-g++", + "ar": "arm-none-eabi-ar", + "target-endian": "little", + "target-pointer-width": "32", + "arch": "arm", + "os": "none", + "cpu": "mpcore", + "features": "+vfp2", + "relocation-model": "static", + "linker-is-gnu": true, + "has-rpath": true, + "morestack": false, + "disable-redzone": true, + "executables": true, + "dynamic-linking": false, + "no-compiler-rt": true, + "exe-suffix": ".elf", + "pre-link-args": ["-specs", + "3dsx.specs", + "-march=armv6k", + "-mtune=mpcore", + "-mfloat-abi=hard" + ], + "is-like-windows": true, + "function-sections": false +} diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9d770f3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "ctru-rs" +version = "0.1.0" +description = "A safe wrapper around smealum's ctrulib." +authors = ["Ronald Kinard "] +links = "ctru" +build = "build.rs" + +[lib] +name = "ctru" +crate-type = ["rlib"] + +[dependencies.core] +git="https://github.com/hackndev/rust-libcore" diff --git a/README.md b/README.md new file mode 100644 index 0000000..9c0c921 --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# ctru-rs + +A Rust wrapper library for smealum's +[ctrulib](https://github.com/smealum/ctrulib). Intended for use only when +targeting CTR. + +## How to build + +1. Install the devkitARM toolchain for your system. Make sure `DEVKITPRO` is + set in your environment. +2. Modify ~/.cargo/config and add the following lines: + +```toml + [target.3ds] + ar = "/path/to/arm-none-eabi-ar" +``` + +3. Build with `cargo build --target 3ds.json`. +4. A dkA linkable .rlib (static library) will be generated. Read below for +instructions on using. + +## How to use + +You can build your homebrew projects through Cargo just as easily as any other +platform. Add this to your `Cargo.toml`: + +```toml + [dependencies.core] + git="https://github.com/hackndev/rust-libcore" + + [dependencies.ctru-rs] + git="https://github.com/Furyhunter/ctru-rs" +``` + +Copy the `3ds.json` target file to your project root and pass `--target +3ds.json` whenever building. The instructions above for cargo configuration and +environment still apply. It's recommended that you put the `bin` dir in your +dkA root to your path. + +Your homebrew's crate must specify that it does not use `std`, because `std` +is not available for the 3ds. `core` is a small subset of `std`'s functionality +that is platform agnostic. You can `use core::prelude::*` to recover much of +std's prelude, after `extern crate core`. This library makes use of core only. + +## Contributing + +This is a thin wrapper library **only**, any additional Rust-centric support +code for the 3DS will be put into another package. However, the wrapper is +incomplete, so PR's to finish it are helpful. diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..05d4cab --- /dev/null +++ b/build.rs @@ -0,0 +1,30 @@ +use std::env; +use std::path::PathBuf; +use std::fs; + +use std::option::Option::{self, Some, None}; + +const ENV_DKP: &'static str = "DEVKITPRO"; + +fn find_libctru() -> Option { + if let Ok(value) = env::var(ENV_DKP) { + let mut path = PathBuf::from(value); + path.push("libctru"); + path.push("lib"); + // metadata returns Err if the dir does not exist + if let Ok(metadata) = fs::metadata(path.as_path()) { + if metadata.is_dir() { + return Some(path); + } + } + } + return None; +} + +fn main() { + if let Some(path) = find_libctru() { + if let Some(s) = path.to_str() { + println!("cargo:rustc-link-search={}", s); + } + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..e94c809 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,29 @@ +#![feature(core)] +#![feature(no_std)] +#![no_std] + +extern crate core; + +pub mod raw; + +pub type Result = i32; +pub type Handle = u32; + +pub mod srv { + use super::Result; + use super::raw::srv; + pub fn init() -> Result { + unsafe { + return srv::srvInit(); + } + } + pub fn exit() -> Result { + unsafe { + return srv::srvExit(); + } + } + + pub fn awesome() -> i32 { + 0 + } +} diff --git a/src/raw/mod.rs b/src/raw/mod.rs new file mode 100644 index 0000000..d02165f --- /dev/null +++ b/src/raw/mod.rs @@ -0,0 +1,72 @@ +#![allow(non_camel_case_types)] +#![allow(overflowing_literals)] + +pub mod srv; +pub mod svc; + +#[repr(C)] +pub enum mediatypes_enum { + mediatype_NAND, + mediatype_SDMC, + mediatype_GAMECARD +} + +pub type s8 = i8; +pub type s16 = i16; +pub type s32 = i32; +pub type s64 = i64; + +#[repr(u8)] +pub enum c_void { + __variant1, + __variant2 +} + +#[repr(C)] +pub enum MemOp { + MEMOP_FREE = 1, + MEMOP_ALLOC = 3, + MEMOP_MAP = 4, + MEMOP_UNMAP = 5, + MEMOP_PROT = 6, + + MEMOP_ALLOC_LINEAR = 0x10003, +} + +#[repr(C)] +pub enum MemState { + MEMSTATE_FREE = 0, + MEMSTATE_RESERVED = 1, + MEMSTATE_IO = 2, + MEMSTATE_STATIC = 3, + MEMSTATE_CODE = 4, + MEMSTATE_PRIVATE = 5, + MEMSTATE_SHARED = 6, + MEMSTATE_CONTINUOUS = 7, + MEMSTATE_ALIASED = 8, + MEMSTATE_ALIAS = 9, + MEMSTATE_ALIASCODE = 10, + MEMSTATE_LOCKED = 11 +} + +#[repr(C)] +pub enum MemPerm { + MEMPERM_READ = 1, + MEMPERM_WRITE = 2, + MEMPERM_EXECUTE = 4, + MEMPERM_DONTCARE = 0x10000000, + MEMPERM_MAX = 0xFFFFFFFF //force 4-byte +} + +#[repr(C)] +pub struct MemInfo { + pub base_addr: u32, + pub size: u32, + pub perm: u32, + pub state: u32, +} + +#[repr(C)] +pub struct PageInfo { + flags: u32, +} diff --git a/src/raw/srv.rs b/src/raw/srv.rs new file mode 100644 index 0000000..338b30f --- /dev/null +++ b/src/raw/srv.rs @@ -0,0 +1,16 @@ +use super::*; +use super::super::{Result, Handle}; + +#[link(name="ctru")] +extern { + pub fn srvInit() -> Result; + pub fn srvExit() -> Result; + pub fn srvGetSessionHandle() -> * const Handle; + pub fn srvRegisterClient() -> Result; + pub fn srvGetServiceHandle(out: *mut Handle, name: * const u8) -> Result; + pub fn srvRegisterService(out: *mut Handle, name: * const u8) -> Result; + pub fn srvUnregisterService(name: * const u8) -> Result; + pub fn srvPmInit() -> Result; + pub fn srvRegisterProcess(procid: u32, count: u32, serviceaccesscontrol: *mut c_void) -> Result; + pub fn srvUnregisterProcess(procid: u32) -> Result; +} diff --git a/src/raw/svc.rs b/src/raw/svc.rs new file mode 100644 index 0000000..e69de29