lorom

; Custom addresses. Most are arbitrary. Feel free to make sure they're okay or moving them elsewhere within ZP
CreditsPtr = $7C   ; 3 bytes
Temp = $B3         ; 2 bytes
StatsBottom = $B5  ; 2 bytes
StatsPtr = $B7     ; 3 bytes
ValueLow = $BA     ; 2 bytes
ValueHigh = $BC    ; 2 bytes
Hours = $72        ; 2 bytes
Minutes = $74      ; 2 bytes
Seconds = $76      ; 2 bytes
RemoveZero = $78   ; 2 bytes

; Original addresses
LineNumber = $CA   ; 2 bytes

PreparePointer:
	LDA.w #$2300
	STA.b CreditsPtr+1
	LDA.w #CreditsLineTable
	STA.b CreditsPtr
	LDA.b [CreditsPtr],Y
	STA.b CreditsPtr
	LDY.w #$0000
RTL

;   Regular stat:   XXXX X00L   LLLL LLLL   BBBB SSSS   CCC- ----	---- ----	AAAA AAAA   AAAA AAAA   AAAA AAAA
;   Time stat:      XXXX X01L   LLLL LLLL   ---- ----	---- ----	---- ----	AAAA AAAA   AAAA AAAA   AAAA AAAA
;   End of data:    1111 1111   1111 1111

;   X   X offset (measured in 8x8 tiles)
;   L   Line number
;   B   Amount of bits to keep after shifting (0000 = 16 bits, 0001 = 1 bit, 1111 = 15 bits)
;   S   Amount of bits to right shift the value by (0000 = 0 bits, 1111 = 15 bits)
;   C   Value cap
;           000 No cap
;           001 9
;           010 99
;           011 999
;           100 9999
;   A   Memory Address

ValueCaps:
	dw 0
	dw 9
	dw 99
	dw 999
	dw 9999
	dw 9999 ; TODO - 5 digits need to be fixed at a later date

BitMasks:
	dw $FFFF
	dw $0001
	dw $0003
	dw $0007
	dw $000F
	dw $001F
	dw $003F
	dw $007F
	dw $00FF
	dw $01FF
	dw $03FF
	dw $07FF
	dw $0FFF
	dw $1FFF
	dw $3FFF
	dw $7FFF

macro StripeStart(xPos, length)
	LDA.b $C8
	CLC
	ADC.w #<xPos>
	XBA
	STA.w $1002,x

	LDA.w #<length>*2-1
	XBA
	LDA.w #$0500
	STA.w $1004,x
endmacro

macro StripeTile()
	STA.w $1006,x
	INX
	INX
endmacro

macro StripeEnd()
	INX
	INX
	INX
	INX
endmacro

HexToDecStats:
	PHA
	PHA
		LDA.w #$0000
		STA.l HexToDecDigit1 : STA.l HexToDecDigit3 : STA.l HexToDecDigit4 ; clear digit storage
	PLA
	-
	CMP.w #10000 : !BLT +
	PHA : SEP #$20 : LDA.l HexToDecDigit1 : INC : STA.l HexToDecDigit1 : REP #$20 : PLA
	!SUB.w #10000 : BRA -
	+ -
	CMP.w #1000 : !BLT +
	PHA : SEP #$20 : LDA.l HexToDecDigit2 : INC : STA.l HexToDecDigit2 : REP #$20 : PLA
	!SUB.w #1000 : BRA -
	+ -
	CMP.w #100 : !BLT +
	PHA : SEP #$20 : LDA.l HexToDecDigit3 : INC : STA.l HexToDecDigit3 : REP #$20 : PLA
	!SUB.w #100 : BRA -
	+ -
	CMP.w #10 : !BLT +
	PHA : SEP #$20 : LDA.l HexToDecDigit4 : INC : STA.l HexToDecDigit4 : REP #$20 : PLA
	!SUB.w #10 : BRA -
	+ -
	CMP.w #1 : !BLT +
	PHA : SEP #$20 : LDA.l HexToDecDigit5 : INC : STA.l HexToDecDigit5 : REP #$20 : PLA
	!SUB.w #1 : BRA -
	+ 
	PLA
