;Blue Paratroopa
;by Alcaro
;based off a disassembly of the vertical red paratroopa


print "INIT ",pc
Init:
JSL $01ACF9
STA $1570,x
JSR SubHorizPos
TYA
STA $157C,x
LDA #$10
STA $AA,x
RTL


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

Main:
JSR SUB_OFF_SCREEN_X0

LDA $9D
BNE .Return
LDA $157C,x
PHA
JSR UpdateDirection
PLA
CMP $157C,x
BEQ +
LDA #$08
STA $15AC,x
+
JSR SetAnimationFrame
JSL $01801A
JSL $018022

LDA $1540,x
BNE .Interact
INC $C2,x
LDA $C2,x
AND #$03
BNE .Interact
LDA $AA,x
BEQ +
LDA $B6,x
BEQ +
LDA $151C,x
INC A
AND #$3F
STA $151C,x
+
LDA $151C,x
LSR #4
TAY
LDA $AA,x
CLC
ADC .YBoost,y
STA $AA,x
LDA $B6,x
CLC
ADC .XBoost,y
STA $B6,x
.Interact

LDA $AA,x
PHA
JSL $01803A
PLA
CMP $AA,x
BEQ .Return
LDA #$00
STA $7FAB10,x

.Return
JMP Graphics;yes, it actually does this. pretty backwars, but I don't care...

.XBoost
db $01,$FF,$FF,$01
.YBoost
db $FF,$FF,$01,$01

Graphics:
LDA $157C,x
PHA
LDY $15AC,x
BEQ ++
LDA #$02
STA $1602,x
LDA #$00
CPY #$05
BCC +
INC A
+
EOR $157C,x
STA $157C,x
++
LDA $1602,x
LSR
LDA $D8,x
PHA
SBC #$0F
STA $D8,x
LDA $14D4,x
PHA
SBC #$00
STA $14D4,x
JSL $019D5F
PLA
STA $14D4,x
PLA
STA $D8,x
JSR Wing
PLA
STA $157C,x
RTS

Wing:
LDA $1602,x
AND #$02
STA $02
LDA $186C,x
BNE .Return
LDA $E4,x
STA $00
LDA $14E0,x
STA $04
LDA $D8,x
STA $01
LDY $15EA,x
PHX
LDA $157C,x
ASL
ADC $02
TAX
LDA $00
CLC
ADC .DispXLo,x
STA $00
LDA $04
ADC .DispXHi,x
PHA
LDA $00
SEC
SBC $1A
STA $0300,y
PLA
SBC $1B
BNE .PullAndReturn
LDA $01
SEC
SBC $1C
CLC
ADC .DispY,x
STA $0301,y
LDA .Tiles,x
STA $0302,y
LDA $64
ORA .Prop,x
STA $0303,y
TYA
LSR
LSR
TAY
LDA .Size,x
STA $0460,y
.PullAndReturn
PLX
.Return
RTS

.DispXLo
db $FF,$F7,$09,$09
.DispXHi
db $FF,$FF,$00,$00
.DispY
db $FC,$F4,$FC,$F4
.Tiles
db $5D,$C6,$5D,$C6
.Prop
db $46,$46,$06,$06
.Size
db $00,$02,$00,$02

;half of those are shared between a bunch of sprites
SubHorizPos:
LDY #$00
LDA $D1
SEC
SBC $E4,x
STA $0F
LDA $D2
SBC $14E0,x
BPL .Return
INY
.Return
RTS


UpdateDirection:
LDA #$00
LDY $B6,x
BEQ .Return
BPL +
INC A
+
STA $157C,x
.Return
RTS

SetAnimationFrame:
INC $1570,x
LDA $1570,x
LSR #3
AND #$01
STA $1602,x
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B760 - graphics routine helper - shared
; sets off screen flags and sets index to OAM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;org $03B75C

TABLE1:			db $0C,$1C
TABLE2:			db $01,$02

GET_DRAW_INFO:		STZ $186C,x             ; reset sprite offscreen flag, vertical
			STZ $15A0,x             ; reset sprite offscreen flag, horizontal
			LDA $E4,x               ; \
			CMP $1A                 ;  | set horizontal offscreen if necessary
			LDA $14E0,x             ;  |
			SBC $1B                 ;  |
			BEQ ON_SCREEN_X         ;  |
			INC $15A0,x             ; /

