Author Topic: What would it take to fix FF8's backgrounds (field files)?  (Read 35879 times)

LeonhartGR

  • *
  • Posts: 2577
  • ~Whatever...~ Enjoy life!
    • View Profile
    • LeonhartGR Productions
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #25 on: 2014-05-19 20:39:26 »
Steam version was a re-release unfortunately... that's about all the fuzz for mods anyway... but they managed to make directx 9 to work with the game. Only graphical updates so far are the sweetfx image management.

Covarr

  • Covarr-Let
  • Administrator
  • *
  • Posts: 3941
  • Just Covarr. No "n".
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #26 on: 2014-05-19 21:44:14 »
Only graphical updates so far are the sweetfx image management.
And the Japanese version has a pretty updated high-res font. I don't know the first thing about how they did that though.

LeonhartGR

  • *
  • Posts: 2577
  • ~Whatever...~ Enjoy life!
    • View Profile
    • LeonhartGR Productions
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #27 on: 2014-05-19 22:02:24 »
Yeah I should correct myself by defining graphical updates as the in-game ones...

Kaldarasha

  • *
  • Posts: 2449
  • Prince of Model Editing
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #28 on: 2014-05-19 22:38:33 »
Correct me if I'm wrong, but the menu system seems to be developed consequently for PC. There were different resolutions in the first place, so I think it was pretty easy for them to replace the fonts (we have done this already too).

Omzy

  • *
  • Posts: 205
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #29 on: 2014-05-20 00:43:43 »
Textures are usually 256 * 256, either 8- or 16-bit. Add 16 different palettes of 256 32-bit colors each and you've got 70-150kb of data to hash every time the game tries to upload a texture. Now add to the mix the fact that palettes are not static, the game (and especially field files) often writes directly to the palette causing the whole texture to be reloaded (and depending on how the palette is modified you could get a million or so different hashes just for that one texture).
I wonder if a different hashing algorithm would make this easier. The hash can be computed from the values of specific pixels normalized to black and white and stored as a string of binary digits. Most backgrounds should have a different pattern of digits if enough digits are used and a few will fail this check if they are largely homeogenous like the credits having mostly black, etc. With carefully chosen pixels and enough of them we might achieve perfect hashing. This may eliminate dependence on palettes and be more specific to patterns. Did that make any sense or am I speaking crazy? I have yet to dig my fingers into the dirt so it might sound abstract right now but I'm going to do some experimenting with patterns and see if it works.

Aavock

  • *
  • Posts: 303
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #30 on: 2014-05-20 02:11:45 »
The original version offers the option to choose between the low-res PSX font texture (1 256x256px texture) or the hi-res PC texture (2 256x256px textures) but the 2013 version removed this option and the hi-res font is now set by default. As I pointed out in the SeeD thread, the new japanese PC release features really sharp font so it would be interesting to see how it works (several 256x256px *.tex files or maybe 1024x1024px/2048x2048px single texture). Also in the main.fs original files there is a 512x512px *.tim file but I'm not even sure if it is an unused file or not.

Omzy

  • *
  • Posts: 205
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #31 on: 2014-05-20 04:40:36 »
I've been playing with hash functions and came up with this, which samples 16 distinct pixels in the VRAM image and compares their grayscales to generate a hashvalue based on their differences. It uses a threshold value for how large the difference must be and that determines if a 0 or 1 is written. Based on only 1 frame of gameplay, this works, however it may need to be expanded to 32 pixels or additional comparisons instead of a linear comparison maybe odds vs evens, etc, if we are to expect different values for every texture/palette combo in the game. Hopefully this sort of technique can eliminate the need for distinguishing between palettes.

Written in python, forgive the poor syntax/lack of efficiency, I've never used it before so I just googled how to do things really quickly
Code: [Select]
import PIL
from PIL import Image

img = PIL.Image.open("5.bmp")
rgb_im = img.convert('RGB')

diff = []
binval = []

for i in range(0, 16):
diff.append(0)
binval.append(0)

currvalue = 255

for i in range(0,16):
x = i*16
pixel = rgb_im.getpixel((x,x)) # diagonal line of pixels to sample
value = (pixel[0] + pixel[1] + pixel[2]) / 3 #grayscale
diff[i] = currvalue - value # difference from last pixel value
currvalue = value
binval[i] = diff[i]
if binval[i] < 10: # convert to binary value based on threshold
binval[i] = 0
else:
binval[i] = 1

hashvalue = 0
for i in range (0, 16): #generate hash value from binary values
hashvalue *= 2
hashvalue += binval[i]
print hashvalue

a = input()

Shard

  • *
  • Posts: 330
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #32 on: 2014-05-20 09:42:52 »
I wish some team would re-design the game in an alternative engine like unity...
This was something I was considering for a while. The problem being that the only legal way to make such an engine is to make it support the files that come with FF8, and we still don't completely understand how some of them work (as you can see from this thread). It's just not feasible at this time. Q-Gears is feasible because we know basically everything about FF7.

Given that we'd need to understand the game files completely before making such an engine (at which point we'd probably already have better texture support), the only real benefit you'd get is higher frame rates, shader support, and extended scripting capabilities.

LeonhartGR

  • *
  • Posts: 2577
  • ~Whatever...~ Enjoy life!
    • View Profile
    • LeonhartGR Productions
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #33 on: 2014-05-20 12:20:28 »
...to make such an engine...
Oh... I was actually referring to Unity or any already made engine. And yes... Q-gears is for VII  :|

Shard

  • *
  • Posts: 330
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #34 on: 2014-05-20 16:16:35 »
You can't just port a game into another existing engine. It doesn't work that way.

LeonhartGR

  • *
  • Posts: 2577
  • ~Whatever...~ Enjoy life!
    • View Profile
    • LeonhartGR Productions
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #35 on: 2014-05-20 20:36:49 »
Yes.. I know... :/

Omzy

  • *
  • Posts: 205
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #36 on: 2014-05-20 21:18:08 »
Oh... I was actually referring to Unity or any already made engine. And yes... Q-gears is for VII  :|
I see what you're saying, I've played with Unity--it is the most awesome design tool around for sure. I could see someone rebuilding these games from scratch in Unity using code from things like Q-gears and rewriting systems entirely to support existing or modified Square assets, but it would take a dedicated team and a good chunk of time to pull off. Heck, being able to use Unity (porting Q-gears) might rally more developers to its cause, even. For now, I'm going to try to hack my way there--at least to see if its possible.

LeonhartGR

  • *
  • Posts: 2577
  • ~Whatever...~ Enjoy life!
    • View Profile
    • LeonhartGR Productions
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #37 on: 2014-05-20 21:56:16 »
And Square hunts those type of projects as well, like beginning a kickstarter... I mean look what happened to the FFVII series project, they made them look untrustworthy and fools!

Omzy

  • *
  • Posts: 205
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #38 on: 2014-05-21 05:02:55 »
I've rewritten the hashing algorithm in C++ and have expanded it to 64 bits of comparison on 16 pixels. It compares the 16 pixels against each other in 4 different ways and generates a 64 bit hash value. If any two images differ by less than 10 bits, they are the same image with a different palette. Otherwise, they are different images. Typically, similar images with different palettes differ by only 3-6 out of 64 bits and images that are completely different differ by 20-45 out of 64 bits. When this algorithm is adapted to sample straight from VRAM instead of filling an image buffer first, it should run very fast.

Next stop, generate a dictionary of hash values mapped to filenames and try to see if it is accurate whilst the game is running. This dictionary will be placed in an external file in the game folder and read into memory when the game starts. That may take a bit longer to figure out.

*C++, uses CImg library
Code: [Select]
#include <iostream>
#include "CImg.h"
using namespace std;
using namespace cimg_library;

uint64_t hashval = 0;
int pixval[16];

void growhash(int columns)
{
    int lastpixel = 127;
    for (int i = 0; i < 16; i++)
    {
        if      (i < 1      ) { lastpixel = 127;                    }
        else if (i < columns) { lastpixel = pixval[i+(15-columns)]; }
        else if (i < 16     ) { lastpixel = pixval[i-columns];      }
        hashval *= 2;
        (pixval[i] - lastpixel) < 0 ? /*nothing*/: hashval++;
    }
}