RTL

LastHexDigit: 
	TYA
	AND.w #$000F
	PHA
	TYA
	LSR #4
	TAY
	CLC
	LDA.b StatsBottom
	BNE +
	; Upper half
	PLA
	ADC.w #$3D40
	RTS
+	; Lower half
	PLA
	ADC.w #$3D50
	RTS

FindLine:
	LDY.w #$0000

-	LDA.w CreditsStats,y
	STZ.b StatsBottom
	CMP.w #$FFFF
	BEQ .noLine

	XBA
	AND.w #$01FF
	CMP.b LineNumber
	BEQ .lineFound

	INC
	INC.b StatsBottom
	CMP.b LineNumber
	BEQ .lineFound

	INY #8
	BRA -

.lineFound
	SEC
	RTS

.noLine
	CLC
	RTS

!FRAMES_PER_SECOND = 60
!FRAMES_PER_MINUTE = 60*60
!FRAMES_PER_HOUR = 60*60*60
!MAX_FRAME_COUNT = 59*60+59*60+59*60+99

macro CountUnits(framesPerUnit, unitCounter)
	STZ.b <unitCounter>
?loop:
	LDA.b ValueLow
	SEC
	SBC.w #<framesPerUnit>
	STA.b Temp
	LDA.b ValueHigh
	SBC.w #<framesPerUnit>>>16
	BCC ?end
	STA.b ValueHigh
	LDA.b Temp
	STA.b ValueLow
	INC.b <unitCounter>
	BRA ?loop
?end:
endmacro

!ColonOffset = $8A
!PeriodOffset = $4D
BlankCreditsTile = $883D

RenderCreditsStatCounter:
	PHB
	PHK
	PLB

	JSR FindLine
	BCS +
	JMP .endStats
+

	;   XXXX X00L   LLLL LLLL   BBBB SSSS   CCC- ----	---- ----	AAAA AAAA   AAAA AAAA   AAAA AAAA

	; == Determine stat type ==
	LDA.w CreditsStats,y  ;   LLLL LLLL XXXX XTTL
	LSR
	AND.w #$0003          ; TT
	CMP.w #$0000
	BEQ .normalStat
	JMP .timeStat

.normalStat
	; == Write Stripe header (VRAM address, i.e. tile coordinates) ==
	LDA.w CreditsStats,y  ;   LLLL LLLL XXXX XTTL
	LSR #3
	AND.w #$001F          ; X XXXX
	CLC
	ADC.w $C8
	XBA
	STA.w $1002,x

	; == Write Stripe header (Length of data) ==
	LDA.w #4*2-1    ; 4 tiles = 8 bytes
	XBA
	STA.w $1004,x
	PHX

	; == Load tile base (upper or lower half of white two-line zero) ==
	LDA.b StatsBottom
	BNE +
	LDA.w #$3D40
	BRA ++
+	LDA.w #$3D50
++	STA.b Temp

	; == Load the actual stat word ==
	LDA.w CreditsStats+5,y
	STA.b StatsPtr
	LDA.w CreditsStats+6,y
	STA.b StatsPtr+1
	LDA.b [StatsPtr]
	STA.b ValueLow

	; == Shift value ==
	LDA.w CreditsStats+2,y;   CCC- ---- BBBB SSSS
	AND.w #$000F        ;   SSSS
	BEQ +
	TAX
	LDA.b ValueLow
-	LSR
	DEX
	BNE -
	STA.b ValueLow
+
	; == Mask value ==
	LDA.w CreditsStats+2,y;   CCC- ---- BBBB SSSS
	;LSR #4
	;AND.w #$000F        ;   BBBB
	LSR #3
	AND.w #$001E
	TAX
	LDA.l BitMasks,x
	AND.b ValueLow
	STA.b ValueLow

	; == Cap value ==
	LDA.w CreditsStats+3,y;   ---- ---- CCC- ----
	LSR #5
	AND.w #$0007        ;   CCC
	BEQ +
	ASL : TAX
	LDA.l ValueCaps,x
	CMP.b ValueLow
	!BGE +
	STA.b ValueLow
