Sunday, January 27, 2013

Daily SMB HL Disassembly Post #7


Presented with no comment for now:

001 JumpMForceData: 002 .byte $20, $20, $1e, $28, $28, $0d, $04 003 004 FallMForceData: 005 .byte $70, $70, $60, $90, $90, $0a, $09 006 007 PlayerYSpdData: 008 .byte $fc, $fc, $fc, $fb, $fb, $fe, $ff 009 010 InitMForceData: 011 .byte $00, $00, $00, $00, $00, $80, $00 012 013 MaxLeftXSpdData: 014 .byte $d8, $e8, $f0 015 016 MaxRightXSpdData: 017 .byte $28, $18, $10 018 .byte $0c ; used for pipe intros 019 020 FrictionData: 021 .byte $e4, $98, $d0 022 023 Climb_Y_SpeedData: 024 .byte $00, $ff, $01 025 026 Climb_Y_MForceData: 027 .byte $00, $20, $ff ; -1 028 029 .code 030 031 .proc PlayerPhysicsSub 032 033 FrictionOffset = temp_byte ; - used to store offset to friction data ( address $00) 034 035 if Player_State = #3 ; check player state, if climbing: 036 037 ldy #0 038 ; get controller bits for up/down; check against player's collision detection bits, if pressing up/down: 039 if a := Up_Down_Buttons & Player_CollisionBits 040 iny 041 if ! a & #BUTTON_UP ; check for pressing up only 042 iny 043 endif 044 endif 045 046 mb x, Player_Y_MoveForce := Climb_Y_MForceData[ Y ] ; store as vertical movement force 047 048 lda #$08 ; load default animation timing 049 mb x, Player_Y_Speed := Climb_Y_SpeedData[ y ] ; store as vertical speed 050 051 if positive ; if climbing down, use default animation timing value 052 lsr ; otherwise divide timer setting by 2 053 endif 054 055 sta PlayerAnimTimerSet ; store animation timer setting and leave 056 rts 057 058 endif ; else: not climbing: 059 060 ;------------------------------------------------------------------------------------------------ 061 062 ; OP -> note two 'jmp X_Physics' a few branches apart 063 064 065 ; if JumpspringAnimCtrl set OR 'A' not pressed OR Previously 'A' was pressed 066 if JumpspringAnimCtrl || ! A_B_Buttons & #BUTTON_A || a & PreviousA_B_Buttons 067 NoJump: 068 jmp X_Physics 069 endif 070 071 ; if here, There is no jumpspring and a there is a valid A button press: 072 073 if lda Player_State ; check player state, not zero = not on ground 074 075 if !SwimmingFlag goto NoJump ; if swimming flag not set (comment this line for air jumping) 076 ; if here, we are swimming: 077 ; if jump/swim timer zero AND player's vertical speed UP 078 if !JumpSwimTimer && Player_Y_Speed == negative 079 jmp X_Physics ; if timer at zero and player still rising, do not swim 080 endif 081 endif 082 083 ; Do Y Physics (Jumping or Swimming): 084 085 mb JumpSwimTimer := #$20 ; set jump/swim timer 086 mb y := #0 087 mb Player_YMF_Dummy := y ; #0 088 mb Player_Y_MoveForce := y ; #0 089 mb JumpOrigin_Y_HighPos := Player_Y_HighPos 090 mb JumpOrigin_Y_Position := Player_Y_Position 091 mb Player_State := #1 ; set player state to jumping/swimming 092 093 lda Player_XSpeedAbsolute 094 ; check value related to walking/running speed 095 if a < #$09 goto CheckSwimming 096 iny ; 1 097 if a < #$10 goto CheckSwimming 098 iny ; 2 099 if a < #$19 goto CheckSwimming 100 iny ; 3 101 if a < #$1c goto CheckSwimming 102 iny ; 4 103 104 CheckSwimming: 105 106 mb DiffToHaltJump := #1 107 108 if SwimmingFlag 109 ldy #5 110 if Whirlpool_Flag 111 iny ; 6 112 endif 113 endif 114 115 ; store appropriate jump/swim 116 117 mb VerticalForce := JumpMForceData[ y ] ; data here 118 mb VerticalForceDown := FallMForceData[ y ] 119 mb Player_Y_MoveForce := InitMForceData[ y ] 120 mb Player_Y_Speed := PlayerYSpdData[ y ] 121 122 if SwimmingFlag ; if swimming 123 mb Square1SoundQueue := #SFX_EnemyStomp ; load swim/goomba stomp sound 124 if Player_Y_Position >= #$14 goto X_Physics ; if below a certain point, branch 125 mb Player_Y_Speed := #0 ; otherwise reset player's vertical speed to stay below water 126 else ; not swimming: 127 lda #SFX_BigJump ; load big mario's jump sound by default 128 if ldy PlayerSize == SmallMario ; if mario is small 129 lda #SFX_SmallJump ; load small mario's jump sound 130 endif 131 sta Square1SoundQueue ; store appropriate jump sound in square 1 sfx queue 132 endif 133 134 ; --------------------------------------------------------------------------------- 135 136 X_Physics: 137 138 mb y, FrictionOffset := #0 ; init value here 139 140 if Player_State != zero ; if mario is not on the ground 141 if Player_XSpeedAbsolute >= #$19 goto GetXPhy ; check something that seems to be related to mario's speed 142 else C clear ; mario on ground: 143 iny 144 if lda AreaType != zero ; check area type, if not water: 145 dey ; decrement Y by default for non-water type area 146 if Left_Right_Buttons = Player_MovingDir ; get left/right controller bits, check against moving direction 147 if A_B_Buttons & #BUTTON_B goto SetRunningTimer ; check for b button pressed if pressed, skip ahead to set timer 148 if RunningTimer goto GetXPhy ; check for running timer set 149 endif 150 endif 151 endif 152 153 iny ; if running timer not set or level type is water, 154 inc FrictionOffset ; increment Y again and temp variable in memory 155 156 if RunningSpeed || Player_XSpeedAbsolute >= #$21 ; if running speed set or speed => $21 increment FrictionOffset 157 158 inc FrictionOffset 159 160 ; endif could go here for better code, but waste of cycles.. 161 162 jmp GetXPhy ; and jump ahead 163 164 SetRunningTimer: 165 mb RunningTimer := #$0a ; if b button pressed and pressing direction of movment, set running timer 166 167 endif 168 GetXPhy: 169 170 171 mb MaximumLeftSpeed := MaxLeftXSpdData[ y ] ; get maximum speed to the left 172 173 if GameEngineSubroutine = #$07 ; check for specific routine running 174 ldy #3 175 endif 176 177 mb MaximumRightSpeed := MaxRightXSpdData[ y ] ; get maximum speed to the right 178 ldy FrictionOffset ; get other value in memory 179 mb FrictionAdderLow := FrictionData[ y ] ; get value using value in memory as offset 180 mb FrictionAdderHigh := #0 ; init something here 181 182 if PlayerFacingDir <> Player_MovingDir ; check facing direction against moving direction 183 asl FrictionAdderLow ; otherwise shift d7 of friction adder low into carry 184 rol FrictionAdderHigh ; then rotate carry onto d0 of friction adder high 185 endif 186 187 rts ; and then leave 188 189 .endproc

