øAslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&topic=2369.msg27408e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/index4375.htmlslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&action=profile;area=showposts;sa=topics;u=337e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/index4375.html.zx±Ih^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ z q/OKtext/htmlISO-8859-1gzip0|Öq/ÿÿÿÿÿÿÿÿWed, 11 Mar 2020 02:31:37 GMT0ó°° ®0®P®€§²ð®°Ih^ÿÿÿÿÿÿÿÿt*q/ Inventory Sorting

Author Topic: Inventory Sorting  (Read 646 times)

Praetarius5018

  • Vargas
  • *
  • Posts: 88
    • View Profile
Inventory Sorting
« on: June 05, 2017, 02:10:11 PM »
Do we have any information on how the inventory is "sorted"?
To be honest, all results seem utterly random apart from consumables first, then weapon, then armor.
Even within each of those groups the order looks random...

samurai goroh

  • FF5 Hacker
  • *
  • Posts: 221
  • Gender: Male
    • View Profile
    • My page
Re: Inventory Sorting
« Reply #1 on: June 05, 2017, 11:08:35 PM »
Wasn't precisely just that? (I mean for the SNES)

Haven't played in a while (so I can be wrong), but wasn't the sort just to separate between these 3 categories (items have this distinction on the code already). Basically you could say:
- If consumable goto top
- If weapon goto middle
- If armor goto bottom

And the items would remain in the same order as they previously were in the inventory.
I'm the best in the universe! Just remember! [F-zero X]

Squall

  • Dark Dragon
  • *
  • Posts: 486
    • View Profile
Re: Inventory Sorting
« Reply #2 on: June 06, 2017, 02:08:02 AM »
Yeah it seems random to me too. Maybe separating the groups was the only goal :)

Praetarius5018

  • Vargas
  • *
  • Posts: 88
    • View Profile
Re: Inventory Sorting
« Reply #3 on: June 06, 2017, 11:16:00 AM »
They should have been more consequent and at least separate weapons by type as well...
*goes back to not finding the misspelled katana in over 100 weapons*

Praetarius5018

  • Vargas
  • *
  • Posts: 88
    • View Profile
Re: Inventory Sorting
« Reply #4 on: June 19, 2017, 04:48:05 PM »
in case I'm not the only one curious about this, here's the relevant code

simply put, it goes three times through your whole inventory, once for consumables, then weapon, then armor and only checks if the item belongs to the current category. If so, it writes a copy to the next best slot in a temporary inventory then transfers all into the real inventory at the very end.
so a sorting doesn't really happen, only categorization.

Code: [Select]
$C2/BA39 20 02 E0    JSR $E002  [$C2:E002]   A:0003 X:003C Y:4307 P:envmxdIZC