+
	; == Display value ==
	LDA.b ValueLow
	JSL HexToDecStats
	PLX
	STZ.b RemoveZero

	LDA.l HexToDecDigit2
	AND.w #$00FF
	CMP.b RemoveZero
	BNE +
	LDA.w #BlankCreditsTile
	BRA ++
+	DEC.b RemoveZero
	CLC
	ADC.b Temp
++	%StripeTile()

	LDA.l HexToDecDigit3
	AND.w #$00FF
	CMP.b RemoveZero
	BNE +
	LDA.w #BlankCreditsTile
	BRA ++
+	DEC.b RemoveZero
	CLC
	ADC.b Temp
++	%StripeTile()

	LDA.l HexToDecDigit4
	AND.w #$00FF
	CMP.b RemoveZero
	BNE +
	LDA.w #BlankCreditsTile
	BRA ++
+	DEC.b RemoveZero
	CLC
	ADC.b Temp
++	%StripeTile()

	LDA.l HexToDecDigit5
	AND.w #$00FF
	CLC
	ADC.b Temp
	%StripeTile()

	%StripeEnd()
.endStats

	PLB
	RTL

.timeStat
	; Output format: HH:MM:SS.FF

	; == Write Stripe header (VRAM address, i.e. tile coordinates) ==
	LDA.w CreditsStats,y  ;   LLLL LLLL XXXX XTTL
	LSR #3
	AND.w #$001F          ; X XXXX
	CLC
	ADC.b $C8
	XBA
	STA.w $1002,x

	; == Write Stripe header (Length of data) ==
	LDA.w #11*2-1    ; 11 tiles = 22 bytes
	XBA
	STA.w $1004,x
	PHX

	; == Load the actual stat words ==
	LDA.w CreditsStats+5,y
	STA.b StatsPtr
	LDA.w CreditsStats+6,y
	STA.b StatsPtr+1
	LDA.b [StatsPtr]
	STA.b ValueLow
	INC.b StatsPtr
	INC.b StatsPtr
	LDA.b [StatsPtr]
	STA.b ValueHigh

	CMP.w #!MAX_FRAME_COUNT>>16+1
	!BGE ++

	; == Convert total frames into hours, minutes, seconds and frames ==
	%CountUnits(!FRAMES_PER_HOUR, Hours)
	%CountUnits(!FRAMES_PER_MINUTE, Minutes)
	%CountUnits(!FRAMES_PER_SECOND, Seconds)

	; == Cap at 99:59:59.59 ==
	LDA.b Hours
	CMP.w #100
	!BLT +
++	LDA.w #99
	STA.b Hours
	LDA.w #59
	STA.b Minutes
	STA.b Seconds
	STA.b ValueLow
+

	; == Load tile base (upper or lower half of white two-line zero) ==
	LDA.b StatsBottom
	BNE +
	LDA.w #$3D40
	BRA ++
+	LDA.w #$3D50
++	STA.b Temp

	PLX

	; == Display value ==
	LDA.b Hours
	JSL HexToDecStats

	LDA.l HexToDecDigit4
	AND.w #$00FF
	CLC
	ADC.b Temp
	%StripeTile()

	LDA.l HexToDecDigit5
	AND.w #$00FF
	CLC
	ADC.b Temp
	%StripeTile()

	LDA.w #!ColonOffset
	CLC
	ADC.b Temp
	%StripeTile()

	LDA.b Minutes
	JSL HexToDecStats
	LDA.l HexToDecDigit4
	AND.w #$00FF
	CLC
	ADC.b Temp
	%StripeTile()

	LDA.l HexToDecDigit5
	AND.w #$00FF
	CLC
	ADC.b Temp
	%StripeTile()

	LDA.w #!ColonOffset
	CLC
	ADC.b Temp
	%StripeTile()

	LDA.b Seconds
	JSL HexToDecStats
	LDA.l HexToDecDigit4
	AND.w #$00FF
	CLC
	ADC.b Temp
	%StripeTile()

	LDA.l HexToDecDigit5
	AND.w #$00FF
	CLC
	ADC.b Temp
	%StripeTile()

	LDA.w #!PeriodOffset
	CLC
	ADC.b Temp
	%StripeTile()

	LDA.b ValueLow
	JSL HexToDecStats
	LDA.l HexToDecDigit4
	AND.w #$00FF
	CLC
	ADC.b Temp
	%StripeTile()

	LDA.l HexToDecDigit5
	AND.w #$00FF
	CLC
	ADC.b Temp
	%StripeTile()

	%StripeEnd()
	JMP .endStats


