From eeefec6e275e72b5f40474fbece2edb1e483899d Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 12 Jul 2022 14:21:13 +0100 Subject: [PATCH 1/8] Make the first infinite_scrolled_map test run --- .../display/tiled/infinite_scrolled_map.rs | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/agb/src/display/tiled/infinite_scrolled_map.rs b/agb/src/display/tiled/infinite_scrolled_map.rs index 97dafea1..715a6220 100644 --- a/agb/src/display/tiled/infinite_scrolled_map.rs +++ b/agb/src/display/tiled/infinite_scrolled_map.rs @@ -20,9 +20,38 @@ use crate::{ /// /// # Example /// -/// ``` -/// let backdrop = InfiniteScrolledMap::new( -/// background.background(Priority::P2, RegularBackgroundSize::Background32x32), +/// ```rust,no_run +/// # #![no_std] +/// # #![no_main] +/// extern crate alloc; +/// +/// use alloc::boxed::Box; +/// +/// use agb::display::tiled::{ +/// InfiniteScrolledMap, +/// TileSetting, +/// RegularBackgroundSize, +/// TileSet, +/// TileFormat, +/// }; +/// use agb::display::Priority; +/// +/// mod tilemap { +/// pub const BACKGROUND_MAP: &[u16] = &[ // Probably load this from a file +/// # 0, 1, 2]; +/// pub const WIDTH: i32 = // set it to some width +/// # 12; +/// pub const MAP_TILES: &[u8] = &[ // probably load this from a file +/// # 0]; +/// } +/// +/// # fn foo(mut gba: agb::Gba) { +/// let (gfx, mut vram) = gba.display.video.tiled0(); +/// +/// let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp); +/// +/// let mut backdrop = InfiniteScrolledMap::new( +/// gfx.background(Priority::P2, RegularBackgroundSize::Background32x32), /// Box::new(|pos| { /// ( /// &tileset, @@ -40,6 +69,7 @@ use crate::{ /// backdrop.set_pos(&mut vram, (3, 5).into()); /// backdrop.commit(&mut vram); /// backdrop.show(); +/// # } /// ``` pub struct InfiniteScrolledMap<'a> { map: MapLoan<'a, RegularMap>, From b29b4c261ed353edaa0e6bc02848f65fb958e488 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 12 Jul 2022 14:37:17 +0100 Subject: [PATCH 2/8] Add justfile target for running the doc tests --- justfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/justfile b/justfile index 79d0099e..15709c8c 100644 --- a/justfile +++ b/justfile @@ -17,6 +17,9 @@ test: test-release: just _test-release agb +doctest-agb: + (cd agb && cargo test --doc -Z doctest-xcompile) + clean: just _all-crates _clean From 643891a9de57ff337ed4da7d28218845758d1ba8 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 12 Jul 2022 14:37:32 +0100 Subject: [PATCH 3/8] Make the doctests work for infinite_scrolled_map --- .../display/tiled/infinite_scrolled_map.rs | 101 +++++++++++++++++- 1 file changed, 97 insertions(+), 4 deletions(-) diff --git a/agb/src/display/tiled/infinite_scrolled_map.rs b/agb/src/display/tiled/infinite_scrolled_map.rs index 715a6220..decdd4db 100644 --- a/agb/src/display/tiled/infinite_scrolled_map.rs +++ b/agb/src/display/tiled/infinite_scrolled_map.rs @@ -113,11 +113,57 @@ impl<'a> InfiniteScrolledMap<'a> { /// /// # Example /// - /// ``` - /// background.init(&mut vram, start_position, || { + /// ```rust,no_run + /// # #![no_std] + /// # #![no_main] + /// # #![no_std] + /// # #![no_main] + /// # extern crate alloc; + /// # + /// # use alloc::boxed::Box; + /// # + /// # use agb::display::tiled::{ + /// # InfiniteScrolledMap, + /// # TileSetting, + /// # RegularBackgroundSize, + /// # TileSet, + /// # TileFormat, + /// # }; + /// # use agb::display::Priority; + /// # + /// # mod tilemap { + /// # pub const BACKGROUND_MAP: &[u16] = &[0, 1, 2]; + /// # pub const WIDTH: i32 = 12; + /// # pub const MAP_TILES: &[u8] = &[0]; + /// # } + /// # + /// # fn foo(mut gba: agb::Gba) { + /// # let (gfx, mut vram) = gba.display.video.tiled0(); + /// # + /// # let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp); + /// # + /// # let mut backdrop = InfiniteScrolledMap::new( + /// # gfx.background(Priority::P2, RegularBackgroundSize::Background32x32), + /// # Box::new(|pos| { + /// # ( + /// # &tileset, + /// # TileSetting::from_raw( + /// # *tilemap::BACKGROUND_MAP + /// # .get((pos.x + tilemap::WIDTH * pos.y) as usize) + /// # .unwrap_or(&0), + /// # ), + /// # ) + /// # }), + /// # ); + /// # + /// # let vblank = agb::interrupt::VBlank::get(); + /// # let mut mixer = gba.mixer.mixer(); + /// let start_position = agb::fixnum::Vector2D::new(10, 10); + /// backdrop.init(&mut vram, start_position, &mut || { /// vblank.wait_for_vblank(); /// mixer.frame(); /// }); + /// # } /// ``` pub fn init( &mut self, @@ -141,11 +187,58 @@ impl<'a> InfiniteScrolledMap<'a> { /// /// # Example /// - /// ``` - /// while background.init_partial(&mut vram, start_position) == PartialUpdateStatus::Continue { + /// ```rust,no_run + /// # #![no_std] + /// # #![no_main] + /// # #![no_std] + /// # #![no_main] + /// # extern crate alloc; + /// # + /// # use alloc::boxed::Box; + /// # + /// # use agb::display::tiled::{ + /// # InfiniteScrolledMap, + /// # TileSetting, + /// # RegularBackgroundSize, + /// # TileSet, + /// # TileFormat, + /// # PartialUpdateStatus, + /// # }; + /// # use agb::display::Priority; + /// # + /// # mod tilemap { + /// # pub const BACKGROUND_MAP: &[u16] = &[0, 1, 2]; + /// # pub const WIDTH: i32 = 12; + /// # pub const MAP_TILES: &[u8] = &[0]; + /// # } + /// # + /// # fn foo(mut gba: agb::Gba) { + /// # let (gfx, mut vram) = gba.display.video.tiled0(); + /// # + /// # let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp); + /// # + /// # let mut backdrop = InfiniteScrolledMap::new( + /// # gfx.background(Priority::P2, RegularBackgroundSize::Background32x32), + /// # Box::new(|pos| { + /// # ( + /// # &tileset, + /// # TileSetting::from_raw( + /// # *tilemap::BACKGROUND_MAP + /// # .get((pos.x + tilemap::WIDTH * pos.y) as usize) + /// # .unwrap_or(&0), + /// # ), + /// # ) + /// # }), + /// # ); + /// # + /// # let vblank = agb::interrupt::VBlank::get(); + /// # let mut mixer = gba.mixer.mixer(); + /// let start_position = agb::fixnum::Vector2D::new(10, 10); + /// while backdrop.init_partial(&mut vram, start_position) == PartialUpdateStatus::Continue { /// vblank.wait_for_vblank(); /// mixer.frame(); /// } + /// # } /// ``` pub fn init_partial( &mut self, From 5e317ef1920d23dc1ae167d1d4b29b6a893c8a2d Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 12 Jul 2022 14:39:50 +0100 Subject: [PATCH 4/8] Get doctests working on lib.rs (will fix ignored later) --- agb/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/agb/src/lib.rs b/agb/src/lib.rs index a45d570c..97f1159c 100644 --- a/agb/src/lib.rs +++ b/agb/src/lib.rs @@ -50,7 +50,7 @@ /// /// This will generate something along the lines of the following: /// -/// ``` +/// ```rust,ignore /// // module name comes from the name of the toml file, so `sprites` in this case because it is /// // called `sprites.toml` /// mod sprites { @@ -75,7 +75,7 @@ /// ``` /// /// In `src/main.rs` -/// ``` +/// ```rust,ignore /// mod gfx { /// use agb::display::object::ObjectControl; /// @@ -105,7 +105,7 @@ /// ``` /// /// In `src/main.rs`: -/// ``` +/// ```rust,ignore /// mod gfx { /// use agb::display::background::BackgroundDistributor; /// @@ -139,7 +139,7 @@ macro_rules! include_font { /// Doing this will ensure that `agb` can correctly set up the environment to call your rust function on start up. /// /// # Examples -/// ``` +/// ```no_run,rust /// #![no_std] /// #![no_main] /// @@ -206,7 +206,7 @@ static mut GBASINGLE: single::Singleton = single::Singleton::new(unsafe { G /// /// # Examples /// -/// ``` +/// ```no_run,rust /// #![no_std] /// #![no_main] /// From 892948638717c2ddb773afd7a03ab5444fb46353 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 12 Jul 2022 14:45:45 +0100 Subject: [PATCH 5/8] Make doctest in interrupt.rs work --- agb/src/interrupt.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/agb/src/interrupt.rs b/agb/src/interrupt.rs index 3d08d216..c88fb9fd 100644 --- a/agb/src/interrupt.rs +++ b/agb/src/interrupt.rs @@ -235,10 +235,17 @@ fn interrupt_to_root(interrupt: Interrupt) -> &'static InterruptRoot { /// /// # Examples /// -/// ``` -/// let _a = add_interrupt_handler(Interrupt::VBlank, |_: &CriticalSection| { -/// println!("Woah there! There's been a vblank!"); +/// ```rust,no_run +/// # #![no_std] +/// # #![no_main] +/// use bare_metal::CriticalSection; +/// +/// # fn foo() { +/// # use agb::interrupt::{add_interrupt_handler, Interrupt}; +/// let _a = add_interrupt_handler(Interrupt::VBlank, |_: CriticalSection| { +/// agb::println!("Woah there! There's been a vblank!"); /// }); +/// # } /// ``` pub fn add_interrupt_handler<'a>( interrupt: Interrupt, From 70b227d4717630f399ef323eab9a115fd3c74ba9 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 12 Jul 2022 15:00:52 +0100 Subject: [PATCH 6/8] Get doctests working for mixer/mod.rs --- agb/examples/sfx/jump.wav | Bin 0 -> 2762 bytes agb/examples/sfx/my_bgm.wav | Bin 0 -> 14602 bytes agb/src/sound/mixer/mod.rs | 81 +++++++++++++++++++++++++++++------- 3 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 agb/examples/sfx/jump.wav create mode 100644 agb/examples/sfx/my_bgm.wav diff --git a/agb/examples/sfx/jump.wav b/agb/examples/sfx/jump.wav new file mode 100644 index 0000000000000000000000000000000000000000..e4f078cb7b835102d327829908aedbc657cfb018 GIT binary patch literal 2762 zcmZve%TJqE5XHw}^DtmY2;or(P(mo1D6LefU3O6xie?ZId`s~EiNqloj3dar{8{l`Reu5fSF}@4a}QO zJu_>w0eiam{KXj07k^p!b@BPaivs^YUHbFo_dh)T?#IX9K6zq)EWKX(i!63xZ*0#F ztz@70)M*8~Zxc3a^ESiZVY_2JmbC_}r*>rTY|B>dA6vJ5E83Y=Dc4QG5u3C*`^Kj2 zD;u(Y>#}yMS=m0=e`MdF#v9wV1FDs+ZaM3-c5RiU$~IM&n^mr; zk_XACO;KZx_c8YOfi?qzbFv=Vj=crfn(b2Ylsp+Q+{C3F1>bR%?AT?;@~s`w$(L&! zgMNqTWp+jHf$A<;ra|=x21eC07{I$W=1za71 zJ}~Wh7h*S0&QU7NQ$b8gj~sejqF50mn=rcqw}KMc^U*!N0V70k``NZ^MM@K zFw&38p`Lgh1mVqi5uNfl;{H@_^(kF%BN6LjF~i!O1ow=Mg$_9-9ICNLlSNtd(4_2~^1 zbDTfv9&AX*lO$FyQEU~KT8MAPo?9!g&S`Yl2g(OzopXN&Z&lXB#HKT`=kBQEgnmxI zRN^JE)`^3|d2w=rhhX?F6Gn4v+Bwq{lXfZEm4x4vg*0n0rmP?7X4l!>blv3U9;S$t z5C=td{imu8v^@{ZhaL`0~t4;y9hOR+K3()9dNq~^`>7jjAg zsnx2!?k-UG`6f=y49#PCpw#SW3+I$vRk5!VG3!3;^Vw3ShXbD!t9V5xQz&)Pq92_F zxx0$mn(uPpW;3HarHl{h{~k`r`Ds5+`VNL#7(@4z^-ElQfRE%nRStf{q}(5zs~4$r z=;vEH7D3o>gel|FrWLnCwlpp}N%IZEjXcz<8y%Oak!Kc8p!6f3ESf_)b8@isd+S_R z-0Q)h`W?g}(pj1WFI#Ya#?B59h00UzoUUe7P2@HA%_n!*kWb?oqHkuCzcdqcay6R< z@XCyz@ge6}*mMtWlWW^=j~b4bx|77kjL}?A=k$6Kr8}mFO5?aMqB`9xI)A$DcRW|z zM4Bv?+STvHgM;e+ROSd9Tf0njwe?zQ6lO+m`=%5r(PEs261CQ zIXgU41tcXRioBQEW9-edJ_!C^sjSHDWHQ za{&`qd^VnU(04cQSt>_NmDRFmsU|GSt69>+GA=S mRU@L2#I*Z*n`eobI+#>N5&F?rQN8qY?Jupxx<2b^^7}uY$*_?C literal 0 HcmV?d00001 diff --git a/agb/examples/sfx/my_bgm.wav b/agb/examples/sfx/my_bgm.wav new file mode 100644 index 0000000000000000000000000000000000000000..80ba543eb4a2e057e083c45c10102d2da81b756c GIT binary patch literal 14602 zcmd5-OK%)S5H7Fn#B0ZnLr5SA0V9G?BoqZCq~yo}OO_&#k_gU`5I1fSzm7kEcpgCF zf_Nwozr0Df zHsN#etl83KvxY6&rIjmJPdb0)sUE~KDf$;t45paGgYt>J)9QoG+pJiB)jZYNvFkWmp?U}_mAF%dO! z(=IHrFAt)X9eu$Y`RpRGQ{b=q;M4mvxCv6DQ)_ePrQ_PkAPB#Mz) z3q)eH9ruN4zK4ujz{0_d8~?|iwu3%r{5g>Du}{Pkd2M=iH*MXXIfBiEf)#IhTny%j z8q+_jgNVd}{M0q*3#m}4LbPU8fCm%RfluXx{2Iyowj)7Bq7FcYQy~A4ARcWZC&cA! zB@5cHCg>3(vJ#+`i@Qn#J}Cv(gEs4P#+qr)*}N^-oO9W2bRFHEPBlOkfe)Qw9gzX> z;QXS(YhGh?8o537`7CiZU1!7j%$6sO+Ut%E{X++*99P35%{qcbpK}RW(+)Ykkmxz5 zXPv)bhkedFHRD$37QT^*Hi`|8xn@u7p}(KneYJvH+{WhtF8&ePaNBQ=d3!)C#jmKGOLQpqkA}ojTD>R!CA$b!`FbW z&N%Wz{>&zw$%JIby`UeDQZ-gR#zRMT&r#g8KkQfg*?zEZe12=++4oNWXg{Ur7yHfr zvOittmfNf)EA;ufM?&w8*m0jH?6jS-SN#39y=AZ489Qt5ICaL}^>xYKaOo-MpR!|a zF`KH1o}uGBU0d#veY@{*R@-&Dks>4d?_QG!UPJWnfmiajKleNvoWPcQYI*G*`~F$l zHB&!ky+gRGntp~}vX|{ON3vvZI!fR@?O2Z6$%O2L9d%sTFSs^O;8EWnvsc{`UkFZG z!@bS<#P`ui-vLiE?}csGz`Yl@1#dx~$TdgGZ=2r_zL=K#nNMfuNIGr!7MuRer!&9k zh!)c1xj*ExW{Tf*Ja~A+;D3QThPMK4k+{9U-E#S)N5bidn+a!RuI+_)I8G71dvgn% zm37D0YJVNL#c?BH;%n#K#6Khc1)%g_K*e#x=r)~9-R9p5HwXOSTPJ3CmN%STTH?Or zm~5j){mDfi!Y6NQesl1OlYkifr}7rZmk8vj6aInN@zz4mcz2?ooVp4sW2NgqqA2oV=UpCpv%|EATKMAz;pV=ENAN z=vCROuFM5~HHZj$$`%rIff1Flsz81Di5VKJO$9LKc{{@24Y&qe!NuV5jcW3D8-70#}|t#o{vFu z9MtZ`szn*ipn272SH?6NPJJ2d$J1zX-7Cs|GT5IjkmVlsLONPG?vCB)u*b;x_0uUt z>6OPR32SBKk;X~anp9V3>~$xVan^vbfechWio0AAbT2xg-HB5Ekc%G0+6m8i_{w;+ zHBeNoi2fptKtqJU7Q8?z{JpQ$b>7X52&1F&{Cdx)PEF)Wf01>LiajWDLbE>#arzmd zU!AdhRZEA-RaJ^H$OWqY@>Cw3SH$5URg62zU0@7M!5bEZ?4tspi?hrr%In?@E6-m1 zvKD*2%NfHrYX})DCQj5(TGWv|w}Xa;w6q`oD&*z-#=(iY3D+Ok~)(XOMJ~ z)>E7DWnPTTY{07;QL8HHet1O`qu&90bBpx z)cMBQ8+E3=#M`SH?9pCYb;x@`OC3ZLg;jfTd-ue%m>i7xCCti2``*^Uth)KGE{9Ho z)@rR`a@nzN$m@~~GmCD%g+ESnP?A-zWj(~H*6oK2ALAX0-w*2gbgODO-g;C;uP@); iJ(Y2=Q{{KAscz=H{n6bJS9PzOewD1dkNsgE(E2}*?e|dt literal 0 HcmV?d00001 diff --git a/agb/src/sound/mixer/mod.rs b/agb/src/sound/mixer/mod.rs index 16ca4cd8..9b72e599 100644 --- a/agb/src/sound/mixer/mod.rs +++ b/agb/src/sound/mixer/mod.rs @@ -35,9 +35,13 @@ //! To create a sound mixer, you will need to get it out of the [`Gba`](crate::Gba) struct //! as follows: //! -//! ``` +//! ```rust,no_run +//! # #![no_std] +//! # #![no_main] +//! # fn foo(gba: &mut agb::Gba) { //! let mut mixer = gba.mixer.mixer(); //! mixer.enable(); +//! # } //! ``` //! //! ## Doing the per-frame work @@ -48,22 +52,34 @@ //! //! Without interrupts: //! -//! ``` +//! ```rust,no_run +//! # #![no_std] +//! # #![no_main] +//! # fn foo(gba: &mut agb::Gba) { +//! # let mut mixer = gba.mixer.mixer(); +//! # let vblank = agb::interrupt::VBlank::get(); //! // Somewhere in your main loop: //! mixer.frame(); //! vblank.wait_for_vblank(); //! mixer.after_vblank(); +//! # } //! ``` //! //! Or with interrupts: //! -//! ``` +//! ```rust,no_run +//! # #![no_std] +//! # #![no_main] +//! # fn foo(gba: &mut agb::Gba) { +//! # let mut mixer = gba.mixer.mixer(); +//! # let vblank = agb::interrupt::VBlank::get(); //! // outside your main loop, close to initialisation //! let _mixer_interrupt = mixer.setup_interrupt_handler(); //! //! // inside your main loop //! mixer.frame(); //! vblank.wait_for_vblank(); +//! # } //! ``` //! //! Despite being high performance, the mixer still takes a sizable portion of CPU time (6-10% @@ -79,14 +95,21 @@ //! Use the [`include_wav!`](crate::include_wav) macro in order to load the sound. This will produce //! an error if your wav file is of the wrong frequency. //! -//! ``` +//! ```rust,no_run +//! # #![no_std] +//! # #![no_main] +//! # fn foo(gba: &mut agb::Gba) { +//! # let mut mixer = gba.mixer.mixer(); +//! # let vblank = agb::interrupt::VBlank::get(); +//! # use agb::{*, sound::mixer::*}; //! // Outside your main function in global scope: -//! const MY_CRAZY_SOUND: &[u8] = include_wav!("sfx/my_crazy_sound.wav"); +//! const MY_CRAZY_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav"); //! //! // Then to play the sound: //! let mut channel = SoundChannel::new(MY_CRAZY_SOUND); //! channel.stereo(); //! let _ = mixer.play_sound(channel); // we don't mind if this sound doesn't actually play +//! # } //! ``` //! //! See the [`SoundChannel`] struct for more details on how you can configure the sounds to play. @@ -152,25 +175,39 @@ enum SoundPriority { /// play regardless of whether you have lots of sound effects playing. You create a high /// priority sound channel using [`new_high_priority`](SoundChannel::new_high_priority). /// -/// ``` +/// ```rust,no_run +/// # #![no_std] +/// # #![no_main] +/// # use agb::sound::mixer::*; +/// # use agb::*; /// // in global scope: -/// const MY_BGM: [u8] = include_wav!("sfx/my_bgm.wav"); +/// const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav"); /// /// // somewhere in code +/// # fn foo(gba: &mut Gba) { +/// # let mut mixer = gba.mixer.mixer(); /// let mut bgm = SoundChannel::new_high_priority(MY_BGM); /// bgm.stereo().should_loop(); /// let _ = mixer.play_sound(bgm); +/// # } /// ``` /// /// ## Playing a sound effect /// -/// ``` +/// ```rust,no_run +/// # #![no_std] +/// # #![no_main] +/// # use agb::sound::mixer::*; +/// # use agb::*; /// // in global scope: -/// const JUMP_SOUND: [u8] = include_wav!("sfx/jump_sound.wav"); +/// const JUMP_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav"); /// /// // somewhere in code -/// let jump_sound = SoundChannel::new(MY_JUMP_SOUND); +/// # fn foo(gba: &mut Gba) { +/// # let mut mixer = gba.mixer.mixer(); +/// let jump_sound = SoundChannel::new(JUMP_SOUND); /// let _ = mixer.play_sound(jump_sound); +/// # } /// ``` pub struct SoundChannel { data: &'static [u8], @@ -198,13 +235,20 @@ impl SoundChannel { /// /// # Example /// - /// ``` + /// ```rust,no_run + /// # #![no_std] + /// # #![no_main] + /// # use agb::sound::mixer::*; + /// # use agb::*; + /// # fn foo(gba: &mut Gba) { + /// # let mut mixer = gba.mixer.mixer(); /// // in global scope: - /// const JUMP_SOUND: [u8] = include_wav!("sfx/jump_sound.wav"); + /// const JUMP_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav"); /// /// // somewhere in code - /// let jump_sound = SoundChannel::new(MY_JUMP_SOUND); + /// let jump_sound = SoundChannel::new(JUMP_SOUND); /// let _ = mixer.play_sound(jump_sound); + /// # } /// ``` #[inline(always)] #[must_use] @@ -233,14 +277,21 @@ impl SoundChannel { /// /// # Example /// - /// ``` + /// ```rust,no_run + /// # #![no_std] + /// # #![no_main] + /// # use agb::sound::mixer::*; + /// # use agb::*; + /// # fn foo(gba: &mut Gba) { + /// # let mut mixer = gba.mixer.mixer(); /// // in global scope: - /// const MY_BGM: [u8] = include_wav!("sfx/my_bgm.wav"); + /// const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav"); /// /// // somewhere in code /// let mut bgm = SoundChannel::new_high_priority(MY_BGM); /// bgm.stereo().should_loop(); /// let _ = mixer.play_sound(bgm); + /// # } /// ``` #[inline(always)] #[must_use] From 4a6b093f6da28e2a0fecd29aca05914275ad527f Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 12 Jul 2022 15:07:28 +0100 Subject: [PATCH 7/8] Update mixer doctests --- agb/examples/mixer_basic.rs | 2 +- agb/src/sound/mixer/sw_mixer.rs | 84 ++++++++++++++++++++++++++++----- 2 files changed, 74 insertions(+), 12 deletions(-) diff --git a/agb/examples/mixer_basic.rs b/agb/examples/mixer_basic.rs index 50aae56d..1419562b 100644 --- a/agb/examples/mixer_basic.rs +++ b/agb/examples/mixer_basic.rs @@ -4,7 +4,7 @@ use agb::fixnum::Num; use agb::input::{Button, ButtonController, Tri}; use agb::sound::mixer::SoundChannel; -use agb::{include_wav, Gba, fixnum::num}; +use agb::{fixnum::num, include_wav, Gba}; // Music - "Dead Code" by Josh Woodward, free download at http://joshwoodward.com const DEAD_CODE: &[u8] = include_wav!("examples/JoshWoodward-DeadCode.wav"); diff --git a/agb/src/sound/mixer/sw_mixer.rs b/agb/src/sound/mixer/sw_mixer.rs index f3f3e081..676c0ed8 100644 --- a/agb/src/sound/mixer/sw_mixer.rs +++ b/agb/src/sound/mixer/sw_mixer.rs @@ -36,15 +36,28 @@ extern "C" { /// You should not create this struct directly, instead creating it through the [`Gba`](crate::Gba) /// struct as follows: /// -/// ``` +/// ```rust,no_run +/// # #![no_std] +/// # #![no_main] +/// # use agb::sound::mixer::*; +/// # use agb::*; +/// # fn foo(gba: &mut Gba) { /// let mut mixer = gba.mixer.mixer(); +/// # } /// ``` /// /// # Example /// -/// ``` +/// ```rust,no_run +/// # #![no_std] +/// # #![no_main] +/// # use agb::sound::mixer::*; +/// # use agb::*; +/// # fn foo(gba: &mut Gba) { +/// # let mut mixer = gba.mixer.mixer(); +/// # let vblank = agb::interrupt::VBlank::get(); /// // Outside your main function in global scope: -/// const MY_CRAZY_SOUND: &[u8] = include_wav!("sfx/my_crazy_sound.wav"); +/// const MY_CRAZY_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav"); /// /// // in your main function: /// let mut mixer = gba.mixer.mixer(); @@ -57,6 +70,7 @@ extern "C" { /// vblank.wait_for_vblank(); /// mixer.after_vblank(); /// } +/// # } /// ``` pub struct Mixer { buffer: MixerBuffer, @@ -72,12 +86,20 @@ pub struct Mixer { /// /// # Example /// -/// ``` +/// ```rust,no_run +/// # #![no_std] +/// # #![no_main] +/// # use agb::sound::mixer::*; +/// # use agb::*; +/// # fn foo(gba: &mut Gba) { +/// # let mut mixer = gba.mixer.mixer(); +/// # const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav"); /// let mut channel = SoundChannel::new_high_priority(MY_BGM); /// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority /// /// // Later, stop that particular channel -/// mixer.channel(bgm_channel_id).stop(); +/// mixer.channel(&bgm_channel_id).expect("Expected to still be playing").stop(); +/// # } /// ``` pub struct ChannelId(usize, i32); @@ -106,12 +128,20 @@ impl Mixer { /// /// # Example /// - /// ``` + /// ```rust,no_run + /// # #![no_std] + /// # #![no_main] + /// # use agb::sound::mixer::*; + /// # use agb::*; + /// # fn foo(gba: &mut Gba) { + /// # let mut mixer = gba.mixer.mixer(); + /// # let vblank = agb::interrupt::VBlank::get(); /// loop { /// mixer.frame(); /// vblank.wait_for_vblank(); /// mixer.after_vblank(); /// } + /// # } /// ``` #[cfg(not(feature = "freq32768"))] pub fn after_vblank(&mut self) { @@ -127,7 +157,14 @@ impl Mixer { /// /// # Example /// - /// ``` + /// ```rust,no_run + /// # #![no_std] + /// # #![no_main] + /// # use agb::sound::mixer::*; + /// # use agb::*; + /// # fn foo(gba: &mut Gba) { + /// # let mut mixer = gba.mixer.mixer(); + /// # let vblank = agb::interrupt::VBlank::get(); /// // you must set this to a named variable to ensure that the scope is long enough /// let _mixer_interrupt = mixer.setup_interrupt_handler(); /// @@ -135,6 +172,7 @@ impl Mixer { /// mixer.frame(); /// vblank.wait_for_vblank(); /// } + /// # } /// ``` pub fn setup_interrupt_handler(&self) -> InterruptHandler<'_> { let mut timer1 = unsafe { Timer::new(1) }; @@ -157,12 +195,20 @@ impl Mixer { /// /// # Example /// - /// ``` + /// ```rust,no_run + /// # #![no_std] + /// # #![no_main] + /// # use agb::sound::mixer::*; + /// # use agb::*; + /// # fn foo(gba: &mut Gba) { + /// # let mut mixer = gba.mixer.mixer(); + /// # let vblank = agb::interrupt::VBlank::get(); /// loop { /// mixer.frame(); /// vblank.wait_for_vblank(); /// mixer.after_vblank(); // optional, only if not using interrupts /// } + /// # } /// ``` pub fn frame(&mut self) { if !self.buffer.should_calculate() { @@ -188,9 +234,17 @@ impl Mixer { /// /// # Example /// - /// ``` + /// ```rust,no_run + /// # #![no_std] + /// # #![no_main] + /// # use agb::sound::mixer::*; + /// # use agb::*; + /// # fn foo(gba: &mut Gba) { + /// # let mut mixer = gba.mixer.mixer(); + /// # const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav"); /// let mut channel = SoundChannel::new_high_priority(MY_BGM); /// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority + /// # } /// ``` pub fn play_sound(&mut self, new_channel: SoundChannel) -> Option { for (i, channel) in self.channels.iter_mut().enumerate() { @@ -229,12 +283,20 @@ impl Mixer { /// /// # Example /// - /// ``` + /// ```rust,no_run + /// # #![no_std] + /// # #![no_main] + /// # use agb::sound::mixer::*; + /// # use agb::*; + /// # fn foo(gba: &mut Gba) { + /// # let mut mixer = gba.mixer.mixer(); + /// # const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav"); /// let mut channel = SoundChannel::new_high_priority(MY_BGM); /// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority /// /// // Later, stop that particular channel - /// mixer.channel(bgm_channel_id).stop(); + /// mixer.channel(&bgm_channel_id).expect("Expected still to be playing").stop(); + /// # } /// ``` pub fn channel(&mut self, id: &ChannelId) -> Option<&'_ mut SoundChannel> { if let Some(channel) = &mut self.channels[id.0] { From 65258ac5750fd7279a214c66d076ee174b9ce4c7 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 12 Jul 2022 15:07:59 +0100 Subject: [PATCH 8/8] Add running the doctests to the ci --- justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/justfile b/justfile index 15709c8c..cdc3097a 100644 --- a/justfile +++ b/justfile @@ -37,7 +37,7 @@ run-game game: run-game-debug game: (cd "examples/{{game}}" && cargo run) -ci: build-debug clippy test build-release test-release build-roms build-book +ci: build-debug clippy test build-release test-release doctest-agb build-roms build-book build-roms: just _build-rom "examples/the-purple-night" "PURPLENIGHT"