From 21cef9ab29c86a077e6430a7ce241409664b6352 Mon Sep 17 00:00:00 2001 From: "DocsBot (from Travis CI)" Date: Sat, 29 Dec 2018 07:10:40 +0000 Subject: [PATCH] Deploy rust-console/gba to github.com/rust-console/gba.git:master --- docs/01-quirks/01-no_std.html | 87 +++++++++----- docs/01-quirks/04-newtype.html | 108 ++++++++++++----- docs/02-concepts/05-palram.html | 4 +- docs/print.html | 199 ++++++++++++++++++++++---------- docs/searchindex.js | 2 +- docs/searchindex.json | 2 +- 6 files changed, 280 insertions(+), 122 deletions(-) diff --git a/docs/01-quirks/01-no_std.html b/docs/01-quirks/01-no_std.html index 624341b..6a2d3f8 100644 --- a/docs/01-quirks/01-no_std.html +++ b/docs/01-quirks/01-no_std.html @@ -217,36 +217,65 @@ the standard library types to be used "for free" once it was set up, o custom allocator that's GBA specific if Rust's global allocator style isn't a good fit for the GBA (I honestly haven't looked into it).

Bare Metal Panic

-

TODO: expand this

- -

TODO: this will probably fail without a __clzsi2 implementation, which is a -good seg for the next section

+

If our code panics, we usually want to see that panic message. Unfortunately, +without a way to access something like stdout or stderr we've gotta do +something a little weirder.

+

If our program is running within the mGBA emulator, version 0.7 or later, we +can access a special set of addresses that allow us to send out CString +values, which then appear within a message log that you can check.

+

We can capture this behavior by making an MGBADebug type, and then implement +core::fmt::Write for that type. Once done, the write! macro will let us +target the mGBA debug output channel.

+

When used, it looks like this:

+

+# #![allow(unused_variables)]
+#fn main() {
+#[panic_handler]
+fn panic(info: &core::panic::PanicInfo) -> ! {
+  use core::fmt::Write;
+  use gba::mgba::{MGBADebug, MGBADebugLevel};
+
+  if let Some(mut mgba) = MGBADebug::new() {
+    let _ = write!(mgba, "{}", info);
+    mgba.send(MGBADebugLevel::Fatal);
+  }
+  loop {}
+}
+#}
+

If you want to follow the particulars you can check the MGBADebug source in +the gba crate. Basically, there's one address you can use to try and activate +the debug output, and if it works you write your message into the "array" at +another address, and then finally write a send value to a third address. You'll +need to have read the volatile section for the +details to make sense.

LLVM Intrinsics

-

TODO: explain that we'll occasionally have to provide some intrinsics.

+

The above code will make your program fail to build in debug mode, saying that +__clzsi2 can't be found. This is a special builtin function that LLVM attempts +to use when there's no hardware version of an operation it wants to do (in this +case, counting the leading zeros). It's not actually necessary in this case, +which is why you only need it in debug mode. The higher optimization level of +release mode makes LLVM pre-compute more and fold more constants or whatever and +then it stops trying to call __clzsi2.

+

Unfortunately, sometimes a build will fail with a missing intrinsic even in +release mode.

+

If LLVM wants core to have that intrinsic then you're in +trouble, you'll have to send a PR to the +compiler-builtins +repository and hope to get it into rust itself.

+

If LLVM wants your code to have the intrinsic then you're in less trouble. You +can look up the details and then implement it yourself. It can go anywhere in +your program, as long as it has the right ABI and name. In the case of +__clzsi2 it takes a usize and returns a usize, so you'd write something +like:

+

+# #![allow(unused_variables)]
+#fn main() {
+#[no_mangle]
+pub extern "C" fn __clzsi2(mut x: usize) -> usize {
+  //
+}
+#}
+

And so on for whatever other missing intrinsic.

diff --git a/docs/01-quirks/04-newtype.html b/docs/01-quirks/04-newtype.html index 381b4c5..5890bd7 100644 --- a/docs/01-quirks/04-newtype.html +++ b/docs/01-quirks/04-newtype.html @@ -227,6 +227,10 @@ style, but there are some rules and considerations here:

+

As a reminder: remember that macro_rules macros have to appear before +they're invoked in your source, so the newtype macro will always have to be at +the very top of your file, or if you put it in a module within your project +you'll need to declare the module before anything that uses it.

