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.

Topics - dziugo

Pages: [1]
IPC Description

Shared memory is used for sending data between Launcher and FF7 (CreateFileMapping -> MapViewOfFile):
Code: [Select]
ff7_sharedMemoryWithLauncher - name of the shared memory resource.Notes: The size of the shared block is 0x20000 bytes in length. First 0x10000 bytes are for Game->Launcher traffic (G2L), following 0x10000 bytes are for Launcher->Game traffic (L2G).

Semaphores are used for synchronizing traffic between Launcher and FF7 (CreateSemaphore/OpenSemaphore -> WaitForSingleObject/ReleaseSemaphore):
Code: [Select]
ff7_launcherCanReadMsgSem - Launcher waits on this semaphore, it's released by FF7 when the data is ready to be read by Launcher.
ff7_launcherDidReadMsgSem - FF7 waits on this semaphore, it's released by Launcher when data to be read by Launcher has been read.
ff7_gameCanReadMsgSem - FF7 waits on this semaphore, it's released by Launcher when data is ready to be read by FF7.
ff7_gameDidReadMsgSem - Launcher waits on this semaphore, it's released by FF7 when data to be read by FF7 has been read.

IPC Protocol

For starters, the [] (square brackets) will be used for denoting the unicode string:
Code: [Select]
[Unicode string] - Basically a unicode string with first 4 bytes (little endian) being the length of the string in wide chars.
If you need a complicated description, it's a structure built like this:
X1 X2 X3 X4 C0 D0 C1 D1 C2 D2 ...
X4X3X2X1 - string length in wide chars
D0C0 - unicode character no0
D1C1 - unicode character no1
D1C1 - unicode character no2

No null terminator since the length is specified. Example of string "Hi!":
03 00 00 00 48 00 69 00 21 00 | ....H.i.!.

Commands sent by the game:

CMD_G2L_01: Achievement unlocked
Code: [Select]
01 00 00 00 XX 00 00 00
XX - Achievement Id
Notes: Sent by FF7 when new achievement has been unlocked.

CMD_G2L_02: Sync saved games
Code: [Select]
02 00 00 00Notes: Sent when FF7 thinks it need the saved games to be synced. It greys out the save slot choose menu until either CMD_L2G_07 or CMD_L2G_08 is received.

CMD_G2L_03: Game saved/loaded
Code: [Select]
03 00 00 00 03 00 00 00 XX 00 00 00 YY 00 00 00 ZZ 00 00 00
XX - 00 if saved, 01 if loaded
YY - Save data file Id (00 - 09)
ZZ - Saved game Id (00 - 0F)
Notes: Sent by FF7 when game has been saved or loaded.

CMD_G2L_04: Ready for init data
Code: [Select]
04 00 00 00Notes: Sent by FF7 when it has inited the IPC module.

Commands sent by the launcher:

CMD_L2G_01: Set unlocked achievement
Code: [Select]
01 00 00 00 XX 00 00 00
XX - Achievement Id
Notes: It is sent at startup for each achievement already unlocked.

CMD_L2G_07: Saved games synced successfully
Code: [Select]
07 00 00 00
CMD_L2G_08: Failed to sync saved games
Code: [Select]
08 00 00 00
CMD_L2G_09: Set save path
Code: [Select]
09 00 00 00 [Unicode string]Notes: Sent at startup.

CMD_L2G_0A: Set config dir
Code: [Select]
0A 00 00 00 [Unicode string]Notes: Sent at startup.

CMD_L2G_0B: Set game dir
Code: [Select]
0B 00 00 00 [Unicode string]Notes: Sent at startup.

CMD_L2G_0C: Set lang dir
Code: [Select]
0C 00 00 00 [Unicode string]Notes: Sent at startup.

CMD_L2G_0D: Set achievement data
Code: [Select]
0D 00 00 00
00 00 00 00 [Achievement  0 name] [Achievement  0 description] [Achievement  0 icon]
01 00 00 00 [Achievement  1 name] [Achievement  1 description] [Achievement  1 icon]
02 00 00 00 [Achievement  2 name] [Achievement  2 description] [Achievement  2 icon]
..                       ..                    ..                           ..
23 00 00 00 [Achievement 35 name] [Achievement 35 description] [Achievement 35 icon]
Notes: Sent at startup - 36 entries total. Icons are in the data/xarch directory (*.fgt files being pngs). List of achievement Ids in the AppendixA.

CMD_L2G_0E: Set localization data
Code: [Select]
0E 00 00 00
00 00 00 00 [Text   0]
01 00 00 00 [Text   1]
02 00 00 00 [Text   2]
..                ...
A2 00 00 00 [Text 162]
Notes: Sent at startup - 163 entries total. List of localization data in the AppendixB.

CMD_L2G_0F: Set keyboard data
Code: [Select]
0F 00 00 00 0E 00 00 00
X0 00 00 00
X1 00 00 00
X2 00 00 00
XD 00 00 00
Notes: Sent at startup - 14 entries total being the keycodes. Note that this list only sends the data to be shown in the New game "Keyboard" screen, ff7input.cfg still holds the actual config. The order of the data is the same as in AppendixB list of Ids starting from 05, ending at 18.

CMD_L2G_10: Show message
Code: [Select]
10 00 00 00 [Message]Notes: Mostly used for "Downloading save files".

CMD_L2G_11: Set version info
Code: [Select]
11 00 00 00 [Version string]Notes: Sent at startup.

CMD_L2G_12: Pause game
Code: [Select]
12 00 00 00Notes: Freezes the whole game (no "PAUSE")

CMD_L2G_13: Unpause game
Code: [Select]
13 00 00 00Notes: Unfreezes the game.

CMD_L2G_14: Run the game
Code: [Select]
14 00 00 00Notes: Sent when the launcher is done sending init data.

AppendixA: List of achievements with their Ids.
Code: [Select]
Achievement Id: 0
Name: End of Part I
Desc: Complete the first part of the game
File: 48464.fgt
Achievement Id: 1
Name: End of Part II
Desc: Complete the second part of the game
File: 86789746.fgt
Achievement Id: 2
Name: End of Game
File: 788923.fgt
Achievement Id: 3
Name: Master Materia
Desc: Reach the maximum level of any Materia
File: 048748899.fgt
Achievement Id: 4
Name: Master of Gil
Desc: 99,999,999 Gil
File: 1248996.fgt
Achievement Id: 5
Name: Top Level
Desc: Reach level 99 with any character
File: 3124788.fgt
Achievement Id: 6
Name: Knights of the Round
Desc: Get materia Knights of the Round
File: 780075644896.fgt
Achievement Id: 7
Name: Omnislash
Desc: Get Cloud's last Limit Break
File: 6574897441.fgt
Achievement Id: 8
Name: Catastrophe
Desc: Get Barret's last Limit Break
File: 7411663323.fgt
Achievement Id: 9
Name: Chaos
Desc: Get Vincent's last Limit Break
File: 34577888.fgt
Achievement Id: 10
Name: Great Gospel
Desc: Get Aeris's last Limit Break
File: 9678414515.fgt
Achievement Id: 11
Name: Highwind
Desc: Get Cid's last Limit Break
File: 1548549646.fgt
Achievement Id: 12
Name: Final Heaven
Desc: Get Tifa's last Limit Break
File: 15896335.fgt
Achievement Id: 13
Name: All Creation
Desc: Get Yuffie's last Limit Break
File: 64848486.fgt
Achievement Id: 14
Name: Cosmo Memory
Desc: Get Red XIII's last Limit Break
File: 247889666.fgt
Achievement Id: 15
Name: Slots
Desc: Get Cait Sith's last Limit Break
File: 7478989663.fgt
Achievement Id: 16
Name: Bahamut Zero
Desc: Get materia Bahamut Zero
File: 48748955454.fgt
Achievement Id: 17
Name: Ultimate Weapon
Desc: Defeat the Ultimate Weapon
File: 97444543361.fgt
Achievement Id: 18
Name: Diamond Weapon
Desc: Defeat the Diamond Weapon
File: 347895142.fgt
Achievement Id: 19
Name: Ruby Weapon
Desc: Defeat the Ruby Weapon
File: 4154425789.fgt
Achievement Id: 20
Name: Emerald Weapon
Desc: Defeat the Emerald Weapon
File: 3377854.fgt
Achievement Id: 21
Name: Vincent
Desc: Get Vincent on your team
File: 1132477952.fgt
Achievement Id: 22
Name: Yuffie
Desc: Get Yuffie on your team
File: 47851852.fgt
Achievement Id: 23
Name: Materia Overlord
Desc: Master all Materias
File: 852963745.fgt
Achievement Id: 24
Name: Battle Square
Desc: Start a battle in the Battle Square
File: 1587462895.fgt
Achievement Id: 25
Name: Gold Chocobo
Desc: Get a Gold Chocobo
File: 358749685.fgt
Achievement Id: 26
Name: Won 1st battle
Desc: Win your first battle
File: 95856245.fgt
Achievement Id: 27
Name: Braver
Desc: Use Cloud's 1st limit
File: 184575825.fgt
Achievement Id: 28
Name: Big Shot
Desc: Use Barret's 1st limit
File: 6657748235.fgt
Achievement Id: 29
Name: Galian Beast
Desc: Use Vincent's 1st limit
File: 075841114.fgt
Achievement Id: 30
Name: Healing Wind
Desc: Use Aeris's 1st limit
File: 57484155.fgt
Achievement Id: 31
Name: Boost Jump
Desc: Use Cid's 1st limit
File: 36851458.fgt
Achievement Id: 32
Name: Beat Rush
Desc: Use Tifa's 1st limit
File: 6478254145.fgt
Achievement Id: 33
Name: Greased Lightning
Desc: Use Yuffie's 1st limit
File: 78564198.fgt
Achievement Id: 34
Name: Sled Fang
Desc: Use Red XIII's 1st limit
File: 25366999.fgt
Achievement Id: 35
Name: Dice
Desc: Use Cait Sith's 1st limit
File: 748574726.fgt

AppendixB: List of localization texts with their Ids.
Code: [Select]
Entry Id: 0     Text: Achievement Unlocked
Entry Id: 1     Text: Failed to sync save files, your progression will only be saved locally
Entry Id: 2     Text: Save files have been synced
Entry Id: 3     Text: Keyboard
Entry Id: 5     Text: OK
Entry Id: 6     Text: Cancel
Entry Id: 7     Text: Menu
Entry Id: 8     Text: Up
Entry Id: 9     Text: Left
Entry Id: 10    Text: Right
Entry Id: 11    Text: Down
Entry Id: 12    Text: Start
Entry Id: 13    Text: Switch
Entry Id: 14    Text: Page up
Entry Id: 15    Text: Page down
Entry Id: 16    Text: Target
Entry Id: 17    Text: Assist
Entry Id: 18    Text: Camera
Entry Id: 19    Text: Esc
Entry Id: 20    Text: 1
Entry Id: 21    Text: 2
Entry Id: 22    Text: 3
Entry Id: 23    Text: 4
Entry Id: 24    Text: 5
Entry Id: 25    Text: 6
Entry Id: 26    Text: 7
Entry Id: 27    Text: 8
Entry Id: 28    Text: 9
Entry Id: 29    Text: 0
Entry Id: 30    Text: -
Entry Id: 31    Text: =
Entry Id: 32    Text: Backspace
Entry Id: 33    Text: Tab
Entry Id: 34    Text: Q
Entry Id: 35    Text: W
Entry Id: 36    Text: E
Entry Id: 37    Text: R
Entry Id: 38    Text: T
Entry Id: 39    Text: Y
Entry Id: 40    Text: U
Entry Id: 41    Text: I
Entry Id: 42    Text: O
Entry Id: 43    Text: P
Entry Id: 44    Text: [
Entry Id: 45    Text: ]
Entry Id: 46    Text: Enter
Entry Id: 47    Text: Ctrl
Entry Id: 48    Text: A
Entry Id: 49    Text: S
Entry Id: 50    Text: D
Entry Id: 51    Text: F
Entry Id: 52    Text: G
Entry Id: 53    Text: H
Entry Id: 54    Text: J
Entry Id: 55    Text: K
Entry Id: 56    Text: L
Entry Id: 57    Text: ;
Entry Id: 58    Text: '
Entry Id: 59    Text: `
Entry Id: 60    Text: Shift
Entry Id: 61    Text: \
Entry Id: 62    Text: Z
Entry Id: 63    Text: X
Entry Id: 64    Text: C
Entry Id: 65    Text: V
Entry Id: 66    Text: B
Entry Id: 67    Text: N
Entry Id: 68    Text: M
Entry Id: 69    Text: ,
Entry Id: 70    Text: .
Entry Id: 71    Text: /
Entry Id: 72    Text: Right Shift
Entry Id: 73    Text: *
Entry Id: 74    Text: Alt
Entry Id: 75    Text: Space
Entry Id: 76    Text: Caps Lock
Entry Id: 77    Text: F1
Entry Id: 78    Text: F2
Entry Id: 79    Text: F3
Entry Id: 80    Text: F4
Entry Id: 81    Text: F5
Entry Id: 82    Text: F6
Entry Id: 83    Text: F7
Entry Id: 84    Text: F8
Entry Id: 85    Text: F9
Entry Id: 86    Text: F10
Entry Id: 87    Text: Num Lock
Entry Id: 88    Text: Scroll Lock
Entry Id: 89    Text: Num 7
Entry Id: 90    Text: Num 8
Entry Id: 91    Text: Num 9
Entry Id: 92    Text: -
Entry Id: 93    Text: Num 4
Entry Id: 94    Text: Num 5
Entry Id: 95    Text: Num 6
Entry Id: 96    Text: +
Entry Id: 97    Text: Num 1
Entry Id: 98    Text: Num 2
Entry Id: 99    Text: Num 3
Entry Id: 100   Text: Num 0
Entry Id: 101   Text: Num Del
Entry Id: 102   Text: \
Entry Id: 103   Text: F11
Entry Id: 104   Text: F12
Entry Id: 105   Text:
Entry Id: 106   Text:
Entry Id: 107   Text:
Entry Id: 108   Text:
Entry Id: 109   Text:
Entry Id: 110   Text:
Entry Id: 111   Text:
Entry Id: 112   Text:
Entry Id: 113   Text: F15
Entry Id: 114   Text:
Entry Id: 115   Text:
Entry Id: 116   Text:
Entry Id: 117   Text:
Entry Id: 118   Text:
Entry Id: 119   Text:
Entry Id: 120   Text:
Entry Id: 121   Text:
Entry Id: 122   Text:
Entry Id: 123   Text:
Entry Id: 124   Text: Num Enter
Entry Id: 125   Text: Right Ctrl
Entry Id: 126   Text:
Entry Id: 127   Text:
Entry Id: 128   Text:
Entry Id: 129   Text:
Entry Id: 130   Text:
Entry Id: 131   Text:
Entry Id: 132   Text:
Entry Id: 133   Text:
Entry Id: 134   Text: Num /
Entry Id: 135   Text: Prnt Scrn
Entry Id: 136   Text: Right Alt
Entry Id: 137   Text: Pause
Entry Id: 138   Text: Home
Entry Id: 139   Text: Up
Entry Id: 140   Text: Page Up
Entry Id: 141   Text: Left
Entry Id: 142   Text: Right
Entry Id: 143   Text: End
Entry Id: 144   Text: Down
Entry Id: 145   Text: Page Down
Entry Id: 146   Text: Insert
Entry Id: 147   Text: Delete
Entry Id: 148   Text: Left Windows
Entry Id: 149   Text: Right Windows
Entry Id: 150   Text: Application
Entry Id: 151   Text:
Entry Id: 152   Text:
Entry Id: 153   Text:
Entry Id: 154   Text:
Entry Id: 155   Text:
Entry Id: 156   Text:
Entry Id: 157   Text:
Entry Id: 158   Text: Forward
Entry Id: 159   Text:
Entry Id: 160   Text:
Entry Id: 161   Text:
Entry Id: 162   Text:

Disclaimer: As there is no non-official launcher, the game is still protected with SecuROM, even with changes below applied. You have to own the game/needed files to be able to use it.

Note: This is a tutorial to change the FF7 ReRelease (2012) to work with the old 1.02 exe and retain the ability to make use of the new graphics engine. It doesn't convert the NEW version to OLD.

As you might know, the recent FF7 ReRelease includes the new DX-based graphics engine, and is protected with SecuROM so it doesn't get too easy to use it with the old exe. Here is a quick tutorial how to make it usable. Why? Because we then have a 1.02 exe (which can be modded with anything compatible with 1.02 exe) and use the cool graphics engine which came with the rerelease.

Changes in the new engine by dotemu feat. Aali: The DLL is protected with SecuROM SLL, and has corrupted Export table + rerouted Entry point (so when it's loaded with proper SecuROM-protected exe, it unprotects itself).

Restoring exports and the entry point of the AF3DN.P:
Code: [Select]
HEX Addresses for 1.06 AF3DN.P

Restoring entry point:
00000128: 65 C7
00000129: 84 E0
0000012A: 13 01

Restoring exports:

00005FA0: 00 33
00005FA1: 00 C0
00005FA2: 00 C2
00005FA3: 00 08

00006040: 00 33
00006041: 00 C0
00006042: 00 C2
00006043: 00 04

0001DB20: 00 E8
0001DB21: 00 9B
0001DB22: 00 40
0001DB23: 00 FF
0001DB24: 00 FF
0001DB25: 00 33
0001DB26: 00 C0
0001DB27: 00 C2
0001DB28: 00 14

0001DB30: 00 8B
0001DB31: 00 44
0001DB32: 00 24
0001DB33: 00 14
0001DB34: 00 56
0001DB35: 00 8B
0001DB36: 00 74
0001DB37: 00 24
0001DB38: 00 0C
0001DB39: 00 E8
0001DB3A: 00 F2
0001DB3B: 00 FA
0001DB3C: 00 FF
0001DB3D: 00 FF
0001DB3E: 00 5E
0001DB3F: 00 C2
0001DB40: 00 18

0001DB50: 00 56
0001DB51: 00 8B
0001DB52: 00 74
0001DB53: 00 24
0001DB54: 00 0C
0001DB55: 00 57
0001DB56: 00 8B
0001DB57: 00 7C
0001DB58: 00 24
0001DB59: 00 1C
0001DB5A: 00 E8
0001DB5B: 00 31
0001DB5C: 00 FF
0001DB5D: 00 FF
0001DB5E: 00 FF
0001DB5F: 00 5F
0001DB60: 00 5E
0001DB61: 00 C2
0001DB62: 00 18

Ok, now we'll mod an old 1.02 exe to be used with new engine. This is one way of doing it - we mimick what dotemu has done, but don't change the size of the exe. All we have to do is to reroute ADVAPI calls (registry related) to the functions within the new engine (RegOpenKeyExA becomes dotemuRegOpenKeyExA etc.).

Manually mapping AF3DN.P:
Code: [Select]
HEX Addresses for 1.02 ff7.exe (english)

New RVAs for imports:
003B4C00: 90 4B
003B4C04: 7C 62
003B4C08: 6C 7A
003B4C0C: 5A 8F
003B4C10: 4C 90
003B4C11: 8E 88

Correction of first/original thunk RVA (duplicating to free some space):
003B73F0: 90 00
003B73F1: 88 60

Correction of module name RVA:
003B73FC: A2 A6

003B7490: 90 00
003B7491: 8E 00
003B7492: 3B 64
003B7493: 00 6F
003B7494: 7C 74
003B7495: 8E 65
003B7496: 3B 6D
003B7497: 00 75
003B7498: 6C 52
003B7499: 8E 65
003B749A: 3B 67
003B749B: 00 43
003B749C: 5A 6C
003B749D: 8E 6F
003B749E: 3B 73
003B749F: 00 65
003B74A0: 4C 4B
003B74A1: 8E 65
003B74A2: 3B 79

003B7A4C: 17 00
003B7A4D: 01 64
003B7A4E: 52 6F
003B7A4F: 65 74
003B7A50: 67 65
003B7A51: 43 6D
003B7A52: 6C 75
003B7A53: 6F 52
003B7A54: 73 65
003B7A55: 65 67
003B7A56: 4B 44
003B7A58: 79 6C
003B7A59: 00 65
003B7A5A: 41 74
003B7A5B: 01 65
003B7A5C: 52 56
003B7A5D: 65 61
003B7A5E: 67 6C
003B7A5F: 53 75
003B7A61: 74 41
003B7A62: 56 00
003B7A63: 61 00
003B7A64: 6C 64
003B7A65: 75 6F
003B7A66: 65 74
003B7A67: 45 65
003B7A68: 78 6D
003B7A69: 41 75
003B7A6A: 00 52
003B7A6B: 00 65
003B7A6C: 2E 67
003B7A6D: 01 51
003B7A6E: 52 75
003B7A70: 67 72
003B7A71: 4F 79
003B7A72: 70 56
003B7A73: 65 61
003B7A74: 6E 6C
003B7A75: 4B 75
003B7A77: 79 45
003B7A78: 45 78
003B7A79: 78 41
003B7A7A: 41 00
003B7A7C: 36 64
003B7A7D: 01 6F
003B7A7E: 52 74
003B7A80: 67 6D
003B7A81: 51 75
003B7A82: 75 52
003B7A84: 72 67
003B7A85: 79 4F
003B7A86: 56 70
003B7A87: 61 65
003B7A88: 6C 6E
003B7A89: 75 4B
003B7A8B: 45 79
003B7A8C: 78 45
003B7A8D: 41 78
003B7A8E: 00 41
003B7A90: 20 00
003B7A91: 01 64
003B7A92: 52 6F
003B7A93: 65 74
003B7A94: 67 65
003B7A95: 44 6D
003B7A96: 65 75
003B7A97: 6C 52
003B7A99: 74 67
003B7A9A: 65 53
003B7A9B: 56 65
003B7A9C: 61 74
003B7A9D: 6C 56
003B7A9E: 75 61
003B7A9F: 65 6C
003B7AA0: 41 75
003B7AA1: 00 65
003B7AA2: 41 45
003B7AA3: 44 78
003B7AA4: 56 41
003B7AA5: 41 00
003B7AA6: 50 41
003B7AA7: 49 46
003B7AA9: 32 44
003B7AAA: 2E 4E
003B7AAB: 64 2E
003B7AAC: 6C 50
003B7AAD: 6C 00

The last step, is to rename ff7.exe with ff7_en.exe and place it in the rerelease directory along with the modified AF3DN.P. Then you can just use the launcher and it should work (at least, works for me).

Didn't have time to check this, but it might be possible to use the new engine the way the custom opengl driver is used (through registry entries). It would still have to go through the launcher (unless you replace the Launcher - FF7 IPC module) and use the launcher-made config files, so I'm not interested in doing that.

Coming soon this year: Non-official launcher allowing for off-line play and disabling the cloud saves feature! Yay!

Initial version: 1.0.5

Changes in 1.0.6 version:
AF3DN.P - updated to new version
strings.dat - 1.0.5 -> 1.0.6

If someone kind enough has already reversed the changes, please share the findings :)

List of files/archives that changed:

Code: [Select]
ancnt1 - Fixes Vincent at the end of Disc1 (his leg is up when Aeris...)
ancnt4 - Fixes Vincent
blackbgb - End of Disc 1/Disc 2 changed to End of Part 1/Part 2 ("Please do not open the CD drive" is tossed since there are no CDs now)
frcyo - Names of greens changed: Gysahl vs Gizzard, Krakka vs Karaka, Pahsana vs Pasana, Curiel vs Kurie, Mimett vs Memit (possibly something more)
fr_e - unknown
fship_4 - Highwind flying instructions -> "[ASSIST] to move ahead" vs "[OK] to move ahead", "[ASSIST] toggle map" vs "[ASSIST] to strafe"
las0_8 - Split in The Northern Crater - fixing choices for "I'm going Left/Right" (original team sometimes used simple spaces instead of tabs/choices)
las2_1 - Same as obove, fixing choices for Up, Down, also, a little Easter Egg ;p
lastmap - unknown
uutai1 - unknown
The easter egg: Unused text "012345678901234" changed to "Secret Cow Level" (Diablo? Anyone?? No? Okay :( )

condor.lgp - textures
Code: [Select]
eunit00.tex - Removing Playstation symbols from the buttons, this one is most likely for the low-res, so unused
eunit00d.tex - Renaming buttons (the Playstation symbols vs B1,B2,B3,B4)

Also, the port team was called "dotemu", and is a 3rd party. The name of the new dll graphics driver is: new_dll_graphics_driver (duh! ;p)

Great job they've done.


If all the tracks are as good as in the demo, this is epic.

Scripting and Reverse Engineering / FF7 source recovery
« on: 2007-10-06 12:41:29 »

Dziugo's FF7 Source Recovery Project (or DFF7SRP) ended as quickly as it started. I don't have my copy of FF7 anymore, so it's unlikely that I'll be working on it anytime soon.

The purpose of this project was to reconstruct the initial structure of the files used to compile FF7, as well as all the functions, and defined data types. STR_EN_102.txt file contains the most probable structure, some of the blocks has been identified by file names because of the debug data Square left in the code.

It's far from being complete, I just thought that it could be useful to someone.

Copy & paste my nick to unpack the archive.

Completely Unrelated / While browsing eBay...
« on: 2007-09-10 22:34:44 »

Not that I haven't seen numerous people selling tweaks etc. but... 1 Euro? Now I'm depressed.

Completely Unrelated / Logic Game
« on: 2006-07-18 10:49:48 »
Task? Figure out the link to the next page. Clues can be anywhere in the page and...

Don't post answers here, it'll only spoil the fun for the rest.


Completely Unrelated / The best goalkeeper ever?
« on: 2006-06-01 18:37:30 »
I looked for a non-polish version, but only found this link:

Google video

If you're not sure: Yes, it's a goalkeeper who scored.

Archive / [BETA] Battle-Swirl Fix
« on: 2006-05-13 22:54:49 »
General purpose:

To fix an issue with FF7 crashing randomly when entering battles.

Addition info:

A crash may occur because FF7 is trying to use an outdated pointer in a function
Code: [Select]
Potential crash at:


A problem and a working fix were discovered by Alhexx (info here). My patch updates a pointer instead of NOP-ing the problematic opcode - so the battle-swirl still looks as it should.


There is a reason why it's a beta version. It's possible that it doesn't help you with those crashes! That's why I need people to download and test it - I cannot fix bug in FF7 not knowing of it's existance. If it still crashes, send me debug.txt file (which was created while installing patch) and a full info about the error you encountered (instead of sending it to Microsoft, copy and send it to me :)). Thanks!

Download links:

BattleSwirl Patch link taken down, download MGP from the link below


FF7 Tools / [PC] Yet Another Multi-Patcher - YAMP
« on: 2005-12-31 00:38:59 »
What it is and what it does?
YAMP is a multi-patcher which can be used to apply my (dziugo's) patches to your version of FF7. By default, it'll take the ff7.exe file, make a backup of it (backup_ff7.exe) and produce the output file named ff7.exe (no need to rename anything to get those patches to work). If there already is a backup file, the ff7.exe WILL BE DELETED and the backup will be patched. If you only want some of the patches to be applied, delete/change extension/move those you don't want to use. Patches are stored in "patches\" directory and only there will be looked for. If your FF7 path is:
Code: [Select]
C:\Program Files\Final Fantasy VII\then patches should be in:
Code: [Select]
C:\Program Files\Final Fantasy VII\patches\Don't make another subdirectory there, as it will not work.

Download YAMP and patches you want to apply, unpack them and copy to your FF7 folder.

Configure the patches if needed (see below) and (when done) run install.bat. If everything went good, you can launch FF7 and check how it works. If there is an error message you don't understand, post it here.

Each patch file (*.srb - skerb file) comes with a config file. It's name is the name of patch file, but with a different extension (.txt). Beware: If any of those files is missing, the patch won't be applied. For some patches (MGP, 9999LimitBreaking and Gypt) there is a possibility to configure some things. For example:

Changing default framerate for minigames:
Open "HighwayAndSnowboardMinigamesFix.txt" with a notepad and find the lines:
set snowboard_speed=25
set highway_speed=25
Change 25 to anything you want :) (higher = faster) Note, it's a decimal value not a hexadecimal.

Changing default hp/mp cap:
What about changing the damage that a monster (weapon? :D) can do to you?
Open "9999LimitBreaking.txt" with a notepad and find line:
set amount_monsterdmghp=30000
Change that 30000 to anything (well... don't use values which are greater than 30000) you want (1 is a nice value, isn't it?).

If there is nothing to configure, you'll see something like this:

Listen to your notepad, move along :P.

If there is a line which starts with "set " and the extension of the file is *.txt it means, that it's a configurable variable.

 - MiniGamesPatch - The very first and the most useful one... It updates the code with a simple frame limiter for the Highway, Snowboard, RollerCoaster minigames and the BattleSwirl. Will apply a little bug fix also, so the Snowboard game won't crash so often. A fix for the BattleSwirlCrash now included. Previous version can be found here, but I don't recommend using it - it lacks most of these fixes.
 - TransparentDialogBoxesPatch - Will make the dialog boxes transparent.
 - NoDialogBoxesPatch - Will make the dialog boxes vanish (will overwrite the TransparentDialogBoxesPatch). For those 2 patches, info here.
 - 9999LimitBreakingPatch - Removes the cap for HP/MP/Damage in your FF7. Normal version here (outdated).
 - Gypt - Allows you to skip FMVs when playing FF7. Previous version (with different approach) here. Readme for the YAMP version here and a little bit of explanation about how to use it here.
 - LuckyTifa - Tifa will always get "Yeah!" in her limit break. Some info here and here.
 - LuckyCaitSith - Allows you to manipulate CaitSith's TheSlotsLimitBreak. More info here.
 - AlwaysRun - The main char will run in field by default - press and hold <CANCEL> to walk. Origins here. discontinued

Download links:

AlwaysRun discontinued

Any suggestions/questions? Post them here.


Edit: 2020-03-19 updated links

Mod Edit (SB): Added release tag.

Gameplay / BETA - 9999 Limit Breaking support thread
« on: 2005-12-05 16:46:51 »

Official support thread for 9999LB Patch.

Some questions & answers:
Quote from: I
Q: What this patch does?
A: It gets rid of 9999 Limit in your FF7 game so your Damage, HP and MP (why not? :P) can go over 9999 now.

Q: How it had been done?
A: Dunno. It's my dog's program.

Q: No really, how it has been done?
A: Do you really want to know? :P

Q: Hey, if the HP can go over 9999, then it won't fit on the screen!
A: My dog has taken care of it. It will fit.

Q: Is this patch compatible with English 1.02 version of FF7?
A: I hope so :).

Q: Is this patch compatible with German/French/Spanish/... 1.02 version of FF7?
A: Probably.

Q: If I run it, will it format my HDD?
A: Yes. And you'll be getting only "F" in school.

Q: Can I get a source code of it? I want to make a better version!
A: PM me.

Q: The link doesn't work!
A: PM me.

Q: I've got some other question.
A: PM me/Post it here.

Some screenies:

Download links:
Skerb.exe (see readme inside)
Patch (see readme inside)

Usage (probably the easiest way):
   1) Download both files and unpack them
   2) Put patch.srb with ff7.exe and Skerb.exe
   3) Run Skerb.exe and press any key when it asks you to do so
   4) Rename ff7.exe to something like backup_ff7.exe
   5) Rename patched_ff7.exe" to ff7.exe
   6) Check if it works

If there was any error message, you've probably done something wrong. Recheck everything, see both readmies and try again. If there is still a problem, PM me or post it here.




Dunno if it's the best subforum to post this thread in... If you are reading this, you're a mod and want to move it, go ahead.

Hello there.

I'll have to disappoint you: No, it's not a miraculous way to get rid of your crashes. It's a little research I have to do, to learn more about corrupted movies and handling them. It's only for testing purposes, but... if you can take an advantage of it, why not give it a try?

dziugo's theory

A little explanation first. Those (in)famous FMV crashes/lockups aren't random. Who's experiencing them? People with corrupted movies on their FF7 CDs. It's not caused by scratches (probably) nor your neighbor's voodoo curses (again, probably :wink:). It's caused by... hmm... won't say it, but it's kind of obvious... There are just few "versions" of FF7. Some of them won't cause any problem when watching FMVs, some of them will...

Thanks goes to Larken and Xcalibur for pointing me in the right direction while looking into those crashes.

Why not a fix instead of this research?

I think that the permanent fix is a better choice. If there are only few differences between those files, a simple patcher will do the job. And that's the part when I need you guys&girls.

I've written a simple program. It'll run some checksums on your CDs and gather the needed information (only about those files). It will produce some files which I need you to send me. And that's it.

Why you should trust me?
Because I ask nicely :P.

Link to my program:

Feel free to post your comments/flames.


Yet another boring tech-related-topic by dziugo.

Related link.

Note: All offsets are for 1.02 (I think...) version of ff7.exe.

First step - removing the cap

Here it goes... some offsets and a short description:
Code: [Select]
0x05C7AE2 - HP check when a person which is not in your party levels-up
0x05CE816 - HP check when entering Battle/Menu
0x05D0671 - setting the maximum damage that a monster can do to each of your party member (called three times when entering battle)
0x05DAA92 - setting the maximum damage that a character can do (called whenever it's your character time to attack)

And some other offsets:
Code: [Select]
0x5F1AA3 - no idea what it does...
0x5F2147 - same as above
0x65362C - dunno what it does
0x6E46E9 - It sets HP to 1 when it exceeds 9999... don't know when it's called (never happened while testing)

How do we remove the cap? It's simple. We change a value which is used in comparisons to some higher one. I used 0x7FFF (32767 decimal).

Second step - displaying values in game

This a tricky part... Everything is hardcoded into ff7.exe, so the only way to make it look better is to find all procedures responsible for drawing those values and change them a little bit.

Here are some of them:
Note: Don't try to decode it. It's unreadable even for me :P (but it looks cool).
Code: [Select]
call at 0066067A
copy_img_to_scr(x, y, xx, yy, src_address)

call at 006F638C
print_bar(&struct, unknown)
word: x, y, width, height, new_val, max_val, mode, old_val
dword: rgb_color
}//mode: no_change = 0, healing = 1, damage = 2

call at 006F7346
print_gauge(x, y, progress, height, rgb_color, unknown)

call at 006F7BFB
copyimg(x, y, src_x, src_y, width, height, col1, col2, sth)

call at 006F7346
print_gauge(x, y, progress, height, rgb_color, unknown)

call at 006F9739
write_value(x, y, value, digits, color, unknown)

call at 006F9C44
write_value(x, y, value, digits, color, unknown)

call at 006FA12F
print_box(x1, y1, x2, y2)

Offsets which should be changed to make it look good (only few examples):
Code: [Select]
006C651A CALL 006F9739 ; displaying current HP in menu
006C64F9 PUSH 5 ; forcing FF7 to display 5 digits (default: 4)
006C6516 ADD EDX,1B ; moving that value few pixel to the left

006C6555 CALL 006F9739 ; displaying maximum HP in menu
006C6534 PUSH 4 ; frocing FF7 to disply 5 digits
006C6551 ADD EDX,5F ; tweaking...

006C664A CALL 006F7BFB ; displaying backslash between act_HP and max_HP
006C6646 ADD EAX,56 ; yeah... moving it a little bit

006C632E CALL 006F638C ; health bar
006C62C0 ADD EAX,1C ; moving it a little bit...
006C62D1 MOV WORD PTR SS:[EBP-10],7D ; making it longer...

And a screenshot after applying those:

Third step - displaying damage

Took me some time to track down the responsible procedures...
Code: [Select]
005BB96B MOV EDX,4
005BB9F4 MOV EAX,4
005BBA13 MOV EDX,4
005BBA27 MOV EDX,4
005BBA70 MOV EAX,5

After applying those changes, the damage should be displayed correctly (5-digits when needed).

Last step - Coder needed?

Yeah... If anyone feels like making a patch which will do necessary changes, go ahead. I've got other things to do right now.


Hello there,

Some of you may know me, some don't. My name's dziugo and right now I'm working on getting around the CosmoCrash. I think that I found a way to fix it by changing the main executable (ff7.exe), but I need some info from you guys. If you wish to help me, please don't stop reading.

First thing - system info

Please fill in this questionnaire, and post it. It doesn't matter if you're experiencing crashes or not.

1. Operation System: [simple XP/98 is ok]
2. System Memory: [your RAM size in MB]
3. Is Direct3D mode playable on your computer? [Yes/No]
4. Optical Drive which you use to play FF7: [be as precise as possible - if you're running from a virtual drive, just type "virtual drive"]
5a. Did you use original disk when installing FF7? [Yes/No]
5b. Are you using original disks when playing? [Yes/No]

5c. <Only if you typed No in 5b> How did you make your copy? [be as precise as possible - if it's Ultima version, just type "Ultima"]
6. Which crashes are you experiencing? (please make a list) [typical: none/Cosmo/Gondola/Black Materia/other]

And that's it.

NOTE: If you are using Ultima version or any other downloaded one, please make a comment about it. If you don't want people to know that you are using one, fill in the questionnaire and PM it to me (your information is safe with me, but do that only if you trust me).

1. Operation System: Windows Server 2003
2. System Memory: 768 MB
3. Is Direct3D mode playable on your computer? Yes
4. Optical Drive which you use to play FF7: BENQ DD DW1620 (DVD+-RW)
5a. Did you use original disk when installing FF7? No
5b. Are you using original disks when playing? No
5c. How did you make your copy? Copied all the files from the CD and burnt it on blank one.
6. Which crashes are you experiencing? none

NOTE: I'm not experiencing any of those crashes, that's why I was able to write gypt. If you want to help community and get rid of those crashes, please reply with your system info.

Asking for help

I need someone who is experiencing the CosmoCanyon crash to help me, and give some info about FF7 memory status when the problem occurs. It would require running a program on your computer so PM me if you're ok with that, and still wish to help me.

Thanks in advance.

General Discussion / It's good to be... a Key to Ancients?
« on: 2005-09-21 07:19:13 »
Intro (read first):

I'm working on some kind of fix for FF7 video issues. I was unable to get my copy of FF7 crash on me while watching Cosmo/Gondola/Black Materia etc. movies. I was installing codecs, reinstalling them, burnt a cd and scratched it, reinstalled windows, tried Direct3D, Software mode, even get my old PC to see if it crashes... No luck :P. So... I burnt a cd without a movie (Bugenhagen's demo) and tried to make it work. Found a way to do so (however, I don't know if it will work for those who are suffering from this kind of crashes) by resetting some variables and forcing ff7 to recreate the scenery. Today I forgot to set some variables and...

Oh well... You have to see it :)

Link 1
Link 2
Link 3

Actually made me laugh, maybe you'll find that funny too :P.

Also: Be prepared for some kind of POLL soon... I'll find some way to test if my fix works, but I need some info from people who suffer from FMV-crashes. If it happened, that I got you past some crash, don't be surprised if you see email from me... Reply or ignore it, just don't flame me for it.


If you're unfamiliar with MGP, check this

Ok... first, the debug info from patching the ff7.exe ver 1.00.
Code: [Select]
1) Initial file analysis.
Free space in text segment (info by image section header): 0xcb
Needed free space: 0xff
Not enough free space. Let's see if we can get some more...
Available free space: 0xacb
Enlarging the segment by: 0x200
Updated segment raw pointer at: 0x1d8 New value: 0x3aac00
Updated segment raw pointer at: 0x200 New value: 0x3ae200
Updated segment raw pointer at: 0x228 New value: 0x58c800

Updated segment raw size at: 0x1b0 New value: 0x3aa800
Analysing text segment...
Checking free space...
Offset: 0x3aa935 Free space: 0x2cb

2)Searching for references.
Raw: 0x24f63d Offset: 0x65023d
Raw: 0x24f2e2 Offset: 0x64fee2
Raw: 0x31828f Offset: 0x718e8f
Raw: 0x25f240 Offset: 0x65fe40
Raw: 0x25f270 Offset: 0x65fe70
Raw: 0x25f2fd Offset: 0x65fefd
Raw: 0x900 Offset: 0x401500
Raw: 0x1acd5 Offset: 0x41b8d5
Raw: 0x1f4016 Offset: 0x5f4c16
Raw: 0x237856 Offset: 0x638456
Raw: 0x2379c5 Offset: 0x6385c5
Raw: 0x2c2eda Offset: 0x6c3ada
Raw: 0x341da4 Offset: 0x7429a4
Raw: 0x36f276 Offset: 0x76fe76
Raw: 0x381f91 Offset: 0x782b91
Raw: 0x39d57b Offset: 0x79e17b
Virtual address: 0x675c8b Raw offset: 0x27508b
Immediate: 0xda4228
Immediate: 0xd76fe4
Immediate: 0xdc9218
Immediate: 0xe65930
Immediate: 0xe65920
Immediate: 0xe65938

3)Preparing the output file.
Allocating space at: 0x3aa935 amount of space allocated: 0x5c
Allocating space at: 0x3aa991 amount of space allocated: 0x22
Allocating space at: 0x3aa9b3 amount of space allocated: 0x41
Allocating space at: 0x3aa9f4 amount of space allocated: 0x40
Inserted a new call/jmp, destination: ffeb48f9
Inserted a new call/jmp, destination: ffeb4913
Inserted a new call/jmp, destination: ffeb4994
Inserted a new immediate, destination: e65920
Inserted a new immediate, destination: e65930
Inserted a new immediate, destination: e65920
Inserted a new immediate, destination: e65938
Inserted a new immediate, destination: e65920
Inserted a new immediate, destination: e65930
Inserted a new immediate, destination: e65924
Inserted a new immediate, destination: e65934
Inserted a new immediate, destination: da4228
Inserted a new immediate, destination: e65938
Inserted a new call/jmp, destination: ffeb486c
Inserted a new call/jmp, destination: ffffffb5
Inserted a new call/jmp, destination: ffffff51
Inserted a new call/jmp, destination: ffea48fa
Inserted a new immediate, destination: d76fe4
Inserted a new immediate, destination: d76fe4
Inserted a new immediate, destination: e65930
Inserted a new immediate, destination: d76fe4
Inserted a new call/jmp, destination: ffeb482d
Inserted a new call/jmp, destination: ffffff76
Inserted a new call/jmp, destination: ffffff12
Inserted a new call/jmp, destination: fff6d865
Inserted a new immediate, destination: dc9218
Inserted a new immediate, destination: dc9218
Inserted a new immediate, destination: e65930
Inserted a new immediate, destination: dc9218
Wrote: 0x5c bytes at offset: 0x3aa935
Wrote: 0x22 bytes at offset: 0x3aa991
Wrote: 0x41 bytes at offset: 0x3aa9b3
Wrote: 0x40 bytes at offset: 0x3aa9f4
Inserted a new jmp at: 24f2e7 jmp destination: 15b6c9
Inserted a new jmp at: 318292 jmp destination: 9275f
Last non-nop byte is at: 0x3aaa33 Size of image: 0x3aa634
Updated segment virtual size at: 0x1b0 New value: 0x3aa634
Raw: 0x547be0
Applying snowboard patch.

4)Saving file.

The debug info contains four headers:
Code: [Select]
1) Initial file analysis.
2) Searching for references.
3) Preparing the output file.
4) Saving file.

Let's take a look at the first one... What the patcher does in it's first stage? Basically, it checks, if the amount of free space in the *.exe file is high enough (first release of my patch needs at least 0xFF bytes). If it's not it'll try to enlarge that area a bit... It requires writing new values into the file header. If the file can be enlarged, the patcher does it (the file will be a little bit bigger after patching). When the first step is successfull...

Patcher moves to the second stage... It will search for all needed functions in the text-segment of the exe file... Here is the full list of the functions:
Code: [Select]
highway_init - function which is called to prepare the HighwayMiniGame (needed only to get the extra_call function)
highway_main - function which is responsible for creating each frame of the HighwayMiniGame (we'll do some modifications here)
snowboard_main - we'll do some modifications here too :P
get_actual_cc - function gets a memory address, and writes there the rdtsc results...
calculate_cc - function gets three memory addresses, subtracts the value in the second one from the value in the first one and writes the result to the third one :P
convert_cc_to_float - gets memory address and converts a hex-value stored there into the float-variable, stores it on the FPU's stack
frame_cap - ok... here ARE the functions responsible for frame-limiting of some modules of ff7 (field, menu, battle, submarine...) - explained below
extra_call - function returns the imm_benchmark value using EAX registry - we aren't exactly searching for this... we get the address from the highway_init function

Here is the first question: Can't we just use some of the existing frame-limiters? We can, but since they aren't optimized at all, and required some pre-call modifications... I decided to write my own (basing on the existing one of course :P). Then why do we search for those? We don't need the code, but we need some safe variables. By safe, I mean the variables which could be used freely. If we're playing HighwayMiniGame then we CAN use SubMarine variables, and we will :). We'll unpack the required variables from some function and hardcode it into our functions. Which function will we hijack? The 9th is the SubMarine frame-limiter and I think it's the best choice (you can always pick some other function, use the -hijack switch when using my patcher).

Immediates used when preparing the code:
Code: [Select]
imm_benchmark - value which stores the address of some MAIN variables... if we add 0x30 to this pointer we'd get a pointer to a value which contains the speed of our CPU in clock cycles (very importand value - VIV :P)
imm_highway - value which contains 1 if the HighwayMiniGame is running - we'll hijack that value too :P see below
imm_snowboard - same as imm_highway, just refers to SnowboardMiniGame
frame_cap - raw_pointer to our hijacked frame-limiting function
imm_old_cc - stores the old clock cycles count
imm_actual_cc - stores the actual clock cycles count
imm_cc_per_frame - imm_benchmark divided by the frame-rate - clock cycles per frame

After that, you can tell if the chosen frame-limiting function was a good one :P. Simply look at the imm_cc variables. If they are something like 0x<six digits here> and are similar, it was a good choice.

If the second part was successfull, patcher moves to the third section...

It'll "allocate" the free space for functions we need to inject into the *.exe file. If it happens, that there is enough free-space (to put our code) in the middle of the text segment it will do that (jumps at the beginning of each function will do the job if it was just a NOP-ed field inside of some bigger functions).

Functions to be injected:
Code: [Select]
frame_cap_main - function which will pause our game if the frame was processed to fast
frame_cap_init - function which will fill the imm_cc values with the initial data
highway_hijack - code which will handle calling the frame_cap_main and frame_cap_init functions
snowboard_hijack - same as above
We will use the imm_highway and imm_snowboard variables to check, if the frame_cap_init was called already. Since these values are BOOLEANS, we will change some code to use (for example) TEST EAX, 0x01 instead of TEST EAX, EAX. Doing that will allow us to use other bits (we'll take the second one :P). If our bit isn't set we call the frame_cap_init and set that bit. Simple isn't it?

We'll do the necessary CMPs in our hijack_functions and use the CMP field in the highway_main and snowboard_main to to our hijack_ones...

When the patch is completed, it's written into the file. At the end the patcher checks if SnowboardMiniGame needs patching (don't know if it's the only problem with that minigame...) and do that if necessary...

When the third step is completed successfully, the patcher creates a new patched file... And that's it... If you read that, you'll know that this patch is somehow flexible. It'll accept ANY version of ff7 as long as the needed functions aren't heavy-modified. If there are any questions/comments (there won't be any :P that's for sure) post them below.


Archive / Mini Games Patcher - BETA release
« on: 2005-09-08 16:57:26 »
This is a BETA release - use it only if you're brave enough.

It's a patch which adds a Frame-Limiter to Highway/Snowboard MiniGame and fixes a bug with Snowboard MiniGame crashing occasionally.

Confirmed to work with:
 - Version 1.00 ENG PC original ff7.exe
 - Version 1.02 ENG PC original ff7.exe

It has been written to be as flexible as possible. Apply it AFTER any other patches (Chocobo/HighRes/Music...).

Usage (important - read it):
 - copy the patcher to your main ff7 folder
 - make sure, that file ff7.exe exists in that folder :P
 - run patch (if all went fine, file "patched_ff7.exe" should appear in that folder)
 - copy your "old" ff7.exe into some safe place
 - rename the newly created file to "ff7.exe"
 - try and run the game

If something went wrong while patching, error message should appear... It's usually self-explanatory (like: Patch failed :P).

Patch itself is a command-line tool. There are few switches which could be used when running it:
Code: [Select]
-debug [0/1]
-errors [0/1]
-in [input_file_name]
-out [output_file_name]
-hijack [Hex digit]

Code: [Select]
-debug 1 -errors 0 -in old_ff7.exe -out ff7.exe -hijack A
 - Debug mode will be turned on (default off) displaying info when patching executable.
 - ErrorDisplaying mode will be turned off (default on) no error messages would appear.
 - File to patch: old_ff7.exe (default ff7.exe)
 - Output file: ff7.exe (default patched_ff7.exe)
 - Variables to hijack: 0x0A (default 9)

What is a "-hijack" switch? The patch uses three variables, which must be static-ones. It will search for the variables to use and "hijack" them. More info soon (I hope...).

Download link:

This is a BETA release - use it only if you're brave enough.

Post your problems here.


Archive / Highway MiniGame speed?
« on: 2005-09-04 23:11:57 »
Ok... first of all, I've managed to add a frame-limiter to the MotorBike MiniGame (and it works, woot). The problem is, I don't know how many frames it should dispay per second. If anyone here owns a PSX (which i think would be the best source) version of FF7 and could check it...

What i need is the time (in second) between the first and the last visible frame in the Highway MiniGame, that can be accessed through the GoldSaucer WonderSquare. Thanks in advance :)



This is another boring (really boring, seriously :P) tech-related-topic by dziugo. If you aren't interested in this kind of stuff, stop reading now, no need to waste your time here :).

For those who haven't yet closed their InternetExplorer window...

Prologue - Info about rdtsc

What is rdtsc? It's an instruction of modern (286+ i think... :P) CPUs that fills the EAX and EDX registers (yep you're right, 64-bit value) with the amount of clock cycles since the start of system. This value is kept by the CPU and is increased every [1/CPU speed] second. I have an Athlon XP 2000+ on-board, so this value is increased every 0.000000000602 seconds in my CPU. Why am I talking about that? You'll see (or you won't? anyone got to this part? :P).

Part1 - FF7 benchmarking your CPU

When FF7 is launched it (kind of) benchamrks your CPU. It checks how many clock cycles are done in 1000ms (it's 1663653990 on my computer). Basically it's just a speed of your CPU in Hertz. After that, this value is stored (address: 0x014F2B80) and used whenever it's necessary.

Part2 - FF7 using simple frame limiter

As we all know (well, I didn't, but you've probably knew :)), FF7 uses a frame limiter to make it run at similar speed on different computers. How it's done? Let's take a SubmarineMiniGame

When initialising the MiniGame, the value found under 0x014F2B80 is divided by 30.0 (meaning - FPS-limit is 30.0). FF7 also subtract 10000.0 from the result (it's some kind of speeding-it-up, but why it's done?). FF7 calls rdtsc before every frame, and stores that value. Then it does all the dirty job (scene creating). When it's done, it calls rdtsc one more time and calculates the difference between the new value and old value. After that, it pauses if necessary (well.. it's just a loop which is ended when the actual value is greater than the one it calculated at initialising the MiniGame). Simple isn't it? It keeps the frame rate under the 30.0FPS (about...). But... what happens, when the CPU isn't fast enough to keep processing the frames? Theoretically, it won't do any frame-skipping, since it's coded to run at 30.0FPS.

Part3 - Other frame limits in FF7

Here are the FPS limits for each FF7-internal system (could contain errors):

Battle - 15.0FPS
Field - 30.0FPS (subtracts 10000.0 from the result)
Menu - 60.0FPS
Submarine - 30.0FPS (subtracts 10000.0 from the result)

Part4 - Misc stuff and ending

First, the misc stuff:
 - timeGetTime is called in SubmarineMiniGame to calculate the FPS rate for debugging, nothing more (AFAIK)
 - I don't know, how much the FF7 speed is affected by using the multi-threading OS (well, at least it looks good...)
 - In HighwayMiniGame, the rdtsc-calculating are done, but not used

I'll try to implement the frame-limiting in the HighwayMiniGame, but i don't know how long will it take (if ever). Also, I'm looking forward to check what Smithie has done already with his dT. For those, who've read the whole topic - congrats :). Yep it's the end.


Archive / gyptNEW - tutorial
« on: 2005-08-22 21:54:18 »
Read this first

A fix that usually works, and which renders this program useless:
Hi, first post here  :-D, ok, i was having the exact same problem and i had k-lite codec pack installed, maybe you are on a similar situation

the game apparently has some incompatibility with the avi splitter, a filter that comes with some codec packs. you can either uninstall it or disable it, in k-lite codec pack this can be done by acessing the Codec Tweak tool that comes together, under "disable filter" tab find Avi Splitter (Gabest) and check it, there you go, hope this helps  :-)

In a case that it didn't work for any reason, read the tutorial. You got any questions / problems? Read it again. You might not get an answer to your problem if you ask for anything that is already covered here.

Tutorial - Part1

I've been told, that my gypt *could* be a mystery to some of you, and it's usage to most of you :P. There you go - a tutorial (with screens :)) to use it which covers skipping the gondola crash.

First of all: We need a copy of FF7 that hangs up when playing some of the FMVs, so if your FF7 runs OK, you'll need to change your PC or OS to the correct one :) (seriously, if you're the lucky one and don't experience those crashes, you can stop reading now).

Ok... how to use it? First of all, download it here:

Link to gypt

...and run it. You'll see something like this:

You can forget about that proggy for a while. Run FF7 and load your save-game. Play as normal as you can :P When you get to this point:

(if you don't see this image, it's Cloud and Aeris in the GhostHotelRoom just before the date)

You have to press Ctrl+Shift+F11.

You *should* hear a Beep coming from your Speakers (if your OS is configured to play those :P).

Again, play normally as before. After the GreatPlay, when your Date normally suggests a gondola ride, you should see something like this:

(this is kinda cool, that FF7 just handles this instead of hanging up)

As Aeris says... Ctrl+Shift+F12 and the gypt should stop. You should also hear a Beep again:

gypt is inactive. Save as soon as possible and restart FF7 (you can close gypt now).

Tutorial - Part2

This part of tutorial will cover the usage of the program without using the shortcuts (Ctrl+Shift+F11 and Ctrl+Shift+F12).

Download the program (link above) and run it:

Launch the FF7. Now Alt-Tab from the game, press the "Refresh" button, and you should see something like this:

If the "Previous Window" and/or "Next Window" buttons are active, it means, that you run more than one instance of FF7. Use these buttons to choose the correct FF7-Window:

When you're sure, that this is the correct window, press the "Guard" button.

It caption will change to "Stop" (could be seen above). To stop the guarding, press that button again.

Part3 - Questions and Answers

Q: When to use gypt?
A: Basically it should be activated just before going to Bugenhagen to see his demo and before the date in Gold Saucer.

Q: When closing gypt it says something like "Address wasn't know, please send the debug.dat to the author of the program". What to do?
A: Send the file that had appeared in your gypt directory. It will contain your save-game. Send it to me only if you're ok with that. Sending that file ensures the future gypt-compatibilty with your version of FF7.

Q: Link is dead. Can't download this program. What to do?
A: PM me.

Q: gypt doesn't work with TheSaiNt's HighRes patch. I like this patch and don't want to uninstall it. What to do?
A: It has been fixed. Be sure to download the latest version.

Q: I downloaded some file, but I can't run it. Why?
A: The program is rar-compressed. You need a program to decompress it. Google for RAR.

Q: I have a problem that wasn't mentioned above. What to do?
A: Post it here. I'll try to answer it ASAP.

Just some new things about the "date in GS".

Section 1 - "gears" update

It's all about the save-game-format (the numbers within parentheses indicate the offset in the save-file when the CRC data is at 0x0000)
 - "counter" (0x0B84) DWORD - it countdowns from the given number of seconds to zero (it still works even if you Alt-TAB from the game)
 - "timer1" (0x0B88) WORD - holds the miliseconds part of the current time (well... it's not exactly the miliseconds, but the in-game-countdown miliseconds are based on this value)
 - "timer2" (0x0B8C) WORD - same as above (why two variables?)
 - "party's heading (not on world map)" (0x0BA0) byte - same as "party's heading" on the world-map (look for info in "gears")
 - "in-game-countdown (hours)" (0x0BB8) byte - DWORD found under the (0x0B84) divided by 3600
 - "in-game-countdown (minutes)" (0x0BB9) byte - minutes...
 - "in-game-countdown (seconds)" (0x0BBA) byte - seconds...
 - "in-game-countdown (miliseconds)" (0x0BBB) byte - miliseconds - based on the (0x0B88) variable
 - "PHS Locking Mask" (0x10A4) WORD - explained in "gears", I've only "updated" the offset

Ok... now the Key Items section. It starts at (0x0BE4) - known in "gears". It's length is 8 bytes (oh well... that's what "gears" say) and first 59 bits indicate the presence (or absence) of "some key item". Here is the Key Items list (looked kinda good in notepad ):

Code: [Select]
1st byte (0x0BE4):
"Cotton Dress" - 0x01 (00000001b)
"Satin Dress" - 0x02 (00000010b)
"Silk Dress" - 0x04 (00000100b)
"Wig" - 0x08 (00001000b)
"Dyed Wig" - 0x10 (00010000b)
"Blonde Wig" - 0x20 (00100000b)
"Glass Tiara" - 0x40 (01000000b)
"Ruby Tiara" - 0x80 (10000000b)

2nd byte (0x0BE5):
"Diamond Tiara" - 0x01 (00000001b)
"Cologne" - 0x02 (00000010b)
"Flower cologne" - 0x04 (00000100b)
"Sexy Cologne" - 0x08 (00001000b)
"Member's Card" - 0x10 (00010000b)
"Lingerie" - 0x20 (00100000b)
"Mystery panties" - 0x40 (01000000b)
"Bikini briefs" - 0x80 (10000000b)

3rd byte (0x0BE6)
"Pharmacy Coupons" - 0x01 (00000001b)
"Disinfectant" - 0x02 (00000010b)
"Deodorant" - 0x04 (00000100b)
"Digestive" - 0x08 (00001000b)
"Huge Materia (Fort Condor)" - 0x10 (00010000b)
"Huge Materia (Corel)" - 0x20 (00100000b)

"Huge Materia (Underwater)" - 0x40 (01000000b)
"Huge Materia (rocket)" - 0x80 (10000000b)

4th byte (0x0BE7)
"Key to Ancients" - 0x01 (00000001b)
"Letter to a Daughter" - 0x02 (00000010b)
"Letter to a Wife" - 0x04 (00000100b)
"Lunar Harp" - 0x08 (00001000b)
"Basement Key" - 0x10 (00010000b)
"Key to Sector 5" - 0x20 (00100000b)
"Keycard 60" - 0x40 (01000000b)
"Keycard 62" - 0x80 (10000000b)

5th byte (0x0BE8)
"Keycard 65" - 0x01 (00000001b)
"Keycard 66" - 0x02 (00000010b)
"Keycard 68" - 0x04 (00000100b)
"Midgar parts" - 0x08 (00001000b)
"Midgar parts" - 0x10 (00010000b)
"Midgar parts" - 0x20 (00100000b)
"Midgar parts" - 0x40 (01000000b)
"Midgar parts" - 0x80 (10000000b)

6th byte (0x0BE9)
"PHS" - 0x01 (00000001b)
"Gold Ticket" - 0x02 (00000010b)
"Keystone" - 0x04 (00000100b)
"Leviathan Scales" - 0x08 (00001000b)
"Glacier Map" - 0x10 (00010000b)
"A Coupon" - 0x20 (00100000b)
"B Coupon" - 0x40 (01000000b)
"C Coupon" - 0x80 (10000000b)

7th byte (0x0BEA)
"Black Materia" - 0x01 (00000001b)
"Mythril" - 0x02 (00000010b)
"Snowboard" - 0x04 (00000100b)

We just have to decide which items do we want (in each byte) and add their values together.

f.e.  If we want the "PHS", "Gold Ticket" and "Glacier Map" we would add 0x01, 0x02 and 0x10 (which gives 0x13 or 00010011b). I know it's obvious :P

Section 2 - date in GS info

We all know about the love-points and this kind of stuff, so let me explain some things, that *could* be unknown.

First of all, the PLOT progression variable (0x0BA4) WORD - let's think of it as a byte.
 - Just before the "Have to stay in Gold Saucer" this var is set to 0x47
 - When staff-member says "I will let you know once the repairs are completed." the var is set to 0x4A
 - When Cid says (:P) "...zzzz...zzzz..." the variable is set to 0x4D
 - When going out with our date (it's set in our room) the var is set to 0x50
 - After the first movie in the gondola the var is set to 0x53
 - When Cloud shouts "Hey Cait Sith!" the var is set to 0x56
 - When our date comments the "behaviour" of Cait Sith (just before going to hotel again) the var is set to 0x59
 - After choosing party-members when Cait Sith says "Then see you later." the var is set to 0x5C

Now the "date plan variable" (0x0CE8) byte - is set to indicate the progress of our date (prevets from joining "The great play" again f.e.)
 - Before the date it's set to 0x00
 - When going out (from our room) it's set to 0x02
 - Immediately after going to "station" it's set to 0x00
 - After the play, when our date suggest to go to gondola it's set to 0xC0
 - It's set to 0x80 right after the *suggestion* (and it's 0x80 ever after :))

The "gondola variable" (0x0CF6) byte - before the date it's set to 0x01 and when we enter the gondola screen with our date (before getting the tickets) it's set to 0x02. It prevents us from getting another ride when chasing Cait Sith.

The "Cait Sith chase variable" (0x0CE9) byte - it's 0 before the great chase and:
 - it's OR-ed with 00000010b (0x02) when entering Battle Square
 - it's OR-ed with 00000100b (0x04) after finding CS in Wonder Square
 - it's OR-ed with 00001000b (0x08) when entering Speed Square
 - it's OR-ed with 00010000b (0x10) when entering Chocobo Square
 - it's OR-ed with 00000001b (0x01) when the CS escapes form Chocobo Square (and gives the Keystone to Tseng)
(Not sure about the last two - these could be switched | Edit: these were all messed up... now it should be correct)

After that, when going back to hotel, we're given the PHS Lock with Aeris (how nice :P) - the (0x10A4) WORD now says 0x09, and the third Party Member is automatically assigned (of course we can switch him/her with someone else). The third member is the person who we had a date with (and if we were on a date with Aeris, the other character which have the most love-points).

Ok... and that's it. I won't post which variables to change to skip the sometimes-crashing-gondola-ride for now. I will have to do some more tests (and implement it into gypt). You're welcome to post any suggestions about this thread (and any other thread :P) and/or correct mistakes that I've just made. Oh well... I just need some feedback... :-?

(sleepy) dziugo

Guess I was too sleepy...

I didn't wrote, why i mentioned those "countdown" and "counter" variables.

Well... It isn't displayed in the game at all, but we have a countdown enabled TWICE when being on a date.

The countdown starts first time (the timer is set to 0x1E or 30 seconds) when we board the gondola (when it reaches zero, the Cloud automatically looks through the "window" and we watch the first movie).

The countdown starts again when starting to chase Cait Sith (the timer is set to 0xB4 or 180 seconds) but this timer doesn't matter though... I don't know why it's there :P After Talking to Cait Sith (or even choosing our party and leaving the Gold Saucer if we are fast enough) it still countdowns (probably, there was a time limit on the Cait Sith chase which had been removed).

Ok... now the Key Items section update... (gee... forgot about it too...)

As we all know (spoiler! spoiler! :P) Cait Sith gives the Keystone to Tseng, so we have to update our Key Item list.

To get rid of a Keystone, we have to AND the (0x0BE9) byte with 0xFB (11111011b) or just zero the third bit.

Now it should be ok...


Scripting and Reverse Engineering / gypt - BETA release
« on: 2005-08-05 01:10:49 »
Program which "skips" the Bugenhagen's tale in his laboratory.

Link to download the program (feel free to scan it with some av): - 239KB Edit: File taken down. Click here for new version.

How does it work?
It "finds" the FF7 program in the memory, search for the correct index and modifies the variables a little bit.

Ok... now what do we need to change (numbers in parentheses indicate the save-game offset when the checksum DWORD is at offset 0x00):

 - "Plot Progression" (0x0BA4 - present in the "gears") variable. Before visiting Bugenhagen, it's 0xD5, when the demo is completed, it's 0xED;

 - "Nanaki's" (0x0D45) variable. When it's set to 0x9C, Bugy will say "the story of the planet...". It's set to 0xFC after the demo, and Bugy will say
"Nanaki? His father a coward?"

 - "Bugenhagen's" (0x0D4E) variable. It's usually 0x01 (but i've seen also 0x09 in one save-game). It's OR-ed with 0x02 (0000010b) when Bugy says "Door is unlocked...". After that it's OR-ed with 0x40 (01000000b) when we're going up with Bugy. It's OR-ed with 0x80 (1000000b) when Bugy says "The story of the planet (blah blah)". So, we need to OR the variable with 0xC2 (11000010b).

 - Char1 (0x0CAE) and Char2 (0x0CAF) variables. Took me some time to figure it out (why the hell it switches sometimes??). But it's rather simple. The Char1 is the second character in your team (just below the Cloud in the Menu) and the Char2 is the third character. Now... these variables sometimes switches when going up with the Bugy to see the demo. It switches because always the second character (the one in Char1 byte) notices the shootig star, and there are some priorities which determine who will say that. Ok... here's the priority from the most to the least:

   Aeris -> Tifa -> Yuffie -> Barret -> Cait Sith

For example: if we had such a team:
 * Cloud
 * Barret
 * Aeris
Then, when going up, Barret and Aeris would switch (before: Char1 == Barret and Char2 == Aeris; after: Char1 == Aeris and Char2 == Barret).
Using that pattern, we would see, that Aeris will ALWAYS notice the shooting start (if she is in a team) and Cait Sith will NEVER say anything about it.

Ok... now, how to use the program?
Launch the FF7, load the correct game and be sure, that you're JUST BEFORE seeing the Bugenhagen's demo (you can be anywhere in CosmoCanyon, but you'd better have 3 characters with you and ready to go to Bugenhagen - I've tested it from the savepoint, standing next to Bugy, next to fire and few other places so it should work) Alt-TAB (or Ctrl-Esc) from the game (this is necessary for now, later I'll do some shortcuts... maybe :P), and run "gypt".

Press the "Refresh" button, and it *should* find the FF7 window. If the "Previous" or "Next" button is active, then you've more than one instance of FF7 launched. Gypt will tell you, who is in your team and where are you. Search for the correct instance of FF7 and press the "Modify" button. And that's it...

Now the worst part - bugs
I've only tested it with my version of FF7 so it could stop responding when used on some other version (but eventually it *should* become active again - just be patient).

When you see a message indicating that it doesn't known the just-found memory index, it will create a file "debug.dat" in the active directory. Please send me that file (it'll conatin the memory address which your version of FF7 uses, and your save-game) if you don't mind.

If you have any question, just post it. Good night (gee... it's 3:10 A.M. ...)


Hello there :P

"Intro - ...duction..."

I was debugging ff7.exe to find some information useful when trying to change font used in-game. Why would i do that for? Because a team from Poland - FF7-PL, is making a polish version of FF7 (which is my favourite game... again :)). You know who M4v3r is, so I think I don't need to say anything else. The polish font in their release occupies some in-my-humble-opinion-very-important characters, so I started to make my own font. I don't know that for sure, but i think I found out some info, which wasn't posted here, on Qhimm's forum. So... that's what I've found out. Listen up...

"First chapter - Why mine is bigger than yours?"

FF7 uses an array to see how much pixels each letter has. The address in memory (after loading ff7.exe EN v1.0):
 - 0x0098F458

In that array, each byte corresponds to a single character. To decode the data stored, all you have to do is get the byte for a character, and look for the corresponding data in the array. After that:
 - to get a character's width, AND a just-found-byte with 0x1F  (00011111b)
 - to get a character's padding (well I don't know if that's what it's called, but it's just a number of pixels before the character), SHR just-found-byte by 5

To get a quotation mark "values", we:
 - get the byte for that character - it's stored in address 0x0098F458 (base address) + 0x1F (the hex value for quotation mark). It should be 0x27 (or 00100111b or 39);
 - AND it with 1F, or modulo it by 0x20 (32) - we get 7
 - SHR it (the byte read 0x27) by 5 (or divide by 32) - we get 1
And... that's it. Remeber that these values are in 320x240 resolution mode (not really sure about that), to get the size in the 640x480 mode multiply the results by 1.666667, and truncate the non-integer part (even if it's 4.9998, we get 4).

OK... We do know, how to get the character size. But how to change it? There are some methods. We can do it by changing the data stored in the memory for example. We get the immediate effect. To those who don't want it to be a temporary change, we have to change data in the file. Which file? Oh... that's the 3rd file of WINDOW.BIN pack-file. We have to unpack it, change it and repack it (the worst part :P). It wasn't me who discovered, that the data is stored in that particular file (i just knew that it's in WINDOW.BIN, then I came here to see if it has already be decoded, and found out that I've just reinvented the wheel), so don't call me a leecher :P

"Second chapter - Oh mummie, that dog after some paintings looks cool"

We all know, that the font itself is in menu_us.lgp file, but do we know how to change it? Well... You do :P I didn't. Used Mirex's Biturn (omg, that's a good piece of work, THX Mirex for writing it), and just changed the font. Then i started to wonder... maybe i can write a program for quick replacing the font graphics and widths. I have a program to repack the modified file which contains the "width-data", I know the TEX format good enough... wait a minute... I didn't :P

After some debugging work, that's what i found out (i know, that some bytes where know for long, but that's what i have found out about reading TEX files by ff7):

TEX_FILE_HEADER is 0xEC long, and contains of 59 int-s. Some of them listed below (by offset):
0x00 - TEX file "version", if it's not 0x00000001, the game will not load it.
0x04 - zero... always... i think :P
0x2C - zero?
0x3C - RES_X (already known...)
0x40 - RES_Y
0x44 - zero?
0x48 - zero?
0x4C - PALLETTE_ACTIVE (if it's set, then there is a pallete data right after the header, if it says zero, the pallette-data is missing from the file)
0x58 - PALLETE_NUM_OF_ENTRIES (to get pallete data width, multiply by 4)
0x60 - PALLETTE_PTR (Doesn't really matter. It's always zero-ed when loading the header, after reading pallette data here is where the pointer to that data is stored)
0x68 - BYTES_PER_PIXEL for the bitmap data (bitmap data comes in the file after the header and the pallette data)
(here some unknown data)
0xBC - MYSTERIOUS_DATA_ACTIVE (if it's set, then there should be some data after the bitmap part of the file)

0xC0 - MYSTERIOUS_DATA_PTR (same as PALLETTE_PTR, it could be 0 as well...)
0xC4 - It's set after loading the header (always with 0xFF... i think)
0xC8 - Set after loading the header (when debugging it was 0x04, mostly)
0xD4 - BITMAP_PTR (it's set after the memory allocation and reading the bitmap data, so... who cares)
0xD8 - don't know :) (hmm... it's zero-ed like the pointers, but i didn't see it containing any data after loading the pallette... weird)

"Third chapter - Can you tell me HOW you DO IT?"

How the game reads the TEX file?
 - Allocates a memory (on the heap... or maybe not... forgot :P) for a header and reads it into the memory.
 - if 0x00 DWORD says 0x00000001 then keeps loading, otherwise stops reading that file
 - if 0x4C DWORD is set, reads the pallette (4*0x58 DWORD) and stores the data pointer in the 0x60; if the pointer is NULL, ff7 stops reading that tex-file
 - reads the bitmap data (0x3C DWORD * 0x40 DWORD * 0x68, or RES_X*RES_Y*BYTES_PER_PIXEL) and stores the pointer in 0xD4 DWORD; again, if the pointer is NULL, stops reading that file
 - if the mysterious data is present (0xBC DWORD is set) reads the data (0x30 DWORD * 1) and stores it's pointer; if it's NULL... blah

After that, it does some mysterious and not really interesting things...

"Epilogue - Stupid talk..."

Well... that's it for now :P I hope it's gonna help someone (hmm... if you are good enough to decode my post, you ain't gonna need it, 'coz you're a super-human with abnormal abilities). When i get any other data which is somehow connected with ff7, I'll post it (or not... if I got banned before that). Have a nice life :P

Pages: [1]