• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
March 28, 2024, 01:33:45 pm

News:

Don't be hasty to start your own mod; all our FFT modding projects are greatly understaffed! Find out how you can help in the Recruitment section or our Discord!


(App) MassHexASM: Encode directly to little endian (v13 Update: 1/11/2017)

Started by Glain, May 08, 2011, 12:41:12 am

Glain

Latest version now included with FFTPatcher suite! (Thread: https://ffhacktics.com/smf/index.php?topic=7163)

---

After being frustrated with manually switching ASM byte order, I've decided to write MassHexASM, a program that lets you encode directly to little endian, and furthermore, should be able to encode ASM in a format where you just copy/paste the output to an XML patch (or what have you).

This program was written in C#/.NET, so you'll need some version of the .NET framework to get this to run. I believe it should work with .NET version 2.0 or later. Other than that, should be all good. Let me know if you find bugs and I'll do what I can to fix 'em.

Note on using the program: If you define a label, you need to put a colon ( : ) after it. If there is a command on the same line, separate it from the label by at least one space.

Some differences between MassHexASM and the Renegade64 assembler:
     * The little endian format uses the correct byte order: B4,B3,B2,B1. It also outputs the hex directly instead of trying to format for Gameshark.
     * My program encodes BEQ and BNE instructions properly. Renegade64 switches the order of the registers for some reason, which it can get away with because they're just used for an equality check, but it is still weird.
     * Encoding and decoding in the same form with little endian format. In testing, I've looked in the various XML files used by FFTorgASM, pasted patches straight into my program, entered a starting address, specified little endian and decoded it. Useful if you've got encoded hex but can't remember what the ASM is.
     * Ability to specify a starting address without using .org (Important for decoding as well)
     * You can pad the output with spaces if you want to preserve formatting when pasting into an FFTorgASM patch.
     * You should be able to use same-line labels. (i.e. put a label and the next instruction on the same line)
     * Registers can use the $[num] format. (e.g. $4 instead of r4). You can still use names like $s0, $t2, etc.
     * You can specify negatives as offsets in save/load instructions (i.e. -0x7fad, as the screenshot shows). The negative sign has to be before the 0x, not after.
     * Encodes statements without regard to whether or not they make sense. This means Renegade64 will stop you in certain cases where my program won't, primarily when BEQ/BNE addresses are invalid.

Java version now available... check the attachment list. To use it, run "java -jar JMassHexASM.jar" in the command line in the directory that contains the jar file. (Updated: I fixed a bug with the Java version)

Changelog:

v13:
      * LEDecoder has been added to MassHexASM, accessed via a menu item (Form -> LEDecoder), and LEDecoder is no longer a standalone program.
      * MassHexASM now checks the ASM upon encoding or decoding and displays warnings for various possible hazards, listed below.
      * MassHexASM uses the latest version of the ASM Encoder/Decoder, which includes numerous fixes, as well as the latest changes:

     * Added check functionality that warns about various possible hazards:
        * Load delay (Attempt to use a loaded value from memory immediately after loading it; ignored in PSP mode)
        * Unaligned offset (When doing a memory load or store)
        * Using mult or div within 2 commands of mflo/mfhi
        * Adding or subtracting a value from the stack pointer register ($sp, r29) that is not a multiple of 8
        * Putting a branch inside a branch delay slot
       
    * Added the ability to use %hi(address) and %lo(address) to get the high and low 16-bit parts of an address.  The low 16-bit portion is considered to be signed.  e.g.:
        * .label @address_current_action, 0x80192d90
        * # (...)
        * lui   t0, %hi(@address_current_action)
        * # (...)
        * lw    t0, %lo(@address_current_action)(t0)
       
        * Note that %hi(address) will be one higher than first 16 bits when the low 16 bit value is negative.
        *   e.g. %hi(0x8018f5f0) = 0x8019; %lo(0x8018f5f0) = -0x0a10 (0xf5f0).
        * This means that the %hi,%lo combination works well with load and store commands, and also with the (lui, addiu) pattern, but not with the (lui, ori) pattern.
       
    * Fixed some issues with the load and store psuedoinstructions when using values between 0x8000 and 0x10000.
       
    * Modified the error checking functionality to report more errors, particularly when an undefined label is referenced.
       
    * Now recognizes GTE and COP0 register names as used by pSX's disassembly.
    * Added beqz (branch if equal to zero) and bnez (branch if not equal to zero) psuedoinstructions.
   
    * Fixed potential issues with byte order that could have occurred if running on a big endian machine.
   
    * Added "replaceLabels" optional attribute to the <Location> tag in XML patches, which, if set to "true", will replace any labels found in the hex with the correct hex address.  The idea here is basically to be able to create dispatch tables using a list of labels if so desired.
   
    * (Undocumented from last release)
    * Added "equivalences" which function similar to macros. Defined with .eqv and are replaced with the specified value before encoding.  e.g.:
        * .label @address_controller_input, 0x80045944
        * .eqv   %start_button_flag, 0x0800
        * # (...)
        * lw     t0, @address_controller_input
        * nop
        * andi   t0, t0, %start_button_flag
        * # (...)

    * The "li" pseudoinstruction now accepts negative values correctly.

v12:

     * Changed the window anchoring so that resizing the window causes the ASM and/or Hex textboxes to expand.  Expanding the window to the right now causes the ASM textbox to expand (as well as the messages window); expanding downward causes both ASM and Hex to expand.
     * Any label starting with the '@' character is now a "persistent label" that will stay around even if not defined in the current code block.
     * Added ".label" directive to define label addresses without putting them inside the code.  The format is: .label (name), (address).  Example: .label  @clear_data_block, 0x05e644
     * Decoding no longer requires newlines; you should just be able to paste straight from a hex editor and it will decode every 4 bytes (8 hex digits) as a command. 
     * Fixed some bugs relating to labels that contained a command on the same line.
     * The encode/decode textboxes are no longer limited to 32767 characters.

v11:

     MassHexASM

     * Both textboxes are now using a fixed-size font (Courier New) at a bigger size. Widened the ASM textbox to accommodate the bigger font.
     * Error reporting (in the "Messages" area) should now report more errors and be more specific.  You should at least get a warning if it skips a line entirely (e.g. an unrecognized command when encoding).  Decoding will also report unknown commands.

     LEDecoder

     * Can now specify starting address.

     Both (MassHexASM and LEDecoder)

     * "Mode" dropdown added to select between PSX/PSP modes (as well as a generic Base mode).  This will primarily affect coprocessor 2 instructions (GTE, VFPU) which differ between the two.  This won't restrict the instruction set completely to ones supported by the CPU.
     * Added support for many new MIPS instructions up to the MIPS32R2 instruction set.
     * PSX mode should contain GTE instructions. Format is slightly different from psxfin's disassembly. GTE registers (both data and control registers) can be referred to simply using the generic format $(num), which works with all register types.
     * Coprocessor 0 registers can also be referred to using $(num).
     * PSP mode should contain the VFPU commands as well as other PSP-specific commands (bitrev, max, min, etc).
     * With the new instructions recognized, there should be no more unknowns in PSX/PSP code!
     * MassHexASM and LEDecoder now both use the same encoding/decoding engine (as well as FFTorgASM, upon release of the next FFTP version).
     * You should be able to specify addresses >= 0x10000000 (either with the starting address textbox, or a .org statement).
     * Encoding/decoding uses an entirely new process and should be significantly faster (In my testing, a decoding of the PSP's EBOOT.BIN going from about 10s to < 3s on LEDecoder). You'll probably only notice the speed if encoding/decoding a LOT (thousands) of commands at once.
     * The input file formats have changed significantly with a lot more options/flexibility. I can give more detail if needed, though it's somewhat complicated...
     * Decoding a line can produce "illegal" if the decoder found the instruction and determined that the inputs are illegal/impossible (typically this can only happen with ins/ext instructions). An unrecognized encoding is still "unknown".  If the program hits an unexpected error trying to decode a line, it can produce "error", but this shouldn't happen if the program is working properly.
     * You can use ';' to denote comments, just like '#'.
     * Syscall and break should now properly use 20-bit immediates.
     * Decoding is less lenient; invalid code will produce more unknowns.

v10:
     * Fixed a bug where load/store instructions with negative offsets were encoded with incorrect hex (and were treated incorrectly as pseudoinstructions).

v9:
     * Fixed a bug where newlines in the assembly section were erroneously removed when encoding.
     * Added a "name registers" option that uses register names like r2 = v0, r4 = a0, r29 = sp, r31 = ra, etc, when decoding.

     * MassHexASM can now support many psuedoinstructons even if they take multiple lines. The list of psuedoinstructions here should mostly be supported. You can also do fun things like lw r2,0x80192d90 and lbu r3,0x801908cc(r4), although these commands always generate the entire address, so this will be less efficient in cases where you can reuse part of the address. Those two statements would become 5 lines of regular ASM, but this example can be done in 4. As a sidenote, these pseudoinstruction patterns are very apparent in FFT's ASM code.

v8:
     * When decoding, immediates will now properly show as signed or unsigned based on the instruction. These are the affected commands:
         Unsigned: andi, ori, xori, sltiu
         Signed: addi, addiu, slti

     * Added a "Show Addresses" option which will show the appropriate addresses on encode/decode in the left textbox.

     * Added support for 'select all' using ctrl+A.
     * Little Endian is now the default byte order.

v7:
     * Added support for srav, jalr, break (10-bit immediate), syscall (10-bit immediate) and trap (26-bit immediate) commands.
     * Fixed a bug where label addresses could be calculated incorrectly when the input contained instructions on the same lines as labels, resulting in incorrect hex for branch/jump instructions.
   
v6:
     * Fixed a bug where an instruction on the same line as a label could be parsed incorrectly.

v5:
     * Fixed a bug with encoding long immediates (such as in the j command) when all eight hex digits were not specified.

v4:
     * Fixed a bug where the program failed to encode certain I-type instructions (bgez,blez,bgtz,bltz,bgezal,bltzal).
     * Fixed a bug where the program could incorrectly decode certain I-type instructions (bgez,blez,bgtz,bltz,bgezal,bltzal).
     * Added support for mthi/mtlo instructions.

v3:
     * Added support for comments on the same line as commands. (They'll need to preceded by #)
     * Fixed a bug where labels would only be recognized if they were from earlier points in the code.
     * Fixed a bug involving placement of tab characters that could cause the program not to recognize lines of code.
     * Added support for nor/not instructions.

v2:
     * Can now decode to negative offsets in the appropriate cases for addi and similar instructions.
  • Modding version: Other/Unknown

Eternal

I'm sure this will be incredibly helpful for your fellow ASMers. Thanks for the contribution, it means a lot! :D
  • Modding version: PSX & WotL
"You, no less human than we? Ha! Now there's a beastly thought. You've been less than we from the moment your baseborn father fell upon your mother in whatever gutter saw you sired! You've been chattel since you came into the world drenched in common blood!"
  • Discord username: eternal248#1817

formerdeathcorps

Your tool is great: it makes Renegade64 obsolete and has a copy/paste feature.

Just as a digression:

Quote
8. You can specify negatives as offsets in save/load instructions (i.e. -0x7fad, as the screenshot shows). The negative sign has to be before the 0x, not after.


Does this also work with addi?
The destruction of the will is the rape of the mind.
The dogmas of every era are nothing but the fantasies of those in power; their dreams are our waking nightmares.

Xifanie

Awesome. Adding an option to save to quicksave would be terrific.
  • Modding version: PSX
Love what you're seeing? https://supportus.ffhacktics.com/ 💜 it's really appreciated

Anything is possible as long as it is within the hardware's limits. (ie. disc space, RAM, Video RAM, processor, etc.)
<R999> My target market is not FFT mod players
<Raijinili> remember that? it was awful

pokeytax

Quote from: formerdeathcorps on May 08, 2011, 02:34:40 am
Your tool is great: it makes Renegade64 obsolete and has a copy/paste feature.


What he said, I've already forgotten about Renegade64 after fifteen seconds of using this. The easy decode is great.
  • Modding version: PSX

Pride

This. Is. Incredible. Thank you so much!

Edit: Deleted Renegade, completely worthless now.
  • Modding version: PSX
Check out my ASM thread. Who doesn't like hax?

Glain

Thanks guys! Glad to see the program being used and speeding things up! Didn't expect I'd just waltz right in and make Renegade totally useless, but if that's what I've done then that's sorta hilarious and awesome at the same time.

Xifanie: Quicksave as in a pSX quicksave, like a save state? That would be interesting... I may have to look into that.

formerdeathcorps: I believe it would encode the negative offsets correctly, but would decode the hex to a positive offset. A new version I've just added to the original post should rectify that. I wasn't sure which instructions treated the offsets as postive/negative, so I got my hands on SPIM and played around a bit.

(I totally didn't just realize that the "addiu" instruction on the stack pointer that I keep seeing in subroutines is actually a subtraction instead of a huge addition... :) I was always wondering how that register got back to its original state... now it makes sense)
  • Modding version: Other/Unknown

Pickle Girl Fanboy

May 10, 2011, 12:06:44 pm #7 Last Edit: May 10, 2011, 04:50:44 pm by Pickle Girl Fanboy
You should tell the guys over at RHDN and gamehacking.org about this.
EDIT
Nevermind, I already did.

http://www.romhacking.net/utils/635/
^Gemini says this is better.

Lazy Bastard

Nice app. Mind if I add it to the Downloads section of GameHacking.org?

Incidentally, it should be noted that Renegade64 (which, by the way, has been superseded by RenegadeEX) isn't made useless by this tool, except in the specific way you previously used it. It's still a very good hacking tool, with many other uses.
I may be lazy, but I can...zzzZZZzzzZZZzzz...

GameHacking.org

Glain

Quote from: Lazy Bastard on May 10, 2011, 03:39:30 pm
Nice app. Mind if I add it to the Downloads section of GameHacking.org?

Incidentally, it should be noted that Renegade64 (which, by the way, has been superseded by RenegadeEX) isn't made useless by this tool, except in the specific way you previously used it. It's still a very good hacking tool, with many other uses.


Yeah, I'm pretty sure this context was understood for Renegade. Sure, you can host my program if you want; if I do make updates I'll probably put them here though.

Regarding armips: I checked it out, pretty cool. It looks like it's both an assembler and a patcher, which in certain situations is going to be easier, but in others may not fit as well, like in this case (Since we're using FFTorgASM as patcher, we really just needed an assembler). Just depends on what you're trying to do. If I was just going to assemble codes and was going to load a program as an external file, I'd just use PCSpim probably (heck, it even executes the code).
  • Modding version: Other/Unknown

Glain

All right, I'm releasing an updated version (v3) because I realized it needed a few fixes.

* Added support for comments on the same line as commands. (They'll need to preceded by #)
* Fixed a bug where labels would only be recognized if they were from earlier points in the code. (Branches to labels could only go backwards) (When defining a label you still need to put a : after it)
* Fixed a bug involving placement of tab characters that could cause the program not to recognize lines of code.
* Added support for nor/not instructions.

With this version I encoded a pretty big (100+ statements) code block with labels and comments (and using that as a test case was what prompted the release of this version). The goal, as always, is to be able to just copy/paste ASM and get the hex in the right format.
  • Modding version: Other/Unknown

Pride

  • Modding version: PSX
Check out my ASM thread. Who doesn't like hax?

Xifanie

May 21, 2011, 03:01:30 pm #12 Last Edit: May 21, 2011, 03:03:05 pm by Xifanie
I will need the source of this later on; I have an idea of creating an excel workbook which patches directly to the ISO.
It would take all the ASM hacks, and concatenate them perfectly next to each other to save a lot of space. It would also be able to remove ASM hacks; only and only if you have the spreadsheet alone that you patched with. Else it will not be able to remember the old code in order to restore it. It will also allow anyone to edit the code without worrying to much about other hacks.
I'd love to implement a "patch directly to quicksave" feature.
  • Modding version: PSX
Love what you're seeing? https://supportus.ffhacktics.com/ 💜 it's really appreciated

Anything is possible as long as it is within the hardware's limits. (ie. disc space, RAM, Video RAM, processor, etc.)
<R999> My target market is not FFT mod players
<Raijinili> remember that? it was awful


Glain

A few issues were brought to my attention with this, so it looks like it needed an update. I attached it to the original post. I also edited the OP to clean it up a bit.

Anyhow, v4's changelog:
     * Fixed a bug where the program failed to encode certain I-type instructions (bgez,blez,bgtz,bltz,bgezal,bltzal).
     * Fixed a bug where the program could incorrectly decode certain I-type instructions (bgez,blez,bgtz,bltz,bgezal,bltzal).
     * Added support for mthi/mtlo instructions.
  • Modding version: Other/Unknown

Pride

Like always, thank you for your updates on this.
  • Modding version: PSX
Check out my ASM thread. Who doesn't like hax?

FFMaster

Hey, this is a great program, but there is just one tiny thing I get annoyed at =p

For example, the jump command

instead of simply typing j 0xaaaaaa, i have to type j 0x00aaaaaa. If you could set it up so that it accepts both formats, that would be awesome. If not, no biggie, I'll just get used to adding a few 0's.
  • Modding version: Other/Unknown
☢ CAUTION CAUTION ☢ CAUTION CAUTION ☢

Glain

June 25, 2011, 12:57:11 pm #17 Last Edit: June 25, 2011, 01:14:18 pm by Glain
Ah, you've uncovered a bug. That was supposed to work, but the program was doing some things incorrectly. I've gone ahead and fixed it; I've attached a new version to the original post. Happy encoding... let me know if you find anything else that seems off!

Edit: I'm sure 0xaaaaaa is just an example, but if you do try to use that as a test case, I should probably point out that it isn't a valid address for j, as it's not a multiple of 4 and therefore can't be a code address :) I was testing encode/decode on it and was confusing myself when I saw that it decoded to [j 0xaaaaa8] but that's correct because it's the closest previous code address.
  • Modding version: Other/Unknown

Pickle Girl Fanboy

June 27, 2011, 05:47:49 pm #18 Last Edit: June 27, 2011, 06:52:34 pm by Pickle Girl Fanboy
Hey, is this written in C# or some other .NET language?

EDIT
Quote from: Glain on May 10, 2011, 08:28:47 pm
Regarding armips: I checked it out, pretty cool. It looks like it's both an assembler and a patcher, which in certain situations is going to be easier, but in others may not fit as well, like in this case (Since we're using FFTorgASM as patcher, we really just needed an assembler). Just depends on what you're trying to do. If I was just going to assemble codes and was going to load a program as an external file, I'd just use PCSpim probably (heck, it even executes the code).


Gemini said:
QuoteI really don't know why you'd need XML hacks when the same stuff (if not even better stuff) can be accomplished with simple batches and armips. Something as uncomplicated as a few .include commands can do this magic and much more.


EDIT
You can reply to Gemini directly at:
http://www.romhacking.net/forum/index.php/topic,12592.0.html

http://aerie.wingdreams.net/?cat=18
^Here's where you can download the lastest version of armips.

Glain

MassHexASM is written in C#. The reason I went with C# is primarily because I wanted access to the Windows forms and the web-like elements it contains (textboxes, buttons, what have you). ...Come to think of it, a lot of our apps would probably be more portable (for example, to Linux) if we wrote them in C++ using GNU gcc, or even Java, but that could be annoying.

armips is great and all, and we could use it, but there's no reason to uproot our current encoding/patching process, since we already have our patcher (FFTorgASM) and assembler (MassHexASM, as it takes the mantle from Renegade64). Not worth changing.
  • Modding version: Other/Unknown