;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; SMW Gray Moving Castle Block (sprite BB), by imamelia
;; additional modifications by Milk
;;
;; This is a disassembly of sprite BB in SMW, the moving castle block.
;; Additional modifications include having it only use two tiles with a
;; Y-offset of $F7 as well as making it passable from the sides and bottom.
;; Additionally, the original state times have been adjusted.
;;
;; Uses first extra bit: YES
;;
;; The extra bit will cause the sprite to read from an alternate speed
;; and state table.
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; defines and tables
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

!ExtraBit = $04	; normally $04; may be set to $01 if using GEMS

Speed:
db $00,$F0,$00,$10

TimeInState:
db $90,$60,$90,$60

Speed2:
db $00,$F8,$00,$08

TimeInState2:
db $00,$E0,$00,$E0

TileDispX:
db $00,$10

TileDispY:
db $F7,$F7

Tilemap:
db $EC,$EE

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; init routine
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

print "INIT ",pc
RTL

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; main routine wrapper
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

print "MAIN ",pc
PHB
PHK
PLB
JSR GrayBlockMain
PLB
RTL

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; main routine
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GrayBlockMain:

JSR GrayBlockGFX	; draw the sprite

LDA $9D		; if sprites are locked...
BNE Return0	; return

LDA $7FAB10,x	;
AND #!ExtraBit	; if extra bit is set...
BNE AltTables	; use alternate speed tables

LDA $1540,x	; if the state timer is up...
BNE NoStateChange	;

INC $C2,x	; increment the sprite state
LDA $C2,x	;
AND #$03	; 4 indexes
TAY		;
LDA TimeInState,y	;
STA $1540,x	; reset the timer
BRA SkipRedundant	;

NoStateChange:	;

LDA $C2,x	;
AND #$03	; 4 indexes
TAY		;

SkipRedundant:

LDA Speed,y	;
TAY		; get the sprite speed into Y
BRA Continue

AltTables:

LDA $1540,x	; if the state timer is up...
BNE NoStateChange2	;

INC $C2,x	; increment the sprite state
LDA $C2,x	;
AND #$03	; 4 indexes
TAY		;
LDA TimeInState2,y	;
STA $1540,x	; reset the timer
BRA SkipRedundant2	;

NoStateChange2:	;

LDA $C2,x	;
AND #$03	; 4 indexes
TAY		;

SkipRedundant2:

LDA Speed2,y	;
TAY		; get the sprite speed into Y

;LDA $7FAB10,x	;
;AND #!ExtraBit	; if the extra bit is set...
;BNE MoveVertically	; move vertically

Continue:

STY $B6,x		; if we're moving horizontally, store the speed value to the X speed table
JSL $018022	; and update sprite X position without gravity
STA $1528,x	; prevent the player from sliding
BRA SolidBlock	;

;MoveVertically:	;

;STY $AA,x	; if we're moving vertically, store the speed value to the Y speed table
;JSL $01801A	; and update sprite Y position without gravity

SolidBlock:	;

LDA $9E,x	; this code wasn't in the original sprite; I had to add it
PHA		; preserve the current sprite number
LDA #$BB		; temporarily set the sprite number to the same as the original
STA $9E,x		; (this is necessary to prevent the player glitching through the sides)

JSL $01B44F	; invisible solid block routine

PLA		;
STA $9E,x		; restore the sprite number

Return0:
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; graphics routine
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GrayBlockGFX:

JSL $20CA4F	; set up some things

PHX		; preserve the sprite index
LDX #$01		; 2 tiles to draw

GFXLoop:		;

LDA $00		;
CLC		;
ADC TileDispX,x	; set the tile X displacement
STA $0300,y	;

LDA $01		;
CLC		;
ADC TileDispY,x	; set the tile Y displacement
STA $0301,y	;

LDA Tilemap,x	; set the tile number
STA $0302,y	;

LDA #$03		; second GFX page, palette 9
ORA $64		; add in level priority bits
STA $0303,y	; set the tile properties

INY #4		;
DEX		; decrement the tile index
BPL GFXLoop	; if positive, draw more tiles

PLX		; pull the sprite index back
LDY #$02		; the tiles are 16x16
LDA #$01		; 2 tiles were drawn
JSL $81B7B3	;
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; subroutines
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

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

