Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Vehek

Pages: [1] 2 3 4 5 6 ... 9
1
Announcements and site development / Re: We were hacked.
« on: 2021-07-23 20:30:49 »
You can have up to 500 of them on a free Yahoo account. It's pretty insane. If for some ungodly reason you manage to come up with more than 500 different email addresses, just make a second Yahoo account and you've got 1000.
I tried, and it looks like your information is out-of-date. At some point it became a Yahoo-Plus-only thing, at least the massive number part (my settings menu says 3 for free). People who were already using the feature may have got to keep it. I haven't found too much information on the change yet.

2
WIP / Re: Recreating Project: Final Fantasy VIII
« on: 2021-02-07 19:56:57 »
I'm sure they were talking about the backgrounds, not the character model.

3
Is your analysis so far any different than this one from last year?
ff8 battle file animation format

4
Been a long time, but I think you divide it by 4096 to get the percentage of a full revolution, then convert it to whatever angular measure unit you're using. But the MCH models in main_chr.fs (like d024.mch you're viewing) don't use that packed system I described. They use simple 16-bit (2-byte) integers. All the real animations anyway aren't in those model files, but part of the chara.one files in the archives for each field.

5
I put them all along one axis (Z in my case). The "rest pose" is just an animation itself, and has no impact on other animations.

6
I did briefly mention back then that I don't load them in XYZ order. As I said there, I read them in ZXY, and used YXZ as the rotation mode. I don't think I've tried things with direct vector rotations in a long time; I've been using poses. I'm not sure how much will be directly applicable since I did things in my script like swap around the axes for the vertex coordinates to YXZ so I wouldn't have to rotate the model and to get left-right correct instead of being mirrored.

Code: [Select]
mdlPoseBones['Bone.%02d' % (rNum + 1)].rotation_mode = 'YXZ'
mdlPoseBones['Bone.%02d' % (rNum + 1)].rotation_euler = (-rots[1] * math.pi / 2048, -rots[2] * math.pi / 2048, rots[0] * math.pi / 2048)

7
Scripting and Reverse Engineering / Re: [FF9]2016 release
« on: 2016-04-21 06:01:40 »
I think it was that they accidentally left their source code in. Amazing mistake, right?
Edit:
I'm not actually sure whether it was actual code or not. .NET might just leave in lots of info. Didn't remember exactly what the opening post originally said.

8
The wiki also mentions Playstation version when mentioning the compression. As in, only the Playstation version. You don't need to decompress further in the PC version.

9
I briefly wrote about that before. That type of chara.one has a a footer (I mean a structure at the end of the file), much like the regular chara.one header, but with the order of the entries reversed, where the final 4 bytes of the file are the model count, the 4 bytes before that are the first model's first texture offset, and so on. Also, no EE EE EE EE separator.

http://wiki.qhimm.com/view/FF8/FileFormat_ONE

10
I'm not sure whether you're already aware of this (especially since I don't know exactly how you're using the textures after loading them), but you have to be careful with UV calculation. I believe the UVs are given for the texture pages, rather than the individual textures, and not all textures have coordinates perfectly aligned at the corners of the texture pages. When working with an extracted texture, you have to account for that difference.

11
I was the one who made that video. I have a Blender script for importing the .mch models, and another script for reconstructing a .mch (mostly, I have to add the texture section manually) from the imported model. After importing, I delete the mesh, then make a new mesh using the same names as the old mesh (the export script refers to things by the names assigned by the import script), keeping only the skeleton and any animations that were loaded.

12
Graphical / Re: [FF8-steam] Character texture replacement
« on: 2014-11-23 20:34:34 »
I just stumbled accross something interesting minutes ago: you can replace lowpoly models with highpoly models thanks to Deling . I replaced lowpoly squall with highpoly squall in main_chr.fs.
I don't think that's safe. When I was doing some high-texture model tests last year, I found that too many model textures can cause graphical glitches. The cube model I showed in that thread was an extreme case of extra textures, but just a few can glitch up cutscenes sometimes. For example, Edea's scene in the Timber studio, and the scene after the prison.

13
First four bytes of what?  The *.ARC header?
First 4 bytes of the first subfile, what you called "pointer of the last, missing file on it.", 86 A5 03 00. These bytes are the LZS header.

Quote
I don't specify the compressed size because I understood that I didn't have to if I was just using the whole sub-file.
By specifying the compressed size, I'm talking about the LZS header. When working in validate header mode (the default), myst6re's tool demands that the remaining file length after the header matches the value of the header exactly. Otherwise it'll throw up that "Invalid LZS header" error message.

Quote
Quote
And the subfile's size as derived from the ARC header does exactly that.
What?
According to the LZS header, the compressed data is 0x3A586 (238982) bytes long. Adding the 4 bytes taken up by the header, the LZS file would be 238986 bytes long. But a length of 238988 bytes, the subfile length you got from the ARC header, is 2 bytes more than that. See my point just above.

Quote
The last two bytes of the *.ARC header, the last two bytes of which specific subfile, or the last two bytes of the whole ARC file?
Last two bytes of the first subfile. I don't know why they're there, but they don't seem to be used. I tried setting a breakpoint while entering battle and they didn't get read.

Steps:
1. Extract the subfiles from BATTLE.ARC
2. Using a hex editor, delete the final two bytes, F1 D2, from the first subfile.
3. Run unlzs on the first subfile.
4. If all went well, you should have a decompressed file with a length of 516688 bytes. It should be identical down to the last byte to BATTLE.OUT.

14
Sorry for missing your report until now.

Those first 4 bytes? Either keep them on or use the "no-header" option. Those bytes are the header (compressed size). Also, the decompressed output should be completely identical to BATTLE.OUT. So, actually, you should be able to skip decompressing the data and go straight to editing and recompressing.
Edit:
Looks like when working with a header, myst6re's unlzs is extremely picky. If there are any extra bytes beyond the specified compressed size, it complains. And the subfile's size as derived from the ARC header does exactly that. Delete the last two bytes (F1 D2).

15
There's no installer, so nothing can be bundled, if that's what you're referring to. It's just an archive file containing the precompiled binaries and required dlls.

16
Troubleshooting / Re: Garden and field files
« on: 2014-05-04 19:18:40 »
The import/export tab only allows importing/exporting from the currently open archive. In the case of field.fs, that's mostly the individual field archives. Vgr, you probably have a different idea of what "field files" are. I believe Shard wants the ability to extract files from every field location at once.

17
Keep in mind, the PC version was developed by Eidos back in 1998; their native language is English.
The PC version wasn't developed by Eidos, it was done by SquareSoft Inc. That's the North American subsidiary, though, so the native language would still (mostly) be English. Looking at the credits, there were at least one Japanese programmer from Square's other games.

18
Troubleshooting / Re: FF VIII Chara.one World.fs
« on: 2014-03-15 06:09:09 »
The chara.one in world.fs is an older type of chara.one. They were used in the PS1's FF8 demo and sometimes appear in the old, unlinked field archives, but the one in world.fs appears to be the only actual use of the old format in the final version.
Some details about the format. I don't know if this is the right term, but there's a "footer". To read it, you have to work backwards from the end of the file. Unlike the headers in standard chara.one files, all offsets are absolute, not relative.

Code: [Select]
import struct
import os.path
from os import mkdir

class genericEntry:
    def __init__(self):
        self.location = 0
        self.size = 0
        self.isNPC = False
        self.MCHNumber = -1
        self.TIMlocations = []
        self.modelLoc = 0
        self.sizeBeforeAnims = 0
        self.anims = []

def unread(src):
    loc = src.tell()
    curResult = struct.unpack("<I", src.read(4))[0]
    src.seek(loc - 4)
    return curResult

name = raw_input('File name:')
src = open(name, 'rb')

charaEnd = struct.unpack("<I", src.read(4))[0]
src.seek(charaEnd - 4)

totalModels = unread(src)

models = []

for i in range(totalModels):
    mdl = genericEntry()
    firstNum = unread(src)
    if (firstNum & 0xD0000000) == 0xD0000000:
        mdl.MCHNumber = firstNum & 0xFFFF
        mdl.location = unread(src)
    else:
        mdl.isNPC = True
        mdl.TIMlocations.append(firstNum)
        loc = unread(src)
        while loc != 0xFFFFFFFF:
            mdl.TIMlocations.append(loc)
            loc = unread(src)
        mdl.modelLoc = unread(src)
        mdl.location = firstNum & 0xFFFFFF

    models.append(mdl)
   
fillerplace = genericEntry()
fillerplace.location = src.tell() + 4
models.append(fillerplace)

if not os.path.exists("%s_extract" % (name)):
    mkdir("%s_extract" % (name))

for i in range(totalModels):
    src.seek(models[i].location)
    curmdl = models[i]
    rawdata = src.read(models[i + 1].location - models[i].location)
    if curmdl.isNPC == True:
        outmdl = open('%s_extract\\mdl%02d.mch' % (name, i), 'wb')
        for offs in curmdl.TIMlocations:
            outmdl.write(struct.pack("I", offs + 0x100 - curmdl.location))
        outmdl.write(struct.pack("I", 0xFFFFFFFF))
        outmdl.write(struct.pack("I", curmdl.modelLoc + 0x100 - curmdl.location))
        while outmdl.tell() < 0x100:
            outmdl.write(chr(0))
        outmdl.write(rawdata)
        outmdl.close()
    else:
        outmdl = open('%s_extract\\d%03d_anim.bin' % (name, curmdl.MCHNumber), 'wb')
        outmdl.write(rawdata)
        outmdl.close()
       
   

src.close()

19
    Alexander: At 0x8138 in mag203_b.01 (Sorry, didn't have it listed correctly in my big list.)
    Brothers: 0x31E0 in mag204_b.00, and 0xE0 in mag204_b.03.

    Grim Reaper:
    According to the models I manually extracted a while ago, there are multiple copies.
    One can be found at 0x122C95C.

    There were so many models that I don't think I got them all, but in FF8.exe, I've found:
    • Gilgamesh's swords (multiple copies, I think)
    • Various Angelo models, and Angelo's bone
    • Rinoa's wings?
    • A cherub (angel)? 0x11786D4
    • Boko models, Cactuar, and Moomba

20
While their textures are in the archives, those summons' models are in FF8.exe.
For the English 1.2, both non-Geforce and Geforce:
  • Phoenix: 0xDB537C
  • MiniMog: 0x112BC04
  • Carbuncle: 0xCB6F94
  • Tonberry: 0x1147514
These are "normal" GF models.

I mean that Quetzacoatl model uses 3 material/maps but the info of the third one is missing and ther is no unwrap for that part of the model.
You may need to increase imageCount in the script in order to have all the UVs preserved.

21
If you've located the beginning of the model, then it should be simple. The first 4 bytes of the alternate header are the length of the model, in little-endian (take the bytes and reverse the order to get the value).

Good night.

22
The alternate-format models are not at the beginning of the file, which is why the script fails. Unfortunately, I don't know enough to automatically locate where they are in the file. I used a hex editor to find the alternate-format models and to copy their data out into new files. That isn't an optimal solution.

For example, open up mag005_b.05 in a hex editor and copy out the data from 0xD4-C643 into a new file.
In its file, Eden is at 0x5A54-134FF.

23
I don't know yet if you've gotten the alternate-format models out of the files yet (though I'm assuming you have), but it requires a slightly different script for conversion.

Replace
Code: [Select]
modelData = model.read(totalSize - offsets[0])with
Code: [Select]
modelData = model.read()And replace all occurrences of "0x1C" in the script with "0x18".

Oh, and I slipped up when I was updating my list to post. There's another Leviathan model in mag005_b.02.

24
Since GF textures are separate from the model, they are not easily merged into the newly created model. It can only directly provide the model.
The script creates placeholder textures for the purpose of being manually replaced or maybe to make textures behave correctly when exported. You can adjust how many placeholders are created by changing the value of imageCount.

25
I'm not sure what to advise other than expanding the header and adjusting the offsets to match the types of battle model that Noesis supports.
I do have a list of where some of the GF models are.

"Alternate format" means that the model uses a different header format that lacks a section count, that the model data does not start at the beginning of the file, and that the model's textures are not TIM-format.

battle.fs:
  • mag005_b.05 (Alternate format) - Leviathan
  • mag094_b - Siren
  • mag099_b - Fat Chocobo (ChocoBocle)
  • mag115_h.07 - Quezacotl
  • mag184_e - Shiva
  • mag186_b - Odin
  • mag190_b - Doomtrain
  • mag201_b.12 (alternate format) - Bahamut
  • mag204_b.03 (alternate format) - Brothers?
  • mag217_b - Gilgamesh
  • mag290_h - Pandemona
  • mag324_h - Diablos
  • mag325_b - Odin (death from Seifer?)
  • mag326_e, mag326_g - Gilgamesh

All listed models in magic.fs are the alternate format.
magic.fs:
  • mag200_b.00 - Ifrit
  • mag201_b.00 - Bahamut (head)
  • mag202_b.00 - Cerberus
  • mag203_b.00 - Alexander
  • mag204_b.00 - Brothers?
  • mag205_b.00 - Eden

A bunch of other models are in FF8.exe. One thing that I've found helpful in finding models is that there's usually if not always either the hex string 68 C0 07 08, 70 C0 07 08, or something similiar near the beginning of the model data.

This is a Python script that takes a "normal" GF-model and turns it into a battle model that Noesis can read.
Code: [Select]
import struct

imageCount = 2

name = raw_input('File name:')
model = open(name, 'rb')
model.seek(4)
offsets = struct.unpack("IIII", model.read(16))
model.seek(offsets[0])
modelData = model.read(offsets[3] - offsets[0])

outt = open(name.split('.')[0] + '_mdl.dat', 'wb')
outt.write(struct.pack("IIII", 11, offsets[0] + 0x1C, offsets[1] + 0x1C, offsets[2] + 0x1C))
for i in range(8):
    outt.write(struct.pack("I", offsets[3] + 0x1C))

outt.write(struct.pack("I", offsets[3] + 0x1C + 4 * (imageCount + 2) + imageCount * 0x4220))

outt.write(modelData)
outt.write(struct.pack("I", imageCount))
for i in range(imageCount + 1):
    outt.write(struct.pack("I", i * 0x4220 + 4 * (imageCount + 2)))
#Create placeholder textures
for j in range(2):
    outt.write(struct.pack("IIIHHHH", 0x10, 9, 0x20C, 2, 2, 256, 1))
    for x in range(256):
        outt.write('\x22\x22')

    outt.write(struct.pack("IHHHH", 0x400C, 1, 1, 0x40, 0x80))
    for x in range(0x4000):
        outt.write("\x00")

outt.close()

Pages: [1] 2 3 4 5 6 ... 9