RenderLineNumber:
	%StripeStart(0, 3)

	STZ.b StatsBottom
	LDA.b $CA
	TAY
	AND.w #$0001
	BEQ +
	DEY
	INC.b StatsBottom
+
	JSR LastHexDigit
	PHA
	JSR LastHexDigit
	PHA
	JSR LastHexDigit
	%StripeTile()
	PLA
	%StripeTile()
	PLA
	%StripeTile()

	%StripeEnd()

	RTS

LoadCreditsTiles:
        JSL CopyFontToVRAM ; What we wrote over

        REP #$10
        LDA.b #$80 : STA.w VMAIN
        LDA.b #$01 : STA.w DMAP0
        LDA.b #$18 : STA.w BBAD0

        ; Item tiles
        LDX.w #$8200 : STX.w VMADDL
        LDA.b #FileSelectNewGraphics>>16 : STA.w A1B0
        LDX.w #FileSelectNewGraphics : STX.w A1T0L
        LDX.w #$0C00 : STX.w DAS0L
        LDA.b #$01 : STA.w DMAENABLE

        ; Small characters A-Z
        LDX.w #$7F00 : STX.w VMADDL
        LDA.b #SmallCharacters>>16 : STA.w A1B0
        LDX.w #SmallCharacters : STX.w A1T0L
        LDX.w #$0200 : STX.w DAS0L
        LDA.b #$01 : STA.w DMAENABLE

        SEP #$10
RTL

LoadOverworldCreditsTiles:
        JSL CopyFontToVRAM ; What we wrote over
        REP #$10

        ; Small characters A-Z
        LDA.b #$80 : STA.w VMAIN
        LDA.b #$01 : STA.w DMAP0
        LDA.b #$18 : STA.w BBAD0
        LDA.b #SmallCharacters>>16 : STA.w A1B0
        LDX.w #SmallCharacters : STX.w A1T0L
        LDX.w #$0200 : STX.w DAS0L
        LDX.w #$7F00 : STX.w VMADDL
        LDA.b #$01 : STA.w DMAENABLE

        SEP #$10
RTL

CheckFontTable:
	TAY
	PHB
	PHK
	PLB
	LDA.w FontTable,Y
	PLB
	RTL

NearEnding:
	STZ.w $012A ; disable triforce helper thread
	JSL LoadCustomHudPalette
	REP #$10
	JSL AltBufferTable_credits
	JSR DrawEndingItems
	JML PaletteFilter_TheEndSprite


EndingItems:
	; This function is not strictly needed, simply updating the tracker
	; every frame, but it is useful for debuging, so should be left in.
	REP #$10
	JSR DrawEndingItems
	REP #$20
	LDX.b #$0E
RTL

DrawEndingItems:
	JSL DrawPlayerFile_credits
	JSL SetItemLayoutPriority
	SEP #$30
	LDA.b #$01 : STA.b NMISTRIPES
RTS

;================================================================================
; Dialog Pointer Override
;--------------------------------------------------------------------------------
EndingSequenceTableOverride:
        PHY
        PHX
        TYX
        LDA.l EndingSequenceText, X
        PLX
        STA.w $1008, X
        PLY
RTL
;--------------------------------------------------------------------------------
EndingSequenceTableLookupOverride:
        PHX : PHB
        PHK : PLB
        TYX
        LDA.l EndingSequenceText, X : AND.w #$00FF
        ASL
        TAY
        LDA.w FontTable,Y
        PLB : PLX
RTL
;--------------------------------------------------------------------------------
