News:

11 March 2016 - Forum Rules

Main Menu

FF1 MMC5 Disassembly Updates

Started by Jiggers, January 04, 2019, 05:36:47 AM

Previous topic - Next topic

Vanya

#720
Terrible. My solution would be to leave out the "item to be removed" from the inventory and then encode the stat number text to display the numbers in the green palette if the gear would improve your stat and in pink if it would worsen it. Would that be even worse to code? I feel like it might be worse.

Also, I noted something else. What if you have at least one of every item?
If you have every slot used in the equipment bags, how do you remove equipped gear?
The original game and most later ones have the equipment menu commands 'EQUIP' and 'RMOVE'.
Since you took out the commands, there is no other way to unequip items.
Should they be restored?

Here... lets get nuts...

They could be added to the title bar in the equipment bag screen similarly to the original game:

'EQUIP' -> Closes the title bar menu, displays the normal equipment bag title bar and enters the equipment bag mode as normal.

'REMOVE' -> Removes the current item and exits without ever going into the equipment bag mode at all.

-OR-

Lets get really insane...

Alternatively you could use the stat "box" at the bottom of the main equipment screen to display an initial menu instead of your current stats:

'EQUIP' -> Goes to the normal equipment slot mode with your stats displayed and otherwise works as normal now.

'REMOVE' -> goes to the normal equipment slot mode, but now pressing A on a slot will empty the slot if there is anything equipped there.

And you could even add more options like maybe:

'EMPTY' -> removes all equipment.

'WEAPONS' -> just goes into the weapons side of the equipment bag to simply look at item stats like in the shops. You could even split the stat box so that a short description could be added to the right.

'ARMOR' -> same as above only for the armor side of the equipment bag.

'RELICS' -> if you add relics into the game then they can have a viewing command too?




Anyway. Back to my reporting...

Everything seems to be fine more or less as far as the town experience is concerned.
Being able to increment the total amount of items to but by 10 is smooth as butter and makes for a far better shopping experience. Groovy!

There is one other feature you might want to consider adding. When increasing the number of items to buy it currently caps the total at the total number of items you can hold minus the total number you have in inventory, but it doesn't take into account the total you can afford. Maybe add a secondary check that divides your GP by the cost of the item round down and if that number is lower than the number being bough it reduces it to that number instead?

In battle, I noticed that sometimes when my command window is supposed to come up it fails to display and the game hangs there playing the battle music. It happened once after getting ambushed and the enemies' extra turn ended, and then in another battle after the enemies' took their normal turn. So maybe it has to do with the enemy turn ending and not calling the right address or something?

Jiggers

#721
Terrible because its a bad idea, or because it would take me so long to do it?

Coloring the numbers would be doable, though kind of annoying (maybe not as annoying as playing with the description strings more)... but its the comparing to old that I worry about. It would require... no, maybe I can simplify.

Update stats with To Be Unequipped item.
Copy Damage, Accuracy, Critical, to tmp RAM. Do this in Bank E... don't want to touch the Update stats routine anymore.
Update stats with To Be Equipped item.
Compare Damage, Accuracy, Critical, to tmp RAM.

Huh. Brain worky somehow.  :D

Yeah... I think... think I can do that? Weapon attribute bytes are $EB, $F3. Armor is $EE, $F6... oh no.

The description box would need to be drawn first, but taller by 1 tile, so the equipment list can cover the top of the box. Otherwise, the box border will be green/pink as well for Damage and Defense. Is that acceptable?

For removing, that's a plus for putting the To Be Unequipped item into the list. Slap a dot on there like so.



Now press A on THAT one, it compares To Be Unequipped with To Be Equipped, matches, and then the < Equipment Bag # > window asks, "Remove? OPYes   No" (I made a li'l glove.)

That way its not popping up every time you press A...?




Ahhh, writing posts while the other person edits, ain't it just the way.

