Project GoalTo get Final Fantasy 7 battles playing at 60 frames per second.
Current Completion ProgressModel animations updated...
0% (Kimera needs a bit of tweaking first)
Limit Break animations updated...
0% (Need to find where these are stored. Potentially within .s files)
Camera animations updated...
80% (still may be a few instances of the camera being handled elsewhere)
Texture animations updated...
10% (Aali seems to have decompiled the .s data, but that information has yet to be harnessed)
Tifa, Cait's limit slots, battle square slots updated...
25% (DLPB will probably knock this out shortly)
Important InformationIn order to get the game running battles at 60fps, the following values need to be hex edited in the ff7.exe:
0x3BF506 from 2E to 5E, 0x3BF50E from 2C to 5C, and 0x3BF516 from 2E to 5E..S Files DumpI wrote these tools to help me read and edit .s files, maybe you can put them to good use. Simply adding more frames to the animations just caused it to cut out early when I tried it but maybe you can figure that out.
sptdump.c: .s file -> text format
#include <stdio.h>
#include "spt.h"
int main(int argc, char *argv[])
{
FILE *f;
struct spt_header header;
int i;
int j;
if(argc < 2)
{
printf("usage: sptdump <file>\n");
exit(1);
}
f = fopen(argv[1], "rb");
fread(&header, sizeof(header), 1, f);
printf("File type: %p\n", header.file_type);
printf("Version: %p\n", header.version);
printf("Number of SPT entries: %i\n", header.num_spt_entries);
printf("\n");
for(i = 0; i < header.num_spt_entries; i++)
{
struct spt_entry entry;
fread(&entry, sizeof(entry), 1, f);
printf(" SPT Entry %i: %p, %i\n", i, entry.field_0, entry.num_spt_struc_183);
for(j = 0; j < entry.num_spt_struc_183; j++)
{
struct spt_struc_183 struc_183;
fread(&struc_183, sizeof(struc_183), 1, f);
printf(" %i: %p %5i %5i %5i %5i %5i %5i 0x%04x %3u %3u %3u %3u\n", j, struc_183.flags, struc_183.x, struc_183.y, struc_183.field_8, struc_183.field_A, struc_183.texture_page, (struc_183.field_E & 0x3F) << 4, struc_183.field_E >> 6, struc_183.w1, struc_183.w2, struc_183.h1, struc_183.h2);
}
}
return 0;
}
sptbuilder.c: text format -> .s file
#include <stdio.h>
#include <string.h>
#include "spt.h"
const char file_type[] = "File type: ";
const char version[] = "Version: ";
const char num_spt_entries[] = "Number of SPT entries: ";
int main(int argc, char *argv[])
{
FILE *f;
FILE *of;
struct spt_header header;
int i;
int j;
char line[4096];
if(argc < 3)
{
printf("usage: sptbuilder <infile> <outfile>\n");
exit(1);
}
f = fopen(argv[1], "r");
of = fopen(argv[2], "wb");
if(!f)
{
perror("input file");
exit(1);
}
if(!of)
{
perror("output file");
exit(1);
}
while(1)
{
fgets(line, sizeof(line), f);
printf("%s", line);
if(!strncmp(line, file_type, sizeof(file_type) - 1)) sscanf(strstr(&line[sizeof(file_type)], "x") + 1, "%hhx", &header.file_type);
else if(!strncmp(line, version, sizeof(version) - 1)) sscanf(strstr(&line[sizeof(version)], "x") + 1, "%hhx", &header.version);
else if(!strncmp(line, num_spt_entries, sizeof(num_spt_entries) - 1)) sscanf(&line[sizeof(num_spt_entries) - 1], "%i", &header.num_spt_entries);
else break;
}
printf("Done parsing headers\n");
header.field_2 = 0;
fwrite(&header, sizeof(header), 1, of);
for(i = 0; i < header.num_spt_entries; i++)
{
struct spt_entry entry;
printf("Parsing SPT entry %i\n", i);
fgets(line, sizeof(line), f);
printf("%s", line);
strtok(line, ":,");
sscanf(strstr(strtok(0, ":,"), "x") + 1, "%hx", &entry.field_0);
sscanf(strtok(0, ":,"), "%hi", &entry.num_spt_struc_183);
fwrite(&entry, sizeof(entry), 1, of);
for(j = 0; j < entry.num_spt_struc_183; j++)
{
struct spt_struc_183 struc_183;
int tmp1;
int tmp2;
printf("%i\n", j);
fgets(line, sizeof(line), f);
printf("%s\n", strtok(line, ":"));
//printf("%s\n", strtok(0, ":"));
sscanf(strstr(strtok(0, ":"), "x") + 1, "%x %5hi %5hi %5hi %5hi %5hi %5i %p %3hhi %3hhi %3hhi %3hhi", &struc_183.flags, &struc_183.x, &struc_183.y, &struc_183.field_8, &struc_183.field_A, &struc_183.texture_page, &tmp1, &tmp2, &struc_183.w1, &struc_183.w2, &struc_183.h1, &struc_183.h2);
struc_183.field_E = tmp2 << 6;
struc_183.field_E |= tmp1 >> 4;
fwrite(&struc_183, sizeof(struc_183), 1, of);
}
}
fclose(of);
return 0;
}
spt.h: data structures used in both programs
#ifndef _SPT_H_
#define _SPT_H_
struct spt_header
{
unsigned char file_type;
unsigned char version;
unsigned short field_2;
unsigned int num_spt_entries;
} __attribute__((__packed__));
struct spt_entry
{
unsigned short field_0;
unsigned short num_spt_struc_183;
} __attribute__((__packed__));
struct spt_struc_183
{
unsigned int flags;
short x;
short y;
short field_8;
short field_A;
unsigned short texture_page;
short field_E;
unsigned char w1;
unsigned char w2;
unsigned char h1;
unsigned char h2;
} __attribute__((__packed__));
#endif
Proof of Concept Videoshttp://www.youtube.com/watch?v=D6ziBsBNSfIhttp://www.youtube.com/watch?v=rx3DHs4iMzA I found a few values in the exe which make the items on the menu smoother. So far I have only found the side menu values but with Kranmer I am guessing the rest (like Gil Box) can also be found. Have a go yourself:
FF7.exe
Edit address 002C8EA0 to 50
Edit address 002C8EAB to 12
Then open the menu and pay attention to the side menu (other values need altering to make it look perfect but this should give you a good idea)