void gethash(CImg<unsigned char> image)
{
    int pixelR, pixelG, pixelB;
    for (int i = 0; i < 16; i++)
    {
        int x = i*16;
        pixelR = image(x/2, x, 0);
        pixelG = image(x/2, x, 1);
        pixelB = image(x/2, x, 2);
        pixval[i] = (pixelR + pixelG + pixelB) / 3;
    }

    growhash(2*2*2*2);
    growhash(2*2*2*1);
    growhash(2*2*1*1);
    growhash(2*1*1*1);
    return;
}

int main() {
    char filename[] = "1.bmp";
    CImg<unsigned char> image(filename), visu(512,512,1,3,0);
    CImgDisplay main_disp(image, filename);

    gethash(image);
    cout << hashval << endl;

    while (!main_disp.is_closed())
    {
        main_disp.wait();
    }
    return 0;
}

Edit (notes):
VRAM order theory: VRAM loads the necessary parts of a scene by selecting the next necessary 128x256 portion of the field texture (block 1) and loading the next 128x256 block after it (block 2) to fill a 256x256 square of VRAM. It cycles through the necessary palettes for block 1 until it completes all portions of block 1. If there happened to be correct palettes for block 2, it will draw those portions but will likely need more palettes to complete block 2. It cycles and loads block 2 into block 1 slot and loads the next block into block 2 slot. The process repeats with the remaining palettes of block 1 loading and completing block 1, etc. The order of necessary blocks follows the file order in that blocks at the beginning of the file are prioritized first and blocks at the end are prioritized last. Animation blocks are not loaded at all unless the current frame demands a block containing a particular animation, in which case that block will be loaded when its turn in the file sequence comes.

This implies that instead of treating each texture file as a texture, each 128x256 block should be treated as its own texture since different combinations of the block will be loaded into the 256x256 VRAM square and recognized as a complete 256x256 texture by DirectX.

So, when checking filenames for DirectX textures, the first block should be identified and the second block should be identified separately with a different hash and in the dictionary these should be labeled filename_1, filename_2, filename_3...etc for all 128x256 blocks of the field texture file.

Rough total block count: 894 files x 1664/128/2 ~5000 blocks
« Last Edit: 2014-05-21 06:15:42 by Omzy »

Kaldarasha

  • *
  • Posts: 2449
  • Prince of Model Editing
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #39 on: 2014-05-21 07:56:43 »
You have lost me when you started to load block2 into block1:

Omzy

  • *
  • Posts: 205
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #40 on: 2014-05-21 08:16:33 »
Maybe this graphic will help. The blocks cycle through the VRAM in the order of the texture file. At each point, the palettes cycle over the image, changing the colors in VRAM until no more colors are needed, then the cycle continues with the next blocks. The palettes needed for the block in the first position are prioritized, that's the point of keeping the next block in the VRAM next state, because it hasn't finished all of its palettes yet, just the ones in common with the block before it.

Keep in mind, this is a theory based on a very small amount of data so far.

« Last Edit: 2014-05-21 08:19:48 by Omzy »

