;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Timer, by imamelia
;;
;; Extra bytes: 4
;;
;; Extra byte 1:
;;	For the clock-style timer:
;;	- Bits 0-4: High byte of the number of time units the timer will start out with.
;;	- Bits 5-6: What will happen when the timer reaches a critical value.
;;		00 = nothing, 01 = kill the player, 10 = teleport to the screen exit of screen 00,
;;		11 = custom routine set by !TSubPtr
;;	- Bit 7: Which type of timer it is.  0 = clock-style (xx:xx:xx), 1 = three-digit (xxx).
;;	For the 3-digit timer:
;;	- Bits 0-1: High byte of the number of time units the timer will start out with.
;;	- Bits 2-3: Size of the numbers.  (Options: 8x8, 8x16, 16x16, 16x32.)
;;	- Bit 4: Unused.
;;	- Bits 5-6: What will happen when the timer reaches a critical value.
;;		00 = nothing, 01 = kill the player, 10 = teleport to the screen exit of screen 00,
;;		11 = custom routine set by !TSubPtr
;;	- Bit 7: Which type of timer it is.  0 = clock-style (xx:xx:xx), 1 = three-digit (xxx).
;; Extra byte 2:
;;	- Bits 0-7: Low byte of the number of time units the timer will start out with.
;; Extra byte 3:
;;	For the clock-style timer:
;;	- Bits 0-4: High byte of the initial critical time value.
;;	- Bit 5: Disable the frames from being shown.
;;	- Bit 6: Initialize the timer to the specified value.  0 = yes, 1 = no.  (This is so
;;		it can keep the same values between sublevels.)
;;	- Bit 7: Counting direction.  0 = down, 1 = up.
;;	For the 3-digit timer:
;;	- Bits 0-1: High byte of the initial critical time value.
;;	- Bits 2-5: Unused.
;;	- Bit 6: Initialize the timer to the specified value.  0 = yes, 1 = no.  (This is so
;;		it can keep the same values between sublevels.)
;;	- Bit 7: Counting direction.  0 = down, 1 = up.
;; Extra byte 4:
;;	- Bits 0-7: Low byte of the initial critical time value.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;incsrc subroutinedefs.asm

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

!HexToDec2 = HexDecLoop	;hex conversion routine

!RAM_TCurrentTime = $7FA230	; how many units of time are currently on the timer (16-bit)
!RAM_TSubPtr = $7FA232		; pointer to critical value subroutine (24-bit)
!RAM_TCriticalTime = $7FA235	; when the time units reach this value, a subroutine will be activated
!RAM_TFlags = $7FA237			; various flags for the timer
;	bit 0 - frozen (will not increment or decrement)
;	bit 1 - a subroutine has already been activated (and will not be again)
;	bits 2-3 - tile size for the 3-digit timer
;	bit 4 - timer type (0 = clock, 1 = 3-digit)
;	bit 5 - disable the frames from being shown
;	bit 6 - unused
;	bit 7 - counting direction
!RAM_TPositionX = $7FA238		; X position at which the timer will show up on the screen
!RAM_TPositionY = $7FA239		; Y position at which the timer will show up on the screen
!RAM_TPalette = $7FA23A		; palette of the timer tiles (low byte) and clock if there is one (high byte)
!RAM_TFrameCtr = $7FA23B		; frame counter (when this reaches the specified value, it resets and the timer ticks)
!RAM_TFrameReset = $7FA23C	; how many frames will pass before the timer ticks one more unit
!DefaultFrameVal = $3C			; how many frames, by default, are in one unit of time
!LEVEL = $00C0		;level dest
!PROPERTIES = $00	;See 7E:19B8 RAM map, minus the high bit
;
; This is the format for a custom subroutine.  It is commented out, obviously,
; because it is not necessary to have it taking up extra space in the patch.
;
; LDA.b #DoStuff/$10000
; STA !RAM_CustPtr+2
; LDA.b #DoStuff/$100
; STA !RAM_CustPtr+1
; LDA.b #DoStuff
; STA !RAM_CustPtr
;
; DoStuff:
; LDA #$13
; STA $9C
; JSL $00BEB0
; RTL

