diff --git a/LTTP_RND_GeneralBugfixes.asm b/LTTP_RND_GeneralBugfixes.asm index 60acd67..e339e59 100644 --- a/LTTP_RND_GeneralBugfixes.asm +++ b/LTTP_RND_GeneralBugfixes.asm @@ -445,6 +445,8 @@ org $00891D org $00893D EnableForceBlank: +DungeonMask = $0098C0 + org $00D308 DecompSwordGfx: diff --git a/compasses.asm b/compasses.asm index b691456..99622e2 100644 --- a/compasses.asm +++ b/compasses.asm @@ -12,7 +12,7 @@ DrawDungeonCompassCounts: CPX.b #$1B : BCS .done ; Skip if not in a valid dungeon ID - CMP.w #$0002 : BEQ ++ ; if CompassMode==2, we don't check for the compass + BIT.w #$0002 : BNE ++ ; if CompassMode==2, we don't check for the compass LDA CompassField : AND.l DungeonItemMasks, X ; Load compass values to A, mask with dungeon item masks BEQ .done ; skip if we don't have compass ++ diff --git a/elder.asm b/elder.asm index 87f25a1..5c4a6a6 100644 --- a/elder.asm +++ b/elder.asm @@ -50,6 +50,8 @@ RTL RTS + SEP #$20 + LDA.b $11 + BNE .done LDA.b #$96 LDY.b #$01 diff --git a/inventory.asm b/inventory.asm index 783c8f0..3e038ce 100644 --- a/inventory.asm +++ b/inventory.asm @@ -703,31 +703,13 @@ RTL RTS .setDungeonCompletion - LDA $040C - CMP #$FF : BEQ + - LSR : AND #$0F : CMP #$08 : !BGE ++ - JSR .valueShift - ORA DungeonsCompleted : STA DungeonsCompleted - BRA + - ++ - !SUB #$08 - JSR .valueShift - BIT.b #$C0 : BEQ +++ : LDA.b #$C0 : +++ ; Make Hyrule Castle / Sewers Count for Both - ORA DungeonsCompleted+1 : STA DungeonsCompleted+1 + LDX $040C : BMI + + REP #$20 ; 16 bit + LDA.l DungeonMask, X + ORA DungeonsCompleted : STA DungeonsCompleted + SEP #$20 ; 8 bit + RTS - -.valueShift - PHX - TAX : LDA.b #$01 - - - CPX #$00 : BEQ + - ASL - DEX - BRA - - + - PLX -RTS ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- diff --git a/newitems.asm b/newitems.asm index 30040af..ce16882 100755 --- a/newitems.asm +++ b/newitems.asm @@ -891,27 +891,26 @@ AddReceivedItemExpanded: ;0x1A - Ganon's Tower .item_masks ; these are dungeon correlations to $7EF364 - $7EF369 so it knows where to store compasses, etc - ; sewers and castle get 2 bits active so that they can share their items elegantly - dw $C000, $C000, $2000, $1000, $0800, $0400, $0200, $0100 - dw $0080, $0040, $0020, $0010, $0008, $0004, $0000, $0000 + ; sewers and castle get 2 bits active so that they can share their items elegantly + dw $C000, $C000, $2000, $1000, $0800, $0400, $0200, $0100 + dw $0080, $0040, $0020, $0010, $0008, $0004, $4B8B, $20AB ; last two can be re-used - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 - dw $0000, $0000, $0000, $0000, $0000, $0000, $0000 - db $00 - dw $0000 ; Caves + ; caves + dw $9CCE, $0390, $2F82, $AD03, $02E9, $01C9, $06D0, $72A5 + dw $A548, $4873, $01A0, $D8AD, $C902, $D020, $A002, $9802 + dw $E48D, $DA02, $D8AC, $D002, $A215, $BD08, $84E2, $0085 + dw $E3BD, $8584, $A901, $857E, $B902, $857A, $0087, $0A98 + dw $BDAA, $84E2, $0085, $E3BD, $8584, $A901, $857E, $B902 + dw $857A, $0230, $0087, $1FC0, $02D0, $5664, $04A9, $4BC0 + dw $06F0, $1EC0, $0AD0, $02A9, $790F, $7EF3, $798F, $7EF3 + dw $1BC0, $04F0, $1CC0, $07D0, $1B22, $1BEE, $0182, $A201 + dw $C004, $F037, $A20C, $C001, $F038, $A206, $C002, $D039 + dw $8A14, $0007, $0087, $00EE, $2902, $C907, $D007, $A906 + dw $8F04, $F3C7, $C07E, $D022, $A70A, $D000, $A904, $8701 + dw $8000, $C0C9, $F025, $C008, $F032, $C004, $D033, $AE11 + dw $040C, $20C2, $C6BD, $0785, $8700, $E200, $8220, $00B0 + dw $3EC0, $0AD0, $082C, $1003, $A905, $8D02, $0309, $20C0 + dw $44D0 } ;-------------------------------------------------------------------------------- BottleListExpanded: @@ -1207,7 +1206,7 @@ UpdateInventoryLocationExpanded: ; Set a flag in SRAM if we pick up a compass in its own dungeon with HUD compass ; counts on MaybeFlagCompassTotalPickup: - LDA CompassMode : BEQ .done + LDA.l CompassMode : AND.b #$0F : BEQ .done LDA $040C : CMP #$FF : BEQ .done LSR : STA $04 : LDA #$0F : !SUB $04 ; Compute flag "index" CPY #$25 : BEQ .setFlag ; Set flag if it's a compass for this dungeon @@ -1230,7 +1229,7 @@ RTL ; that compass MaybeFlagCompassTotalEntrance: LDX $040C : CPX #$FF : BEQ .done ; Skip if we're not entering dungeon - LDA CompassMode : BEQ .done ; Skip if we're not showing compass counts + LDA.l CompassMode : AND.w #$000F : BEQ .done ; Skip if we're not showing compass counts CMP.w #$0002 : BEQ .countShown LDA CompassField : AND.l DungeonItemMasks, X : BEQ .done ; skip if we don't have compass .countShown diff --git a/sram.asm b/sram.asm index 3897796..37e8ef1 100644 --- a/sram.asm +++ b/sram.asm @@ -24,8 +24,8 @@ org 0 ; This module writes no bytes. Asar gives bank cross errors without this. ; Example: We can use RoomDataWRAM[$37].high to read or write the pot key in the first ; floodable room in Swamp Palace ($04) ;-------------------------------------------------------------------------------- -; .high Byte: d d d d b k u r -; .low Byte: c c c c q q q q +; .high Byte: d d d d b k u t +; .low Byte: s e h c q q q q ; ; d = Door opened (key, bomb wall, etc) ; b = Boss kill / Heart Container diff --git a/stats/font.2bpp b/stats/font.2bpp new file mode 100644 index 0000000..c0ce111 Binary files /dev/null and b/stats/font.2bpp differ diff --git a/stats/font.gb b/stats/font.gb index cc173b4..9894dc4 100755 Binary files a/stats/font.gb and b/stats/font.gb differ diff --git a/stats/main.asm b/stats/main.asm index 975eb3b..fe33a33 100755 --- a/stats/main.asm +++ b/stats/main.asm @@ -1,666 +1,670 @@ -lorom - -!ADD = "CLC : ADC" -!SUB = "SEC : SBC" -!BLT = "BCC" -!BGE = "BCS" - -org $238000 -incsrc stats/creditsnew.asm - -FontGfx: -incbin stats/font.gb -FontGfxEnd: - -; 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 [!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 AddStat(address, type, shiftRight, bits, digits, xPos, lineNumber) - db <<2|<<9|>>8 - db - db <<4| - db <<5 - db $00 - dl
-endmacro - -macro StripeStart(xPos, length) - LDA $C8 - CLC - ADC.w # - XBA - STA $1002,x - - LDA.w #*2-1 - XBA - LDA #$0500 - STA $1004,x -endmacro - -macro StripeTile() - STA $1006,x - INX - INX -endmacro - -macro StripeEnd() - INX - INX - INX - INX -endmacro - -HexToDecStats: - PHA - PHA - LDA.w #$0000 - STA $7F5003 : STA $7F5005 : STA $7F5006 ; clear digit storage - PLA - - - CMP.w #10000 : !BLT + - PHA : SEP #$20 : LDA $7F5003 : INC : STA $7F5003 : REP #$20 : PLA - !SUB.w #10000 : BRA - - + - - CMP.w #1000 : !BLT + - PHA : SEP #$20 : LDA $7F5004 : INC : STA $7F5004 : REP #$20 : PLA - !SUB.w #1000 : BRA - - + - - CMP.w #100 : !BLT + - PHA : SEP #$20 : LDA $7F5005 : INC : STA $7F5005 : REP #$20 : PLA - !SUB.w #100 : BRA - - + - - CMP.w #10 : !BLT + - PHA : SEP #$20 : LDA $7F5006 : INC : STA $7F5006 : REP #$20 : PLA - !SUB.w #10 : BRA - - + - - CMP.w #1 : !BLT + - PHA : SEP #$20 : LDA $7F5007 : INC : STA $7F5007 : REP #$20 : PLA - !SUB.w #1 : BRA - - + - PLA -RTL - -LastHexDigit: - TYA - AND #$000F - PHA - TYA - LSR #4 - TAY - CLC - LDA !StatsBottom - BNE + - ; Upper half - PLA - ADC #$3D40 - RTS -+ ; Lower half - PLA - ADC #$3D50 - RTS - -FindLine: - LDY.w #$0000 - -- LDA.w CreditsStats,y - STZ !StatsBottom - CMP #$FFFF - BEQ .noLine - - XBA - AND #$01FF - CMP !LineNumber - BEQ .lineFound - - INC - INC !StatsBottom - CMP !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 -?loop: - LDA !ValueLow - SEC - SBC.w # - STA !Temp - LDA !ValueHigh - SBC.w #>>16 - BCC ?end - STA !ValueHigh - LDA !Temp - STA !ValueLow - INC - BRA ?loop -?end: -endmacro - -!ColonOffset = $83 -!PeriodOffset = $80 -!BlankTile = #$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 #$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 #$001F ; X XXXX - CLC - ADC $C8 - XBA - STA $1002,x - - ; == Write Stripe header (Length of data) == - LDA.w #4*2-1 ; 4 tiles = 8 bytes - XBA - STA $1004,x - PHX - - ; == Load tile base (upper or lower half of white two-line zero) == - LDA !StatsBottom - BNE + - LDA #$3D40 - BRA ++ -+ LDA #$3D50 -++ STA !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 !ValueLow - - ; == Shift value == - LDA.w CreditsStats+2,y; CCC- ---- BBBB SSSS - AND.w #$000F ; SSSS - BEQ + - TAX - LDA !ValueLow -- LSR - DEX - BNE - - STA !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 !ValueLow - STA !ValueLow - - ; == Cap value == - LDA.w CreditsStats+3,y; ---- ---- CCC- ---- - LSR #5 - AND.w #$0007 ; CCC - BEQ + - ASL : TAX - LDA.l ValueCaps,x - CMP !ValueLow - !BGE + - STA !ValueLow -+ - ; == Display value == - LDA !ValueLow - JSL HexToDecStats - PLX - STZ !RemoveZero - - LDA $7F5004 - AND #$00FF - CMP !RemoveZero - BNE + - LDA !BlankTile - BRA ++ -+ DEC !RemoveZero - CLC - ADC !Temp -++ %StripeTile() - - LDA $7F5005 - AND #$00FF - CMP !RemoveZero - BNE + - LDA !BlankTile - BRA ++ -+ DEC !RemoveZero - CLC - ADC !Temp -++ %StripeTile() - - LDA $7F5006 - AND #$00FF - CMP !RemoveZero - BNE + - LDA !BlankTile - BRA ++ -+ DEC !RemoveZero - CLC - ADC !Temp -++ %StripeTile() - - LDA $7F5007 - AND #$00FF - CLC - ADC !Temp - %StripeTile() - - %StripeEnd() -.endStats - - ;JSR RenderLineNumber - - 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 #$001F ; X XXXX - CLC - ADC $C8 - XBA - STA $1002,x - - ; == Write Stripe header (Length of data) == - LDA.w #11*2-1 ; 11 tiles = 22 bytes - XBA - STA $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 !ValueLow - INC !StatsPtr - INC !StatsPtr - LDA.b [!StatsPtr] - STA !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 !Hours - CMP.w #100 - !BLT + -++ LDA.w #99 - STA !Hours - LDA.w #59 - STA !Minutes - STA !Seconds - STA !ValueLow -+ - - ; == Load tile base (upper or lower half of white two-line zero) == - LDA !StatsBottom - BNE + - LDA #$3D40 - BRA ++ -+ LDA #$3D50 -++ STA !Temp - - PLX - - ; == Display value == - LDA !Hours - JSL HexToDecStats - - LDA $7F5006 - AND #$00FF - CLC - ADC !Temp - %StripeTile() - - LDA $7F5007 - AND #$00FF - CLC - ADC !Temp - %StripeTile() - - LDA.w #!ColonOffset - CLC - ADC !Temp - %StripeTile() - - LDA !Minutes - JSL HexToDecStats - LDA $7F5006 - AND #$00FF - CLC - ADC !Temp - %StripeTile() - - LDA $7F5007 - AND #$00FF - CLC - ADC !Temp - %StripeTile() - - LDA.w #!ColonOffset - CLC - ADC !Temp - %StripeTile() - - LDA !Seconds - JSL HexToDecStats - LDA $7F5006 - AND #$00FF - CLC - ADC !Temp - %StripeTile() - - LDA $7F5007 - AND #$00FF - CLC - ADC !Temp - %StripeTile() - - LDA.w #!PeriodOffset - CLC - ADC !Temp - %StripeTile() - - LDA !ValueLow - JSL HexToDecStats - LDA $7F5006 - AND #$00FF - CLC - ADC !Temp - %StripeTile() - - LDA $7F5007 - AND #$00FF - CLC - ADC !Temp - %StripeTile() - - %StripeEnd() - JMP .endStats - - -RenderLineNumber: - %StripeStart(0, 3) - - STZ !StatsBottom - LDA $CA - TAY - AND #$0001 - BEQ + - DEY - INC !StatsBottom -+ - JSR LastHexDigit - PHA - JSR LastHexDigit - PHA - JSR LastHexDigit - %StripeTile() - PLA - %StripeTile() - PLA - %StripeTile() - - %StripeEnd() - - RTS - -LoadModifiedFont: - ; Based on CopyFontToVram(Bank00) - ; copies font graphics to VRAM (for BG3) - - ; set name base table to vram $4000 (word) - LDA.b #$02 : STA $2101 - - ; increment on writes to $2119 - LDA.b #$80 : STA $2115 - - ; set bank of the source address (see below) - LDA.b #FontGfx>>16 : STA $02 - - REP #$30 - - ; vram target address is $7000 (word) - LDA.w #$7000 : STA $2116 - - ; $00[3] = $0E8000 (offset for the font data) - LDA.w #FontGfx : STA $00 - - ; going to write 0x1000 bytes (0x800 words) - LDX.w #FontGfxEnd-FontGfx/2-1 - -.nextWord - - ; read a word from the font data - LDA [$00] : STA $2118 - - ; increment source address by 2 - INC $00 : INC $00 - - DEX : BPL .nextWord - - SEP #$30 - JSL LoadFullItemTilesCredits - - RTL - -LoadFullItemTilesCredits: - ; Based on CopyFontToVram(Bank00) - ; copies font graphics to VRAM (for BG3) - - ; increment on writes to $2119 - LDA.b #$80 : STA $2115 - - ; set bank of the source address (see below) - LDA.b #FileSelectNewGraphics>>16 : STA $02 - - REP #$30 - - ; vram target address is $8000 (word) (Wraps to start of VRAM on normal SNES, but using the correct address so it works on extended VRAM machines) - LDA.w #$8000 : STA $2116 - - ; $00[3] = $0E8000 (offset for the font data) - LDA.w #FileSelectNewGraphics : STA $00 - - ; going to write 0x1000 bytes (0x800 words) - LDX.w #$800-1 - - .nextWord - - ; read a word from the font data - LDA [$00] : STA $2118 - - ; increment source address by 2 - INC $00 : INC $00 - - DEX : BPL .nextWord - - SEP #$30 - - 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.l $00ec03 ; PaletteFilter_InitTheEndSprite - -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 $14 -RTS - -FontTable: - incbin stats/fonttable.bin - -CreditsStats: -incsrc stats/statConfig.asm -dw $FFFF - -org $0eedd9 - JSL EndingItems - -org $0eedaf - JSL NearEnding - -org $0EE651 - JSL LoadModifiedFont - -org $0EE828 - JSL PreparePointer - LDA [!CreditsPtr],Y - NOP -org $0EE83F - LDA [!CreditsPtr],Y - NOP -org $0EE853 - LDA [!CreditsPtr],Y - NOP - AND.w #$00ff - ASL A - JSL CheckFontTable - -org $0ee86d - JSL RenderCreditsStatCounter - JMP.w AfterDeathCounterOutput - -org $0ee8fd - AfterDeathCounterOutput: +lorom + +!ADD = "CLC : ADC" +!SUB = "SEC : SBC" +!BLT = "BCC" +!BGE = "BCS" + +org $238000 +incsrc stats/creditsnew.asm + +FontGfx: +if !FEATURE_NEW_TEXT + incbin stats/font.2bpp +else + incbin stats/font.gb +endif +FontGfxEnd: + +; 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 [!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 AddStat(address, type, shiftRight, bits, digits, xPos, lineNumber) + db <<2|<<9|>>8 + db + db <<4| + db <<5 + db $00 + dl
+endmacro + +macro StripeStart(xPos, length) + LDA $C8 + CLC + ADC.w # + XBA + STA $1002,x + + LDA.w #*2-1 + XBA + LDA #$0500 + STA $1004,x +endmacro + +macro StripeTile() + STA $1006,x + INX + INX +endmacro + +macro StripeEnd() + INX + INX + INX + INX +endmacro + +HexToDecStats: + PHA + PHA + LDA.w #$0000 + STA $7F5003 : STA $7F5005 : STA $7F5006 ; clear digit storage + PLA + - + CMP.w #10000 : !BLT + + PHA : SEP #$20 : LDA $7F5003 : INC : STA $7F5003 : REP #$20 : PLA + !SUB.w #10000 : BRA - + + - + CMP.w #1000 : !BLT + + PHA : SEP #$20 : LDA $7F5004 : INC : STA $7F5004 : REP #$20 : PLA + !SUB.w #1000 : BRA - + + - + CMP.w #100 : !BLT + + PHA : SEP #$20 : LDA $7F5005 : INC : STA $7F5005 : REP #$20 : PLA + !SUB.w #100 : BRA - + + - + CMP.w #10 : !BLT + + PHA : SEP #$20 : LDA $7F5006 : INC : STA $7F5006 : REP #$20 : PLA + !SUB.w #10 : BRA - + + - + CMP.w #1 : !BLT + + PHA : SEP #$20 : LDA $7F5007 : INC : STA $7F5007 : REP #$20 : PLA + !SUB.w #1 : BRA - + + + PLA +RTL + +LastHexDigit: + TYA + AND #$000F + PHA + TYA + LSR #4 + TAY + CLC + LDA !StatsBottom + BNE + + ; Upper half + PLA + ADC #$3D40 + RTS ++ ; Lower half + PLA + ADC #$3D50 + RTS + +FindLine: + LDY.w #$0000 + +- LDA.w CreditsStats,y + STZ !StatsBottom + CMP #$FFFF + BEQ .noLine + + XBA + AND #$01FF + CMP !LineNumber + BEQ .lineFound + + INC + INC !StatsBottom + CMP !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 +?loop: + LDA !ValueLow + SEC + SBC.w # + STA !Temp + LDA !ValueHigh + SBC.w #>>16 + BCC ?end + STA !ValueHigh + LDA !Temp + STA !ValueLow + INC + BRA ?loop +?end: +endmacro + +!ColonOffset = $83 +!PeriodOffset = $80 +!BlankTile = #$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 #$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 #$001F ; X XXXX + CLC + ADC $C8 + XBA + STA $1002,x + + ; == Write Stripe header (Length of data) == + LDA.w #4*2-1 ; 4 tiles = 8 bytes + XBA + STA $1004,x + PHX + + ; == Load tile base (upper or lower half of white two-line zero) == + LDA !StatsBottom + BNE + + LDA #$3D40 + BRA ++ ++ LDA #$3D50 +++ STA !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 !ValueLow + + ; == Shift value == + LDA.w CreditsStats+2,y; CCC- ---- BBBB SSSS + AND.w #$000F ; SSSS + BEQ + + TAX + LDA !ValueLow +- LSR + DEX + BNE - + STA !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 !ValueLow + STA !ValueLow + + ; == Cap value == + LDA.w CreditsStats+3,y; ---- ---- CCC- ---- + LSR #5 + AND.w #$0007 ; CCC + BEQ + + ASL : TAX + LDA.l ValueCaps,x + CMP !ValueLow + !BGE + + STA !ValueLow ++ + ; == Display value == + LDA !ValueLow + JSL HexToDecStats + PLX + STZ !RemoveZero + + LDA $7F5004 + AND #$00FF + CMP !RemoveZero + BNE + + LDA !BlankTile + BRA ++ ++ DEC !RemoveZero + CLC + ADC !Temp +++ %StripeTile() + + LDA $7F5005 + AND #$00FF + CMP !RemoveZero + BNE + + LDA !BlankTile + BRA ++ ++ DEC !RemoveZero + CLC + ADC !Temp +++ %StripeTile() + + LDA $7F5006 + AND #$00FF + CMP !RemoveZero + BNE + + LDA !BlankTile + BRA ++ ++ DEC !RemoveZero + CLC + ADC !Temp +++ %StripeTile() + + LDA $7F5007 + AND #$00FF + CLC + ADC !Temp + %StripeTile() + + %StripeEnd() +.endStats + + ;JSR RenderLineNumber + + 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 #$001F ; X XXXX + CLC + ADC $C8 + XBA + STA $1002,x + + ; == Write Stripe header (Length of data) == + LDA.w #11*2-1 ; 11 tiles = 22 bytes + XBA + STA $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 !ValueLow + INC !StatsPtr + INC !StatsPtr + LDA.b [!StatsPtr] + STA !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 !Hours + CMP.w #100 + !BLT + +++ LDA.w #99 + STA !Hours + LDA.w #59 + STA !Minutes + STA !Seconds + STA !ValueLow ++ + + ; == Load tile base (upper or lower half of white two-line zero) == + LDA !StatsBottom + BNE + + LDA #$3D40 + BRA ++ ++ LDA #$3D50 +++ STA !Temp + + PLX + + ; == Display value == + LDA !Hours + JSL HexToDecStats + + LDA $7F5006 + AND #$00FF + CLC + ADC !Temp + %StripeTile() + + LDA $7F5007 + AND #$00FF + CLC + ADC !Temp + %StripeTile() + + LDA.w #!ColonOffset + CLC + ADC !Temp + %StripeTile() + + LDA !Minutes + JSL HexToDecStats + LDA $7F5006 + AND #$00FF + CLC + ADC !Temp + %StripeTile() + + LDA $7F5007 + AND #$00FF + CLC + ADC !Temp + %StripeTile() + + LDA.w #!ColonOffset + CLC + ADC !Temp + %StripeTile() + + LDA !Seconds + JSL HexToDecStats + LDA $7F5006 + AND #$00FF + CLC + ADC !Temp + %StripeTile() + + LDA $7F5007 + AND #$00FF + CLC + ADC !Temp + %StripeTile() + + LDA.w #!PeriodOffset + CLC + ADC !Temp + %StripeTile() + + LDA !ValueLow + JSL HexToDecStats + LDA $7F5006 + AND #$00FF + CLC + ADC !Temp + %StripeTile() + + LDA $7F5007 + AND #$00FF + CLC + ADC !Temp + %StripeTile() + + %StripeEnd() + JMP .endStats + + +RenderLineNumber: + %StripeStart(0, 3) + + STZ !StatsBottom + LDA $CA + TAY + AND #$0001 + BEQ + + DEY + INC !StatsBottom ++ + JSR LastHexDigit + PHA + JSR LastHexDigit + PHA + JSR LastHexDigit + %StripeTile() + PLA + %StripeTile() + PLA + %StripeTile() + + %StripeEnd() + + RTS + +LoadModifiedFont: + ; Based on CopyFontToVram(Bank00) + ; copies font graphics to VRAM (for BG3) + + ; set name base table to vram $4000 (word) + LDA.b #$02 : STA $2101 + + ; increment on writes to $2119 + LDA.b #$80 : STA $2115 + + ; set bank of the source address (see below) + LDA.b #FontGfx>>16 : STA $02 + + REP #$30 + + ; vram target address is $7000 (word) + LDA.w #$7000 : STA $2116 + + ; $00[3] = $0E8000 (offset for the font data) + LDA.w #FontGfx : STA $00 + + ; going to write 0x1000 bytes (0x800 words) + LDX.w #FontGfxEnd-FontGfx/2-1 + +.nextWord + + ; read a word from the font data + LDA [$00] : STA $2118 + + ; increment source address by 2 + INC $00 : INC $00 + + DEX : BPL .nextWord + + SEP #$30 + JSL LoadFullItemTilesCredits + + RTL + +LoadFullItemTilesCredits: + ; Based on CopyFontToVram(Bank00) + ; copies font graphics to VRAM (for BG3) + + ; increment on writes to $2119 + LDA.b #$80 : STA $2115 + + ; set bank of the source address (see below) + LDA.b #FileSelectNewGraphics>>16 : STA $02 + + REP #$30 + + ; vram target address is $8000 (word) (Wraps to start of VRAM on normal SNES, but using the correct address so it works on extended VRAM machines) + LDA.w #$8000 : STA $2116 + + ; $00[3] = $0E8000 (offset for the font data) + LDA.w #FileSelectNewGraphics : STA $00 + + ; going to write 0x1000 bytes (0x800 words) + LDX.w #$800-1 + + .nextWord + + ; read a word from the font data + LDA [$00] : STA $2118 + + ; increment source address by 2 + INC $00 : INC $00 + + DEX : BPL .nextWord + + SEP #$30 + + 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.l $00ec03 ; PaletteFilter_InitTheEndSprite + +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 $14 +RTS + +FontTable: + incbin stats/fonttable.bin + +CreditsStats: +incsrc stats/statConfig.asm +dw $FFFF + +org $0eedd9 + JSL EndingItems + +org $0eedaf + JSL NearEnding + +org $0EE651 + JSL LoadModifiedFont + +org $0EE828 + JSL PreparePointer + LDA [!CreditsPtr],Y + NOP +org $0EE83F + LDA [!CreditsPtr],Y + NOP +org $0EE853 + LDA [!CreditsPtr],Y + NOP + AND.w #$00ff + ASL A + JSL CheckFontTable + +org $0ee86d + JSL RenderCreditsStatCounter + JMP.w AfterDeathCounterOutput + +org $0ee8fd + AfterDeathCounterOutput: