Anyway i have found this too:
Sprite Noob Question
Moderator: Moderators
Re: Sprite Noob Question
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.
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.
Re: Sprite Noob Question
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.
Re: Sprite Noob Question
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.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.
- ShaneM
- Posts: 353
- Joined: Wed Apr 04, 2012 4:15 pm
- Location: United States of America (USA)
- Contact:
Re: Sprite Noob Question
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- ShaneM
- Posts: 353
- Joined: Wed Apr 04, 2012 4:15 pm
- Location: United States of America (USA)
- Contact:
Re: Sprite Noob Question
The Mario Master has fixed this issue! Here is my fix:
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
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- Attachments
-
- Super Mario Bros. (World) - Copy (2)_001.png (3.06 KiB) Viewed 3319 times
- ShaneM
- Posts: 353
- Joined: Wed Apr 04, 2012 4:15 pm
- Location: United States of America (USA)
- Contact:
Re: Sprite Noob Question
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:
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
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 offsetCode: 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 (3.9 KiB) Viewed 3154 times