; clock-style timer
!TileXPosition1 = $B0		; the X position of the numbers on the screen
!TileYPosition1 = $20		; the Y position of the numbers on the screen
!TilePalette1 = $3A			; palette of the numbers (low nybble) and clock (high nybble)
Tilemap1:				; tile numbers of the numerals 0-9 (the last two are the colon and clock)
db $76,$77,$46,$47,$C2,$C3,$D2,$D3,$D4,$D5,$4D,$67
TileProps1:				; tile properties of all 9 tiles in order (for the clock tiles)
db $31,$31,$31,$31,$31,$31,$31,$31,$31
TileXOffsets1:				; X offsets of all 9 tiles in order relative to the first tile
db $00,$08,$10,$17,$1F,$27,$2E,$36,$3E

; 3-digit timer
TileXPosition2:
db $73,$73,$66,$66
TileYPosition2:
db $28,$28,$28,$28
TilePalette2:
db $0B,$07,$09,$05
TileSpacing:
db $09,$09,$11,$11
Tilemap8x8:
db $30,$31,$32,$33,$34,$35,$36,$37,$38,$39
Tilemap8x16:
db $40,$41,$42,$43,$44,$45,$46,$47,$48,$49
db $50,$51,$52,$53,$54,$55,$56,$57,$58,$59
Tilemap16x16:
db $C4,$C6,$C8,$CA,$CC,$CE,$E4,$E6,$E8,$EA
Tilemap16x32:
db $80,$82,$84,$86,$88,$8A,$8C,$8E,$C0,$C2
db $A0,$A2,$A4,$A6,$A8,$AA,$AC,$AE,$E0,$E2
TileFlip8x16:
db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
TileFlip16x32:
db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00

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

EndInit2:					;
RTL						;

print "INIT ",pc

Init:

	LDA #$60
	STA $7FAB40,x	;byte 1
	LDA $7F9A84	;RAM of initial time
	STA $7FAB4C,x	;...
	LDA #$00
	STA $7FAB58,x	;...
	LDA #$32
	STA $7FAB64,x	;byte 4 - critical time value.
			;$46 = 1:10:00 - first place threshold for coingrab.
			;$5A = 1:30:00 - second place threshold for coingrab.
			;$78 = 2:00:00 - third place threshold for coingrab.

	REP #$20
	LDA $010B
	CMP #$00BD
	BNE NoSetPointer
	SEP #$20

	LDA.b #CritTimeA/$10000
	STA !RAM_TSubPtr+2

	LDA.b #CritTimeA/$100
	STA !RAM_TSubPtr+1

	LDA.b #CritTimeA
	STA !RAM_TSubPtr
	BRA PointerSet
NoSetPointer:
	SEP #$20
	LDA.b #CritTimeC/$10000
	STA !RAM_TSubPtr+2

	LDA.b #CritTimeC/$100
	STA !RAM_TSubPtr+1

	LDA.b #CritTimeC
	STA !RAM_TSubPtr
	LDA #$00
	STA $7FAB64,x
PointerSet:

LDA $7FAB58,x			;
STA $00					;
AND #$40				;
BNE EndInit2				;

LDA #!DefaultFrameVal		;
STA !RAM_TFrameReset		;
LDA #$80				;
STA !RAM_TFlags			;
STA !RAM_TFrameCtr		;

LDA $00					;
AND #$80				;
STA $01					;
LDA !RAM_TFlags			;
AND #$7F				;
ORA $01					;
STA !RAM_TFlags			;
LDA $7FAB4C,x			;
STA !RAM_TCurrentTime		;
LDA $7FAB64,x			;
STA !RAM_TCriticalTime		;

LDA $7FAB40,x			;
PHA						;
AND #$60				;
LSR #5					;
STA $02					;
BEQ .NoSub				;
CMP #$03				;
BEQ .SkipNoSub			;
CMP #$02				;
BEQ .SetPtr2				;
LDA #$06				;
STA !RAM_TSubPtr			;
LDA #$F6					;
STA !RAM_TSubPtr+1		;
LDA #$80				;
STA !RAM_TSubPtr+2		;
BRA .SkipNoSub			;
.SetPtr2					;
LDA.b #Teleport00			;
STA !RAM_TSubPtr			;
LDA.b #Teleport00/$100	;
STA !RAM_TSubPtr+1		;
LDA.b #Teleport00/$10000	;
STA !RAM_TSubPtr+2		;
BRA .SkipNoSub			;
.NoSub					;
LDA !RAM_TFlags			;
ORA #$02				;
STA !RAM_TFlags			;
.SkipNoSub				;					;
PLA						;
BMI .InitTimer2			;
AND #$1F				;
STA !RAM_TCurrentTime+1	;

LDA !RAM_TFlags			;
AND #$E3				; clear bits 2, 3, and 4
STA !RAM_TFlags			;

