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 - phaeron

Pages: [1] 2
1
Argh... I hadn't touched the anim data for about a year and a half and you suckered me back into looking at it tonight.

I translated the unknown part of Cloud's anim to bit form a long time ago and lined it up. Once you view it as a bitstream it's pretty apparent where the translations are because you have huge strings of zeroes. It looks to me like the second frame is ~39 bytes, the third ~40, the fourth ~39, and the rest about +/-5 from those for a total of 19 deltas + 1 key = 20 frames. 39 bytes for 34 axis deltas plus a translation comes out to a little over 8 bits per non-zero axis, which isn't out of line.

What I don't like is that (a) the translations have to be bitshifted to align, and (b) the really nutty things the game does when you flip single bits are in line with a variable-length coding scheme getting derailed temporarily. I tried comparing the deltas you listed again the bitstream, and didn't see an obvious correlation; you'd expect that the low bits of each delta would show up in sequence but that didn't seem to be the case.

By the way, the first three longs don't appear in the PSX data -- this is what I see in the start of the third record for CLOUD.LZS, which corresponds to the bone data you posted:
Code: [Select]

00000000: 14 00 56 03 00 00 00 FE-2E 00 00 00 00 00 00 0C

2
I'm not sure there is anything in this that you guys haven't already replicated in your own viewers, but what the heck....

Here is the binary and source to my own OpenGL-based model viewer for FF7 PSX that I wrote:

http://www.virtualdub.org/other/ff7view.zip
http://www.virtualdub.org/other/ff7viewsrc.zip

As compiled it will expect EARITH.BIN and CLOUD.BIN in the current directory or it will crash (decompress EARITH.LZS and CLOUD.LZS to get these). It will then load and display Aerith, and you can adjust the skeleton. The keys are something like (a)ntialias, (w)ireframe, (t)ranslate, f2/f3 to load and save, (i)k mode, space to switch axes, and [ and ] to change bones. The viewer knows how to load the models as well as the first frame of 12-bit coded anims. There's some really ratty export-to-DXF code in there as well although I don't think it ever worked that well since it couldn't export vertex colors.

Obviously, the viewer isn't polished; I wrote it to make a really high quality image for a T-shirt of Aerith hugging Cloud.

3
Microsoft WinDbg may come in handy -- although it still has some rough edges, it supports both GUI and command-line operation, is more powerful than the Visual C++ debugger, and can do remote debugging.  It has some neat commands, like "grep disassembly."

http://www.microsoft.com/ddk/debugging/

As for the dynamic menus, you can use any numeric IDs between (IIRC) 1-65534.  Just pick an ID around ~45000 or so that isn't near the ranges that the resource editor is using.

4
I'm a bit skeptical about proper support for OpenGL selection -- it's not commonly used on the PC platform and so it's likely to be emulated in software or even broken.  It's safer just to transform your pick vector into world space and intersection test it against your triangle meshes; I think you'll need to do that anyway for a "nearest" hit test, as needed for vertices.

5
Some of the files in PSX version, most notably the program files, are just GZIP files concatenated back-to-back -- you can slice them apart with a hex editor and gzip -d the sections.

6
Hmm... looks like Z-fighting due to polygon interpenetration at the edges of the rocks in the zengan2 picture.  Polygons a little too big?

7
Scripting and Reverse Engineering / C++ Struct Size Bug??
« on: 2002-08-27 03:30:18 »
For Visual C++, you can disable padding as follows:
Code: [Select]

#pragma pack(push)
#pragma pack(1)
struct Foo {
   ...
};
#pragma pack(pop)

A better idea, though, is just to split the dword member into two words and be done with it.  Your struct will generally be free of padding if each element is aligned to its size and the struct size is evenly divisible by the largest element.

The rule for sizeof() is that it returns the size of an object as if it were an array element.  Even though your struct doesn't need to be padded when used by itself, sizeof() still returns the padded size.

8
I've never gotten it to work -- OpenProcess() always returns NULL, even with Administrator privileges.  Might need some NT security mojo.

9
CPU usage is tricky -- under Windows NT, you can get your own process's memory usage with GetProcessTimes() and GetThreadTimes(), but I don't know how to read the global CPU usage yet since I haven't been able to get a usable process or thread handle for the idle process.  Get*Times() doesn't work under Windows 95/98, but you can get the global CPU usage from the registry.  See oshelper.cpp in the VirtualDub source code for ways to measure CPU usage under both NT and 9x.

It is possible to measure per-thread CPU usage under 9x, but it's difficult -- the KernelToy WinTop does it by loading a special VxD that activates on context switches.

10
Visual Studio .NET was obviously rushed.  VB lost edit and continue, VC++ build engine is broken, IDE has a lot of stupid bugs such as commands dropping out of the customization window, source code control is frustrating as hell to use, etc.  I've really only used the VC++ component; the compiler has some improvements, but for VC6 programmers the IDE is a gigantic step backward in many ways.

11
Scripting and Reverse Engineering / Battle Locations
« on: 2002-06-29 03:06:22 »
Hey ShinRa, where did that model come from?  Is that Rika from Phantasy Star IV?

12
Don't pass endian-swapped floats in as floats -- they will get loaded in and out of the floating point registers, and if the swapped bit pattern happens to correspond to a denormal, the FPU will normalize it and trash the value.

Code: [Select]

void __declspec(naked) __stdcall ByteSwap32(void *pValue) {
    __asm {
        mov edx, [esp+4]
        mov eax, [edx]
        bswap eax   ;requires 486+
        mov [edx], eax
        ret 4
    }
}

[/code]

13
Nice work.

The reason why it doesn't crash under Windows 95/98 is the OS's Windows 3.1 heritage -- all processes must have a DOS task block, and the entire DOS memory arena from 10000-FFFFF is mapped for read/write access to everyone for speed.  The data being read under 9x is almost certainly not correct.  If the FF7 programmer hadn't used such an insanely large structure, the access would have fallen into 00000-0FFFFF and would have crashed even under 9x.

14
Scripting and Reverse Engineering / Yatta!!
« on: 2002-04-17 05:25:00 »
Quote
By the way, can you explain the way the PSX version reads the animations and the file names?


There are no individual item names in the PSX archive -- CLOUD.LZS contains the PSX equivalents of the PC's rt** files, but the files are stored solely by pointer and length.  The animations are stored exactly the same as the PC version, byte-by-byte exact with the PC's **da files.  So in other words, I know no more about that than you see here in this thread.


15
Scripting and Reverse Engineering / Yatta!!
« on: 2002-04-16 08:12:00 »
Quote

Yesterday my screen broke. However, at least it looked like a cool supernova  
However, I possibly won't be able to post ...

What are you, a wimp?  Why do you think Microsoft Narrator exists in Windows 2000?  Just run NARRATOR.EXE and have the computer read your screen for you.

"Foreground window... Microsoft Internet Explorer... Qhimm's Forums... Post Reply... editable text...."

  :D

Seriously, my condolences about the screen, though.  When I had a CRT go out, I actually ran Narrator in order to figure out what was going on long enough to set up a PCAnywhere link to my laptop.

Quote

Yeah, that's pretty much what I was driving at. I know she keeps a hold of it most of the time, but does Yuffie ever throw her shuriken?


I vaguely remember that possibly happening in one of her limit breaks.... but I'm sure my definitive answer helps you immensely.


16
Scripting and Reverse Engineering / Yatta!!
« on: 2002-04-16 07:30:00 »
The problem is not how to attach the sword -- that much is obvious and falls naturally out of attaching the sword to the hand bone.  The issue is how the game actually does it so that the animations can be replayed.  What's interesting is that if you look at the PSX version, there is a second set of animations beginning at packet 54 that run in parallel with the primary set of animations and have the same number of frames.  It's a possibility that the weapon is _never_ attached to the hand and simply looks attached because paired weapon and player animations are running simultaneously.  This would also allow FF7 to manually control the animation of the weapon, which would be necessary when attacking since the distance and direction is different for each enemy.

Okay, will someone please decode the delta frame format for me so I don't have to go bitwhacking?  I hate variable bit streams.    :cry:

17
Scripting and Reverse Engineering / Yatta!!
« on: 2002-04-15 02:09:00 »
Almost.  All of the animation frames after the first appear to be stored as deltas, so you'll still get roughly the same fidgeting even with the new pose.  What you'll likely end up with, though, is a floating weapon since it doesn't seem to be attached to the hands like you'd expect.



18
Scripting and Reverse Engineering / Yatta!!
« on: 2002-04-14 21:35:00 »
This is the code that I use:

Code: [Select]

class twelvebit_iterator {
protected:
const unsigned char *src;
bool half;
public:
twelvebit_iterator(const void *s) : src((const unsigned char *)s), half(false) {}

int operator*() const {
int v = (src[0]<<8) + src[1];

return half ? v&0xfff : v>>4;
}

twelvebit_iterator& operator++() {
++src;
if (half)
++src;

half = !half;
return *this;
}

twelvebit_iterator operator++(int) {
twelvebit_iterator it(*this);

++*this;

return it;
}
};

void FF7Model::loadPose(FF7Pack& pack, int pose_packet) {
const unsigned char *src = (const unsigned char *)pack[pose_packet].p + 11;
int nBones = mBones.size();

twelvebit_iterator it(src);

for(int i=0; i<nBones; ++i) {
int x = *it++;
int y = *it++;
int z = *it++;

mBones[i].setOrientation(Quaternion(Vector3(0,0,0), 1));
mBones[i].rotateXYZ(x, y, z);
}
}

19
Scripting and Reverse Engineering / Yatta!!
« on: 2002-04-13 19:53:00 »
'rvaa' (Aeris' skeleton, PC style):

0000000C: 1F 00 00 00 (31 bones)

00000034: FF FF FF FF (hip: parent is root locator)
00000038: 00 00 A4 C2 (hip: bone length is -82.0F)
0000003C: 01 00 00 00 (??)

00000040: 00 00 00 00 (torso: parent is hip)
00000044: 00 00 01 C3 (torso: bone length is -129.0F)
00000048: 01 00 00 00 (??)

0000004C: 01 00 00 00 (head: parent is torso)
00000050: 00 00 AC C2 (head: bone length is -86.0F)
00000054: 01 00 00 00 (??)

You get the idea.  All bones are rotated by their transform; all children are rotated and translated.  The skeletons are constructed roughly the same as the field models, although Aeris has 4 bones in her pigtail here.   :laugh:

In case anyone is interested, the PSX skeleton format is similar, except that the bone records are composed of four 16-bit integers (8 bytes), in the order bone ID, length, data offset, bone length.  Same skeleton.

20
Scripting and Reverse Engineering / Yatta!!
« on: 2002-04-13 07:58:00 »
Skeletal information isn't stored in the '__da' file -- that is stored in '__aa'.  All that the '__da' file gives you is bone orientations.  I know that the '__da' file contains at least some of the battle animations -- the second packet is the critical HP animation.  I haven't been able to decode any of the animation frames or any animations past the first two.  I think the first two bytes in each animation are the frame count.  It's easier to look at the PSX animation files than the PC version's, because although the data is exactly the same, the PSX version has the animations individually indexed and the PC version doesn't.  Cloud has at least 40 battle animations.

The '__ab' file is still a mystery to me, but it does contain either decoding directions or pointers to animations, because patching the first table entry at 00000190 from 00 FE C0 to 01 FE C0 makes Cloud play his critical HP animation instead of his normal battle idle.

21
Scripting and Reverse Engineering / Yatta!!
« on: 2002-04-13 04:33:00 »
Alright, who's the wiseguy who entered in "famous programmer" as my tag?  :D

22
Scripting and Reverse Engineering / Yatta!!
« on: 2002-04-13 04:32:00 »
I figured out how Cloud's battle pose is stored... finally!

The battle pose is stored at the beginning of the 'rtda' resource, as a translation followed by Euler angles for each bone.  It took me a long time to figure out that the Euler angles are actually 36-bit, stored as three 12-bit binary rotation fractions (0x400 == 90 degrees).  The battle coordinate system is right handed, with X-Z being the ground plane, +Y being into the ground, and +Z ordinarily away from the enemies.  Rotation order is +Z axis, then +X axis, then +Y axis.

Anyway, in 'rtda':

00000010: 14 00 (unknown)
00000012: 56 03 (length of data for this chunk)
00000014: 00 00 (X translation)
00000016: 00 FE (Y translation)
00000018: 2E 00 (Z translation)
0000001A: 00 (unknown)
0000001B: 00 00 00 00 0_ (root locator: X 0d, Y 0d, Z 0d)
0000001F: _C 00 EC E0 00 (hip: X 270d, Y 333d, Z 0d)
00000024: F8 2F E5 E8 A_ (torso: X 349d, Y 358d, Z 327d)
00000028: _0 BB 0C 82 BC (head: X 16d, Y 17d, Z 62d)
...
00000083: _D 56 00 00 00 (right boot tip: X 300d, Y 0d, Z 0d)

I haven't figured out the rest of the data in the block, but with the above I have Cloud rendering in OpenGL in his base pose.  I suspect the rest of the block is the idle animation, but I haven't confirmed that yet.  Also, now that I know that the junk in 'rtab' isn't a bone mask, I'm beginning to suspect it is animation sequencing data.

23
Scripting and Reverse Engineering / Remake Inquiry
« on: 2002-04-06 02:29:00 »
Although there's no way to tell for sure until someone pops open the files enough to render them, I think it's unlikely that FF7 is using a plain height map since the meshes you get from them have a lot of polygons, and the tesselation to triangles is nontrivial.  The easiest way to tell would be to watch FF7 PSX -- the Playstation can't do subpixel coordinates or texture filtering, so you can figure out where polygons are by the jittering.

As for the RPGamer picture, it's a hexagonal grid instead of the usual rectangular, and you can see obvious grid artifacts in the mountains in the lower left of the rendered shot.  Those definitely don't show up in the game.  I wouldn't be surprised if the game model is a polygon-reduced version of the picture's model, though.

24
My guess is software OpenGL (GDI unaccelerated).  There's no doubt that OpenGL is being used, though, if you look at the imports for ff7.exe.  I think I remember some people having problems with the NVIDIA patched version due to a missing or bad GLU32.DLL.



25
FF7PC is definitely buggy (I like how they claim the crashing at the Chocobo race is due to an incompatibility with Windows 2000), but if you're playing with the NVIDIA patch, you should check how much swap you have available -- I think Eidos recommends at least 350MB of virtual memory (physical + swap) for the NVIDIA workaround mode.  FF7 is probably the only Direct3D game that uses OpenGL to convert textures.

Direct3D has a exception handler for full-screen mode, so sometimes when a D3D game crashes, you get the silent drop to the desktop.  I can't get FF7 to run more than 30 seconds in W2K without crashing, really.


Pages: [1] 2