SAV Format (Hocus Pocus)

From ModdingWiki
Jump to navigation Jump to search
SAV Format (Hocus Pocus)
Format typeSaved game and Configuration
StoringSound, Scores
Save locationsReturned to level start
Elements savedLevel, Difficulty, Score
Games

Information from the shareware episode:

File format

The file HOCUS.SAV stores the following data structure:

typedef struct {
	Uint16 soundOn, musicOn;
	Uint16 controlMode;
	Uint16 gamespeed;
	Uint16 joyLoX, joyMiX, joyHiX;
	Uint16 joyLoY, joyMiY, joyHiY;
	Uint16 joyFireButton;
	Uint8 controlKeys[8];
	//saved games:
	Sint16 sg_episodes[9];
	Sint16 sg_levels[9];
	Sint16 sg_skill[9];
	char sg_names[9][26];	//9 entries, 26 chars each (25 chars + terminating 0)
	Uint8 unused[10];	//only used by setup (first 9 bytes set to 1)
	Sint32 sg_scores[9];
	//high scores:
	char hs_names[4][5][26];	//4*5 entries, 26 chars each (25 chars + terminating 0)
	Sint32 hs_scores[4][5];
	//sound setup:
	Sint16 soundCard;
	Uint16 numVoices;
	Uint16 mixBits;
	Sint16 musicCard;
	Uint16 midiPort;
	//settings for setup tool:
	Uint16 soundCardIndex;
	Uint16 numVoicesIndex;
	Uint16 mixingQualityIndex;
	Uint16 musicCardIndex;
	Uint16 midiPortIndex;
	//more sound settings:
	Uint16 soundVolume;
	Uint16 musicVolume;
	Uint16 usesGravis;
} TGameConfig;

Save Game part

Offset Data type Description
0x1E SINT16LE episode[9] episode, also indicating whether the each savegame can be loaded. -1 = empty. 0 = first episode. 1 = second episode etc.
0x30 INT16LE level[9] saved level of each savegame. 0 = first level. 1 = second level etc.
0x42 INT16LE difficulty[9] difficulty of each savegame 0 = easy, 1 = moderate, 2 = hard, 3 = godmode
0x54 ASCIZ [9][26] name of each savegame with trailing zero. (maximum 25 characters + trailing zero)
0x13E BYTE unused[10] some rubbish 9 times 1 and 1 time zero. Never used by the game.
Note: The 0 might just be padding, so that the scores start at an even address.
0x148 INT32LE score[9] score of each savegame.

Example

Small sample program(C++) to show information about the savegames: (start like this: app HOCUS.SAV) int assumed to be 32 bit, short to be 16 bit. Only for little endian machines.

 #include <iostream>
 #include <fstream>
 using namespace std;
 
 int main(int argc, char* argv[]) {
    if(argc != 2) return 1;
 
    ifstream input(argv[1]);
    input.seekg(0x1E,ios::beg);
    short signed int episode[9];
    input.read(reinterpret_cast<char*>(&episode),2*9);
    short level[9];
    input.read(reinterpret_cast<char*>(&level),2*9);
    short difficulty[9];
    input.read(reinterpret_cast<char*>(&difficulty),2*9);
    char name[9][26];
    input.read(&name[0][0],9*26);
 
    input.seekg(0x148,ios::beg);
    int score[9];
    input.read(reinterpret_cast<char*>(&score),4*9);
 
    for(int i = 0;i < 9;i++) {
       cout << "save " << i+1 << " episode " << episode[i]
            << " level " << level[i] << " difficulty " << difficulty[i]
            << " name: "<< name[i] << " score " << score[i] << endl;
      }
    return 0;
 }

Highscore part

Offset Data type Description
0x16C ASCIZ Name1[5][26] Names of the people with highscores for episode 1
0x1EE ASCIZ Name2[5][26] Names of the people with highscores for episode 2
0x270 ASCIZ Name3[5][26] Names of the people with highscores for episode 3
0x2F2 ASCIZ Name4[5][26] Names of the people with highscores for episode 4
0x374 INT32LE Score[4][5] Highscores themselves. Listed by episode.

Sound Configuration

Stored at the bottom of the file. (less interesting as setup.exe can change those)

Credits

This file format was reverse engineered by Qbix. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)