summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGriffinR <griffin.g.richards@gmail.com>2022-01-17 13:19:52 -0500
committerGriffinR <griffin.g.richards@gmail.com>2022-01-17 15:34:18 -0500
commit225147a94f8baf30c6e7db7084c5b8663d52ca3c (patch)
tree3b2ce7a2ed30d5222053c5e11e5011ad66e49cd0 /src
parent4024b3f1b3a9d51e42fc8a49cf361bd22484c82f (diff)
Document Spinda spot algorithm
Diffstat (limited to 'src')
-rw-r--r--src/pokemon.c84
1 files changed, 59 insertions, 25 deletions
diff --git a/src/pokemon.c b/src/pokemon.c
index 9476dbb2e..e5d321f5a 100644
--- a/src/pokemon.c
+++ b/src/pokemon.c
@@ -1345,10 +1345,10 @@ static const u16 sHoennToNationalOrder[NUM_SPECIES - 1] =
const struct SpindaSpot gSpindaSpotGraphics[] =
{
- {16, 7, INCBIN_U16("graphics/spinda_spots/spot_0.bin")},
- {40, 8, INCBIN_U16("graphics/spinda_spots/spot_1.bin")},
- {22, 25, INCBIN_U16("graphics/spinda_spots/spot_2.bin")},
- {34, 26, INCBIN_U16("graphics/spinda_spots/spot_3.bin")}
+ {.x = 16, .y = 7, .image = INCBIN_U16("graphics/spinda_spots/spot_0.bin")},
+ {.x = 40, .y = 8, .image = INCBIN_U16("graphics/spinda_spots/spot_1.bin")},
+ {.x = 22, .y = 25, .image = INCBIN_U16("graphics/spinda_spots/spot_2.bin")},
+ {.x = 34, .y = 26, .image = INCBIN_U16("graphics/spinda_spots/spot_3.bin")}
};
#include "data/pokemon/item_effects.h"
@@ -5653,42 +5653,76 @@ u16 SpeciesToCryId(u16 species)
return gSpeciesIdToCryId[species - (SPECIES_TREECKO - 1)];
}
-#define DRAW_SPINDA_SPOTS \
+// To draw the spot, add 4 to the color indexes
+#define SPOT_COLOR_ADJUSTMENT 4
+
+/*
+ The macro below handles drawing the randomly-placed spots on Spinda's front sprite.
+ Spinda has 4 spots, each with an entry in gSpindaSpotGraphics. Each entry contains
+ a base x and y coordinate for the spot and a 16x16 binary image. Each bit in the image
+ determines whether that pixel should be considered part of the spot.
+
+ The position of each spot is randomized using the Spinda's personality. The entire 32 bit
+ personality value is used, 4 bits for each coordinate of the 4 spots. If the personality
+ value is 0x87654321, then 0x1 will be used for the 1st spot's x coord, 0x2 will be used for
+ the 1st spot's y coord, 0x3 will be used for the 2nd spot's x coord, and so on. Each
+ coordinate is calculated as (baseCoord + (given 4 bits of personality) - 8). In effect this
+ means each spot can start at any position -8 to +7 off of its base coordinates (256 possibilities).
+
+ The macro then loops over the 16x16 spot image. For each bit in the spot's binary image, if
+ if the bit is set then it's part of the spot; try to draw it. A pixel is drawn on Spinda
+ if the pixel on Spinda satisfies the following formula: (colorIndex - 1 <= 2). The -1 excludes
+ transparent pixels, as these are index 0. Therefore only colors 1, 2, or 3 on Spinda will
+ allow a spot to be drawn. These color indexes are Spinda's light brown body colors. To create
+ the spot it adds 4 to the color index, so Spinda's spots will be colors 5, 6, and 7.
+
+ The above is done two different ways in the macro: one with << 4, and one without. This
+ is because Spinda's sprite is a 4 bits per pixel image, but the pointer to Spinda's pixels
+ (destPixels) is an 8 bit pointer, so it addresses two pixels. Shifting by 4 accesses the 2nd
+ of these pixels, so this is done every other time.
+*/
+#define DRAW_SPINDA_SPOTS(personality, dest) \
{ \
- int i; \
- for (i = 0; i < 4; i++) \
+ s32 i; \
+ for (i = 0; i < (s32)ARRAY_COUNT(gSpindaSpotGraphics); i++) \
{ \
- int j; \
+ s32 row; \
u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8); \
u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8); \
\
- for (j = 0; j < 16; j++) \
+ for (row = 0; row < SPINDA_SPOT_HEIGHT; row++) \
{ \
- int k; \
- s32 row = gSpindaSpotGraphics[i].image[j]; \
+ s32 column; \
+ s32 spotPixelRow = gSpindaSpotGraphics[i].image[row]; \
\
- for (k = x; k < x + 16; k++) \
+ for (column = x; column < x + SPINDA_SPOT_WIDTH; column++) \
{ \
- u8 *val = dest + ((k / 8) * 32) + \
- ((k % 8) / 2) + \
- ((y >> 3) << 8) + \
- ((y & 7) << 2); \
+ /* Get target pixels on Spinda's sprite */ \
+ u8 *destPixels = dest + ((column / 8) * TILE_SIZE_4BPP) + \
+ ((column % 8) / 2) + \
+ ((y / 8) * TILE_SIZE_4BPP * 8) + \
+ ((y % 8) * 4); \
\
- if (row & 1) \
+ /* Is this pixel in the 16x16 spot image part of the spot? */ \
+ if (spotPixelRow & 1) \
{ \
- if (k & 1) \
+ /* destPixels addressess two pixels, alternate which */ \
+ /* of the two pixels is being considered for drawing */ \
+ if (column & 1) \
{ \
- if ((u8)((*val & 0xF0) - 0x10) <= 0x20) \
- *val += 0x40; \
+ /* Draw spot pixel if this is Spinda's body color */ \
+ if ((u8)((*destPixels & 0xF0) - (1 << 4)) <= (2 << 4)) \
+ *destPixels += (SPOT_COLOR_ADJUSTMENT << 4); \
} \
else \
{ \
- if ((u8)((*val & 0xF) - 0x01) <= 0x02) \
- *val += 0x04; \
+ /* Draw spot pixel if this is Spinda's body color */ \
+ if ((u8)((*destPixels & 0xF) - 1) <= 2) \
+ *destPixels += SPOT_COLOR_ADJUSTMENT; \
} \
} \
\
- row >>= 1; \
+ spotPixelRow >>= 1; \
} \
\
y++; \
@@ -5705,13 +5739,13 @@ static void DrawSpindaSpotsUnused(u16 species, u32 personality, u8 *dest)
if (species == SPECIES_SPINDA
&& dest != gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_LEFT]
&& dest != gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_RIGHT])
- DRAW_SPINDA_SPOTS;
+ DRAW_SPINDA_SPOTS(personality, dest);
}
void DrawSpindaSpots(u16 species, u32 personality, u8 *dest, bool8 isFrontPic)
{
if (species == SPECIES_SPINDA && isFrontPic)
- DRAW_SPINDA_SPOTS;
+ DRAW_SPINDA_SPOTS(personality, dest);
}
void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies)