Temporal Flux Plugin Architecture v1.00
This
document assumes you have a decent
working
knowledge of programming in a .NET language (and uses C# notation).
It also assumes you have moderate experience in ROM hacking.
This document provides some
basic
information on the Temporal Flux Plugin Architecture (TFPA), but it is strongly recommended that you look
over the included MapPlugin example to see how it all fits together.
A "starting point" project has also been included
(FluxPlugin). Any members or
methods not listed here are for use by Flux only at this time.
The point of the TFPA is to provide a
unified profile of handling data, in both reading and writing.
This allows Temporal Flux to treat a plugin's data just like
its own and enforces a certain amount of data integrity.
Since
Flux already takes care of all the overhead necessary for any ROM
editor, the TFPA also resolves a lot of the "heavy lifting" allowing
the plugin author to focus on writing the editor itself.
The TFPA is considered to be an open standard (and
may later be open source). This means the development of how the
TFPA works and what features it contains is open to all programmers
using it.
Limitations
Because of the way the .NET framework links its
libraries together, every time a change is made to the TFPA's interface
or supporting classes, all older
plugins depending on it will be immediately obsoleted. When the
occasion arises I will look into writing a wrapper class, but I'm not
sure the limitation can be overcome at this time.
References
At a minimum, you will want to add the
FluxShared library as a reference in your project. You may
also want to add WeifenLuo.WinFormsUI.Docking,
PSVRender, and GGRLib.
- FluxShared
- Plugin architecture
- WeifenLuo.WinFormsUI.Docking
- WinForms docking
- PSVRender
- Pixel drawing
- GGRLib
- Custom controls used in Temporal Flux
IFluxPlugin Interface
In order for Temporal Flux to recognize
your plugin, you will need to inherit a public class from the
IFluxPlugin interface. Your plugin will also need to be in
the same directory as Flux's executable.
- Members
- nFluxSchema
(ushort) - The schema of your flux files. This should change very
rarely, typically only when you are completely rewriting your flux file
format.
- nFluxVersion (ushort) - The version of your flux files. This should change each time you change your flux file format.
- nFluxMinSchema (ushort) - Minimum schema your plugin will support reading.
- nFluxMinVersion (ushort) - Minimum version your plugin will support reading.
- PlugMenu
(MenuItem) - Your plugin's menu that will appear in Flux's plugin list.
Essential for launching your plugin.
- sPlugName(string)
- Name of your plugin, used internally by Flux. You should avoid
chainging this once you decide on a name, as your plugin's flux files
will no longer be compatible.
- RecDict
(Dictionary<string, int>) - Provides a list of names and
corresponding values for each record type your plugin supports.
This is primarly used during the export / import process. The value for a record type should never change.
- RecList
(List<SaveRecord[]>) - Essentially a double dimensioned
array of
your records, the first dimension of the array is a List so it can be
grown dynamically. Flux looks at RecList to
find modified records to save.
- Methods
- all of these methods return a bool value indicating success (true) or
failure (false)
- bool
Close() - Called by Flux when shutting the application
down. Should contain plugin cleanup code. Probably
won't be needed for most plugins.
- bool
GetRecords() - Called by Flux when a new ROM is opened.
Should contain whatever code you need to call each record's
Get method.
- bool Init()
- Called by Flux when your plugin is first loaded. Should
contain your initialization code.
SaveRecord Class
The SaveRecord class is used to read and
write records from the ROM. There are four pre-defined types,
as indicated by the PointerType enumeration. To use any of these types,
simply assign a value to the nPointerType variable. Flux also
has a few other more complex types not available publicly at
this time (and likely of limited use).
- Predefined
types
- Simple
- Simple data used as is without extra processing. Can be
compressed or uncompressed.
- Local
- Reserved for future use. Currently defaults back to Simple.
- SizedByAddress
- Data whose
size is determined by the difference between adjacent addresses.
Each
record typically consists of several subrecords. Used by
Treasure and
Location Exits.
- OWExit
- Overworld Exit
data, similar to Simple data, but requires pre / post processing.
Not
likely to be useful for any other records.
- Members
- bCompressed
(bool) - True if the record is compressed.
- bCreateEmpty
(bool) - True if the record should be created at full size, even if the
record is empty or invalid.
- LocalRec
(SaveRecord[]) - Subrecords contained within this master record.
Typically used for SavedByAddress data records.
- nData
(byte[]) - The editable (decoded) data obtained from the Get
method.
- nDataSize
(uint) - The current size of the editable data.
- bFullFlux (bool) - True
if the record should have its full information stored to Flux files
(which typically is considerably more data than is needed to
reconstruct it). Only Custom Data records used this currently. Default: false.
- nID
(ushort) - Index of this record in its array.
- nMaxSize
(uint) - Maximum possible size of the record. Default value
of 0x10000.
- sName
(string) - Name of the record.
- nOrigAddr
(uint) - Original address of the record at load / save time.
- nOrigSize
(uint) - Original (encoded) size of the record at load / save time.
This should never be greater than the size of the ROM's banks
(0x10000).
- bOverride
(bool) - True if the record should ignore whether the space at
nOrigAddr is free or not. Useful for uncompressed, fixed
length, fixed address data (such as a Location's properties).
- Pointer
(PointerRecord[]) - All the addresses that point to this data in the
ROM. See the PointerRecord class.
- nPointers
(ushort) - Number of valid pointer records. Typically this
value is not assigned directly, but by assigning an array to the
Pointer member.
- nRecords
(uint) - Number of local records contained in the LocalRec
member. Typically used for SavedByAddress data records.
Default value of 1.
- RecClaim
(ClaimDel) - Delegate of the record's Claim method.
- RecExport (ExportDel) - Delegate of the record's Export method.
- RecGet
(GetDel) - Delegate of the record's Get method.
- RecImport (ImportDel) - Delgate of the record's Import method.
- RecReseat (ReseatDel) - Delegate of the record's Reseat method.
- RecSave
(SaveDel) - Delegate of the record's Save method.
- RecSize
(SizeDel) - Delegate of the record's Size method.
- nRecSize
(uint) - Size of each local record contained in the LocalRec member.
Typically used for SavedByAddress data records.
Default value of 1.
- Methods
- bool Claim()
- Calls the record's Claim delegate, claiming its original location's
space in the ROM. Automatically returns true if the record is
modified or nOrigAddr is set to 0.
- void Export(BinaryWriter Bout)
- Call's the record's Export delegate, exporting the record to a flux
file. Write the record's data out using the Bout variable.
- void Get()
- Calls the record's Get delegate, decoding the record's data to an
editable form stored in nData.
- void Import(BinaryReader Bin, ushort anSchema, ushort anVersion)
- Calls the record's Import delegate, reading the data from file.
Read the record's data in with the Bin variable. Check for
file format using anSchema and anVersion. Minimum schema and
version values have already been checked, and the record will be
set to modified.
- void
PointersSave(uint nNewAddr) - Saves the record's pointer
records. nNewAddr is the new address the pointers should be
set to.
- void Reseat() - Calls the record's Reseat delegate, forcing the record to be saved to a new location. Record has been set to modified.
- bool Save()
- Calls the record's Save delegate, writing it into its original space
if it will fit, or a new address otherwise. Automatically
returns true if the record is unmodified. Sets
bModified to the delegate's return value.
- uint Size()
- Calls the record's Size delegate, returning the records current,
encoded size. Primarly used during the save process.
If you need to define a new type, you'll
need to inherit from the SaveRecord class and create new delegates for
RecClaim, RecExport, RecGet, RecImport, RecReseat, RecSave, and RecSize. Its possible to have
a mixture of predefined and newly defined delegates (OWExits uses its
own Get and Size, but Simple's Save and Claim).
PointerRecord Class
The PointerRecord class is designed to
properly store and save all of a records pointers, no matter how
complex they may be.
- Members
- bAddress
(bool) - True if nAddress and nByte should be written
- nAdjust
(short) -
Adjustment to the pointer's address, if its offset from the actual
address. Example, data is at 242C00, but the pointer points to
242C02.
- bBank
(bool) - True if the nBank should be written.
- nBank (uint)
- Address of the pointer's bank byte. Mask: 0xFF0000.
- nByte
(uint) - Address of the pointer's least significant, or
"byte" byte. Mask: 0x0000FF.
- nRange
(uint) - Address of the pointer's range byte. Mask: 0x00FF00.
- Methods
- PointerRecord(uint
anBank, uint anRange, uint anByte, short anAdjust, bool abBank, bool
abAddress) - The explicit constructor, setting each member
value
- PointerRecord(long
nAddress, short anAdjust, bool abBank, bool abAddress) -
Constructor assuming only the pointer's address member values.
If abBank is true and abAddress is false, nAddress is assumed
to be nBank's address. Otherwise, nAddress
is assumed to be nByte's address, with nRange (+1) and nBank (+2)
immediately following.
- PointerRecord(long
nAddress)
- Constructor assuming most of the pointer's member values.
nAddress
is assumed to be nByte's address, with nRange (+1) and nBank (+2)
immediately following. Assumed to have no adjustment and that
all
bytes should be written.
- uint
GetFileOffset() - Returns this pointer's value from
GlobalShared's GetFileOffset(uint[] nData), providing its offset in the
ROM's data.
- uint
GetLocalFileOffset() - A local pointer version of
GetFileOffset.
- ushort
SizedByAddressRecROMSize() - Returns the size of the
current SBA record as stored in the ROM's data.
GlobalShared Class
The GlobalShared class contains a number
of static helper members and methods.
- Members
- sCardDir
(string[]) - Cardinal directions as used by the Facing event commands.
(Technically a misnomer.)
- sColorMathColors
(string[]) - Colors as used by the Color Math commands.
- CoordStatus
(StatusBarPanel) - Coordinates portion of the status bar.
- DockMan
(DockPanel) - WinForm docking manager.
- FreeSpace
(cFreeSpace) - Contains all of the freespace available in the ROM.
See class cFreeSpace for more information.
- KnownAddrHash
(Hashtable) - String names of known memory values. Should
only be used directly for adding more addresses.
- sLocations
(string[]) - Location names as they appear in the Locations
dropdown list.
- sNPC
(string[]) - NPC names as they appear in the event editor.
- sOverworld
(string[]) - Overworld names as they appear in the Overworlds
dropdown list.
- sPC
(string[]) - Character names as used throughout the ROM.
- PostStatus
(PostStatusDel) - Delegate for posting a status message. See method
below, or assign your own function.
- nRomAddr
(List<uint[]>) - Data ROM addresses, for each ROM
type. Should only be used directly for adding more addresses.
- nRomType
(byte) - Opened ROM's type (0 - Jap, 1 - Eng, 2 - Beta).
- nRomValue
(List<ushort[]>) - ROM data amounts, for each ROM type.
Should only be used directly for adding more values.
- sSoundEffect
(string[]) - Sound effect names as they appear in the event editor.
- sStore
(string[]) - Shop names as they appear in the event editor.
- WorkingData
(byte[]) - The ROM's raw data. This should only be used on a
read-only basis. It should primarly appear in your SaveRecord
Get delegates, and only in edge cases outside of them. This
item is a likely candidate for future obsolescence.
- nZoomFactor
(byte) - Graphical zoom factor, as used internally by Temporal Flux.
- Methods
- uint
GetFileOffset(uint[] nData) - Get the
file offset from the three addresses stored in nData, each
pointing to a different byte of the pointer (Bank, Range, and Byte).
- uint
GetFileOffset(int nAddrOffset) - Get the file offset from
the ROM data at address offset nAddrOffset. (Careful which type you
pass in.)
- uint
GetRomAddr(RomAddr RomAddress) - Retrieve a ROM address
for the current ROM type.
- ushort
GetRomValue(RomValue RomVal) - Retrieve a ROM value for
the current ROM type.
- string GetStrFromGroup(StrRecType nGroup, ushort nIndex) - Get string from group nGroup with index nIndex. Useful for getting enemy or item names.
- string
KnownAddr(uint nAddr)
- Returns a string value for the memory address at nAddr in the form
"Mem.Address". If the address is unknown, a hex value is
appended
instead.
- void PostStatus(string sStatus) - Post a message to Flux's main status bar.
- Inherited
Methods
- uint
GetFileOffset(uint nSnesAddr) - Get the file offset
directly from the passed in value. (Careful which type you pass in.)
- uint
GetInt24(byte[] nSrc, uint nOffset) - Get an unsigned 24
bit integer from the data nSrc at offset nOffset.
- uint
GetSnesAddr(uint nFileOffset) - Get the SNES address
equivalent of a file offset.
- ushort
GetShort(byte[] nSrc, uint nOffset) - Returns a ushort
from the data nSrc at offset nOffset. (All variants of this function
work the same.)
- string
HexStr(int nVal, int nPad) - Returns a hex string of the
value nVal padded to nPad digits. (All variants of this function work
the same.)
- string
HexStr(ushort nVal) - Returns a hex string of the value
nVal, padded to four digits.
- string
HexStr(byte nVal) - Returns a hex string of the value
nVal, padded to two digits.
- void
SetInt24(byte[] nDest, uint nOffset, uint nVal) - Set an
unsigned 24 bit integer in th data nDest at offset nOffset to value
nVal.
- void
SetShort(byte[] nDest, uint nOffset, ushort nVal) - Set a
ushort in the data nDest at offset nOffset to value nVal.
(All variants of this function work the same.)
cFreeSpace Class
The cFreeSpace class is essentially a
doubly-linked list containing all the known free space in the ROM.
This is not a live variable and is reconstructed on
request by Temporal Flux, typically at the start of the saving process.
- Methods
- uint
AddData(uint nSpaceNeeded) - Returns the address to the
first chunk of free space at least nSpaceNeeded bytes in size.
- void
AddSpace(uint nStartOffset, uint nEndOffset)
- Adds space to the list, from offset nStartOffset to offset
nEndOffset. Should only be used in edge cases where the
record's
address will affect the record's data, possibly causing it to not fit
in the space it had already taken. If it doesn't fit, you
should add
the space back into the list. Example, Location Events
contain a
string index pointing to the space immediately after it.
Should be immediately followed by SortAndCollapse().
- bool
ClaimSpace(uint nStartOffset, uint nEndOffset) - Claims a
chunk of free space, from offset nStartOffset to offset
nEndOffset. Returns true if the full space is available.
Should only be called in your record's Claim delegate.
If ClaimSpace returns false, you may want to set your record
to modified.
- bool
FitsSpace(uint nOffset, uint nSpaceNeeded) - If there are
nSpaceNeeded bytes available at offset nOffset, returns true and claims
the space.
- void
SortAndCollapse() - Sorts the list of free space and
collapses adjacent chunks contained in the same bank. Should
only be used in edge cases after calling AddSpace.