LDA $00					;
AND #$1F				;
STA !RAM_TCriticalTime+1	;
LDA $00					;
AND #$20				;
STA $01					;
LDA !RAM_TFlags			;
AND #$DF				;
ORA $01					;
STA !RAM_TFlags			;

LDA #!TileXPosition1		;
STA !RAM_TPositionX		;
LDA #!TileYPosition1		;
STA !RAM_TPositionY		;
LDA #!TilePalette1			;
STA !RAM_TPalette			;

BRA .EndInit				;

.InitTimer2				;
PHA						;
AND #$03				;
STA !RAM_TCurrentTime+1	;
PLA						;
AND #$0C				;
STA $02					;
ORA #$10				;
STA $01					;
LDA !RAM_TFlags			;
AND #$E3				;
ORA $01					;
STA !RAM_TFlags			;

LDA $00					;
AND #$03				;
STA !RAM_TCriticalTime+1	;

LDA $02					;
LSR #2					;
TAY						;
LDA TileXPosition2,y		;
STA !RAM_TPositionX		;
LDA TileYPosition2,y		;
STA !RAM_TPositionY		;
LDA TilePalette2,y			;
STA !RAM_TPalette			;

.EndInit					;
RTL						;

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

print "MAIN ",pc

Main:
PHB
PHK
PLB
JSR TimerMainRt
PLB
RTL

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

TimerMainRt:

JSR TimerGFX

LDA $1A
CLC
ADC #$80
STA $E4,x
LDA $1B
ADC #$00
STA $14E0,x
LDA $1C
CLC
ADC #$40
STA $D8,x
LDA $1D
ADC #$00
STA $14D4,x

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

JSR UpdateTimer

.Return
RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; draw the timer
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

TimerGFX:

JSR GET_DRAW_INFO			;

LDA !RAM_TFlags			;
AND #$10				;
BEQ TimerGFXClock			;

LDA !RAM_TFlags			;
LSR #2					;
AND #$03				;
JSL $8086DF				;

dw TimerGFX8x8			; 00 - 3-digit timer, 8x8 tiles
dw TimerGFX8x16			; 01 - 3-digit timer, 8x16 tiles
dw TimerGFX16x16			; 02 - 3-digit timer, 16x16 tiles
dw TimerGFX16x32			; 03 - 3-digit timer, 16x32 tiles

;------------------------------------------------
; GFX routine for the clock-style timer
;------------------------------------------------

TimerGFXClock:

PHY						;
REP #$20					;
LDA !RAM_TCurrentTime		; dividend - current time value
STA $4204				;
LDY #$3C				; divided by 60 (decimal)
STY $4206				;
SEP #$20					;
LDA ($42,s),y				; waste cycles
LDA ($42,s),y				;
LDA $4214				; quotient = number of minutes
PHA						;
LDA $4216				; remainder = number of seconds
JSL !HexToDec2			; convert the seconds into decimal
STY $0B					;
STA $0C					;
PLA						;
JSL !HexToDec2			; convert the minutes into decimal
STY $08					;
STA $09					;
LDA !RAM_TFlags			;
BMI .NoInvert				;

LDA !RAM_TCurrentTime	;
CMP !RAM_TCriticalTime
BEQ .NoInvert
LDA #$3B					;
SEC						;
SBC !RAM_TFrameCtr		;
BRA .ConvertFrames		;
.NoInvert					;
LDA !RAM_TFrameCtr		;
.ConvertFrames			;
JSL !HexToDec2			; convert the frames into decimal
STY $0E					;
STA $0F					;
LDY #$09					; if the frames are supposed to be shown,
LDA !RAM_TFlags			; draw 10 tiles
AND #$20				;
BEQ $02					; else,
LDY #$07					; draw 8 tiles
STY $06					;
PLY						;

LDA #$0B					;
STA $07					;
LDA #$0A				;
STA $0A					;
STA $0D					;

STZ $05					;
LDX #$00					;

.Loop					;

LDA $07,x				;
BNE .StoreTile				;
CPX #$01					; if the tens digit of the minutes is 0, skip it
BEQ .SkipTile				;
.StoreTile					;
PHX						;
TAX						;
LDA.w Tilemap1,x			;
PLX						;
STA $0302,y				;

LDA !RAM_TPalette			;
;CPX #$00					; if we're drawing the clock tile...
;BNE $04					;
;LSR #4					; then use the upper nybble of the palette RAM
;AND #$0F				;
;ORA #$30				;
STA $0303,y				;

LDA !RAM_TPositionX		;
CLC						;
ADC.w TileXOffsets1,x		;
STA $0300,y				;

LDA !RAM_TPositionY		;
STA $0301,y				;

INC $05					;
INY #4					;
.SkipTile					;
INX						;
CPX $06					;
BCC .Loop				;

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

;------------------------------------------------
; GFX routine for the 3-digit 8x8 timer
;------------------------------------------------

TimerGFX8x8:

LDA !RAM_TPositionX		;
STA $0300,y				;
CLC						;
ADC.w TileSpacing			;
STA $0304,y				;
CLC						;
ADC.w TileSpacing			;
STA $0308,y				;

LDA !RAM_TPositionY		;
STA $0301,y				;
STA $0305,y				;
STA $0309,y				;

PHY						;
REP #$20					;
LDA !RAM_TCurrentTime		;
STA $4204				;
LDY #$64					; divide by 100 (decimal)
STY $4206				;
SEP #$20					;
LDA ($42,s),y				; waste cycles
LDA ($42,s),y				;
LDA $4214				;
STA $00					;
LDA $4216				;
JSL !HexToDec2			;
STY $01					;
STA $02					;
PLY						;

LDX $00					;
LDA.w Tilemap8x8,x		;
STA $0302,y				;
LDX $01					;
LDA.w Tilemap8x8,x		;
STA $0306,y				;
LDX $02					;
LDA.w Tilemap8x8,x		;
STA $030A,y				;

LDA !RAM_TPalette			;
AND #$0F				;
ORA #$30				;
STA $0303,y				;
STA $0307,y				;
STA $030B,y				;

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

;------------------------------------------------
; GFX routine for the 3-digit 8x16 timer
;------------------------------------------------

TimerGFX8x16:

LDA !RAM_TPositionX		;
STA $0300,y				;
STA $030C,y				;
CLC						;
ADC.w TileSpacing+1		;
STA $0304,y				;
STA $0310,y				;
CLC						;
ADC.w TileSpacing+1		;
STA $0308,y				;
STA $0314,y				;

LDA !RAM_TPositionY		;
STA $0301,y				;
STA $0305,y				;
STA $0309,y				;
CLC						;
ADC #$08				;
STA $030D,y				;
STA $0311,y				;
STA $0315,y				;

PHY						;
REP #$20					;
LDA !RAM_TCurrentTime		;
STA $4204				;
LDY #$64					; divide by 100 (decimal)
STY $4206				;
SEP #$20					;
LDA ($42,s),y				; waste cycles
LDA ($42,s),y				;
LDA $4214				;
STA $00					;
LDA $4216				;
JSL !HexToDec2			;
STY $01					;
STA $02					;
PLY						;

LDA !RAM_TPalette			;
AND #$0F				;
ORA #$30				;
STA $03					;

STA $0303,y				;
STA $0307,y				;
STA $030B,y				;
STA $030F,y				;
STA $0313,y				;
STA $0317,y				;

LDX $00					;
LDA.w Tilemap8x16,x		;
STA $0302,y				;
LDA $03					;
ORA.w TileFlip8x16,x		;
STA $0303,y				;
LDA.w Tilemap8x16+$0A,x	;
STA $030E,y				;
LDA $03					;
ORA.w TileFlip8x16+$0A,x	;
STA $0303,y				;

LDX $01					;
LDA.w Tilemap8x16,x		;
STA $0306,y				;
LDA $03					;
ORA.w TileFlip8x16,x		;
STA $0307,y				;
LDA.w Tilemap8x16+$0A,x	;
STA $0312,y				;
LDA $03					;
ORA.w TileFlip8x16+$0A,x	;
STA $0313,y				;

LDX $02					;
LDA.w Tilemap8x16,x		;
STA $030A,y				;
LDA $03					;
ORA.w TileFlip8x16,x		;
STA $030B,y				;
LDA.w Tilemap8x16+$0A,x	;
STA $0316,y				;
LDA $03					;
ORA.w TileFlip8x16+$0A,x	;
STA $0317,y				;

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

;------------------------------------------------
; GFX routine for the 3-digit 16x16 timer
;------------------------------------------------

TimerGFX16x16:

LDA !RAM_TPositionX		;
STA $0300,y				;
CLC						;
ADC.w TileSpacing+2		;
STA $0304,y				;
CLC						;
ADC.w TileSpacing+2		;
STA $0308,y				;