ON_SCREEN_X:		LDA $14E0,x             ; \
			XBA			;  |
			LDA $E4,x               ;  |
			REP #$20                ;  |
			SEC			;  |
			SBC $1A                 ;  | mark sprite invalid if far enough off screen
			CLC			;  |
			ADC #$0040            ;  |
			CMP #$0180            ;  |
			SEP #$20                ;  |
			ROL A                   ;  |
			AND #$01                ;  |
			STA $15C4,x             ; / 
			BNE INVALID             ; 
			
			LDY #$00                ; \ set up loop:
			LDA $1662,x             ;  | 
			AND #$20                ;  | if not smushed (1662 & 0x20), go through loop twice
			BEQ ON_SCREEN_LOOP      ;  | else, go through loop once
			INY			; / 
ON_SCREEN_LOOP:		LDA $D8,x               ; \ 
			CLC			;  | set vertical offscreen if necessary
			ADC TABLE1,y            ;  |
			PHP			;  |
			CMP $1C                 ;  | (vert screen boundry)
			ROL $00                 ;  |
			PLP			;  |
			LDA $14D4,x             ;  | 
			ADC #$00                ;  |
			LSR $00                 ;  |
			SBC $1D                 ;  |
			BEQ ON_SCREEN_Y         ;  |
			LDA $186C,x             ;  | (vert offscreen)
			ORA TABLE2,y            ;  |
			STA $186C,x             ;  |
ON_SCREEN_Y:		DEY			;  |
			BPL ON_SCREEN_LOOP      ; /

			LDY $15EA,x             ; get offset to sprite OAM
			LDA $E4,x               ; \ 
			SEC			;  | 
			SBC $1A                 ;  | $00 = sprite x position relative to screen boarder
			STA $00                 ; / 
			LDA $D8,x               ; \ 
			SEC			;  | 
			SBC $1C                 ;  | $01 = sprite y position relative to screen boarder
			STA $01                 ; / 
			RTS			; return

INVALID:		PLA			; \ return from *main gfx routine* subroutine...
			PLA			;  |    ...(not just this subroutine)
			RTS			; /

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUB_OFF_SCREEN
; This subroutine deals with sprites that have moved off screen
; It is adapted from the subroutine at $01AC0D
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
			
SPR_T12:		db $40,$B0
SPR_T13:		db $01,$FF
SPR_T14:		db $30,$C0,$A0,$C0,$A0,$F0,$60,$90		;bank 1 sizes
			db $30,$C0,$A0,$80,$A0,$40,$60,$B0		;bank 3 sizes
SPR_T15:		db $01,$FF,$01,$FF,$01,$FF,$01,$FF		;bank 1 sizes
			db $01,$FF,$01,$FF,$01,$00,$01,$FF		;bank 3 sizes

SUB_OFF_SCREEN_X1:	LDA #$02                ; \ entry point of routine determines value of $03
			BRA STORE_03            ;  | (table entry to use on horizontal levels)
SUB_OFF_SCREEN_X2:	LDA #$04                ;  | 
			BRA STORE_03            ;  |
SUB_OFF_SCREEN_X3:	LDA #$06                ;  |
			BRA STORE_03            ;  |
SUB_OFF_SCREEN_X4:	LDA #$08                ;  |
			BRA STORE_03            ;  |
SUB_OFF_SCREEN_X5:	LDA #$0A                ;  |
			BRA STORE_03            ;  |
SUB_OFF_SCREEN_X6:	LDA #$0C                ;  |
			BRA STORE_03            ;  |
SUB_OFF_SCREEN_X7:	LDA #$0E                ;  |
STORE_03:		STA $03			;  |            
			BRA START_SUB		;  |
SUB_OFF_SCREEN_X0:	STZ $03			; /

START_SUB:		JSR SUB_IS_OFF_SCREEN   ; \ if sprite is not off screen, return
			BEQ RETURN_35           ; /
			LDA $5B                 ; \  goto VERTICAL_LEVEL if vertical level
			AND #$01                ; |
			BNE VERTICAL_LEVEL      ; /     
			LDA $D8,x               ; \
			CLC			; | 
			ADC #$50                ; | if the sprite has gone off the bottom of the level...
			LDA $14D4,x             ; | (if adding 0x50 to the sprite y position would make the high byte >= 2)
			ADC #$00                ; | 
			CMP #$02                ; | 
			BPL ERASE_SPRITE        ; /    ...erase the sprite
			LDA $167A,x             ; \ if "process offscreen" flag is set, return
			AND #$04                ; |
			BNE RETURN_35           ; /
			LDA $13                 ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0756 VC:176 00 FL:205
			AND #$01                ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0780 VC:176 00 FL:205
			ORA $03                 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0796 VC:176 00 FL:205
			STA $01                 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0820 VC:176 00 FL:205
			TAY			;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0844 VC:176 00 FL:205
			LDA $1A                 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0858 VC:176 00 FL:205
			CLC			;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0882 VC:176 00 FL:205
			ADC SPR_T14,y           ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0896 VC:176 00 FL:205
			ROL $00                 ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizcHC:0928 VC:176 00 FL:205
			CMP $E4,x               ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:0966 VC:176 00 FL:205
			PHP			;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:0996 VC:176 00 FL:205
			LDA $1B                 ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdizCHC:1018 VC:176 00 FL:205
			LSR $00                 ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdiZCHC:1042 VC:176 00 FL:205
			ADC SPR_T15,y           ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdizcHC:1080 VC:176 00 FL:205
			PLP			;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F0 P:eNvMXdizcHC:1112 VC:176 00 FL:205
			SBC $14E0,x             ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1140 VC:176 00 FL:205
			STA $00                 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:1172 VC:176 00 FL:205
			LSR $01                 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:1196 VC:176 00 FL:205
			BCC SPR_L31             ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZCHC:1234 VC:176 00 FL:205
			EOR #$80                ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZCHC:1250 VC:176 00 FL:205
			STA $00                 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1266 VC:176 00 FL:205
