aboutsummaryrefslogtreecommitdiff
path: root/arm9/source/devices/math.c
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2025-09-19 13:17:14 +1200
committerBen Bridle <ben@derelict.engineering>2025-09-19 13:32:32 +1200
commitbb1aa5958d1b67707dcf0f6b08bfaf0b408bd46e (patch)
treeb26d07ed58aaf7a5230fc3e28c103d616abfa9b8 /arm9/source/devices/math.c
parent9612c307f00c4313d73fe0c3a86c05c8d8cd514e (diff)
downloadbedrock-nds-bb1aa5958d1b67707dcf0f6b08bfaf0b408bd46e.zip
Massive rewrite
This commit rewrites the emulator halfway from scratch to make it easier to change and maintain in the future. The emulator core was rewritten to adhere to the released Bedrock specification (earlier versions implemented an older prototype specification, which is no longer relevant). This commit also adds proper support for running multiple concurrent Bedrock instances. This was previously supported in a limited manner for the on-screen keyboard, but now works for any regular program as well, with switching being performed by pressing the L or R bumper buttons. This is disabled by default, as programs will still need to be baked into the emulator and hand-loaded.
Diffstat (limited to 'arm9/source/devices/math.c')
-rw-r--r--arm9/source/devices/math.c143
1 files changed, 98 insertions, 45 deletions
diff --git a/arm9/source/devices/math.c b/arm9/source/devices/math.c
index bb592e0..33aeb63 100644
--- a/arm9/source/devices/math.c
+++ b/arm9/source/devices/math.c
@@ -1,66 +1,119 @@
-#include <nds.h>
-#include <math.h>
#include "math.h"
-#include "../bang.h"
-#define CLEAR \
- math->sqrt_rc = FALSE;\
- math->atan_rc = FALSE;\
- math->prod_rc = FALSE;\
- math->quot_rc = FALSE;\
- math->rem_rc = FALSE;
-void set_op1_high(MathDevice *math, u8 high) { SET_HIGH(math->op1, high); CLEAR; }
-void set_op1_low( MathDevice *math, u8 low) { SET_LOW(math->op1, low); CLEAR; }
-void set_op2_high(MathDevice *math, u8 high) { SET_HIGH(math->op2, high); CLEAR; }
-void set_op2_low( MathDevice *math, u8 low) { SET_LOW(math->op2, low); CLEAR; }
+// Angle conversion constants.
+const double fromRadians = 10430.378350470453; // 65536 / 2π
+const double toRadians = 0.00009587379924285257; // 2π / 65536
-u16 get_sqrt(MathDevice *math) {
- if (!math->sqrt_rc) {
- u32 input = math->op1 << 16 | math->op2;
- math->sqrt = sqrt32(input);
- math->sqrt_rc = TRUE;
+
+// Reset the math device.
+void math_reset(MathDevice *math) {
+ math->x = 0;
+ math->y = 0;
+ math->r = 0;
+ math->t = 0;
+ math_clear_cartesian(math);
+ math_clear_polar(math);
+}
+
+// Clear all values calculated from cartesian coordinates.
+void math_clear_cartesian(MathDevice *math) {
+ math->r_cached = false;
+ math->t_cached = false;
+ math->prod_cached = false;
+ math->quot_cached = false;
+ math->rem_cached = false;
+}
+
+// Clear all values calculated from polar coordinates.
+void math_clear_polar(MathDevice *math) {
+ math->x_cached = false;
+ math->y_cached = false;
+}
+
+// Calculate the x coordinate of the polar point.
+s16 math_get_x(MathDevice *math) {
+ if (!math->x_cached) {
+ double x = cos(math->t * toRadians) * math->r;
+ if (-32768.0 <= x && x <= 32768.0) {
+ math->x_read = x;
+ } else {
+ math->x_read = 0;
+ }
+ math->x_cached = true;
+ }
+ return math->x_read;
+}
+
+// Calculate the y coordinate of the polar point.
+s16 math_get_y(MathDevice *math) {
+ if (!math->y_cached) {
+ double y = sin(math->t * toRadians) * math->r;
+ if (-32768.0 <= y && y <= 32767.0) {
+ math->y_read = y;
+ } else {
+ math->y_read = 0;
+ }
+ math->y_cached = true;
+ }
+ return math->y_read;
+}
+
+// Calculate the r coordinate of the cartesian point.
+u16 math_get_r(MathDevice *math) {
+ if (!math->r_cached) {
+ u32 x2 = math->x * math->x;
+ u32 y2 = math->y * math->y;
+ math->r_read = sqrt32(x2 + y2);
+ math->r_cached = true;
}
- return math->sqrt;
+ return math->r_read;
}
-u16 get_atan(MathDevice *math) {
- if (!math->atan_rc) {
- if (math->op1 || math->op2) {
- double op1 = (s16) math->op1;
- double op2 = (s16) math->op2;
- const double scale = 10430.378350470453; // PI * 32768
- math->atan = (s32) (atan2(op1, op2) * scale);
+// Calculate the t coordinate of the cartesian point.
+u16 math_get_t(MathDevice *math) {
+ if (!math->t_cached) {
+ if (math->x || math->y) {
+ math->t_read = atan2(math->y, math->x) * fromRadians;
+ } else {
+ math->t_read = 0;
}
- math->atan_rc = TRUE;
+ math->t_cached = true;
}
- return math->atan;
+ return math->t_read;
}
-u32 get_prod(MathDevice *math) {
- if (!math->prod_rc) {
- math->prod = math->op1 * math->op2;
- math->prod_rc = TRUE;
+// Calculate the product of x by y.
+u32 math_get_prod(MathDevice *math) {
+ if (!math->prod_cached) {
+ math->prod_read = (u16)math->x * (u16)math->y;
+ math->prod_cached = true;
}
- return math->prod;
+ return math->prod_read;
}
-u16 get_quot(MathDevice *math) {
- if (!math->quot_rc) {
- if (math->op2) {
- math->quot = div32(math->op1, math->op2);
+// Calculate the quotient of x by y.
+u16 math_get_quot(MathDevice *math) {
+ if (!math->quot_cached) {
+ if (math->y) {
+ math->quot_read = div32((u16)math->x, (u16)math->y);
+ } else {
+ math->quot_read = 0;
}
- math->quot_rc = TRUE;
+ math->quot_cached = true;
}
- return math->quot;
+ return math->quot_read;
}
-u16 get_rem(MathDevice *math) {
- if (!math->rem_rc) {
- if (math->op2) {
- math->rem = mod32(math->op1, math->op2);
+// Calculate the remainder of x by y.
+u16 math_get_rem(MathDevice *math) {
+ if (!math->rem_cached) {
+ if (math->y) {
+ math->rem_read = mod32((u16)math->x, (u16)math->y);
+ } else {
+ math->rem_read = 0;
}
- math->rem_rc = TRUE;
+ math->rem_cached = true;
}
- return math->rem;
+ return math->rem_read;
}