On this page
  1. Related
  2. Mechanics

Mechanics

MechanicKindHow
Growth rateFixed gainsevery level gives Benjamin 40 maximum HP and set gains in his other stats, to level 41
Visible encounterTouchwalking into a monster in a dungeon or town starts its battle, and the first strike is a roll on the two sides' levels
Every claim about this game, by concept (27)
generalEach of the 81 monsters, from the Brownie to the Dark King, has a 14-byte record at $02:C275 (HP as a word, then four stats, which terriblesecret names strength, defense, speed and magic, then eight more bytes), a 3-byte record at $02:C17C (its level, then its experience and gold, each stored as a third), and a 16-byte name at $0C:CBA0. When a battle loads a monster, the game copies its name, sets its level, sets current and maximum HP to the HP word, copies the four stats, copies bytes 6-7 to two places, bytes 8-11 to four, and bytes 12 and 13 to one place each, and and sets offset $2F to $80 for monster $42 (Behemoth) and every monster after it, $00 before it. HP runs from 50 (Brownie) to 40,000 (Dark King), levels from 1 to 40 (Dark King), and experience up to 762 (Stone Golem).Code
Each of the 81 monsters has a 9-byte attack record at $02:C6FF: a profile number in the first byte's low four bits, then eight bytes, which read as item and attack numbers name attacks in the shared name table ($FF in the empty ones; the code that reads them isn't traced). When a battle loads a monster, the game copies the profile's eight bytes from the 16 profiles at $02:C9EA to offset $44 of its battle record and the whole 9-byte record to offset $57.Code
The 16 attack profiles at $02:C9EA hold eight bytes each; a monster's attack record names its profile (ffmq-tables/monster-attacks), and the loader copies it to offset $44. In 10 of them the bytes' low seven bits sum to 100 (profiles 0, 1, 2, 8, 10, 11, 12, 13, 14, 15); the rest sum to 80, 102, 98, 102, 78, 104. Profiles 11, 12, 13, 14, 15 set the top bit on one byte.Code
Each of the 234 formations at $02:CA6A is 4 bytes: three monster slots and a flags byte. A slot of $FF is empty; otherwise its low seven bits are the monster number. Each slot's top bit is kept apart for that slot ($80 for an empty one), and the flags byte's bits 4 and 5 are kept apart too; what those do isn't read. Bit 7 of the flags byte skips the first-strike roll and bit 6 stops the party running (ffmq/first-strike, ffmq/run).Code
The 207 battle numbers each have three formations at $02:CE12. When a battle starts, the game draws a number from 0 to 100 and takes the first formation for 0-33, the second for 34-67, and the third for 68-100. Computed: the third comes up 33 times in 101 and the others 34; battle number $FF skips the draw and uses the formation already in $0515. Battle numbers 0-19 are the 20 battlefields (ffmq/battlefields).Code
The 15 weapons, items $20-$2E from the Steel Sword to the Ninja Star, have 8-byte records at $02:BC00. When a weapon's action is set up, the game takes bytes 0-1 as a word, bytes 2-5 into four places (keeping the low six bits of bytes 3 and 4, and folding their top two bits into a derived byte), byte 6 into one place, and byte 7 split into its two nibbles. terriblesecret names byte 0 the element, byte 1 the status, byte 2 the power and byte 7 a stat boost.Code
The 157 monster attacks, numbers $40-$DC from Sword to an unnamed last entry, have 7-byte records at $02:BC78. The game takes bytes 0-1 as a word, bytes 2-5 into four places (byte 3's low six bits are the effect routine its battle code dispatches on, and its top two bits and byte 4's go into a derived byte), and byte 6 split into nibbles. terriblesecret names byte 0 the element, 1 the status, 2 the power, 3 the effect and 5 the targeting.Code
The 12 spells, items $14-$1F from Exit to Flare, have 7-byte records at $02:C0C3 in the attack format: bytes 0-1 a word, bytes 2-5 into four places (byte 3's low six bits the effect routine), and byte 6 into one place. terriblesecret's attack fields name them: element, status, power, effect, sound effect, targeting.Code
The four consumables, items $10-$13 (Cure Potion, Heal Potion, Seed, Refresher), have 4-byte records at $02:C117, which the game copies into the same four places as an attack's bytes 2-5: byte 1's low six bits are the effect routine.Code
The 17 pieces of armor, items $2F-$3F (helmets, armor, shields, and the Charm, Magic Ring and Cupid Locket), have 5-byte records at $02:C127. The game takes bytes 0-1 as a word, then splits each of bytes 2, 3 and 4 into its two nibbles. Byte 2 runs in blocks: 0x80 for 3 (Steel Helm, Moon Helm, Apollo Helm); 0x00 for 6 (Steel Armor, Noble Armor, Gaia's Armor, Relica Armor, Mystic Robe, Flame Armor); 0x20 for 5 (Black Robe, Steel Shield, Venus Shield, Aegis Shield, Ether Shield); 0x10 for 3 (Charm, Magic Ring, Cupid Locket). terriblesecret names byte 0 the element and byte 1 the status.Code
The 9 character records at $0C:D0B0, 80 bytes each, are Benjamin's starting record and two for each companion, Kaeli, Tristam, Phoebe and Reuben, the second at a higher level. A new game copies record 0 to Benjamin's place at $1000; a script command copies the record it names, whole, to the companion's place at $1080 (ffmq/companion-records). By terriblesecret's field names, which the copies and the level-up fit, each holds the level ($10), current and maximum HP ($14, $16), the three kinds of magic points ($18-$1A, with maxima at $1B-$1D), the four stats as level gives them ($4C-$4F) and with equipment ($22-$25), and accuracy ($40), which Benjamin's level-up sets to 75 plus half the level.Code
Each of the 20 battlefields, battle numbers 0-19, has a count of battles at $0C:D4D0, which a new game copies to $0FD4, and a reward word at $07:EFA1. Every battlefield starts at 10. After a won battle with a number below 20, the game takes one off that battlefield's count and shows the number left; at zero it gives the reward: with the top bit set, the low 15 bits times 3 in experience; with bit 14, the item in the low byte; otherwise the low 14 bits times 3 in gold. The battlefield names are Archipelago's, not the game's: Archipelago's object ids 1-20 are taken as battle numbers 0-19 because their types (experience, item, gold) follow the reward words in the same order, and the official guide's numbered battlefields -2-, -5-, -19- and -20- have the rewards of battle numbers 1, 4, 18 and 19.Code
The level-up compares Benjamin's experience total at $1011-$1013 with the figure at $0510-$0512 (the experience for his next level). A Mesen probe replays the attract mode's level-25 Benjamin from one savestate, answers each read of his level with 1 to 41 in turn, and records what the game then writes to $0510-$0512: 13L³ + 100L² + 161L + 74 for levels 1 to 39 (348 at level 1, 929,600 at level 39), but 146,546 at level 40 and 218,780 at level 41, each 851,968 (13 × 65,536) below that cubic, so the level-40 figure is lower than the 929,600 that took him to level 40. The probe records the write coming from the script command at $00:AF5B with the event-script pointer at $03:AE36; the script isn't decoded.Verified
The code at $00:A274 reads a word through the 24-bit pointer at $17 and moves the pointer past it, puts the word's low byte, the battle number, in $0513 and its high byte in $0A9C, and calls $00:D080 with the pointer saved. The battle setup at $02:8000 copies $0513 to $0514 unless it's $FF, and the number then picks the battle's formation set (ffmq-tables/formation-sets); battle numbers 0-19 are the battlefields. Not read here: the path from $00:D080 to the battle setup, and the dispatch that runs the code at $00:A274 as an event-script command. The manuals' account of battles on the map is ffmq/map-battles.Code
After a won battle, each monster present adds 3 times its experience byte to the battle's experience and 3 times its gold byte to its gold (ffmq-tables/monsters). The code would use 6 for a gold byte of $42-$49 and 10 for $4A or more, but no monster's gold byte is above 10.Code
When Benjamin's experience reaches the figure at $0510, he goes up one level, to at most 41: his maximum HP rises by 40 and his current HP is scaled by the new maximum over the old; his maximum white magic rises by 1, black by 1 whenever half his level (rounded down) rises, and wizard whenever a quarter of it does; his level stats rise by 3 attack, 2 defense, 2 speed and 1 magic, and offset $40 becomes 75 plus half his level. The check runs once after a battle's rewards and once after a battlefield's experience reward.Code
A companion joins when an event-script command names one of the 9 character records (ffmq-tables/characters): the game copies all 80 bytes of that record over the companion's place at $1080, so the companion arrives at the record's level, HP, stats and equipment, and nothing of the previous companion's record is kept; bit 7 of offset $20 is cleared in the copy unless it was set in the record it replaced.Code
A save holds three blocks: Benjamin's 80-byte record at $1000, the companion's at $1080, and the 380 bytes at $0E84-$0FFF. The routine at $00:C9D3 copies them, in that order, to the start of a buffer at $7F:3000 (540 bytes), and the routine it calls three times writes the buffer's first 902 bytes (what fills the last 362 isn't read) to save RAM in bank $70, after a 6-byte header that holds a checksum of them, at slot × 908 for slots n, n + 3 and n + 6, reading each copy back to check its checksum. Loading copies the three blocks back from the buffer and then runs the same save. A new game fills the blocks from the cartridge: Benjamin's record from the character table, $FF in the companion's level and status, and the 380 bytes from $0C:D380, which put each battlefield's count of 10 at $0FD4 (ffmq-tables/battlefields). So each battlefield's count, which a won battle there lowers and a cleared one leaves at 0, is in the save.Code
The shops' stock and prices and the chests' contents haven't been read yet.Unsourced
Critical hitWhether and how the game rolls critical hits hasn't been read yet.Unsourced
Damage formulaHow Final Fantasy Mystic Quest computes physical and magic damage hasn't been read yet.Unsourced
FleeingThe main loop runs the run check when bit 6 of $1020, in Benjamin's record, is set; what sets that bit isn't read. The run fails outright when the formation's flags byte has bit 6 set, and succeeds outright in round 0 after the party won the first strike. Otherwise the game takes the party's speed (Benjamin's, averaged with the companion's when both can act) and the monsters' average speed: the speeds of those that can act, summed from 1 instead of 0 when the first monster can't act, over their number. It draws a random byte modulo ⌊average ÷ 5⌋ × round + 1 (rounds counted from 0; the product and the + 1 kept to 8 bits), and the run succeeds when (average − draw) mod 256 is below the party's speed, so a draw larger than the average wraps to 256 + average − draw. A failed run gives the monsters a round to themselves. Computed: in round 0 the draw is 0, so the run succeeds only when the party is faster.Code
Hit chanceHow the game decides whether an attack hits hasn't been read yet.Unsourced
Random number generatorThe game's random numbers come from one 16-bit state kept in save RAM at $70:1FFE: each call shifts it left twice, then adds the old state, $3711 and the frame counter at $0E96 in turn, each addition taking in the carry the step before left (the first takes bit 14 of the old state, which the second shift pushed out, so the step is 5 times the state plus that bit, not 5 times the state alone), keeps the 16-bit result, and returns its high byte, reduced modulo the range the caller puts in $A8 when that isn't 0. A range of $65 gives 0-100.Code
Turn orderBefore the first round the game rolls for a first strike. Unless the formation's flags byte has bit 7 set, it takes the monsters' figure as the first slot's level plus twice the second slot's plus 3 (an empty slot's level is $FF, so each slot counts its level plus one, and the third slot is never read), divided by the number of monsters, and the party's as Benjamin's level, averaged with the companion's when one is present; it draws 0-100 and, when the draw is at least 100 minus 10 times the difference (the difference capped at 10), gives the first strike to the side with the higher figure. Computed: a difference of d gives a first strike 10d + 1 times in 101. The party's first strike is a round in which only the party acts; the monsters' is a round in which only they act, and only in battle numbers 0-19, the battlefields. With bit 7 set the roll is skipped and the monsters strike first in a battlefield.Code
Each round the game gives every actor a key of its speed plus a random number below half its speed (0-255 when half its speed is 0), or 2 for an actor with status bit 6 or 7 set, and sorts the actors by key, highest first; an exchange needs a strictly higher key, so ties keep the order Benjamin, companion, first, second and third monster. A round after a first strike or a failed run includes only one side (ffmq/first-strike, ffmq/run).Code
Visible encounterBy the US and Japanese manuals and Squaresoft's newsletter, monsters stand on the map in dungeons and towns, and walking into one starts a battle; the Overworld has no monsters to run into, and its battlefields are optional: 20 of them, each of 10 battles, with a prize for clearing one (ffmq-tables/battlefields). The code that stores a battle's number is ffmq/script-battle.Manual