View in color | License | Download script | History | Other scripts by: caldixon |
12-Sep 18:53 UTC
[0.056] 19.705k
[0.056] 19.705k
ff3edit.rREBOL [
Title: "FF3 ZSNES Saved state editor"
File: %ff3edit.r
Author: "Cal Dixon"
Date: 21-Dec-2002
Purpose: {A tool to edit saved state files for Final Fantasy 3 as created by the ZSNES emulator}
Library: [
level: 'intermediate
platform: [all windows]
type: 'tool
domain: [file-handling game vid]
tested-under: [view 1.2.10.3.1 on [W2K] by "Cal"]
license: 'PD
support: none
]
]
to-cstring: func [ str bufsize ] [
head change (head insert/dup (make binary! bufsize) #{00} bufsize) to-binary str
]
unsignedint32: func [ n ] [
reduce [
to-char ((n / 65536) / 256) to-char ((n / 65536) // 256)
to-char ((n // 65536) / 256) to-char ((n // 65536) // 256)
]
]
signedint32: func [ n ] [
n: either n < 0 [
xor~ #{ffffffff} to-binary rejoin unsignedint32 ((n * -1) - 1)
][
unsignedint32 n
]
reduce [ to-char first n to-char second n to-char third n to-char fourth n ]
]
to-binary-int: func [ n /unsigned /short /intel ] [
n: either unsigned [ unsignedint32 n ] [ signedint32 n ]
to-binary rejoin either intel [
either short [ [fourth n third n] ] [ head reverse n ]
][
either short [ [third n fourth n] ] [ n ]
]
]
items: [
#{00} "Dirk" #{01} "MithrilKnife" #{02} "Guardian" #{03} "Air Lancet" #{04} "ThiefKnife" #{05} "Assassin"
#{06} "Man Eater" #{07} "SwordBreaker" #{08} "Graedus" #{09} "ValiantKnife" #{0A} "MithrilBlade"
#{0B} "RegalCutlass" #{0C} "Rune Edge" #{0D} "Flame Sabre" #{0E} "Blizzard" #{0F} "ThunderBlade"
#{10} "Epee" #{11} "Break Blade" #{12} "Drainer" #{13} "Enhancer" #{14} "Crystal" #{15} "Falchion"
#{16} "Soul Sabre" #{17} "Ogre Nix" #{18} "Excalibur" #{19} "Scimiter" #{1A} "Illumina" #{1B} "Ragnarok"
#{1C} "Atma Weapon" #{1D} "Mithril Pike" #{1E} "Trident" #{1F} "Stout Spear" #{20} "Partisan" #{21} "Pearl Lance"
#{22} "Gold Lance" #{23} "Aura Lance" #{24} "Imp Halberd" #{25} "Imperial" #{26} "Kodachi" #{27} "Blossom"
#{28} "Hardened" #{29} "Striker" #{2A} "Stunner" #{2B} "Ashura" #{2C} "Kotetsu" #{2D} "Forged" #{2E} "Tempest"
#{2F} "Murasame" #{30} "Aura" #{31} "Strato" #{32} "Sky Render" #{33} "Heal Rod" #{34} "Mithril Rod"
#{35} "Fire Rod" #{36} "Ice Rod" #{37} "Thunder Rod" #{38} "Poison Rod" #{39} "Pearl Rod" #{3A} "Gravity Rod"
#{3B} "Punisher" #{3C} "Magus Rod" #{3D} "Chocobo Brsh" #{3E} "DaVinci Brsh" #{3F} "Magical Brsh"
#{40} "Rainbow Brsh" #{41} "Shuriken" #{42} "Ninja Star" #{43} "Tack Star" #{44} "Flail" #{45} "Full Moon"
#{46} "Morning Star" #{47} "Boomerang" #{48} "Rising Sun" #{49} "Hawk Eye" #{4A} "Bone Club" #{4B} "Sniper"
#{4C} "Wing Edge" #{4D} "Cards" #{4E} "Darts" #{4F} "Doom Darts" #{50} "Trump" #{51} "Dice" #{52} "Fixed Dice"
#{53} "MetalKnuckle" #{54} "Mithril Claw" #{55} "Kaiser" #{56} "Poison Claw" #{57} "Fire Knuckle"
#{58} "Dragon Claw" #{59} "Tiger Fangs" #{5A} "Buckler" #{5B} "Heavy Shld" #{5C} "Mithril Shld" #{5D} "Gold Shld"
#{5E} "Aegis Shld" #{5F} "Diamond Shld" #{60} "Flame Shld" #{61} "Ice Shld" #{62} "Thunder Shld"
#{63} "Crystal Shld" #{64} "Genji Shld" #{65} "TortoiseShld" #{66} "Cursed Shld" #{67} "Paladin Shld"
#{68} "Force Shld" #{69} "Leather Hat" #{6A} "Hair Band" #{6B} "Plumed Hat" #{6C} "Beret" #{6D} "Magus Hat"
#{6E} "Bandana" #{6F} "Iron Helmet" #{70} "Coronet" #{71} "Bard's Hat" #{72} "Green Beret" #{73} "Head Band"
#{74} "Mithril Helm" #{75} "Tiara" #{76} "Gold Helmet" #{77} "Tiger Mask" #{78} "Red Hat" #{79} "Mystery Veil"
#{7A} "Circlet" #{7B} "Regal Crown" #{7C} "Diamond Helm" #{7D} "Dark Hood" #{7E} "Crystal Helm" #{7F} "Oath Veil"
#{80} "Cat Hood" #{81} "Genji Helmet" #{82} "Thornlet" #{83} "Titanium" #{84} "LeatherArmor" #{85} "Cotton Robe"
#{86} "Kung Fu Suit" #{87} "Iron Armor" #{88} "Silk Robe" #{89} "Mithril Vest" #{8A} "Ninja Gear"
#{8B} "White Dress" #{8C} "Mithril Mail" #{8D} "Gaia Gear" #{8E} "Mirage Dress" #{8F} "Gold Armor"
#{90} "Power Sash" #{91} "Light Robe" #{92} "Diamond Vest" #{93} "Red Jacket" #{94} "Force Armor"
#{95} "DiamondArmor" #{96} "Dark Gear" #{97} "Tao Robe" #{98} "Crystal Mail" #{99} "Czarina Gown"
#{9A} "Genji Armor" #{9B} "Imp's Armor" #{9C} "Minerva" #{9D} "Tabby Suit" #{9E} "Chocobo Suit" #{9F} "Moogle Suit"
#{A0} "Nutkin Suit" #{A1} "BehemethSuit" #{A2} "Snow Muffler" #{A3} "NoiseBlaster" #{A4} "Bio Blaster"
#{A5} "Flash" #{A6} "Chain Saw" #{A7} "Debilitator" #{A8} "Drill" #{A9} "Air Anchor" #{AA} "AutoCrossbow"
#{AB} "Fire Skean" #{AC} "Water Edge" #{AD} "Bolt Edge" #{AE} "Inviz Edge" #{AF} "Shadow Edge" #{B0} "Goggles"
#{B1} "Star Pendant" #{B2} "Peace Ring" #{B3} "Amulet" #{B4} "White Cape" #{B5} "Jewel Ring" #{B6} "Fair Ring"
#{B7} "Barrier Ring" #{B8} "MithrilGlove" #{B9} "Guard Ring" #{BA} "RunningShoes" #{BB} "Wall Ring"
#{BC} "Cherub Down" #{BD} "Cure Ring" #{BE} "True Knight" #{BF} "DragoonBoots" #{C0} "Zephyr Cape"
#{C1} "Czarina Ring" #{C2} "Cursed Cing" #{C3} "Earrings" #{C4} "Atlas Armlet" #{C5} "BlizzardRing"
#{C6} "Rage Ring" #{C7} "Sneak Ring" #{C8} "Pod Bracelet" #{C9} "Hero Ring" #{CA} "Ribbon" #{CB} "Muscle Belt"
#{CC} "Crystal Orb" #{CD} "Gold Hairpin" #{CE} "Economizer" #{CF} "Thief Glove" #{D0} "Gauntlet"
#{D1} "Genji Glove" #{D2} "Hyper Wrist" #{D3} "Offering" #{D4} "Beads" #{D5} "Black Belt" #{D6} "Coin Toss"
#{D7} "FakeMustache" #{D8} "Gem Box" #{D9} "Dragon Horn" #{DA} "Merit Award" #{DB} "Momento Ring"
#{DC} "Safety Bit" #{DD} "Relic Ring" #{DE} "Moogle Charm" #{DF} "Charm Bangle" #{E0} "Marvel Shoes"
#{E1} "Back Gaurd" #{E2} "Gale Hairpin" #{E3} "Sniper Sight" #{E4} "Exp. Egg" #{E5} "Tintinabar"
#{E6} "Sprint Shoes" #{E7} "Rename Card" #{E8} "Tonic" #{E9} "Potion" #{EA} "X Potion" #{EB} "Tincture"
#{EC} "Ether" #{ED} "X Ether" #{EE} "Elixir" #{EF} "Megalixir" #{F0} "Fenix Down" #{F1} "Revivify"
#{F2} "Antidote" #{F3} "Eydrop" #{F4} "Soft" #{F5} "Remedy" #{F6} "Sleeping Bag" #{F7} "Tent" #{F8} "Green Cherry"
#{F9} "Magicite" #{FA} "Super Ball" #{FB} "Echo Screen" #{FC} "Smoke Bomb" #{FD} "Warp Stone" #{FE} "Dried Meat"
#{FF} "Nothing"
]
espernames: [
[
Ramuh
Ifrit
Shiva
Siren
Terrato
Maduin
Shoat
Bismark
]
[
Stray
Palidor
Tritoch
Odin
Raiden
Bahamut
Alexandr
Crusader
]
[
Ragnarok
Kirin
Zoneseek
Carbunkl
Phantom
Sraphim
Golem
Unicorn
]
[
Fenrir
Startlet
Phoenix
]
]
bits: [
#{01}
#{02}
#{04}
#{08}
#{10}
#{20}
#{40}
#{80}
]
item-code-to-name: func [ code ][
if integer? code [ code: to-binary to-char code ]
any [select items hex2bin code "Nothing"]
]
item-name-to-code: func [ name ][
first to-block any [back any [find items name [#{FF}]] [#{FF}]]
]
hex2bin: func [hex][
if binary? hex [ return hex ]
if string? hex [ return load rejoin ["#{" hex "}"] ]
if issue? hex [ return hex2bin to-string hex ]
to-binary hex
]
o-itemtype: to-integer hex2bin #247C
o-itemcount: to-integer hex2bin #257C
load-game: func [][
flash "Loading"
data: read/binary request-file/file/only/filter %Final_Fantasy_III_official.zs1 ["*.zs?"]
unview
inv-scroll-n: 0
decode-game: func [data /local inventory gold esperbits names byte bytenum i][
inventory: make block! 256
for n 0 255 1 [
item: copy/part skip data (o-itemtype + n) 1
count: copy/part skip data (o-itemcount + n) 1
if all [item <> #{FF} count <> #{00}][
;print [ to-integer count item-code-to-name item " in slot " n ]
append inventory reduce [to-integer item to-integer count]
]
]
gold: to-integer head reverse copy/part skip data to-integer #{2473} 3
esperbits: copy/part skip data to-integer #{267C} 4
for bytenum 1 4 1 [
names: pick espernames bytenum
byte: to-binary to-char pick esperbits bytenum
for i 1 8 1 [
if all [pick names i #{00} <> ((pick bits i) and byte)] [
print to-string pick names i
]
]
]
return reduce [inventory gold]
]
set [inventory gold] decode-game data
]
load-game
view center-face layout [
across
text "Gold:" gold-field: field form gold [
gold: to-integer value
]
return
text 150 "All items:" pad 100 text "Inventory:" return
item-sel: text-list 250x400 data extract/index items 2 2
space 0
inv-sel: list 250x400 [
across
name: text 200x16 with [n: 256] feel [
engage: func [f a e i][
; probe f/text
if e/type = 'up [
nt: number: request-text/title/default
item-code-to-name pick inventory ((f/n - 1) * 2) + 1 form pick inventory ((f/n - 1) * 2) + 2
item-code: pick inventory ((f/n - 1) * 2) + 1
if none? nt [return]
number: any [attempt [to-integer number] pick inventory ((f/n - 1) * 2) + 2 ]
either number = 0 [
remove/part skip inventory ((f/n - 1) * 2) 2
][
change/part skip inventory ((f/n - 1) * 2) reduce [ item-code number ] 2
]
show inv-sel
]
]
]
quantity: text 50x16
] supply [
count: count + inv-scroll-n
set [id num] skip inventory ((count - 1) * 2)
name/n: any [count 256]
name/text: if integer? id [item-code-to-name id]
quantity/text: if integer? id [form num]
]
inv-scroll: slider 16x400 [
inv-scroll-n: to-integer max 0 inv-scroll/data * (-24 + (.5 * length? inventory)) show inv-sel
]
return
button "Add" [
;print [item-sel/picked item-name-to-code item-sel/picked]
if all [item-sel/picked not empty? item-sel/picked][
insert tail inventory reduce [to-integer item-name-to-code first item-sel/picked 1]
show inv-sel
]
]
tab button "Save" [
change/part skip data to-integer #{2473} copy/part to-binary-int/intel gold 3 3
n: 0
for n 0 255 1 [ poke data o-itemtype + n to-char 255 poke data o-itemcount + n to-char 0 ]
foreach [item-type number] inventory [
poke data o-itemtype + n to-char to-integer item-type
poke data o-itemcount + n to-char to-integer number
n: n + 1
]
write/binary request-file/file/only/save %Final_Fantasy_III_official.zs2 data
]
tab button "Quit" [quit]
] |