Tuesday, January 8, 2013

Ca65hl Macros

If you are interested in using the ca65 macros that are used on this blog, I'm going to keep them updated here: https://www.assembla.com/code/ca65hl/git/nodes There is also a nice wiki on assembla that I plan on updating. There is not much there at this time, but there will be more soon.

Daily SMB HL Disassembly Post #6

I've arbitrary selected this code to post next.
This code is run to display the points won when jumping onto an enemy, hitting a coinblock or grabbing a mushroom, etc.
There is a scetion where it checks if the current enemy falls within a certain range of tests and uses a different OAM offset, but I am uncertian what the purpose is. Otherwise, this is pretty easy to follow.

FloateyNum[ x ]::Control - the score to award (or a 1up)
FloateyNum[ x ]::X_Pos - the screen x pos
FloateyNum[ x ]::Y_Pos - the screen y pos

Note the FloateyNum is not initailized here, just processed, The Spawning code will be posted soon.

001 ; DATA 002 ; Sprite tile pairs: 003 004 FloateyNumTileData: 005 006 .byte $ff, $ff ; dummy 007 .byte $f6, $fb ; "100" 008 .byte $f7, $fb ; "200" 009 .byte $f8, $fb ; "400" 010 .byte $f9, $fb ; "500" 011 .byte $fa, $fb ; "800" 012 .byte $f6, $50 ; "1000" 013 .byte $f7, $50 ; "2000" 014 .byte $f8, $50 ; "4000" 015 .byte $f9, $50 ; "5000" 016 .byte $fa, $50 ; "8000" 017 .byte $fd, $fe ; "1-UP" 018 019 ScoreUpdateData: 020 021 ; high nybble is digit number ( 4 is 100, 3 is 1000), low nybble is number to 022 ; add to the digit of the player's score 023 024 .byte $ff ; dummy 025 .byte $41, $42, $44, $45, $48 026 .byte $31, $32, $34, $35, $38 027 .byte $00 ; 1 up 028 029 .code 030 031 ;---------------------------------------------------------------------------------------------- 032 033 .proc FloateyNumbersRoutine 034 035 ; load control for floatey number, if zero, branch to leave 036 if lda FloateyNum[ x ]::Control == zero goto PlayerEndWorld::Exit 037 038 if a >= #$0b 039 mb FloateyNum[ x ]::Control := #$0b ; set to $0b, thus keeping it in range 040 endif 041 042 tay ; use as Y 043 044 if !FloateyNum_Timer[ x ] ; check value here 045 mb FloateyNum[ x ]::Control := a ; #0 ; initialize floatey number control and leave 046 rts 047 endif 048 049 dec FloateyNum_Timer,x ; decrement value here 050 051 ; if FloateyNum_Timer = 2b (before decrement) 052 if a = #$2b 053 054 ; if FloateyNum[ x ]::Control = #$0b 055 if y = #$0b ; check offset for $0b 056 inc NumberofLives ; give player one extra life (1-up) 057 mb Square2SoundQueue := #Sfx_ExtraLife ; and play the 1-up sound 058 endif 059 060 ; use as X offset, essentially the digit to be incremented 061 mb x := ScoreUpdateData[ y ] >> 4 062 ; mask out the high nybble, store as amount to add to the digit 063 mb DigitModifier[ x ] := ScoreUpdateData[ y ] & #%00001111 064 065 jsr AddToScore ; update the score accordingly 066 067 endif 068 069 ldy Enemy_SprDataOffset,x ; get OAM data offset for enemy object 070 071 072 ; This section of codes purpose is uncertain: 073 ; ------------------------------------------------ 074 mb a := Enemy_ID[ x ] 075 ; if enemy is not spiny AND not Pplant AND ( is hammerbro OR 076 ; ( Not either cheepcheep AND ( greater or equal to tallenemy OR state less than #2)) ) 077 078 if a <> #Spiny && a <> #PiranhaPlant && ( a = #HammerBro || \ 079 ( a <> #GreyCheepCheep && a <> #RedCheepCheep && ( a >= #TallEnemy || Enemy_State[x] < #$02 ) ) ) 080 ldx SprDataOffset_Ctrl ; load some kind of control bit 081 ldy Alt_SprDataOffset,x ; get alternate OAM data offset 082 ldx ObjectOffset ; get enemy object offset again 083 endif 084 ; ------------------------------------------------ 085 086 087 if FloateyNum[ x ]::Y_Pos >= #$18 ; if coordinate is below the status bar: 088 ; carry is clear 089 mb FloateyNum[ x ]::Y_Pos := a -- #1 ; subtract one (move up one pixel) and store as new 090 endif 091 092 mb a := FloateyNum[ x ]::Y_Pos -- #8 ; subtract eight and dump into the 093 jsr DumpTwoSpr ; left and right sprite's Y coordinates 094 095 mb Sprite[ y ]::X_Position := FloateyNum[ x ]::X_Pos ; X coordinate of left sprite 096 mb Sprite[ y + 4 ]::X_Position := a + #8 ; X coordinate of right sprite 097 098 mb a := #$02 099 mb Sprite[ y ]::Attributes := a ; set palette control in attribute bytes 100 mb Sprite[ y + 4 ]::Attributes := a ; of left and right sprites 101 102 mb x := FloateyNum[ x ]::Control * 2 ; and use as offset for look-up table 103 mb Sprite[ y ]::Tilenumber := FloateyNumTileData[ x ] ; display first half of number of points 104 mb Sprite[ y + 4 ]::Tilenumber := FloateyNumTileData[ x + 1 ] ; display the second half 105 106 ldx ObjectOffset ; get enemy object offset and leave 107 rts 108 109 .endproc