$C2/E002 8B          PHB                     A:0003 X:003C Y:4307 P:envmxdIZC
$C2/E003 08          PHP                     A:0003 X:003C Y:4307 P:envmxdIZC
$C2/E004 F4 7E 7E    PEA $7E7E               A:0003 X:003C Y:4307 P:envmxdIZC
$C2/E007 AB          PLB                     A:0003 X:003C Y:4307 P:envmxdIZC
$C2/E008 AB          PLB                     A:0003 X:003C Y:4307 P:envmxdIzC
$C2/E009 C2 20       REP #$20                A:0003 X:003C Y:4307 P:envmxdIzC
$C2/E00B A6 8E       LDX $8E    [$00:018E]   A:0003 X:003C Y:4307 P:envmxdIzC
$C2/E00D 9E 00 7F    STZ $7F00,x[$7E:7F00]   A:0003 X:0000 Y:4307 P:envmxdIZC
$C2/E010 E8          INX                     A:0003 X:0000 Y:4307 P:envmxdIZC
$C2/E011 E8          INX                     A:0003 X:0001 Y:4307 P:envmxdIzC
$C2/E012 E0 00 03    CPX #$0300              A:0003 X:0002 Y:4307 P:envmxdIzC
$C2/E015 D0 F6       BNE $F6    [$E00D]      A:0003 X:0002 Y:4307 P:eNvmxdIzc
$C2/E00D 9E 00 7F    STZ $7F00,x[$7E:7F02]   A:0003 X:0002 Y:4307 P:eNvmxdIzc
$C2/E010 E8          INX                     A:0003 X:0002 Y:4307 P:eNvmxdIzc
$C2/E011 E8          INX                     A:0003 X:0003 Y:4307 P:envmxdIzc
$C2/E012 E0 00 03    CPX #$0300              A:0003 X:0004 Y:4307 P:envmxdIzc
$C2/E015 D0 F6       BNE $F6    [$E00D]      A:0003 X:0004 Y:4307 P:eNvmxdIzc
$C2/E00D 9E 00 7F    STZ $7F00,x[$7E:7F04]   A:0003 X:0004 Y:4307 P:eNvmxdIzc
...
$C2/E00D 9E 00 7F    STZ $7F00,x[$7E:81FE]   A:0003 X:02FE Y:4307 P:eNvmxdIzc
$C2/E010 E8          INX                     A:0003 X:02FE Y:4307 P:eNvmxdIzc
$C2/E011 E8          INX                     A:0003 X:02FF Y:4307 P:envmxdIzc
$C2/E012 E0 00 03    CPX #$0300              A:0003 X:0300 Y:4307 P:envmxdIzc
$C2/E015 D0 F6       BNE $F6    [$E00D]      A:0003 X:0300 Y:4307 P:envmxdIZC
$C2/E017 C2 20       REP #$20                A:0003 X:0300 Y:4307 P:envmxdIZC
$C2/E019 A4 8E       LDY $8E    [$00:018E]   A:0003 X:0300 Y:4307 P:envmxdIZC
$C2/E01B A9 E0 00    LDA #$00E0              A:0003 X:0300 Y:0000 P:envmxdIZC lowest id of this category
$C2/E01E A2 00 01    LDX #$0100              A:00E0 X:0300 Y:0000 P:envmxdIzC highest id of this category
$C2/E021 20 50 E0    JSR $E050  [$C2:E050]   A:00E0 X:0100 Y:0000 P:envmxdIzC sort first time, for consumables
$C2/E024 A5 8E       LDA $8E    [$00:018E]   A:0012 X:0100 Y:0012 P:envmxdIzC
$C2/E026 A2 80 00    LDX #$0080              A:0000 X:0100 Y:0012 P:envmxdIZC
$C2/E029 20 50 E0    JSR $E050  [$C2:E050]   A:0000 X:0080 Y:0012 P:envmxdIzC sort again, this time for weapons
$C2/E02C A9 80 00    LDA #$0080              A:0090 X:0100 Y:0090 P:envmxdIzC
$C2/E02F A2 E0 00    LDX #$00E0              A:0080 X:0100 Y:0090 P:envmxdIzC
$C2/E032 20 50 E0    JSR $E050  [$C2:E050]   A:0080 X:00E0 Y:0090 P:envmxdIzC sort again, this time for armors
$C2/E035 A2 00 80    LDX #$8000              A:00F2 X:0100 Y:00F2 P:envmxdIzC
$C2/E038 A0 40 06    LDY #$0640              A:00F2 X:8000 Y:00F2 P:eNvmxdIzC
$C2/E03B A9 FF 01    LDA #$01FF              A:00F2 X:8000 Y:0640 P:envmxdIzC
$C2/E03E 54 7E 7E    MVN 7E 7E               A:01FF X:8000 Y:0640 P:envmxdIzC
$C2/E041 A2 00 7F    LDX #$7F00              A:FFFF X:8200 Y:0840 P:envmxdIzC
$C2/E044 A0 8A 28    LDY #$288A              A:FFFF X:7F00 Y:0840 P:envmxdIzC
$C2/E047 A9 FF 00    LDA #$00FF              A:FFFF X:7F00 Y:288A P:envmxdIzC
$C2/E04A 54 7E 7E    MVN 7E 7E               A:00FF X:7F00 Y:288A P:envmxdIzC
$C2/E04D 28          PLP                     A:FFFF X:8000 Y:298A P:envmxdIzC
$C2/E04E AB          PLB                     A:FFFF X:8000 Y:298A P:envmxdIZC
$C2/E04F 60          RTS                     A:FFFF X:8000 Y:298A P:envmxdIzC