Aali

  • *
  • Posts: 1196
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #41 on: 2014-05-21 14:36:55 »
PSX textures are always 256x256 and on a real GPU there would be no reduction in performance if you were to access them on 128 pixel boundaries. From your point of view (I am assuming you're getting this from PIX) you will only see which textures need to be constructed to emulate the GPU commands from the game. There is no "good" reason for the duplication you're seeing other than that its necessary to properly emulate the GPU. This is one of the big issues with replacing textures in FF8, field backgrounds are used as if they were 128x256 but when they're uploaded to a texture the next 128x256 pixels from the VRAM will be uploaded with it because that's just how the GPU works.

Omzy

  • *
  • Posts: 205
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #42 on: 2014-05-21 17:19:06 »
There is no "good" reason for the duplication you're seeing other than that its necessary to properly emulate the GPU. This is one of the big issues with replacing textures in FF8, field backgrounds are used as if they were 128x256 but when they're uploaded to a texture the next 128x256 pixels from the VRAM will be uploaded with it because that's just how the GPU works.
I understand, so the second block in memory I'm referring to doesn't really do anything, its just there because the commands that load the first block automatically load whatever's next for no good reason. So the palettes cycle on the first block, then the next one loads, etc.

Aali

  • *
  • Posts: 1196
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #43 on: 2014-05-21 19:43:57 »
If I were to implement modpath/replaceable textures for FF8 the first step would be to rewrite parts of or maybe the entire GPU emulation. Not because it is flawed in any way (although it isn't very efficient) but because then I could start rewriting all the rendering code to use explicit textures instead of just VRAM coordinates.

It would be a massive undertaking. Good luck ::)

Omzy

  • *
  • Posts: 205
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #44 on: 2014-05-23 21:25:27 »
I'm ready to test my new dictionary of hashes in-game but I need to gain a bit more d3d9 knowledge first. I'm planning on making use of a d3d9 interceptor DLL located here: http://graphics.stanford.edu/~mdfisher/D3D9Interceptor.html. I'm trying to find out which files I absolutely need and which ones I can change to test texture replacement in-game. Basically I need to capture the SetTexture calls and replace them with any test texture. Any help/advice would be appreciated to help me go faster  :-D

Here's the hash dictionary using the algorithm described above. It adds a numerical suffix to the filenames for each 128x256 block of the texture. There are a total of 6245 blocks in the game.
FF8 Field Hash Dictionary

Edit (note):
http://www.gamedev.net/topic/178004-idirect3dtexture9-and-manipulation-of-single-pixels/

Update (preliminary):
I have verified that my hash function has been successful at identifying my first test case, bghall1, from the VRAM. At first I was a little worried, because the hash value showed up 3 times, but those were bghall1, bghall1a, bghall1b, which are all identical textures. More to come when I have time!

Update2:
I've got the game successfully running the hash function on every texture that is called by D3D. First, I load my hash map from a file of all the known textures (described above). Then, I run the hash function whenever a SetTexture call is made. I then compare that hash value against the hash values in the hash map to find the closest match (the texture with the least different bits of comparison). I've done a test run from bghall1 (first save point) to the front gates of balamb garden and I've recorded these matches in a file to see if the correct textures were found. Here is that file, with a few annotations thrown in regarding where I was at each point in time: http://pastebin.com/9UpAynEd

Explanation of the results--
line structure: filename_blocknum,mismatchedbits,thistexturehashval,closestmatchedtexturehashval

I've only recorded 1/100 texture calls in the results because the file would be too long to navigate if I didn't. Whenever a background is supposed to be set, the hash function correctly identifies the texture and spits out the file name. However, whenever a texture with mostly black or monotone pixels is called, like in intro screens, and some other screens, including some animations that have a lot of black but a few spots here and there like lights, the hash function fails, usually identifying another texture file that has mostly black or monotone pixels. Additionally, whenever a character sprite texture is called, the results show either NO_MATCH or may sometimes identify the wrong texture as a match.

Keep in mind, these are results of a completely untested hash function that has a ton of room for improvement. The number of pixels sampled, number of comparisons between those pixels, randomness of the pixels, and thresholds for matches and mismatches can be varied. Also, secondary hash functions can be used on textures that are mostly black, for example, and eventually special cases can be worked on separately.

Next step: test texture replacement in D3D

Update 3:
Successfully replaced textures in-game with a simple 256x256 fire texture. This slows the system down tremendously if the texture file is loaded from the disk every time a SetTexture is called. This is because SetTexture is called roughly 150 times per frame to render all the various parts of the scene. Since all of the parts of the scene, except the character and object sprites, are loaded from a single field texture file, this 1664x256 (or 1536x256) texture file should be loaded only on the first texture call of the scene and then referenced in memory for each SetTexture call. This should drastically improve framerate and reduce errors in hashing during the other 149 SetTexture calls in the scene to 13/6245 = 0.2% of the original error rate. This all hinges on the ability to detect the correct texture on the first call during the frame.

Update 4: I have now successfully replaced textures in-game with their appropriate textures, using the hash method. It is not perfect, but it reliable chooses the correct texture > 90% of the time so far. I've expanded the pixel selection from 16 to 64 pixels to make it more reliable. It needs some optimization to avoid lag and some other fixes, but I really need to work through the next huge hurdle: allowing resized textures in-game. This, I fear, will be very difficult, since there are many operations performed on the passed-in textures in order to render them to the frame buffer. These operations include drawing all of the geometry of characters/objects, etc, and I'm so far unsure how to resize only the field textures yet keep everything else unaffected. I'll be thinking on that...
« Last Edit: 2014-05-30 04:21:26 by Omzy »

Omzy

  • *
  • Posts: 205
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #45 on: 2014-06-04 20:01:21 »
Just wanted to update you all on my current progress. I've been able to resize a field file to 4x and get it working in-game. All of the animations and lighting effects seem to work. I've been working rather feverishly on this, more than I should readily admit.

My previous hash algorithm caused a lot of lag every time a texture was loaded since it was searching the entire hash. The new hash technique I'm working on should produce much more reliable hashing that is hundreds of times faster (17 iterations to find the texture vs 6256 iterations per texture). This represents the difference between an algorithm that searches linearly through a large data set and one that searches with a binary search algorithm. It should eliminate that lag altogether.

This method should work on all field backgrounds once I get polished, but also has the ability to work for all other texture-like files in the game including character/monster sprites, battle scenes, cards, menus, etc. In order to get it to work for those other texture types, I need to have directories full of those images extracted from the game files. I can see that myst6re's deling works to view most of those files, but extracting the textures from them is something I haven't tried. I'll cross that bridge when I come to it.

Stay tuned for a release within the next couple of weeks! (this will not include a resize pack, that is the next project)
« Last Edit: 2014-06-06 23:51:53 by Omzy »

Covarr

  • Covarr-Let
  • Administrator
  • *
  • Posts: 3941
  • Just Covarr. No "n".
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #46 on: 2014-06-04 20:05:50 »
Can this include better world map textures as well? The world map is easily the worst looking part of the game.

Mendelevium

  • *
  • Posts: 222
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #47 on: 2014-06-05 05:33:29 »
Covarr read my mind, it was a question I had since you started! The world map is muddy when put next the ps1 version.
So that issue being resolved would be amazing!

Mirrorman95

  • *
  • Posts: 144
    • View Profile
    • Mirrorman95 - YouTube Channel
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #48 on: 2014-06-06 18:26:45 »
That's great news! Will this new algorithm work on the 3D models' textures, or just the 2D textures in-game?

Omzy

  • *
  • Posts: 205
    • View Profile
Re: What would it take to fix FF8's backgrounds (field files)?
« Reply #49 on: 2014-06-06 23:17:12 »
The way this all works is that whenever the game wants to display ANY texture, it calls a CreateTexture command first and then does the processing it needs to draw the texture onto triangles on the screen. Even the field backgrounds are drawn onto strips of triangles that produce a flat rectangle. So far I know that these commands are called when field backgrounds, character sprites (the character models you speak of), object sprites like save points, character portraits, menus with text, and cards are drawn. By extension, I believe they are also called for the world map, battle scenes and spell effects, and everything else, but I haven't proven those because I haven't recorded PIX data on those scenarios yet. So, if a CreateTexture command is called, then this method can replace that texture.

All that I have to know in order to replace a texture is what it looks like in memory. So far, the field backgrounds look exactly like the mim file contents in memory (with various palettes applied). I've already done the legwork and have written algorithms to display every necessary permutation with all necessary palettes for the field files. Character and object sprite textures look just like they do in myst6re's deling program when you open a field file and go to 3d models section. I don't have any experience with those files yet. So the bottom line here is that if any of you guys want non-field textures to work as well, I'll need to get copies of all of those images so that I can run my hash algorithm on them.

Generating these images is not hard--in fact myst6re has generated most of them by reading the ff8 files in her deling program. Its a matter of writing little programs that read the ff8 files and output them to image formats like PNG. In order to see what they look like in memory, you can download the DirectX SDK (June 2010) and use the PIX tool to record all the directx calls. When viewing a PixRUN file, you can click the texture references on all the SetTexture calls and it will display what the textures look like in memory. My guess is that most of them look exactly like they do in deling, because field files are the most convoluted files to display and tex files, etc, are very simple.

If anyone wants to help speed up the progress on those other types of textures, feel free to write python scripts that output images from game files or send me rar's of images. For now, I'm focusing on field files. This process actually becomes more reliable (from 98%->100%) once I have hash values for EVERY texture in the game. As it is now, it is theoretically possible for my hash algorithm to place a field texture over a character sprite, for instance, if they coincidentally have the same hash value. Rare, but possible.
« Last Edit: 2014-06-06 23:52:22 by Omzy »