Difference between revisions of "FF8/FileFormat X"

From Final Fantasy Inside
< FF8
Jump to navigation Jump to search
my_wiki>MaKi
(Camera data)
my_wiki>MaKi
(Camera data)
Line 286: Line 286:
 
|-
 
|-
 
|0
 
|0
|UNKNOWN
+
|ushort
|UNKNOWN
+
|AnimPointer
 
|-
 
|-
|8*2 (not quite sure why, but engine just skips 8*2 bytes)
+
|AnimPointer
|UNKNOWN
+
|Varies
|RealCameraTransform
+
|RealCameraTransform + opcodes; ends with -1
 
|}
 
|}
 
 
Explained:
 
EIDOS/Square did really made it a bit tougher for some reason-
 
 
1. Engine loads CameraSettings and CameraAnim pointers (the one you get after obtaining available Cameras, which is usually one only. I don't know what happens when there are two cameras)
 
 
2. Camera Animation Set holds collection of camera sequences designed for different monster spectrums. I don't know yet what triggers the engine to load which animation set, but I think this may be related to encounter data
 
 
3. After getting to specific anim you get the correct animation. It start's with 08 00 that indicates 8 pointers (including himself). Engine just skips over by 8*2 to get to data from which finally renders camera animation.
 
  
 
== Geometry ==
 
== Geometry ==

Revision as of 16:36, 26 June 2018

By MaKiPL. Thanks for help in research for: shakotay2 (XeNTaX), Halfer, Yagami Light. Complete list of original battle stages by Kaspar01: List of battle stages

Info

.X file is uncompressed 3D stage model with texture embedeed. The file contains unused info (not used by FF8 engine), camera data, movement, translations and geometry data.

Battle stages DOES NOT contain pointers to next sections. All pointers are HARDCODED in FF8.EXE. Click me for battle stage pointer list

Name Usually starting with: Description
PlayStation MIPS assembly E8 FF BD 27 01 00 02 Used only in PS version; skipped in PC
Camera data + movement 02 00 08 00 20 00 Camera animations, movement (pre-keyed)
Model section 06 00 00 00 (See geometry section info) Divides to object (group) and it's sub-objects + vert/triangle grouping
Texture 01 00 00 00 09 (Always) Contains one .TIM texture

How is this file handled by the engine?

FF8 loads specific file and reads it from hardcoded (written in FF8 code) position (or reads MIPS PlayStation assembly that contains battle stage load code). This hardcoded position points to camera data (in PC). Camera data has size uint16, which is calculated and relative jump is made. Just after camera, a typical section based file handling is made.

Offset Length Description
0 uint32 Number of sections
4 uint32 Objects group #1
8 uint32 Objects group #2
12 uint32 Objects group #3
16 uint32 Objects group #4
20 uint32 Texture [unused in code]
24 uint32 Texture
28 uint32 Relative to EOF

Objects group:

Offset Length Description
0 uint32 Number of sections
4 uint32 Pointer to Settings #1
8 uint32 Pointer to ObjectsList
12 uint32 Pointer to Settings #2
16 uint32 Relative to end_of_group

Objects list:

Offset Length Description
0 uint32 Number of objects
Num_of_obj*4 uint32 Relative pointer to segment (one .obj file) [01 00 01 00]

Settings 1:

Offset Length Description
0 uint16 Unknown, fixed 2?
2 sint16 (probably, or uint16) Scale (01 is the smallest)
4 4 bytes PADDING
8 4 bytes Nothing?
12 4 bytes Nothing?
16 2 bytes if not FF FF, then model vanishes
18 sint16 X or Z Axis rot origin (Translation)
20 44 bytes Left null for storing some engine data AFTER loaded in-game
64 2 bytes if not FF FF or 00 00, then model vanishes
66 2 bytes Nothing?
68 ...up to end Left null for storing some engine data AFTER loaded in-game

This might look difficult, but it's like multi-pointer file that starts at different location given by executable. See list at the beginning of this wiki to see which stages camera starts at which position (where FF8.exe really starts to read file as BattleStage) [FF8 stores whole file, even with useless data before camera] If this still makes trouble, see this video: TODO

Camera data

Starts at ~0x5d4 (see How the engine handles this file?). [.text:00509820]

Offset Length Description
0 uInt16 Fixed 02 00 (Unused in code)/ pointers count
2 uInt16 Relative jump to CameraSetting
4 uInt16 Relative jump to CameraAnimation
6 uInt16 Camera data size (starting from 0) [unused in code]
8 24 bytes Camera Settings
32 ?? bytes Cameras

Camera Setting:

Offset Length Description
0 char (based on disassembly) CameraAnimMode?
1 byte? StopEnemyBeforeAnim?
2 Bitfield? (1B) UHM?
3 ??? DefaultEndofCameraPosition_Zoom?
4 ??? ???

Cameras:

Offset Length Description
0 uint16 NumberOfCameras
2 *(Camera) uint16 Relative pointer to camera animation
2 *(Camera)+ 2 uint16 Relative pointer to EOF
2 *(Camera) + 4 CameraAnimationSet CameraAnimationSet

Camera Animation set:


Offset Length Description
0 uint16 NumOfAnimations (Only 7 are valid)
2 *(KeypointID) uint16 Relative pointer to camera Animation (only 7 are valid)
2 *(NumOfKeypoints)+ 2 uint16 Camera EOF
KeypointPointer Keyframe Keyframe

Animation:

Offset Length Description
0 ushort AnimPointer
AnimPointer Varies RealCameraTransform + opcodes; ends with -1

Geometry

Geometry contains groups, that contains Triangles and/or quads poligons. Models always stars at 01 00 01 00, and needs to be after camera data, either it's not model itself, but some other data.

Group

Offset Length Description
0 4 bytes Always 01 00 01 00 / Header of object
4 2 bytes Uint16 / number of vertices.
6 Number of vertices * 6 Vertex data, short X; short Y; short Z;
6 + (Number of vertices *6) (AbsolutePosition MOD 4) + 4 Padding
varies (just after above) 2 bytes uint16 / number of triangles
varies (just after above) 2 bytes uint16 / number of quads
varies (just after above) 4 bytes padding
varies (just after above) number of triangles * 20 Triangle data. If NumOfTriangles = 0, then instead of any triangle data, there's quad data.
varies (just after above) number of quads * 24 Triangle data. If NumOfQuads = 0, then instead of any quad data, there's either next header 01 00 01 00, or end of group.
Triangle
Name Type Description
F1 (A) uint16 A of face indice
F2 (B) uint16 B of face indice
F3 (C) uint16 C of face indice
U1 Byte U of first texture coordinate
V1 Byte V of first texture coordinate
U2 Byte U of second texture coordinate
V2 Byte V of second texture coordinate
CLUT_ID UInt16 (BIT operated)* Index to CLUT_ID operated by BIT (see below)
U3 Byte U of third texture coordinate
V3 Byte V of third texture coordinate
Special (see below / After QUAD table) 8 Byte See below (after QUAD table)
Hide Byte/Bool Bool. Hides or shows texture
Red Byte Texture colourization (Red)
Green Byte Texture colourization (Green)
Blue Byte Texture colourization (Blue)
PSone GPU related Byte PSOne instruction
Quad
Name Type Description
F1 (A) uint16 A of face indice
F2 (B) uint16 B of face indice
F3 (C) uint16 C of face indice
F4 (D) uint16 D of face indice
U1 Byte U of first texture coordinate
V1 Byte V of first texture coordinate
CLUT_ID UInt16 (BIT operated)* Index to CLUT_ID operated by BIT (see below)
U2 Byte U of second texture coordinate
V2 Byte V of second texture coordinate
Special (see below) 8 Byte See below (after table)
Hide Byte/Bool Bool. Hides or shows texture
U3 Byte U of third texture coordinate
V3 Byte V of third texture coordinate
U4 Byte U of fourth texture coordinate
V4 Byte V of fourth texture coordinate
Red Byte Texture colourization (Red)
Green Byte Texture colourization (Green)
Blue Byte Texture colourization (Blue)
PSone GPU related Byte PSOne instruction

Special Byte: This byte, needs to be divided to two bytes. So, for example, a 0xE5 needs to be treated like two bytes: 0x0E 0x05

Singular of char Example Description
First char/ 4 BIT B2 --> 0B Unknown
Second char / 4 BIT B2 --> 02 Texture page number

CLUT ID

The most important bit's are the first two on one byte, and last two on last byte. Example: 00000000 00111100 (00 3C) should be read like this: 00111100 00000000 (3C 00) And the CLUT ID is revealed by watching this four bits: 001111[00 00]000000

Same applies to reading CLUT colors (16bits) where they are: 1b-T, 5b-B, 5b-G, 5b-R (Or RGBT if reordered as shown above)

Complete list (without replacing bit order - as is in HEX editor/memory):

CLUT ID BIT HEX
#1 00000000 00111100 00 3C
#2 01000000 00111100 40 3C
#3 10000000 00111100 80 3C
#4 11000000 00111100 C0 3C
#5 00000000 00111101 00 3D
#6 01000000 00111101 40 3D
#7 10000000 00111101 80 3D
#8 11000000 00111101 C0 3D
#9 00000000 00111110 00 3E
#10 01000000 00111110 40 3E
#11 10000000 00111110 80 3E
#12 11000000 00111110 C0 3E
#13 00000000 00111111 00 3F
#14 01000000 00111111 40 3F
#15 10000000 00111111 80 3F
#16 11000000 00111111 C0 3F

Texture

Contains one TIMs with various size 512x256, 673x256, 768x256 (8BPP).

UV calculation algorithm

Float U = (float)U_Byte / (float)(TIM_Texture_Width * 2) + ((float)Texture_Page/(TIM_Texture_Width * 2));

Texture page calculation

               Byte TPage = InputBytes[TexturePage_index] & 0F; //Bitwise TPage byte AND 0F, to delete first 4 bits
               int TPageINT = TPage * 128; //For 16 bit TIM's, the texture page is 128 sized

Example: 0xB2 byte is: 2*128 = 256

Face order / Translation/ triangulation

1.Quad wing order:

 ABCD ---> ABDC
 example:
  f 1 2 3 4
 to:
  f 1 2 4 3

2.Quad triangulation face order

 ABDC > ABD
        ACD (same for VT)
 example:
 f 1 2 4 3
 to:
 f 1 2 4
 f 1 3 4

3.Triangles VT order:

 A/T1 > A/T2
 B/T2 > B/T3
 C/T3 > C/T1
 Example:
 (Also with quad triangulation face order!)
 f 1/1 2/2 7/4 6/3
 to:
 f 1/1 2/2 7/4
 f 1/1 6/3 7/4
 where:
 A=1 B=2 C=6 D=7