actual comparison
Code: [Select]
$C2/E050 85 93       STA $93    [$00:0193]   A:00E0 X:0100 Y:0000 P:envmxdIzC
$C2/E052 86 95       STX $95    [$00:0195]   A:00E0 X:0100 Y:0000 P:envmxdIzC
$C2/E054 A6 8E       LDX $8E    [$00:018E]   A:00E0 X:0100 Y:0000 P:envmxdIzC

$C2/E056 BD 40 06    LDA $0640,x[$7E:0641]   A:000D X:0001 Y:0000 P:eNvmxdIzc tent in 2nd slot
$C2/E059 29 FF 00    AND #$00FF              A:E2F0 X:0001 Y:0000 P:eNvmxdIzc
$C2/E05C F0 3D       BEQ $3D    [$E09B]      A:00F0 X:0001 Y:0000 P:envmxdIzc
$C2/E05E C9 01 00    CMP #$0001              A:00F0 X:0001 Y:0000 P:envmxdIzc
$C2/E061 F0 38       BEQ $38    [$E09B]      A:00F0 X:0001 Y:0000 P:envmxdIzC
$C2/E063 C9 80 00    CMP #$0080              A:00F0 X:0001 Y:0000 P:envmxdIzC
$C2/E066 F0 33       BEQ $33    [$E09B]      A:00F0 X:0001 Y:0000 P:envmxdIzC
$C2/E068 85 E0       STA $E0    [$00:01E0]   A:00F0 X:0001 Y:0000 P:envmxdIzC
$C2/E06A BD 40 07    LDA $0740,x[$7E:0741]   A:00F0 X:0001 Y:0000 P:envmxdIzC item quantity
$C2/E06D 29 FF 00    AND #$00FF              A:0102 X:0001 Y:0000 P:envmxdIzC
$C2/E070 F0 29       BEQ $29    [$E09B]      A:0002 X:0001 Y:0000 P:envmxdIzC
$C2/E072 C9 64 00    CMP #$0064              A:0002 X:0001 Y:0000 P:envmxdIzC
$C2/E075 30 03       BMI $03    [$E07A]      A:0002 X:0001 Y:0000 P:eNvmxdIzc
$C2/E07A 85 E2       STA $E2    [$00:01E2]   A:0002 X:0001 Y:0000 P:eNvmxdIzc
$C2/E07C A5 E0       LDA $E0    [$00:01E0]   A:0002 X:0001 Y:0000 P:eNvmxdIzc
$C2/E07E C5 93       CMP $93    [$00:0193]   A:00F0 X:0001 Y:0000 P:envmxdIzc compare item id to min id
$C2/E080 30 19       BMI $19    [$E09B]      A:00F0 X:0001 Y:0000 P:envmxdIzC
$C2/E082 C5 95       CMP $95    [$00:0195]   A:00F0 X:0001 Y:0000 P:envmxdIzC compare item id to max id
$C2/E084 10 15       BPL $15    [$E09B]      A:00F0 X:0001 Y:0000 P:eNvmxdIzc
$C2/E086 E2 20       SEP #$20                A:00F0 X:0001 Y:0000 P:eNvmxdIzc
$C2/E088 A5 E0       LDA $E0    [$00:01E0]   A:00F0 X:0001 Y:0000 P:eNvMxdIzc item id
$C2/E08A 99 00 80    STA $8000,y[$7E:8000]   A:00F0 X:0001 Y:0000 P:eNvMxdIzc temp slot1
$C2/E08D A5 E2       LDA $E2    [$00:01E2]   A:00F0 X:0001 Y:0000 P:eNvMxdIzc item quantity
$C2/E08F 99 00 81    STA $8100,y[$7E:8100]   A:0002 X:0001 Y:0000 P:envMxdIzc
$C2/E092 BD 8A 28    LDA $288A,x[$7E:288B]   A:0002 X:0001 Y:0000 P:envMxdIzc
$C2/E095 99 00 7F    STA $7F00,y[$7E:7F00]   A:000D X:0001 Y:0000 P:envMxdIzc
$C2/E098 C8          INY                     A:000D X:0001 Y:0000 P:envMxdIzc
$C2/E099 C2 20       REP #$20                A:000D X:0001 Y:0001 P:envMxdIzc
$C2/E09B E8          INX                     A:000D X:0001 Y:0001 P:envmxdIzc
$C2/E09C E0 00 01    CPX #$0100              A:000D X:0002 Y:0001 P:envmxdIzc
$C2/E09F D0 B5       BNE $B5    [$E056]      A:000D X:0002 Y:0001 P:eNvmxdIzc
...
$C2/E056 BD 40 06    LDA $0640,x[$7E:073F]   A:0000 X:00FF Y:0011 P:eNvmxdIzc empty slot
$C2/E059 29 FF 00    AND #$00FF              A:0400 X:00FF Y:0011 P:envmxdIzc
$C2/E05C F0 3D       BEQ $3D    [$E09B]      A:0000 X:00FF Y:0011 P:envmxdIZc
$C2/E09B E8          INX                     A:0000 X:00FF Y:0011 P:envmxdIZc
$C2/E09C E0 00 01    CPX #$0100              A:0000 X:0100 Y:0011 P:envmxdIzc
$C2/E09F D0 B5       BNE $B5    [$E056]      A:0000 X:0100 Y:0011 P:envmxdIZC
$C2/E0A1 98          TYA                     A:0000 X:0100 Y:0011 P:envmxdIZC create an empty slot at end of category if necessary
$C2/E0A2 1A          INC A                   A:0011 X:0100 Y:0011 P:envmxdIzC
$C2/E0A3 29 FE FF    AND #$FFFE              A:0012 X:0100 Y:0011 P:envmxdIzC
$C2/E0A6 A8          TAY                     A:0012 X:0100 Y:0011 P:envmxdIzC
$C2/E0A7 60          RTS                     A:0012 X:0100 Y:0012 P:envmxdIzC


