Alchemy
Loading...
Searching...
No Matches

sprites.c

Go to the documentation of this file.
1/// @file
2/// Battle sprites: enemy sprite slots and the party's weapon sprites.
3/// Part of battle.c, the battle object, compiled only through it.
4
6
7/// Readies the sprite of every unit in the battle (releasing those of units
8/// that left) and sets each one's display mode and motion afresh. Called by
9/// Battle_RunEncounter as the battle is set up, by
10/// BattlePresentation_DispatchAction, BattlePresentation_RunUnitTransition,
11/// the auto battle and BattleTargetExec after a call for help, and through
12/// the far stub BattleActor_CommitPlacementFar by BattleFx_RunParticleStreams.
13void BattleObjPut(void) {
14 s16 unitIds[14];
15
18}
19
20/// Readies the sprite of every unit in the battle (releasing those of units
21/// that left), keeping their modes and motions. Called by BattlePres_RunAttack.
23 s16 unitIds[14];
24
27}
28
29/// Returns the palette of unit id's battle object. Called by
30/// BattleEvent_Playback and BattleMotion_FlashHit, and through its far stub
31/// by the effect dispatcher (effect/parts/dispatch.c).
33
34/// The battle has six enemy sprite slots; a large enemy takes two side by
35/// side, a small one (BattleClass_IsSmall) one.
36#define ENEMY_SPRITE_SLOTS 6
37
38/// Returns 1 if an enemy of class classId would find room among the enemy
39/// sprite slots: one free slot for a small enemy, two free side by side for
40/// a large one. Called by BattleTargetExec before an enemy calls for help.
41s32 EnemyCheck(s32 classId) {
42 struct BattleWork *battle;
43 s32 needsSingleSlot;
44 s32 spriteSlot;
45
46 needsSingleSlot = BattleClass_IsSmall(classId);
47 battle = gBattleWork;
48 for (spriteSlot = 0; spriteSlot < ENEMY_SPRITE_SLOTS; spriteSlot++) {
49 if (battle->spriteSlots[spriteSlot] != 0)
50 continue;
51 if (needsSingleSlot != 0)
52 break;
53 if (spriteSlot < ENEMY_SPRITE_SLOTS - 1 &&
54 battle->spriteSlots[spriteSlot + 1] == 0)
55 break;
56 }
57 return spriteSlot != ENEMY_SPRITE_SLOTS;
58}
59
60/// Loads an enemy unit's battle sprite into the first free enemy sprite
61/// slots (one for a small enemy, two side by side for a large one) and
62/// records the unit as their owner. Two sprites take a second part,
63/// loaded the same way into further slots. Returns the first slot and the
64/// sprite as (slot << 12) | sprite, or 0 for a party member's unit or when
65/// a load fails. Called by BattleObjMake. Writes gBattleWork->spriteSlots
66/// and the slots' 16 KB sprite buffers at Ram_ActorSpriteSlots.
68 s32 spritePart;
69 struct BattleWork *battle = gBattleWork;
70 struct BattleUnit *unit = UnitGetFar(unitId);
71 s32 needsSingleSlot = BattleClass_IsSmall(unit->classId);
72 /* FAKEMATCH(temporary): result cleared a halfword at a time, which keeps
73 * spritePart a copy of its register (mov r4, r10); as an s32 set to 0, 1 of
74 * 114 instructions differ in tbs-en. */
75 union {
76 s32 value;
77 u16 halves[2];
78 } result;
79 s32 sprite;
80
81 result.halves[0] = 0;
82 result.halves[1] = 0;
83 sprite = BattleClass_GetSprite(unit->classId);
84 spritePart = result.value;
85 // Once for the sprite, and again for its second part if it has one.
86 do {
87 s32 slot;
88
89 // A unit with a classIndex is no enemy: nothing is loaded and the
90 // result stays 0.
91 if (unit->classIndex != 0)
92 continue;
93
94 // The first free slot (and, for a large enemy, the one after it).
95 for (slot = 0; slot < ENEMY_SPRITE_SLOTS; slot++) {
96 if (battle->spriteSlots[slot] != 0)
97 continue;
98 if (needsSingleSlot)
99 break;
100 if (slot < ENEMY_SPRITE_SLOTS - 1 && battle->spriteSlots[slot + 1] == 0)
101 break;
102 }
103
104 if (slot == ENEMY_SPRITE_SLOTS)
105 break;
106
107 {
108 s32 palette = BattleClass_GetPalette(unit->classId);
109 // Each slot owns 16 KB of sprite buffer.
110 s32 spriteBuffer = (slot << 14) + (s32)Ram_ActorSpriteSlots;
111
112 if (ResourceSlot_LoadFar(slot, (u32 *)spriteBuffer, sprite + spritePart,
113 palette) == 0)
114 return 0;
115 }
116
117 /* FAKEMATCH(dead): two updates that cancel, raising sprite's priority in
118 * allocation; without them, 9 of 114 instructions differ in tbs-en. */
119 sprite ^= 1;
120 sprite ^= 1;
121 if (spritePart == 0)
122 result.value = (slot << 12) | sprite;
123
124 battle->spriteSlots[slot] = unitId;
125 if (!needsSingleSlot)
126 battle->spriteSlots[slot + 1] = unitId;
127
128 if (sprite != SPRITE_WITH_SECOND_PART_A &&
130 break;
131 } while (++spritePart <= 1);
132
133 return result.value;
134}
135
136/// Frees every enemy sprite slot unit unitId holds, unloading its sprite.
137/// Called by BattleObj_MarkForRelease. Clears those gBattleWork->spriteSlots.
138#ifdef UBFIX
140#else
142#endif
143 struct BattleWork *battle = gBattleWork;
144 s32 spriteSlot;
145
146 for (spriteSlot = 0; spriteSlot < ENEMY_SPRITE_SLOTS; spriteSlot++) {
147 if (battle->spriteSlots[spriteSlot] == unitId) {
148 ResourceSlot_LoadFar(spriteSlot, 0, 0, 0);
149 battle->spriteSlots[spriteSlot] = 0;
150 }
151 }
152}
153
154// gResource_SlotAssignments: each entry is a weapon's item id in the low nine
155// bits and its kind above them; the list ends with -1.
156#define WEAPON_ITEM_MASK 0x1ff
157#define WEAPON_KIND_SHIFT 9
158#define WEAPON_KIND_NONE 6
159
160/// Returns the kind of the weapon whose item id is itemId (0 to 5), which
161/// picks a party member's attack animation, or WEAPON_KIND_NONE for an item
162/// the list lacks. Called by BattleUnit_LookupWeaponValueByClass.
164 /// gResource_SlotAssignments seen as volatile, for the FAKEMATCH below.
165 struct SlotAssignmentView {
166 volatile u16 entries[52]; ///< bits: 15..9 weapon kind | 8..0 item id
167 };
168 s32 assignmentIndex;
169 s32 assignment;
170 u32 reloadedAssignment;
171 s32 weaponKind;
172
173 for (assignmentIndex = 0;; assignmentIndex++) {
174 assignment = gResource_SlotAssignments[assignmentIndex];
175 if (itemId == (assignment & WEAPON_ITEM_MASK)) {
176 /* FAKEMATCH(volatile): the entry read again through a volatile view,
177 * a second ldrh as in the ROM; through the plain array the first load is
178 * reused, and 11 of 24 instructions differ in tbs-en. */
179 reloadedAssignment =
180 ((struct SlotAssignmentView *)gResource_SlotAssignments)
181 ->entries[assignmentIndex];
182 weaponKind = reloadedAssignment >> WEAPON_KIND_SHIFT;
183 break;
184 }
185 if ((s16)assignment == -1) {
186 weaponKind = WEAPON_KIND_NONE;
187 break;
188 }
189 }
190 return weaponKind;
191}
192
193/// Returns the weapon sprite a party member's attack shows for the kind of
194/// weapon they have equipped (gBattleUnit_WeaponAnimsClass*), or 0 for no
195/// weapon, for Felix, or for a unit that is no party member. Called by
196/// BattleObjMake.
198 struct BattleUnit *unit;
199 s32 slot;
200 s32 weaponSprite;
201
202 unit = UnitGetFar(unitId);
204 weaponSprite = 0;
205 if (slot >= 0) {
206 s32 weaponKind;
207
208 weaponKind =
210 switch (unit->classId) {
211 case ISAAC:
212 weaponSprite = gBattleUnit_WeaponAnimsClass0[weaponKind];
213 break;
214 case GARET:
215 weaponSprite = gBattleUnit_WeaponAnimsClass1[weaponKind];
216 break;
217 case IVAN:
218 weaponSprite = gBattleUnit_WeaponAnimsClass2[weaponKind];
219 break;
220 case MIA:
221 weaponSprite = gBattleUnit_WeaponAnimsClass3[weaponKind];
222 break;
223 case FELIX:
224 break;
225 case JENNA:
226 weaponSprite = gBattleUnit_WeaponAnimsClass5[weaponKind];
227 break;
228 }
229 }
230 return weaponSprite;
231}
s32 BattleClass_GetPalette(s32 index)
Returns the class's sprite palette.
Definition classes.c:35
s32 BattleClass_IsSmall(s32 index)
Returns 1 for a small class, which takes one enemy sprite slot instead of two and stands closer to it...
Definition classes.c:45
s32 BattleClass_GetSprite(s32 index)
Returns the class's battle sprite, row 0's for a class out of range.
Definition classes.c:24
s32 BattleParty_ListActorIds(s32 sideMask, u16 *unitIds)
Lists the units in the battle's unit lists on the sides in sideMask, party first, skipping those remo...
Definition encounter.c:510
void BattleActor_SpawnObjectsForList(s16 *unitIds, s32 refreshPoses)
Readies the sprites of the units in list: releases those of every place list lacks,...
Definition objects.c:356
struct BattleObj * BattleObjGet(s32 unitId)
Returns unitId's battle object, through its place, or null for a unit with no place.
Definition objects.c:480
void BattleObjPut(void)
Readies the sprite of every unit in the battle (releasing those of units that left) and sets each one...
Definition sprites.c:13
void BattleParty_ListAllUnitsAndSubmit(void)
Readies the sprite of every unit in the battle (releasing those of units that left),...
Definition sprites.c:22
s32 SummonSlot_RegisterActorSprites(s32 unitId)
Loads an enemy unit's battle sprite into the first free enemy sprite slots (one for a small enemy,...
Definition sprites.c:67
s32 BattleUnit_LookupWeaponValueByClass(s32 unitId)
Returns the weapon sprite a party member's attack shows for the kind of weapon they have equipped (gB...
Definition sprites.c:197
#define WEAPON_ITEM_MASK
Definition sprites.c:156
s32 BattleUnit_GetWeaponKind(s32 itemId)
Returns the kind of the weapon whose item id is itemId (0 to 5), which picks a party member's attack ...
Definition sprites.c:163
#define ENEMY_SPRITE_SLOTS
The battle has six enemy sprite slots; a large enemy takes two side by side, a small one (BattleClass...
Definition sprites.c:36
s32 BattleMotion_ReleaseObjectSlotByValue(s32 unitId)
Frees every enemy sprite slot unit unitId holds, unloading its sprite.
Definition sprites.c:141
#define WEAPON_KIND_SHIFT
Definition sprites.c:157
s32 EnemyCheck(s32 classId)
Returns 1 if an enemy of class classId would find room among the enemy sprite slots: one free slot fo...
Definition sprites.c:41
#define WEAPON_KIND_NONE
Definition sprites.c:158
s32 BattleMotion_GetSlotPalette(s32 id)
Returns the palette of unit id's battle object.
Definition sprites.c:32
u16 gBattleUnit_WeaponAnimsClass2[]
u16 gBattleUnit_WeaponAnimsClass3[]
u16 gResource_SlotAssignments[]
u16 gBattleUnit_WeaponAnimsClass5[]
u16 gBattleUnit_WeaponAnimsClass1[]
u16 gBattleUnit_WeaponAnimsClass0[]
What every part of the battle object shares: its includes, in their original order,...
#define SPRITE_WITH_SECOND_PART_B
#define EQUIP_WEAPON
The inventory's weapon slot, for Inventory_FindEquippedFar.
#define SPRITE_WITH_SECOND_PART_A
The two battle sprites whose next sprite is loaded with them (into a second free place),...
@ BATTLE_SIDE_BOTH
struct BattleWork * gBattleWork
#define GARET
Jerald.
#define MIA
Mary.
#define ISAAC
Robin.
#define JENNA
Jasmine.
#define IVAN
Ivan.
#define FELIX
Garcia.
s32 ResourceSlot_LoadFar(u32 slot, u32 *buffer, s32 number, u32 variant)
struct BattleUnit * UnitGetFar(u32 owner)
s32 Inventory_FindEquippedFar(s32 owner, s32 type)
#define Ram_ActorSpriteSlots
Definition ram_buffer.h:16
s32 palette
the unit sprite's palette
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u8 classId
Who the unit is: a character's id (ISAAC to JENNA, below 8) or an enemy's id (BattleUnitSet).
u8 classIndex
The character's class, worked out from its Djinn (Unit_UpdateClass); 0 marks an enemy,...
u16 inventory[15]
Items held, one entry each: bits 15..11 quantity | 10 broken | 9 equipped | 8..0 item id (INVENTORY_*...
The battle's own work: its enemies, units and their objects, the turn's actions, the spoils,...
Definition battle_work.h:71
s16 spriteSlots[6]
the unit in each enemy sprite slot, 0 when free
Definition battle_work.h:73
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13