Sprite Noob Question

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

User avatar
Anes
Posts: 604
Joined: Tue Dec 21, 2004 8:35 pm
Location: Argentina
Contact:

Re: Sprite Noob Question

Post by Anes » Thu Apr 16, 2015 4:03 pm

I partially fixed it, it was a "hack".

Anyway i have found this too:

Image
ANes

mkwong98
Posts: 226
Joined: Mon May 30, 2011 9:01 pm

Re: Sprite Noob Question

Post by mkwong98 » Thu Apr 16, 2015 8:07 pm

I think it is the responsibility of the game to test for negative values and so you don't need to fix that.

But if you want to make it look better, I can think of two ways of doing it:
1. Detect whether the x value of the sprite comes from a subtraction or not. In that case, you know whether it is a negative value or the sprite really is on the right screen edge.

2. Set a negative range for x, let say 4 pixels, so that positive values for x is limited to 0 - 251 and anything above it will be treated as negative values and are rendered on the left edge. Then you can optionally cover up 4 pixels on each side of the screen.

tepples
Posts: 21973
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Sprite Noob Question

Post by tepples » Thu Apr 16, 2015 8:31 pm

It turns out this bug in SMB1 isn't easily fixable, as the fix ShaneM tried caused the player to get stuck in the wall when attempting the walk through walls glitch. He had to back out the fix.

mkwong98
Posts: 226
Joined: Mon May 30, 2011 9:01 pm

Re: Sprite Noob Question

Post by mkwong98 » Thu Apr 16, 2015 8:44 pm

tepples wrote:It turns out this bug in SMB1 isn't easily fixable, as the fix ShaneM tried caused the player to get stuck in the wall when attempting the walk through walls glitch. He had to back out the fix.
Yes, it is important to fix the rendering without changing the logic behind it. However I understand that this is difficult to do for emulators where the rendering is done directly by the PPU module.

User avatar
ShaneM
Posts: 353
Joined: Wed Apr 04, 2012 4:15 pm
Location: United States of America (USA)
Contact:

Re: Sprite Noob Question

Post by ShaneM » Thu Apr 16, 2015 9:48 pm

tepples wrote:It turns out this bug in SMB1 isn't easily fixable, as the fix ShaneM tried caused the player to get stuck in the wall when attempting the walk through walls glitch. He had to back out the fix.

tepples is right. We talked about this on IRC.

The issue actually deals with collision. The routine in question is "CheckSideMTiles:". That is the routine for left/right collision against any solid object. The glitch occurs when Mario is all the way at the left of the screen, holding left in between another block and the screen, jumping, he gets pushed to the right, making him go partially into the block thus causing him to be pushed more leftward and disappearing for a frame and then reappearing with part of him on the other side. It would be the same since blocks are to the right of Mario and the screen is to the left. He no longer would get pushed if I corrected him from being pushed leftward when going into a block, which fixes that part, but gets stuck in places like where tepples linked where it is required to move on. If Mario is to the left of the screen and jumps, he gets partially sucked into the block to the right and pushed by out the opposite way (leftward) causing him to "wrap" around.

Notice in the link to themushroomkingdom that tepples linked to, the picture called "Mario standing on the wall" specifically. You can see part of Mario's hand on the other side. That wall pushing (intentional) causes the wrap around as seen there. In all the versions, SNES, GBC etc. this collision stands for that very reason. --ShaneM, the Master of ASM.

EDIT: I think I would be able to correct this if I had more PRG. If this was on something like loopy's MMC3 version, I would be able to. A fix would specifically have to be

Code: Select all

LDY Player_OffscreenBits, 
CPY #$F0 ;are we at a specific point at the left of the screen? 
BCS ImpedePlayerMove ;if so, branch
This fix would have to go right at the beginning of the routine "ChkPBtm:" which is really part of "CheckSideMTiles:". If the player's movement is stopped when going leftward, he'd still be able to "walk through walls" to the right.

User avatar
ShaneM
Posts: 353
Joined: Wed Apr 04, 2012 4:15 pm
Location: United States of America (USA)
Contact:

Re: Sprite Noob Question

Post by ShaneM » Fri Apr 17, 2015 12:51 pm

The Mario Master has fixed this issue! Here is my fix:

Code: Select all

RenderPlayerSub:
        sta $07                      ;store number of rows of sprites to draw
        ldy Player_Rel_XPos   ;SHANEM CODE
        cpy #$FF                 ;SHANEM CODE
		bne label         ;SHANEM CODE
		iny                  ;SHANEM CODE
label:	sty Player_Pos_ForScroll     ;SHANEM CODE store player's relative horizontal position
        sty $05                      ;store it here also
        lda Player_Rel_YPos
        sta $02                      ;store player's vertical position
        lda PlayerFacingDir
        sta $03                      ;store player's facing direction
        lda Player_SprAttrib
        sta $04                      ;store player's sprite attributes
        ldx PlayerGfxOffset          ;load graphics table offset
        ldy Player_SprDataOffset     ;get player's sprite data offset
Originally, it was "lda Player_Rel_XPos" and "sta Player_Pos_ForScroll". RAM $03AD was causing underflow when the player jumped in this specific way, but I fixed this and now you can still walk through walls if you get stuck. --ShaneM, the Master of ASM
Attachments
Super Mario Bros. (World) - Copy (2)_001.png
Super Mario Bros. (World) - Copy (2)_001.png (3.06 KiB) Viewed 2196 times

User avatar
ShaneM
Posts: 353
Joined: Wed Apr 04, 2012 4:15 pm
Location: United States of America (USA)
Contact:

Re: Sprite Noob Question

Post by ShaneM » Mon Sep 14, 2015 10:02 am

As I'm getting ready to commit a new build, I realized that the code to SMB: The Lost Levels had to be slightly different to fix this OAM wraparound mentioned by OP; this is due to wind in the game pushing player further left when caught in between the leftmost screen and a block and having RAM $86 increment by an additional #1. So $03AD was actually being underflowed by more than #$FF. This fixes that issue:

Code: Select all

RenderPlayerSub:
        sta $07                      ;store number of rows of sprites to draw
               ldy Player_Rel_XPos   ;SHANEM CODE
               cpy #$FD                 ;SHANEM CODE    SMB:TLL different
               bcc label         ;SHANEM CODE       SMB:TLL different
	       ldy #$00                  ;SHANEM CODE   SMB:TLL different
label:	sty Player_Pos_ForScroll     ;SHANEM CODE store player's relative horizontal position
        
         sty $05                      ;store it here also
        lda Player_Rel_YPos
        sta $02                      ;store player's vertical position
        lda PlayerFacingDir
        sta $03                      ;store player's facing direction
        lda Player_SprAttrib
        sta $04                      ;store player's sprite attributes
        ldx PlayerGfxOffset          ;load graphics table offset
        ldy Player_SprDataOffset     ;get player's sprite data offset
EDIT: I couldn't use A register instead and utilize a transfer and save a byte since neither X nor Y were loaded with zero at the time and the fact that 6502 is lacking in an STZ instruction. So this fix uses 1 additional byte of PRG compared to the NES SMB1 fix above. Don't worry, you can optimize this next routine after to save some space:

Code: Select all



;original

ProcessPlayerAction:
        lda Player_State      ;get player's state
        cmp #$03
        beq ActionClimbing    ;if climbing, branch here
        cmp #$02
        beq ActionFalling     ;if falling, branch here
        cmp #$01
        bne ProcOnGroundActs  ;if not jumping, branch here


;optimized

RenderPlayerSub:
        lda Player_State      ;get player's state
        beq ProcOnGroundActs  ;if not jumping, branch here
        cmp #$03
        beq ActionClimbing    ;if climbing, branch here
        cmp #$02
        beq ActionFalling     ;if falling, branch here

;saves 2 bytes of PRG

Attachments
Super Mario Bros. 2 - The Lost Levels_002.png
Super Mario Bros. 2 - The Lost Levels_002.png (3.9 KiB) Viewed 2031 times

Post Reply