0) Started a new game, lost some life, and manual save. Clicked "save" and save state before it ends.
1) We know hearts are at $66f and $670. Put read breakpoint and you should end at 05:8B6D.
>05:8B6D: AD 6F 06 LDA $066F = #$22
05:8B70: 29 F0 AND #$F0
05:8B72: 09 02 ORA #$02
05:8B74: 8D 6F 06 STA $066F = #$22
05:8B77: A9 FF LDA #$FF
05:8B79: 8D 70 06 STA $0670 = #$7F
Looks important!
2) Another read takes us here
>02:A6C6: B9 57 06 LDA $0657,Y @ $0670 = #$7F
02:A6C9: 91 C0 STA ($C0),Y @ $68D9 = #$00
02:A6CB: 88 DEY
02:A6CC: 10 F8 BPL $A6C6
You've possibly seen this before.
3) Then we end up here.
>02:A6F3: AD 6F 06 LDA $066F = #$22
02:A6F6: 29 F0 AND #$F0
02:A6F8: 48 PHA
02:A6F9: 4A LSR
02:A6FA: 4A LSR
02:A6FB: 4A LSR
02:A6FC: 4A LSR
02:A6FD: 85 0A STA $0A = #$19
02:A6FF: 68 PLA
02:A700: 05 0A ORA $0A = #$19
02:A702: 8D 6F 06 STA $066F = #$22
02:A705: A9 FF LDA #$FF
02:A707: 8D 70 06 STA $0670 = #$7F
02:A70A: 20 19 A8 JSR $A819
>02:A819: A4 16 LDY $16 = #$01
02:A81B: B9 A1 A6 LDA $A6A1,Y @ $A7A0 = #$48
02:A81E: 85 0C STA $0C = #$40
02:A820: B9 A4 A6 LDA $A6A4,Y @ $A7A3 = #$48
02:A823: 85 0D STA $0D = #$06
02:A825: A0 01 LDY #$01
>02:A827: B9 6F 06 LDA $066F,Y @ $0670 = #$7F
02:A82A: 91 0C STA ($0C),Y @ $0653 = #$FF ====
02:A82C: 88 DEY
02:A82D: 10 F8 BPL $A827
02:A82F: 60 RTS -----------------------------------------
Okay. That's more interesting.
I marked A82A as I thought it was interesting.
4) I chose to stop refilling $670 and got a crash. So I looked at 0653.
02:A509: B9 50 06 LDA $0650,Y @ $0653 = #$7F
02:A50C: 85 0E STA $0E = #$22
02:A50E: C8 INY
>02:A50F: B9 50 06 LDA $0650,Y @ $0653 = #$7F
02:A512: 85 0F STA $0F = #$00
> :6EC4: A5 0F LDA $0F = #$7F
:6EC6: F0 0D BEQ $6ED5
:6EC8: C9 C0 CMP #$C0
:6ECA: B0 F4 BCS $6EC0
:6ECC: A9 00 LDA #$00
:6ECE: 8D 29 05 STA $0529 = #$00
:6ED1: 4C BC BE JMP $BEBC
02:BEBC: FF UNDEFINED
02:BEBD: FF UNDEFINED
02:BEBE: FF UNDEFINED
02:BEBF: FF UNDEFINED
02:BEC0: FF UNDEFINED
02:BEC1: FF UNDEFINED
I'll stop here. If you have questions about any code or answers to give, ask away.
I think I had most of the routines you have listed there in here:
https://github.com/ShadowOne333/The-Legend-of-Zelda-Redux/blob/master/MMC1/code/gameplay/hearts.asm(I have further modified the file to accommodate your points and the routines)
I only had that for archival purposes, since all that does is overwrite the original routines with the same code, but I had it in place just for when I got around to it.
Almost all code you mentioned is included to some extend in there.
I think the only one which I didn't have included was the one here:
02:A509: B9 50 06 LDA $0650,Y @ $0653 = #$7F
02:A50C: 85 0E STA $0E = #$22
02:A50E: C8 INY
>02:A50F: B9 50 06 LDA $0650,Y @ $0653 = #$7F
02:A512: 85 0F STA $0F = #$00
As for the one at $6EC4 up to $6ED1...
That one I remember modifying way earlier in the project, when I was doing changes to the original Automap code by Snarfblam.
I remember making changes there specifically for Automap.
The CMP at $6EC8 is the one that determines at what health value the heart sprite will change. In the original it was $80, since it only had sprites for full heart, half heart or empty, but I modified Automap to add 1/4 heart decrements, hence the $C0, so it changes the sprite to 3/4 hearts at $C0.
There's also the JMP there at $6ED1, which is also part of Automap (Partial Heart Routine).
I think that whole part of the code is related to in-game handling of the health/hearts.
Here you can see the specific changes in there from Automap:
https://github.com/ShadowOne333/The-Legend-of-Zelda-Redux/blob/master/MMC1/code/gameplay/automap.asm#L818-L828Outside of that, from the little I can gather, it seems like the routine at bank 5, $8B6D seems to be the one that's modifying the max value of the hearts at $066F. It's right after the STA $066F at $8B74 that the value changes from whatever the current amount is, to the default of $X2, with the 2 being the value for the default 3 hearts.
By the time the loads from accumulator of bank 2 read the value at $066F, that value has already changed to $X2, so I am inclined to say the one at bank 5 might be key, but I could still be wrong of course.
As for the others, I am not sure how the change/read of $FFs in the $650~ range (and $0670) are modified to #$7F.
For $C0 in RAM, that one seems to be a table of sorts, but I am still not sure what that table is for precisely.
However, one thing I did notice, is that the values at $0650 up to $0655 is a table for the values of the Max Amount of Hearts based on the Save Slot, with $0651, $0653 and $0655 possibly being a terminator, since it's $FF for all 3 instances.
$0650=Max hearts for Save 1
$0652=Max hearts for Save 2
$0653=Max hearts for Save 3
If I modify the amount of hearts manually of a given save slot, and then save, the value at the determined address changes from the default $22 (3 hearts) to whatever the new amount is ($33, $44, etc.).
One other routine I found that seems to write the value at $066F upon save load is the one at $A606, which sets whatever value is at that address to $X2 on load, and this seems to be loading it from the SRAM addresses related to the save file, at $6032:
02:A606: B1 00 LDA ($00),Y @ $6032 = #$92
>02:A608: 99 57 06 STA $0657,Y @ $066F = #$99
02:A60B: 88 DEY
02:A60C: 10 F8 BPL $A606
So far this is what I have found.
I do get bits and glimpses, but I am not 100% sure if my assumption that the code at bank 5 is the sole one that might need a rework, and/or if the others at bank 2 might be directly related to saving the value to SRAM.
Please do let me know if I am on the right track, and if I missed any pivotal information that could point towards the right direction.