| 1 | /* |
| 2 | * Elite - The New Kind. |
| 3 | * |
| 4 | * Reverse engineered from the BBC disk version of Elite. |
| 5 | * Additional material by C.J.Pinder. |
| 6 | * |
| 7 | * The original Elite code is (C) I.Bell & D.Braben 1984. |
| 8 | * This version re-engineered in C by C.J.Pinder 1999-2001. |
| 9 | * |
| 10 | * email: <christian@newkind.co.uk> |
| 11 | * |
| 12 | * |
| 13 | */ |
| 14 | |
| 15 | /* |
| 16 | * file.c |
| 17 | */ |
| 18 | |
| 19 | #include <ctype.h> |
| 20 | #include <stdio.h> |
| 21 | #include <stdlib.h> |
| 22 | #include <string.h> |
| 23 | |
| 24 | #include "elite.h" |
| 25 | #include "config.h" |
| 26 | #include "file.h" |
| 27 | |
| 28 | void write_config_file (void) |
| 29 | { |
| 30 | FILE *fp; |
| 31 | |
| 32 | fp = fopen ("newkind.cfg", "w"); |
| 33 | if (fp == NULL) |
| 34 | return; |
| 35 | |
| 36 | fprintf (fp, "%d\t\t# Game Speed, the lower the number the faster the game.\n", speed_cap); |
| 37 | |
| 38 | fprintf (fp, "%d\t\t# Graphics: 0 = Solid, 1 = Wireframe\n", wireframe); |
| 39 | |
| 40 | fprintf (fp, "%d\t\t# Anti-Alias Wireframe: 0 = Normal, 1 = Anti-Aliased\n", anti_alias_gfx); |
| 41 | |
| 42 | fprintf (fp, "%d\t\t# Planet style: 0 = Wireframe, 1 = Green, 2 = SNES, 3 = Fractal\n", planet_render_style); |
| 43 | |
| 44 | fprintf (fp, "%d\t\t# Planet Descriptions: 0 = Tree Grubs, 1 = Hoopy Casinos\n", hoopy_casinos); |
| 45 | |
| 46 | fprintf (fp, "%d\t\t# Instant dock: 0 = off, 1 = on\n", instant_dock); |
| 47 | |
| 48 | fprintf (fp, "newscan.cfg\t# Name of scanner config file to use.\n"); |
| 49 | fprintf (fp, "%d\t\t# Run in a window: 0 = off, 1 = on\n", prefer_window); |
| 50 | |
| 51 | fclose (fp); |
| 52 | } |
| 53 | |
| 54 | |
| 55 | /* |
| 56 | * Read a line from a .cfg file. |
| 57 | * Ignore blanks, comments and strip white space. |
| 58 | */ |
| 59 | |
| 60 | void read_cfg_line (char *str, int max_size, FILE *fp) |
| 61 | { |
| 62 | char *s; |
| 63 | |
| 64 | do |
| 65 | { |
| 66 | fgets (str, max_size, fp); |
| 67 | |
| 68 | for (s = str; *s; s++) /* End of line at LF or # */ |
| 69 | { |
| 70 | if ((*s == '\n') || (*s == '#')) |
| 71 | { |
| 72 | *s = '\0'; |
| 73 | break; |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | if (s != str) /* Trim any trailing white space */ |
| 78 | { |
| 79 | s--; |
| 80 | while (isspace(*s)) |
| 81 | { |
| 82 | *s = '\0'; |
| 83 | if (s == str) |
| 84 | break; |
| 85 | s--; |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | } while (*str == '\0'); |
| 90 | } |
| 91 | |
| 92 | |
| 93 | /* |
| 94 | * Read in the scanner .cfg file. |
| 95 | */ |
| 96 | |
| 97 | void read_scanner_config_file (char *filename) |
| 98 | { |
| 99 | FILE *fp; |
| 100 | char str[256]; |
| 101 | |
| 102 | fp = fopen (filename, "r"); |
| 103 | if (fp == NULL) |
| 104 | return; |
| 105 | |
| 106 | read_cfg_line (str, sizeof(str), fp); |
| 107 | strcpy (scanner_filename, str); |
| 108 | |
| 109 | read_cfg_line (str, sizeof(str), fp); |
| 110 | sscanf (str, "%d,%d", &scanner_cx, &scanner_cy); |
| 111 | scanner_cy += 385; |
| 112 | |
| 113 | read_cfg_line (str, sizeof(str), fp); |
| 114 | sscanf (str, "%d,%d", &compass_centre_x, &compass_centre_y); |
| 115 | compass_centre_y += 385; |
| 116 | |
| 117 | read_cfg_line (str, sizeof(str), fp); |
| 118 | sscanf (str, "%d,%d,%d", &condition_x, &condition_y, &condition_r); |
| 119 | condition_y += 385; |
| 120 | |
| 121 | read_cfg_line (str, sizeof(str), fp); |
| 122 | sscanf (str, "%d,%d", &zoom_x, &zoom_y); |
| 123 | zoom_y += 385; |
| 124 | |
| 125 | fclose (fp); |
| 126 | } |
| 127 | |
| 128 | /* |
| 129 | * Read in the newkind.cfg file. |
| 130 | */ |
| 131 | |
| 132 | void read_config_file (void) |
| 133 | { |
| 134 | FILE *fp; |
| 135 | char str[256]; |
| 136 | |
| 137 | fp = fopen ("newkind.cfg", "r"); |
| 138 | if (fp == NULL) |
| 139 | return; |
| 140 | |
| 141 | read_cfg_line (str, sizeof(str), fp); |
| 142 | sscanf (str, "%d", &speed_cap); |
| 143 | |
| 144 | read_cfg_line (str, sizeof(str), fp); |
| 145 | sscanf (str, "%d", &wireframe); |
| 146 | |
| 147 | read_cfg_line (str, sizeof(str), fp); |
| 148 | sscanf (str, "%d", &anti_alias_gfx); |
| 149 | |
| 150 | read_cfg_line (str, sizeof(str), fp); |
| 151 | sscanf (str, "%d", &planet_render_style); |
| 152 | |
| 153 | read_cfg_line (str, sizeof(str), fp); |
| 154 | sscanf (str, "%d", &hoopy_casinos); |
| 155 | |
| 156 | read_cfg_line (str, sizeof(str), fp); |
| 157 | sscanf (str, "%d", &instant_dock); |
| 158 | |
| 159 | read_cfg_line (str, sizeof(str), fp); |
| 160 | read_scanner_config_file (str); |
| 161 | |
| 162 | read_cfg_line (str, sizeof(str), fp); |
| 163 | sscanf (str, "%d", &prefer_window); |
| 164 | |
| 165 | fclose (fp); |
| 166 | } |
| 167 | |
| 168 | int checksum (unsigned char *block) |
| 169 | { |
| 170 | int acc,carry; |
| 171 | int i; |
| 172 | |
| 173 | acc = 0x49; |
| 174 | carry = 0; |
| 175 | for (i = 0x49; i > 0; i--) |
| 176 | { |
| 177 | acc += block[i-1] + carry; |
| 178 | carry = acc >> 8; |
| 179 | acc &= 255; |
| 180 | acc ^= block[i]; |
| 181 | } |
| 182 | |
| 183 | return acc; |
| 184 | } |
| 185 | |
| 186 | |
| 187 | int save_commander_file (char *path) |
| 188 | { |
| 189 | FILE *fp; |
| 190 | unsigned char block[256]; |
| 191 | int i; |
| 192 | int chk; |
| 193 | |
| 194 | fp = fopen (path, "wb"); |
| 195 | if (fp == NULL) |
| 196 | return 1; |
| 197 | |
| 198 | block[0] = cmdr.mission; |
| 199 | block[1] = docked_planet.d; |
| 200 | block[2] = docked_planet.b; |
| 201 | block[3] = cmdr.galaxy.a; |
| 202 | block[4] = cmdr.galaxy.b; |
| 203 | block[5] = cmdr.galaxy.c; |
| 204 | block[6] = cmdr.galaxy.d; |
| 205 | block[7] = cmdr.galaxy.e; |
| 206 | block[8] = cmdr.galaxy.f; |
| 207 | block[9] = (cmdr.credits >> 24) & 255; |
| 208 | block[10] = (cmdr.credits >> 16) & 255; |
| 209 | block[11] = (cmdr.credits >> 8) & 255; |
| 210 | block[12] = cmdr.credits & 255; |
| 211 | block[13] = cmdr.fuel; |
| 212 | block[14] = 4; |
| 213 | block[15] = cmdr.galaxy_number; |
| 214 | block[16] = cmdr.front_laser; |
| 215 | block[17] = cmdr.rear_laser; |
| 216 | block[18] = cmdr.left_laser; |
| 217 | block[19] = cmdr.right_laser; |
| 218 | block[20] = 0; |
| 219 | block[21] = 0; |
| 220 | block[22] = cmdr.cargo_capacity + 2; |
| 221 | |
| 222 | for (i = 0; i < NO_OF_STOCK_ITEMS; i++) |
| 223 | block[23+i] = cmdr.current_cargo[i]; |
| 224 | |
| 225 | block[40] = cmdr.ecm ? 255 : 0; |
| 226 | block[41] = cmdr.fuel_scoop ? 255 : 0; |
| 227 | block[42] = cmdr.energy_bomb ? 0x7F : 0; |
| 228 | block[43] = cmdr.energy_unit; |
| 229 | block[44] = cmdr.docking_computer ? 255 : 0; |
| 230 | block[45] = cmdr.galactic_hyperdrive ? 255 : 0; |
| 231 | block[46] = cmdr.escape_pod ? 255 : 0; |
| 232 | block[47] = 0; |
| 233 | block[48] = 0; |
| 234 | block[49] = 0; |
| 235 | block[50] = 0; |
| 236 | block[51] = cmdr.missiles; |
| 237 | block[52] = cmdr.legal_status; |
| 238 | |
| 239 | for (i = 0; i < NO_OF_STOCK_ITEMS; i++) |
| 240 | block[53+i] = stock_market[i].current_quantity; |
| 241 | |
| 242 | block[70] = cmdr.market_rnd; |
| 243 | block[71] = cmdr.score & 255; |
| 244 | block[72] = cmdr.score >> 8; |
| 245 | block[73] = 0x20; |
| 246 | |
| 247 | chk = checksum (block); |
| 248 | |
| 249 | block[74] = chk ^ 0xA9; |
| 250 | block[75] = chk; |
| 251 | |
| 252 | for (i = 76; i < 256; i++) |
| 253 | block[i] = 0; |
| 254 | |
| 255 | if (fwrite (block, 256, 1, fp) != 1) |
| 256 | return 1; |
| 257 | |
| 258 | if (fclose (fp) == EOF) |
| 259 | return 1; |
| 260 | |
| 261 | return 0; |
| 262 | } |
| 263 | |
| 264 | |
| 265 | int load_commander_file (char *path) |
| 266 | { |
| 267 | FILE *fp; |
| 268 | unsigned char block[256]; |
| 269 | int i; |
| 270 | int chk; |
| 271 | |
| 272 | fp = fopen (path, "rb"); |
| 273 | if (fp == NULL) |
| 274 | return 1; |
| 275 | |
| 276 | if (fread (block, 256, 1, fp) != 1) |
| 277 | return 1; |
| 278 | |
| 279 | chk = checksum (block); |
| 280 | |
| 281 | if ((block[74] != (chk ^ 0xA9)) || (block[75] != chk)) |
| 282 | return 1; |
| 283 | |
| 284 | saved_cmdr.mission = block[0]; |
| 285 | |
| 286 | saved_cmdr.ship_x = block[1]; |
| 287 | saved_cmdr.ship_y = block[2]; |
| 288 | |
| 289 | saved_cmdr.galaxy.a = block[3]; |
| 290 | saved_cmdr.galaxy.b = block[4]; |
| 291 | saved_cmdr.galaxy.c = block[5]; |
| 292 | saved_cmdr.galaxy.d = block[6]; |
| 293 | saved_cmdr.galaxy.e = block[7]; |
| 294 | saved_cmdr.galaxy.f = block[8];; |
| 295 | |
| 296 | saved_cmdr.credits = block[9] << 24; |
| 297 | saved_cmdr.credits += block[10] << 16; |
| 298 | saved_cmdr.credits += block[11] << 8; |
| 299 | saved_cmdr.credits += block[12]; |
| 300 | |
| 301 | saved_cmdr.fuel = block[13]; |
| 302 | |
| 303 | saved_cmdr.galaxy_number = block[15]; |
| 304 | saved_cmdr.front_laser = block[16]; |
| 305 | saved_cmdr.rear_laser = block[17]; |
| 306 | saved_cmdr.left_laser = block[18]; |
| 307 | saved_cmdr.right_laser = block[19]; |
| 308 | |
| 309 | saved_cmdr.cargo_capacity = block[22] - 2; |
| 310 | |
| 311 | for (i = 0; i < NO_OF_STOCK_ITEMS; i++) |
| 312 | saved_cmdr.current_cargo[i] = block[23+i]; |
| 313 | |
| 314 | saved_cmdr.ecm = block[40]; |
| 315 | saved_cmdr.fuel_scoop = block[41]; |
| 316 | saved_cmdr.energy_bomb = block[42]; |
| 317 | saved_cmdr.energy_unit = block[43]; |
| 318 | saved_cmdr.docking_computer = block[44]; |
| 319 | saved_cmdr.galactic_hyperdrive = block[45]; |
| 320 | saved_cmdr.escape_pod = block[46]; |
| 321 | saved_cmdr.missiles = block[51]; |
| 322 | saved_cmdr.legal_status = block[52]; |
| 323 | |
| 324 | for (i = 0; i < NO_OF_STOCK_ITEMS; i++) |
| 325 | saved_cmdr.station_stock[i] = block[53+i]; |
| 326 | |
| 327 | saved_cmdr.market_rnd = block[70]; |
| 328 | |
| 329 | saved_cmdr.score = block[71]; |
| 330 | saved_cmdr.score += block[72] << 8; |
| 331 | |
| 332 | if (fclose (fp) == EOF) |
| 333 | return 1; |
| 334 | |
| 335 | return 0; |
| 336 | } |
| 337 | |
| 338 | |
| 339 | |
| 340 | |