LDA !RAM_TPositionY		;
STA $0301,y				;
STA $0305,y				;
STA $0309,y				;

PHY						;
REP #$20					;
LDA !RAM_TCurrentTime		;
STA $4204				;
LDY #$64					; divide by 100 (decimal)
STY $4206				;
SEP #$20					;
LDA ($42,s),y				; waste cycles
LDA ($42,s),y				;
LDA $4214				;
STA $00					;
LDA $4216				;
JSL !HexToDec2			;
STY $01					;
STA $02					;
PLY						;

LDX $00					;
LDA.w Tilemap16x16,x		;
STA $0302,y				;
LDX $01					;
LDA.w Tilemap16x16,x		;
STA $0306,y				;
LDX $02					;
LDA.w Tilemap16x16,x		;
STA $030A,y				;

LDA !RAM_TPalette			;
AND #$0F				;
ORA #$30				;
STA $0303,y				;
STA $0307,y				;
STA $030B,y				;

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

;------------------------------------------------
; GFX routine for the 3-digit 16x32 timer
;------------------------------------------------

TimerGFX16x32:

LDA !RAM_TPositionX		;
STA $0300,y				;
STA $030C,y				;
CLC						;
ADC.w TileSpacing+3		;
STA $0304,y				;
STA $0310,y				;
CLC						;
ADC.w TileSpacing+3		;
STA $0308,y				;
STA $0314,y				;

LDA !RAM_TPositionY		;
STA $0301,y				;
STA $0305,y				;
STA $0309,y				;
CLC						;
ADC #$10				;
STA $030D,y				;
STA $0311,y				;
STA $0315,y				;

PHY						;
REP #$20					;
LDA !RAM_TCurrentTime		;
STA $4204				;
LDY #$64					; divide by 100 (decimal)
STY $4206				;
SEP #$20					;
LDA ($42,s),y				; waste cycles
LDA ($42,s),y				;
LDA $4214				;
STA $00					;
LDA $4216				;
JSL !HexToDec2			;
STY $01					;
STA $02					;
PLY						;

LDA !RAM_TPalette			;
AND #$0F				;
ORA #$30				;
STA $03					;

STA $0303,y				;
STA $0307,y				;
STA $030B,y				;
STA $030F,y				;
STA $0313,y				;
STA $0317,y				;

LDX $00					;
LDA.w Tilemap16x32,x		;
STA $0302,y				;
LDA $03					;
ORA.w TileFlip16x32,x		;
STA $0303,y				;
LDA.w Tilemap16x32+$0A,x	;
STA $030E,y				;
LDA $03					;
ORA.w TileFlip16x32+$0A,x	;
STA $0303,y				;

LDX $01					;
LDA.w Tilemap16x32,x		;
STA $0306,y				;
LDA $03					;
ORA.w TileFlip16x32,x		;
STA $0307,y				;
LDA.w Tilemap16x32+$0A,x	;
STA $0312,y				;
LDA $03					;
ORA.w TileFlip16x32+$0A,x	;
STA $0313,y				;

LDX $02					;
LDA.w Tilemap16x32,x		;
STA $030A,y				;
LDA $03					;
ORA.w TileFlip16x32,x		;
STA $030B,y				;
LDA.w Tilemap16x32+$0A,x	;
STA $0316,y				;
LDA $03					;
ORA.w TileFlip16x32+$0A,x	;
STA $0317,y				;

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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; update the timer
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

UpdateTimer:

LDA !RAM_TFlags		;
LSR					;
BCS .Return		; don't do anything if the timer is frozen

LDA !RAM_TFrameCtr	;
INC					; increment the frame counter
STA !RAM_TFrameCtr	;
CMP !RAM_TFrameReset	; if it has reached maximum...
BCC .Return			;
LDA #$00			; reset it
STA !RAM_TFrameCtr	;

LDA !RAM_TFlags		;
BMI .Increment			;
REP #$20				;
LDA !RAM_TCurrentTime	;
BEQ .MaybeStopUpdate	;
DEC					;
STA !RAM_TCurrentTime	;
BRA .Shared			;

.Increment			;
REP #$20				;
LDA !RAM_TCurrentTime	;
CMP #$176F			;
BEQ .MaybeStopUpdate	;
INC					;
STA !RAM_TCurrentTime	;

.Shared				;
CMP !RAM_TCriticalTime	;
SEP #$20				;
BNE .Return			;

JSR ActivateSubroutine	;

.Return				;
RTS					;

