Much of this material is in the form of C source code. Needless to say, familiarity with the C language is a definite plus. I haven't edited the source in any way, so beware portability and compiler problems, and note also that it's all for the PC version. You Amiga owners seem a pretty tight-lipped bunch!
You can also look for my GPList program and GPTools source archive. I never really finished GPList and will probably re-write it from scratch as part of GPTools, but it does contain details of how the setups, track records, and names files are stored. Both are available from http://www.mal.com/~dgymer/f1gp/util/.
From: ubjc@rz.uni-karlsruhe.de Subject: f1gp To: dgymer@gdcarc.co.uk (gizmo) Date sent: Mon, 1 May 1995 03:07:08 +0200 (CES) [...] In this case some details concerning your upcomming tech. FAQ: Date of files on disk: 04/19/93 Length of gp.exe : 321878 Bytes Version : 1.05 Offsets: Driving Aids: $1E4FF BHP : $1C212 Colors: Cars : $26B24 Helmets : $26C4B Team clothes: $26EBD (I haven't seen it used in any Editor ??) . . . More details are available if required (e.g.the exepack-alghorithm, which seems to be different to other versions, see above mentioned problems with F1ED).
From: ubjc@rz.uni-karlsruhe.de Subject: Re: Karusell To: dgymer@gdcarc.co.uk Date sent: Wed, 14 Jun 1995 19:39:50 +0200 (CES) [gp.exe] Compression (only verified with European 1.05 packed version) may be you find this sequence of bytes (in hex): .... ll hh B2 nn ll hh B0 ..... ll hh - Low and high byte of the count of bytes since last appearance of a B0. This indicates that the following B2 is a compression indicator B2 - start of compressed area nn - byte to repeat ll hh - low and high byte of the count of repeats B0 - end of compressed area Example: compressed: ... B2 4F 09 00 B0 00 01 4F 4F 4F 4F 06 07 00 B2 .... 9 x 4F | 7 bytes not compr. | next compressed area is expanded to: ... 4F 4F 4F 4F 4F 4F 4F 4F 4F 00 01 4F 4F 4F 06 .... You need at least 8 equal bytes to spare some bytes.
From: Craig Heath <craig@sco.COM> To: dgymer@gdcarc.co.uk Subject: F1GP Save File Checksums Date sent: Wed, 19 Apr 95 19:16:19 BST Here is a little C program which recalculates the checksums on F1GP save files - enjoy! - Craig @ SCO near London. #include <stdio.h> main(argc, argv) char *argv[]; { FILE *savefile; long datasize; unsigned short sum = 0, cycle = 0; unsigned char c; if (argc != 2) { fprintf(stderr, "usage: %s save-file\n", argv[0]); exit(1); } if ((savefile=fopen(argv[1], "rb+"))==NULL) { fprintf(stderr, "%s: cannot open %s for update\n", argv[0], argv[1]); exit(1); } if (fseek(savefile, -4L, SEEK_END) < 0) { fprintf(stderr, "%s: seek failed in %s\n", argv[0], argv[1]); exit(1); } datasize = ftell(savefile); rewind(savefile); while (datasize--) { sum += (c = fgetc(savefile)); cycle = (cycle << 3) + (cycle >> 13); cycle += c; } if (fseek(savefile, -4L, SEEK_END) < 0) { fprintf(stderr, "%s: seek failed in %s\n", argv[0], argv[1]); exit(1); } if (fwrite(&sum, 2, 1, savefile) < 1 || fwrite(&cycle, 2, 1, savefile) < 1) { fprintf(stderr, "%s: error writing %s checksum\n", argv[0], argv[1]); exit(1); } (void) fclose(savefile); exit(0); }
#include <stdio.h> #include <stdlib.h> #include <memory.h> typedef unsigned char uchar; #define NPATCHES 5 uchar qtso1[] = { 0xf6,0x86,0x4a,0x12,0x40,0x74,0x23 }; uchar qtsn1[] = { 0xf6,0x86,0x4a,0x12,0x80,0x75,0x23 }; uchar mano1[] = { 0xb8,0x00,0x00,0x9a,0x0a,0x08 }; uchar mann1[] = { 0xb8,0x0b,0x00,0x9a,0x25,0x08 }; uchar mann2[] = { 0x8b,0xbb,0xe4,0x02 }; uchar aido1[] = { 0x3f,0x3e,0x3e,0x32,0x02 }; uchar aidn1[] = { 0x3f,0x3f,0x3f,0x3f,0x3f }; uchar ffdo1[] = { 0xec,0xa8,0x08,0x75,0xfb,0xec,0xa8,0x08,0x74,0xfb }; uchar ffdn1[] = { 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90 }; struct { unsigned long offset[6]; char *oldpart1, *newpart1; int length1, gap; char *newpart2; int length2; char *name; } table[NPATCHES] = { /* packed packed packed unpacked unpacked unpacked European Italian American European Italian American */ 0x0ac14, 0x0ac14, 0x0ac14, 0x0c014, 0x0c014, 0x0c014, qtso1, qtsn1, sizeof qtso1, 0, 0, 0, "practice tyres", 0x1aa61, 0x1aa2d, 0x1aa35, 0x1c104, 0x1c0d0, 0x1c0d8, mano1, mann1, sizeof mano1, 1, mann2, sizeof mann2, "manual crack", 0x1e4ff, 0x1e4cb, 0x1e4d3, 0x1fd36, 0x1fcf6, 0x1fd06, aido1, aidn1, sizeof aido1, 0, 0, 0, "allow all aids", 0x33d80, 0, 0, 0x6c1b8, 0, 0, "Siete:", "Seite:", 6, 0, 0, 0, "German spelling", 0x4a606, 0x4a57b, 0x4a560, 0x8d53a, 0x8d4aa, 0x8d49a, ffdo1, ffdn1, sizeof ffdo1, 0, 0, 0, "fast fades" }; unsigned long ver105off[] = { 0x33841, 0x3380d, 0x33803, 0x6bc79, 0x6bc39, 0x6bc37 }; char *version[] = { "European", "Italian", "US" }; void main(int argc, char *argv[]) { FILE *exe; register i; int ver; uchar buf[64]; if (argc != 2) { fprintf(stderr, "usage: %s exe-file\n", argv[0]); exit(1); } if ((exe=fopen(argv[1], "rb+"))==NULL) { fprintf(stderr, "%s: cannot open %s for update\n", argv[0], argv[1]); exit(1); } for (i=0; i<6; i++) { if (fseek(exe, ver105off[i], SEEK_SET) == 0 && fread(buf, 12, 1, exe) == 1 && memcmp(buf, "Version 1.05", 12) == 0) { printf("%s version (%spacked)\n", version[i % 3], (i > 2) ? "un" : ""); goto gotver; } } fprintf(stderr, "%s: %s unrecognised version (v1.05 required)\n", argv[0], argv[1]); exit(1); gotver: ver = i; for (i=0; i<NPATCHES; i++) { if (table[i].offset[ver] == 0) continue; if (fseek(exe, table[i].offset[ver], SEEK_SET) != 0 || fread(buf, table[i].length1, 1, exe) < 1) { fprintf(stderr, "%s: error reading %s\n", argv[0], argv[1]); exit(1); } if (memcmp(buf, table[i].oldpart1, table[i].length1) == 0) { if (fseek(exe, table[i].offset[ver], SEEK_SET) != 0 || fwrite(table[i].newpart1, table[i].length1, 1, exe) < 1 || (table[i].gap && (fseek(exe, (long)table[i].gap, SEEK_CUR) != 0 || fwrite(table[i].newpart2, table[i].length2, 1, exe) < 1 ))) { fprintf(stderr, "%s: error writing %s\n", argv[0], argv[1]); exit(1); } printf("%s patch: applied\n", table[i].name); } else if (memcmp(buf, table[i].newpart1, table[i].length1) == 0) { printf("%s patch: already applied\n", table[i].name); } else { printf("%s patch: not found!\n", table[i].name); } } (void) fclose(exe); exit(0); }
From: John Robert Cole <s9506032@arcadia.cs.rmit.edu.au> Subject: Re: Tire Cheats for WC. To: dgymer@gdcarc.co.uk Date sent: Sun, 18 Jun 1995 13:49:30 +0000 (australasia) [...] Here is some information that could be used in the technical FAQ or passed onto someone who is writing an editor for word circuit, it involves the points scoring system and modifying it as I have figured out it's location. (This is the ofsets for the US v1.05 version of the game.) ofset length contains Normal 026a59 6 bytes 0a 06 04 03 02 01 UnCompressed 0acfcf 26 bytes 0a 06 04 03 02 01 00 00 ... 00 Effectively every driver can obtain a point if the uncompressed EXE was set up in that way, I have set up an EXE which is based around the Indycar points scoring system and it works fine. [...]