News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: FF1 MMC5 Disassembly Updates  (Read 47789 times)

Vanya

  • Hero Member
  • *****
  • Posts: 1443
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #220 on: April 18, 2019, 01:03:34 am »
Quote
...shop logic stuff...

Looks pretty good.
The only thing I would suggest is to make sure that the quantities under each item in the list reflects how many you have total between inventory and equipped stuff.
Oh, also make sure the shop list redrawn every time you gain an item.


Quote
...trait system...

That sounds really good.
The names and exact effects need some work, but that is actually a really good idea.
Kinda like a precursor to the support abilities in later games.


Quote
Speaking of intelligence... anyone wanna try adding that in to the battle code?

I volunteer. Haven't done ASM in a while, so I could use the practice.
I really want that feature, too.

Come to think of it, are there any of AstralEsper's / Anomie's bug fixes or enhancements already incorporated into the disassembly yet?

Jiggers

  • Full Member
  • ***
  • Posts: 207
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #221 on: April 18, 2019, 01:36:37 am »
Not sure if the list I have is complete, but here are the bugs I haven't fixed (yet):
* The airship can land on the caravan.
* HEL2 effectivity should be 0x18. Or should it, now that we have heal-doubling
  in the INT patch?

* In the Ice Cave, you can use WARP to get back up holes.
* Poison doesn't work on enemies.
* If you stand on a door, enter a menu, exit the menu, then step down, the door
  will usually end up elsewhere on the screen.
* The Fire and Wind altars say "Nothing here" instead of their proper message.
* There are a number of sprites that start out in non-walkable areas.
  Sometimes, they can even end up outside the bounds of the dungeons.
