NXEngine v1.0.0.6
[NXEngine.git] / profile.cpp
blob61f8f4e0bdabb181ef0ab141d285ad77a3f629c5
2 #include "nx.h"
3 #include "profile.h"
4 #include "profile.fdh"
6 #define PF_WEAPONS_OFFS 0x38
7 #define PF_CURWEAPON_OFFS 0x24
8 #define PF_INVENTORY_OFFS 0xD8
9 #define PF_TELEPORTER_OFFS 0x158
10 #define PF_FLAGS_OFFS 0x218
12 #define MAX_WPN_SLOTS 8
13 #define MAX_TELE_SLOTS 8
15 // load savefile #num into the given Profile structure.
16 bool profile_load(const char *pfname, Profile *file)
18 int i, curweaponslot;
19 FILE *fp;
21 stat("Loading profile from %s...", pfname);
22 memset(file, 0, sizeof(Profile));
24 fp = fileopen(pfname, "rb");
25 if (!fp)
27 staterr("profile_load: unable to open '%s'", pfname);
28 return 1;
31 if (!fverifystring(fp, "Do041220"))
33 staterr("profile_load: invalid savegame format: '%s'", pfname);
34 fclose(fp);
35 return 1;
38 file->stage = fgetl(fp);
39 file->songno = fgetl(fp);
41 file->px = fgetl(fp);
42 file->py = fgetl(fp);
43 file->pdir = CVTDir(fgetl(fp));
45 file->maxhp = fgeti(fp);
46 file->num_whimstars = fgeti(fp);
47 file->hp = fgeti(fp);
49 fgeti(fp); // unknown value
50 curweaponslot = fgetl(fp); // current weapon (slot, not number, converted below)
51 fgetl(fp); // unknown value
52 file->equipmask = fgetl(fp); // equipped items
54 // load weapons
55 fseek(fp, PF_WEAPONS_OFFS, SEEK_SET);
56 for(i=0;i<MAX_WPN_SLOTS;i++)
58 int type = fgetl(fp);
59 if (!type) break;
61 int level = fgetl(fp);
62 int xp = fgetl(fp);
63 int maxammo = fgetl(fp);
64 int ammo = fgetl(fp);
66 file->weapons[type].hasWeapon = true;
67 file->weapons[type].level = (level - 1);
68 file->weapons[type].xp = xp;
69 file->weapons[type].ammo = ammo;
70 file->weapons[type].maxammo = maxammo;
72 if (i == curweaponslot)
74 file->curWeapon = type;
78 // load inventory
79 file->ninventory = 0;
80 fseek(fp, PF_INVENTORY_OFFS, SEEK_SET);
81 for(i=0;i<MAX_INVENTORY;i++)
83 int item = fgetl(fp);
84 if (!item) break;
86 file->inventory[file->ninventory++] = item;
89 // load teleporter slots
90 file->num_teleslots = 0;
91 fseek(fp, PF_TELEPORTER_OFFS, SEEK_SET);
92 for(i=0;i<NUM_TELEPORTER_SLOTS;i++)
94 int slotno = fgetl(fp);
95 int scriptno = fgetl(fp);
96 if (slotno == 0) break;
98 file->teleslots[file->num_teleslots].slotno = slotno;
99 file->teleslots[file->num_teleslots].scriptno = scriptno;
100 file->num_teleslots++;
103 // load flags
104 fseek(fp, PF_FLAGS_OFFS, SEEK_SET);
105 if (!fverifystring(fp, "FLAG"))
107 staterr("profile_load: missing 'FLAG' marker");
108 fclose(fp);
109 return 1;
112 fresetboolean();
113 for(i=0;i<NUM_GAMEFLAGS;i++)
115 file->flags[i] = fbooleanread(fp);
118 fclose(fp);
119 return 0;
123 bool profile_save(const char *pfname, Profile *file)
125 FILE *fp;
126 int i;
128 //stat("Writing saved game to %s...", pfname);
129 fp = fileopen(pfname, "wb");
130 if (!fp)
132 staterr("profile_save: unable to open %s", pfname);
133 return 1;
136 fputstringnonull("Do041220", fp);
138 fputl(file->stage, fp);
139 fputl(file->songno, fp);
141 fputl(file->px, fp);
142 fputl(file->py, fp);
143 fputl((file->pdir == RIGHT) ? 2:0, fp);
145 fputi(file->maxhp, fp);
146 fputi(file->num_whimstars, fp);
147 fputi(file->hp, fp);
149 fseek(fp, 0x2C, SEEK_SET);
150 fputi(file->equipmask, fp);
152 // save weapons
153 fseek(fp, PF_WEAPONS_OFFS, SEEK_SET);
154 int slotno = 0, curweaponslot = 0;
156 for(i=0;i<WPN_COUNT;i++)
158 if (file->weapons[i].hasWeapon)
160 fputl(i, fp);
161 fputl(file->weapons[i].level + 1, fp);
162 fputl(file->weapons[i].xp, fp);
163 fputl(file->weapons[i].maxammo, fp);
164 fputl(file->weapons[i].ammo, fp);
166 if (i == file->curWeapon)
167 curweaponslot = slotno;
169 slotno++;
170 if (slotno >= MAX_WPN_SLOTS) break;
174 if (slotno < MAX_WPN_SLOTS)
175 fputl(0, fp); // 0-type weapon: terminator
177 // go back and save slot no of current weapon
178 fseek(fp, PF_CURWEAPON_OFFS, SEEK_SET);
179 fputl(curweaponslot, fp);
181 // save inventory
182 fseek(fp, PF_INVENTORY_OFFS, SEEK_SET);
183 for(i=0;i<file->ninventory;i++)
185 fputl(file->inventory[i], fp);
188 fputl(0, fp);
190 // write teleporter slots
191 fseek(fp, PF_TELEPORTER_OFFS, SEEK_SET);
192 for(i=0;i<MAX_TELE_SLOTS;i++)
194 if (i < file->num_teleslots)
196 fputl(file->teleslots[i].slotno, fp);
197 fputl(file->teleslots[i].scriptno, fp);
199 else
201 fputl(0, fp);
202 fputl(0, fp);
206 // write flags
207 fseek(fp, PF_FLAGS_OFFS, SEEK_SET);
208 fputstringnonull("FLAG", fp);
210 fresetboolean();
211 for(i=0;i<NUM_GAMEFLAGS;i++)
213 fbooleanwrite(file->flags[i], fp);
216 fbooleanflush(fp);
218 fclose(fp);
219 return 0;
224 void c------------------------------() {}
227 // returns the filename for a save file given it's number
228 const char *GetProfileName(int num)
230 if (num == 0)
231 return "profile.dat";
232 else
233 return stprintf("profile%d.dat", num+1);
236 // returns whether the given save file slot exists
237 bool ProfileExists(int num)
239 return file_exists(GetProfileName(num));
242 bool AnyProfileExists()
244 for(int i=0;i<MAX_SAVE_SLOTS;i++)
245 if (ProfileExists(i)) return true;
247 return false;