Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,115 @@
19
123
134
49
63
0
135
146
49
63
0
147
158
49
63
0
159
170
49
63
0
171
182
49
63
0
183
194
49
63
0
123
134
64
77
0
135
146
64
77
0
147
158
64
77
0
159
170
64
77
0
171
182
64
77
0
183
194
64
77
0
135
146
78
91
0
147
158
78
91
0
159
170
78
91
0
171
182
78
91
0
84
235
7
131
0
0
24
0
137
0
295
319
0
137
0

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,241 @@
239
0 0 0
5 5 5
8 8 8
11 11 11
14 14 14
17 17 17
20 20 20
24 24 24
28 28 28
32 32 32
36 36 36
40 40 40
45 45 45
50 50 50
56 56 56
63 63 63
0 0 63
16 0 63
31 0 63
47 0 63
63 0 63
63 0 47
63 0 31
63 0 16
63 0 0
63 16 0
63 31 0
63 47 0
63 63 0
47 63 0
31 63 0
16 63 0
0 63 0
0 63 16
0 63 31
0 63 47
0 63 63
0 47 63
0 31 63
0 16 63
31 31 63
39 31 63
47 31 63
55 31 63
63 31 63
63 31 55
63 31 47
63 31 39
63 31 31
63 39 31
63 47 31
63 55 31
63 63 31
55 63 31
47 63 31
39 63 31
31 63 31
31 63 39
31 63 47
31 63 55
31 63 63
31 55 63
31 47 63
31 39 63
45 45 63
49 45 63
54 45 63
58 45 63
63 45 63
63 45 58
63 45 54
63 45 49
63 45 45
63 49 45
63 54 45
63 58 45
63 63 45
58 63 45
54 63 45
49 63 45
45 63 45
45 63 49
45 63 54
45 63 58
45 63 63
45 58 63
45 54 63
45 49 63
0 0 28
7 0 28
14 0 28
21 0 28
28 0 28
28 0 21
28 0 14
28 0 7
28 0 0
28 7 0
28 14 0
28 21 0
28 28 0
21 28 0
14 28 0
7 28 0
0 28 0
0 28 7
0 28 14
0 28 21
0 28 28
0 21 28
0 14 28
0 7 28
14 14 28
17 14 28
21 14 28
24 14 28
28 14 28
28 14 24
28 14 21
28 14 17
28 14 14
28 17 14
28 21 14
28 24 14
28 28 14
24 28 14
21 28 14
17 28 14
14 28 14
14 28 17
14 28 21
14 28 24
14 28 28
14 24 28
14 21 28
14 17 28
20 20 28
22 20 28
24 20 28
26 20 28
28 20 28
28 20 26
28 20 24
28 20 22
28 20 20
28 22 20
28 24 20
28 26 20
28 28 20
26 28 20
24 28 20
22 28 20
20 28 20
20 28 22
20 28 24
20 28 26
20 28 28
20 26 28
20 24 28
20 22 28
0 0 16
4 0 16
8 0 16
50 50 50
0 0 0
28 25 20
15 13 11
55 34 21
57 38 20
58 38 21
24 21 17
49 10 10
26 23 19
53 38 17
22 19 16
20 18 14
20 20 20
56 38 19
34 29 9
36 36 36
40 40 40
63 39 24
51 38 16
50 37 15
54 38 18
34 31 25
47 37 14
43 36 11
46 37 13
44 36 12
49 37 14
49 10 10
30 27 22
19 7 3
34 29 9
40 10 8
27 9 5
42 36 11
34 34 34
40 37 30
44 10 9
23 8 4
23 21 17
30 27 24
31 9 6
36 10 7
35 31 28
45 43 39
38 35 28
31 28 23
43 43 43
32 28 26
37 34 27
32 29 24
34 31 25
35 32 26
18 16 13
43 41 37
40 36 30
44 40 33
42 38 32
19 17 14
38 35 29
36 33 27
36 32 29
21 19 16
34 31 26
46 42 35
29 26 21
42 39 35
23 21 17
29 26 21
31 28 23
33 29 24
27 24 20
25 22 18
40 38 34
37 34 31
39 36 32

View File

@@ -0,0 +1,161 @@
20
0
319
0
137
0
0
0
123
134
49
62
0
44160
0
135
146
49
62
0
44328
0
147
158
49
62
0
44496
0
159
170
49
62
0
44664
0
171
182
49
62
0
44832
0
183
194
49
62
0
45000
0
123
134
63
76
0
45168
0
135
146
63
76
0
45336
0
147
158
63
76
0
45504
0
159
170
63
76
0
45672
0
171
182
63
76
0
45840
0
183
194
63
76
0
46008
0
135
146
77
90
0
46176
0
147
158
77
90
0
46344
0
159
170
77
90
0
46512
0
171
182
77
90
0
46680
0
84
235
6
131
0
46848
0
84
235
39
131
0
464
1
84
235
93
131
0
14600
1

View File

@@ -0,0 +1,7 @@
1
0
319
0
199
0

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

View File

@@ -0,0 +1,241 @@
239
0 0 0
0 6 0
0 6 4
0 6 8
4 6 0
4 6 3
4 6 8
8 6 0
5 6 6
5 6 11
1 7 6
7 6 3
0 9 0
7 6 8
10 5 4
9 6 4
0 9 1
7 7 2
0 9 4
3 8 4
0 9 6
5 7 2
5 7 5
1 9 3
3 9 0
1 9 5
2 9 2
4 9 3
5 9 2
1 10 8
4 9 7
1 10 3
1 10 1
5 9 1
2 9 9
12 7 2
7 9 2
6 9 7
8 9 0
5 9 9
8 9 3
5 10 5
0 12 0
8 9 8
5 10 7
9 9 5
8 9 7
1 12 3
8 9 10
5 10 6
10 8 10
7 10 7
5 10 13
0 12 8
8 10 5
1 12 2
12 9 4
11 9 8
12 9 0
2 12 6
4 12 0
3 11 8
4 12 3
13 8 7
5 12 1
3 12 5
4 12 7
4 12 6
5 12 4
9 9 16
9 11 4
2 12 10
1 14 0
7 11 5
5 12 0
8 12 0
7 12 4
2 12 14
8 12 8
7 11 12
6 12 8
9 11 10
9 12 8
6 12 12
0 16 0
11 13 4
12 13 1
12 12 8
2 16 8
4 16 3
4 16 2
12 13 12
4 16 7
7 16 2
6 16 5
4 16 10
8 15 8
16 13 9
9 15 14
8 16 7
8 16 4
12 15 1
17 14 5
7 16 13
15 14 10
13 14 16
11 15 13
5 17 15
7 17 11
12 16 3
7 16 20
11 15 20
11 16 8
10 16 11
13 16 8
13 16 9
4 20 3
12 17 7
12 16 12
3 20 7
19 14 17
15 17 8
12 17 17
7 20 3
10 19 7
16 17 12
6 20 11
8 20 7
16 17 16
12 19 11
11 20 2
15 19 2
20 16 12
12 19 8
12 21 11
9 21 17
13 21 16
15 21 8
16 21 12
7 24 7
10 22 25
16 21 16
7 24 12
10 24 4
15 21 20
20 21 7
5 26 5
20 21 12
24 20 12
12 24 8
6 25 16
9 25 2
19 21 23
12 24 11
20 21 16
20 21 20
24 20 18
11 24 15
22 21 15
7 26 11
16 24 7
17 22 19
17 24 8
16 24 12
18 21 33
25 20 24
13 24 24
15 24 16
12 25 21
16 26 4
20 24 7
16 25 15
15 26 13
16 25 19
20 25 12
20 24 20
20 25 16
12 28 8
11 28 11
11 28 16
16 28 8
16 28 12
22 27 4
12 29 21
16 28 16
18 27 24
20 28 7
19 28 12
24 27 9
17 28 28
20 28 16
22 27 18
23 27 21
24 27 18
18 28 21
16 30 17
22 28 11
21 28 22
12 32 9
30 26 11
12 32 18
21 28 33
21 29 25
24 28 26
35 25 16
18 33 11
17 31 35
18 33 18
17 33 24
23 33 12
24 33 18
19 36 7
25 34 24
17 36 30
19 37 16
27 33 33
21 35 39
29 33 43
32 35 18
32 35 26
21 38 45
35 37 12
26 39 31
23 41 19
26 40 26
37 36 33
20 43 25
25 40 49
33 41 15
32 39 43
27 44 13
34 41 25
42 40 23
26 43 55
28 44 40
34 44 24
37 43 35
33 49 29
44 49 23

View File

@@ -0,0 +1,9 @@
1
0
319
0
199
0
0
0

View File

@@ -0,0 +1,7 @@
1
0
319
0
199
0

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -0,0 +1,241 @@
239
0 0 0
10 10 10
10 10 10
11 11 11
11 11 11
12 12 12
13 13 13
13 13 13
13 13 13
13 13 13
14 14 14
14 14 14
14 14 14
15 15 15
15 15 15
15 15 15
15 15 15
16 16 16
16 16 16
16 16 16
16 16 16
17 17 17
17 17 17
17 17 17
17 17 17
18 18 18
18 18 18
18 18 18
18 18 18
19 19 19
19 19 19
19 19 19
19 19 19
20 20 20
20 20 20
20 20 20
20 20 20
21 21 21
21 21 21
21 21 21
21 21 21
22 22 22
22 22 22
22 22 22
22 22 22
23 23 23
23 23 23
23 23 23
23 23 23
24 24 24
24 24 24
24 24 24
24 24 24
25 25 25
25 25 25
25 25 25
25 25 25
26 26 26
26 26 26
26 26 26
26 26 26
27 27 27
27 27 27
27 27 27
27 27 27
28 28 28
28 28 28
28 28 28
28 28 28
29 29 29
29 29 29
29 29 29
29 29 29
30 30 30
30 30 30
30 30 30
30 30 30
31 31 31
31 31 31
31 31 31
31 31 31
32 32 32
32 32 32
32 32 32
32 32 32
33 33 33
33 33 33
33 33 33
33 33 33
34 34 34
34 34 34
34 34 34
34 34 34
35 35 35
35 35 35
35 35 35
35 35 35
36 36 36
36 36 36
36 36 36
36 36 36
37 37 37
37 37 37
37 37 37
37 37 37
38 38 38
38 38 38
38 38 38
38 38 38
39 39 39
39 39 39
39 39 39
39 39 39
40 40 40
40 40 40
40 40 40
40 40 40
41 41 41
41 41 41
41 41 41
41 41 41
42 42 42
42 42 42
42 42 42
42 42 42
43 43 43
43 43 43
43 43 43
43 43 43
44 44 44
44 44 44
44 44 44
44 44 44
45 45 45
45 45 45
45 45 45
45 45 45
46 46 46
46 46 46
46 46 46
46 46 46
47 47 47
47 47 47
47 47 47
47 47 47
48 48 48
48 48 48
48 48 48
48 48 48
49 49 49
49 49 49
49 49 49
49 49 49
50 50 50
50 50 50
50 50 50
50 50 50
51 51 51
51 51 51
51 51 51
51 51 51
52 52 52
52 52 52
52 52 52
52 52 52
53 53 53
53 53 53
53 53 53
53 53 53
54 54 54
54 54 54
54 54 54
54 54 54
55 55 55
55 55 55
55 55 55
55 55 55
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0

View File

@@ -0,0 +1,9 @@
1
0
319
0
199
0
0
0

View File

@@ -0,0 +1,87 @@
This tool can be used to generate Mission Supernova 2 datafiles containing images
and might be able to do the same even for Mission Supernova 1.
The tool is not foolproof and a lot of checks are missing (since it's just a tool),
so it could easily generate nonsense without any warning if for example command line
arguments aren't as expected.
To use this tool create a folder named as the number of the datafile you want to
create, it should be 3 characters long, add required numbers of zeros to the beginning
of the name (015 for ms2_data.015).
Inside this folder should be:
--clickfield_info, this contains info about clickfields. On the first row should be a
number saying how many clickfields there are and on the following rows are
descripitons of individual clickfields in this order (x1, x2, y1, y2, next),
for example:
2
123
134
49
63
0
135
146
49
63
0
This would be the contents of a file describing 2 clickfields.
--section_info similar to the clickfield_info. Contains info about sections. On the
first row should be a number saying how many sections there are and on the following
rows are descripitons of individual sections in this order
(x1, x2, y1, y2, next, addressLow, addressHigh), for example:
2
0
319
0
137
0
0
0
123
134
49
62
0
44160
0
This would be the contents of a file describing 2 sections
--palette Contains info about palette. On the first row should be a number saying
how many colors there are and on the following rows are the individual RGB values of
colors (don't forget, that the engine shifts each color by 2 places to the left
(brightening the image), so the palette basically has to be shifted by 2 to the right
to get the right colors). For example:
3
50 50 50
0 0 0
28 25 20
This would be the contents of a file containing palette with 3 colors.
--image#.bmp For each section, there has to be image#.bmp, replace the '#' by the
number of section this image belongs to. The image has to use indexes to the palette
for storing the color of each pixel (Image -> Mode -> Indexed... in gimp).
Running the tool
The tool needs 3 comand line arguments when running it:
-- Prefix of the file to be created (use "ms2_data" to create "ms2_data.###")
-- Number of the file to be created and also the number of a folder to read all the
files from (use "15" to create prefix.015)
-- Number of bytes to skip in each .bmp file. At the beginning of each .bmp file is
a header with information about the file and after that is stored the palette. This
tool doesn't need these, so this number says how many bytes to skip to get to the pixel
data. For example: use 1146 to generate ms2_data.015 from the files included.
Be aware, this tool does only basic checks of comandline arguments and no checks of
the input files (only their presence).

View File

@@ -0,0 +1,202 @@
#include <fstream>
#include <iostream>
#include <sstream>
#include <cstring>
#include <iomanip>
#include <cstdlib>
std::string *filenumber;
int writePalette(std::ofstream &output) {
std::string filename = *filenumber + "/palette";
std::ifstream palette(filename.c_str());
if (!palette.is_open()) {
std::cerr << "Couldn't open palette file" << std::endl;
return 1;
}
int input;
do {
palette >> input;
if (palette.eof())
break;
output << (char) input;
} while(true);
palette.close();
return 0;
}
int writeSections(std::ofstream &output) {
std::string filename = *filenumber + "/section_info";
std::ifstream sectionInfo(filename.c_str());
if (!sectionInfo.is_open()) {
std::cerr << "Couldn't open section_info file" << std::endl;
return 0;
}
int numSections;
sectionInfo >> numSections;
output << (char) numSections;
int input;
char *input_byte = (char *) &input;
for(int i = 0; i < numSections; i++) {
//x1
sectionInfo >> input;
output << (char)input_byte[0];
output << (char)input_byte[1];
//x2
sectionInfo >> input;
output << (char)input_byte[0];
output << (char)input_byte[1];
//y1
sectionInfo >> input;
output << (char)input;
//y2
sectionInfo >> input;
output << (char)input;
//next
sectionInfo >> input;
output << (char)input;
//addressLow
sectionInfo >> input;
output << (char)input_byte[0];
output << (char)input_byte[1];
//addressHigh
sectionInfo >> input;
output << (char)input;
}
sectionInfo.close();
return numSections;
}
int writeClickFields(std::ofstream &output) {
std::string filename = *filenumber + "/clickfield_info";
std::ifstream clickFieldInfo(filename.c_str());
if (!clickFieldInfo.is_open()) {
std::cerr << "Couldn't open clickfield_info file" << std::endl;
return 1;
}
int numClickFields;
clickFieldInfo >> numClickFields;
output << (char) numClickFields;
int input;
char *input_byte = (char *) &input;
for(int i = 0; i < numClickFields; i++) {
//x1
clickFieldInfo >> input;
output << (char)input_byte[0];
output << (char)input_byte[1];
//x2
clickFieldInfo >> input;
output << (char)input_byte[0];
output << (char)input_byte[1];
//y1
clickFieldInfo >> input;
output << (char)input;
//y2
clickFieldInfo >> input;
output << (char)input;
//next
clickFieldInfo >> input;
output << (char)input;
}
clickFieldInfo.close();
return 0;
}
int writePixelData(std::ofstream &output, int imageNum, int skip) {
std::ostringstream fileName;
fileName << *filenumber << "/image" << imageNum << ".bmp";
std::ifstream image(fileName.str().c_str(), std::ios::binary);
if (!image.is_open()) {
std::cerr << "Couldn't open " << fileName.str() << " file" << std::endl;
return 0;
}
image.seekg(0, image.end);
int length = image.tellg();
length -= skip;
image.seekg(skip, image.beg);
char *buf = new char[length];
image.read(buf, length);
output.write(buf, length);
delete[] buf;
return length;
}
void printHelp() {
std::cout << "create_image output-prefix file-number bytes-skip" << std::endl << std::endl;
std::cout << " output-prefix: String the created file should begin with" << std::endl;
std::cout << " file-number: Number of the created file and also name of source folder" << std::endl;
std::cout << " bytes-skip: How many bytes to skip in each .bmp file" << std::endl;
std::cout << std::endl << "EXAMPLE:" << std::endl
<< "create_image ms2_data 15 1146" << std::endl
<< " creates ms2_data.015 assuming there are the right files inside 015 folder" << std::endl;
}
int main(int argc, char *argv[]) {
if (argc == 2 && !strcmp(argv[1], "--help")) {
printHelp();
return 0;
}
if (argc != 4 ) {
printHelp();
return 1;
}
std::ostringstream oss;
oss << std::setfill('0') << std::setw(3) << argv[2];
*filenumber = oss.str();
char *ptr;
int bytesSkip = strtol(argv[3], &ptr, 10);
std::string oFileName = argv[1];
oFileName += "." + *filenumber;
std::ofstream output(oFileName.c_str(), std::ios::binary);
if (!output.is_open()) {
std::cerr << "Couldn't open output file" << std::endl;
return 1;
}
// size
// just a place holder, will be filled later
output << (char) 0x40;
output << (char) 0x70;
output << (char) 0x01;
output << (char) 0x00;
if (writePalette(output))
return 1;
int numImages = writeSections(output);
if (numImages == 0)
return 1;
if (writeClickFields(output))
return 1;
// we don't compress the images, so set to 0
output << (char) 0; //numRepeat
output << (char) 0; //numZw
int totalLength = 0;
int oldLength = 0;
for (int i = 0; i < numImages; i++) {
totalLength += writePixelData(output, i, bytesSkip);
if (oldLength == totalLength) {
std::cerr << "Error while reading the image number: " << i << std::endl;
return 1;
}
oldLength = totalLength;
}
//reversing the size computation inside the engine
totalLength += 15;
totalLength /= 16;
totalLength -= 0x70;
int i = (totalLength & 0xf000) >> 12;
int j = totalLength << 4;
char *i_p = (char *) &i;
char *j_p = (char *) &j;
//writing the size
output.seekp(0);
output << j_p[0];
output << j_p[1];
output << i_p[0];
output << i_p[1];
output.close();
return 0;
}

View File

@@ -0,0 +1,3 @@
#!/bin/sh
./create_image ms2_data 15 1146

View File

@@ -0,0 +1,3 @@
#!/bin/sh
./create_image ms2_data 27 1146

View File

@@ -0,0 +1,3 @@
#!/bin/sh
./create_image ms2_data 28 829

View File

@@ -0,0 +1,10 @@
MODULE := devtools/create_supernova/create_image
MODULE_OBJS := create_image.o
# Set the name of the executable
TOOL_EXECUTABLE := create_image
# Include common rules
include $(srcdir)/rules.mk

View File

@@ -0,0 +1,402 @@
#include "create_supernova.h"
#include "gametext.h"
#include "file.h"
#include "po_parser.h"
#include <iostream>
// List of languages to look for. To add new languages you only need to change the array below
// and add the supporting files:
// - 640x480 bitmap picture for the newpaper named 'img1-##.pbm' and 'img2-##.pbm'
// in pbm binary format (you can use gimp to generate those)
// - strings in a po file named 'strings-##.po' that uses CP850 encoding
const char *lang[] = {
"en",
"it",
nullptr
};
void writeDatafile(File& outputFile, int fileNumber, const char* language, int part) {
File dataFile;
char fileName[20];
if (part == 1)
sprintf(fileName, "msn_data.%03d-%s", fileNumber, language);
if (part == 2)
sprintf(fileName, "ms2_data.%03d-%s", fileNumber, language);
if (!dataFile.open(fileName, kFileReadMode)) {
printf("Cannot find dataFile %s. This file will be skipped.\n", fileName);
return;
}
// Write block header in output file (4 bytes).
// M(fileNumber) for example M015
char number[4];
sprintf(number, "%03d", fileNumber);
outputFile.writeByte('M');
for (int i = 0 ; i < 3 ; ++i) {
outputFile.writeByte(number[i]);
}
// And write the language code on 4 bytes as well (padded with 0 if needed).
int languageLength = strlen(language);
for (int i = 0 ; i < 4 ; ++i) {
if (i < languageLength)
outputFile.writeByte(language[i]);
else
outputFile.writeByte(0);
}
// Write block size
dataFile.seek(0, SEEK_END);
int length = dataFile.pos();
dataFile.seek(0, SEEK_SET);
outputFile.writeLong(length);
// Write all the bytes. We should have w * h / 8 bytes
// However we need to invert the bits has the engine expects 1 for the background and 0 for the text (black)
// but pbm uses 0 for white and 1 for black.
for (int i = 0 ; i < length; ++i) {
byte b = dataFile.readByte();
outputFile.writeByte(b);
}
dataFile.close();
}
void writeDocFile(File& outputFile, const char *fileExtension, const char* language, int part) {
File docFile;
char fileName[20];
if (part == 1)
sprintf(fileName, "msn.%s-%s", fileExtension, language);
if (part == 2)
sprintf(fileName, "ms2.%s-%s", fileExtension, language);
if (!docFile.open(fileName, kFileReadMode)) {
printf("Cannot find file '%s'. This file will be skipped.\n", fileName);
return;
}
// Write block header in output file (4 bytes).
// We convert the file extension to upper case.
for (int i = 0 ; i < 3 ; ++i) {
if (fileExtension[i] >= 97 && fileExtension[i] <= 122)
outputFile.writeByte(fileExtension[i] - 32);
else
outputFile.writeByte(fileExtension[i]);
}
outputFile.writeByte((char) part + '0');
// And write the language code on 4 bytes as well (padded with 0 if needed).
int languageLength = strlen(language);
for (int i = 0 ; i < 4 ; ++i) {
if (i < languageLength)
outputFile.writeByte(language[i]);
else
outputFile.writeByte(0);
}
// Write block size
docFile.seek(0, SEEK_END);
int length = docFile.pos();
docFile.seek(0, SEEK_SET);
outputFile.writeLong(length);
// Write all the bytes.
for (int i = 0 ; i < length; ++i) {
byte b = docFile.readByte();
outputFile.writeByte(b);
}
docFile.close();
}
void writeImage(File& outputFile, const char *name, const char* language) {
File imgFile;
char fileName[16];
sprintf(fileName, "%s-%s.pbm", name, language);
if (!imgFile.open(fileName, kFileReadMode)) {
printf("Cannot find image '%s' for language '%s'. This image will be skipped.\n", name, language);
return;
}
char str[256];
// Read header (and check we have a binary PBM file)
// See https://netpbm.sourceforge.net/doc/pbm.html
// Header is in the form:
// - A "magic number" for identifying the file type ("P4" for binary pdm)
// - Whitespace (blanks, TABs, CRs, LFs).
// - The width in pixels of the image, formatted as ASCII characters in decimal.
// - Whitespace.
// - The height in pixels of the image, again in ASCII decimal.
// - A single whitespace character (usually a newline).
// - The raster data.
// Before the whitespace character that delimits the raster, any characters from a "#"
// through the next carriage return or newline character, is a comment and is ignored.
// Note that the comment can starts in the middle of a line. Note also that if you have
// a comment right before the raster, the newline at the end of the comment is not
// sufficient to delimit the raster.
int w = 0, h = 0;
enum PbmState { PbmMagic, PbmWidth, PbmHeight};
PbmState state = PbmMagic;
int i = 0;
do {
char c = (char)imgFile.readByte();
if (c == '#') {
do {
c = (char)imgFile.readByte();
} while (c != '\r' && c != '\n' && !imgFile.eof());
// If the comment is after the height, we need to read one more character
// before the raster data begin.
if (state == PbmHeight && i > 0)
c = (char)imgFile.readByte();
}
if (isspace(c)) {
if (i > 0) {
str[i] = 0;
i = 0;
if (state == PbmMagic) {
if (strcmp(str, "P4") != 0) {
imgFile.close();
printf("File '%s' doesn't seem to be a binary pbm file! This image will be skipped.\n", fileName);
return;
}
} else {
int *s = state == PbmWidth ? &w : &h;
if (sscanf(str, "%d", s) != 1) {
imgFile.close();
printf("Failed to read image size in binary pbm file '%s'. This image will be skipped.\n", fileName);
return;
}
}
if (state == PbmMagic)
state = PbmWidth;
else if (state == PbmWidth)
state = PbmHeight;
else {
// We have finished reading the header.
// Check the size is as expected.
if (w != 640 || h != 480) {
imgFile.close();
printf("Binary pbm file '%s' doesn't have the expected size (expected: 640x480, read: %dx%d). This image will be skipped.\n", fileName, w, h);
return;
}
// And break out of the loop.
break;
}
}
} else
str[i++] = c;
if (imgFile.eof()) {
imgFile.close();
printf("Unexpected end of file in '%s' while reading pbm header! This image will be skipped.\n", fileName);
return;
}
} while (1);
// Write block header in output file (4 bytes).
// We convert the image name to upper case.
for (i = 0 ; i < 4 ; ++i) {
if (name[i] >= 97 && name[i] <= 122)
outputFile.writeByte(name[i] - 32);
else
outputFile.writeByte(name[i]);
}
// And write the language code on 4 bytes as well (padded with 0 if needed).
int languageLength = strlen(language);
for (i = 0 ; i < 4 ; ++i) {
if (i < languageLength)
outputFile.writeByte(language[i]);
else
outputFile.writeByte(0);
}
// Write block size (640*480 / 8)
outputFile.writeLong(38400);
// Write all the bytes. We should have 38400 bytes (640 * 480 / 8)
// However we need to invert the bits has the engine expects 1 for the background and 0 for the text (black)
// but pbm uses 0 for white and 1 for black.
for (i = 0 ; i < 38400 ; ++i) {
byte b = imgFile.readByte();
outputFile.writeByte(~b);
}
imgFile.close();
}
void writeGermanStrings(File& outputFile, int part) {
// Write header and language
outputFile.write("TEXT", 4);
outputFile.write("de\0\0", 4);
// Reserve the size for the block size, but we will write it at the end once we know what it is.
uint32 blockSizePos = outputFile.pos();
uint32 blockSize = 0;
outputFile.writeLong(blockSize);
// Write all the strings
const char **s;
if (part == 1)
s = &gameText1[0];
if (part == 2)
s = &gameText2[0];
while (*s) {
outputFile.writeString(*s);
blockSize += strlen(*s) + 1;
++s;
}
// Now write the block size and then go back to the end of the file.
outputFile.seek(blockSizePos, SEEK_SET);
outputFile.writeLong(blockSize);
outputFile.seek(0, SEEK_END);
}
void writeStrings(File& outputFile, const char* language, int part) {
char fileName[16];
sprintf(fileName, "strings%d-%s.po", part, language);
PoMessageList* poList = parsePoFile(fileName);
if (!poList) {
printf("Cannot find strings%d file for language '%s'.\n", part, language);
return;
}
// Write block header
outputFile.write("TEXT", 4);
// And write the language code on 4 bytes as well (padded with 0 if needed).
int languageLength = strlen(language);
for (int i = 0 ; i < 4 ; ++i) {
if (i < languageLength)
outputFile.writeByte(language[i]);
else
outputFile.writeByte(0);
}
// Reserve the size for the block size, but we will write it at the end once we know what it is.
uint32 blockSizePos = outputFile.pos();
uint32 blockSize = 0;
outputFile.writeLong(blockSize);
// Write all the strings.
// If a string is not translated we use the German one.
const char **s;
if (part == 1)
s = &gameText1[0];
if (part == 2)
s = &gameText2[0];
while (*s) {
const char* translation = poList->findTranslation(*s);
if (translation) {
outputFile.writeString(translation);
blockSize += strlen(translation) + 1;
} else {
outputFile.writeString(*s);
blockSize += strlen(*s) + 1;
}
++s;
}
delete poList;
// Now write the block size and then go back to the end of the file.
outputFile.seek(blockSizePos, SEEK_SET);
outputFile.writeLong(blockSize);
outputFile.seek(0, SEEK_END);
}
void writeMS1(File &outputFile) {
// First part
outputFile.writeByte(1);
// Reserve space for game block size
uint32 blockSizePos = outputFile.pos();
uint32 blockSize = 0;
outputFile.writeLong(blockSize);
// German strings
writeGermanStrings(outputFile, 1);
// Other languages
const char **l = &lang[0];
while(*l) {
writeImage(outputFile, "img1", *l);
writeImage(outputFile, "img2", *l);
writeStrings(outputFile, *l, 1);
writeDocFile(outputFile, "inf", *l, 1);
writeDocFile(outputFile, "doc", *l, 1);
++l;
}
blockSize = outputFile.pos() - blockSizePos - 4;
outputFile.seek(blockSizePos, SEEK_SET);
outputFile.writeLong(blockSize);
outputFile.seek(0, SEEK_END);
}
void writeMS2(File &outputFile) {
// Second part
outputFile.writeByte(2);
// Reserve space for game block size
uint32 blockSizePos = outputFile.pos();
uint32 blockSize = 0;
outputFile.writeLong(blockSize);
// German strings
writeGermanStrings(outputFile, 2);
// Other languages
const char **l = &lang[0];
while(*l) {
writeImage(outputFile, "img3", *l);
writeDatafile(outputFile, 15, *l, 2);
writeDatafile(outputFile, 27, *l, 2);
writeDatafile(outputFile, 28, *l, 2);
writeStrings(outputFile, *l, 2);
writeDocFile(outputFile, "inf", *l, 2);
writeDocFile(outputFile, "doc", *l, 2);
++l;
}
blockSize = outputFile.pos() - blockSizePos - 4;
outputFile.seek(blockSizePos, SEEK_SET);
outputFile.writeLong(blockSize);
outputFile.seek(0, SEEK_END);
}
/**
* Main method
*/
int main(int argc, char *argv[]) {
File outputFile;
if (!outputFile.open("supernova.dat", kFileWriteMode)) {
printf("Cannot create file 'supernova.dat' in current directory.\n");
exit(0);
}
// The generated file is of the form:
// 3 bytes: 'MSN'
// 1 byte: version
// - game blocks
// 1 byte: part (1 or 2)
// 4 bytes: game block size
// -- data blocks
// 4 bytes: header 'IMG1' and 'IMG2' for newspaper images (for file 1 and file 2 respectively),
// 'TEXT' for strings
// 4 bytes: language code ('en\0', 'de\0'- see common/language.cpp)
// 4 bytes: block size n (uint32)
// n bytes: data
// --
// -
// Header
outputFile.write("MSN", 3);
outputFile.writeByte(VERSION);
writeMS1(outputFile);
writeMS2(outputFile);
outputFile.close();
return 0;
}

View File

@@ -0,0 +1,32 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* This is a utility for generating a data file for the supernova engine.
* It contains strings extracted from the original executable as well
* as translations and is required for the engine to work properly.
*/
#ifndef CREATE_SUPERNOVA_H
#define CREATE_SUPERNOVA_H
#define VERSION 4
#endif // CREATE_SUPERNOVA_H

View File

@@ -0,0 +1,66 @@
#include "file.h"
bool File::open(const char *filename, AccessMode mode) {
f = fopen(filename, (mode == kFileReadMode) ? "rb" : "wb");
return (f != nullptr);
}
void File::close() {
fclose(f);
f = nullptr;
}
int File::seek(int32 offset, int whence) {
return fseek(f, offset, whence);
}
long File::read(void *buffer, int len) {
return fread(buffer, 1, len, f);
}
void File::write(const void *buffer, int len) {
fwrite(buffer, 1, len, f);
}
bool File::eof() {
return feof(f) != 0;
}
byte File::readByte() {
byte v;
read(&v, sizeof(byte));
return v;
}
uint16 File::readWord() {
uint16 v;
read(&v, sizeof(uint16));
return FROM_LE_16(v);
}
uint32 File::readLong() {
uint32 v;
read(&v, sizeof(uint32));
return FROM_LE_32(v);
}
void File::writeByte(byte v) {
write(&v, sizeof(byte));
}
void File::writeWord(uint16 v) {
uint16 vTemp = TO_LE_16(v);
write(&vTemp, sizeof(uint16));
}
void File::writeLong(uint32 v) {
uint32 vTemp = TO_LE_32(v);
write(&vTemp, sizeof(uint32));
}
void File::writeString(const char *s) {
write(s, strlen(s) + 1);
}
uint32 File::pos() {
return ftell(f);
}

View File

@@ -0,0 +1,58 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* This is a utility for generating a data file for the supernova engine.
* It contains strings extracted from the original executable as well
* as translations and is required for the engine to work properly.
*/
#ifndef FILE_H
#define FILE_H
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/endian.h"
enum AccessMode {
kFileReadMode = 1,
kFileWriteMode = 2
};
class File {
private:
FILE *f;
public:
bool open(const char *filename, AccessMode mode = kFileReadMode);
void close();
int seek(int32 offset, int whence = SEEK_SET);
uint32 pos();
long read(void *buffer, int len);
void write(const void *buffer, int len);
bool eof();
byte readByte();
uint16 readWord();
uint32 readLong();
void writeByte(byte v);
void writeWord(uint16 v);
void writeLong(uint32 v);
void writeString(const char *s);
};
#endif // FILE_H

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,15 @@
MODULE := devtools/create_supernova
MODULE_OBJS := \
file.o \
po_parser.o \
create_supernova.o
# Set the name of the executable
TOOL_EXECUTABLE := create_supernova
# Include common rules
include $(srcdir)/rules.mk
include $(srcdir)/devtools/create_supernova/create_image/module.mk
.PHONY: $(srcdir)/devtools/create_supernova/create_image/module.mk

View File

@@ -0,0 +1,34 @@
Mission Supernova - Part 2: The Doppelg„nger
--------------------------------------
Press F1 during the game for help. You can run SETUP.BAT,
to change the sound settings. If you have problems with the
game (especially with the sound), read the PROBLEME.TXT
file.
You can find detailed instructions on how to use the program
in the game 1st part.
Special passages in part 2:
-----------------------
1. Pyramid
---------
During the game you will get into a pyramid at one point. It
is advisable to draw a map of the corridors of the pyramid.
The control there is a bit different than usual. The exit
window turns into a compass. If you click with the mouse on
the right edge of the screen, you turn to the right. However,
you remain in the same place.
Click on the left edge to turn to the left. When you turn,
the compass rotates at the same time, so that you always
know in which direction you are looking.
You can move around by clicking in the middle of the screen.
You will then always go one room further.
2. Museum
--------
Further into the game, at one point you will have to break
into a museum. During the burglary you cannot save the game,
but you can load a previously saved game. This time the exit
window changes into a clock. You must therefore always click
on the exits in the room view itself.

View File

@@ -0,0 +1,18 @@
Mission Supernova - Part 2: The Doppelg„nger
--------------------------------------
The game MISSION SUPERNOVA was created in 1992-94 and was
distributed as shareware. It consists of two parts, the
first of which could be freely copied and distributed. The
second part of the game was only available for registered
users.
However both parts are now freely copyable and available on
the internet at :
http://www.simplicity.de/
Copyright 1994, 1995 Thomas and Steffen Dingel
Musik: Bernd Hoffmann

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,93 @@
Instructions
--------
In this game you take over the role of Horst Hummel, the
ship's cook of the "Supernova". You can determine his actions
by clicking on commands with the mouse.
Press F1 during the game for help. You can run SETUP.BAT to
change the sound settings.
If you have problems with the game (especially with the
sound) read the PROBLEME.TXT file.
1. Commands selection
------------------
A command is composed of 1 verb and 1 or 2 objects.
You can select a verb by clicking on the desired verb in the
command bar (e.g. Look, Take). It will then appear in the
line above the command bar. This is the record line (it
contains the current command that you are building).
You can select an object in two different ways:
-You click on an object in the graphics window. Important
items in the graphics window appear in the record line when
you move the mouse over them.
-You click on an item in your inventory. Your inventory is
located at the bottom of the screen. There you will see all
the items you carry with you. You can take as many items as
you want during the game. If you have more than 8 items,
arrows will appear to the right of the inventory. With these
arrows you can scroll the list.
If you have selected a verb and an object, the command is
usually executed.
Examples: Open Hatch
Look Chessboard
Take Chessboard
Look Keycard
You can try these examples directly in the room in which
you start the game.
The verb "Use" sometimes requires 2 objects. The verb "Give"
always requires 2 objects.
Example: You are in the room in which you start the game.
Select the verb "Use" and as object the keycard
from your inventory. The sentence line says:
"Use keycard with". Now click on the slot of the
middle cabinet to open the cabinet.
Additional information about the commands:
-After a command has been executed, the game always
switches to the verb "Go to".
-Some actions can be simplified by pressing the right mouse
button:
-Opening and closing hatches/doors etc.
-Pushing buttons.
-Talking with people.
-Looking at objects.
Example: You want to open a closed hatch.
Move the mouse over the hatch and press the right
mouse button. The hatch opens. If you press the
right mouse button again, the hatch closes.
For objects where it is not quite obvious that you can open,
close, push or talk to them, pressing the right mouse button
automatically executes the command "Look".
2. Moving around
-------------
You can move around in two ways.
-Click a box in the small area at the bottom right of the
screen while selecting the Go To command. The boxes
symbolize the exits of the room you are in.
-You can also click on an exit directly in the graphics
window (e.g. an open hatch).
Important: The graphics window does not always show all the
exits that a room really has. Some exits can only
be used in the exit view at the bottom right.
3. Load/save
-----------
You can save or load a game at any time. To do this, press
"F5". A menu appears.
If you want to save a game, select one of the 10 slots with
the mouse or the arrow keys. Then type in a name
under which you want to save the game and click on "Save".
To load a savegame, simply click on the desired savegame and
then on "Load".
4. Talking to other creatures
----------------------------
Later in the game you will meet other creatures. When talking
to them you have different questions/answers. Select one of
these options with the mouse.

View File

@@ -0,0 +1,103 @@
Istruzioni
--------
In questo gioco impersoni Horst Hummel, il cuoco di bordo
della "Supernova". Puoi decidere le sue azioni cliccando
con il mouse sui comandi visualizzati a schermo.
Premi F1 durante il gioco per aprire la schermata di aiuto.
Puoi anche avviare SETUP.BAT per modificare le impostazioni
del suono.
In caso di problemi con il gioco (specialmente per l'audio)
consulta il file PROBLEME.TXT.
1. Selezione dei comandi
--------------------
Un comando e` costituito da un verbo ed 1 o 2 oggetti.
Puoi selezionare un verbo cliccando nella barra dei comandi
(es. Guarda, Prendi). Il verbo prescelto apparira` quindi
nella riga sovrastante la barra dei comandi. Questa riga
funge da "registro" per tenere traccia del comando che stai
costruendo.
Puoi selezionare un oggetto in due modi:
-Cliccandoci sopra nella schermata grafica. Gli oggetti
importanti vengono indicati nella riga-registro quando
passi sopra il puntatore.
-Cliccando su un oggetto nell'inventario. L'inventario si
trova in basso sullo schermo e mostra tutti gli oggetti
che stai portando con te. Puoi raccogliere tutti gli
oggetti che desideri. Se possiedi piu` di otto oggetti,
verranno visualizzate delle freccette sulla destra, che
puoi usare per scorrere la lista completa.
Dopo avere selezionato un verbo ed un oggetto, l'azione
prescelta verra` subito eseguita (solitamente).
Esempi:
Apri Portello
Guarda Scacchiera
Prendi Scacchiera
Guarda Tesserino
Puoi provare questi esempi nella stanza dove inizia il
gioco.
Il verbo "Usa" talvolta richiede due oggetti. Il verbo "Dai"
richiede sempre due "oggetti".
Esempio:
Ti trovi nella stanza dove inizia il gioco.
Seleziona il verbo "Usa" e l'oggetto "Tesserino"
dal tuo inventario. La riga del testo indichera`
"Usa Tesserino con". Ora clicca sullo slot
dell'armadietto centrale per aprirlo.
Informazioni aggiuntive per i comandi:
-Dopo avere eseguito un comando, il gioco passa sempre al
verbo "Vai verso".
-Alcune azioni possono essere svolte piu` rapidamente
premendo il tasto destro del mouse:
-Aprire e chiudere sportelli/porte...
-Premere pulsanti
-Parlare con persone
-Guardare oggetti
Esempio:
Desideri aprire un portello chiuso.
Sposta il puntatore del mouse sopra al portello
e premi il tasto destro. Il portello si aprira`.
Premendo di nuovo il tasto destro, il portello
si richiudera`.
Se un oggetto non presenta possibilita` EVIDENTI di
essere aperto, chiuso, spinto o interrogato, premendo il
tasto destro verra` automaticamente eseguito il comando
"Guarda".
2. Movimento
----------
Puoi spostarti in due modi.
-Cliccando uno dei quadratini nell'area in basso a destra
dello schermo, quando il comando "Vai" e` selezionato.
I quadratini rappresentano le possibili uscite dalla stanza
dove ti trovi.
-Puoi anche cliccare su di un'uscita direttamente nella
schermata grafica (per es. un portello aperto).
Importante: La schermata grafica non mostra sempre tutte
le uscite di una stanza. Alcune uscite
potrebbero essere accessibili solo tramite la
"mappa" in basso a destra.
3. Salvataggio/Caricamento
-----------------------
Puoi salvare o caricare il gioco in qualsiasi momento. Per
fare cio`, premi "F5". Apparira` un menu`.
Per salvare il gioco, seleziona una delle 10 posizioni con
il mouse o le frecce direzionali. Quindi inserisci un nome
per il salvataggio e clicca "salva".
Per caricare, clicca semplicemente sul salvataggio
desiderato e quindi clicca su "carica".
4. Parlare con altre creature
-------------------------
Proseguendo nel gioco incontrerai altre creature. Parlando
con loro avrai a disposizione diverse domande e risposte.
Selezionale usando il mouse.

View File

@@ -0,0 +1,58 @@
Program information
-------------------
The 1st part of the game "Mission Supernova" is shareware,
i.e. you may and should copy and distribute it to others.
If you like the game, register for 30,- DM!
Advantages for registered users:
------------------------------
- You will receive the 2nd part of the game.
In "Part 2 - The Doppelg„nger" you will find
- more tricky puzzles
- Superjokes and surprises
- even more graphics and sound
- You also get a help system on floppy disk for both parts
of "Mission Supernova". The help system contains the
solutions to all puzzles in the game. So if you are stuck
somewhere in the 1st part, you can look there.
The 2nd part of the game is not available as shareware, it
is for registered users only!
Send the registrations to:
Steffen Dingel
Idsteiner Str. 5
57074 Siegen
If possible, use the registration form ("REGISTER.TXT")
that you can print by pressing "D" now.
Be sure to specify the following:
- name
- address
- desired disk format
(5.25"/1.2MB or 3.5"/1.44MB)
You have the following options to pay the registration fee
of 30,- DM:
- payment by cheque
- cash (no stamps)
- bank transfer (advance payment) to account 1794379 at
Sparkasse Siegen (BLZ 460 500 01)
Registrations are also possible from abroad without
surcharge. The fee must be paid in DM.
Copyright 1994 Thomas and Steffen Dingel
Idsteiner Str. 5
57074 Siegen
Musik: Bernd Hoffmann
Biedenkopfer Str. 34
57072 Siegen

View File

@@ -0,0 +1,60 @@
Informazioni Programma
--------------------
La prima parte del gioco "Mission Supernova" e` shareware,
quindi puoi (devi!) copiarla e distribuirla a chi desideri.
Se il gioco ti piace, registrati per 30,- DM!
Vantaggi per gli utenti registrati:
----------------------------
- Riceverai la seconda parte del gioco.
In "Parte 2 - Il Doppelganger" trovarai:
- nuovi intelligenti puzzle
- situazioni divertenti e sorprese
- ancora piu` schermate ed effetti sonori
- Riceverai inoltre un servizio di aiuto, su floppy disk,
per entrambe le parti di "Mission Supernova". Il sistema
contiene le soluzioni di tutti gli enigmi presenti nel
gioco, quindi anche se sei rimasto bloccato nella prima
parte puoi darci un'occhiata.
La seconda parte del gioco non e` disponibile come shareware
ma solo per gli utenti registrati!
Invia la tua registrazione a:
Steffen Dingel
Idsteiner Str. 5
57074 Siegen
Se possibile, usa il modello di registrazione "REGISTER.TXT"
che puoi stampare premendo "D" ora.
Assicurati di avere specificato:
- nome
- indirizzo
- formato disco desiderato
(5.25"/1.2MB o 3.5"/1.44MB)
Le seguenti opzioni sono disponibili per il pagamento di
30,- DM:
- assegno
- contanti (non francobolli)
- bonifico bancario al conto 1794379 a
Sparkasse Siegen (BLZ 460 500 01)
Le registrazioni sono possibili anche dell'estero senza
sovrapprezzi. Il pagamento deve essere effettuato in DM.
Copyright 1994 Thomas and Steffen Dingel
Idsteiner Str. 5
57074 Siegen
Musica: Bernd Hoffmann
Biedenkopfer Str. 34
57072 Siegen

View File

@@ -0,0 +1,221 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "po_parser.h"
PoMessageList::PoMessageList() : _list(nullptr), _size(0), _allocated(0) {
}
PoMessageList::~PoMessageList() {
for (int i = 0; i < _size; ++i)
delete _list[i];
delete[] _list;
}
int PoMessageList::compareString(const char* left, const char* right) {
if (left == nullptr && right == nullptr)
return 0;
if (left == nullptr)
return -1;
if (right == nullptr)
return 1;
return strcmp(left, right);
}
int PoMessageList::compareMessage(const char *msgLeft, const char *contextLeft, const char *msgRight, const char *contextRight) {
int compare = compareString(msgLeft, msgRight);
if (compare != 0)
return compare;
return compareString(contextLeft, contextRight);
}
void PoMessageList::insert(const char *translation, const char *msg, const char *context) {
if (msg == nullptr || *msg == '\0' || translation == nullptr || *translation == '\0')
return;
// binary-search for the insertion index
int leftIndex = 0;
int rightIndex = _size - 1;
while (rightIndex >= leftIndex) {
int midIndex = (leftIndex + rightIndex) / 2;
int compareResult = compareMessage(msg, context, _list[midIndex]->msgid, _list[midIndex]->msgctxt);
if (compareResult == 0)
return; // The message is already in this list
else if (compareResult < 0)
rightIndex = midIndex - 1;
else
leftIndex = midIndex + 1;
}
// We now have rightIndex = leftIndex - 1 and we need to insert the new message
// between the two (i.a. at leftIndex).
if (_size + 1 > _allocated) {
_allocated += 100;
PoMessage **newList = new PoMessage*[_allocated];
for (int i = 0; i < leftIndex; ++i)
newList[i] = _list[i];
for (int i = leftIndex; i < _size; ++i)
newList[i + 1] = _list[i];
delete[] _list;
_list = newList;
} else {
for (int i = _size - 1; i >= leftIndex; --i)
_list[i + 1] = _list[i];
}
_list[leftIndex] = new PoMessage(translation, msg, context);
++_size;
}
const char *PoMessageList::findTranslation(const char *msg, const char *context) {
if (msg == nullptr || *msg == '\0')
return nullptr;
// binary-search for the message
int leftIndex = 0;
int rightIndex = _size - 1;
while (rightIndex >= leftIndex) {
int midIndex = (leftIndex + rightIndex) / 2;
int compareResult = compareMessage(msg, context, _list[midIndex]->msgid, _list[midIndex]->msgctxt);
if (compareResult == 0)
return _list[midIndex]->msgstr;
else if (compareResult < 0)
rightIndex = midIndex - 1;
else
leftIndex = midIndex + 1;
}
return nullptr;
}
PoMessageList *parsePoFile(const char *file) {
FILE *inFile = fopen(file, "r");
if (!inFile)
return nullptr;
char msgidBuf[1024], msgctxtBuf[1024], msgstrBuf[1024];
char line[1024], *currentBuf = msgstrBuf;
PoMessageList *list = new PoMessageList();
// Initialize the message attributes.
bool fuzzy = false;
bool fuzzy_next = false;
// Parse the file line by line.
// The msgstr is always the last line of an entry (i.e. msgid and msgctxt always
// precede the corresponding msgstr).
msgidBuf[0] = msgstrBuf[0] = msgctxtBuf[0] = '\0';
while (!feof(inFile) && fgets(line, 1024, inFile)) {
if (line[0] == '#' && line[1] == ',') {
// Handle message attributes.
if (strstr(line, "fuzzy")) {
fuzzy_next = true;
continue;
}
}
// Skip empty and comment line
if (*line == '\n' || *line == '#')
continue;
if (strncmp(line, "msgid", 5) == 0) {
if (currentBuf == msgstrBuf) {
// add previous entry
if (*msgstrBuf != '\0' && !fuzzy)
list->insert(msgstrBuf, msgidBuf, msgctxtBuf);
msgidBuf[0] = msgstrBuf[0] = msgctxtBuf[0] = '\0';
// Reset the attribute flags.
fuzzy = fuzzy_next;
fuzzy_next = false;
}
strcpy(msgidBuf, stripLine(line));
currentBuf = msgidBuf;
} else if (strncmp(line, "msgctxt", 7) == 0) {
if (currentBuf == msgstrBuf) {
// add previous entry
if (*msgstrBuf != '\0' && !fuzzy)
list->insert(msgstrBuf, msgidBuf, msgctxtBuf);
msgidBuf[0] = msgstrBuf[0] = msgctxtBuf[0] = '\0';
// Reset the attribute flags
fuzzy = fuzzy_next;
fuzzy_next = false;
}
strcpy(msgctxtBuf, stripLine(line));
currentBuf = msgctxtBuf;
} else if (strncmp(line, "msgstr", 6) == 0) {
strcpy(msgstrBuf, stripLine(line));
currentBuf = msgstrBuf;
} else {
// concatenate the string at the end of the current buffer
if (currentBuf)
strcat(currentBuf, stripLine(line));
}
}
if (currentBuf == msgstrBuf) {
// add last entry
if (*msgstrBuf != '\0' && !fuzzy)
list->insert(msgstrBuf, msgidBuf, msgctxtBuf);
}
fclose(inFile);
return list;
}
char *stripLine(char *const line) {
// This function modifies line in place and return it.
// Keep only the text between the first two unprotected quotes.
// It also look for literal special characters (e.g. preceded by '\n', '\\', '\"', '\'', '\t')
// and replace them by the special character so that strcmp() can match them at run time.
// Look for the first quote
char const *src = line;
while (*src != '\0' && *src++ != '"') {}
// shift characters until we reach the end of the string or an unprotected quote
char *dst = line;
while (*src != '\0' && *src != '"') {
char c = *src++;
if (c == '\\') {
switch (c = *src++) {
case 'n': c = '\n'; break;
case 't': c = '\t'; break;
case '\"': c = '\"'; break;
case '\'': c = '\''; break;
case '\\': c = '\\'; break;
default:
// Just skip
fprintf(stderr, "Unsupported special character \"\\%c\" in string. Please contact ScummVM developers.\n", c);
continue;
}
}
*dst++ = c;
}
*dst = '\0';
return line;
}
char *parseLine(const char *line, const char *field) {
// This function allocate and return a new char*.
// It will return a NULL pointer if the field is not found.
// It is used to parse the header of the po files to find the language name
// and the charset.
const char *str = strstr(line, field);
if (str == nullptr)
return nullptr;
str += strlen(field);
// Skip spaces
while (*str != '\0' && isspace(*str)) {
++str;
}
// Find string length (stop at the first '\n')
int len = 0;
while (str[len] != '\0' && str[len] != '\n') {
++len;
}
if (len == 0)
return nullptr;
// Create result string
char *result = new char[len + 1];
strncpy(result, str, len);
result[len] = '\0';
return result;
}

View File

@@ -0,0 +1,77 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* This is a utility for generating a data file for the supernova engine.
* It contains strings extracted from the original executable as well
* as translations and is required for the engine to work properly.
*/
#ifndef PO_PARSER_H
#define PO_PARSER_H
struct PoMessage {
char *msgstr;
char *msgid;
char *msgctxt;
PoMessage(const char *translation, const char *message, const char *context = NULL) :
msgstr(NULL), msgid(NULL), msgctxt(NULL)
{
if (translation != NULL && *translation != '\0') {
msgstr = new char[1 + strlen(translation)];
strcpy(msgstr, translation);
}
if (message != NULL && *message != '\0') {
msgid = new char[1 + strlen(message)];
strcpy(msgid, message);
}
if (context != NULL && *context != '\0') {
msgctxt = new char[1 + strlen(context)];
strcpy(msgctxt, context);
}
}
~PoMessage() {
delete[] msgstr;
delete[] msgid;
delete[] msgctxt;
}
};
class PoMessageList {
public:
PoMessageList();
~PoMessageList();
void insert(const char *translation, const char *msg, const char *context = NULL);
const char *findTranslation(const char *msg, const char *context = NULL);
private:
int compareString(const char *left, const char *right);
int compareMessage(const char *msgLeft, const char *contextLeft, const char *msgRight, const char *contextRight);
PoMessage **_list;
int _size;
int _allocated;
};
PoMessageList *parsePoFile(const char *file);
char *stripLine(char *);
char *parseLine(const char *line, const char *field);
#endif /* PO_PARSER_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff