Author Topic: FF8 Checksum problem - Old title: Changing game time of FF8 PSX  (Read 15573 times)

Goth

  • Guest
Hi, I want to change the game time of FF8 for PSX.
I don't have Visual C++ 2006 but I downloaded Griever's source code and I wrote a program in C++ trying to change the game time.
It doesn't work. Here I post the source code of my program.
Can anyone tell me what it's wrong?
Thank you and a happy new year to all users.

This is my code:
Code: [Select]
#include <cstdlib>
#include <iostream>
#include <fstream>

//Types of data used in this program. I use Dev C++, and so I don't know if BYTE, USHORT, etc. that I defined here
//are the same types of Visual C++ 2006.
typedef char BYTE;
typedef unsigned short int USHORT;
typedef unsigned int UINT;

/////////////////////////////////////////////////////////////////
// Final Fantasy VIII codes

/*
This, untill the main program, is the structure of one FF8 save block
that I've found on Griever's source code.
*/

/*
enum FF8CHARID {
Squall,
Zell,
Irvine,
Quistis,
Rinoa,
Selphie,
Seifer,
Edea,
Laguna,
_zz1,
_zz2,
_blank,
Griever,
MiniMog,
Chicobo,
Angelo,
None = 0xFF
};
*/

#define CHAR_SQUALL        0
#define CHAR_ZELL          1
#define CHAR_IRVINE        2
#define CHAR_QUISTIS       3
#define CHAR_RINOA         4
#define CHAR_SELPHIE       5
#define CHAR_SEIFER        6
#define CHAR_EDEA          7
#define CHAR_LAGUNA        8
#define CHAR_KIROS         9
#define CHAR_WARD          10

#define CHAR_GRIEVER       12
#define CHAR_MINIMOG       13
#define CHAR_CHICOBO       14
#define CHAR_ANGELO        15
#define CHAR_NONE          0xFF


typedef BYTE FF8CHARID;

struct _FF8ITEM {
BYTE type;
char *name;
};

struct _FF8ABILITY {
BYTE type;
BYTE ap;
char *name;
};

struct _FF8MAGIC {
char *name;
};

#define CARD(t,l,r,b) { 0x##t,0x##l,0x##r,0x##b }

#define NONE -1
#define FIRE 0
#define ICE 1
#define THUNDER 2
#define EARTH 3
#define POISON 4
#define WIND 5
#define WATER 6
#define HOLY 7

#define SIMPLE 0
#define BOSS 1
#define GF 2
#define PLAYER 3

struct _FF8CARD {
char *name;
struct _FF8CARDVALUES {
char top;
char left;
char right;
char bottom;
} values;
char element;
char border;
};

struct _FF8CARDLOCATION {
char *name;
};

struct _FF8LOCATION {
char *name;
};

typedef BYTE _FF8INNATEABILITY;

/////////////////////////////////////////////////////////////////
// Final Fantasy VIII save file structures

// Unknown data
struct UNKNOWN {
UNKNOWN () { data = 0xFF; }
BYTE data;
};

// FF8 text identifier
typedef char FF8STR;

// Save file description block
struct FF8DESC {
USHORT checktag; // Tag - must be 0x0FF8
USHORT location; // Current location
UNKNOWN zz0[4];
USHORT saves; // Number of saves
UINT gil; // Gil
UINT seconds; // Game time
BYTE level; // Lead character's level
FF8CHARID party[3]; // [3] Current party
};

// Guardian Force block
struct FF8GF {
FF8STR name[10]; // [10] GF name
UNKNOWN zz1[2];
UINT exp; // GF EXP
UNKNOWN zz2;
BYTE found; // Has GF been found?
USHORT hp; // Current HP
BYTE abilities[16]; // [16] Learned abilities (bLearned[i] = abilities[i/8] & (1 << (i%8)))
BYTE ap[21]; // [21] Ability APs
UNKNOWN zz3[3];
USHORT kills; // Number of enemies killed
USHORT ko; // Number of KOs
BYTE learning; // Ability being learnt
BYTE forgotten[3]; // Abilities forgotten
};

// Magic block
struct FF8MAGIC {
BYTE type;
BYTE amount;
};

// Character block
struct FF8CHAR {
USHORT hp; // Current HP
USHORT basehp; // Base HP
UINT exp; // EXP
FF8CHARID id; // Character id
BYTE weapon; // Current weapon
BYTE str; // Strength
BYTE vit; // Vitality
BYTE mag; // Magic
BYTE spr; // Spr
BYTE spd; // Speed
BYTE luck; // Luck
FF8MAGIC magic[32]; // [32] Magic library (stock)
BYTE ab_command[3]; // [3] Command abilities
UNKNOWN zz;
BYTE ab_char[4]; // [4] Character abilities
USHORT gf; // Junctioned GFs
UNKNOWN zz2[2];
BYTE junction[19]; // [19] Junctions
// 00: HP Junction (Magic Type)
// 01: Str Junction (Magic Type)
// 02: Vit Junction (Magic Type)
// 03: Mag Junction (Magic Type)
// 04: Spr Junction (Magic Type)
// 05: Spd Junction (Magic Type)
// 06: Hit Junction (Magic Type)
// 07: Eva Junction (Magic Type)
// 08: Luck Junction (Magic Type)
// 09: Elem-Atk Junction (Magic Type)
// 10: ST-Atk Junction (Magic Type)
// 11: Elem-Def Junction 1 (Magic Type)
// 12: Elem-Def Junction 2 (Magic Type)
// 13: Elem-Def Junction 3 (Magic Type)
// 14: Elem-Def Junction 4 (Magic Type)
// 15: ST-Def Junction 1 (Magic Type)
// 16: ST-Def Junction 2 (Magic Type)
// 17: ST-Def Junction 3 (Magic Type)
// 18: ST-Def Junction 4 (Magic Type)
UNKNOWN zz3;
USHORT compat[16]; // [16] GF compatibility
USHORT kills; // Number of enemies killed
USHORT ko; // Number of KOs
BYTE stats; // Can view stats?
UNKNOWN zz4;
BYTE status; // Status effects
//   1: ????
//   2: Poison
//   4: Petrify
//   8: Darkness
//  16: Silence
//  32: Berserk
//  64: Zombie
// 128: ????
UNKNOWN zz5;
};

// Item block
struct FF8ITEM {
BYTE type;
BYTE amount;
};

// Card identifier
typedef BYTE FF8CARD; // 0x80: Collected    0x7F: Amount
// Rare cards: Location
struct FF8CONFIG {
BYTE spd_battle; // Battle speed (0=fast,4=slow)
BYTE spd_battlemsg; // Battle message speed (0=fast,4=slow)
BYTE spd_fieldmsg; // Field message speed (0=fast,4=slow)
BYTE soundvolume; // Sound volume (0-100(%))
BYTE options; // Misc. options
//   1: ATB - 1:Wait 0:Active
//   2: ???
//   4: Cursor - 1:Memory 0:Initial
//   8: ???
//  16: ???
//  32: Controller - 1:Customize 0:Normal
//  64: ???
// 128: ???
BYTE scan; //   1: Scan - 1:Always 0:Once
BYTE camera; // Camera movement (0=100%,4=0%)
UNKNOWN zz1;
UNKNOWN buttons[12]; // [12] Button configuration (?)
};

// Chocobo World data
struct FF8CHOCOBO {
UNKNOWN zz[64];
};

// Save file block
struct FF8BLOCK {
UNKNOWN zz1[384];

USHORT checksum1; // Checksum
FF8DESC desc; // Save block description

FF8STR squall[12]; // [12] Squall's name
FF8STR rinoa[12]; // [12] Rinoa's name
FF8STR angelo[8]; // [8] Angelo's name
UNKNOWN zz0[4];
FF8STR chicobo[4]; // [4] Chicobo's name
UNKNOWN zz01[8];
BYTE disc; // Current disc (zero based)
UNKNOWN zz[3];
UINT saves; // Number of times saved (*2?)

FF8GF gf[16]; // [16] GF blocks

FF8CHAR chars[8]; // [8] Character blocks

UNKNOWN zz2[400];

FF8CONFIG config; // Configuration
FF8CHARID party[3]; // [3] Party
UNKNOWN zz22[5];
FF8STR griever[8]; // [8] Griever's name

UNKNOWN zz23[8];
UINT gil; // Gil
UNKNOWN zz24[4];

BYTE limits[6]; // [6] Learned limit breaks
// [0]-[1] Quistis
// [2]-[3] Zell
// [4] Irvine
// [5] Selphie
BYTE combine_compl; // Rinoa's Combine: Angelo Abilities Completed
BYTE combine_known; // Rinoa's Combine: Angelo Abilities Known
BYTE combine_left[8]; // [8] Rinoa's Combine: Points left to learn different abilities
// [0] 'Angelo Rush' (max 10)
// [1] 'Angelo Recover' (max 30)
// [2] 'Angelo Reverse' (max 40)
// [3] 'Angelo Search' (max 60)
// [4] 'Angelo Cannon' (max 80)
// [5] 'Angelo Strike' (max 120)
// [6] 'Invincible Moon' (max 140)
// [7] 'Wishing Star' (max 160)

BYTE b_items[32]; // [32] Order of battle items
FF8ITEM items[198]; // [198] Items

//#############################################################################################
UINT seconds; // Game time (I want to change this)
//#############################################################################################

UNKNOWN zz28[8];
UINT battleswon; // Number of battles won
UNKNOWN zz29[2];
USHORT battlesescaped; // Number of battles escaped
UNKNOWN zz30[60];
BYTE limit_options; // Limit break options (1:Renzokuken Auto, 2:Duel Auto)
BYTE limit_indicator; // Renzokuken indicator (128)
BYTE dreamworld; // Party isolated / Dream world (1)
BYTE information[9]; // [9] Information (bitmask)
// [0]1-8: Location information
// [2]1-8: Location information
// [3]1-4: Location information
// [3]5-8: Term information
// [4]1-8: Term information
// [5]1-6: Term information
// [5]7-8: People information
// [6]1-5: People information
// [6]6-8: Character reports
// [7]1-4: Character reports
// [8]3-3: Term information
// [8]4-6: Report information
UNKNOWN zz31;
BYTE gf_reports[3]; // [3] GF reports

UNKNOWN zz3[3];
BYTE testlevel; // Current written test level
UNKNOWN zz39[4];
FF8CHARID party_field[3]; // [3] Current field party ([0] = leader)
UNKNOWN zz395[7];
USHORT location; // Current location
USHORT location_last; // Last location (?)
UNKNOWN zz4[30];
UINT steps; // Number of steps taken
USHORT payslip; // Payslip steps
UNKNOWN zz5[6];
USHORT seedlevel; // SeeD Level
UNKNOWN zz55[66];

UNKNOWN zz550[2];
// USHORT location_last; // Last location ?
UNKNOWN zz551[186];

BYTE tt_rules[8]; // [8] Region game rules
BYTE tt_traderules[8]; // [8] Region trade rules
BYTE tt_lastrules[2]; // [2] Last game rules remembered ([1] = second to last)
BYTE tt_lastregion[2]; // [2] Last region remembered ([1] = second to last)
UNKNOWN zz555;
BYTE tt_currules; // Current game rule
BYTE tt_curtraderule; // Current trade rules
BYTE tt_cardqueen; // Card Queen's location
BYTE tt_traderating_region; // Region for trade rating
BYTE tt_traderating; // Trade rating

UNKNOWN zz6[1110];
FF8CARD cards[77]; // [77] Cards (bit 8=collected, bit 1-7=amount)
BYTE card_locations[33]; // [33] Card locations
BYTE cards_rare[5]; // [5] Rare cards found (bFound[i] = cardsfound[i/8] & (1 << (i%8)))
UNKNOWN zz7[9];

USHORT test1;
USHORT test2;
FF8CHOCOBO cw; // Chocobo World data
USHORT checksum2; // Checksum (identical to checksum1)
BYTE padding[2782]; // Padding, makes save block 8192 bytes
};

/////////////////////////////////////////////////////////////////
//                      Main Program
/////////////////////////////////////////////////////////////////
/*
This is my code.
The problem is that the game seconds are not right, so the data read from the memory card is not saved correctly
in the FF8BLOCK structure.
And the size of my block is 8196 instead of 8192, and I don't know why.
*/
using namespace std;

int main(int argc, char *argv[])
{char FileName[100];
 USHORT blocco;
 FF8BLOCK ff8;
 fstream FileMem;

 while(1)
 {//START of While

cout<<"Size of my block: "<<sizeof(ff8)<<".\n";
strcpy(FileName,"");
cout << "Name of the memory card:\n";
cin >> FileName;
FileMem.open(FileName,ios::binary | ios::in | ios::out);
if(!FileMem)
 cout<<"Impossible to open the file.\n\n";
else
{

cout << "File loaded.\nInsert number of the block:\n";
cin >> blocco;
blocco-=1; //because I think that the block start from zero
cout <<endl<<endl;
int m_Type = 1; //I have a Memory Card File of 131'072 Byte, so the m_Type is 1 and theOffSet is zero.
int offset;
if(m_Type==1) offset = 0; //this is my case
if(m_Type==2) offset = 0xF40;
if(m_Type==3) offset = 64;

//8192 is 0x2000
//now I do the same things that Griever do to read from the Memory Card:
FileMem.seekg(offset+8192+(8192*blocco), ios::beg);
FileMem.read((char*)&ff8, 8192);

cout<<"Game time: "<<ff8.seconds<<";\n"; //but they are not right
ff8.seconds = 20000; //sample value

//and now I write on file. The writing seems to be correct, but the modify is not correct.
//So the second doesn't change.
FileMem.seekp(offset+8192+(8192*blocco), ios::beg);
FileMem.write((char*)&ff8, 8192);
cout<<"Game time modified.\n\n\n";
FileMem.close();

}

 }//FINE While
 return EXIT_SUCCESS; //end of Windows Application
}
« Last Edit: 2008-06-28 08:08:18 by Goth »

Cyberman

  • *
  • Posts: 1572
    • View Profile
Re: Changing game time of FF8 - PSX [C++]
« Reply #1 on: 2008-01-03 02:29:14 »
Specifically what time are you trying to change (as I remember there were multiple) and what problems or errors did you encounter?

I was playing through the game to figure out all the bit fields in it but being a bit ADD I got distracted, however I have complete source of my plugin for modifying the data all you need is a program that can run the DLL's. I thought I had placed those available publicly but it's been numerous years since then.

So Qhimm, I, or any number of people likely can help you if you are more specific. Help us help you :)

Cyb

Goth

  • Guest
Re: Changing game time of FF8 - PSX [C++]
« Reply #2 on: 2008-01-03 10:39:09 »
What time:
I'm sorry but I think that the time is only one. I mean the game time, to be more precise the numbers that appear in the menu on the bottom-right, just over the guil.
In the source code, I have specified where the seconds that I want to modified are (in the FF8 Save Block structure).

The problem:
I explained the errors adding comments in the source code.
In particular, the seconds read aren't correct. This means that the structure have some errors, I think.
Or maybe I read from the memory card file in a wrong way.
If you build the code, you can see that the seconds shown with "cout" can't be the correct seconds of the game.

If there are any other incomprension or doubts, tell me without problem.
Thank you for the answer.

Cyberman

  • *
  • Posts: 1572
    • View Profile
