;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Lightning Bolt/Brightness Reset Switch, by imamelia
;;
;; This will either be a lightning bolt that follows the player through the sublevel
;; or a switch that resets the screen brightness to normal depending on the extra
;; bit.
;;
;; Uses first extra bit: YES
;;
;; If the extra bit is clear, the sprite will be a lightning bolt.
;; If the extra bit is set, the sprite will be a brightness reset switch.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

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

!SwitchTile = $88
SwitchYOffset:
db $00,$FC,$F9,$F8,$F8,$F9,$FC,$00,$00

LightningTiles:
db $06,$08,$0A,$0C,$0E,$6B,$6D,$64

!LightningPalette = $3D

LightningTilemap1:
db $00,$05,$06,$04,$02,$04
LightningXOffsets1:
db $00,$F8,$08,$F8,$08,$08
LightningYOffsets1:
db $00,$10,$10,$20,$20,$30

LightningTilemap2:
db $00,$01,$00,$05,$06,$02,$00,$07,$03,$05,$06,$01
db $01,$00,$03,$03,$01,$00,$04,$00,$01,$01,$04,$04
LightningXOffsets2:
db $00,$00,$00,$F8,$08,$F8,$08,$F4,$08,$E8,$F8,$09
db $E8,$F8,$0A,$E8,$F8,$0B,$E8,$F8,$0B,$F8,$0B,$F8
LightningYOffsets2:
db $00,$10,$20,$30,$30,$40,$40,$50,$50,$60,$60,$60
db $70,$70,$70,$80,$80,$80,$90,$90,$90,$A0,$A0,$B0
LightningXOffsets2H:
db $00,$00,$00,$FF,$00,$FF,$00,$FF,$00,$FF,$FF,$00
db $FF,$FF,$00,$FF,$FF,$00,$FF,$FF,$00,$FF,$00,$FF

!SFX1 = $251DFC
!SFX2 = $181DFC

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

print "INIT ",pc
LDA #$04
STA $C2,x
LDA #$FF
STA $1602,x
RTL

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

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

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

LightBrightMain:

LDA $7FAB10,x
AND #$04
BEQ LightningBoltMain
JMP BrightnessSwitchMain

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; main routine for the lightning bolt
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

LightningBoltMain:


LDA $1602,x
BMI .SkipGFX
JSR LightningBoltGFX
.SkipGFX

LDA $14C8,x
CMP #$08
BNE .Return
LDA $9D
BNE .Return

LDA $C2,x			;
JSL $8086DF			;

dw S00_WaitToFlash1	;
dw S01_SmallFlash		;
dw S02_WaitToFlash2	;
dw S03_LargeFlash		;
dw S04_WaitToActivate	;

.Return
RTS

;------------------------------------------------
; state 00 - waiting for the small flash
;------------------------------------------------

S00_WaitToFlash1:

JSR SetPosition			; the sprite's position is always relative to the screen boundary

LDA $1540,x			; if the timer has run out...
BNE .Return			;

INC $C2,x			; increment the sprite state
JSL $81ACF9			; get a random number
ADC $01E0			; make it a little more random
ADC $47				;
ADC $7B				;
STA $1528,x			; set the new X position of the sprite
LDA.b #!SFX1>>16		;
STA.w !SFX2&$FFFF		; play a sound effect
LDA #$08			;
STA $1540,x			; set the time to show the small bolt
STZ $1602,x			; set the animation frame to 0 (for the small bolt)
JSR SetPosition			;

.Return				;
RTS					;

;------------------------------------------------
; state 01 - small flash (near the top of the screen)
;------------------------------------------------

S01_SmallFlash:

JSR SetPosition			; the sprite's position is always relative to the screen boundary

LDA $1540,x			; if the timer has run out...
BNE .Return			;

INC $C2,x			; increment the sprite state
LDA #$30			;
STA $1540,x			; set the time to wait for the large flash
LDA #$FF				;
STA $1602,x			; prevent the graphics from being shown

.Return				;
RTS					;

;------------------------------------------------
; state 02 - waiting for the large flash
;------------------------------------------------

S02_WaitToFlash2:

JSR SetYPosition		; the sprite's Y position is always relative to the screen boundary

LDA $1540,x			; if the timer has run out...
BNE .Return			;

INC $C2,x			; increment the sprite state
LDA.b #!SFX2>>16		;
STA.w !SFX2&$FFFF		; play a sound effect
LDA #$08			;
STA $1540,x			; set the time to show the large bolt
LDA $7FC0F8			;
ORA #$03			; activate One Shot ExAnimation triggers 0 and 1
STA $7FC0F8			;
LDA #$01			;
STA $1602,x			; set the animation frame to 1 (for the large bolt)