shouldn't be too hard to add a minor sorting there...

noisecross

  • FF5 Hacker
  • *
  • Posts: 146
    • View Profile
Re: Inventory Sorting
« Reply #5 on: June 20, 2017, 02:51:16 AM »
shouldn't be too hard to add a minor sorting there...
Not hard, but tedious.

The simpler way to sort the items would be:
1- Goes through inventory and for each item (id/quantity) do temporaryInventory[itemId] = quantity
2- Goes through temporaryInventory, consider every quantity of 0 as irrelevant and bring together every item where quantity > 0
3- Copy temporaryInventory over inventory

The weak point of this approach is, the items are not very well sorted internally. I.e., the 27 weapons above the Tinklebell id are a mix of knives, swords, harps, axes and bows...
To avoid this, we should count with a table to map itemIds to itemPositionInMenu. Maybe, a 256 bytes table is too much to do this thing.

Squall

  • Dark Dragon
  • *
  • Posts: 486
    • View Profile
Re: Inventory Sorting
« Reply #6 on: June 20, 2017, 05:54:59 AM »
Yeah no sorting at all. TBH sorting will be a hard task. If we sort by ItemID, items are mixed. If we try Alphabet sort, we will need a separate table because internally the game doesnt use ASCII. We can solve both problems by a table with priorities (what we consider first, item, second,..), similar to what noisecross suggested. By using different tables we can achieve different types of sort, including different languages/translations.