Re: Changing game time of FF8 - PSX [C++]
« Reply #3 on: 2008-01-03 22:50:11 »
You may have modified a time correctly or not if you don't compute the CRC correctly it is all for naught because it won't load correctly (IE it won't load?)

Also you are incorrect in that there is 1 single time there are TWO seperate time values one is in a structure used with the card information displayed on the PS1 (it's read by the game for a 'quick value' but I don't believe it's used) another time is further into the game save structure and this is the actual time.  The second time is JUST after the items in the FF8 data.

As I said which do you want?

Cyb

Zande

  • *
  • Posts: 55
  • 友情は武器よりも強し
    • View Profile
Re: Changing game time of FF8 - PSX [C++]
« Reply #4 on: 2008-01-03 23:52:12 »
Quote
/*
This is my code.
The problem is that the game seconds are not right, so the data read from the memory card is not saved correctly
in the FF8BLOCK structure.
And the size of my block is 8196 instead of 8192, and I don't know why.
*/
The incorrect size sounds like an aligment problem, set a 1-byte boundary for struct alignment in your project, or use pack pragma, ie:

Code: [Select]
#pragma pack(push, 1)
struct NameofStruct {
 // Struct members goes here...
}
#pragma pack(pop)

Goth

  • Guest
Re: Changing game time of FF8 - PSX [C++]
« Reply #5 on: 2008-01-04 14:29:43 »
Zande, thank you very much, the problem was this. Now the size is correct, and the seconds read are correct.

Now, my last problem.

I need to calculate checksum, but the Griever's code doesn't work, I think due to the difference between Visual C++ and C++.

The code is this:
Code: [Select]
void CalculateChecksum(FF8BLOCK &ff8)
{   WORD checksum = 0;
void *dataptr = (void*)&ff8.gf;

    asm{push dataptr
push 00001350h
push 00000000h
}

__asm {
sub esp, 00000200h
mov ecx, 00000080h
xor eax, eax
push esi
push edi
lea edi, dword ptr [esp+08h]
xor esi, esi
repz stosd
mov eax, 0000FFFFh
lea edi, dword ptr [esp+08h]
label2:
mov ecx, esi
mov edx, 00000008h
shl ecx, 08h

label3:
test ch, 80h
je label4
add ecx, ecx
xor ecx, 00001021h
jmp label5
label4:
shl ecx, 1
label5:
dec edx
mov word ptr [edi], cx
jne label3
inc esi
add edi, 00000002h
cmp esi, 000000FFh
jb label2
mov edi, dword ptr [esp+0000020Ch]
test edi, edi
jle label7
mov esi, dword ptr [esp+00000210h]
label6:
xor ecx, ecx
xor edx, edx
mov dl, byte ptr [esi]
mov cl, ah
and ecx, 000000FFh
xor ecx, edx
xor edx, edx
mov dh, al
mov ax, word ptr [esp+2*ecx+08h]
xor ax, dx
inc esi
dec edi
jne label6
label7:
pop edi
pop esi
not eax
add esp, 00000200h

}

__asm {
add esp, 0000000Ch
mov checksum, ax
}


ff8->checksum1 = ff8->checksum2 = checksum;
}

So, WORD doesn't exist in c++, so I have replaced it with USHORT (unsigned short int) that I defined before, but is not the same. I don't know what to do.
__asm doesn't exist, the command is simply "asm".
But I have the following errors:

In the line:
Code: [Select]
asm{I got this error: expected `(' before '{' token

°__°
To insert assembler instruction in a C or C++ program, the code is:
asm{
//assembler instructions
}
So, what's wrong with my code?

P.S. = I use DevC++.
« Last Edit: 2008-01-04 18:17:26 by Goth »

Cyberman

  • *
  • Posts: 1572
    • View Profile
Re: Changing game time of FF8 - PSX [C++]
« Reply #6 on: 2008-01-06 14:38:27 »
Dev C++ uses GCC not VC++
Assembly is not done the same in GCC as it is in VC++, I suggest you look up how to use assembly in GCC, this is a good place to start, and you may need to look here as well.

Cyb

Goth

  • Guest
Re: Changing game time of FF8 - PSX [C++]
« Reply #7 on: 2008-01-06 14:46:35 »
***Sorry for this message, admin can delete it.
Read the following message.
« Last Edit: 2008-01-06 14:49:55 by Goth »

Goth

  • Guest
Re: Changing game time of FF8 - PSX [C++]
« Reply #8 on: 2008-01-06 14:47:40 »
Dev C++ uses GCC not VC++
Yes, I know, but I thought that asm was the same.

I made this change:
 __asm("istruction");
instead of using asm{list of instructions};

but I got a list of many assembler errors.
I have to modify the assembler code...  :-o
Nah, too difficult for me.

If someone can do it.. :)
« Last Edit: 2008-01-06 14:58:08 by Goth »

Cyberman

  • *
  • Posts: 1572
    • View Profile
Re: Changing game time of FF8 - PSX [C++]
« Reply #9 on: 2008-01-06 18:23:27 »
Read the first reference I gave you. :)
That will definately get you started.

Cyb

Goth

  • Guest
Re: Changing game time of FF8 - PSX [C++]
« Reply #10 on: 2008-01-06 18:46:38 »
OK, thanks.

Goth

  • Guest
Re: Changing game time of FF8 - PSX [C++]
« Reply #11 on: 2008-06-26 21:32:11 »
This is an old topic but I never solved my problem.
Anyway, I found a solution.
I've put this line on the compiler:
-masm=intel
so it works following Intel rules.

So my code now is this:
Code: [Select]
void CalcoloChecksum(FF8BLOCK &ff8)
{USHORT checksum = 0;
 void *dataptr = (void*)&ff8.gf;

asm("push dataptr\n"
    "push 00001350\n"
"push 00000000\n");

asm("sub esp, 00000200\n"
"mov ecx, 0x00000080\n"
"xor eax, eax\n"
"push esi\n"
"push edi\n"
"lea edi, dword ptr [esp+0x08]\n"
"xor esi, esi\n"
"repz stosd\n"
"mov eax, 0x0000FFFF\n"
"lea edi, dword ptr [esp+0x08]\n");

label2:
asm("mov ecx, esi\n"
"mov edx, 0x00000008\n"
"shl ecx, 0x08\n");

label3:
asm("test ch, 80\n"
"je label4\n"
"add ecx, ecx\n"
"xor ecx, 00001021\n"
"jmp label5\n");

label4:
asm("shl ecx, 1\n");

label5:
asm("dec edx\n"
"mov word ptr [edi], cx\n"
"jne label3\n"
"inc esi\n"
"add edi, 00000002\n"
"cmp esi, 0x000000FF\n"
"jb label2\n"
"mov edi, dword ptr [esp+0000020Ch]\n"
"test edi, edi\n"
"jle label7\n"
"mov esi, dword ptr [esp+00000210]\n");

label6:
asm("xor ecx, ecx\n"
"xor edx, edx\n"
"mov dl, byte ptr [esi]\n"
"mov cl, ah\n"
"and ecx, 0x000000FF\n"
"xor ecx, edx\n"
"xor edx, edx\n"
"mov dh, al\n"
"mov ax, word ptr [esp+2*ecx+0x08]\n"
"xor ax, dx\n"
"inc esi\n"
"dec edi\n"
"jne label6\n");

label7:
asm("pop edi\n"
"pop esi\n"
"not eax\n"
"add esp, 00000200\n");

asm("add esp, 0000000Ch\n"
"mov checksum, ax\n");

 ff8.checksum1 = ff8.checksum2 = checksum;
}

But I got the followings errors:
Assembler messages:
  junk `Ch' after expression
  junk `Ch' after expression
Path_of_the_project\Makefile.win [Build Error]  [main.o] Error 1

Can anyone help me?
I don't know what's wrong.
« Last Edit: 2008-06-26 21:42:36 by Goth »

*:.Griever.:*

  • *
  • Posts: 410
  • Formerly Tidus_Lionheart
    • View Profile
Re: Changing game time of FF8 - PSX [C++]
« Reply #12 on: 2008-06-26 21:34:49 »
Just out of curiosity, I have to ask, why do you want to go to so much trouble just to change your game time?
Unless your truly terrible, and have a really lousy time, I can't really see a reason to go through so much for such an insignificant thing.

Goth

  • Guest
Re: Changing game time of FF8 - PSX [C++]
« Reply #13 on: 2008-06-26 21:52:08 »
Eh, eh, a lot of people asked me this.
Do you know that when your timer reach 99:59 it turns into red and restart from 00:00? Well, I simply wanted to know what it does then. So, modifying the save, I have managed to see that when you reach 99 hours and 59 minutes red, the colour changes to blue, then to yellow, green, and purple. At 99:59 purple the timer stops. This corresponds to 600 hours of playing.
I simply wanted to know this, I was curious, I wanted to know all of FF8.

Now I've reached my goal, but I want to modify other things. To do this, I cannot satisfy myself seeing the blocks like I've done to knowing the game time behaviour, but I have to do CRC control.
So, now I need your help.

Cyberman

  • *
  • Posts: 1572
    • View Profile
You solved or didn't solve the problem?

I'm confused. I have code that generates the CRC however I probably should reduce it to a standard CRC polynomial and SEED format to perform the calculation (in a normal manner).

Things you do when you are ... young  :roll:

I'll have to dig it up.  I haven't messed with FF8 data in ... 2 years :D

Cyb

Goth

  • Guest
You solved or didn't solve the problem?
I solved an old problem, but now, as you can see from this post: http://forums.qhimm.com/index.php?topic=7268.msg93638#msg93638
I have a last problem (the CRC).
Can you help me?
« Last Edit: 2008-06-28 08:07:31 by Goth »

Cyberman

  • *
  • Posts: 1572
    • View Profile
It's possible but do you understand how the CRC function works even?

I think that you need to study it instead of someone else completely doing it for you.

Look up CRC calculation on the net first. There are some general routines available on the net for it.

The most common way to do the CRC is to have a table to look up the values and generate the CRC based on the table data.

The table is generated from each possible symbol to find the next CRC symbol.

The method used in Qhimm's griever code is similar to this, except it calculates the high and low byte tables together (ugh) each time the CRC routine is called and uses that table to compute the CRC of the data in the FF8 save. This makes the code a bit more cryptic to look at because it requires a lot of fancy byte swapping at the end.

The SEED value for the CRC is 0xFFFF and the POLYNOMIAL is 0x1021.  The save data block length is 0x1350 or 4944 bytes.

Everything in bold letters is a hint :D

Erstwhile I rewrote my Grieve DLL to use a table CRC instead thus it's a bit faster but mostly easier to understand.

Cyb

Goth

  • Guest
I wasn't interested to understand the CRC simply because I'm studying and programming other things and I only wanted to create a personal Griever quickly, with the purpose of changing stuffs that Qhimm's Griever doesn't.
Moreover, I have only two errors on my code now, so I wanted only a correction.

In any case thanks for the hints and the links.

Cyberman

  • *
  • Posts: 1572
    • View Profile
What were your errors then?
The assembly code reads a bit strange but it does work by the way.

And if you have questions apart from Qhimm's reference material <TM> ask me I went further than he did with the save data.
Cyb

Goth

  • Guest
What were your errors then?
The assembly code reads a bit strange but it does work by the way.

I have a feeling that you don't read my posts entirely... :D
I show again this link: http://forums.qhimm.com/index.php?topic=7268.msg93638#msg93638
Or rather, I'll quote to you the part of the post that shows the errors:
Quote
But I got the followings errors:
Assembler messages:
  junk `Ch' after expression
  junk `Ch' after expression
Path_of_the_project\Makefile.win [Build Error]  [main.o] Error 1

I hope that the code will work correcting these errors.

Cyberman

  • *
  • Posts: 1572
    • View Profile
I have a feeling that you don't read my posts entirely... :D
I show again this link: http://forums.qhimm.com/index.php?topic=7268.msg93638#msg93638
Or rather, I'll quote to you the part of the post that shows the errors:
Quote
But I got the followings errors:
Assembler messages:
  junk `Ch' after expression
  junk `Ch' after expression
Path_of_the_project\Makefile.win [Build Error]  [main.o] Error 1

I hope that the code will work correcting these errors.

Those errors are missing context.  ch after what expression?
The only CH value I can see is test ch,80h
it might be saying "test" is a valid opcode but ch may not be the proper register name for that particular assembler.
Do you have the assembler manual?
Did you look up the error in it?
What compiler are you using, GCC or an older version of VC++?

Cyb

Goth

  • Guest
Quote
Those errors are missing context.  ch after what expression?
I'm sorry but DevC++ doesn't specify the numeber of the line when it checks assembler code.
In any case, as you said, the line/s are certainly "test ch,80h".

Quote
What compiler are you using, GCC or an older version of VC++?
As I already said in some post before, I use DevC++, so GCC.
Certainly I don't use VC++, or else I could use the same CRC' assembly code as Qhimm's one.
« Last Edit: 2008-06-29 21:48:25 by Goth »

Cyberman

  • *
  • Posts: 1572
    • View Profile
Hmmm documentation time
Quote
-masm=dialect
    Output asm instructions using selected dialect. Supported choices are `intel' or `att' (the default one). Darwin does not support `intel'.
Darwin is an OS (not of use here).

http://sourceware.org/binutils/docs-2.18/as/i386_002dSyntax.html#i386_002dSyntax

The big difference is numbering methodology, register syntax and source destination ordering.
 Now comes the fun part is Ch a register or a hexadecimal value to the GNU assembler in Intel format?
I suppose it differentiates based on weather there is a leading 0 or not (IE 0Ch is 0x0c). looks problematic if you ask me.
 
HOWEVER I think THIS is the problem
Quote
asm("test ch, 80\n"
   "je label4\n"
test ch,80 is NOT valid Intel syntax and should read
Quote
asm("test ch, 80h\n"
   "je label4\n"
hexadecimal numbers must end in h for Intel syntax.
see if that is the problem

Cyb

dziugo

  • *
  • Posts: 1470
    • View Profile
    • A new copy of FF7 thanks to Salk. Pack (zip/rar/etc) your saved game before sending it to me.
You can try with "test ecx, 8000h", as 80 would still be a valid constant.

Goth

  • Guest
Quote
hexadecimal numbers must end in h for Intel syntax.
If I put the H, I got an error. In fact, as you can see from the code, I never put it.
So the problem is not this. Instead, I managed to understand that the lines to correct is not these, but these:
Code: [Select]
"mov edi, dword ptr [esp+0000020Ch]\n"
"add esp, 0000000Ch\n"
The problem is that c is an hexadecimal number and so I've put the "0x" before. Now the code is this:
Code: [Select]
void CalcoloChecksum(FF8BLOCK &ff8)
{USHORT checksum = 0;
 void *dataptr = (void*)&ff8.gf;

asm("push dataptr\n"
    "push 00001350\n"
"push 00000000\n");

asm("sub esp, 00000200\n"
"mov ecx, 0x00000080\n"
"xor eax, eax\n"
"push esi\n"
"push edi\n"
"lea edi, dword ptr [esp+0x08]\n"
"xor esi, esi\n"
"repz stosd\n"
"mov eax, 0x0000FFFF\n"
"lea edi, dword ptr [esp+0x08]\n");

label2:
asm("mov ecx, esi\n"
"mov edx, 0x00000008\n"
"shl ecx, 0x08\n");

label3:
asm("test ch, 80\n"
    "je label4\n"
"add ecx, ecx\n"
"xor ecx, 00001021\n"
"jmp label5\n");

label4:
asm("shl ecx, 1\n");

label5:
asm("dec edx\n"
"mov word ptr [edi], cx\n"
"jne label3\n"
"inc esi\n"
"add edi, 00000002\n"
"cmp esi, 0x000000FF\n"
"jb label2\n"
"mov edi, dword ptr [esp+0x0000020C]\n"
"test edi, edi\n"
"jle label7\n"
"mov esi, dword ptr [esp+00000210]\n");

label6:
asm("xor ecx, ecx\n"
"xor edx, edx\n"
"mov dl, byte ptr [esi]\n"
"mov cl, ah\n"
"and ecx, 0x000000FF\n"
"xor ecx, edx\n"
"xor edx, edx\n"
"mov dh, al\n"
"mov ax, word ptr [esp+2*ecx+0x08]\n"
"xor ax, dx\n"
"inc esi\n"
"dec edi\n"
"jne label6\n");

label7:
asm("pop edi\n"
"pop esi\n"
"not eax\n"
"add esp, 00000200\n");

asm("add esp, 0x0000000C\n"
"mov checksum, ax\n");

 ff8.checksum1 = ff8.checksum2 = checksum;
}
The errors are vanished but now I got other errors:
[Linker error] undefined reference to `dataptr'
  [Linker error] undefined reference to `checksum'
  [Linker error] undefined reference to `label4'
  [Linker error] undefined reference to `label5'
  [Linker error] undefined reference to `label3'
  [Linker error] undefined reference to `label2'
  [Linker error] undefined reference to `label7'
  [Linker error] undefined reference to `label6'
  ld returned 1 exit status
 Path_of_the_project\Makefile.win [Build Error]  [program.exe] Error 1
« Last Edit: 2008-07-02 10:41:53 by Goth »