Kajar notes of ChronoRET, rebuilding Chrono Trigger one matched routine at a time

Last updated: October 9, 2026

Sprites & objects

Field objects and how they reach the screen: the per-object animation tick and frame-build queue, the frame builders that copy graphics into a WRAM buffer and queue them for VRAM, and the OAM shadow that every visible object is appended to each frame. The full walk-through, with the data structures, is the Sprite Init Explainer.

The function table below lists the "Sprites & objects" group, the routines named Obj_*. The OAM and placement routines (Oam_*, Spr_*, SprBuf_*, VramQ_Flush) and Field_ProcessAnimQueue belong to the same system but are in the "Engine" group, on the Engine core page.

See also: Frame cycle and NMI, Field event scripts.

Objects

Each location defines Evt_ObjCount objects (from its event data), kept in per-object tables indexed by object number × 2 (Obj_Cur, $016D). Positions (Obj_PosX/Y) are in 1/16 pixel, the high byte being the 16-pixel map tile; Obj_SprSize gives the size class (4, 8, 12 or 24 sprite tiles), Obj_State the progress of the frame build, Obj_OamFlags the OAM range.

Every frame, Vblank_UnkA810 ($C0:A810) walks the objects: moves each one (Obj_MoveStep, Obj_MoveStepFree), tests it against a window a little larger than the view (Obj_UpdateInView), and for one in the window ticks its animation (Obj_AnimTickAndQueue), works out its screen position (Obj_CalcScreenPos) and re-links it into the draw bucket for that position (Obj_DrawUnlink, Obj_DrawLink). Field_UnkB0E6 is the same pass at a location load, without movement.

Frames

When an object's animation timer runs out it joins the frame-build queue, and Field_ProcessAnimQueue builds queued frames while the frame still has time (Obj_BuildSpriteFrameStep → Obj_BuildFrame4 / 8 / 12, in one, two or three passes). A build copies the frame's 8×8 graphics tiles into one to three $200-byte chunks of the WRAM tile buffer at $7F:3800, queues them for VRAM, and writes the object's tile records. Spr_LoadLargeObj loads a 24-tile object in one go.

Slots

Objects take VRAM tile space and palette rows by kind (Obj_Unk1100): Obj_Unk6F9A / Obj_Unk7056 allocate and free tile slots (Obj_TileSlot), and Obj_Unk7170 / Obj_Unk72B4 / Obj_Unk734C palette slots (Obj_PalSlot; kinds 0–2 have fixed slots 5–7). These keep Unk names for their verified callers; NEXT.md suggests Obj_TileSlotAlloc/Free and Obj_PalSlotAlloc/AllocBtl/Free.

Drawing

Oam_BuildShadow ($C0:B271) rebuilds the OAM shadow before each frame wait: for every object in every draw bucket, Spr_AppendToOam brings its tile records up to date (Spr_PrepareTiles) and copies them into one of three ranges of the shadow; leftover entries are parked off screen. The NMI uploads the shadow and the queued graphics.

53functions matched
9,088code bytes matched
53readable
53verified

Functions

AddressFunctionSizeStatusNotes
$C0:305DObj_Unk305D86verifiedSteps Obj_Cur toward the point $80 / $F0 within its tile (Obj_TileCentreX, Obj_TileFootY: the middle column, the bottom row of the tile), one frame at a time.
$C0:30B3Obj_Unk30B3161verifiedSteps Obj_Cur onto the position of the object in ObjFront_Other, one frame at a time: compares Obj_PosX and then Obj_PosY of the two with the low four bits masked (Obj_PosCoarseMask).
$C0:5614Obj_SetMoveAnim119verifiedPicks Obj_Cur's animation row from its speed.
$C0:568BObj_SetStandAnim27verified
$C0:6F9AObj_Unk6F9A13verifiedRuns Obj_TileSlotHandlers entry Obj_Unk1100 of Obj_Cur, unless bit 7 of it is set.
$C0:6FA7Obj_TileSlotHandlers18verifiedObj_Unk6F9A's handlers by Obj_Unk1100 (9 words, kinds 0-8).
$C0:6FB9Obj_TileSlotNone1verifiedObj_TileSlotHandlers' entry for the kinds that take no tile slot: RTS.
$C0:6FBAObj_TileSlotAllocKind156verifiedGives Obj_Cur tile slots in Obj_TileSlot by its size class (Obj_SprSize & ObjSpr_SizeMask): - class 0: the first free slot from ObjTile_SingleTop ($19) down to 1 (slot 0 is never tried); - classes...
$C0:7056Obj_Unk705646verifiedGives back Obj_Cur's tile slot(s): n = Obj_TileRecOfs / $20 (the slot Obj_TileSlotAllocKind took).
$C0:7170Obj_Unk717017verifiedUnless Field_Unk54 bit 7 is set or Obj_Cur's Obj_Unk1100 has bit 7 set, runs Obj_PalSlotHandlers entry Obj_Unk1100 (kinds 0-11) to give the object a palette slot.
$C0:7181Obj_PalSlotHandlers24verifiedObj_Unk7170's handlers by Obj_Unk1100 (12 words, kinds 0-11).
$C0:7199Obj_PalSlotKind02verifiedKind 0: X = ObjPal_SlotKind0 (slot 5), then falls into Obj_PalSlotFixed.
$C0:719BObj_PalSlotFixed119verifiedGives Obj_Cur the palette slot X (5, 6 or 7 for kinds 0, 1 and 2).
$C0:7212Obj_PalSlotKind15verifiedKind 1: Obj_PalSlotFixed with X = ObjPal_SlotKind1 (slot 6).
$C0:7217Obj_PalSlotKind25verifiedKind 2: Obj_PalSlotFixed with X = ObjPal_SlotKind2 (slot 7).
$C0:721CObj_PalSlotAny152verifiedKinds 3, 4 and 7-11: first looks through slots 0 to ObjPal_AnyEnd - 1 (0-4) for a taken one whose owner has Obj_Cur's Obj_PalSrc and, at the first, chains Obj_Cur after the owner (Obj_PalPrev =...
$C0:72B4Obj_Unk72B4152verifiedAs Obj_PalSlotAny over slots ObjPal_BtlFirst to ObjPal_BtlEnd - 1 (1-3): kinds 5 and 6 through Obj_PalSlotHandlers, and FieldBtl_SaveObj for an object with Obj_Unk1A81 bit 7 set.
$C0:734CObj_Unk734C77verifiedTakes Obj_Cur out of its palette slot's chain, unless Field_Unk54 bit 7 is set (then nothing, C=1).
$C0:A7E9Obj_ResetFrameState39verifiedFor each location object (Evt_ObjCount of them) writes 0 to its Obj_Unk0F00 (no frame to build) and Obj_LastFrameNone to its Obj_LastFrame (so the next frame is always rebuilt), through the WRAM...
$C0:A88DObj_UpdateInView186verifiedTests object Obj_Cur against the view window and sets it up or drops it as it enters or leaves.
$C0:A947Obj_FlagInView67verifiedThe view test for objects whose Obj_Unk1100 is Obj_Unk1100Seven: only sets Obj_Unk0F00 = Obj_Unk0F00Active in the window and 0 out of it, with no set-up, linking or release.
$C0:A98AObj_DrawUnlink67verifiedTakes object Obj_Cur out of its draw bucket, if it is in one (Obj_DrawOut bit 7 clear).
$C0:A9CDObj_DrawLink58verifiedPuts object Obj_Cur at the head of the draw bucket for its Obj_ScreenY, unless it is already in one (Obj_DrawOut bit 7 clear).
$C0:AA07Obj_MoveStep192verifiedOne frame of movement for object Obj_Cur (Obj_Unk1100 3 and up), while Obj_MoveFrames is nonzero (it is decremented first).
$C0:AAC7Obj_MoveStep_Arc54verified
$C0:AAFDObj_MoveStepFree72verifiedMovement for objects with Obj_Unk1100 below Obj_Unk1100FreeMove: with Obj_ArcMode set, the arc step (BRA Obj_MoveStep_Arc); otherwise, while Obj_MoveFrames is nonzero (decremented first), the low...
$C0:AB45Obj_CalcScreenPos93verifiedScreen position of object Obj_Cur from its map position and the layer-1 view: ObjScr_ViewX = Map_TileOriginX (low byte) x 8 + (Map_Unk1D87 & 7), ObjScr_ViewY likewise from Map_TileOriginY and...
$C0:ABA2Obj_CalcDirection199verifiedDirection from point (ObjDir_FromX, ObjDir_FromY) to (ObjDir_ToX, ObjDir_ToY), map tiles, as an angle in Obj_Direction: 256 per turn, $00 = +X (right), $40 = +Y (down), $80 = -X, $C0 = -Y.
$C0:AC69Obj_SetVelocity148verifiedSets object X's steps from Obj_Direction and Obj_Speed with the hardware multiplier: Obj_VelY = speed x sin / 256 and Obj_VelX = speed x cos / 256 (Rom_SineTable256 at the direction and at the...
$C0:ACFDObj_SetVelocityChecked410verifiedAs Obj_SetVelocity (steps from Obj_Direction and Obj_Speed, the sine into ObjVel_Y and the cosine into ObjVel_X, sign-extended into ObjVel_YHi / ObjVel_XHi), but it looks at the map tile the...
$C0:AE97Obj_SetVelocityChecked_Probe153verified
$C0:AF30Obj_SetVelocityAxis30verifiedZeroes one of the two steps in ObjVel_X / ObjVel_Y, then probes and stores them through Obj_SetVelocityChecked_Probe: when |Y step| >= |X step| the Y step goes, else the X step.
$C0:B127Obj_ActivateIfInView107verifiedObj_UpdateInView's set-up half for a location load: when Obj_Unk1A81 is 1..$7F and the object lies in the view window, sets it up exactly as Obj_UpdateInView does (Obj_DrawPrev / Obj_DrawNext /...
$C0:B192Obj_ResetStates32verified(was Sub_B192.) Clears Obj_State for every object the location defines (count in Evt_ObjCount), pointing DP at the Obj_State table so each clear is a 2-byte dp store, then tail-jumps to...
$C0:B204Obj_ResetDrawLists94verifiedEmpties the draw buckets: with DP=$2100 it writes ObjQ_Empty ($80) to the first 32 bytes at Obj_DrawBucket through the WRAM port, then MVNs spread them over the rest of the page ($0E20-$0EFF: 32...
$C0:C98AObj_AnimTickAndQueue236verifiedPer-object animation tick, called for object Obj_Cur from the object loop ($C0:A832, $C0:A878).
$C0:CAD9Obj_BuildSpriteFrameStep49verifiedOne step of building object Obj_Cur's current frame, graphics included: skips (C=0) unless Obj_Unk1100 bit 7 is clear, Obj_Unk1A81 is 1..$7F and Obj_Unk0F00 is nonzero; then by size class...
$C0:CB0AObj_BuildFrameLayout48verified(was Sub_CB0A.) Like Obj_BuildSpriteFrameStep, but for objects whose tiles are already in VRAM: tail-calls Obj_FrameLayout4 / 8 / 12, which only rewrite the SprTile records for Obj_LastFrame.
$C0:CB3AObj_AnimFrameLookup162verified(was Sub_CB3A.) Returns in A the frame number object X should show: Anim_FramePtr = Obj_AnimFrameTbl + (Obj_Facing × Obj_AnimFacingStride) + row*4 + Obj_AnimColumn, row = Obj_AnimRow (or...
$C0:CBDCObj_BuildFrame4492verified(was Sub_CBDC.) Builds frame A (Obj_FixedFrame in mode 3, else Obj_AnimFrameLookup) of a 4-tile object, in one pass.
$C0:CDC8Obj_FrameLayout4301verified(was Sub_CDC8.) Rewrites the 4 SprTile records of a 4-tile object for Obj_LastFrame directly (tiles already in VRAM): offsets from the frame record, Tile = Obj_VramTile + 2n, attributes as in...
$C0:CEF5Obj_BuildFrame8559verified(was Sub_CEF5.) Builds the current frame of an 8-tile object.
$C0:D124Obj_FrameLayout8358verified(was Sub_D124.) As Obj_FrameLayout4 for an 8-tile object (frame record 80 bytes, positions after 32 tile words); the first four tiles take Obj_PrioLow, the last four Obj_PrioHigh (by index, not by...
$C0:D28AObj_BuildFrame8Pass0131verified(was Sub_D28A.) First pass of an 8-tile frame: look the frame up, SprBuf_Alloc2 (2 adjacent SprBuf chunks), copy tiles 0-15 into the first chunk, INC Obj_State, return C=1 (more to do).
$C0:D30DObj_BuildFrame8Pass1490verified(was Sub_D30D.) Second pass: tiles 16-31 into the second chunk (Obj_TileBuf + $200), queue the VRAM upload ($200 bytes to Obj_VramTile*16, $200 more to the next tile row), write the 8 SprTileSrc...
$C0:D4F7Obj_BuildFrame1279verified(was Sub_D4F7.) Builds the current frame of a 12-tile object over three passes chosen by the Obj_State count (0 / 1 / 2+), each with an "Alt" variant when Obj_VramTile is ObjTile_AltLayout ($68...
$C0:D546Obj_BuildFrame12Pass0194verified(was Sub_D546.) Pass 0: frame lookup, SprBuf_Alloc3 (3 adjacent SprBuf chunks), tiles 0-7 to the buffer start and tiles 8-15 to +$200, INC Obj_State; C=1.
$C0:D608Obj_BuildFrame12Pass0Alt131verified(was Sub_D608.) Pass 0 for the ObjTile_AltLayout ($68) layout: frame lookup, SprBuf_Alloc3, tiles 0-15 in one run to the buffer start, INC Obj_State; C=1 (C=0 when nothing changed or no chunks are...
$C0:D68BObj_BuildFrame12Pass1173verified(was Sub_D68B.) Pass 1: tiles 16-23 to +$100, tiles 24-31 to +$300; INC Obj_State; C=1.
$C0:D738Obj_BuildFrame12Pass1Alt173verified(was Sub_D738.) Pass 1 for the ObjTile_AltLayout ($68) layout: tiles 16-23 to +$200, tiles 24-31 to +$400; INC Obj_State; C=1.
$C0:D7E5Obj_BuildFrame12Pass2644verified(was Sub_D7E5.) Pass 2: tiles 32-47 to +$400, queue the VRAM upload ($500 bytes from Obj_TileBuf to Obj_VramTile*16, then $100 bytes from +$500 to 3 tile rows further on, +$300 words), write the...
$C0:DA69Obj_BuildFrame12Pass2Alt703verified(was Sub_DA69.) Pass 2 for the ObjTile_AltLayout ($68) layout: tiles 32-39 to +$300 and 40-47 to +$500, queue the upload ($100 bytes to Obj_VramTile*16, then $500 bytes from +$100 to the next tile...
$C0:DD28Obj_FrameLayout121,026verified(was Sub_DD28.) Rewrites the 12 SprTile records of a 12-tile object for Obj_LastFrame (tiles already in VRAM): offsets from the frame record (120 bytes, positions after 48 tile words), tile...

Generated from functions.csv. Do not edit.