View previous topic :: View next topic |
Author |
Message |
Baaleos
Joined: 02 Sep 2007 Posts: 830
|
Posted: Wed Jun 23, 2010 14:07 Post subject: Blood Omen 2 - Hidden Developer Menu?? |
|
|
Yes, I realise this is a nwn/nwnx forum, but I promiss, this is sorta on point.
Alot of the guys here at nwnx know more about programming than other websites (subtle compliment)
Anyway..
Im an avid fan of the Legacy of Kain series, and found that all of the legacy of kain series games have a secret developer debug menu, except Blood Omen 2.
No one has released a Developer Debug Menu accessing trainer/program as of yet.
I was hunting around the Blood Omen executable in IDA, and found some strings which suggest there is infact a debug menu hidden in there after all.
Code: |
aShowMemoryStat db 'show memory stats',0
.data:008CEB0E align 10h
.data:008CEB10 aResetCreatures db 'reset creatures',0
.data:008CEB20 aUseOriginalKai db 'use original kain (requires level reload)',0
.data:008CEB4A align 4
.data:008CEB4C aShowDarkGiftNa db 'show dark gift name in menu',0
.data:008CEB68 aAllowAttackThr db 'allow attack thru walls',0
.data:008CEB80 aUseRightStickI db 'use right stick in menu (requires restart)',0
.data:008CEBAB align 4
.data:008CEBAC aTrackRangedCom db 'track ranged combat target',0
.data:008CEBC7 align 4
.data:008CEBC8 aShowSuperJumpA db 'show super jump areas',0
.data:008CEBDE align 10h
.data:008CEBE0 aEnableSaveRest db 'enable save/restore game UI',0
.data:008CEBFC aDonTUseDeathDu db 'don',27h,'t use death dust effect',0
.data:008CEC18 aInvertSelectUp db 'invert select up down',0
.data:008CEC2E align 10h
.data:008CEC30 aSoundPaths db 'sound paths',0
.data:008CEC3C aEnemiesAlwaysB db 'enemies always block',0
.data:008CEC51 align 4
.data:008CEC54 aDisableEnemies db 'disable enemies',0
.data:008CEC64 aShowEnemyClipC db 'show enemy clip changes',0
.data:008CEC7C aPosition_0 db 'position',0
.data:008CEC85 align 4
.data:008CEC88 aGotoposLowleve db 'gotopos lowlevel',0
.data:008CEC99 align 4
.data:008CEC9C aPolywalk db 'polywalk',0
.data:008CECA5 align 4
.data:008CECA8 aAnimations_0 db 'animations',0
.data:008CECB3 align 4
.data:008CECB4 aBehaviors db 'behaviors',0
.data:008CECBE align 10h
.data:008CECC0 aNames db 'names',0
.data:008CECC6 align 4
.data:008CECC8 aRangeCombatStu db 'range combat stuff',0
.data:008CECDB align 4
.data:008CECDC aFleeStuff db 'flee stuff',0
.data:008CECE7 align 4
.data:008CECE8 aChaseStuff db 'chase stuff',0
.data:008CECF4 aHearingRange db 'hearing range',0
.data:008CED02 align 4
.data:008CED04 aSightViewVolum db 'sight view volume',0
.data:008CED16 align 4
.data:008CED18 aCombatStuff db 'COMBAT stuff',0
.data:008CED25 align 4
.data:008CED28 aCombatMessages db 'COMBAT messages',0
.data:008CED38 aTimings db 'timings',0
.data:008CED40 aShowKainSBlock db 'show Kain',27h,'s blocking preference',0
.data:008CED60 aShowCheckpoint db 'show checkpoint info',0
.data:008CED75 align 4
.data:008CED78 aIgnoreWaterFor db 'ignore water for Kain',0
.data:008CED8E align 10h
.data:008CED90 aDarkGiftsAlway db 'Dark gifts always available',0
.data:008CEDAC aShowKainClipCh db 'show kain clip changes',0
.data:008CEDC3 align 4
.data:008CEDC4 aDisplayLadderA db 'display ladder and edge grab probes',0
.data:008CEDE8 aShowElapsedPla db 'show elapsed player time',0
.data:008CEE01 align 4
.data:008CEE04 aShowKainSCharg db 'show Kain',27h,'s charge move points',0
.data:008CEE23 align 4
.data:008CEE24 aHideKainDuring db 'hide Kain during dark gift targeting',0
.data:008CEE49 align 4
.data:008CEE4C aKainSInvulnera db 'kain',27h,'s invulnerable',0
.data:008CEE60 aDonTUseDebugHe db 'don',27h,'t use debug health',0
.data:008CEE77 align 4
.data:008CEE78 aShowKainSHitPo db 'show Kain',27h,'s hit points',0
.data:008CEE8F align 10h
.data:008CEE90 aShowKainSLore db 'show Kain',27h,'s lore',0
.data:008CEEA1 align 4
.data:008CEEA4 aShowKainSSelec db 'show Kain',27h,'s select aiming',0
.data:008CEEBE align 10h
.data:008CEEC0 aShowKainSFacin db 'show Kain',27h,'s facing',0
.data:008CEED3 align 4
.data:008CEED4 aShowKainSAnima db 'show Kain',27h,'s animations',0
.data:008CEEEB align 4
.data:008CEEEC aShowKainSPlatf db 'show Kain',27h,'s platform info',0
.data:008CEF06 align 4
.data:008CEF08 aShowKainSVeloc db 'show Kain',27h,'s velocity',0
.data:008CEF1D align 10h
.data:008CEF20 aDebugKainSGrab db 'debug Kain',27h,'s grab attacks',0
.data:008CEF3A align 4
.data:008CEF3C aShowKainSPosit db 'show Kain',27h,'s position',0
.data:008CEF51 align 4
.data:008CEF54 aShowKainSBehav db 'show Kain',27h,'s behaviors',0
.data:008CEF6A align 4
.data:008CEF6C aDrawKainSEnemy db 'draw Kain',27h,'s enemy SENSE stuff',0
.data:008CEF8A align 4
.data:008CEF8C aShowWeaponAnim db 'show weapon animations',0
.data:008CEFA3 align 4
.data:008CEFA4 aPrintWeaponSta db 'print weapon states',0
.data:008CEFB8 aDellSSecretFla db 'Dell',27h,'s secret flag',0
.data:008CEFCB align 4
.data:008CEFCC aShowDetectorDe db 'show detector debug stuff',0
.data:008CEFE6 align 4
|
These strings are highly reminiscent of the menu headings and options which are present in the other legacy of kain debug menus.
With the absence of any symbol list for BO2, all the functions are 'helpfully' named sub_blahblah.
Anyone wana have a crack at making 'something' that can access the developer debug menu for this game?
I've only just started getting used to hooking events in nwnx, but im a long way away from creating my own injectable dll from scratch.
If this could be accomplished by simply 'poking' memory addresses, that would be better. |
|
Back to top |
|
|
Baaleos
Joined: 02 Sep 2007 Posts: 830
|
Posted: Thu Jun 24, 2010 1:38 Post subject: Not often u get the source code with a game |
|
|
Its not often that the developers of a game, leave the source code packaged with it.
I've found a bunch of unencrypted source code in some of the data files in the data folder of blood omen 2.
It details the structure of the game classes etc.
for instance, Kain, the protagonists, and the gameplay, seems to be linked to a class/struct called
Code: |
struct kainTune {
int32 fOldTuneData; // desc=DO_NOT_CHANGE default=0
KainAccessoryParams accessoryParams;
KainAirParams airParams;
KainAttackParams attackParams;
AwarenessParams awarenessParams;
KainBlockParams blockParams;
KainBloodSuckParams bloodSuckParams;
KainClothParams clothParams;
KainCollisionParams collisionParams;
KainDarkGiftParams darkGiftParams;
KainDeathParams deathParams;
KainDebugControls debugParams;
KainEdgeGrabParams edgeGrabParams;
KainFallParams fallParams;
KainFallToDeathParams fallToDeathParams;
KainFireParams fireParams;
KainHeadControls headParams;
KainHealthParams healthParams;
KainHitReactControls hitReactParams;
KainInteractParams interactParams;
KainJumpParams jumpParams;
KainLadderParams ladderParams;
CreatureLightingTune lightingParams;
KainMoveParams moveParams;
OtherKainData otherParams;
KainRageParams rageParams;
KainSelectCreatureParams selectCreatureParams;
CreatureShadowTune shadowParams;
KainSuperJumpAttackParams superJumpAttackParams;
KainTriggerParams triggerParams;
KainWallHugParams wallhugParams;
KainWaterParams waterParams;
TriggerNAlignTune *alignArray;
int32 numAligns; // sizeof=alignArray (must be int32!!!)
char* cameraEType; // resourcetype=etype desc=etype_of_kains_camera
};
|
Strangely, enough, all of the things I wana change or edit, are located in the
KainHealthParams struct - it details the 'dark gifts' that kain starts with.
eg - the comments in this struct specify that.
Code: |
// This is the template for the camera params
struct KainDebugHealth
{
char * name; // desc=The_name_of_the_level.
int32 loreLevel; // desc=What_lore_level_Kain_starts_at default=1
int32 charmPossessed; // desc=Does_Kain_start_with_charm default=0
int32 furyPossessed; // desc=Does_Kain_start_with_fury default=1
int32 rupturePossessed; // desc=Does_Kain_start_with_rupture default=0
int32 speedPossessed; // desc=Does_Kain_start_with_speed default=0
int32 stealthPossessed; // desc=Does_Kain_start_with_stealth default=1
int32 superJumpPossessed; // desc=Does_Kain_start_with_superJump default=0
int32 telekinesisPossessed; // desc=Does_Kain_start_with_telekinesis default=0
};
struct KainHealthParams
{
float healthIncreaseRate; // desc=Health_and_max_health_bar_grow_rates_after_suck_in_or_lore_level_upgrade default=50
float loreIncreaseRate; // desc=How_fast_lore_accumulated_by_particles_actually_gets_added_per_second default=1
float thirstDrainRate; // desc=How_many_hit_points_we_lose_per_second_due_to_thirst default=0.1
float thirstMinPercent; // desc=What_is_the_minimum_percentage_of_health_the_thirst_can_drain_us_to default=10.0
float thirstDrainTime; // desc=Number_of_seconds_between_thirst_drains default=30.0
float thirstDrainAmount; // desc=Number_of_hit_points_that_get_drained_per_thirst default=10.0
KainLoreLevels * lorePerLevelArray;
int32 numLoreLevels; // sizeof=lorePerLevelArray (must be int32!!!)
KainDebugHealth defaultHealth; // desc=default_health_and_gifts_for_non-game_levels
KainDebugHealth * debugHealth;
int32 numDebugHealths; // sizeof=debugHealth (must be int32!!!)
};
|
Structs within Structs within Structs.
So, question.
How would one locate any of this via IDA or something similar.
I have absolutely no symbol database and no idea how to track down a struct, since it doesnt actually execute, it just gets lots of xrefs to it from other things.... potentially thousands of funcs may call it.
Does IDA allow the user to search by function declarations?
eg Im looking for a function/struct which takes 8 int32's and 1 char for its struct contents?
Can IDA help me out here by locating functions which meet this criteria? |
|
Back to top |
|
|
peachykeen
Joined: 13 Feb 2010 Posts: 15 Location: MD, US
|
Posted: Thu Jun 24, 2010 2:14 Post subject: |
|
|
You can, sometimes (depending on the functions) find out a little bit about the declaration. The first step would be to load the whole thing up in IDA and let it decompile. Save the database. Now start the game in the debugger.
Next, I'd actually grab a copy of Cheat Engine and hook it up, hopefully both debugger work together. Get one of the values you're interested in to a known value, scan for that, change the value, rescan, etc. Pick it out that way. That will provide you with a memory offset.
Now go to IDA's window and find the memory offset, add a breakpoint for when it's modified. Wait till the breakpoint triggers, then follow the call stack and you'll know some of the functions. |
|
Back to top |
|
|
Baaleos
Joined: 02 Sep 2007 Posts: 830
|
Posted: Thu Jun 24, 2010 3:03 Post subject: Unfortunately, not that easy |
|
|
My first attempt was with cheat engine (btw, only one debugger can be active on the exe at a time... unfortunately, cause cheat engine has a 'find out what accesses this' function, which updates in real time as the event plays out.
My first attempt was along the lines of
select dark gift mist.
scan for unknown value
change to fury
scan for changed value
repeated this for a bit,
In the end I managed to find about 12 memory locations which were 4 bytes long each, which updated when I changed dark gift.
Im guessing these values which changed were to do with the gui, and/or back end settings such as targetting reticles for the dark gifts.
Because when I modified or nop'd them or the functions that accessed them, it resulted in
1. Kain turning pink - the pansy!!
2. Kain Couldnt jump higher than 1 mm of the ground
3. Targetting reticle for jump dark gift moved diagonally instead of where u tell it to go.
4. Kain walks in a similar manner to the targetting reticle.
Also, freezing the values which were associated with the dark gifts did not prevent me from changing dark gift either.
The values I managed to determine, or at least observed being present at the time of each dark gift was as seen below.
C2 00 00 48 - MIST
C2 00 00 2A - IMMOLATE
C2 00 00 16 - JUMP
C2 00 00 02 - BERSERK
C2 00 00 DC - CHARM
C2 00 00 B4 - FURY
C2 00 00 8C - TELEKINESIS
In regards to your suggestion, the only method I can really check the difference between having dark gift, and not having dark gift, is to go back and forth between save games or instances where I have no dark gift, and then when I do have the dark gift.
The variations I can achieve with this is limited, and it entails alot more work.
But I will give it a quick test, to see if it proves productive. |
|
Back to top |
|
|
Baaleos
Joined: 02 Sep 2007 Posts: 830
|
Posted: Thu Jun 24, 2010 3:31 Post subject: grrr |
|
|
I've been doing as I said.
Loading a save game from chapter 1 - with only 2 default dark gifts.
and then loading the bonus mode one, where it gives u all the dark gifts (the bad thing about bonus mode, is it only lasts for one level)
Ive noticed something rather odd.
A repeating pattern.
Im on Chapter 1 at the minute, and I am seeing alot of the memory addresses repeating the same values.
4/5 bytes long.
00 00 00 05
or perhaps the most repeating one that needs mentioning is the 3 byte length one which repeats over 2000 times.
2000 memory bytes with same 3 length repeating pattern.
Which gives 00 00 05
However, in some cases, these 3 length patterns are actually 6 in length, which would be 00 00 05 68 00 00 - not sure how... but thats what cheatmachine says.
The same 6 long array of bytes in bonus mode Kain, is
00 00 88 68 00 00
Im about to perform a single test that 'may' help lower the amout of addresses.
Because Ive only been going back and forth between 2 saves, to two levels, some of those values may relate to level data, so I will take bonus kain, onto the same level as level 1 save is, and scan for something changed, opposed to something same as first scan. |
|
Back to top |
|
|
Baaleos
Joined: 02 Sep 2007 Posts: 830
|
Posted: Thu Jun 24, 2010 3:36 Post subject: double arg!! |
|
|
I cant get the address list below 2000 |
|
Back to top |
|
|
Baaleos
Joined: 02 Sep 2007 Posts: 830
|
Posted: Thu Jun 24, 2010 3:44 Post subject: freezing one of those 3 length addresses.. |
|
|
K, This is what freezing one of those 2000+ addresses did. Lol |
|
Back to top |
|
|
Baaleos
Joined: 02 Sep 2007 Posts: 830
|
Posted: Thu Jun 24, 2010 4:00 Post subject: other funny effects |
|
|
I've managed to make sprites appear all over the screen, turn steam into xbox controller buttons, and make my dark gift glow, reveal secret messages....well... really just gibberish... |
|
Back to top |
|
|
peachykeen
Joined: 13 Feb 2010 Posts: 15 Location: MD, US
|
Posted: Thu Jun 24, 2010 4:46 Post subject: |
|
|
My first guess, when you say repeating patterns, is a struct. Some kind of struct with similar data being repeated in memory, possibly for multiple objects or instances of an object. I'm not familiar with the game or engine, but it's a thought.
My next suggestion is to use the cheat engine to find the code modifying some of your mystery patterns, or better yet, the code that changes the data when the gift changes. Write down the addresses, all of them (I literally have a hundred sheets of notebook paper with RVAs, offsets, function addresses and such scattered around my room).
Now open the game in IDA and go to each of those addresses. Search up till you find the function they belong to, then set breakpoints at the start of each function. That'll give you some idea of what's going on. If a function contains any render calls (what system does the game use, OpenGL or DirectX?), you can probably discount it (or set it off into a second group for now).
At this point, the more you know the better, doesn't matter what it happens to be. |
|
Back to top |
|
|
Baaleos
Joined: 02 Sep 2007 Posts: 830
|
Posted: Thu Jun 24, 2010 14:54 Post subject: OOOH Idea |
|
|
I just had an idea, and this idea would not have come to me, had I not seen the source code for the game.
struct kainTune { } This contains alot of structs inside it,
The ones I wana alter, is the Healthparams one which tells the game if each of the dark gifts is available.
I've been trying to go straight to the dark gift values or locations etc, to get them.
What I should be doing, is finding something which is easier to locate, like a health value, and then using the information from the source code, to aproximate the location of the dark gifts.
eg
Code: |
kainTune {
int32 fOldTuneData; // desc=DO_NOT_CHANGE default=0
KainAccessoryParams accessoryParams;
KainAirParams airParams;
KainAttackParams attackParams;
AwarenessParams awarenessParams;
KainBlockParams blockParams;
KainBloodSuckParams bloodSuckParams;
KainClothParams clothParams;
KainCollisionParams collisionParams;
KainDarkGiftParams darkGiftParams;
KainDeathParams deathParams;
KainDebugControls debugParams;
KainEdgeGrabParams edgeGrabParams;
KainFallParams fallParams;
KainFallToDeathParams fallToDeathParams;
KainFireParams fireParams;
KainHeadControls headParams;
KainHealthParams healthParams;
KainHitReactControls hitReactParams;
KainInteractParams interactParams;
KainJumpParams jumpParams;
KainLadderParams ladderParams;
CreatureLightingTune lightingParams;
KainMoveParams moveParams;
OtherKainData otherParams;
KainRageParams rageParams;
KainSelectCreatureParams selectCreatureParams;
CreatureShadowTune shadowParams;
KainSuperJumpAttackParams superJumpAttackParams;
KainTriggerParams triggerParams;
KainWallHugParams wallhugParams;
KainWaterParams waterParams;
TriggerNAlignTune *alignArray;
int32 numAligns; // sizeof=alignArray (must be int32!!!)
char* cameraEType; // resourcetype=etype desc=etype_of_kains_camera
};
|
if we know that the first bit of data in the kain struct is an int32, which is apparently fOldTuneData (perhaps for previous level data), then that means that the next bytes to come afterwards, has to be the KainAccessoryParams, this too is a struct within the KainTune struct, so we gather information about this struct, to determine its length.
Im happy to see that is is possibly the shortest struct I have ever seen.
Just a single char value inside it.
Then we have kains air params
Code: |
struct KainAirParams
{
float maxJumpHeight; // desc=max_jump_height(inches) default=128.
float controlThresh; // desc=analog_threshold_for_in_air_control default=0.1
};
|
which is 2 floats long, guessing thats 2 x 4 bytes in length....
NEWS FLASH..
I might not have to do memory scanning constantly after all.
If I have the uncompiled information relating to the source code, I should be able to use this information to locate structs in memory.
I do have the default values of the structs
Code: |
struct KainHealthParams
{
float healthIncreaseRate; // desc=Health_and_max_health_bar_grow_rates_after_suck_in_or_lore_level_upgrade default=50
float loreIncreaseRate; // desc=How_fast_lore_accumulated_by_particles_actually_gets_added_per_second default=1
float thirstDrainRate; // desc=How_many_hit_points_we_lose_per_second_due_to_thirst default=0.1
float thirstMinPercent; // desc=What_is_the_minimum_percentage_of_health_the_thirst_can_drain_us_to default=10.0
float thirstDrainTime; // desc=Number_of_seconds_between_thirst_drains default=30.0
float thirstDrainAmount; // desc=Number_of_hit_points_that_get_drained_per_thirst default=10.0
KainLoreLevels * lorePerLevelArray;
int32 numLoreLevels; // sizeof=lorePerLevelArray (must be int32!!!)
KainDebugHealth defaultHealth; // desc=default_health_and_gifts_for_non-game_levels
KainDebugHealth * debugHealth;
int32 numDebugHealths; // sizeof=debugHealth (must be int32!!!)
};
|
So, for this struct, on level 1, the default data would/should be
float 50
float 1
float 0.1
float 10
float 30
float 10
int unknownstartvalue
struct ourdarkgiftsstoredhere
50 as a float, not sure what that is in hex, but calculator says 32??
float value of 1 i think would be 00 01
float of 0.1 not a clue.
float of 10 to hex I think is 00 0A according to calc
30 would be 00 1e I think?
So, put this together, we get
00 32 00 01 xx xx 00 0A 00 1e xx <start of struct here that we want>
(I think)
Ive possibly calculated these wrong |
|
Back to top |
|
|
peachykeen
Joined: 13 Feb 2010 Posts: 15 Location: MD, US
|
Posted: Thu Jun 24, 2010 18:27 Post subject: |
|
|
I would still do a scan, personally, but going by the KainHealthParams struct, scan for this:
Code: |
struct KainHealthParams
{
0x00004842 // 50 as a float
0x000008F3 // 1 as a float
0xCCCCCC3D // 0.1
0x00000241
0x00000F41 // I think these are right, check my conversions though
0x00000241
void * unknown; // 32-bits, 4 bytes
}
|
If you're right and that memory does start with htose values, having 24 bytes of known data to go on will definitely help you narrow down possible locations. Knowing the struct its part of and any children, you can then calculate offsets from that and hook those, making a full-blown memory editor (or just use CE). |
|
Back to top |
|
|
Baaleos
Joined: 02 Sep 2007 Posts: 830
|
Posted: Thu Jun 24, 2010 21:18 Post subject: |
|
|
certainly a tricky one.
I havent been able to find
00 00 48 42 00 00 08 F3 CC CC CC 3D anywhere in the exe.
Odd.
I did however, see a comment/static data in the program, which referers to a file path for the games kain.big file (where I found all those structs)
But this big file, isnt in my data folder, at least not that I can tell.
It appears to be accessing this file path, in a virtual directory of some sort.
Like the file directory exists in dat files, on the pc cd disc.
(Virtual Disc.... not that I condone piracy..... I assure you... I own the game.... just not on the pc.....)
Im just wondering if it loads the structs into memory, and disposes of them when no longer needed.
In theory, it could just load the struct when needed - as far as I know, it loads the kain.big file when I start a new level, or load a game.
So, it is very likely it accesses the classes and structs from the big file at this time, loads data into ram, then disposes of the structs.
Where is wonder hacker when u need him! |
|
Back to top |
|
|
peachykeen
Joined: 13 Feb 2010 Posts: 15 Location: MD, US
|
Posted: Thu Jun 24, 2010 21:34 Post subject: |
|
|
Baaleos wrote: | certainly a tricky one.
I havent been able to find
00 00 48 42 00 00 08 F3 CC CC CC 3D anywhere in the exe.
Odd. |
Chances are, it won't be in the EXE in a row anywhere. You'll have to scan for that in memory when the game is first started, while the values are at the default.
Quote: | I did however, see a comment/static data in the program, which referers to a file path for the games kain.big file (where I found all those structs)
But this big file, isnt in my data folder, at least not that I can tell.
It appears to be accessing this file path, in a virtual directory of some sort.
Like the file directory exists in dat files, on the pc cd disc.
(Virtual Disc.... not that I condone piracy..... I assure you... I own the game.... just not on the pc.....) |
What file format does the game use, DAT? You may be able to extract them. I think DAT is a simplistic uncompressed archive format like CAB or BSA, but I'm not familiar with it.
Quote: | Im just wondering if it loads the structs into memory, and disposes of them when no longer needed.
In theory, it could just load the struct when needed - as far as I know, it loads the kain.big file when I start a new level, or load a game.
So, it is very likely it accesses the classes and structs from the big file at this time, loads data into ram, then disposes of the structs.
Where is wonder hacker when u need him! |
I think you may be misunderstanding structs, here. A struct is how the data is set up in memory. There's no such thing as a struct, not really. A struct (short for structure) defines how data is stored and retrieved from memory and is really just a way to make things easier for programmers.
For example, the following snippets are effectively identical:
Code: |
struct inventory
{
int weapon;
int shield;
int armor;
};
struct myChar
{
string name;
float health;
inventory myInventory;
}; |
and
Code: |
struct myChar
{
string name;
float health;
int weapon;
int shield;
int armor;
}; |
The difference is, to get the armor from the first example, I can type myChar.myInventory.armor. To get it from the second, it becomes myChar.armor. That's not a big deal with 5 members, but with 15, or 150, or lists and structs within structs, or shared structs (I've been using those a lot lately), it can make a huge difference.
So, you can't look for a struct, but the struct helps you figure out how the data is arranged so you can look for it. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|