* If you enter a map (by teleporting, exiting a shop, or exiting a menu) in the
  top/left 7 rows/columns, sprites will walk through you until you step
  verically/horizontally. (JiggersNote: I did make it so that exiting a shop will put you 1 tile under the door, so I've seen this happen a lot lately.)

Not sure about these bugs, might have fixed them with all my fiddling:
* Enemies always wake from sleep.
* Target-dark and evade should not be applied when the target is asleep/stopped.
* Hit% should be applied even if asleep.
* Enemy-cast all-allies spells (e.g. AFIR) don't hit the caster.
* Hit chance should not clamped until after evade is subtracted.
* Spells causing multiple status ailments will claim "Ineffective" if the
  target has any of the ailments (all will still be applied though). (JiggersNote: Is it normal for a player character to have more than one status ailment at a time? If so, I plan on re-sorting which ailment bit is which, so that ones like stun and sleep will have priority to display their icon over dark/mute.)

These should definitely be checked out:
* LOK2 should use effect 0E instead of 10.
* LOCK (and fixed LOK2) always misses.
* TMPR should probably be using effect 0B instead of 0D.

Disch might have fixed this one, or I might have fixed it from his initial disassembly notes:
* In the 2-large-6-small enemy formation, the game shifts one too far so the
  third enemy uses the palette selection bit for the second enemy.

In the Enhancements file, I'd like to see these:
* Make CONF do something vaguely resembling an actual attack (can miss, and
  damage [D..2D]-A).
* Potions would be easier to use if they stayed on the "use" screen (JiggersNote: Forget if I did this or not.)
* This rearranges the teleport coordinate tables to allow for more of each
  kind. This has no effect on the actual game, but might be useful for a hack.
* Replace the crappy PRNG with a slightly better one
* This creates a magic Effect for a "RUN" spell, and assigns it to EXIT.
* Allow all battle numbers except 0x80 to be used as spiked squares, instead of
  only 00-7f.

There's two mentions of nerfing the BlackBelt, I don't know if people find that necessary or not.

Looks pretty good.
The only thing I would suggest is to make sure that the quantities under each item in the list reflects how many you have total between inventory and equipped stuff.
Oh, also make sure the shop list redrawn every time you gain an item.

Pretty sure it does that now for all the shops... Good catch on the re-drawing to update inventory count, changed my logic map file to remember that.

Also, I could possibly cap gold at 9,999,999? It only needs 7 tiles to display for one more byte of RAM (which is there is lots of still.) That fits in both the menu and shop if people are fine with the number snuggling up to the G.
I know exactly what I'm doing. I just don't know what effect it's going to have.

Vanya

  • Hero Member
  • *****
  • Posts: 1443
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #222 on: April 18, 2019, 06:10:55 am »
Coolio.
I'll start a branch just for the bug fix and enhancement stuff.
Fortunately the notes Astral Esper and Anomie made for their work is very comprehensive.

One thing, tho. I don't think that being able to warp back up a hole in the Ice Cavern is really a bug.
I mean you are using magic to teleport.

Raising max gold sounds fine to me.
It could almost even be taken as a fun challenge to try to reach it.



Here's my take on the content of the traits system idea:
Code: [Select]
(Armor refers to defensive equipment for the Body slot, not all defensive gear in general.)
(Use refers to equipping gear in normal equipment slots, not to using them as battle items.)

Fighter:
> Swordsman
  - Attack and Hit% bonus when using swords.
  - Evade +10%, minimum +1.
  - Armor use reduced to same as Thief.
> Barbarian
  - Attack and Hit% bonus when using axes.
  - HP +10%, minimum +1.
  - Armor use reduced to same as Red Mage.
> Cataphract
  - Attack and Hit% bonus when using hammers.
  - Defense +10%, minimum +1.
  - Cannot use swords.

Thief:
> Brigand
  - Chance to steal gil as part of using the Fight command.
  - Axe and hammer use increased to same as Fighter.
  - Effect of using the Hide command reduced to same as all other jobs.
> Partisan
  - Auto-hide at start of battle.
  - Chance to auto-hide after taking damage.
  - Chance to auto-hide when landing a critical hit instead of stealing gil.
> Scout
  - Increased chance for party to get a surprise attack on the enemy.
  - Agility and Luck +5%, minimum +1.
  - No special effect when landing a critical hit.

Monk:
> Brawler
  - Weapons do not negate bare-handed attack bonus.
  - Armor use increased to same as Fighter.
  - No unarmored defense bonus.
> Pugilist
  - Chance to counter attack when hit.
  - Armor use increased to same as Thief; glove use increased to same as Fighter.
  - Inverse of glove weight added to attack.
  - No unarmored defense bonus.
> Mystic
  - Fight command treated as having hurt flag vs unknown, undead, were, mage, and regenerative types.
  - Armor use increased to same as Red Mage.
  - No unarmored defense bonus.

Red Mage:
> Magus
  - Chance to attack twice when using the Fight command.
  - Shield and glove use increased to same as Fighter.
  - Can only learn spells up to level 4.
> Battle Mage
  - Increased potency of attack spells.
  - Can equip Black Robe.
  - Weapon use reduced to same as Black Mage.
> Physic Mage
  - Increased potency of healing spells.
  - Can equip White Robe.
  - Weapon use reduced to same as White Mage.

White Mage:
> Chaplain
  - Axe and staff use increased to same as Fighter.
  - Armor, shield, and glove use increased to same as Fighter.
  - Decreased potency of healing spells.
> Enchanter
  - Increased potency of status spells.
  - Armor use increased to same as Red Mage.
  - Cannot use hammers.
  - Decreased potency of healing spells.
> Holy Mage
  - Chance to add regen effect as part of casting healing spells.
  - Harm spells can effect all enemies regardless of type.
  - Decreased potency of harm spells.
  - Cannot use hammers.
  - Decreased potency of status spells.

Black Mage:
> War Mage
  - Attack spells that target single enemies instead target all enemies.
  - Decreased potency of attack spells that normally target single enemies.
  - Sword use increased to same as Red Mage.
> Duelist
  - Attack spells that target all enemies instead target single enemies.
  - Increased potency of attack spells that normally target all enemies.
  - Cannot use knives.
  - Decreased potency of status spells.
> Hex Mage
  - Non-death status spells that target single enemies instead target all enemies.
  - Increased potency of non-death status spells.
  - Cannot use staves.
  - Decreased potency of attack spells.
« Last Edit: April 19, 2019, 12:09:26 pm by Vanya »

Jiggers

  • Full Member
  • ***
  • Posts: 207
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #223 on: April 21, 2019, 04:16:10 pm »
Yeah, warping should be allowed! Unless it somehow breaks the game? Maybe all the teleports going up and down floors does something weird with the map data on the stack and warping back will screw up?

So I thought gold was only 2 bytes, but its 3 bytes, so the max gold is... 3F 42 3F? Or 999,999. Even though 3F 42 3F should be 4,145,727...? The game does weird things when you try to display 999,999 gold in the menu.

Anyway, gold is fine then. I thought the max was way lower and was confused. Bumping it up to 9,999,999 will involve making a new thing to display 7 digit numbers and I don't wanna.

Your trait things are lookin' good! I might disagree on a few things here and there, but no reason to argue over it until there's actual code in place to make any of it work. XD Right now there's 3 free bytes in character stats... to make 4, I could combine ch_weaponelement and ch_weaponcategory to use high/low bytes? There's only 8 elements and 8 categories, after all...

I tweaked the echo a bit more as well. Took out all the square 2 echo tracks, and shortened the delay on some songs. Not uploaded yet, though.

Update: Pushed my changes to various things. Shops still buggy, haven't started that yet.
« Last Edit: April 21, 2019, 06:11:18 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

Disch

  • Hero Member
  • *****
  • Posts: 2710
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #224 on: April 21, 2019, 05:33:51 pm »
Disch might have fixed this one, or I might have fixed it from his initial disassembly notes:
* In the 2-large-6-small enemy formation, the game shifts one too far so the
  third enemy uses the palette selection bit for the second enemy.

I pretty much ripped out all of that code and rewrote it when moving the enemy formations.  So yeah that bug should be fixed.

EDIT:  Or did I?  I forget how I actually am getting the palette assignment for the enemy.  Lemme have another look to make sure.

EDIT 2:  Okay, I didn't fix that.  The palette assignments were previously prepped by the time my new code runs, so the bug would have happened before then.  HOWEVER it looks like Jiggers fixed it before I got there.   :)
« Last Edit: April 21, 2019, 05:56:13 pm by Disch »

Jiggers

  • Full Member
  • ***
  • Posts: 207
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #225 on: April 22, 2019, 12:27:19 am »
'Course I only fixed it 'cos you pointed it out...!

Working on the shops, I can't test this yet, but does the concept sound right?

Code: [Select]
ShopBuy:
    JSR LoadShopInventory
   
    LDX shop_type
    LDA lut_ShopWhatWant, X
    JSR DrawShopDialogueBox     ; "what would you like" dialogue (different depending on shop type)
    LDA #0
    STA cursor
   
    JSR ShopSelectItem_Buy      ; let them choose an item from the shop inventory (fills str_buf with item IDs and everything!)
    BCS RestartShopLoop         ; if they pressed B, restart the loop
   
Shop_CheckInventory:
    LDX cursor
    LDA item_box, X             ; get chosen item ID
    STA shop_curitem            ; save it
   
    LDA #13
    JSR MultiplyXA              ; multiply cursor position by each item's str_buf length
    TAX
   
    LDA shop_type
    CMP #2                      ; if its below 2, its 0, weapons, or 1, armor
    BCC @CheckEquipment
    CMP #4                      ; if its below 4, its 3, black magic, or 2, white magic
    BCC @CheckMagic             ; it can't be inn or clinic, so its an item shop
   
   @CheckItems:
    LDA #99
    STA shop_amount_max
    LDA str_buf+$46, X           ;
    CMP #$FF                     ; if this position in the string buffer is #$FF
    BEQ ShopSelectAmount         ; then we know the player has less than 10 of this item, so go buy more
    CMP #$89                     ; otherwise its the 1s, and need to compare against the tile ID of the number 9
    BCC ShopSelectAmount         ; and if its less than that, there's room for more
    LDA str_buf+$45, X           ; else, check the 10s position
    CMP #$89                     ; again, against the tile ID for the number 9
    BCC ShopSelectAmount         ; and if its less, there's room for more
    JMP :+
   
   @CheckEquipment:
    LDA #16
    STA shop_amount_max     
    LDA str_buf+$46, X           
    CMP #$FF                     
    BEQ ShopSelectAmount         
    CMP #$86                     ; otherwise its the 1s, and need to compare against the tile ID of the number 6
    BCC ShopSelectAmount         ; and if its less than that, there's room for more; no need to check the 10s position?
 :  LDA #$13                     ; load up "you can't carry any more" string ID
    JMP @DrawDialogue_AndReturn  ; print it and return   

   @CheckMagic:
    LDA #4
    STA shop_amount_max
    LDA str_buf+$45, X           ; for magic, much easier
    CMP #$84
    BCC ShopSelectAmount
    LDA #$14                    ; "That spell is out of stock"

   @DrawDialogue_AndReturn:   
    JSR DrawShopDialogueBox   
    JMP ShopBuy

I updated the code in ShopSelectItem_Buy (previously named Shop Select Buy Item) to work with magic, as well as items and equipment. For each type, it checks players as well for equipped/learned things. So rather than do all that AGAIN here, I figured the best way to let the game know what the limit to allow the player to buy is, is to snag the number they have ... from ... the ... shop list itself... damn.

I still need to actually convert it to a single byte to subtract it from shop_amount_max!

Really not sure how to do that. So str_buf+$45, X is the 1s column if they have less than 10, or the 10s column if they have more, and str_buf+$46, X can be $FF if they have less than 10, or is the 1s column if they have more. How would you even organize that, then grab both numbers and squeeze them into one!

Update: Oh, oh, maybe like this?

Code: [Select]
ShopConvertAmount: 
    LDA #0
    STA shop_amount_high
   
    LDA str_buf+$46, X   
    CMP #$FF
    BEQ @SingleDigit
   
    SEC
    SBC #$80            ; convert from tile ID to byte
    LDX #10             ; multiply by $0A to convert to hex tens column
    JSR MultiplyXA
    STA shop_amount_high     
   
   @SingleDigit:
    LDA str_buf+$45, X     
    SEC
    SBC #$80
    CLC
    ADC shop_amount_high
    STA shop_amount
   
    LDA shop_amount_max
    SEC
    SBC shop_amount
    STA shop_amount_max
    RTS

Update 2: And with that figured out (hopefully), I managed to condense it all down to this:

Code: [Select]
ShopBuy:
    JSR LoadShopInventory
   
    LDX shop_type
    LDA lut_ShopMaxAmount       ; gets either #99, #16, or #4 depending on shop type
    STA shop_amount_max
   
    LDA lut_ShopWhatWant, X
    JSR DrawShopDialogueBox     ; "what would you like" dialogue (different depending on shop type)
    LDA #0
    STA cursor
   
    JSR ShopSelectItem_Buy      ; let them choose an item from the shop inventory (fills str_buf with item IDs and everything!)
    BCS RestartShopLoop         ; if they pressed B, restart the loop
   
Shop_CheckInventory:
    LDX cursor
    LDA item_box, X             ; get chosen item ID
    STA shop_curitem            ; save it
   
    LDA #13
    JSR MultiplyXA              ; multiply cursor position by each item's str_buf length
    TAY
   
    LDA #0
    STA shop_amount_high
   
    LDA str_buf+$46, Y   
    CMP #$FF
    BEQ @SingleDigit
   
    SEC
    SBC #$80                    ; convert from tile ID to byte
    LDX #10                     ; multiply by $0A to convert to hex tens column
    JSR MultiplyXA
    STA shop_amount_high     
   
   @SingleDigit:
    LDA str_buf+$45, Y     
    SEC
    SBC #$80                    ; convert from tile ID to byte
    CLC 
    ADC shop_amount_high        ; add in 0 or tens column
    STA shop_amount
   
    LDA shop_amount_max         ; get max
    STA tmp                     ; store in tmp
    SEC
    SBC shop_amount             ; subtract total in inventory/on characters
    STA shop_amount_max         ; save as new max

    CMP tmp                     ; compare to old max
    BNE ShopSelectAmount        ; if its not maxed out, go buy more
   
    LDA shop_type               ; get shop type again
    CMP #2
    BEQ @Scrolls                ; if its 2 or 3, its a magic shop
    CMP #3
    BEQ @Scrolls
   
    LDA #$13                     ; load up "you can't carry any more" string ID
    JMP @DrawDialogue_AndReturn  ; print it and return   

   @Scrolls
    LDA #$14                     ; "That spell is out of stock"

   @DrawDialogue_AndReturn:   
    JSR DrawShopDialogueBox   
    JMP ShopBuy

Hoping the BNEs and all that is correct. Without being able to test this all yet, I can only go by what I think might be right.

Pushed what I got so far so people can check it out if they want. What's currently working is bugged and I don't know how yet, but its 4 AM so I can't figure it out. I have 21 heals, but then in RAM it says I got 12, and sets the max to buy to 4. Pures meanwhile, it lets me go up to ... a lot (NO is displayed in the numbers)... weird stuff like that.

Next Day update:

Got buying working in item shops. Working on magic and equipment shops displaying the right amounts now.

To get equipment displaying right, I'll have to again change how armor is equipped. Instead of storing them in ch_stats as $1-$41, it will be $41-$81. So if you want your save files to work properly after this, add $40 to your armor slots!

Otherwise, the game is checking to see if I've got a rapier equipped... but it will count iron armor as a rapier, too.

BIG UPDATE!:

Buying now works for all shop types? Only standard buying so far; equipment shops will not yet allow equipping in the shop just yet! Its coming!

All the shops should display the proper amount in inventory now--PROVIDED you updated your save files as I mentioned!

Selling does not work yet, it will just exit. I haven't tested manually pressing A on things like Exit yet.

Changes are pushed to the Jiggers'-Ponkery branch!

Midnight EST update:

Equipping in shops should work now. Sensing there might be some wonkiness with the messaging and boxes refreshing at the right times. Let me know if any of it feels awkward? Like, to me, pressing cancel at "X gold, okay?", I think it should show "Eh, alright then, anything else?"--but then still allow to select things to buy... but then pressing B then to go back to Buy/Sell/Exit--isn't that awkward? I d'nno...
« Last Edit: April 22, 2019, 11:54:31 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

Vanya

  • Hero Member
  • *****
  • Posts: 1443
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #226 on: April 23, 2019, 11:47:20 am »
Seems good so far except for one thing.
When I buy multiple items and then choose to equip it now, it equips one buy the other one is not added to inventory. So one is lost.

Also, you might want to either refresh or un-draw the shop list as the final step of any transaction.
Right now the list does not update after buying or selling resulting in wrong inventory info remaining on the screen.
That could confuse some players.

Music sounds pretty damn fine.
The new Marsh Cave seems a bit too 'noisy' to me, though. Maybe tone down it's reverb a tad?

Oh, and Armor names are not displayed correctly in battle. I presume that is because of the change to how armor is handled.

Jiggers

  • Full Member
  • ***
  • Posts: 207
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #227 on: April 23, 2019, 07:44:05 pm »
Oops, its only supposed to ask if you want to equip if you're buying one. Fixed that.

Marsh Cave (New) was bugged when I was adding the echo tracks to begin with, so any echo you were hearing before was just the way I composed the song originally... I thought it sounded dry compared to the rest of the songs now. It is a pretty busy song, with the bassline doubled up with square AND triangle... All I can do to have the echo there and not as strong is to halve the volume again. So I did that!

I forgot to actually reference the shop logic layout I made while doing all this... I'll go through it again and tweak stuff once everything actually works.

Fixed the armor thing! Just by taking out code; love it when that's the solution. XD

Got a question before I update the changes though:

Code: [Select]
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Add GP To Party  [$DDEA :: 0x3DDFA]
;;
;;  IN:  tmp - tmp+2 = GP to give to party
;;
;;  BUGGED -- theoretically, it is possible for this routine to allow
;;   you to go over the maximum ammount of gold if you add a large enough number.
;;
;;     After CMPing the high byte of your gold against the maximum, it
;;  only does a BCC (which is only a less than check).  It proceeds to check the middle
;;  bytes EVEN IF the high byte of gold is GREATER than the high byte of the max.  This
;;  means that numbers such as 1065535 will not appear to be over the maximum when, in
;;  fact, they are.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;

AddGPToParty:
    LDA gold        ; Add the 3 bytes of GP to the
    CLC             ;  party's gold total
    ADC tmp
    STA gold
    LDA gold+1
    ADC tmp+1
    STA gold+1
    LDA gold+2
    ADC tmp+2
    STA gold+2

    CMP #^1000000   ; see if high byte is over maximum
    BCC @Exit       ; if gold_high < max_high, exit

    LDA gold+1
    CMP #>1000000   ; check middle bytes
    BCC @Exit       ; if gold < max, exit
    BEQ @CheckLow   ; if gold = max, check low bytes
    BCS @Max        ; if gold > max, over maximum

  @CheckLow:
    LDA gold
    CMP #<1000000   ; check low bytes
    BCC @Exit       ; if gold < max, exit

  @Max:
    LDA #<999999    ; replace gold with maximum
    STA gold
    LDA #>999999
    STA gold+1
    LDA #^999999
    STA gold+2

  @Exit:
    RTS

How can I fix the potential issue here? I'm not really sure what's happening when its comparing with such big numbers.

I need to figure out how to use a version of this to make sure you can't go over the limit while selling in shops. gold + shop_curprice, save as tmp, C set if successful, clear if not, that sorta thing...

Also--when buying in shops:

Code: [Select]
   LDA gold
    SEC
    SBC shop_curprice         ; subtract low byte
    STA gold

    LDA gold+1
    SBC shop_curprice+1       ; mid byte
    STA gold+1

    LDA gold+2
    SBC shop_curprice+2       ;; JIGS - hope this will work...
    ;SBC #0                    ; and get borrow from high byte
    STA gold+2

Is the carry ever going to cause an issue? shop_curprice+3 exists, but isn't ever used except for the multiplication routines...
I know exactly what I'm doing. I just don't know what effect it's going to have.

Disch

  • Hero Member
  • *****
  • Posts: 2710
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #228 on: April 23, 2019, 07:58:01 pm »
Quote
Is the carry ever going to cause an issue

Carry will only matter (be clear) if they are spending more than they have (shop_curprice > gold) -- which should never happen since presumably you're checking for that long before this code runs.

So... no.  It won't be an issue.

EDIT:  I'm looking at the comparison code now.  Will edit again briefly.

EDIT 2:  Took me a minute to understand the bug in the comment but I see it now.
See how the middle byte is doing a BCC/BEQ/BCS but the high byte is only doing a BCC?  This means that once high_gold >= high_max, it treats it as high_gold = high_max and compares the middle byte (even though when it's greater, it shouldn't).

EXAMPLE

Maximum gold is 1000000.  In hex that is $0F4240

If the party has, say $100000 gold (1048576), it will compare the high bytes ($10 vs $0F) to see that the gold is NOT less than the max, then will proceed to check the middle bytes ($00 vs $42) to see that it IS less than the max, and that will "trick" the routine into thinking the gold is below the max, even though it is over it.

This means that adding any amount of gold over 48577 with this routine has potential to allow the party to exceed the maximum gold.

This can be fixed by doing the full proper comparisons for the high byte, which I do here with 3 added lines:

Code: [Select]
AddGPToParty:
    LDA gold        ; Add the 3 bytes of GP to the
    CLC             ;  party's gold total
    ADC tmp
    STA gold
    LDA gold+1
    ADC tmp+1
    STA gold+1
    LDA gold+2
    ADC tmp+2
    STA gold+2
   
    CMP #^1000000   ; see if high byte is over maximum
    BCC @Exit       ; if gold_high < max_high, exit
    BEQ @CheckMid   ; high bytes are equal -- need to compare middle bytes   !!! added this line
    BCS @Max        ; gold_high > max_high, we're over the max               !!! added this line

  @CheckMid:                                                                 !!! added this line
    LDA gold+1
    CMP #>1000000   ; check middle bytes
    BCC @Exit       ; if gold < max, exit
    BEQ @CheckLow   ; if gold = max, check low bytes
    BCS @Max        ; if gold > max, over maximum

  @CheckLow:
    LDA gold
    CMP #<1000000   ; check low bytes
    BCC @Exit       ; if gold < max, exit

  @Max:
    LDA #<999999    ; replace gold with maximum
    STA gold
    LDA #>999999
    STA gold+1
    LDA #^999999
    STA gold+2

  @Exit:
    RTS
« Last Edit: April 23, 2019, 08:17:48 pm by Disch »

Jiggers

  • Full Member
  • ***
  • Posts: 207
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #229 on: April 23, 2019, 10:25:33 pm »
Nice! Thanks!

So this will work?

Code: [Select]
Shop_CanShopkeepAfford:
    LDA gold        ; Add the 3 bytes of GP to the
    CLC             ;  party's gold total
    ADC shop_curprice
    STA tmp
    LDA gold+1
    ADC shop_curprice+1
    STA tmp+1
    LDA gold+2
    ADC shop_curprice+2

    CMP #^1000000   ; see if high byte is over maximum
    BCC @Exit       ; if gold_high < max_high, exit with carry clear
    BEQ @CheckMid   ; high bytes are equal -- need to compare middle bytes   
    BCS @Exit       ; gold_high > max_high, we're over the max, with carry set               

  @CheckMid:                                                                 
    LDA tmp+1
    CMP #>1000000   ; check middle bytes
    BCC @Exit       ; if gold < max, exit with carry clear
    BEQ @CheckLow   ; if gold = max, check low bytes
    BCS @Exit       ; if gold > max, over maximum, exit with carry set

  @CheckLow:
    LDA tmp
    CMP #<1000000   ; check low bytes

  @Exit:            ; carry set; can't sell
    RTS             ; carry clear, sell is go
I know exactly what I'm doing. I just don't know what effect it's going to have.

Disch

  • Hero Member
  • *****
  • Posts: 2710
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #230 on: April 23, 2019, 10:33:32 pm »
You're losing the high byte (you never STA it to tmp+2)

Also you probably want to change '1000000' to '999999' if you're doing it this way, since C will be set when tmp=max

EDIT: Actually I might be wrong.... 1000000 might be right.  I'm confuzzled.

C=set when you CAN'T sell (gold >= 1000000)
C=clear when you CAN sell (gold < 1000000)

So... yeah.... 1000000 is right.  Sorry.


Jiggers

  • Full Member
  • ***
  • Posts: 207
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #231 on: April 24, 2019, 01:01:23 am »
No worries, I didn't even see until after you edited!

Saving tmp+2 isn't necessary here is it? Since this is just a check to make sure you can't get over the gold limit while selling. Only output that matters is C. I thought, why bother saving to tmp+2 if its only used to compare what's already in the accumulator?

I pushed more updates! Selling should now maybe work? I'm back to where I was before with the bug though. If you have 6 weapons, and sell the 6th on page 2 of the shop list, all the characters get a ! beside them. Think it might have something to do with the item_box_offset variable...

I'm also really proud and at the same time embarrassed about how I made the inventory box have empty spaces. See, I didn't like how it was drawing the whole box every time you updated--so you'd see the text vanish and re-draw from the top even if the only change was a single number. So I ended up adding a new control code to the main text drawing routine (which to be fair, needed to be done!) which just prints spaces, and then I had to figure out how to print 3 lines of 8 letter spaces while using up exactly #13 bytes--EVEN THOUGH I probably didn't need to do that, since the empty inventory slots show up after where the string buffer data needs to be in increments of #13... so I could have just done the 3 normal lines and put in some code to adjust Y for #9 instead...

Well, the good news is spaces can be print with only 2 bytes, so all those $FFs in the strings can be chopped out!

And I haven't actually tested selling besides in the weapon shop so far... time to see what breaks!

Do we want this?


All I'd have to do is change 3 $FF attribute bytes to $FA and back again. Probably almost the same code as the one that makes them change stances and draws/undraws the !s. Would be a good indicator of what's selected--then I'd work on moving the cursor to the amount while you're choosing how many of the thing to buy. I can't do that right now because the cursor has to stay on the item so the characters keep their pose while you're deciding; I'm exactly the sort of person who would forget what I'm buying while deciding how many, and having them keep their "I can equip this pose" is less helpful than "oh the thing I'm buying is green!" ... I kind of just convinced myself to do it I guess. :P

Update: Item shop seems to sell okay. Fixed a lotta bugs with things again... Magic shops now displaying the amount of spells wrong. I have 3 spells, it says I have 3 of the first, 2 of the second, 1 of the third... Will work on that tomorrow.
« Last Edit: April 24, 2019, 04:08:00 am by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

Disch

  • Hero Member
  • *****
  • Posts: 2710
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #232 on: April 24, 2019, 01:48:27 am »
Quote
Saving tmp+2 isn't necessary here is it? Since this is just a check to make sure you can't get over the gold limit while selling.

Ah.  Okay.

I got mixed up and thought this was still the 'AddGpToParty' routine so I thought that sum was eventually going to get moved to 'gold'.

But yeah if you're just doing a check, then you're right.   :thumbsup: :beer:

Jiggers

  • Full Member
  • ***
  • Posts: 207
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #233 on: April 24, 2019, 05:42:15 pm »


PRETTY MUCH DONE!!

I'm not running into any more bugs that I can find on my own...

And there's now less than 16 bytes of space left. Even after cutting out all those blank spaces in the text strings and deleting two other shop types.  :-[ But... but shops are so sleek now! And mostly snappy; there's a tiny delay when moving the cursor to the inventory when its already drawn, since its drawing over itself. It only seems like a delay because you don't see the whole box re-draw from scratch, so I had the cursor hide during this.

I think the Party Generation stuff should be moved to Bank Z with the intro, but there's so many things it uses that automatically revert to Bank E afterwards (almost everything that loads graphics!). I actually tried to move it before I started working on the shops, but ran into a bug where returning to the title screen from any of the 3 options garbled the cursor sprite and flickered the screen. Guess I'll try again after...





How about this? Could make the gold box normal blue as well. Even the title box.





Working on getting this MP box to show properly. Any better ideas for format? I tried having it like...

Code: [Select]
6 4 3 2 0 0 0 0
\ \ \ \ \ \ \ \
6 4 3 2 0 0 0 0

But it looked weird. The box has odd proportions and it would be ugly to have the list over 3 rows...

What I might do instead is see if I can replace the Cast/Learn/Forget box with something that says like... "Level X MP: #/#" that updates as you move the cursor around.
« Last Edit: April 25, 2019, 12:30:57 am by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

Vanya

  • Hero Member
  • *****
  • Posts: 1443
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #234 on: April 25, 2019, 12:21:21 am »
Damn! That is some amazing work!
Gonna give this a quick try before bed.

Having all the text boxes in the shops be the same color is much more consistent with the later games in the series, so I say go for it.
But, make sure that other colors are still supported in case someone wants to use them for their own project.
(Probably a good idea to put a nice big comment box in the code so it's easy to find, too.)

Love the highlight on the current item you're dealing with!

The formatting on the MP display looks fine to me.

Almost forgot to mention this, but my party is starting the game equipped with wooden nunchaku for armor.
« Last Edit: April 25, 2019, 12:27:46 am by Vanya »

Jiggers

  • Full Member
  • ***
  • Posts: 207
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #235 on: April 25, 2019, 12:45:05 am »
Thanks! I forgot to mention, a restriction during selling, is that it won't display your equipped gear/learned spells. Even if I made it backup what it searches for in inventory, then subtract that from the amount you can sell, that would be confusing: "I have 4 cure spells but I can only sell 3???" Even though the ! should inform them the extra one is equipped... hm...

Nunchuck armor sounds neat, though!

Update: Fixed the armor, put the MP in the title bar.

One or two last changes for the equip screen on the way, then will tackle the skipped music frames in battle.

April 25, 2019, 09:29:16 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Update to the Equipment inventory screen is live. I need some help with it, though!

Code: [Select]
    @Loop:
    JSR ClearOAM
    JSR DrawEquipInventoryCursor
    LDA cursor_change
    BEQ :+
  : JSR UpdateEquipInventoryStats
    JSR MenuFrame

    LDA joy_a
    BNE @A_Pressed            ; check to see if A pressed
    LDA joy_b
    BNE @B_Pressed            ; or B

    JSR MoveEquipInventoryCursor   ; if neither A nor B pressed, move the mode cursor
    JMP @Loop                      ; and loop until one of them is pressed

Why would the addition of UpdateEquipInventoryStats cause the cursor to go insane speeds? It no longer stops and waits for new input if you hold down a directional button...

So far the only other thing I've noticed iffy is it might not let you equip a battle item. Otherwise, it seems to work as intended so far? I still need to do more testing to make sure its behaving properly for all the different equipment slots. Update: Now works for battle items... I think. It shows "xx" when you can't equip something (either in that slot or on that class), and "--" when picking a battle item.

Also to explain what it is I DID: Instead of unequipping an item when you press A on the equip screen, it goes straight to the inventory whether you had something equipped or not. It basically unequips it, but pressing B in the inventory re-equips it. Meanwhile, the description box stays open and displays the stats for whatever the cursor is pointing at, if it exists.

I basically really like having real-time feedback now that I know how to do this. That crazy cursor speed is driving me nuts though! Whyyyy.
« Last Edit: April 25, 2019, 11:08:28 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

Disch

  • Hero Member
  • *****
  • Posts: 2710
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #236 on: April 25, 2019, 11:34:15 pm »
Only thing I can think of that would mess with the cursor speed is 'joy_prevdir' getting corrupted/overwritten.  There there some variable in UpdateEquipInventoryStats that is assigned to the same location in memory?

Jiggers

  • Full Member
  • ***
  • Posts: 207
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #237 on: April 25, 2019, 11:55:53 pm »
... so I looked, but not very hard. That is, I looked at the variables I thought I was using, and was like, nope, those aren't anywhere near it!

Then I looked at exactly that one, and... yeah. equipmenu_tmp uses the same spot. And guess what uses equipmenu_tmp? ...the silly darn Unadjust/Readjust equipment stats... that my new thing does every time you move the cursor.

Thanks. XD My brain is truly mush.

Update! Cursor is now slow. And the stats display like this:
If you CAN equip it, but not in this slot: !!
If you CAN'T equip it at all: xx
If you're in the Battle Item slots: --
If there's nothing there to equip: Your stats as they would be with no item in the slot.
If there's something there to equip: Your stats as they would be with that item in the slot.



Battle music not updating... Could it be btl_msgbuffer_loopctr with BattleDrawMessageBuffer and BattleDrawMessageBuffer_Reverse?

When it first draws the rows, it only does 9. When it draws them in reverse to undraw a box, it does 5--because it does 2 rows. So a possible fix would just be to draw the 10 rows at the start, even if the 10th is invisible...?

Another possibility is Battle_DrawMessageRow. It used to only draw $19 tiles a row, I expanded that to $20--would 7 more tiles make a difference in how long it takes, causing the a couple random frames to last longer or something?

When I fiddle with it I just make it worse. I also think I'm hearing it skip frames, not just lingering on one too long?



April 27th Bugs fixed:
* Enemies regenerate properly now
* Poison messaging no longer draws garbage after clearing boxes
* Ruby, Adamant, and ... bah, something else, can now properly be gotten from treasure chests
* Level up message box widened properly (finally!)
* Equip Inventory no longer displays random stuff after the Evasion number.


Tweaks:
* Marsh Cave has a Phoenix Down so Astos's RUB attack isn't just so unfair.
* Provoka has Eyedrops
* Crescent Lake has Wakeup bells
* Gaia has Phoenix Downs
* Caravan has X-Heals, Ethers, Elixirs, and Smokebombs

« Last Edit: April 27, 2019, 05:50:59 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

Vanya

  • Hero Member
  • *****
  • Posts: 1443
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #238 on: April 27, 2019, 08:37:27 pm »
Cool. I'll give this a go again as soon as I can.

I need to familiarize myself more with GitHub and it's lingo.
Quick questions though...
Applying changes from a branch to the master is called pushing?
And grabbing changes from the master is pulling?
Can I grab changes from other branches?
Can I grab changes from individual files within a project branch?

Disch

  • Hero Member
  • *****
  • Posts: 2710
  • NES Junkie
    • View Profile
Re: FF1 MMC5 Disassembly Updates
« Reply #239 on: April 28, 2019, 12:33:59 am »
I need to familiarize myself more with GitHub and it's lingo.

Get SmartGit.  It's free for noncommercial use and it's great.  It really simplifies a lot of it.


As for your questions....
Quote
Applying changes from a branch to the master is called pushing?
And grabbing changes from the master is pulling?

Nah, pushing/pulling doesn't really have to do with branching.


Think of it this way.  From your perspective, there are two "repositories".  One is your local machine, the other is the remote machine, or the "server" (eg: github).

When you have local changes that you want to upload to the server, that's "pushing".
When there are changes on the server that you want to bring into your local machine, that's "pulling"

Basically, pushing is uploading -- pulling is downloading.


Quote
Can I grab changes from other branches?

Yes.  The easiest way to do this is to "merge" one branch into the other.


Quote
Can I grab changes from individual files within a project branch?

Individual files?  Not really (there might be a way but it'd be very hacky and I wouldn't recommend it)

Individual commits?  Yes, it's called "cherry picking" and you'd want to use a client like SmartGit to do it otherwise it's kind of tricky.  GENERALLY you want to avoid this as much as possible and stick to merging, but sometimes you just gotta do it.



Bit more detailed overview:

The basic building block in git is the "commit".  Every time you do a commit, you are effectively creating a full backup of your code.  Git doesn't store the code in full, though, it just stores each individiual commit as a list of changes you made.  So if you only changed a few lines of text, it only needs to track those, and not EVERYTHING.  But.... it can rebuild ANYTHING by following your commit history and applying all the changes on top of each other.

A "branch" is just a collection of commits.  The branch itself doesn't have any code in it, it just has a list of commits -- the commits are what have the code.  This is why I said before that branches "don't cost anything" -- they're extremely light -- just a list of commit IDs.  At any time you have one branch "checked out" -- which just means that is the branch whose list of commits you are currently using, and who gets any new commits that you make.

But once you check out a new branch, you get a new commit list, and so all of your files will instantly change to reflect the new commit list.

When you merge branch A into branch B, you're telling git to "take all the commits in branch A that aren't already in branch B and add them to branch B"



Tips 'n' tricks:

Keep commits small-ish.  I like to think of an individual commit as one individual task I completed.... or if the task is particularly large, I break it up into several commits.  You don't have to do a commit for every single line of code you changes, but don't wait until you have like 300 lines across 20 files before you do a commit.

If you ever feel uneasy about touching something, make a branch and do it there.  Branches are cheap and isolated, and therefore act as a good, safe sandbox for you to mess around it.

Safest way to do a merge (ie:  merging a feature branch into master):
- Pull the latest master to get any changes other people have made
- Merge master into your feature branch FIRST to make sure there are no conflicts
--- If there are conflicts, fix them in the feature branch.
- THEN merge feature into master
- push master

Seems like a lot of steps and might seem overly complicated, but it becomes second nature and it makes it easier to clean up if a merge goes bad (which probably won't happen on a project like this, but on bigger projects with more developers, conflicts can get REALLY messy)

If you want to be EVEN SAFER you can make a 3rd branch off of your feature branch specifically to do the merge in:
- Create a new branch off of your feature, we'll call it fmerge
- Do all steps above, but use fmerge instead of your feature branch
- delete fmerge

This way if things get REALLY mucked up you can just toss fmerge and both your feature branch and master remain pristine.  But again, this is probably overkill for this project.