Tools for working with Cidco Mailstations
1/*
2 * Maildump.cpp
3 * ------------
4 *
5 * This should dump your Mailstation's codeflash or dataflash, in
6 * combination with the codedump.asm or datadump.asm app for the
7 * Mailstation, and a laplink cable of course.
8 *
9 * Basic use would be as follows:
10 * 1.) connect laplink cable to MS and PC
11 * 2.) turn on MS
12 * 3.) run "maildump /code" on PC
13 * 4.) run codedump on MS
14 *
15 * The MS should be on first to ensure parallel port signals are
16 * reset, otherwise your dump could be bad. If you think you
17 * did get a bad dump, it wouldn't hurt to turn the MS off and
18 * on again, waiting for the main menu to show up, just to make
19 * sure it resets itself before you start listening for data.
20 *
21 * A dump of the codeflash should be 1,048,576 bytes (1MB), and named
22 * "codeflash.bin", which is automatically overwritten everytime you run
23 * the program.
24 *
25 * A dump of the dataflash should be 524,288 bytes (512Kb), and named
26 * "dataflash.bin", which is automatically overwritten everytime you run
27 * the program.
28 *
29 * This is based around Cyrano Jones' unit_tribbles in Pascal,
30 * but written to work under Windows (tested under 98 and XP) thanks
31 * to inpout32.dll, which doesn't require a separate driver
32 * to interface with I/O ports. It's pretty useful!
33 *
34 * - FyberOptic (fyberoptic@...)
35 *
36 */
37
38#include <windows.h>
39#include <stdio.h>
40#include <math.h>
41
42#define PORTADDRESS 0x378
43
44#define DATA PORTADDRESS+0
45#define STATUS PORTADDRESS+1
46#define CONTROL PORTADDRESS+2
47
48#define bsyin 0x40
49#define bsyout 0x08
50#define stbin 0x80
51#define stbout 0x10
52#define tribmask 0x07
53#define dibmask 0x03
54
55typedef short (_stdcall *inpfuncPtr)(short portaddr);
56typedef void (_stdcall *oupfuncPtr)(short portaddr, short datum);
57
58inpfuncPtr inp32fp;
59oupfuncPtr oup32fp;
60
61short
62Inp32(short portaddr)
63{
64 return (inp32fp)(portaddr);
65}
66
67void
68Out32(short portaddr, short datum)
69{
70 (oup32fp)(portaddr,datum);
71}
72
73int
74InitIOLibrary(void)
75{
76 HINSTANCE hLib;
77
78 hLib = LoadLibrary("inpout32.dll");
79
80 if (hLib == NULL) {
81 fprintf(stderr,"LoadLibrary Failed.\n");
82 return -1;
83 }
84
85 inp32fp = (inpfuncPtr)GetProcAddress(hLib, "Inp32");
86
87 if (inp32fp == NULL) {
88 fprintf(stderr,"GetProcAddress for Inp32 Failed.\n");
89 return -1;
90 }
91
92 oup32fp = (oupfuncPtr)GetProcAddress(hLib, "Out32");
93
94 if (oup32fp == NULL) {
95 fprintf(stderr,"GetProcAddress for Oup32 Failed.\n");
96 return -1;
97 }
98}
99
100unsigned char
101recvtribble(void)
102{
103 unsigned char mytribble;
104
105 // drop busy/ack
106 Out32(DATA,0);
107
108 // wait for (inverted) strobe
109 while ((Inp32(STATUS) & stbin) != 0)
110 ;
111
112 // grab tribble
113 mytribble = (Inp32(STATUS) >> 3) & tribmask;
114
115 // raise busy/ack
116 Out32(DATA,bsyout);
117
118 // wait for (inverted) UNstrobe
119 while ((Inp32(STATUS) & stbin) == 0)
120 ;
121
122 return mytribble;
123}
124
125int
126main(int argc, void **argv)
127{
128 FILE *pFile;
129 unsigned int received = 0, expected = 0;
130 unsigned char t1, t2, t3, b;
131 char fn[14];
132 int codeflash = 0, dataflash = 0;
133 int x;
134
135 for (x = 1; x < argc; x++) {
136 if (strcmp((char *)argv[x], "/code") == 0)
137 codeflash = 1;
138 else if (strcmp((char *)argv[x], "/data") == 0)
139 dataflash = 1;
140 else
141 printf("unknown parameter: %s\n", argv[x]);
142 }
143
144 if (codeflash == dataflash) {
145 printf("usage: %s [/code | /data]\n", argv[0]);
146 return 1;
147 }
148
149 if (codeflash) {
150 expected = 1024 * 1024;
151 strncpy(fn, "codeflash.bin", sizeof(fn));
152 } else if (dataflash) {
153 expected = 1024 * 512;
154 strncpy(fn, "dataflash.bin", sizeof(fn));
155 }
156
157 if (!InitIOLibrary()) {
158 printf("Failed to initialize port I/O library\n");
159 return -1;
160 }
161
162 pFile = fopen(fn, "wb");
163 if (!pFile) {
164 printf("couldn't open file %s\n", fn);
165 return -1;
166 }
167
168 printf("waiting to dump to %s...", fn);
169
170 while (received < expected) {
171 t1 = recvtribble();
172 t2 = recvtribble();
173 t3 = recvtribble();
174
175 b = t1 + (t2 << 3) + ((t3 & dibmask) << 6);
176
177 if (received == 0)
178 printf("\n");
179
180 if (0) {
181 printf("[%08d] received 0x%x, 0x%x, 0x%x = 0x%x\r\n", received, t1, t2, t3, b);
182 }
183
184 fputc(b, pFile);
185 received++;
186
187 if (received % 1024 == 0 || received == expected)
188 printf("\rreceived: %07d/%07d", received, expected);
189 }
190 fclose(pFile);
191
192 printf("\n");
193
194 return 0;
195}
196