The following warnings occurred:
Warning [2] count(): Parameter must be an array or an object that implements Countable - Line: 895 - File: showthread.php PHP 7.3.33 (Linux)
File Line Function
/showthread.php 895 errorHandler->error




Users browsing this thread: 2 Guest(s)
FFVI - Lore Complete

#1
Posts: 9
Threads: 1
Thanks Received: 0
Thanks Given: 0
Joined: Sep 2017
Reputation: 0
Status
None
A quick introduction of myself and dev background are further down, as this is my first post, but I'll detail my project first to maintain the common format of threads in this section. Since this actually covers both the mod and the tool I'm using, this post is a bit lengthy; if I should put the tool details in a different subforum/thread, just say the word.

This is actually a two-part project: The FF6 mod itself, and then the internal tools I've developed that I'll eventually make public (probaby via GitHub) once they're further along and have a bit more polish. Beyond the mod itself, I'd very much like to give back to such a generous and knowledgeable community.

- - -

The Mod:
The goal of the project is to add a considerable amount of additional information to the game in the form of expanded dialogues, books, and examinable items. There's a fair bit of FF6 lore that isn't available in the game, but still comes from official sources, if you're willing to do the research (which has actually taken up about half of my time spent on this project). Developer interviews, official guides, etc. Finding the information isn't terribly difficult (quite a few wikis include the information), but I don't trust everything I read to be "canon," so I've also been doing a lot of cross referencing for accuracy, to ensure I'm mostly only including official information, and not just "fanfic."

Another goal is to include additional character events and interactions that developers mentioned they had wanted to include, but didn't due to lack of space, time, or some other reason. I may also flesh out some of the characters a bit more, though I'd be doing so in ways that couldn't really be considered part of the official storyline.

Eg: Mog was criminally glossed over, and probably has more reason to upset than most of the other characters. He effectively loses his entire village; for all we know, he could be the last of his kind. One of those lost probably being his girlfriend (I can elaborate, but see: Molulu Charm and dev interviews). What does he have to say about this? "Oh, hey, you're not dead. Ok, let's go. Also, I know a guy."

