mirror of
https://github.com/italicsjenga/gba.git
synced 2024-12-23 10:51:30 +11:00
arctan and arctan2
This commit is contained in:
parent
2ecf62e06e
commit
e38ddee38b
|
@ -3,6 +3,12 @@
|
||||||
* **0.9.2:**
|
* **0.9.2:**
|
||||||
* Adds support for more BIOS functions, though not all functions are as
|
* Adds support for more BIOS functions, though not all functions are as
|
||||||
clearly documented as I'd like.
|
clearly documented as I'd like.
|
||||||
|
* Made much more of the `Fixed` type const friendly. Most ops now have an
|
||||||
|
inherent method that is `const fn` as well as implementing the `core::ops`
|
||||||
|
trait (the trait fn just calls the inherent fn). This means that you can't
|
||||||
|
do `x + y` in a const context, but you can do `x.add(y)`. This is not the
|
||||||
|
best system, but until const trait impls are stable this is the best middle
|
||||||
|
ground.
|
||||||
* **0.9.1:**
|
* **0.9.1:**
|
||||||
* Adds some randomization support directly into the crate.
|
* Adds some randomization support directly into the crate.
|
||||||
* Added more methods to the `Fixed` type.
|
* Added more methods to the `Fixed` type.
|
||||||
|
|
66
src/bios.rs
66
src/bios.rs
|
@ -8,11 +8,31 @@
|
||||||
//! of the function ends up inlined). Despite this higher cost, some bios
|
//! of the function ends up inlined). Despite this higher cost, some bios
|
||||||
//! functions are useful enough to justify the overhead.
|
//! functions are useful enough to justify the overhead.
|
||||||
|
|
||||||
use crate::interrupts::IrqBits;
|
use crate::{fixed::i16fx14, interrupts::IrqBits};
|
||||||
|
|
||||||
// Note(Lokathor): All `swi` calls will preserve the flags. You should generally
|
// Note(Lokathor): All `swi` calls will preserve the flags. You should generally
|
||||||
// not use any other inline-asm options with `swi` calls.
|
// not use any other inline-asm options with `swi` calls.
|
||||||
|
|
||||||
|
/// `0x00`: Software Reset.
|
||||||
|
///
|
||||||
|
/// This clears the BIOS portion of IWRAM (the top `0x200` bytes), resets the
|
||||||
|
/// SVC, IRQ, and SYS stack pointers to their defaults, then performs a `bx r14`
|
||||||
|
/// to go to an address based on what's written to the byte at `0x0300_7FFA`:
|
||||||
|
/// * zero: `0x0800_0000` (ROM)
|
||||||
|
/// * non-zero: `0x0200_0000` (IWRAM).
|
||||||
|
///
|
||||||
|
/// (Note: the target address is determined *before* clearing the top of IWRAM.)
|
||||||
|
#[inline]
|
||||||
|
#[instruction_set(arm::t32)]
|
||||||
|
pub fn SoftReset() -> ! {
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm! {
|
||||||
|
"swi #0x00",
|
||||||
|
options(noreturn),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// `0x04`: Waits for a specific interrupt type(s) to happen.
|
/// `0x04`: Waits for a specific interrupt type(s) to happen.
|
||||||
///
|
///
|
||||||
/// Pauses the CPU until any of the interrupt types set in `target_irqs` to
|
/// Pauses the CPU until any of the interrupt types set in `target_irqs` to
|
||||||
|
@ -62,6 +82,50 @@ pub fn VBlankIntrWait() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `0x09`: Arc tangent.
|
||||||
|
///
|
||||||
|
/// * **Returns:** The output is in the range +/- `pi/2`, but accuracy is worse
|
||||||
|
/// outside of +/- `pi/4`.
|
||||||
|
#[inline]
|
||||||
|
#[instruction_set(arm::t32)]
|
||||||
|
pub fn ArcTan(theta: i16fx14) -> i16fx14 {
|
||||||
|
let mut i = theta.into_raw();
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm! {
|
||||||
|
"swi #0x09",
|
||||||
|
inout("r0") i,
|
||||||
|
out("r1") _,
|
||||||
|
out("r3") _,
|
||||||
|
options(pure, nomem, preserves_flags),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
i16fx14::from_raw(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `0x0A`: The "2-argument arctangent" ([atan2][wp-atan2]).
|
||||||
|
///
|
||||||
|
/// [wp-atan2]: https://en.wikipedia.org/wiki/Atan2
|
||||||
|
///
|
||||||
|
/// * **Returns:** The angle of the input vector, with `u16::MAX` being
|
||||||
|
/// equivalent to `2pi`.
|
||||||
|
#[inline]
|
||||||
|
#[instruction_set(arm::t32)]
|
||||||
|
pub fn ArcTan2(x: i16fx14, y: i16fx14) -> u16 {
|
||||||
|
let x = x.into_raw();
|
||||||
|
let y = y.into_raw();
|
||||||
|
let output: u16;
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm! {
|
||||||
|
"swi #0x0A",
|
||||||
|
inout("r0") x => output,
|
||||||
|
inout("r1") y => _,
|
||||||
|
out("r3") _,
|
||||||
|
options(pure, nomem, preserves_flags),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
/// Used to provide info to a call of the [`BitUnPack`] function.
|
/// Used to provide info to a call of the [`BitUnPack`] function.
|
||||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
@ -6,6 +6,12 @@ use core::ops::*;
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub type i16fx8 = Fixed<i16, 8>;
|
pub type i16fx8 = Fixed<i16, 8>;
|
||||||
|
|
||||||
|
/// `i16` with 14 bits of fixed-point fraction.
|
||||||
|
///
|
||||||
|
/// This is used by the [`ArcTan`] and [`ArcTan2`] BIOS functions.
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub type i16fx14 = Fixed<i16, 14>;
|
||||||
|
|
||||||
/// `i32` with 8 bits of fixed-point fraction.
|
/// `i32` with 8 bits of fixed-point fraction.
|
||||||
///
|
///
|
||||||
/// This is used by the background reference point entries.
|
/// This is used by the background reference point entries.
|
||||||
|
|
Loading…
Reference in a new issue