Language…
4 users online: fanfan21, Gamet2004, Jordan, Josuke Yoshikage - Guests: 67 - Bots: 181
Users: 69,784 (2,507 active)
Latest user: Kidd005

Posts by overdrive

overdrive's Profile → Posts

I've been messing around with Layer 2 levels and had some hiccups I haven't managed to work out. The limitations seem to be common knowledge based on random comments I've seen on various posts/submissions, but I can't find them spelled out anywhere or how/if they can be worked around.

To confirm, my levels are set to this:


Issue 1:

I have partially underwater levels I've implemented by adding water tiles to Layer 2. This seems the best way to implement a SMB3 style level with both water and land since it doesn't leave a bunch of unsightly clear gaps everwhere. This technique has worked quite well for me.

EXCEPT when Mario goes through a pipe or a powerup is rising up from a block.




They work, but the sprite is hidden underneath the water tile til the move is done. I know this isn't a Layer 2 specific thing and that Mario basically goes behind any block when traveling through a pipe, not just priority ones. I get why the game would do that (though I'd rather just set all pipes as priority), but I don't see how I can get around this (tolerable) annoyance.

Issue 2:
More seriously, I've learned that an auto scrolling layer 2 that goes past the end doesn't loop immediately.

I started making a train level with high ideas of tunnels and light strips and all sorts of other fun things. Layer 2 auto scrolls.




I found that layer 2 has to be interactive to make it respect priority tiles, letting me have foreground objects that blur past.



Okay, not an original idea. But it looks good in motion. For abot 15 seconds. Then...


Garbage! The layer loops around alright, but over twice as much as it presumably should. Mode 01, the non-interactive Layer 2 mode (which doesn't respect priority), also does this. I want priority tiles in my scrolling background--failing that, I at least want a large one for added character.

Is there anything I can do to make layer 2 work the way I want it to? To loop before the garbage?
If not, is there a way I can get something reasonably close to what I want using some other method? I haven't fiddled with Layer 3 at all so I don't know if that's the sort of thing it's good for.
Originally posted by Thomas

Use the object Layer 2, but wrap it with some code like this:
Code
!wrapPoint      =   $0400 ; X position to wrap Layer 2 at
!wrapDistance   =   $0400 ; distance to teleport back

main: 
    REP #$20
    LDA $1452|!addr
    CMP #!wrapPoint
    BCC .ret
    SBC #!wrapDistance
    STA $1452|!addr
  .ret:
    SEP #$20
    RTL

You may need to play around with the numbers a bit on those two lines at the top. Note that this doesn't refresh the Layer 2 tilemap (the pre-wrap tiles will stay rendered until new ones scroll on screen) so you'll want to try and match up the screens at either side of the wrap for a clean loop.


I was hoping to avoid editing UberASM; I know that's going to require a lot of background knowledge before I can work out what it's doing to the engine. But if that's the way, *rolls up sleeves*

Code
main: 
    REP #$20                ; Tell the processor we're doing things in words, not bytes
    LDA $1452|!addr         ; Load address $7E1452 into the accumulator.
                            ; 7E1452 == "This is used internally by the scroll sprites for updating the layer 2 X position."
                            ; "In particular, the routine at $05:C4F9 uses it to add the current speed to."
    CMP #!wrapPoint         ; Compare the accumulator to 0x400.  Which happens to be the length of four screens.
    BCC .ret                ; If the accumulator is LESS than 0x400, go to the .ret tag and skip the rest of this.
    SBC #!wrapDistance      ; Subtract 0x400 from the accumulator
    STA $1452|!addr         ; Store the accumulator back in $7E1452
  .ret:
    SEP #$20                ; Tells the processor to go back to bytes
    RTL                     ; End

This is my read. That wasn't too bad I guess.

Of course the next step is working out how the scroll routine uses this value. Trying it out, that routine clearly takes the current screen into account, meaning so will I (High byte of 7E0094, and possibly 7E1933), meaning it's probably best to keep things lined up on screen borders) which means splitting Layer2 into regions and transitioning the backgrounds on a single level is plausible.
It does work right out of the box. Thank you. There are some notes I have for the next guy:

* When the BG rewinds, it rewinds hard.

* The player''s X position has an effect. The rewind does not have to happen on a subscreen boundary even if the wrap points are configured that way.


If you're doing a single background that loops around, neither is a problem as long as your start and end points are aligned. The second bullet point can be avoided by adding the player's X position into the equasion.
Code
    LDA $1452|!addr
    ADC $0094|!dp
    CMP #!wrapPoint
    BCC .ret
    LDA $1452|!addr
    SBC #!wrapDistance
    STA $1452|!addr
  .ret:


With this I think it shoud be possible to make seamless BG transitions using the player X position, additional wrap points, and careful use of the 16 BG screens available to me. I think I can pull it off from here.