Alchemy
Loading...
Searching...
No Matches

events.c

Go to the documentation of this file.
1/// @file
2/// Battle events: a downed unit's reset, waiting for the player, and the
3/// event queue, filled by BattleEvPush and played at once by
4/// BattleEv_DispatchQueued.
5/// Part of battle.c, the battle object, compiled only through it.
6
8
9/// Clears every ailment and stat change of a unit that goes down, recalculates
10/// its stats and rebuilds its status icons.
11/// Reached through the BATTLE_EVENT_DEFEAT event, from BattleEv_DispatchQueued
12/// and BattleEvent_Playback. Clears the unit's element levels, poison, stat
13/// stages and their turns, every status, its equipment bonuses, ready,
14/// immobile and challenge; UnitCalcFar then recomputes its stats, and
15/// BattleUnit_BuildStatusFlags its battle object's status flags.
16#ifdef UBFIX
18#else
20#endif
21 struct BattleUnit *unit;
23
24 unit = UnitGetFar(unitId);
25 for (element = NUM_ELEMENTS - 1; element >= 0; element--)
26 unit->elementLevels[element] = 0;
27
28 unit->poison = 0;
29 unit->attackTurns = 0;
30 unit->attackStage = 0;
31 unit->defenseTurns = 0;
32 unit->defenseStage = 0;
33 unit->resistanceTurns = 0;
34 unit->resistanceStage = 0;
35 unit->delusion = 0;
36 unit->confusion = 0;
37 unit->charm = 0;
38 unit->stun = 0;
39 unit->sleep = 0;
40 unit->psySeal = 0;
41 unit->refrain = 0;
42 unit->reflect = 0;
43 unit->haunt = 0;
44 unit->grimReaper = 0;
45 unit->equipBonus[0] = 0;
46 unit->equipBonus[1] = 0;
47 unit->ready = 0;
48 unit->immobile = 0;
49 unit->agilityTurns = 0;
50 unit->agilityStage = 0;
51 unit->challenge = 0;
52
53 UnitCalcFar(unitId);
55}
56
57/// One OAM entry for Runtime_PushSlotEntry.
58/// A second view of struct BattlePromptSprite, kept: plain halfwords, where its
59/// bit-fields change BattlePresentation_WaitForAdvance (differ 50).
61 struct AdvanceSprite *next; ///< never set here
62 union {
63 struct {
64 u16 attr0; ///< OAM attribute 0: y in the low byte
65 u16 attr1; ///< OAM attribute 1: x in the low nine bits
66 u16 attr2; ///< OAM attribute 2: tile in the low ten bits
67 u16 attr3; ///< cleared with attr2 each frame
68 } fields;
69 u32 words[2]; ///< paired attributes, initialized together
70 u8 bytes[8]; ///< the y byte can change without replacing attribute 0
72};
73
74/// The advance arrow's attribute 0: a 256-colour, semi-transparent tall
75/// sprite; with attribute 1's size 0 it is 8 by 16 pixels.
76#define ADVANCE_ARROW_ATTR0 0xa400
77
78/// Shows the bobbing arrow at the message window and waits for the player to
79/// go on (B, or one of KEY_ADVANCE), then plays the cursor sound.
80/// Called after a message by BattlePresentation_DispatchAction and the
81/// staging runners, BattleCommand_BuildPlan (a flight),
82/// BattleIntro_AnnounceEncounter, the round's end (turn_end.c), and
83/// BattleEv_DispatchQueued for each BATTLE_EVENT_MESSAGE. Waits for the
84/// message window first. Takes a 128-byte VRAM cache entry for the arrow's
85/// tiles and frees it; each frame queues the WINOUT writes, sets REG_BLDALPHA
86/// and pushes the arrow sprite.
87#ifdef UBFIX
89#else
91#endif
92 struct AdvanceSprite *prompt;
93 struct AdvanceSprite promptStorage;
94 s32 frame;
95 s32 tileSlot;
96 s32 frameTiles;
97 struct UiWindow *window;
98 struct BattleDisplayOffset *offset;
99 s32 attr2;
100 s32 attr1;
101 s32 x;
102 s16 tile;
103
104 while (!UiWork_IsCompleteFar())
105 WaitFrames(1);
106 prompt = &promptStorage;
107 tileSlot = VramCache_AllocEntry(128);
108 for (frame = 0;; frame++) {
109 // Cycle the eight frames, one every four frames.
110 frameTiles =
111 ((gFrameCount >> 2) & 7) * 128 + (s32)gBattlePres_AdvanceArrowTiles;
112 window = gBattleDisplayWork->window;
113 offset = gBattleDisplayWork->offset;
117 prompt->attributes.words[0] = ADVANCE_ARROW_ATTR0;
118 prompt->attributes.words[1] = 0;
119 tile = VramCache_Reload(tileSlot, frameTiles) & 0x3ff;
120 attr2 = prompt->attributes.fields.attr2;
121 prompt->attributes.fields.attr2 = (attr2 & ~0x3ff) | tile;
122 // The window is placed in tiles, its offset in 1/256 pixels.
123 x = (u16)((window->x * 8 + (offset->x >> 8) + 4) & 0x1ff);
124 attr1 = prompt->attributes.fields.attr1;
125 prompt->attributes.fields.attr1 = (attr1 & ~0x1ff) | x;
126 // Bob up and down by up to 2 pixels.
127 prompt->attributes.bytes[0] = Trig_Sin(gFrameCount << 12) / 32768 +
128 window->y * 8 + (offset->y >> 8) + 6;
129 Runtime_PushSlotEntry(prompt, 240);
130 // A held advance key counts only after 16 frames, so one still held from
131 // the previous message does not skip this one; B held goes on at once.
132 if ((gKeysHeld & KEY_B) || (gKeysPressed & KEY_ADVANCE) ||
133 (frame > 15 && (gKeysHeld & KEY_ADVANCE)))
134 break;
135 WaitFrames(1);
136 }
138 Resource_ResetEntry(tileSlot);
139 WaitFrames(1);
140}
141
142/// Shows the cursor bobbing at (x, y) and waits for one of KEY_ADVANCE.
143/// Called by Battle_RunEncounter under the Djinn tutorial's standby message,
144/// and by Menu_RunCommandRow through BattlePresentation_WaitForPromptAtFar.
145/// Waits for the message window first; takes a 128-byte VRAM cache entry for
146/// the cursor's tiles and frees it, and each frame queues the WINOUT writes,
147/// sets REG_BLDALPHA and pushes the cursor sprite.
148/// x, y : in pixels
149#ifdef UBFIX
151#else
153#endif
154 struct MenuPoint position;
155 s32 frameTiles;
156 struct CursorSprite promptStorage;
157 struct CursorSprite *prompt;
158 s32 tileSlot;
159
160 frameTiles = Ui_GetTableWordZeroFar(0);
161 position.x = x;
162 position.y = y;
163 while (!UiWork_IsCompleteFar())
164 WaitFrames(1);
165 prompt = &promptStorage;
166 tileSlot = VramCache_AllocEntry(128);
167 while (1) {
171 ((s32 *)prompt)[1] = MENU_SPRITE_SIZE_16;
172 ((s32 *)prompt)[2] = 0;
173 prompt->tile = VramCache_Reload(tileSlot, frameTiles);
174 // Nudge it up and right every four frames.
175 prompt->x = position.x + ((gFrameCount & 4) >> 1) - 4;
176 prompt->y = position.y - ((gFrameCount & 4) >> 2) - 8;
177 Runtime_PushSlotEntry(prompt, 240);
179 break;
180 WaitFrames(1);
181 }
182 Resource_ResetEntry(tileSlot);
183 WaitFrames(1);
184}
185
186/// Sets gBattleDisplayWork->marked, which the next message reads, as
187/// BATTLE_EVENT_MARK does.
188/// Called by BattleCommand_BuildPlan between a weapon's two unleash messages.
190
191/// Takes an enemy out of the battle at once (one that leaves rather than
192/// falls): its HP to 0, out of the lists, and its object released.
193/// Reached through the BATTLE_EVENT_REMOVE_UNIT event, which BattleTargetExec
194/// queues for a self-destructing actor, from BattleEv_DispatchQueued and
195/// BattleEvent_Playback. A party unit is left as it is. Clears the battle
196/// object's object and active and releases its dispatch object.
197#ifdef UBFIX
199#else
201#endif
202 struct BattleUnit *enemy;
203 struct BattleObj *slot;
204
205 enemy = UnitGetFar(unitId);
206 if (enemy->side == BATTLE_UNIT_ENEMY) {
207 Unit_SetHpFar(enemy, 0);
210 slot = BattleObjGet(unitId);
212 slot->object = 0;
213 slot->active = 0;
214 }
215}
216
217/// BattleEventState.flags bit 0: a Djinni struck a weakness, so enemies that
218/// fall pay the Djinn bonus (BattleEnemy_RecordDefeat).
219#define EVENT_FLAG_DJINN_BONUS 1
220
221/// The BATTLE_EVENT_DJINN_BONUS event: grants the Djinn bonus for the rest of
222/// the action. Its operand is ignored.
223/// Called for the event by BattleEv_DispatchQueued and BattleEvent_Playback;
224/// BattleTargetExec queues it. Sets EVENT_FLAG_DJINN_BONUS in runtime->flags,
225/// which BattleEventRuntime_Reset clears.
226void BattleEv_GrantDjinnBonus(struct BattleEventState *runtime, u32 operand) {
227 runtime->flags |= EVENT_FLAG_DJINN_BONUS;
228}
229
230/// Plays the queued battle events at once, in order (BattleEvent_Playback
231/// plays them over frames instead): the messages with their arguments, the
232/// hit flashes, the downed units, the redraws. Then empties the queue.
233/// Called where an outcome is shown outside an effect: by the staging runners
234/// (a blocked cast, a dodge, a broken item, a plan's targets one by one),
235/// BattleCommand_BuildPlan's debug defeat, and the turn's end (turn_end.c).
236/// Each message, flash and fall waits its frames here. Ends with
237/// BattleEventRuntime_Reset.
238#ifdef UBFIX
239void BattleEv_DispatchQueued(void) {
240#else
242#endif
243 struct BattleEventState *runtime = &gBattleWork->events;
244 struct BattleEventQueue *queue = &runtime->queue;
245 s32 eventIndex;
246
247 for (eventIndex = 0; eventIndex < queue->count; eventIndex++) {
248 u8 opcode = queue->opcodes[eventIndex];
249 // BATTLE_EVENT_SOUND, the last opcode, is skipped: played at once, the
250 // queue makes no sounds but a hit's.
251 if (opcode <= BATTLE_EVENT_DJINN_BONUS)
252 switch (opcode) {
254 BattleEv_GrantDjinnBonus(runtime, queue->operands[eventIndex]);
255 break;
258 break;
261 break;
263 UiWork_PushValueSlotFar(queue->operands[eventIndex], VALUE_NUMBER);
264 break;
266 UiWork_PushValueSlotFar(queue->operands[eventIndex] & ITEM_ID_MASK,
268 break;
270 UiWork_PushValueSlotFar(queue->operands[eventIndex] &
273 break;
276 break;
279 break;
280 // A negative message (MESSAGE_NONE in target_exec.c) shows nothing:
281 // the event only waits for the player.
283 if ((s32)queue->operands[eventIndex] >= 0)
284 UiText_ShowMessageAndWaitCoreFar(queue->operands[eventIndex]);
287 break;
289 if ((s32)queue->operands[eventIndex] >= 0)
290 UiText_ShowMessageAndWaitCoreFar(queue->operands[eventIndex]);
292 break;
293 case BATTLE_EVENT_HIT:
294 if (runtime->pendingCue > 0)
296 BattleMotion_FlashHit(queue->operands[eventIndex], 0, 0);
297 break;
299 BattleEnemy_RecordDefeat(queue->operands[eventIndex], runtime->flags);
300 BattleActor_ResetRuntimeFields(queue->operands[eventIndex]);
301 BattleMotion_ShowDowned(queue->operands[eventIndex]);
302 break;
305 break;
307 BattleUnit_BuildStatusFlags(queue->operands[eventIndex],
308 BattleObjGet(queue->operands[eventIndex]));
309 BattlePres_SetActorModeAndAction(queue->operands[eventIndex]);
310 break;
311 }
312 }
314}
315
316/// Queues one battle event (enum BattleEventOpcode) with its operand, and
317/// returns the opcode.
318/// Called, directly or through PUSH_MESSAGE, by BattleTargetExec for each
319/// step of an outcome, and by staging.c, plan.c and turn_end.c. Appends to
320/// gBattleWork->events.queue with no test against BATTLE_EVENT_CAPACITY.
321u32 BattleEvPush(u32 opcode, u32 operand) {
322 struct BattleEventQueue *queue = &gBattleWork->events.queue;
323 u32 index = queue->count;
324
325 queue->opcodes[index] = opcode;
326 queue->operands[index] = operand;
327 queue->count = index + 1;
328 return opcode;
329}
330
331#undef ADVANCE_ARROW_ATTR0
s32 BattleActor_ResetRuntimeFields(s32 unitId)
Clears every ailment and stat change of a unit that goes down, recalculates its stats and rebuilds it...
Definition events.c:19
#define ADVANCE_ARROW_ATTR0
The advance arrow's attribute 0: a 256-colour, semi-transparent tall sprite; with attribute 1's size ...
Definition events.c:76
void BattleEv_MarkDisplay(void)
Sets gBattleDisplayWork->marked, which the next message reads, as BATTLE_EVENT_MARK does.
Definition events.c:189
u32 BattleEvPush(u32 opcode, u32 operand)
Queues one battle event (enum BattleEventOpcode) with its operand, and returns the opcode.
Definition events.c:321
u32 BattleEv_DispatchQueued(void)
Plays the queued battle events at once, in order (BattleEvent_Playback plays them over frames instead...
Definition events.c:241
s32 BattleActor_DestroyTemporaryObject(s32 unitId)
Takes an enemy out of the battle at once (one that leaves rather than falls): its HP to 0,...
Definition events.c:200
#define EVENT_FLAG_DJINN_BONUS
BattleEventState.flags bit 0: a Djinni struck a weakness, so enemies that fall pay the Djinn bonus (B...
Definition events.c:219
void BattleEv_GrantDjinnBonus(struct BattleEventState *runtime, u32 operand)
The BATTLE_EVENT_DJINN_BONUS event: grants the Djinn bonus for the rest of the action.
Definition events.c:226
s32 BattlePresentation_WaitForPromptAt(s32 x, s32 y)
Shows the cursor bobbing at (x, y) and waits for one of KEY_ADVANCE.
Definition events.c:152
s32 BattlePresentation_WaitForAdvance(void)
Shows the bobbing arrow at the message window and waits for the player to go on (B,...
Definition events.c:90
s32 BattlePres_SetActorModeAndAction(s32 unitId)
Sets unit id's pose to match its state: held (asleep, stunned or unable to move) or down,...
Definition objects.c:294
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
s32 BattleUnit_BuildStatusFlags(s32 unitId, struct BattleObj *battleObject)
Builds the status icon bits of unit id's ailments into its battle object's activeConditions,...
Definition objects.c:155
s32 BattleObj_MarkForRelease(s32 unitId)
Frees the enemy sprite slots unitId holds and marks its object for release at the end of the round (B...
Definition objects.c:543
u8 gBattlePres_AdvanceArrowTiles[]
@ BATTLE_EVENT_DEFEAT
the unit falls; an enemy fades out
@ BATTLE_EVENT_UNIT_NAME
a unit's name for the next message
@ BATTLE_EVENT_MARK
sets gBattleDisplayWork->marked
@ BATTLE_EVENT_DRAW_STATUS
redraws the party's status
@ BATTLE_EVENT_DJINN_BONUS
later defeats give the Djinn bonus
@ BATTLE_EVENT_HIT
the unit flinches and flashes
@ BATTLE_EVENT_CLEAR_ARGUMENTS
forgets the names and numbers pushed
@ BATTLE_EVENT_ABILITY_NAME
an ability's name for the next message
@ BATTLE_EVENT_REFRESH_UNIT
the unit's status icons, colour, pose
@ BATTLE_EVENT_REMOVE_UNIT
an enemy leaves the battle
@ BATTLE_EVENT_MESSAGE
a message, waiting for the player
@ BATTLE_EVENT_MESSAGE_NO_WAIT
a message, going straight on
@ BATTLE_EVENT_ITEM_NAME
an item's name for the next message
@ BATTLE_EVENT_NUMBER
a number for the next message
What every part of the battle object shares: its includes, in their original order,...
#define VALUE_ABILITY_NAME
#define VALUE_UNIT_NAME
#define VALUE_ITEM_NAME
#define VALUE_NUMBER
#define KEY_ADVANCE
The keys that take the player on past a message: A, B, L and R.
@ BATTLE_UNIT_ENEMY
@ NUM_ELEMENTS
Definition battle_unit.h:41
@ OWNER_ACTION_ID_MASK
Definition battle_unit.h:14
struct BattleWork * gBattleWork
struct BattleDisplayWork * gBattleDisplayWork
void ObjectDispatch_ReleaseFar(struct DispatchObject *obj)
struct BattleUnit * UnitGetFar(u32 owner)
void Unit_SetHpFar(struct BattleUnit *unit, s32 hp)
void UnitCalcFar(s32 owner)
void AudioCommand_PlayFar(s32 id)
s32 Ui_GetTableWordZeroFar(s32 no)
void PartyStatusDrawFar(s32 flags)
void UiWork_PushValueSlotFar(u32 value, u32 kind)
s32 UiWork_IsCompleteFar(void)
void UiText_ShowMessageAndWaitCoreFar(s32 argument)
void UiWork_ClearValueNameTablesFar(void)
s32 Trig_Sin(s32 angle)
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
volatile u32 gFrameCount
Frames WaitFrames has finished.
void IoWriteQueue_ClearBits16(u32 address, u32 value)
Queues clearing a halfword register's bits.
Definition io_queue.c:33
void IoWriteQueue_SetBits16(u32 address, u32 value)
Queues setting a halfword register's bits.
Definition io_queue.c:27
@ KEY_B
Definition io_reg.h:244
#define BLEND_ALPHA(top, bottom)
A REG_BLDALPHA value: top and bottom are the two targets' weights, out of 16.
Definition io_reg.h:145
#define REG_BLDALPHA
Definition io_reg.h:142
#define REG_WINOUT
Definition io_reg.h:82
#define Io_Write16(v, reg)
Writes a value to a 16-bit register or memory location.
Definition iowrite.h:14
@ ITEM_ID_MASK
Definition item.h:16
volatile u32 gKeysHeld
Keys down now.
volatile u32 gKeysPressed
Keys that went down this frame.
#define MENU_SPRITE_SIZE_16
Definition menu_list.h:67
void BattleEventRuntime_Reset(void)
Stops playback and empties the event queue.
Definition playback.c:437
void Runtime_PushSlotEntry(void *slotEntry, s32 slot)
Links a sprite entry into depth slot slot (clamped to 0..255) for this frame.
Definition render.c:79
#define SE_MENU_CURSOR_MOVE
Definition songs.h:104
s32 BattleEnemy_RecordDefeat(s32 unitId, s32 djinnBonus)
Counts a fallen enemy and adds its coins, experience and perhaps its item to the spoils.
Definition spoils.c:99
void BattleMotion_FlashHit(s32 unitId, s32 unused0, s32 unused1)
Flashes unit id as it is hit: puts it in its damage pose and switches its sprites between white and t...
Definition staging.c:978
void BattleActor_RemoveFromLists(s32 unitId)
Takes unit id out of the party's or the enemies' list and out of this round's actions,...
Definition staging.c:1019
void BattleMotion_ShowDowned(s32 unitId)
Shows a downed unit: a party member lies down, an enemy keeps its damage pose, turns grey,...
Definition staging.c:1072
u16 attr1
OAM attribute 1: x in the low nine bits.
u16 attr2
OAM attribute 2: tile in the low ten bits.
One OAM entry for Runtime_PushSlotEntry.
Definition events.c:60
struct AdvanceSprite * next
never set here
Definition events.c:61
union AdvanceSprite::@053115132014001324162033173333120206315020022315 attributes
The battle message's text channel, as far as its offset in the window.
Definition battle_work.h:30
u16 x
1/256 pixels
Definition battle_work.h:32
u16 y
1/256 pixels
Definition battle_work.h:33
s32 marked
set by BATTLE_EVENT_MARK; passed to the next message
Definition battle_work.h:41
struct UiWindow * window
the message window
Definition battle_work.h:39
struct BattleDisplayOffset * offset
its text channel
Definition battle_work.h:40
The battle event queue: up to 64 events, each an opcode (enum BattleEventOpcode) and one operand,...
u32 operands[BATTLE_EVENT_CAPACITY]
s32 count
events queued
u8 opcodes[BATTLE_EVENT_CAPACITY]
The battle event queue and the state of its playback: the phase, the event playing and the advance ar...
Definition battle_work.h:51
struct BattleEventQueue queue
Definition battle_work.h:52
s32 pendingCue
hit sound (an SE_ id), played on the next hit
Definition battle_work.h:59
s32 flags
bits: 0 Djinn bonus (EVENT_FLAG_DJINN_BONUS), for the enemies that fall during the action
Definition battle_work.h:62
A unit's place on the battlefield: its sprite object, resources and animations, its anchor spot and s...
struct MotionObject * object
NULL once released.
s16 active
Set by BattleObj_MarkForRelease: the object is released with the others by BattleMotion_DestroyAllSlo...
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u8 agilityTurns
the Agility change's turns left, 5 when cast
u8 immobile
set by Ground: the next action is lost
s8 elementLevels[4]
A summon's boost to each element: the Djinn of that element the summon spent, adding (n * n + n) * 5 ...
u8 grimReaper
The Grim Reaper's countdown: 7 when cursed, down one at each turn's end; at 0 the unit falls.
u8 psySeal
bits: 7..3 Luff (16 when cast, minus 8 a turn) | 2..0 Bind's turns (7 when cast).
u8 side
BATTLE_UNIT_ABSENT (0), BATTLE_UNIT_ENEMY (1) or BATTLE_UNIT_PARTY (2).
s8 poison
1 poisoned, 2 deadly poison
u8 haunt
set while an evil spirit grips the unit
struct BattleElementStats element[4]
Power and resistance in each element, 0 to 200, after equipment, element levels and Resistance stages...
s8 challenge
Set by the challenge effect: an enemy with it never chooses to flee.
s8 agilityStage
The Agility stage: -4 (Vine) to 8 (Zephyr, twice the Agility).
u8 refrain
Regenerate's turns left, 7 when cast.
s8 reflect
Reflect's turns left, 7 when cast.
u8 equipBonus[2]
The totals of equipment effects 23 (unleash chance) and 24 that UnitCalc sums; TBS never reads them b...
u8 attackTurns
Each stat change: the turns it has left, and its stage (UnitCalc: an eighth of Attack,...
u8 delusion
Delusion to sleep: the turns each status has left, 7 when it lands; each may end sooner at the end of...
u8 ready
Kite's extra action: 2 when cast, down one at each turn's end; while nonzero UnitCalc gives the unit ...
u8 partyStatus
PARTY_STATUS_SUMMONS or PARTY_STATUS_NO_SUMMONS.
Definition battle_work.h:86
struct BattleEventState events
A cursor or prompt sprite: a list link and its OAM attributes as fields.
Definition menu_list.h:50
A field object as the object dispatcher's far calls take it.
A point on the screen where a menu shows its cursor.
Definition menu_list.h:97
s32 y
screen pixels
Definition menu_list.h:99
s32 x
screen pixels
Definition menu_list.h:98
A window: a framed rectangle of the tilemap with its sprite outputs, its opening or closing animation...
Definition uiwindow.h:11
u16 y
tiles
Definition uiwindow.h:16
u16 x
tiles
Definition uiwindow.h:15
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
unsigned char u8
Definition types.h:11
struct AdvanceSprite::@053115132014001324162033173333120206315020022315::@032333004100157315263147312361357251135164165300 fields
u8 bytes[8]
the y byte can change without replacing attribute 0
u32 words[2]
paired attributes, initialized together
s32 VramCache_AllocEntry(s32 size)
Takes a free cache entry, gives it size bytes of sprite VRAM and returns its number.
Definition vram_cache.c:227
s32 VramCache_Reload(s32 no, s32 src)
Copies src again into entry no's VRAM, keeping its size.
Definition vram_cache.c:238
s32 Resource_ResetEntry(u32 no)
Frees cache entry no: its blocks go back and the entry is marked free (offset 0xffff).
Definition vram_cache.c:106