.Return				;
RTS					;

;------------------------------------------------
; state 03 - large flash (almost all the way to the bottom of the screen)
;------------------------------------------------

S03_LargeFlash:

JSR SetYPosition		; the sprite's Y position is always relative to the screen boundary

JSR LargeBoltInteraction	; make the large lightning bolt interact with the player

LDA $1540,x			; if the timer has run out...
BNE .Return			;

STZ $C2,x			; reset the sprite state
JSL $81ACF9			; get a random number
ADC $01E0			; make it a little more random
ADC $47				;
ADC $7B				;
AND #$7F			;
ADC #$40			;
STA $1540,x			;
LDA #$FF				;
STA $1602,x			; prevent the graphics from being shown

.Return				;
RTS					;

;------------------------------------------------
; state 04 - waiting until the player reaches a certain screen
;------------------------------------------------

S04_WaitToActivate:

JSR SetPosition			; the sprite's position is always relative to the screen boundary

LDA $95				;
CMP #$02			;
BNE .Return			;
STZ $C2,x			;
LDA #$40			;
STA $1540,x			;

.Return				;
RTS					;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; graphics routine for the lightning bolt
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

LightningBoltGFX:

JSR GetDrawInfo		;

LDA $1602,x			;
BEQ DrawSmallBolt		;
JMP DrawLargeBolt		;

DrawSmallBolt:

LDX #$05					;
.Loop					;

LDA $00					;
CLC						;
ADC.w LightningXOffsets1,x	;
STA $0300,y				;

LDA $01					;
CLC						;
ADC.w LightningYOffsets1,x	;
STA $0301,y				;

LDA.w LightningTilemap1,x	;
PHX						;
TAX						;
LDA.w LightningTiles,x		;
PLX						;
STA $0302,y				;

LDA #!LightningPalette		;
STA $0303,y				;

INY #4					;
DEX						;
BPL .Loop					;

LDX $15E9				;
LDY #$02					;
LDA #$05				;
JSL $81B7B3				;

RTS						;

DrawLargeBolt:

LDX #$17					;
.Loop					;

LDA #$02				;
STA $02					;
LDA $00					;
CLC						;
ADC.w LightningXOffsets2,x	;
STA $0300,y				;
LDA #$00				;
ADC.w LightningXOffsets2H,x;
BEQ .NotOffscreen			;
LDA #$01				;
TSB $02					;
.NotOffscreen				;

LDA $01					;
CLC						;
ADC.w LightningYOffsets2,x	;
STA $0301,y				;

LDA.w LightningTilemap2,x	;
PHX						;
TAX						;
LDA.w LightningTiles,x		;
PLX						;
STA $0302,y				;

LDA #!LightningPalette		;
STA $0303,y				;

PHY						;
TYA						;
LSR #2					;
TAY						;
LDA $02					;
STA $0460,y				;
PLY						;

INY #4					;
DEX						;
BPL .Loop					;

LDX $15E9				;
RTS						;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; screen position-setting routine (for the lightning bolt)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SetPosition:

LDA $1528,x			; the sprite's position is always relative to the screen boundaries
REP #$20				;
AND #$00FF			;
CLC					; $1528,x = X position
ADC $1A				;
SEP #$20				;
STA $E4,x			;
XBA					;
STA $14E0,x			;

SetYPosition:			;

LDA $1C				;
STA $D8,x			;
LDA $1D				;
STA $14D4,x			;

RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; player interaction routine (for the large form of the lightning bolt)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ClippingXDisp:
dw $0003,$000B,$FFFE,$FFEE,$FFF8
ClippingYDisp:
dw $0000,$0020,$0020,$0048,$0030
ClippingWidth:
dw $000A,$000B,$000B,$000B,$0009
ClippingHeight:
dw $0020,$0080,$0090,$0038,$0018

LargeBoltInteraction:

REP #$20				;
LDY #$08				;
.Loop				;
LDA ClippingXDisp,y	;
STA $08				;
LDA ClippingYDisp,y	;
STA $0A				;
LDA ClippingWidth,y	;
STA $0C				;
LDA ClippingHeight,y	;
STA $0E				;

JSR GetPlayerClipping2	;
JSR GetSpriteClippingA2	;
JSR CheckForContact2	;
BCC .NoContact		;
SEP #$20				;
PHY					;
JSL $80F5B7			;
PLY					;
.NoContact			;
REP #$20				;
DEY #2				;
BPL .Loop				;

