geschrieben am 25.12.2012 16:08:50 in Weihnachten 2012
(
Link
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; SMW Floating Platforms (sprites 5B & 5C), by imamelia
;;
;; This is a disassembly of sprites 5B and 5C in SMW, floating platforms.
;;
;; Uses first extra bit: YES
;;
;; If the extra bit is clear, this will act like sprite 5B, a wooden platform. If the
;; extra bit is set, this will act like sprite 5C, a checkerboard platform. You must
;; set sprite buoyancy on for these to work.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; defines and tables
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
!ExtraBit = $04 ; extra bit (should usually be 04, but 01 works if you're using GEMS)
!WoodenTile1 = $60 ; the left tile of the wooden platform
!WoodenTile2 = $61 ; the middle tile of the wooden platform
!WoodenTile3 = $62 ; the right tile of the wooden platform
!CheckerboardTile1 = $EA ; the left tile of the checkerboard platform
!CheckerboardTile2 = $EB ; the middle tile of the checkerboard platform
!CheckerboardTile3 = $EC ; the right tile of the checkerboard platform
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; init routine
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print "INIT ",pc ;
LDA $7FAB10,x ; sprite extra bits
LSR ;
LSR ; remove these two LSRs if you're using GEMS and have set !ExtraBit to $01
AND #$01 ;
STA $1504,x ; make a backup of the extra bit at $1504,x
BEQ InitFloatingPlat ;
INC $1662,x ; adjust the sprite clipping if necessary
INC $1602,x ;
LDA $160E ; if sprite buoyancy is not on...
BNE InitFloatingPlat ;
INC $C2,x ;
RTL ;
InitFloatingPlat: ;
LDA #$03 ;
STA $151C,x ; set some sort of counter...
InitObjContLoop: ;
JSL $019138 ; check the sprite's contact with objects
LDA $164A,x ; if the sprite is in water or lava...
BNE EndInit ; terminate the init routine
DEC $151C,x ; decrement the counter
BMI ReInit ; and if it has dropped below zero, re-initialize the sprite...?
LDA $D8,x ;
CLC ;
ADC #$08 ; offset the sprite's Y position
STA $D8,x ;
LDA $14D4,x ;
ADC #$00 ; handle the high byte
STA $14D4,x ;
CMP #$02 ; if the high byte has reached 02...
BCS EndInit ; end the init routine
BRA InitObjContLoop ;
ReInit: ;
LDA #$01 ;
STA $14C8,x ;
EndInit:
RTL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; main routine wrapper
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print "MAIN ",pc
PHB
PHK
PLB
JSR FloatingPlatformMain
PLB
RTL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; main routine
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FloatingPlatformMain:
LDA $9D ;
BEQ NoSkip1 ; if sprites are locked...
JMP SkipToGFX ; skip directly to the GFX routine
NoSkip1: ;
LDA $1588,x ; check the sprite's blocked status
AND #$0C ; if the sprite is touching the ceiling or floor...
BNE NoUpdateY ; don't update its Y position
JSL $01801A ; update sprite Y position without gravity
NoUpdateY: ;
STA $1491 ; reset the "prevent sliding on a platform" flag
; removed sprite number check for the spike ball (CMP #$A4)
LDA $AA,x ; check the sprite Y speed
CMP #$40 ; if it is greater than 40...
BPL NoIncYSpeed ; don't increment it
INC $AA,x ; if it is 40 or less, increment it
NoIncYSpeed: ;
LDA $164A,x ; if the sprite isn't in water or lava...
BEQ NoDecYSpeed ; don't do some subsequent Y speed checks
; another removed sprite number check
LDA $AA,x ; check the sprite's Y speed
BPL DecYSpeed ; if positive, decrement it
CMP #$F8 ; also decrement it if it is negative
BCC NoDecYSpeed ; and no less than F8
DecYSpeed: ;
SEC ;
SBC #$02 ; decrement the sprite's Y speed by 2
STA $AA,x ;
NoDecYSpeed:
LDA $7D ;
PHA ; save the player Y speed value
JSL $01B44F ; invisible solid block/platform routine
PLA ;
STA $00 ;
STZ $185E ;
BCC NoContact ; branch if the player isn't on the sprite
; removed sprite number check
INC $185E ;
LDA $00 ; check the value from before
CMP #$20 ; if it is less than 20...well, why the heck wouldn't it be? We just stored 02/03 to it!
BCC NoContact ; skip setting the Y speed again
LSR ;
LSR ;
STA $AA,x ; set the Y speed *again* (surely Nintendo could have done this better)
NoContact: ;
LDA $185E ;
CMP $151C,x ; not sure what the purpose of this is
STA $151C,x ;
BEQ SkipYSpd2 ;
LDA $185E ;
BNE SkipYSpd2 ; or this
LDA $7D ;
BPL SkipYSpd2 ; branch if the player is moving downward
LDY #$08 ; start Y at 08
LDA $19 ; if the player is small...
BNE NotSmall2 ;
LDY #$06 ; use Y = 06 instead
NotSmall2: ;
STY $00 ;
LDA $AA,x ; ANOTHER Y speed check?!
CMP #$20 ;
BPL SkipYSpd2 ; branch if the sprite Y speed is greater than 20...
CLC ;
ADC $00 ; Good gravy, how many times are they going to change the Y speed in this thing?
STA $AA,x ; Who programmed the sprite, some old geezer with Alzheimer's?
SkipYSpd2: ;
LDA $13 ;
AND #$01 ;
BNE SkipToGFX ; skip the next part every other frame
LDA $AA,x ; check the Y speed AGAIN
BEQ NoChangeYSpd1 ;
BPL NoIncYSpd2 ;
CLC ;
ADC #$02 ;
NoIncYSpd2: ; there HAS to be a better way of doing this...
SEC ;
SBC #$01 ; because we totally haven't already messed with the sprite's Y speed enough,
STA $AA,x ; we'll set it again
NoChangeYSpd1: ;
LDY $185E ; I'd put an enlightening comment here,
BEQ SkipYSpd3 ; but your guess is as good as mine.
LDY #$05 ;
LDA $19 ; Hey, kids! Let's play the "set Y to a number depending on whether or not
BNE SkipYSpd3 ; the player is small" game again!
LDY #$02 ; This time, our lovely numbers are 05 and 02!
SkipYSpd3: ;
STY $00 ;
LDA $D8,x ;
PHA ; save the sprite Y position...this can't be good...
SEC ;
SBC $00 ;
STA $D8,x ; Okay, so...apparently we're messing with the sprite's Y position
LDA $14D4,x ; as well as its speed. Wonderful.
PHA ;
SBC #$00 ;
STA $14D4,x ; looks like we want to offset the sprite's Y position...
JSL $019138 ; so that it will use a different base position when interacting with objects.
PLA ; pull back stuff
STA $14D4,x ;
PLA ; All this just to make the sprite float?
STA $D8,x ; Nintendo, you fail.
SkipToGFX: ;
JSR SubOffscreenX0 ; Whoa! Something that we actually semi-know what it does!
; removed sprite check
FloatingPlatformGFX: ;
; removed flipping sprite check
JSR GetDrawInfo ;
LDA $1602,x ;
STA $01
LDA $D8,x ;
SEC ;
SBC $1C ;
STA $0301,y ;
STA $0305,y ;
STA $0309,y ;
LDX $01 ; if the sprite is a checkerboard platform...
BEQ Only3Tiles1: ; we'll be drawing 5 tiles instead of 3
STA $030D,y ;
STA $0311,y ;
Only3Tiles1: ;
LDX $15E9 ;
LDA $E4,x ;
SEC ;
SBC $1A ;
STA $0300,y ; set the tile X displacement
CLC ;
ADC #$10 ;
STA $0304,y ; second tile 16 pixels to the right of the first
CLC ;
ADC #$10 ;
STA $0308,y ; third tile 16 pixels to the right of the second
LDX $01 ;
BEQ Only3Tiles2 ; and, if necessary...
CLC ;
ADC #$10 ;
STA $030C,y ; fourth tile 16 pixels to the right of the third
CLC ;
ADC #$10 ;
STA $0310,y ; fifth tile 16 pixels to the right of the fourth
Only3Tiles2: ;
LDX $15E9 ;
LDA $01 ; if the sprite is the wooden one...
BEQ WoodenTiles ; draw different tiles
LDA #!CheckerboardTile1 ;
STA $0302,y ; first tile
LDA #!CheckerboardTile2 ;
STA $0306,y ; second,
STA $030A,y ; third,
STA $030E,y ; and fourth tiles
LDA #!CheckerboardTile3 ;
STA $0312,y ; fifth tile
BRA SetUpTiles ;
WoodenTiles: ;
LDA #!WoodenTile1 ;
STA $0302,y ; first tile
LDA #!WoodenTile2 ;
STA $0306,y ; second,
STA $030A,y ; third,
STA $030E,y ; and fourth tiles...?
LDA #!WoodenTile3 ;
STA $0312,y ; fifth tile...? Maybe this graphics routine is shared by another sprite?...
SetUpTiles: ;
LDA $64 ;
ORA $15F6,x ; no hardcoded palette this time, and the two platforms use the same one
STA $0303,y ; properties for the first...
STA $0307,y ; second...
STA $030B,y ; third...
STA $030F,y ; fourth...
STA $0313,y ; and fifth tile
LDA $01 ;
BNE Draw5Tiles ; set the number of tiles to be drawn as 3 or 5
LDA #!WoodenTile3 ; if only 3...
STA $030A,y ; make the third tile the end of the wooden platform
LDA #$02 ; 3 tiles to draw
BRA FinishGFX ;
Draw5Tiles: ;
LDA #$04 ; 5 tiles to draw
FinishGFX: ;
LDY #$02 ; all tiles are 16x16
JSL $81B7B3 ;
RTS ;
Table1: db $0C,$1C
Table2: db $01,$02
Table3: db $40,$B0
Table6: db $01,$FF
Table4: db $30,$C0,$A0,$C0,$A0,$F0,$60,$90,$30,$C0,$A0,$80,$A0,$40,$60,$B0
Table5: db $01,$FF,$01,$FF,$01,$FF,$01,$FF,$01,$FF,$01,$FF,$01,$00,$01,$FF
SubOffscreenX0:
LDA #$00
;BRA SubOffscreenMain
;SubOffscreenX1:
;LDA #$02
;BRA SubOffscreenMain
;SubOffscreenX2:
;LDA #$04
;BRA SubOffscreenMain
;SubOffscreenX3:
;LDA #$06
;BRA SubOffscreenMain
;SubOffscreenX4:
;LDA #$08
;BRA SubOffscreenMain
;SubOffscreenX5:
;LDA #$0A
;BRA SubOffscreenMain
;SubOffscreenX6:
;LDA #$0C
;BRA SubOffscreenMain
;SubOffscreenX7:
;LDA #$0E
SubOffscreenMain:
STA $03
JSR SubIsOffscreen
BEQ Return2
LDA $5B
LSR
BCS VerticalLevel
LDA $D8,x
CLC
ADC #$50
LDA $14D4,x
ADC #$00
CMP #$02
BPL EraseSprite
LDA $167A,x
AND #$04
BNE Return2
LDA $13
AND #$01
ORA $03
STA $01
TAY
LDA $1A
CLC
ADC Table4,y
ROL $00
CMP $E4,x
PHP
LDA $1B
LSR $00
ADC Table5,y
PLP
SBC $14E0,x
STA $00
LSR $01
BCC Label20
EOR #$80
STA $00
Label20:
LDA $00
BPL Return2
EraseSprite:
LDA $14C8,x
CMP #$08
BCC KillSprite
LDY $161A,x
CPY #$FF
BEQ KillSprite
LDA #$00
STA $1938,y
KillSprite:
STZ $14C8,x
Return2:
RTS
VerticalLevel:
LDA $167A,x
AND #$04
BNE Return2
LDA $13
LSR
BCS Return2
AND #$01
STA $01
TAY
LDA $1C
CLC
ADC Table3,y
ROL $00
CMP $D8,x
PHP
LDA $1D
LSR $00
ADC Table6,y
PLP
SBC $14D4,x
STA $00
LDY $02
BEQ Label22
EOR #$80
STA $00
Label22:
LDA $00
BPL Return2
BMI EraseSprite
SubIsOffscreen:
LDA $15A0,x
ORA $186C,x
RTS
GetDrawInfo:
STZ $186C,x
STZ $15A0,x
LDA $E4,x
CMP $1A
LDA $14E0,x
SBC $1B
BEQ OnscreenX
INC $15A0,x
OnscreenX:
LDA $14E0,x
XBA
LDA $E4,x
REP #$20
SEC
SBC $1A
CLC
ADC.w #$0040
CMP #$0180
SEP #$20
ROL A
AND #$01
STA $15C4,x
BNE Invalid
LDY #$00
LDA $1662,x
AND #$20
BEQ OnscreenLoop
INY
OnscreenLoop:
LDA $D8,x
CLC
ADC Table1,y
PHP
CMP $1C
ROL $00
PLP
LDA $14D4,x
ADC #$00
LSR $00
SBC $1D
BEQ OnscreenY
LDA $186C,x
ORA Table2,y
STA $186C,x
OnscreenY:
DEY
BPL OnscreenLoop
LDY $15EA,x
LDA $E4,x
SEC
SBC $1A
STA $00
LDA $D8,x
SEC
SBC $1C
STA $01
RTS
Invalid:
PLA
PLA
RTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;HDMA Brightness Gradient Bottom
;by Ice Man
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
lorom ;\ ROM is LoRom
header ;| and has a header
org $228000 ;/ Address to insert code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;RATS Tag Macro
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
macro RATS_start(id)
db "STAR"
dw RATS_Endcode-RATS_Startcode
dw RATS_Endcode-RATS_Startcode ^#$FFFF
RATS_Startcode:
endmacro
macro RATS_end(id)
RATS_Endcode:
endmacro
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;HDMA Channel Settings
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%RATS_start(0)
REP #$20 ;\ Set processor 16 bit
LDA #$0000 ;| $4350 = $2100
STA $4350 ;| $4351 = Mode 00
LDA #Gradient ;| Get gradient pointer
STA $4352 ;| low and high byte
PHK ;| Get bank
PLY ;|
STY $4354 ;| Store to address bank
SEP #$20 ;/ Set processor 8 bit
LDA #$20 ;\ Enable HDMA
TSB $0D9F ;| on channel 5
RTS ;/ Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Table Settings
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Gradient:
db $80,$0F
db $10,$0F
db $08,$0E
db $08,$0D
db $08,$0C
db $08,$0B
db $08,$0A
db $08,$09
db $08,$08
db $08,$07
db $08,$06
db $00
%RATS_end(0)