News: 11 March 2016 - Forum Rules

Author Topic: FFI (NES) Armor Indices  (Read 2327 times)

Spindaboy

  • Full Member
  • ***
  • Posts: 171
  • ただいま!
    • View Profile
    • SyndROMe Hacking
FFI (NES) Armor Indices
« on: April 28, 2021, 04:58:51 pm »
So I noticed Final Fantasy seems to determine which slots are reserved for which armor pieces (e.g. slots 1-16 are reserved for body armor) via their placement in the ROM rather than by an attribute attached to each entry (the same seemingly applies to magic). Would anyone happen to know where these values are listed in the ROM or how I might go about finding them?
« Last Edit: April 28, 2021, 07:55:06 pm by Spindaboy »

FAST6191

  • Hero Member
  • *****
  • Posts: 3517
    • View Profile
Re: FFI Armor Indices
« Reply #1 on: April 28, 2021, 06:40:52 pm »
While we are probably going to guess you mean Final Fantasy 1 (as opposed to final fight, fatal frame, fossil fighters or fatal fury), and presume the NES version as that is the main one people look at, you might wish to state that for the benefit of the people reading.

I am not entirely sure where you are heading with that. I thought at first it was an is equippable or not but I am not sure now.

On the disassembly.
https://github.com/Entroper/FF1Disassembly/tree/master/Final%20Fantasy%20Disassembly
Looks to be bank bank 0E.

