Camera_min_X_pos = ramaddr( $FFFFEE14 ) ; word Camera_max_X_pos = ramaddr( $FFFFEE16 ) ; word Camera_min_Y_pos = ramaddr( $FFFFEE18 ) ; word Camera_max_Y_pos = ramaddr( $FFFFEE1A ) ; wordThe origin point (0,0) of a level is at its top left corner, so Camera_min_X_pos and Camera_max_X_pos correspond to the left and right level boundaries, where as Camera_min_Y_pos and Camera_max_Y_pos correspond to the top and bottom level boundaries, respectively. When a level is first loaded, these addresses are initialized to the values in the LevelSizes data structure:
; xstart xend ystart yend ; Level LevelSizes: dc.w $1308, $6000, $0, $390 ; AIZ1 dc.w $0, $4640, $0, $590 ; AIZ2 dc.w $0, $6000, $0, $1000 ; HCZ1 dc.w $0, $6000, $0, $1000 ; HCZ2 dc.w $0, $6000, -$100, $1000 ; MGZ1 dc.w $0, $6000, $0, $1000 ; MGZ2 dc.w $0, $6000, $0, $B20 ; CNZ1 dc.w $0, $6000, $580, $1000 ; CNZ2 dc.w $0, $2E60, $0, $B00 ; FBZ1 dc.w $0, $6000, $0, $B00 ; FBZ2 ...It should be noted that all the camera positions stored in these addresses correspond to the pixel displayed at the top left corner of the screen. That means in order to figure out the actual level dimensions, you need to add the screen's width (320 pixels) to the max X position, and the screen's height (224 pixels) to the max Y position.
dc.w $60, $60, $0, $240 ; Gumball dc.w $60, $60, $0, $240 ; Gumball dc.w $0, $140, $0, $F00 ; Pachinko dc.w $0, $140, $0, $F00 ; PachinkoFor instance, in the pachinko/glowing spheres stage, although Camera_max_X_pos is set to $140 (320 pixels), since there are already 320 pixels horizontally on screen when Camera_X_pos is zero, scrolling to the right reveals another 320 pixels, for a total level width of 640 pixels. On the flipside, despite Camera_min_X_pos and Camera_max_X_pos both being set to $60, the gumball stage's width isn't actually zero. It just can't scroll horizontally. However, at the very least it's still as wide as the screen, so the actual level width is 320 pixels.
While debug mode is active, the score display is replaced by four counters, which show the player and the camera's current position. This makes it invaluable for testing events triggered by those values. In the example above, 0D00 is the player's X position and 0178 is their Y position, while 0C60 is the camera's X position and 00F8 is its Y position.
As an aside, the time display is also replaced by a counter. This one shows how many sprites are being displayed, in decimal. The reason it alternates between N and N+2 when you have no rings is because the "RINGS" portion of the HUD blinks in and out of existence, and since it's composed of two sprites, one for the "RING" and another for the S, there are two more sprites being displayed on frames in which it's visible.
Exercise: Why is the left boundary for Angel Island Zone 1 set to such a high value?
I assume it is to prevent going back once the intro portion of AIZ1 is scrolled out of view, since after the main level graphics are loaded the intro chucks glitch out.
ReplyDeleteThat, and those chucks aren't solid so you'd inevitably fall into the pit if you could go back.
Right. Due to the whole intro area at the start, the actual level only begins at $1300 or thereabouts. The left boundary is set up for the common case, and then there's special code that pulls it back to zero when you play as Sonic.
DeletePresumably the negative number for MGZ1 is due to the level's vertical looping, and the unusually high number for CNZ2 is to offset for the similar looping in the miniboss arena?
ReplyDeleteGood catch on CNZ2. The low ceiling is there to keep the act 1 boss scroll's guts out of reach, but there's already code elsewhere that resizes the level depending on your horizontal position, so the value there is actually pretty useless.
DeleteNegative numbers do indeed turn infinite scrolling on. I'll get back to this at some point.