Prepare for trouble... and make it.... fixed point?

To protect the world from the soft float library...
To unite all arithmetic within our binary...
To denounce the evils of floating point precision...
To save more kilobytes - that's our vision....

(god this is cringe)

All floating point math has been eliminated, and replaced with
equivalent or near-equivalent fixed-point math.

sprite_data.cpp uses Q16, and get_rand_range uses a full Q32 to
ensure that the exact same results are generated as before, at
the cost of some inline assembly to do a umull (__aeabi_lmul is a
little excessive when the lower 32 bits are discarded)

This eliminates all of the expensive double precision float library,
saving a few kilobytes.

Additionally, the unneccessary parts of nanoprintf have been
disabled. There is no need for precision specifiers, long longs, or
floats.
This commit is contained in:
easyaspi314 2025-06-30 13:05:32 -04:00
parent 16345eff59
commit 750641c78f
4 changed files with 29 additions and 11 deletions

View File

@ -1,4 +1,11 @@
#define NANOPRINTF_IMPLEMENTATION 1
// Remove what we don't need
#define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 0
#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 0
#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 0
#define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 0
#define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 0
#define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 0
#include "libstd_replacements.h"
#include "libraries/nanoprintf/nanoprintf.h"

View File

@ -220,7 +220,7 @@ int pokedex_loop()
if (is_caught(dex_shift + i + 1 + mythic_skip))
{
tte_set_pos(dex_x_cord + (1.5 * 8), (i * 8 * 2) + 32);
tte_set_pos(dex_x_cord + (3 * 8 / 2), (i * 8 * 2) + 32);
temp_string[0] = 0xF7;
temp_string[1] = 0xF8;
temp_string[2] = 0xFF;

View File

@ -40,7 +40,15 @@ u16 get_rev_rand_u16(u32 input)
return (get_rev_rand_u32(input) >> 16);
}
unsigned int get_rand_range(unsigned int inc_min, unsigned int exc_max)
// Force ARM mode. In Thumb mode this imports __aeabi_lmul.
__attribute__((target("arm"), noinline))
static unsigned multiply_high(unsigned x, unsigned y)
{
return ((double)((get_rand_u32() / (double)0x100000000) * (exc_max - inc_min)) + inc_min);
return ((unsigned long long)x * y) >> 32; // umull
}
unsigned get_rand_range(unsigned inc_min, unsigned exc_max)
{
// fixed point: get_rand_u32() / (float)0x100000000 * (exc_max - inc_min) + inc_min
return multiply_high(get_rand_u32(), exc_max - inc_min) + inc_min;
}

View File

@ -13,6 +13,7 @@ int y_offset = 0;
int y_offset_timer = 0;
int y_offset_direction = 1;
// BACKGROUNDS
#define QF(x) ((unsigned)(x * 65536.0f))
#include "background.h"
void load_background()
@ -79,10 +80,12 @@ void set_background_pal(int curr_rom_id, bool dark, bool fade)
}
if (fade)
{
#define NUM_CYCLES 30.0
#define NUM_CYCLES 30
COLOR curr_pal_bg[8];
COLOR old_pal[3];
COLOR new_pal[3];
unsigned INV_NUM_CYCLES = QF(1.0 / NUM_CYCLES);
tonccpy(curr_pal_bg, &pal_bg_mem[0], 16);
for (int n = 0; n <= NUM_CYCLES; n++)
{
@ -94,9 +97,9 @@ void set_background_pal(int curr_rom_id, bool dark, bool fade)
new_pal[b] = (new_pal_bg[i] >> (b * 5)) & 0b11111;
}
pal_bg_mem[i] = RGB15(
(((NUM_CYCLES - n) / NUM_CYCLES) * old_pal[0]) + ((n / NUM_CYCLES) * new_pal[0]),
(((NUM_CYCLES - n) / NUM_CYCLES) * old_pal[1]) + ((n / NUM_CYCLES) * new_pal[1]),
(((NUM_CYCLES - n) / NUM_CYCLES) * old_pal[2]) + ((n / NUM_CYCLES) * new_pal[2]));
((((NUM_CYCLES - n) * INV_NUM_CYCLES) * old_pal[0]) + ((n * INV_NUM_CYCLES) * new_pal[0])) >> 16,
((((NUM_CYCLES - n) * INV_NUM_CYCLES) * old_pal[1]) + ((n * INV_NUM_CYCLES) * new_pal[1])) >> 16,
((((NUM_CYCLES - n) * INV_NUM_CYCLES) * old_pal[2]) + ((n * INV_NUM_CYCLES) * new_pal[2])) >> 16);
}
global_next_frame();
}
@ -879,10 +882,10 @@ void update_front_box_sprite(Simplified_Pokemon *curr_pkmn)
LZ77UnCompWram((const unsigned short *)palette_location, buffer); // This is a little silly, but it's being weird with bytes vs shorts when we copy it directly
for (int i = 0; i < 16; i++)
{
double red = (buffer[i] >> 0) & 0b11111;
double green = (buffer[i] >> 5) & 0b11111;
double blue = (buffer[i] >> 10) & 0b11111;
int grey = (0.299 * red) + (0.587 * green) + (0.114 * blue);
unsigned red = (buffer[i] >> 0) & 0b11111;
unsigned green = (buffer[i] >> 5) & 0b11111;
unsigned blue = (buffer[i] >> 10) & 0b11111;
unsigned grey = ((QF(0.299f) * red) + (QF(0.587f) * green) + (QF(0.114f) * blue)) >> 16;
// buffer[i] = RGB15_SAFE(red, ((int)green >> 1), 0);
buffer[i] = RGB15_SAFE(grey, (grey >> 1), 0);