I actually kinda dig that description-box-menu thing. You don't think that would mess with flow too much? Maybe its my FF14 experience kicking in again, but I just realized I've been striving to cut down the number of prompts as much as possible. The menus can be overwhelmingly ridiculous. When I'm in the Zone I don't want to be trifled with by Yesses and Nos. Except for the battle confirmation, which I need because I screw up the 4th character's turn so much.

Or would the menu be in the first Equip screen?

Equip        - Remove
Skills       - Get Nekked
View Stats   - Change Class 

Equip/Remove then puts the cursor where it is now, in the Right Hand/Left Hand/Bodyparts list...
Skills, change the screen to your 4 skill slots. Get Nekked removes everything, updates screen...
View Stats shows the screen without the cursor until you press a button again.
Change Class... Well, that's a screen for another day, but would putting it here be okay?

Secondary Gold check--good idea! (I kind of thought it was already there...?)

Battle stuff--yeah, its still all kinds of bad there, sorry. I got them flashing again at least. I just updated sprite positioning and stone tile loading as well! Stat loading is weird, an Imp just ran away from my level 1 guys and my white mage keeps getting 3 hits in. I need to deep debug all that. I don't wanna...
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

Vanya

#722
Quote from: Jiggers on October 30, 2020, 07:51:52 AM
Terrible because its a bad idea, or because it would take me so long to do it?

"Terrible" is just an exclamation I use. It;s just a Vanya-ism. lol :3
I guess right now it means "Terrible, that we always go for the bigger more complex solutions when something simpler would suffice to most people, but it's expressed in a good way."


Quote from: Jiggers on October 30, 2020, 07:51:52 AM
Coloring the numbers would be doable, though kind of annoying (maybe not as annoying as playing with the description strings more)... but its the comparing to old that I worry about. It would require... no, maybe I can simplify.

I like it just fine in the games that have such colored text.
Usually it's paired with a up or down triangle as well. Maybe just using those would work fine?


Quote from: Jiggers on October 30, 2020, 07:51:52 AM
Update stats with To Be Unequipped item.
Copy Damage, Accuracy, Critical, to tmp RAM. Do this in Bank E... don't want to touch the Update stats routine anymore.
Update stats with To Be Equipped item.
Compare Damage, Accuracy, Critical, to tmp RAM.

Huh. Brain worky somehow.  :D

Yeah... I think... think I can do that? Weapon attribute bytes are $EB, $F3. Armor is $EE, $F6... oh no.

Not messing with other routines would probably be a good idea, yes.


Quote from: Jiggers on October 30, 2020, 07:51:52 AM
The description box would need to be drawn first, but taller by 1 tile, so the equipment list can cover the top of the box. Otherwise, the box border will be green/pink as well for Damage and Defense. Is that acceptable?

Sounds fine to me.


Quote from: Jiggers on October 30, 2020, 07:51:52 AM
For removing, that's a plus for putting the To Be Unequipped item into the list. Slap a dot on there like so.



Now press A on THAT one, it compares To Be Unequipped with To Be Equipped, matches, and then the < Equipment Bag # > window asks, "Remove? OPYes   No" (I made a li'l glove.)

That way its not popping up every time you press A...?

That could work, if you want to keep things as simple as possible.



Quote from: Jiggers on October 30, 2020, 07:51:52 AM
Ahhh, writing posts while the other person edits, ain't it just the way.

This is the way.


Quote from: Jiggers on October 30, 2020, 07:51:52 AM
I actually kinda dig that description-box-menu thing. You don't think that would mess with flow too much? Maybe its my FF14 experience kicking in again, but I just realized I've been striving to cut down the number of prompts as much as possible. The menus can be overwhelmingly ridiculous. When I'm in the Zone I don't want to be trifled with by Yesses and Nos. Except for the battle confirmation, which I need because I screw up the 4th character's turn so much.

Cutting down on the number prompts is usually a good idea in game design in general.

The description-box-menu thingy would basically add one step to the "Equipment Bag X" screen in much the same way as adding the Yes/No prompt except it would be upfront instead and would always have that extra step.


Quote from: Jiggers on October 30, 2020, 07:51:52 AM
Or would the menu be in the first Equip screen?