"IsEquipLegal" being the function name of choice (line 9057 https://github.com/Entroper/FF1Disassembly/blob/c47ab71702bcd7f0b2a2221c55adc4c9fa941d80/Final%20Fantasy%20Disassembly/bank_0E.asm and continuing on through it all). Where that might land in the ROM I am not sure other than obviously bank 0E.

https://github.com/Entroper/FF1Disassembly/blob/c47ab71702bcd7f0b2a2221c55adc4c9fa941d80/Final%20Fantasy%20Disassembly/bank_0C.asm has some stuff on the armour and spells themselves.

Spindaboy

  • Full Member
  • ***
  • Posts: 171
  • ただいま!
    • View Profile
    • SyndROMe Hacking
Re: FFI (NES) Armor Indices
« Reply #2 on: April 28, 2021, 07:56:43 pm »
Hmmm do you if there's any way to modify the values used in the function with a ROM that's already been assembled?

Cyneprepou4uk

  • Hero Member
  • *****
  • Posts: 875
  • I am the baldest romhacker
    • View Profile
Re: FFI (NES) Armor Indices
« Reply #3 on: April 29, 2021, 09:05:04 am »
Ever heard of a hex editor?

Spindaboy

  • Full Member
  • ***
  • Posts: 171
  • ただいま!
    • View Profile
    • SyndROMe Hacking
Re: FFI (NES) Armor Indices
« Reply #4 on: April 29, 2021, 02:16:49 pm »
Ever heard of a hex editor?

Allow me to rephrase, does anyone know how to locate the values?
« Last Edit: April 29, 2021, 03:26:41 pm by Spindaboy »

Cyneprepou4uk

  • Hero Member
  • *****
  • Posts: 875
  • I am the baldest romhacker
    • View Profile
Re: FFI (NES) Armor Indices
« Reply #5 on: April 29, 2021, 04:31:06 pm »
Well you can try to search for bytes/instructions inside a rom file that you see in asm files. If the data is at the beginning/end of the bank, it will be much easier, since banks usually start with 0x00010, 0x04010, 0x08010 and so on (+4000).

Also some assemblers can produce a listing file if you configure them properly.

April 29, 2021, 09:20:14 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
The dude that made the disassembly left quite a few notes regarding locations. For example the "IsEquipLegal" function from bank 0E which was mentioned earlier, line 9039 tells you where it begins (cpu and rom file addresses).
« Last Edit: April 29, 2021, 09:20:14 pm by Cyneprepou4uk »

Spindaboy

  • Full Member
  • ***
  • Posts: 171
  • ただいま!
    • View Profile
    • SyndROMe Hacking
Re: FFI (NES) Armor Indices
« Reply #6 on: April 30, 2021, 02:02:23 pm »
So it looks like the isEquipLegal function occupies this little snippet right here. I can't seem to find where exactly the values lie though. Is there something I missing here?



Code: [Select]
IsEquipLegal:
    SEC
    SBC #$01          ; subtract 1 from the item ID to make it zero based
    ASL A             ; double it
    STA tmp           ; tmp = (2*item_id)

    LDA cursor        ; get the cursor
    ASL A
    ASL A
    ASL A
    ASL A
    AND #$C0          ; shift and mask to get usable character index
    TAX               ; put char index in X

    LDA ch_class, X   ; get the character's class
    ASL A             ; double it (2 bytes for equip permissions)
    TAX               ; and put in X to index the equip bit

    LDA lut_ClassEquipBit, X        ; get the class permissions bit position word
    STA tmp+4                       ;  and put in tmp+4,5
    LDA lut_ClassEquipBit+1, X
    STA tmp+5

    LDY equipoffset              ; now, see if we're dealing with weapons or armor
    CPY #ch_weapons-ch_stats
    BNE @Armor

  @Weapon:
    LDX tmp                        ; get the weapon id (*2)
    LDA lut_WeaponPermissions, X   ; use it to get the weapon permissions word (low byte)
    AND tmp+4                      ; mask with low byte of class permissions
    STA tmp                        ;  temporarily store result
    LDA lut_WeaponPermissions+1, X ; then do the same with the high byte of the permissions word
    AND tmp+5                      ;  mask with high byte of class permissions
    ORA tmp                        ; then combine with results of low mask
                          ;  here... any nonzero value will indicate that the item cannot be equipped

    CMP #$01              ; compare with 1 (any nonzero value will set C)
    BCC :+                ; if C is set (can't equip)....
      RTS                 ;   ... just exit.  otherwise...

:   LDA cursor            ; get the cursor (character id*4)
    AND #$0C              ; isolate the character bits
    TAX                   ; and put in X for indexing

    LDA item_box, X       ; unequip all weapons
    AND #$7F
    STA item_box, X
    LDA item_box+1, X
    AND #$7F
    STA item_box+1, X
    LDA item_box+2, X
    AND #$7F
    STA item_box+2, X
    LDA item_box+3, X
    AND #$7F
    STA item_box+3, X

    RTS                   ; then exit (C is still clear, indicating item can be equipped)

  @Armor:
    LDX tmp                       ; get the armor id (*2)
    LDA lut_ArmorPermissions, X   ; use it to get the armor permissions word
    AND tmp+4                     ;  and mask it with the class permissions word
    STA tmp
    LDA lut_ArmorPermissions+1, X
    AND tmp+5
    ORA tmp               ; and OR both high and low bytes of result together.  A nonzero result here indicates
                          ;  armor cannot be equipped

    CMP #$01              ; compare with 1 (any nonzero value sets C)
    BCC :+                ; if armor can't be equipped....
      RTS                 ; .. just exit.  Otherwise...

:   TXA                   ; get back the armor_id*2
    LSR A                 ; /2 to restore armor_id
    TAX                   ; and put back in X

    LDA lut_ArmorTypes, X ; use armor ID to index and find out what kind of armor it is (body, helmet, shield, etc)
    STA tmp+2             ; store armor type in tmp+2

    LDA cursor            ; store current cursor in tmp (seems dumb... we could just reference cursor directly)
    STA tmp
    AND #$0C              ; mask out the charater bits  (char ID * 4)
    STA tmp+1             ;  store that in tmp+1  (loop's item to unequip)

    LDY #$04              ; set Y (loop counter) to 4 (loop 4 times)

  @ArmorLoop:
    LDA tmp+1             ; get the loop item index
    CMP tmp               ; compare to the item we're trying to equip
    BEQ @ArmorSkip        ; if they're equal, skip over this item (seems pointless... the item we're checking wouldn't be equipped)

    LDX tmp+1             ; put loop item index in X
    LDA item_box, X       ;  use it to get that item from the item_box
    BPL @ArmorSkip        ; if that item is not equipped, skip it

    SEC                   ; otherwise (it is equipped), subtract $81 to get the armor ID
    SBC #$81
    TAX                   ; put armor ID in X
    LDA lut_ArmorTypes, X ; use that to look up what type of armor this is

    CMP tmp+2             ; compare that to the type of armor we're trying to equip
    BNE @ArmorSkip        ; if it doesn't match (different kind of armor), skip it

                          ; otherwise... it's a match!  need to unequip it.
    LDX tmp+1             ; get this loop item index in X
    LDA item_box, X       ; use it to get the item from the item box
    AND #$7F              ;    unequip it
    STA item_box, X       ;    then write it back

  @ArmorSkip:
    INC tmp+1             ; increment our loop item counter (to examine next item in the item box)
    DEY                   ; decrement our loop counter
    BNE @ArmorLoop        ; and keep looping until it expires

    CLC                   ; once we're done with all that, CLC to indicate the item can be equipped
    RTS                   ; and exit
« Last Edit: May 01, 2021, 03:03:35 am by Spindaboy »

Cyneprepou4uk

  • Hero Member
  • *****
  • Posts: 875
  • I am the baldest romhacker
    • View Profile
Re: FFI (NES) Armor Indices
« Reply #7 on: April 30, 2021, 08:19:17 pm »
That depends on what values are you looking for. If you are talking about "lut_ArmorPermissions" or something, then this is a table, it is located somewhere else, not inside the function directly. Search by the name.

And you should put code inside "code" tags.