Alchemy
Loading...
Searching...
No Matches

object_camera.c

Go to the documentation of this file.
1/// @file
2/// The object cameras, which place every object's sprite each frame.
3/// Part of field.c, the field object, compiled only through it.
4
5#include "../field_internal.h"
6
7/// A map cell's word, as the camera reads it.
9 u32 block : 12; ///< the block (metatile) number
10 u32 layer : 2; ///< if not 0, the layer of an object standing on it, + 1
11 u32 priority : 2; ///< if not 0, the priority of an object standing on it
12 u32 unk10 : 16;
13};
14
15/// A field object, as the camera reads it.
17 u32 active; ///< zero for a free slot
19 u16 angle; ///< the sprite's facing, before the camera's angle is added
21 s32 y; ///< up; the on-screen test uses z - y
23 s32 height; ///< the ground height under the object
24 s32 scaleX; ///< Q16
25 s32 scaleY; ///< Q16
27 u8 layer; ///< the map layer it stands on; the cell under it may change it
28 u8 flags; ///< bits: 2 draw 320 pixels down | 1 up | 0 priority from cell
29 u8 unk24[0x2c];
30 void *sprite; ///< a sprite, or for kind 2 an array of four sprite pointers
31 u8 kind; ///< 1: one sprite, 2: up to four
33 u8 held; ///< nonzero keeps the sprite and its VRAM off screen or suspended
34 u8 unk5d[0x13];
35};
36
37/// A point the fixed camera looks from or at.
39 s32 x; ///< 16.16 fixed-point pixels
40 s32 y; ///< 16.16 fixed-point pixels
41 s32 z; ///< 16.16 fixed-point pixels
42};
43
47 struct ObjectCameraPoint *eyeOverride; ///< when set, used as the eye
48 struct ObjectCameraPoint *targetOverride; ///< when set, used as the target
49};
50
51/// Each frame, with the scrolling camera: places every object's sprite on the
52/// screen. An object on or near the screen takes its layer and priority from
53/// the cell under it; one off screen gives up its VRAM cache entry.
54/// ObjectSystem_Initialize schedules it (order 0xc80, after the objects move)
55/// for every mode but 3 and 4; ObjectSystem_SuspendProjectionAndShowSprites
56/// suspends it. Resets the system's used count, may change an object's layer
57/// and its sprite's priorities, and holds the frame decoder in heap slot
58/// HEAP_SLOT_FRAME_SCRATCH only while it runs.
60 /* FAKEMATCH(dead): an unused local for the room the native frame keeps for
61 * three points above the position; without it, 2 of 267 instructions differ
62 * in tbs-en. */
63 UNUSED struct ObjectCameraPoint unusedPoints[3];
64 s32 objectIndex;
65 struct MapScrollWork *mapWork;
66 s32 viewX;
67 s32 viewZ;
68 struct ObjectSystemWork *system;
69 struct ObjectCameraObject *object;
70 struct AnimationObject *sprite;
71#ifndef UBFIX
72 s32 *viewCoordinates;
73#endif
74 u32 kind;
75 s32 dx;
76 s32 dz;
77 s32 screenTop;
78 struct ObjectCameraTile *tile;
80 struct SpriteScale scale;
81 struct SpritePlacement drawPosition;
82 u32 layerPlusOne;
83
84 // MapScrollWork owns all three layer cell pointers at their 0x30-byte stride.
85 // UB: map and system work are separate globals, beyond gObjectSlots.
86 // Reading their named slots adds eight bytes in the forced EN build.
87#ifdef UBFIX
88 mapWork = gMapWork[0];
89#else
90 mapWork = *(struct MapScrollWork **)(((u8 *)&gObjectSlots) + 12);
91#endif
92#ifdef UBFIX
93 viewX = mapWork->viewX & 0xffff0000;
94 viewZ = mapWork->viewY & 0xffff0000;
95#else
96 viewCoordinates = &mapWork->viewX;
97 viewX = viewCoordinates[0] & 0xffff0000;
98 viewZ = viewCoordinates[1] & 0xffff0000;
99#endif
100#ifdef UBFIX
101 system = gMenuCtrlWork;
102#else
103 system = *(struct ObjectSystemWork **)(((u8 *)&gObjectSlots) + 4);
104#endif
105 // Copy the frame decoder (Render_DecodeFrame) into its heap slot.
108 system->used = 0;
109 object = (struct ObjectCameraObject *)gObjectSlots;
110 for (objectIndex = 0; objectIndex < FIELD_OBJECT_COUNT;
111 objectIndex++, object++) {
112 if (object->active == 0)
113 continue;
114 // An object at (x, z) = (0, 0) is not placed; only its sprite's VRAM is
115 // given up.
116 if (object->x != 0 || object->z != 0) {
117 kind = object->kind & 15;
118 if (kind == 0)
119 continue;
120 // This camera places single sprites only; groups (kind 2) are left.
121 if (kind != 1)
122 continue;
123 // While a menu has sprite projection suspended, only held objects are
124 // drawn.
125 if (system->suspended != 0 && object->held == 0) {
126 struct AnimationObject *frozen = object->sprite;
127
129 frozen->dirty = kind;
130 continue;
131 }
132 dx = object->x - viewX;
133 dz = object->z - viewZ;
134 screenTop = dz - object->y;
135 sprite = object->sprite;
136 // From 32 pixels left of the screen to 32 past its 240, and from 32
137 // pixels above it to 224.
138 if (dx > -0x200000 && dx < 0x1100000 && screenTop > -0x200000 &&
139 screenTop < 0xe00000) {
140 // The cell under the object.
141 tile = &((struct ObjectCameraTile *)mapWork->layers[object->layer]
142 .cells)[(object->x >> 20) + ((object->z >> 20) << 7)];
143 if (object->flags & 1) {
144 priority = tile->priority;
145 if (priority != 0) {
146 sprite->image.priority = priority;
147 sprite->shadow.priority = priority;
148 }
149 }
150 layerPlusOne = tile->layer;
151 if (layerPlusOne != 0)
152 object->layer = layerPlusOne - 1;
153 scale.x = Iwram_MulQ16(object->scaleX, sprite->scale);
154 scale.y = Iwram_MulQ16(object->scaleY, sprite->scale);
155 drawPosition.x = dx;
156 drawPosition.height = object->y;
157 drawPosition.y = dz;
158 drawPosition.groundHeight = object->height;
159 // XXX: flag bits 1 and 2 draw the object 320 pixels up or down the
160 // map from where it is; the scenes that set them would say why.
161 if (object->flags & 2) {
162 drawPosition.height += 0xfec00000; // -320 pixels
163 drawPosition.y += 0xfec00000;
164 drawPosition.groundHeight += 0xfec00000;
165 }
166 if (object->flags & 4) {
167 drawPosition.height += 0x1400000; // +320 pixels
168 drawPosition.y += 0x1400000;
169 drawPosition.groundHeight += 0x1400000;
170 }
171 Render_ApplyProjectedPlacement(sprite, &drawPosition, &scale,
172 object->angle);
173 continue;
174 }
175 // Off screen: the sprite's VRAM goes back to the cache, and dirty makes
176 // it redraw when it comes back.
177 if (object->held == 0) {
178 if (!sprite->retainCacheEntry) {
180 sprite->dirty = 1;
181 }
182 }
183 } else {
184 kind = object->kind & 15;
185 if (kind == 1) {
186 sprite = object->sprite;
187 if (object->held == 0 && !sprite->retainCacheEntry) {
189 sprite->dirty = kind;
190 }
191 }
192 }
193 }
195}
196
198
199/// Each frame, with the fixed camera: places every object's sprite, from the
200/// 64th object down, facing them by the angle from the eye to the target.
201/// While battle commands are chosen (flag 363, set by
202/// BattlePresentation_BuildActions) it uses the fixed view matrix and 1.0
203/// scale. ObjectSystem_Initialize schedules it (order 0xc80) for modes 3 (the
204/// world map) and 4 (battle); ObjectSystem_SuspendProjectionAndShowSprites
205/// suspends it. Resets the system's used count.
207 s32 i;
208 struct ObjectCameraFixed *camera;
209 struct ObjectSystemWork *system;
210 struct ObjectCameraPoint *eye;
211 struct ObjectCameraPoint *target;
212 struct ObjectCameraObject *object;
213 s32 angle;
214 s32 spritesRemaining;
215 s32 kind;
216 s32 *objectPosition;
217 s32 fixedScale;
218 void **sprites;
219 void *sprite;
220 s32 groupScale[2];
221 s32 scale[2];
222 /* FAKEMATCH(dead): an unused local for the room the native frame keeps for
223 * two points above the scales; without it, 2 of 181 instructions differ in
224 * tbs-en. */
225 UNUSED struct ObjectCameraPoint unusedPoints[2];
226
227 // UB: camera and system work are separate globals, beyond gObjectSlots.
228 // Reading their named slots adds four bytes in the forced EN build.
229#ifdef UBFIX
230 camera = (struct ObjectCameraFixed *)gCameraWork;
231 system = gMenuCtrlWork;
232#else
233 camera = *(struct ObjectCameraFixed **)(((u8 *)&gObjectSlots) + 0x1c);
234 system = *(struct ObjectSystemWork **)(((u8 *)&gObjectSlots) + 4);
235#endif
238 eye = &camera->eye;
239 target = &camera->target;
240 if (camera->eyeOverride != NULL)
241 eye = camera->eyeOverride;
242 if (camera->targetOverride != NULL)
243 target = camera->targetOverride;
244 angle = (s16)ArcTan2((eye->x - target->x) >> 16, (eye->z - target->z) >> 16);
245 system->used = 0;
247 // Under the fixed view matrix every sprite also faces an eighth of a turn
248 // (0x2000) further back.
250 angle += 0xffffe000;
252 Transform_ApplyLookAt((s32 *)eye, (s32 *)target);
253 } else {
254 Transform_SetLookAt((s32 *)eye, (s32 *)target);
255 }
256 object = (struct ObjectCameraObject *)gObjectSlots;
257 object += FIELD_OBJECT_COUNT - 1;
258 fixedScale = 0x10000;
259 for (i = FIELD_OBJECT_COUNT - 1; i >= 0; i--, object--) {
260 if (object->active == 0)
261 continue;
262 kind = object->kind & 15;
263 switch (kind) {
264 case 1:
265 objectPosition = &object->x;
266 scale[0] = object->scaleX;
267 scale[1] = object->scaleY;
268 sprite = object->sprite;
270 scale[0] = fixedScale;
271 scale[1] = fixedScale;
272 }
273 Render_PlaceProjectedSprite(sprite, objectPosition, scale,
274 object->angle + angle, object->layer);
275 break;
276 case 2:
277 groupScale[0] = object->scaleX;
278 groupScale[1] = object->scaleY;
280 groupScale[0] = fixedScale;
281 groupScale[1] = fixedScale;
282 }
283 // A group's sprite field points to its four sprite pointers; empty
284 // ones are null.
285 sprites = object->sprite;
286 for (spritesRemaining = 3; spritesRemaining >= 0; spritesRemaining--) {
287 sprite = *sprites++;
288 if (sprite != NULL)
289 Render_PlaceProjectedSprite(sprite, &object->x, groupScale,
290 object->angle + angle, object->layer);
291 }
292 break;
293 case 0:
294 break;
295 }
296 }
298}
struct BattleCamera * gCameraWork
const s32 gCamera_FixedViewMatrix[12]
The fixed camera's view matrix (Q16): identity with a -0.8 shear of y by x.
Definition facing.c:80
s32 GameFlag_TestFar(s32 flag)
u8 Render_DecodeFrameCodeSize[]
u8 Render_DecodeFrame[]
What every part of the field object shares: its includes and the few names more than one part uses.
@ FIELD_OBJECT_COUNT
#define FLAG_CHOOSING_COMMANDS
set while the commands are chosen
Definition flags.h:67
void * gMapWork[]
@ HEAP_SLOT_FRAME_SCRATCH
Lives for one frame: WaitFrames builds the OAM list in it, and the field sprite decoder keeps its cod...
Definition heap_state.h:53
#define Iwram_MulQ16(left, right)
Definition iwram_call.h:127
static void Iwram_TransformMatrix(const s32 *matrix)
Definition iwram_call.h:69
s32 ArcTan2(s32 x, s32 y)
Returns the angle of the vector (x, y), in 1/65536 turns, measured from the y axis: 0 along +y,...
Definition math.c:36
void Runtime_ReleaseHeapBlock(s32 slot)
struct ObjectSystemWork * gMenuCtrlWork
UNUSED s32 ObjectCamera_ReturnTrue(void)
void ObjectSystem_UpdateCamera(void)
Each frame, with the scrolling camera: places every object's sprite on the screen.
void ObjectSystem_UpdateCameraFixed(void)
Each frame, with the fixed camera: places every object's sprite, from the 64th object down,...
#define RamCode_LoadSlot(slot, code, bytes)
Allocates a work-slot copy; release it with Runtime_ReleaseHeapBlock.
Definition ramcode.h:26
void Render_ApplyProjectedPlacement(struct AnimationObject *sprite, const struct SpritePlacement *position, const struct SpriteScale *scale, s32 facing)
Places a sprite for the scrolling camera and queues it for drawing.
void Render_PlaceProjectedSprite(struct AnimationObject *sprite, s32 *point, s32 *scale, s32 facing, s32 depth)
Places a sprite at 3D point for the fixed camera and queues it for drawing: projected to the screen a...
#define NULL
Definition bilibin.h:6
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
struct AnimationSpritePart shadow
Definition animspr.h:110
struct AnimationSpritePart image
Definition animspr.h:109
u8 slot
VRAM cache entry holding its tiles.
Definition animspr.h:112
s32 scale
16.16 fixed point, 0x10000 full size
Definition animspr.h:111
u8 retainCacheEntry
Keeps the VRAM cache entry when it is released or off screen.
Definition animspr.h:114
u8 dirty
nonzero redraws its pixels into VRAM when next drawn
Definition animspr.h:125
u16 priority
2 when created
Definition animspr.h:100
struct MapCell * cells
the layer's first cell in the map cell buffer
Definition map_scroll.h:21
The field map's work: the followed position, screen shake, tile animations, blend script,...
Definition map_scroll.h:27
s32 viewY
the view's top left, 16.16 fixed-point pixels
Definition map_scroll.h:40
struct MapLayerScroll layers[3]
BG3, BG2 and BG1, in that order.
Definition map_scroll.h:49
struct ObjectCameraPoint * targetOverride
when set, used as the target
struct ObjectCameraPoint * eyeOverride
when set, used as the eye
struct ObjectCameraPoint eye
struct ObjectCameraPoint target
A field object, as the camera reads it.
u16 angle
the sprite's facing, before the camera's angle is added
u8 held
nonzero keeps the sprite and its VRAM off screen or suspended
void * sprite
a sprite, or for kind 2 an array of four sprite pointers
s32 height
the ground height under the object
u8 flags
bits: 2 draw 320 pixels down | 1 up | 0 priority from cell
u8 layer
the map layer it stands on; the cell under it may change it
u8 kind
1: one sprite, 2: up to four
s32 y
up; the on-screen test uses z - y
u32 active
zero for a free slot
A point the fixed camera looks from or at.
s32 x
16.16 fixed-point pixels
s32 z
16.16 fixed-point pixels
s32 y
16.16 fixed-point pixels
A map cell's word, as the camera reads it.
u32 priority
if not 0, the priority of an object standing on it
u32 layer
if not 0, the layer of an object standing on it, + 1
u32 block
the block (metatile) number
The object system's work: the flag that suspends sprite projection, the outline's edge and fill colou...
Definition animspr.h:66
u16 used
sprite pixel bytes composed since the camera reset it
Definition animspr.h:67
s16 suspended
nonzero while a menu has suspended sprite projection
Definition animspr.h:69
A sprite's screen position and its two vertical offsets, in 16.16 pixels.
s32 x
screen x of the sprite's centre
s32 y
screen y at the ground; sets the depth slot
s32 groundHeight
how far the shadow is raised above y
s32 height
how far the image is raised above y
Horizontal and vertical sprite scale; 0x10000 is the original size.
void Transform_ApplyLookAt(s32 *eye, s32 *target)
Multiplies the camera at eye looking at target into gTransform.
Definition transform.c:324
void Render_ResetTransformState(void)
Allocates the one-level save area (heap slot HEAP_SLOT_TRANSFORM_STACK), clears gTransformStackDepth ...
Definition transform.c:19
void Transform_SetLookAt(s32 *eye, s32 *target)
Makes the camera at eye looking at target the whole of gTransform.
Definition transform.c:318
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
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
struct ScriptMotionObject * gObjectSlots
s32 VramCache_ReleaseVram(u32 no)
Gives back entry no's blocks but keeps the entry taken, with size 1, so a later VramCache_Load can re...
Definition vram_cache.c:122