.MaybeStopUpdate		;
SEP #$20				;
LDA !RAM_TFrameCtr	;
INC					;
CMP !RAM_TFrameReset	;
BCC .Return			;
LDA !RAM_TFlags		;
ORA #$01			;
STA !RAM_TFlags		;
RTS					;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; activate a subroutine at the critical value
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ActivateSubroutine:

;LDA !RAM_TFlags		;
;AND #$02			;
;BNE .Return			; don't do anything if a subroutine is set not to be activated

JSR RunSubroutine		;

;LDA !RAM_TFlags		;
;ORA #$02			;
;STA !RAM_TFlags		;
.Return				;
RTS					;

RunSubroutine:				;

			;put the good stuff here


LDA !RAM_TSubPtr		;
STA $00				;
LDA !RAM_TSubPtr+1	;
STA $01				;
LDA !RAM_TSubPtr+2	;
STA $02				;
PHK					;
PEA.w .SubRet-1		;
JML [$0000]			;
.SubRet				;
RTS					;

Teleport00:

LDA $5B				;
LSR					;
BCS .Vertical			;
LDY $95				;
BRA .Continue			;
.Vertical				;
LDY $97				;
.Continue				;
LDA $19B8			;
STA $19B8,y			;
LDA $19D8			;
ORA #$04			;
STA $19D8,y			;
LDA #$06			;
STA $71				;
STZ $88				;
STZ $89				;
EndSub:				;
RTL					;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; init and main pointers
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

dl Init,Main



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GET_DRAW_INFO
; This is a helper for the graphics routine.  It sets off screen flags, and sets up
; variables.  It will return with the following:
;
;		Y = index to sprite OAM ($300)
;		$00 = sprite x position relative to screen boarder
;		$01 = sprite y position relative to screen boarder  
;
; It is adapted from the subroutine at $03B760
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SPR_T1:              db $0C,$1C
SPR_T2:             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 SPR_T1,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 SPR_T2,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                     ; /



;==========================================================================
;Hex->Dec Conversion Routine.
;
;A must be loaded with the RAM Address to convert to, and then must be JSL'd
;to HexDecLoop. A will contain the ones, Y will contain the tens, and X will
;contain the hundreds. Note that it won't go beyond FF.
;==========================================================================


HexDecLoop:
	LDX #$00 ; X initially 00..
	LDY #$00 ; .. Y initially 00 ..
LoopY:
	CMP #$64 ; <- If A != 64 ..
	BCC LoopX ; .. check loop X.
	SBC #$64 ; A == 00 ..
	INX	; Y + 1.
	BRA LoopY
LoopX:
	CMP #$0A ; <- If A != 10 ..
	BCC Return
	SBC #$0A ; A - 10.
	INY	; X + 1.
	BRA LoopX
Return:
	RTL

CritTimeA:
	REP #$20	;HELP !!! TOO STUPID TO MAKEING THE FIXING THE PROBLEMING!!!!!!1
	LDA #$001E
	STA !RAM_TCriticalTime

	SEP #$20

	LDA.b #CritTimeB/$10000
	STA !RAM_TSubPtr+2

	LDA.b #CritTimeB/$100
	STA !RAM_TSubPtr+1

	LDA.b #CritTimeB
	STA !RAM_TSubPtr

	LDA #$34
	STA !RAM_TPalette

	LDA #$01
	STA $7F9A82	;points missed in last game
	
	RTL

CritTimeB:

	REP #$20	
	LDA #$0000
	STA !RAM_TCriticalTime
	SEP #$20

	LDA.b #CritTimeC/$10000
	STA !RAM_TSubPtr+2

	LDA.b #CritTimeC/$100
	STA !RAM_TSubPtr+1

	LDA.b #CritTimeC
	STA !RAM_TSubPtr

	LDA #$38
	STA !RAM_TPalette

	LDA #$03
	STA $7F9A82	;points missed in last game

	RTL
CritTimeC:

	LDA #$05
	STA $7F9A82	;points missed in last game
	LDA #$2A
	STA $1DFC
	
	LDA $5B
	BEQ Horz

	LDX $97
	BRA Setup
Horz:
	LDX $95		;mario X pos high

Setup:
	PEA !LEVEL	;push teleport destination
	PLA		;low byte
	STA $19B8,x	;write exit table
	PLA		;high byte
	ORA #$04	;exit present
	ORA #!PROPERTIES	
	STA $19D8,x	;write high bit and properties

Teleport:
	LDA #$06	;teleport
	STA $71
	STZ $89
	STZ $88
	
	RTL



