-
Notifications
You must be signed in to change notification settings - Fork 0
/
inforead.c
164 lines (147 loc) · 3.92 KB
/
inforead.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/* inforead.c V7/3
*
* Read Infocom data files from an IBM bootable diskette
*
* usage: inforead datafile-name [start-track [drive#]]
*
* datafile-name is required
* start-track is optional (default is 6, should be OK)
* drive# is optional (default is 0 for a:, use 1 for b:)
*
* The data file is extracted starting at track 6 and continues
* for the length of the data area. The data file that is created
* is the correct length and is verified using the checksum in the
* data area.
*
* This only works for type 3 games on IBM 5 1/4" diskettes. I
* believe that all of the bootable Infocom games were type 3.
*
* (Note: Seems to work for 3 1/2" diskettes as well -- S.J.)
*
* Once you have extracted the datafile use the /G switch with
* a type 3 Infocom interpreter, for example:
*
* C> zork1/ginfidel.dat
*
* NB. no space between the /g and the data file name and nothing
* after the data file name.
*
* (Note: Nowadays you will probably want to use one of the freely
* available interpreters such as "Zip" or "Frotz" -- S.J.)
*
* This C program was written with MicroSoft C specifically for the
* IBM PC.
*
* (Note: It also compiles under Borland C -- S.J.)
*
* I also have a CBM 64/128 version of this program for Commodore disks.
*
* Mark Howell 20 January 1992 [email protected]
*
* DJGPP changes provided by Esa A E Peuha <[email protected]> -- MTR
*
*/
#include <bios.h>
#include <stdio.h>
#include <stdlib.h>
#define TRACK_SIZE 4096
int read_track (int drive, int track, unsigned char *tp);
int main (int argc, char *argv[])
{
int track = 6;
int drive = 0;
FILE *fp;
unsigned char *tp;
int i, j, size, status;
unsigned long int glength;
unsigned short gchksum, chksum = 0;
if (argc >= 4)
drive = atoi (argv[3]);
if (drive < 0 || drive > 1) {
fprintf (stderr, "invalid drive #%d\n", drive);
exit (1);
}
if (argc >= 3)
track = atoi (argv[2]);
if (track < 0 || track > 39) {
fprintf (stderr, "invalid track #%d\n", track);
exit (1);
}
if (argc < 2) {
fprintf (stderr, "usage: %s story-file-name [start track [drive]]\n\n", argv[0]);
fprintf (stderr, "INFOREAD version 6/8 - convert Infocom boot disks to files. By Mark Howell\n");
fprintf (stderr, "Works with V3 Infocom games.\n");
exit (1);
}
if ((tp = (unsigned char *) malloc (TRACK_SIZE)) == NULL) {
perror ("malloc");
exit (1);
}
if ((fp = fopen (argv[1], "wb")) == NULL) {
perror ("fopen");
exit (1);
}
for (i = track; i < 40; i++) {
if (status = read_track (drive, i, tp)) {
fprintf (stderr, "error %d from drive #%d, track #%d\n",
status, drive, track);
exit (1);
}
if (i == track) {
glength = ((unsigned) tp[26] * 256) + tp[27];
gchksum = ((unsigned) tp[28] * 256) + tp[29];
glength = (glength * 2) - TRACK_SIZE;
for (j = 64; j < TRACK_SIZE; j++)
chksum += tp[j];
if (fwrite (tp, TRACK_SIZE, 1, fp) != 1) {
perror ("fwrite");
exit (1);
}
} else {
if (glength > TRACK_SIZE) {
size = TRACK_SIZE;
glength -= TRACK_SIZE;
} else {
size = (int) glength;
i = 40;
}
for (j = 0; j < size; j++)
chksum += tp[j];
if (fwrite (tp, (size_t) size, 1, fp) != 1) {
perror ("fwrite");
exit (1);
}
}
}
if (gchksum == chksum)
printf ("game copied OK\n");
else
fprintf (stderr, "game copy failed!\n");
free (tp);
fclose (fp);
exit (0);
return (0);
}/* main */
int read_track (int drive, int track, unsigned char *tp)
{
struct diskinfo_t di;
unsigned int status;
int i;
di.drive = drive;
di.head = 0;
di.track = track;
di.sector = 1;
di.nsectors = 8;
#ifdef __DJGPP
di.buffer = (void *) tp;
#else
di.buffer = (void far *) tp;
#endif
for (i = 0; i < 3; i++) {
status = _bios_disk (_DISK_READ, &di);
if (status == 8)
return (0);
_bios_disk (_DISK_RESET, NULL);
}
return (status >> 8);
}/* read_track */