From 225147a94f8baf30c6e7db7084c5b8663d52ca3c Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 17 Jan 2022 13:19:52 -0500 Subject: [PATCH 1/4] Document Spinda spot algorithm --- include/pokemon.h | 5 ++- src/pokemon.c | 84 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 63 insertions(+), 26 deletions(-) diff --git a/include/pokemon.h b/include/pokemon.h index 28460bbe6..8039a4fdd 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -239,10 +239,13 @@ struct BattleMove u8 flags; }; +#define SPINDA_SPOT_WIDTH 16 +#define SPINDA_SPOT_HEIGHT 16 + struct SpindaSpot { u8 x, y; - u16 image[16]; + u16 image[SPINDA_SPOT_HEIGHT]; }; struct __attribute__((packed)) LevelUpMove 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) From 177863da4728237c8fef4e6b69417d91d1b003cd Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 17 Jan 2022 16:04:02 -0500 Subject: [PATCH 2/4] Fix typo --- src/pokemon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pokemon.c b/src/pokemon.c index e5d321f5a..bc83bc588 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5670,8 +5670,8 @@ u16 SpeciesToCryId(u16 species) 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 + 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. From 313f14ed63f52b6b4371cabe858c5cde5705cc0f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 17 Jan 2022 17:00:18 -0500 Subject: [PATCH 3/4] Add Spinda spot color constants --- src/pokemon.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/pokemon.c b/src/pokemon.c index bc83bc588..902d576f7 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5653,9 +5653,12 @@ u16 SpeciesToCryId(u16 species) return gSpeciesIdToCryId[species - (SPECIES_TREECKO - 1)]; } -// To draw the spot, add 4 to the color indexes -#define SPOT_COLOR_ADJUSTMENT 4 +// Spots can be drawn on Spinda's color indexes 1, 2, or 3 +#define FIRST_SPOT_COLOR 1 +#define LAST_SPOT_COLOR 3 +// To draw a spot pixel, add 4 to the color index +#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 @@ -5711,13 +5714,15 @@ u16 SpeciesToCryId(u16 species) if (column & 1) \ { \ /* Draw spot pixel if this is Spinda's body color */ \ - if ((u8)((*destPixels & 0xF0) - (1 << 4)) <= (2 << 4)) \ + if ((u8)((*destPixels & 0xF0) - (FIRST_SPOT_COLOR << 4))\ + <= ((LAST_SPOT_COLOR - FIRST_SPOT_COLOR) << 4))\ *destPixels += (SPOT_COLOR_ADJUSTMENT << 4); \ } \ else \ { \ /* Draw spot pixel if this is Spinda's body color */ \ - if ((u8)((*destPixels & 0xF) - 1) <= 2) \ + if ((u8)((*destPixels & 0xF) - FIRST_SPOT_COLOR) \ + <= (LAST_SPOT_COLOR - FIRST_SPOT_COLOR)) \ *destPixels += SPOT_COLOR_ADJUSTMENT; \ } \ } \ From 30d970441839e8b2473f6962ab9b70f4f8422507 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 17 Jan 2022 17:27:17 -0500 Subject: [PATCH 4/4] Specify unsigned in spot comment --- src/pokemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pokemon.c b/src/pokemon.c index 902d576f7..08a6fd0f9 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5674,7 +5674,7 @@ u16 SpeciesToCryId(u16 species) The macro then loops over the 16x16 spot image. For each bit in the spot's binary image, 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 + pixel on Spinda satisfies the following formula: ((u8)(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.