Finally, I'd like to do a little rebalancing to make the game a little more interesting. Beyond the usual bug fixes that are often included in patches (eg: The Evade issue), some of the stats in the game just don't have that much use in comparison to other things you could be boosting via espers (I'm looking at you, Stamina). I was also always a bit annoyed by every character being able to learn any spell; really killed some of uniqueness of some of the characters, and made others incredibly undesirable near endgame. BNW's solution to this problem was fantastic, though I don't imagine I'll be going quite as far in my revamps; I'd like most of my revamps to be mostly invisible, outside of the additional content.

I've used the Ted Woolsey Uncensored Edition as a base, as it already includes a lot of critical fixes, and a good translation foundation.

Once ready for release, I'll be providing three versions of the mod:
  • Complete: All features
  • Expanded: Minus the rebalance (all original mechanics and items are vanilla, changes are mostly just cosmetic in nature). Additional events still included.
  • Canon Only: Just the examinable books/objects detailing information about the setting, timeline, and character backgrounds. Nothing that can't be confirmed as coming from an official source.

- - -

Features

Main Features (All Versions):
  • Every book (the books open on tables and bookcases) will be readable, and most will provide additional information about the setting and its timeline.
  • Certain objects in the game will also be able to be examined. Dead end? Well, at least there's probably something there to be "looked" at. It's not all just decoration.
  • Some character dialogue will be expanded or slightly altered to make some details about in-game events a little more clear, or tips to point players in the direction of some easily-missed cutscenes. Eg: I only FINALLY got to see the cutscene between Setzer and Cid on the Blackjack... that window is extremely narrow.
Expanded Features (Non Canon, Optional):
  • Add additional in-game events that devs originally wanted to include, but didn't. Eg: Shadow revealing his identity to Strago in a pub, Gogo and Umaro appearing to some extent in the WoB.
  • More fleshing out of some of the characters that never really got much attention (while trying to stay as close as possible to official data... some extrapolation will be necessary, though).
  • Minor map additions to fill in some missing details. Eg: Where does Castle Figaro house its chocobos in the middle of the desert? What's inside the burned house in Kohlingen?
Rebalance Features (Optional):
  • All stats should be useful in some capacity. Eg: I've already done a quick hack to add 1/4 Stamina to Defense, and reflect that change in all menus.
  • Nerf some of the more OP items that made the game too easy. Eg: Economizer/Celestriad. 
  • I agree with BNW's idea that tents/sleeping bags are too useful. But I don't want to remove them entirely, so I'll just be removing them from store listings.
  • Enforce Esper restrictions, and redo spell lists so characters only learn spells that make sense to their character, while allowing them to remain useful.
  • Alter character abilities that are less useful. Eg: Allow Runic to be replaced with Magitek (Shock would also make sense, but there are already a ton of mods doing that), speed up Bushido.
  • Rebalance spells/abilities that players would normally pass over to be more useful. Eg: Merton/Crusader, Tornado, Spiraler.

- - -

The Tools -- (Warning: Includes minor code samples/examples, feel free to skip if this isn't your thing)
I found manual hex editing and assembly patches became a bit too much of a pain to maintain, as they aren't easy to read without excessive commenting, hard to come back to after a break in development, and creating ROM backups all the time was too much of a chore.

My solution was to create a core "SNES Editing" library in C# to apply the same changes you would via a hex editor or xkas assembly patch. You instantiate a "HexPatcher" object, and then build up your edits in the same way you might a StringBuilder (I used this approach a few years ago to create SQL queries for use with a micro-ORM, Dapper, and it worked really well). While I would normally prefer a more data-oriented approach, creating "patches" directly in C# provides a lot of IDE support (IntelliSense is a crutch I can't leave behind), and rather than memorize a bunch of 65816 opcodes+operands, I can do things via method calls that are quite a bit more readable and self documenting. Not to mention the usefulness of using named constants for common offsets and byte values. Everything ends up reading a bit more like plain English.

Doing things this way, devs could create their own patching programs to produce ROM hacks of a more dynamic nature, with parameters. Example: See the Link to the Past randomizer. It was actually where I got the idea to do all my edits in C#. The idea isn't so much to create a full-fledged tool, so much as to provide a base so making your own is a lot easier and straight-forward.

The core library itself could probably be used for other ROM hacks, not just FF6. Hence why it's its own library. HexPatcher can be used for any basic hex editing, then there's Asm65816Patcher inheriting from it that covers all SNES-specific opcodes, but "renamed" to be a little more obvious as to what some opcodes do. Eg: LDA addr becomes GetAddressValue(ushort address).

Then I have a main "FF6Hack" project utilizing and expanding the library for FF6 specific hacks, as well as containing numerous classes housing named constants/enums for commonly used offsets and byte values. 

Event hacks have their own difficulties, so I made an EventPatcher, also inheriting from HexPatcher, that handles inserting new events. Since free space for new events is a thing, it also include utilities for moving blocks of bytes to new offsets, inserting the appropriate jumps, and returning a MovedBytesReport that details how many bytes were made available and the offset where its safe to insert your new events. With a few extra utility functions for my own hacks, adding a "readable book" to the game is as simple as making some free space, then calling CreateReadableBook(Book bookDetails).

So to sum up: You load your ROM file into a byte array, instantiate a patcher object, build up your edits similar to how you'd build up a StringBuilder, and then when you're ready to apply your edits, you just call patcher.Apply(byte[] byteArrayForYourROM). Finally, write the byte array to file with something like File.WriteAllBytes("patchedRom.smc", byteArrayForYourROM).

In my case, I have a clean version of the original ROM in my project resources, load it into a new byte array, have the program apply all my "patches," and then write to a new file. This avoids having to make frequent backups of the ROM, as I'm always applying my edits to a clean version.

For my own use, I'm basically just using C# patches in the same manner someone else might a batch file + .asm files. To each their own. Do things the way you're most comfortable with. This is just my preference.

I still have a long way to go with this library. I'm still hardcoding a lot of offsets, and have trouble with some of the math involved in translating the different banks to the appropriate offset areas, so I just hardcode quite a few values, and also have the HexPatcher "map" banks to relevant offset bytes (like translating bank CC to 0C). Not really maintainable solutions, so will have to be fixed eventually.

I was about to post a code block of an example use of the patcher, but I think I'll do that with another post in this thread, as this post is already pretty lengthy.

- - -

Other Tools I'm Using
There are still quite a few gaps in my knowledge (some already mentioned). For instance, how to edit maps directly from the C# patcher. Or edit dialogue/item data directly from the C# patcher. How to expand/move banks to create more free space, beyond those minor bits used for event edits. These are things I plan to have the library handle eventually, but for the time being, I'm relying on some of the staple utilities to get the ball rolling:
  • FF3usME: For editing dialogue, renaming things, altering item/esper/character data.
  • FF6LE-CE: For actually placing event flags/tiles in maps.
Until I get those mentioned features implemented in my own code, these utilities allow me to test planned hacks to make sure they don't bork anything, and being able to export/import data is IMMENSELY helpful. Thank you so much, to the dev(s) who worked on them. I am infinitely humbled by your dedication, and hope I can eventually assist the community in a similar capacity for those who prefer a code-first approach (you've already got data-first and user-friendly utilities covered in a way I couldn't hope to catch up with).

- - -

My Background:
Not just to talk about myself, I include this in the event anyone would like to assist in the areas I'm having some trouble on, and wants to know the experience level of the person they'd be dealing with.

I only started getting my feet wet with ROM hacking a little over a week ago. I started getting interested about halfway through my playthrough of Brave New World (fantastic mod, nearing the end of it). Thanks to this site in particular and its wealth of information, I've managed to learn quite a lot more about hex editing, assembly, and event hacking in a relatively short time. It probably also helps that I make my income as a game dev contractor/consultant, setting my own hours for the most part, and my current contract has hit a lull while we wait for our first Steam release to be approved. So, yeah, a lot of 12-18 hour days working primarily on this FF6 hack. I think it's fair to say I've been bitten by the bug; it's the most fun I've had in a long time! Even once the lull breaks, though, I'll still have a lot of time to dedicate to the project, as I'm a shameless shut-in who ops to live in games and personal coding projects.

Most of my dev background is in mid-level languages (C# and Java), but I've also worked JS, PHP, Python, and a little C++. C# is my preferred language, but I've always used whatever tool is most appropriate for the task. Roles at previous companies have also seen me doing a surprising amount of penetration and exploit testing (mostly man-in-the-middle style attacks and light hex editing).

I always wanted to get closer to metal, but I learn mostly by working on things having an actual purpose (if it's not going to see potential use by other people, I lose interest very quickly). So, this has been a great opportunity to finally pick up some Assembly, and learn more about machine language beyond simple string/number replacement in a hex editor.

- - -

Places I Could Use Help:
As stubborn as I am about wanting to do/learn everything myself, and hate asking for help, some assistance in these areas could really accelerate things:
  • After going through every single map, I counted 12 instances of "books open on tables" (fewer than I expected). These were originally the only books I was going to make interactable. That's not really enough to cover the three pages of notes I made for additional information I want to add, though, so I decided to also include bookcases. That... was a different story. I counted around 44, which is WAY more than I have content for. I could just make SOME bookcases interactable, but I prefer consistency, so if anyone has ideas for what else I could have in books, beyond the already mentioned setting history and additional character details, I'd love to get more suggestions.
  • I saw that FF6LE-CE/Zone Doctor was also implemented in C#. I'd love to get permission to lift some of the code. Given the greenlight, even better if I can get some pointers on which classes and methods I should look at if I wanted to, say, place event tiles/flags directly into maps. Ideally, I'd eventually like to be able to do that with a method call like patcher.PlaceEventTile(mapId, x, y, eventId). If I could do that, I could truly implement single-line solutions for each book placement. That'd be keen! I said keen. Bringing it back.
  • Anyone forward me to some info on how to replace dummied monster sprites with custom ones? I didn't find anything in the existing utilities (maybe just didn't look hard enough), and I'd love to put the Nutkin/Nut Eater enemy into the South Figaro area. Sabin is apparently afraid of "Nut Eaters," and I'd LOVE to make reference to that beyond just simple text.
  • In vein with the previous question, any idea of an offset I could branch to in order to make a single character automatically "run" from a battle? Even if it just set their animation to running, without actually running? My first instinct was to look at the Phantom Train battle, but I'm not seeing anything obvious.

- - -

Big thanks to anyone who actually managed to get through that wall of text and put up with my numerous parenthetical statements and run-on sentences. More thanks to anyone who offers suggestions or corrections. To those that can lend development assistance in the form of information, I'll pay you in favors (favors are the best currency).

And if any of this is in the wrong section, or should be split/moved into another thread, again, just say the word! As mentioned, this is my first post here, and possibly a bit presumptuous to do it in the Den, but I've been lurking for ages (previously just to find mods, recently for hacking info), have immense respect for the community, and don't want to step on any toes.

As I said I would, here's a quick example of an example "patch" using the SNES Editing and FF6Hack libraries. This is the one that adds 1/4 of a character's Stamina to their Defense, and reflects that information in the Stats and Equip menus.

Code:
public static class StaminaDefenseHack
{
    private const ushort InBattleDefense = 0x3BB8;
    private const ushort InBattleStamina = 0x3B40;
    private const ushort StatScreenDefense = 0x11BA;
    private const ushort StatScreenStamina = 0x11BA;
    private const ushort EquipBeforeStamina = 0x3002;
    private const ushort EquipBeforeDefense = 0x301A;


    public static void ApplyAll(Asm65816Patcher asm65816Patcher)
    {
        ChangeBattleDefenseAlgorithm(asm65816Patcher);
        ChangeMenuDefenseAlgorithms(asm65816Patcher);
    }


    public static void ChangeMenuDefenseAlgorithms(Asm65816Patcher asm65816Patcher)
    {
        // Replace loaded Defense in Stats screen with new algorithm.
        asm65816Patcher.ChangeOffset(0xC36019);
        asm65816Patcher
            .JumpToSubroutine(0xF1E0);

        // Replace loaded "before" Defense in Equip screen with new algorithm.
        asm65816Patcher.ChangeOffset(0xC39192);
        asm65816Patcher
            .JumpToSubroutine(0xF1EB);

        // Replace loaded "after" Defense in Equip screen with new algorithm.
        asm65816Patcher.ChangeOffset(0xC392D1);
        asm65816Patcher
            .JumpToSubroutine(0xF1E0);

        // Algorithm that changes how Defense is calculated in Stats and "after" Equip screen.
        asm65816Patcher.ChangeOffset(0xC3F1E0);
        asm65816Patcher
            .GetAddressValue(StatScreenDefense)
            .DivideBy2()
            .DivideBy2()
            .AddNumberFromAddress(StatScreenStamina)
            .TerminateSubroutine();

        // Algorithm that changes how Defense is calculated in "before" Equip screen.
        asm65816Patcher.ChangeOffset(0xC3F1EB);
        asm65816Patcher
            .GetAddressValue(EquipBeforeStamina)
            .DivideBy2()
            .DivideBy2()
            .AddNumberFromAddress(EquipBeforeDefense)
            .TerminateSubroutine();
    }


    public static void ChangeBattleDefenseAlgorithm(Asm65816Patcher asm65816Patcher)
    {
        // Replace loaded Defense in battle with new algorithm.
        asm65816Patcher.ChangeOffset(0xC20CD1);
        asm65816Patcher
            .JumpToDistantSubroutine(0xC26515);

        // Algorithm that changes how defense is calculated in battle.
        asm65816Patcher.ChangeOffset(0xC26515);
        asm65816Patcher
            .GetAddressValueWithYIndex(InBattleStamina)
            .DivideBy2()
            .DivideBy2()
            .AddNumberFromAddressAtIndexY(InBattleDefense)
            .TerminateDistantSubroutine();
    }
}

All methods in the patching libraries are documented, so when using in an IDE like Visual Studio, you can also see information about what an operation is actually doing, total bytes used by the opcode, and things jump distance restrictions.
Quote  
[-] The following 6 users say Thank You to justonecog for this post:
  • madsiur (09-08-2017), Rjenyawd (09-11-2017), Robo Jesus (12-24-2017), Setzer (07-04-2020), SSJ Rick (09-08-2017), Turbotastic (09-09-2017)



Messages In This Thread
FFVI - Lore Complete - by justonecog - 09-07-2017, 09:07 PM
RE: FFVI - Lore Complete - by SSJ Rick - 09-08-2017, 12:41 AM
RE: FFVI - Lore Complete - by GrayShadows - 09-08-2017, 04:12 AM
RE: FFVI - Lore Complete - by justonecog - 09-08-2017, 07:11 AM
RE: FFVI - Lore Complete - by GrayShadows - 09-08-2017, 12:41 PM
RE: FFVI - Lore Complete - by madsiur - 09-08-2017, 07:04 PM
RE: FFVI - Lore Complete - by justonecog - 09-08-2017, 10:02 PM
RE: FFVI - Lore Complete - by Robo Jesus - 12-24-2017, 02:45 PM
RE: FFVI - Lore Complete - by justonecog - 01-03-2018, 02:38 AM
RE: FFVI - Lore Complete - by justonecog - 09-10-2018, 06:31 PM
RE: FFVI - Lore Complete - by justonecog - 08-05-2022, 02:39 PM

Forum Jump:

Users browsing this thread: 2 Guest(s)


Theme by Madsiur2017Custom Graphics by JamesWhite