P.S. Does anybody know what info is in $288A (LDA $288A,x)?

Praetarius5018

  • Vargas
  • *
  • Posts: 88
    • View Profile
Re: Inventory Sorting
« Reply #7 on: June 20, 2017, 11:06:32 AM »
sorting by alphabet needs no additional table; whether A is 05 or 3A or 5C doesn't matter as long as all letters are in order, which they should be


for general consumables, I'd just keep the sorting by id, that area (E0+) looks sorted enough as is.

for the rest, I'll try to sort by type - so swords stay with swords, axes with axes, knight swords with knight swords - then by attack value/defense power (7th byte in both cases).
not sure how to get item type in a better way then read the name...

I'll put a jump here:
$C2/E08D A5 E2       LDA $E2    [$00:01E2]   A:00F0 X:0001 Y:0000 P:eNvMxdIzc   item quantity   
$C2/E08F 99 00 81    STA $8100,y[$7E:8100]   A:0002 X:0001 Y:0000 P:envMxdIzc
where the "temp item" is put at the end of the list, then go backwards to see if the items need to be moved.
All under the assumption that the list is always sorted in each step - which it must be.

Praetarius5018

  • Vargas
  • *
  • Posts: 88
    • View Profile
Re: Inventory Sorting
« Reply #8 on: June 20, 2017, 03:23:29 PM »
I've expanded my ROM, so I'll not even bother to find enough free space in the ROM.
I'll have to leave that to each user for themselves. Mine'll sit at E8/3B30.
So a few JMPs will have to be adjusted.
Since this relies on the item name, it won't work as it is for untranslated versions. They use different addresses for the item name.

$C2/E08D
A5 E2 99 00 81
place a JSL to your routine here instead

Code: [Select]
E8/3B30
A5 E2 LDA $E2    [$00:01E2]
99 00 81 STA $8100,y[$7E:8100]
C0 00 00 CPY #$0000
D0 01 BNE
6B RTL
DA PHX
5A PHY
---loop start---
88 DEY
30 24 BMI go to end if Y < 0
B9 00 80 LDA $8000,y[$7E:8000]
20 90 3B JSR validate item
F0 1C BEQ if 0 exit
85 E0 STA $E0
B9 01 80 LDA $8001,y[$7E:8001]
20 90 3B JSR validate
F0 12 BEQ if 0 exit
C5 E0 CMP $E0
F0 04 BEQ
10 0C BPL go to end if right sorting
30 05 BMI go to switch
20 D0 3B JSR compare both items for attack/defense
---compare both values; value != id
F0 05 BEQ if 0 exit
20 70 3B JSR switch items
80 D9 BRA loop start
---loop end---
7A PLY
FA PLX
6B RTL


switch items
Code: [Select]
E8/3B70
B9 00 80 LDA $8000,y[$7E:8000]
48 PHA
B9 01 80 LDA $8001,y[$7E:8001]
99 00 80 STA $8000,y[$7E:8000]
68 PLA
99 01 80 STA $8001,y[$7E:8001]
B9 00 81 LDA $8100,y[$7E:8100]
48 PHA
B9 01 81 LDA $8101,y[$7E:8101]
99 00 81 STA $8100,y[$7E:8100]
68 PLA
99 01 81 STA $8101,y[$7E:8101]
60 RTS