This is the second option. It would work kinda like the Magic screen does now, but just arranged differently.

Right now the Magic screen has a title bar menu that lets you cast learn or forget.
So the flow is pretty straight forward.
'CAST' goes to the spell list, then from there you select a spell and go to the casting screen.
'LEARN' goes to the magic inventory, there you choose a spell to "equip".
'FORGET' goes to the spell list, then you pick a spell to remove.

The description-box-menu for the Equip screen would work similarly.
So the flow should be about the same.


Quote from: Jiggers on October 30, 2020, 07:51:52 AM
Equip        - Remove
Skills       - Get Nekked
View Stats   - Change Class 

Equip/Remove then puts the cursor where it is now, in the Right Hand/Left Hand/Bodyparts list...
Skills, change the screen to your 4 skill slots. Get Nekked removes everything, updates screen...
View Stats shows the screen without the cursor until you press a button again.
Change Class... Well, that's a screen for another day, but would putting it here be okay?

'EQUIP' goes to the equipment list like now, yes. Then it takes you to the equipment bag when you pick an equipment slot.
'REMOVE' also goes to the equipment list, but now pressing 'A' would simply remove gear if there is any in the selected slot. No need for a prompt since you needed to specifically choose this command to get here in the first place.
'GET NEKKED' should probably open a Yes/No prompt, but otherwise goes no further anyway.

I don't think view stats is really needed as long as as you erase the menu and display the stats when it's relevant to do so like when you go to the equipment list.

And the class and skills stuff is definitely a screen for another day.
I think it should be its own menu entirely.


Quote from: Jiggers on October 30, 2020, 07:51:52 AM
Secondary Gold check--good idea! (I kind of thought it was already there...?)

Yes!


Quote from: Jiggers on October 30, 2020, 07:51:52 AM
Battle stuff--yeah, its still all kinds of bad there, sorry. I got them flashing again at least. I just updated sprite positioning and stone tile loading as well! Stat loading is weird, an Imp just ran away from my level 1 guys and my white mage keeps getting 3 hits in. I need to deep debug all that. I don't wanna...

Lol.




EDIT: I keep forgetting to mention this.
Can the equipment bag be modified to list our inventory sequentially instead of hard-coding each item into a specific slot?

Jiggers

#723
Done any thinking on how a class/skill menu would look? If I'm going to be digging around in menu code again, I should start working on that too. I don't want to re-arrange the main menu any further, so I think replacing STATUS with SKILL or CLASS would work... There's unused space for sure.

Could go back to squishing up the stat words if needed. Str., Agil, Int., Vit., Luck, Soul, Dmg., Acc., Crit, Def., Evas, MgDf. Name + Class with a space between is 15 tiles long, out of 30 tiles if the text hugs the box borders. Main stat+## would be 7 including a space, substats would be 8.

If it were up to me, I'd move the sprite to sit above the level #, aligned with name and class. Shift the whole name/class/level/exp/next up one, put a box around it, maybe move it to the top right corner. Put another one in the top left with:
!COMMANDS
ABILITIES
CHANGE JOB
JOB LEVEL
VIEW STATS

And the bottom box could display info for each thing. VIEW STATS would do as it does now. JOB LEVEL would show unlockable abilities and commands, along with Job level and Exp. CHANGE JOB would convert the bottom box to a swappable list -- job on the first row, with the < arrows >, and any pertinent information on the 5 lines below; descriptive text, or base stats, or what have you... that's all I got for now.

Lots of things we could do!




Tonight's update tweaked the shop cursor/attribute bar updating speed. Shop logic itself shouldn't change much, but i may have missed a variable or two updating. Let me know if anything breaks.

I think the only way I can get this faster, is if there's a Buy Mode toggle which knows not to update the inventory text if its been written. Which... sounds good to me, let me see if I can do that... Nope, it has to update amounts, and its not worth it to not update the text if you're backing out of buying...

Can the equipment bag be modified to list our inventory sequentially instead of hard-coding each item into a specific slot?

I... really hope I have that capability now. I'll keep it in mind.




__CAST__LEARN__FORGET
_EQUIP__REMOVE__EMPTY

Equip with only one space should be okay, as the cursor would be on the box border. Or it could be WEAR, and fit perfectly.




Some screenshots posted up in the Discord if you can check them, Vanya. I'm starting to think maybe something else would be better. Need convincing I'm on the right track. With the submenu, pressing left/right to switch characters won't be possible... Up/Down would feel weird, or would it? Select to scroll through, or Start to scroll through, the way party leader does?
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

Vanya

Sorry I never got back to you on this! Last couple of days were very hectic with finishing up the diorama base for my girlfriend's Spooky Town display. I was exhausted after completing that project.

Any who, it sounds like what you'd do for the status screen is something somewhat like FF6.


FF5 also has a similar set up.

FF6 doesn't have classes, but one character has the ability to swap around his commands in the status screen. I actually tried making an ASM hack for FF6 once so that all characters could change their commands, but I got stuck on some bugs and tried to bite off more than I could chew.

So given that FF6 has a similar arrangement I think moving the class change and commands to the status screen would work just fine.

For the status screen menu I would have:
JOB
COMMAND
ABILITY

I'd prefer it be on the right, tho.

If we do shrink the stat names I prefer going with D&D conventions:
Strength -> STR
Agility -> AGI
Intellect -> INT
Vitality -> CON (as in constitution)
Speed -> DEX (as in dexterity)(what did speed do again? I know we changed it from luck.)
Morale -> BRV (as in bravery)(I don't don't remember what this does either. Does bravery fit for it?)
Damage -> ATK (as in attack, which is what it originally was in Japanese.)
Accuracy -> HIT (as in hit rate, which I think is what it was in Japanese, too.)
Critical -> CRT
Defense -> DEF
Evasion -> EVA
M. Resist -> RES

Only other thing I would do is to include job level in there.
I'll have to think on it a bit more and get back to you.
I want to see how these are all handled in FF3, 4, 5, & 6.




Coolio. I'll check things out and report back.




The D&D geek in me wants to have it read __DON__DOFF__DISROBE, but...

How about __EQUIP__REMOVE__BARE ?




I'm still leaning toward changing everything to switch characters with select.
But if the submenu is arranged vertically, then we can do switching with left/right, no?
Either way I'll check those pics out for now.

Jiggers

Still alive!

In the last month I've been puttering away at updating the music driver.

I'm wondering if I have this right, for how FF1 works out the speed of moving through volume envelopes.

Original code for reference:
@UpdateLoop:
    LDX mu_chan              ; put current channel in X for indexing

    DEC ch_lenctr, X         ; decrement the channel's len counter
    BNE @EnvStep             ; if it's nonzero -- a note is still playing, so update the env pattern

      JSR Music_ChannelScore ; otherwise, the note is done (len expired), so do more score processing
      LDA ch_envpos, X       ; put the env position in A (expected to be there in @UpdateVol)
      JMP @UpdateVol         ;  and jump ahead

  @EnvStep:            ; if a note is still playing... update the env pattern
    LDA ch_envrate, X      ; get the envelope rate
    CLC
    ADC ch_envrem, X       ; add to it the remaining "fraction"
    STA ch_envrem, X       ; and write that back as updated fraction

    CMP #8                 ; check to see if fraction >= 8 (take another step)
    BCC @UpdateNext        ; if not, no further work to be done for envelope.  Skip ahead

      STA tmp              ; otherwise (fraction >= 8), store fraction in tmp for later
      AND #7               ; isolate just the low bits (fraciton bits)
      STA ch_envrem, X     ;  and write those back as the channel's remaining fraction

      LDA tmp              ; then get all the full value back from tmp
      LSR A                ; right shift by 3 (removing fraction)
      LSR A
      LSR A
      CLC
      ADC ch_envpos, X     ; and add that to the envelope position

    @UpdateVol:
      CMP #$20             ; check to see if the envelope position is >= $20
      BCC :+               ;  if it is...
        LDA #$1F           ;  ... cap it at $1F ($1F is maximum)

:     STA ch_envpos, X     ; write back as current env pos
      TAY                  ; then put in Y for indexing

      LDA ch_envptr, X     ; copy the channel's env pointer to tmp
      STA tmp
      LDA ch_envptr+1, X
      STA tmp+1

      LDA (tmp), Y         ; then read the env byte to output
      STA ch_vol, X        ; and record that as channel's output volume


Disch's notes and other references:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  LUT for music envelope speeds  [$B3B9 :: 0x373C9]
;;
;;    Values here are used as speeds for traversal through below envelope tables.
;;  Values are fixed point with 3 bits of fraction.  IE:  a speed of $0C would be
;;  one and a half steps through the table every frame (3 steps every two frames)
;;
;;    Note that overflow when doing math with these values is not handled by the
;;  game, so none of these values should go above %11111000.  That will ensure that
;;  the addition of the existing 'fraction' will never cause an overflow.

lut_EnvSpeeds:
  .BYTE $80,$60,$40,$30,$20,$18,$10,$0C,$08,$06,$04,$03,$02,$01,$00,$00


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  LUTs for envelope patterns  [$B3C9 :: 0x373D9]
;;
;;    These are 16 tables, each table consisting of 32 entries.  These tables
;;  represent the envelope pattern that the channel is to take every note it plays.
;;  $0F is full volume, and $00 is silence.  The speed at which the channel traverses
;;  these tables depends on their envelope rate, which is determined in part by
;;  the above lut (lut_EnvSpeeds).  Once the channel reaches the end of the table, the
;;  last entry is sustained (infinitely repeated).
;;    Note that volume/envelope is only applicable to squares, as triangle has no volume
;;  control.

lut_EnvPatterns:
  .BYTE  $0F,$0F,$0E,$0E,$0D,$0D,$0C,$0C,$0B,$0B,$0A,$0A,$09,$09,$08,$08 ; pattern $E0
  .BYTE  $07,$07,$06,$06,$05,$05,$04,$04,$03,$03,$02,$02,$01,$01,$00,$00 ;  gradual decay from F



The table I made to try and make sense of what that all actually means:
ENV SPEED (ch_envrate)
vv   ENVELOPE DONE IN...                VALUES PER FRAME
80 - 2 frames                         | 16
60 - 3 frames                         | 12
40 - 4 frames                         | 8
30 - 6 frames                         | 6
20 - 8 frames                         | 4
18 - 11 frames                        | 3
10 - 16 frames                        | 2
0C - 32 frames                        | 1, 2

                                         FRAMES PER VALUE
08 - 32 frames                        | 1
06 - 52 frames                        | 2, 2, 1
04 - 64 frames (1 second+4 frames)    | 2
03 - 83 frames                        | 3, 3, 2
02 - 128 frames (2 seconds+8 frames)  | 4
01 - 256 frames (4 seconds+16 frames) | 8
00 - never moves                      |


So with a speed of $00, it gets $80 from lut_EnvSpeeds, which results in the volume being $0F on the first frame, $07 on the second, and $00 for all frames after.

While a speed of $0D, it gets $01 from lut_EnvSpeeds, which results in the volume changing by 1 value only every 8 frames.

To save on RAM space for how all this is calculated, I tried to do something different and just set the envelope speed manually. The high bit being set decides whether or not it holds a volume for X frames, or traverses the envelope X amount each frame.

My altered code: (Lots of ANDing going on because I tried to cram as much info into every bit as I could.)
@UpdateLoop:
    TAX ; LDX mu_chan              ; put current channel in X for indexing
   
    DEC ch_notelength, X     ; decrement the channel's len counter
    BNE @EnvStep             ; if it's nonzero -- a note is still playing, so update the env pattern

      JSR Music_ChannelScore ; otherwise, the note is done (len expired), so do more score processing
      JMP @UpdateVol         ;  and jump ahead

  @EnvStep:                 ; if a note is still playing... update the env pattern
    ;; JIGS - this should save some cycles!
    CPX #CHAN_TRI
    BNE :+
        JMP @UpdateNext         ; Triangle channel does not use envelopes or volume control...
   
  : LDA ch_envelope_type, X
    BMI @XValuesPerFrame
   
  @XFramesPerValue:
    DEC ch_envelope_time, X  ; decrease the frame-count timer before the next update
    BNE @UpdateNext          ; no need to update volume yet then... so next channel!   

    LDA ch_envelope_length, X
    AND #%00111111           ; remove legato/vibrato on bits
    STA ch_envelope_time, X  ; get the length set earlier and save as the new timer
   
    LDA ch_envelope_position, X
    AND #%00111111
    CMP #%00111111           ; see if the position is at max, and if so, leave it
    BCS @UpdateNext
   
    INC ch_envelope_position, X ; else, increase it by one
    BNE @UpdateVol
   
  @XValuesPerFrame:          ; high bit is 0
    LDA ch_envelope_position, X
    AND #%11000000
    STA tmp                  ; backup these two bits
   
    LDA ch_envelope_position, X
    AND #%00111111           ; keep only the actual position bits
    CLC
    ADC ch_envelope_time, X  ; add the distance per frame
    AND #%00111111           ; capping at #63
    ORA tmp                  ; add back in the other bits
    STA ch_envelope_position, X ; and save

   @UpdateVol:
    LDA ch_envelope_position, X
    AND #%00111111
    TAY                      ; then put in Y for indexing

    LDA ch_instrument, X     ; instrument * Envelope pattern length
    AND #%00011111
    LDX #ENVELOPE_LENGTH     ; length of Envelope patterns (32)
    JSR MultiplyXA
    CLC
    ADC #<lut_EnvPatterns    ; add the ROM address of the pattern table!
    STA tmp
    TXA
    ADC #>lut_EnvPatterns
    STA tmp+1

    LDA (tmp), Y             ; then read the env byte to output


I can't tell if this works. I think I detect oddness with how instruments sound, but the other problem is that my new way of changing tempo isn't working correctly and I'm still investigating that. I'll try to figure out how to upload my changes to a fork tomorrow so folks can test it out.
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

Vanya

:D Huzzah to being alive!

This something I'm ill equipped to comment on as music is not my thing and I'm practically tone-deaf.
I'll try looking over the code for anything obvious that could be wrong.

Jiggers

#727
Thanks!

I solved the tempo problem, which was that I'd set the original Tempo values to be 1-based, but then changed the 2-byte codes to 0-based.

The other issue I hear is that long notes (notes made longer by having a $Cx rest after them I think) are restarting rather than resuming. Wondering if it has to do with how I re-arranged the updating of things with this part:

@Resume:
  ;; First, update Square 1's regs to match output music data
  ;;  The high bit of the output F-value is checked to see if the frequency has changed.
  ;;  If there was no change, the frequency should not be written again because writing
  ;;  to the last channel reg ($4003 for sq1) to change the freq resets the duty.  If
  ;;  this is done every frame, the sound would crackle something fierce.

    LDA CHAN_SQ1 + ch_freq+1     ; get high bit of output F-value
    BMI @Sq1_NoFreqChange        ; if it's set, there's no change, so skip ahead

    ORA #$80                   ; set high bit of freq to mark that it doesn't need to be updated
    STA CHAN_SQ1 + ch_freq+1   ;  anymore
    AND #$07                   ; JIGS - remove everything but frequency bits!
    STA $4003                  ; output frequency
    LDA CHAN_SQ1 + ch_freq
    STA $4002

   @Sq1_NoFreqChange:          ; if the freq is not to be changed...
    LDA CHAN_SQ1 + ch_volume   ; still update volume (same process as above)
    ORA #%00110000   
    STA $4000
    LDA #%01111111             ; and disable sweep
    STA $4001

   @Sq1_Done:

  ;; Now we update Sq2's regs.  Since Sq2 is also used for some sound effects, we need
  ;;  to skip this step if Sq2 is busy playing a sound effect.
  ;;
  ;; Square 1 is fixed to output 25% duty all the time (or 75% -- but that's audibly identical)
  ;; Square 2 on the other hand has no duty bits explicitly set, which means the envelope pattern
  ;;  can also specify any duty cycle.  If no duty bits are set in the envelope pattern, it
  ;;  would be 12.5%.  This is the case in the original game, as no duty bits in the envelope tables
  ;;  are set.

    LDA sq2_sfx         ; is sq2 currently playing sfx?
    BEQ @Sq2_Update     ;  if not, update it normally
    DEC sq2_sfx         ; otherwise dec the sfx counter
    BNE @Sq2_Done       ; if it's still not zero (still playing), skip sq2 updating completely
    ;LDA #$30
    ;STA $4004           ; JIGS - set volume to 0
    ;LDA #$80
    ;STA CHAN_SQ2 + ch_freq+1
    ;JMP @Sq2_FreqChange

    BEQ @Sq2_FreqChange ; otherwise, it's done, force an update to all sq2 regs (always branches)
                        ;   this ensures sq2 will resume playing music immediately, rather than
                        ;   waiting for the next note.
   @Sq2_Update:                 ;  if not playing a sound effect...
    LDA CHAN_SQ2 + ch_freq+1    ; check high bit of F value
    BMI @Sq2_NoFreqChange       ; if set... no freq change

   @Sq2_FreqChange:
    ORA #$80                  ; then set high bit to mark that it doesn't need updating
    STA CHAN_SQ2 + ch_freq+1  ; and write it back
    AND #$07                  ; remove high bit flag from F-value (not necessary)
    STA $4007
    LDA CHAN_SQ2 + ch_freq    ; output freq
    STA $4006

   @Sq2_NoFreqChange:
    LDA CHAN_SQ2 + ch_volume  ; get volume
    ORA #%00110000            ; disable length/decay.  Don't set any duty bits (12.5% by default)
    STA $4004                 ; output
    LDA #%01111111
    STA $4005                 ; disable sweep

   @Sq2_Done:

  ;; The same process one last time, but this time for the Triangle.
  ;;  Triangle also has the high byte of the freq as $FF if it is to be silenced.
  ;; This is probably because the triangle has no volume control and thus can't be silenced
  ;;  by just setting the volume to zero (even though that could work if coded that way -- but
  ;;  whatever).

    LDA CHAN_TRI + ch_freq+1    ; Get high byte of freq
    BMI @Tri_HighBitSet         ; if high bit of high byte set, skip ahead

    LDA #%10001111            ; otherwise, set linear counter to keep channel playing
    STA $4008                 ;  (keep it audible)
    LDA CHAN_TRI + ch_freq    ; set the freq
    STA $400A
    LDA CHAN_TRI + ch_freq+1
    STA $400B
   
    ORA #%10000000
    STA CHAN_TRI + ch_freq+1  ; then set high bit to indicate freq doesn't need updating
    JMP @CheckHush

   @Tri_HighBitSet:           ; if high bit was set
    CMP #$FF                  ;  see if high byte = $FF
    BNE @CheckHush            ; if not, do nothing
    LDA #%10000000            ;  otherwise, silence the tri by setting the linear counter reload
    STA $4008                 ;  to zero.  This will silence the tri on the next linear counter clock.
   
   @CheckHush:
    LDA MenuHush
    BNE @HushTri              ; hush triangle if in menu
    LDA TriangleHush
    BPL @CheckUnhush          ; skip hush triangle if high bit not set (song is not forcing half volume)
   
   @HushTri:
    JSR HushTriangle       
   
   @CheckUnhush:   
    LDA MenuHush             
    BNE @Tri_Done              ; skip unhushing if in menu
    LDA TriangleHush
    BMI @Tri_Done              ; skip unhushing if high bit set
   
    JSR UnhushTriangle

   @Tri_Done:

  ;; JIGS - here we do MMC5 square stuff!

    LDA CHAN_SQ3 + ch_freq+1     ; get high bit of output F-value
    BMI @Sq3_NoFreqChange        ; if it's set, there's no change, so skip ahead

    ORA #$80                   ; set high bit of freq to mark that it doesn't need to be updated
    STA CHAN_SQ3 + ch_freq+1   ;  anymore
    AND #$07
    STA $5003                    ; output frequency
    LDA CHAN_SQ3 + ch_freq
    STA $5002

   @Sq3_NoFreqChange:          ; if the freq is not to be changed...
    LDA CHAN_SQ3 + ch_volume   ; get the output volume
    ORA #%00110000             ;  set bits to disable length and decay, do not set duty
    STA $5000                  ;  output the volume/duty

   @Sq3_Done:
    LDA CHAN_SQ4 + ch_freq+1     ; get high bit of output F-value
    BMI @Sq4_NoFreqChange        ; if it's set, there's no change, so skip ahead

    ORA #$80                   ; set high bit of freq to mark that it doesn't need to be updated
    STA CHAN_SQ4 + ch_freq+1   ;  anymore
    AND #$07
    STA $5007                  ; output frequency
    LDA CHAN_SQ4 + ch_freq
    STA $5006

   @Sq4_NoFreqChange:          ; if the freq is not to be changed...
    LDA CHAN_SQ4 + ch_volume   ; get the output volume
    ORA #%00110000             ;  set bits to disable length and decay, do not set duty
    STA $5004                  ;  output the volume/duty


The main change is doing the opposite half of the frequency first, to save a few cycles on checking the high bit--since the value is already in A, why throw it away and load another one, then go back to the one that was just loaded, right? Since the tones sound right, I don't think that's the problem. I think the high bit, the "update this note's frequency" thing, is getting toggled somehow... That will be my next debug adventure.

Update on the debug adventure: Rests aren't making notes reset, but I'm noticing in the Prelude, the melody on Square 3, the volume keeps flipping to $xC pretty often. Envelope is #7, which ends on a $03, then Envelope #8 starts with $0C, so...

    LDA ch_envelope_position, X
    AND #%00111111
    CMP #%00111111           ; see if the position is at max, and if so, leave it
    BCS @UpdateNext

    INC ch_envelope_position, X ; else, increase it by one
    BNE @UpdateVol


This must not be working as intended...? Should that be a BEQ instead of a BCS? It sounds a little cleaner, but its not the same...

... oh. I'm an idiot.

#$3F is double the size of the envelopes. Because now it CAN be, but the envelopes aren't yet. So it is going through two envelopes. Yeah.

Now to find out why the echo track is so far ahead/behind...

GitHub branch for current music driver shenanigans: https://github.com/JiggeryPonkery/FF1-MMC5/tree/Music-Driver-Updates
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

Jiggers

#728
https://cdn.discordapp.com/attachments/814600678055608351/957533355879055400/FinalFantasyBattle.mp3

As I posted in the NES Development Discord server...
Going through the score of FF1, I noticed a lot of redudant octave-set bytes. The Prelude, the healing SFX, and the Battle theme are the only affected songs. Since I added the lowest octave into the game's music driver, this is my attempt to set the octaves correctly for the Battle theme... I may have made a mistake or two, but I tried to follow the logic of the composition as well as assuming that no octave-set byte was placed redundantly.

The top part is the new version, bottom is how the original was.

(slight mistake in that image, the two boops in the middle of bar 15 should match the ones after that slide down in bar 12--image was just how I was trying to visualize the nonsense going on with the score code.)

https://cdn.discordapp.com/attachments/763975597906329603/957392521309339718/FinalFantasy.mp3

Also fixed timing errors I had with the Prelude! This also shows the fixed bass octave notes off.

I think all the current bugs with the music driver tweaks have been squished and the songs should all sound as intended once again. Mostly. Due to the nature of the fractions with the envelope speeds, no more does it jump two bytes of envelope data, two bytes of envelope data, THREE bytes of envelope data... It will now always be two or three for those edge cases.

So next up, I can finally start adding in wobbles and legato! I have a whole 26 bits of data PER CHANNEL to play around with! Not counting all the bytes the triangle never uses for volume and envelope junk! Little weasel in a candy vole shop am I.
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

Vanya