SPR_L31:		LDA $00                 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1290 VC:176 00 FL:205
			BPL RETURN_35           ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1314 VC:176 00 FL:205
ERASE_SPRITE:		LDA $14C8,x             ; \ if sprite status < 8, permanently erase sprite
			CMP #$08                ; |
			BCC KILL_SPRITE         ; /    
			LDY $161A,x             ;A:FF08 X:0007 Y:0001 D:0000 DB:01 S:01F3 P:envMXdiZCHC:1108 VC:059 00 FL:2878
			CPY #$FF                ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdiZCHC:1140 VC:059 00 FL:2878
			BEQ KILL_SPRITE         ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdizcHC:1156 VC:059 00 FL:2878
			LDA #$00                ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdizcHC:1172 VC:059 00 FL:2878
			STA $1938,y             ;A:FF00 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdiZcHC:1188 VC:059 00 FL:2878
KILL_SPRITE:		STZ $14C8,x             ; erase sprite
RETURN_35:		RTS			 ; return

VERTICAL_LEVEL:		LDA $167A,x             ; \ if "process offscreen" flag is set, return
			AND #$04                ; |
			BNE RETURN_35           ; /
			LDA $13                 ; \
			LSR A                   ; | 
			BCS RETURN_35           ; /
			LDA $E4,x               ; \ 
			CMP #$00                ;  | if the sprite has gone off the side of the level...
			LDA $14E0,x             ;  |
			SBC #$00                ;  |
			CMP #$02                ;  |
			BCS ERASE_SPRITE        ; /  ...erase the sprite
			LDA $13                 ;A:0000 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:1218 VC:250 00 FL:5379
			LSR A                   ;A:0016 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1242 VC:250 00 FL:5379
			AND #$01                ;A:000B X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1256 VC:250 00 FL:5379
			STA $01                 ;A:0001 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1272 VC:250 00 FL:5379
			TAY			;A:0001 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1296 VC:250 00 FL:5379
			LDA $1C                 ;A:001A X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0052 VC:251 00 FL:5379
			CLC			;A:00BD X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0076 VC:251 00 FL:5379
			ADC SPR_T12,y           ;A:00BD X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0090 VC:251 00 FL:5379
			ROL $00                 ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:enVMXdizCHC:0122 VC:251 00 FL:5379
			CMP $D8,x               ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0160 VC:251 00 FL:5379
			PHP			;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0190 VC:251 00 FL:5379
			LDA $001D               ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F2 P:eNVMXdizcHC:0212 VC:251 00 FL:5379
			LSR $00                 ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:enVMXdiZcHC:0244 VC:251 00 FL:5379
			ADC SPR_T13,y           ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:enVMXdizCHC:0282 VC:251 00 FL:5379
			PLP			;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:envMXdiZCHC:0314 VC:251 00 FL:5379
			SBC $14D4,x             ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0342 VC:251 00 FL:5379
			STA $00                 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0374 VC:251 00 FL:5379
			LDY $01                 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0398 VC:251 00 FL:5379
			BEQ SPR_L38             ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0422 VC:251 00 FL:5379
			EOR #$80                ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0438 VC:251 00 FL:5379
			STA $00                 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0454 VC:251 00 FL:5379
SPR_L38:		LDA $00                 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0478 VC:251 00 FL:5379
			BMI ERASE_SPRITE        ;A:8AFF X:0002 Y:0000 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0704 VC:184 00 FL:5490
RTS

SUB_IS_OFF_SCREEN:	LDA $15A0,x             ; \ if sprite is on screen, accumulator = 0 
			ORA $186C,x             ; |  
			RTS			; / return