Upgrade That Macro!

We also want to be able to add derive stuff and doc comments to our newtype. Within the context of macro_rules! definitions these are called "meta". Since @@ -254,35 +258,81 @@ newtype! { PixelColor, u16 } #} -

And that's about all we'll need for the examples.

-

As a reminder: remember that macro_rules macros have to appear before -they're invoked in your source, so the newtype macro will always have to be at -the very top of your file, or if you put it in a module within your project -you'll need to declare the module before anything that uses it.

-

Potential Homework

-

If you wanted to keep going and get really fancy with it, you could potentially -add a lot more:

- +

Next, we can allow for the wrapping of types that aren't just a single +identifier by changing $old_name from :ident to :ty. We can't also do +this for the $new_type part because declaring a new struct expects a valid +identifier that's not already declared (obviously), and :ty is intended for +capturing types that already exist.

+

+# #![allow(unused_variables)]
+#fn main() {
+#[macro_export]
+macro_rules! newtype {
+  ($(#[$attr:meta])* $new_name:ident, $old_name:ty) => {
+    $(#[$attr])*
+    #[repr(transparent)]
+    pub struct $new_name($old_name);
+  };
+}
+#}
+

Next of course we'll want to usually have a new method that's const and just +gives a 0 value. We won't always be making a newtype over a number value, but we +often will. It's usually silly to have a new method with no arguments since we +might as well just impl Default, but Default::default isn't const, so +having pub const fn new() -> Self is justified here.

+

Here, the token 0 is given the {integer} type, which can be converted into +any of the integer types as needed, but it still can't be converted into an +array type or a pointer or things like that. Accordingly we've added the "no +frills" option which declares the struct and no new method.

+

+# #![allow(unused_variables)]
+#fn main() {
+#[macro_export]
+macro_rules! newtype {
+  ($(#[$attr:meta])* $new_name:ident, $old_name:ty) => {
+    $(#[$attr])*
+    #[repr(transparent)]
+    pub struct $new_name($old_name);
+    impl $new_name {
+      /// A `const` "zero value" constructor
+      pub const fn new() -> Self {
+        $new_name(0)
+      }
+    }
+  };
+  ($(#[$attr:meta])* $new_name:ident, $old_name:ty, no frills) => {
+    $(#[$attr])*
+    #[repr(transparent)]
+    pub struct $new_name($old_name);
+  };
+}
+#}
+

Finally, we usually want to have the wrapped value be totally private, but there +are occasions where that's not the case. For this, we can allow the wrapped +field to accept a visibility modifier.

+

+# #![allow(unused_variables)]
+#fn main() {
+#[macro_export]
+macro_rules! newtype {
+  ($(#[$attr:meta])* $new_name:ident, $v:vis $old_name:ty) => {
+    $(#[$attr])*
+    #[repr(transparent)]
+    pub struct $new_name($v $old_name);
+    impl $new_name {
+      /// A `const` "zero value" constructor
+      pub const fn new() -> Self {
+        $new_name(0)
+      }
+    }
+  };
+  ($(#[$attr:meta])* $new_name:ident, $v:vis $old_name:ty, no frills) => {
+    $(#[$attr])*
+    #[repr(transparent)]
+    pub struct $new_name($v $old_name);
+  };
+}
+#}
diff --git a/docs/02-concepts/05-palram.html b/docs/02-concepts/05-palram.html index 870e1d2..0be81cb 100644 --- a/docs/02-concepts/05-palram.html +++ b/docs/02-concepts/05-palram.html @@ -152,8 +152,8 @@ byte: if you try to write just 1 byte, it writes that byte into both pa the larger 16-bit location. This doesn't really affect us much with PALRAM, because palette values are all supposed to be u16 anyway.

The palette memory actually contains not one, but two sets of palettes. First -there's 256 entries for the background palette data (starting at 0x5000000), -and then there's 256 entries for object palette data (starting at 0x5000200).

+there's 256 entries for the background palette data (starting at 0x500_0000), +and then there's 256 entries for object palette data (starting at 0x500_0200).

The GBA also has two modes for palette access: 8-bits-per-pixel (8bpp) and 4-bits-per-pixel (4bpp).

+

As a reminder: remember that macro_rules macros have to appear before +they're invoked in your source, so the newtype macro will always have to be at +the very top of your file, or if you put it in a module within your project +you'll need to declare the module before anything that uses it.

Upgrade That Macro!

We also want to be able to add derive stuff and doc comments to our newtype. Within the context of macro_rules! definitions these are called "meta". Since @@ -1508,35 +1541,81 @@ newtype! { PixelColor, u16 } #} -

And that's about all we'll need for the examples.

-

As a reminder: remember that macro_rules macros have to appear before -they're invoked in your source, so the newtype macro will always have to be at -the very top of your file, or if you put it in a module within your project -you'll need to declare the module before anything that uses it.

-

Potential Homework

-

If you wanted to keep going and get really fancy with it, you could potentially -add a lot more:

- +

Next, we can allow for the wrapping of types that aren't just a single +identifier by changing $old_name from :ident to :ty. We can't also do +this for the $new_type part because declaring a new struct expects a valid +identifier that's not already declared (obviously), and :ty is intended for +capturing types that already exist.

+

+# #![allow(unused_variables)]
+#fn main() {
+#[macro_export]
+macro_rules! newtype {
+  ($(#[$attr:meta])* $new_name:ident, $old_name:ty) => {
+    $(#[$attr])*
+    #[repr(transparent)]
+    pub struct $new_name($old_name);
+  };
+}
+#}
+

Next of course we'll want to usually have a new method that's const and just +gives a 0 value. We won't always be making a newtype over a number value, but we +often will. It's usually silly to have a new method with no arguments since we +might as well just impl Default, but Default::default isn't const, so +having pub const fn new() -> Self is justified here.

+

Here, the token 0 is given the {integer} type, which can be converted into +any of the integer types as needed, but it still can't be converted into an +array type or a pointer or things like that. Accordingly we've added the "no +frills" option which declares the struct and no new method.

+

+# #![allow(unused_variables)]
+#fn main() {
+#[macro_export]
+macro_rules! newtype {
+  ($(#[$attr:meta])* $new_name:ident, $old_name:ty) => {
+    $(#[$attr])*
+    #[repr(transparent)]
+    pub struct $new_name($old_name);
+    impl $new_name {
+      /// A `const` "zero value" constructor
+      pub const fn new() -> Self {
+        $new_name(0)
+      }
+    }
+  };
+  ($(#[$attr:meta])* $new_name:ident, $old_name:ty, no frills) => {
+    $(#[$attr])*
+    #[repr(transparent)]
+    pub struct $new_name($old_name);
+  };
+}
+#}
+

Finally, we usually want to have the wrapped value be totally private, but there +are occasions where that's not the case. For this, we can allow the wrapped +field to accept a visibility modifier.

+

+# #![allow(unused_variables)]
+#fn main() {
+#[macro_export]
+macro_rules! newtype {
+  ($(#[$attr:meta])* $new_name:ident, $v:vis $old_name:ty) => {
+    $(#[$attr])*
+    #[repr(transparent)]
+    pub struct $new_name($v $old_name);
+    impl $new_name {
+      /// A `const` "zero value" constructor
+      pub const fn new() -> Self {
+        $new_name(0)
+      }
+    }
+  };
+  ($(#[$attr:meta])* $new_name:ident, $v:vis $old_name:ty, no frills) => {
+    $(#[$attr])*
+    #[repr(transparent)]
+    pub struct $new_name($v $old_name);
+  };
+}
+#}

Constant Assertions

Have you ever wanted to assert things even before runtime? We all have, of course. Particularly when the runtime machine is a poor little GBA, we'd like to @@ -1939,8 +2018,8 @@ byte: if you try to write just 1 byte, it writes that byte into both pa the larger 16-bit location. This doesn't really affect us much with PALRAM, because palette values are all supposed to be u16 anyway.

The palette memory actually contains not one, but two sets of palettes. First -there's 256 entries for the background palette data (starting at 0x5000000), -and then there's 256 entries for object palette data (starting at 0x5000200).

+there's 256 entries for the background palette data (starting at 0x500_0000), +and then there's 256 entries for object palette data (starting at 0x500_0200).

The GBA also has two modes for palette access: 8-bits-per-pixel (8bpp) and 4-bits-per-pixel (4bpp).