SEP #$20				;
RTS					;

GetPlayerClipping2:		; modified player clipping routine, based off and equivalent to $03B664

PHX					;
REP #$20				;
LDA $94				;
CLC					;
ADC #$0002			;
STA $00				; $00-$01 = player X position plus X displacement
LDA #$000C			;
STA $04				; $04-$05 = player clipping width
SEP #$20				;
LDX #$00				;
LDA $73				;
BNE .Inc1				;
LDA $19				;
BNE .Next1			;
.Inc1				;
INX					;
.Next1				;
LDA $187A			;
BEQ .Next2			;
INX #2				;
.Next2				;
LDA $83B660,x		;
STA $06				; $06-$07 = player clipping height
STZ $07				;
LDA $83B65C,x		;
REP #$20				;
AND #$00FF			;
CLC					;
ADC $96				;
STA $02				; $02-$03 = player Y position plus Y displacement
SEP #$20				;
PLX					;
RTS					;

GetSpriteClippingA2:	; custom sprite clipping routine, equivalent to $03B69F

LDA $14E0,x			;
XBA					;
LDA $E4,x			;
REP #$20				;
CLC					;
ADC $08				;
STA $08				; $08-$09 = sprite X position plus X displacement
;LDA $0C				;
;STA $0C				; $0C-$0D = sprite clipping width
SEP #$20				;
LDA $14D4,x			;
XBA					;
LDA $D8,x			;
REP #$20				;
CLC					;
ADC $0A				;
STA $0A				; $0A-$0B = sprite Y position plus Y displacement
;LDA $0E				;
;STA $0E				; $0E-$0F = sprite clipping height
SEP #$20				;
RTS					;

CheckForContact2:		; custom contact check routine, equivalent to $03B72B

REP #$20				;

.CheckX				;
LDA $00				; if the sprite's clipping field is to the right of the player's,
CMP $08				; subtract the former from the latter;
BCC .CheckXSub2		; if the player's clipping field is to the right of the sprite's,
.CheckXSub1			; subtract the latter from the former
SEC					;
SBC $08				;
CMP $0C				;
BCS .ReturnNoContact	;
BRA .CheckY			;
.CheckXSub2			;
LDA $08				;
SEC					;
SBC $00				;
CMP $04				;
BCS .ReturnNoContact	;

.CheckY				;
LDA $02				; if the sprite's clipping field is below the player's,
CMP $0A				; subtract the former from the latter;
BCC .CheckYSub2		; if the player's clipping field is above the sprite's,
.CheckYSub1			; subtract the latter from the former
SEC					;
SBC $0A				;
CMP $0E				;
BCS .ReturnNoContact	;
.ReturnContact		;
SEC					;
SEP #$20				;
RTS					;
.CheckYSub2			;
LDA $0A				;
SEC					;
SBC $02				;
CMP $06				;
BCC .ReturnContact		;
.ReturnNoContact		;
CLC					;
SEP #$20				;
RTS					;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; main routine for the brightness switch
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BrightnessSwitchMain:

JSR BrightnessSwitchGFX

LDA $14C8,x
CMP #$08
BNE .Return
LDA $9D
BNE .Return

JSR SubOffscreenX0

LDA $C2,x			;
JSL $8086DF			;

dw S00_Stationary		;
dw S01_JustHit		;
dw S02_Moving		;

.Return
RTS

S00_Stationary:
JSL $81B44F			;
RTS					;

S01_JustHit:
LDA #$0B				;
STA $1DF9			;
LDA #$0F				;
STA $0DAE			;
INC $1558,x			;
INC $C2,x			;
RTS					;

S02_Moving:
LDA $1558,x			;
LSR					;
TAY					;
LDA SwitchYOffset,y	;
STA $160E,x			;
LDA $1558,x			;
CMP #$01			;
BNE .End				;
STZ $C2,x			;
.End					;
RTS					;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; graphics routine for the brightness switch
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BrightnessSwitchGFX:

JSR GetDrawInfo

LDA $00				;
STA $0300,y			;

LDA $01				;
CLC					;
ADC $160E,x			;
STA $0301,y			;

LDA #!SwitchTile		;
STA $0302,y			;

LDA $15F6,x			;
ORA $64				;
STA $0303,y			;

LDX $15E9			;
LDY #$02				;
LDA #$00			;
JSL $81B7B3			;
.Return				
RTS					;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; miscellaneous standard 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

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