validate item, returns primary sorting value of item
Code: [Select]
E8/3B90
F0 12 BEQ
C9 01 CMP #$01
F0 0E BEQ
C9 80 CMP #$80
F0 0A BEQ
C5 93 CMP $93
30 06 BMI
C5 95 CMP $95
10 02 BPL
80 03 BRA
A9 00 LDA #$00
60 RTS
C9 E0 CMP #$E0 if it is a consumable, return id
90 03 BCC $03
29 FF AND #$FF
60 RTS
C2 20 REP #$20
29 FF 00 AND #$00FF #$1380 + 9xID is the offset for name
48 PHA
0A ASL A
0A ASL A
0A ASL A
18 CLC
63 01 ADC $01,s
18 CLC
69 80 13 ADC #$1380
FA PLX
AA TAX
BF 00 00 D1 LDA $0000,x weapon symbol
29 FF 00 AND #$00FF
E2 20 SEP #$20
60 RTS


compare both items for attack/defense
Code: [Select]
E8/3BD0
B9 00 80 LDA $8000,y[$7E:8000]
20 F0 3B JSR get atk/def
85 E0 STA $E0
B9 01 80 LDA $8001,y[$7E:8001]
20 F0 3B JSR get atk/def
C5 E0 CMP $E0
F0 05 BEQ
90 03 BCC
A9 01 LDA #$01
60 RTS
A9 00 LDA #$00
60 RTS

get atk/def
Code: [Select]
E8/3BF0
C2 20 REP #$20
48 PHA
0A ASL A
18 CLC
63 01 ADC $01,s
0A ASL A
0A ASL A
FA PLX
AA TAX
29 FF 00 AND #$00FF
E2 20 SEP #$20
BF 07 00 D1 LDA $0007,x atk/def, highest value to the top
60 RTS

Squall

  • Dark Dragon
  • *
  • Posts: 486
    • View Profile
Re: Inventory Sorting
« Reply #9 on: June 21, 2017, 04:33:38 AM »
Looking in the original code, I don't understand:

1. In the end of the sorting, what exactly this code does:
Code: [Select]
C2/E0A1: 98           TYA
C2/E0A2: 1A           INC
C2/E0A3: 29 FE FF     AND #$FFFE
C2/E0A6: A8           TAY
It seems it make sure, next section always starts at even address (last bit 0) ... but whats the purpose?

2. What info we have in $288A? ($640 holds ItemID, $740 - hold quantity of the item)

3. Items with ID: 0, 1 and $80 are skipped. Is there any specific distinction in these values?



Praetarius5018

  • Vargas
  • *
  • Posts: 88
    • View Profile
Re: Inventory Sorting
« Reply #10 on: June 21, 2017, 10:54:40 AM »
Looking in the original code, I don't understand:

1. In the end of the sorting, what exactly this code does:
Code: [Select]
C2/E0A1: 98           TYA
C2/E0A2: 1A           INC
C2/E0A3: 29 FE FF     AND #$FFFE
C2/E0A6: A8           TAY
It seems it make sure, next section always starts at even address (last bit 0) ... but whats the purpose?
so that a new category starts on the left side, like a linebreak

item item
item <empty>
weapon weapon
etc.

2. What info we have in $288A? ($640 holds ItemID, $740 - hold quantity of the item)
honestly, no idea

3. Items with ID: 0, 1 and $80 are skipped. Is there any specific distinction in these values?
those are empty (weapon), fist and empty (armor) which you shouldn't find in your inventory

Squall

  • Dark Dragon
  • *
  • Posts: 486
    • View Profile
Re: Inventory Sorting
« Reply #11 on: June 22, 2017, 01:36:02 AM »
Looking in the original code, I don't understand:

1. In the end of the sorting, what exactly this code does:
Code: [Select]
C2/E0A1: 98           TYA
C2/E0A2: 1A           INC
C2/E0A3: 29 FE FF     AND #$FFFE
C2/E0A6: A8           TAY
It seems it make sure, next section always starts at even address (last bit 0) ... but whats the purpose?
so that a new category starts on the left side, like a linebreak

item item
item <empty>
weapon weapon
etc.
Hehe I was thinking about that, just rarely use sorting and haven't observed that behavior. Nice one Praetarius5018  :laugh: