1 #include <stdio.h>
2 #include <string.h>
3 #include <ctype.h>
4 #include "develo.h"
5 
6 /* locals */
7 static unsigned char buffer[128];
8 static unsigned char block_buffer[256];
9 static char line[256];
10 static int  bank_base;
11 static int  bank,  old_bank;
12 static int  block, old_block, last_block;
13 static int  buffer_start, buffer_index;
14 static int  display;
15 
16 /* protos */
17 static int htoi(char *str, int nb);
18 static int upload(unsigned char *data, int addr, int cnt);
19 static int flush(int end);
20 
21 
22 /* ----
23  * dv_load_mx()
24  * ----
25  */
26 
27 int
dv_load_mx(char * fname,int * a,int * b,int disp)28 dv_load_mx(char *fname, int *a, int *b, int disp)
29 {
30 	FILE *fp;
31 	char *ptr;
32 	char  type;
33 	int addr, data, cnt, chksum;
34 	int start;
35 	int ln;
36 	int i;
37 
38 	/* set global display flag */
39 	display = disp;
40 
41 	/* upload message */
42 	printf("uploading program");
43 	fflush(stdout);
44 
45 	/* open the mx file */
46 	if ((fp = fopen(fname, "r")) == NULL) {
47 		printf("... can not open file '%s'!\n", fname);
48 		return (DV_ERR);
49 	}
50 
51 	/* new line */
52 	printf("\n");
53 
54 	/* init variables */
55  	buffer_start = -1;
56  	buffer_index =  0;
57 	old_block = 0;
58 	old_bank  = 0;
59 	start     = 0;
60 
61 	/* line counter */
62 	ln = 1;
63 
64 	/* main read loop */
65 	while (fgets(line, 254, fp) != NULL) {
66 		if (line[0] == 'S') {
67 			/* get s-record type */
68 			type = line[1];
69 
70 			/* skip unsupported records */
71 			if ((type != '2') && (type != '8'))
72 				continue;
73 
74 			/* check the line length */
75 			if (strlen(line) < 12)
76 				goto err;
77 
78 			/* count, address */
79 			cnt  = htoi(&line[2], 2);
80 			addr = htoi(&line[4], 6);
81 
82 			if ((cnt < 4) || (addr == -1))
83 				goto err;
84 
85 			/* adjust count */
86 			cnt -= 4;
87 
88 			/* checksum */
89 			chksum = cnt + ((addr >> 16) & 0xFF) +
90 						   ((addr >> 8) & 0xFF) +
91 						   ((addr) & 0xFF) + 4;
92 
93 			/* data */
94 			ptr = &line[10];
95 
96 			for (i = 0; i < cnt; i++) {
97 				data = htoi(ptr, 2);
98 				buffer[i] = data;
99 				chksum += data;
100 				ptr += 2;
101 
102 				if (data == -1)
103 					goto err;
104 			}
105 
106 			/* checksum test */
107 			chksum = (~chksum) & 0xFF;
108 			data = htoi(ptr, 2);
109 
110 			if (data != chksum)
111 				goto err;
112 
113 			/* record switch */
114 			if (type == '8') {
115 				/* S8: start address - end */
116 				if (addr)
117 					start = addr;
118 				break;
119 			}
120 			else {
121 				/* S2: data */
122 				if (start == 0)
123 					start = addr;
124 				if (upload(buffer, addr, cnt) != DV_OK)
125 					return (DV_ERR);
126 			}
127 		}
128 
129 		/* incremente line counter */
130 		ln++;
131 	}
132 
133 	/* flush block buffer */
134 	if (flush(1) != DV_OK)
135 		return (DV_ERR);
136 
137 	/* ok - return start address and bank base index */
138 	*a = start;
139 	*b = bank_base;
140 
141 	return (DV_OK);
142 
143 	/* error */
144 err:
145 	printf("... error in the mx file, line %i!\n", ln);
146 	return (DV_ERR);
147 }
148 
149 
150 /* ----
151  * htoi()
152  * ----
153  */
154 
155 static int
htoi(char * str,int nb)156 htoi(char *str, int nb)
157 {
158 	char c;
159 	int val;
160 	int i;
161 
162 	val = 0;
163 
164 	for (i = 0; i < nb; i++) {
165 		 c = toupper(str[i]);
166 
167 		if ((c >= '0') && (c <= '9'))
168 			val = (val << 4) + (c - '0');
169 		else if ((c >= 'A') && (c <= 'F'))
170 			val = (val << 4) + (c - 'A' + 10);
171 		else
172 			return (-1);
173 	}
174 
175 	/* ok */
176 	return (val);
177 }
178 
179 
180 /* ----
181  * upload()
182  * ----
183  */
184 
185 static int
upload(unsigned char * data,int addr,int cnt)186 upload(unsigned char *data, int addr, int cnt)
187 {
188 	int offset;
189 	int i;
190 
191 	/* calculate bank and block indexes */
192 loop:
193 	bank   = (addr >> 13);
194 	block  = (addr >> 8);
195 	offset = (addr & 0xFF);
196 
197 	/* develo compatibility */
198 	if (bank < 8) {
199 		if (bank < 3 || bank == 7) {
200 			printf("incorrect destination address, %04X!\n", addr);
201 			return (DV_ERR);
202 		}
203 		bank += 0x81;
204 	}
205 
206 	/* block change */
207 	if (block != old_block)
208 		if (flush(0) != DV_OK)
209 			return (DV_ERR);
210 
211 	/* bank change */
212 	if (bank != old_bank) {
213 		/* save starting bank index */
214 		if (old_bank == 0)
215 			bank_base = bank;
216 
217 		/* update bank index */
218 		old_bank = bank;
219 
220 		/* status */
221 		if (display) {
222 			if (last_block) {
223 				/* mask block index */
224 				last_block = (last_block - 1) & 0x1F;
225 
226 				/* progress bar */
227 				if (last_block < 31) {
228 					for (i = last_block; i < 31; i++)
229 						printf("�");
230 
231 					/* ok */
232 					printf(" OK\n");
233 				}
234 			}
235 
236 			/* bank message */
237 			printf("bank %02X: ", bank);
238 			fflush(stdout);
239 		}
240 
241 		/* reset block index */
242 		last_block = 0;
243 
244 		/* select the bank */
245 		if (dv_set_bank(4, bank) != DV_OK) {
246 			printf("\n%s, can not set bank!\n", dv_get_errmsg());
247 			return (DV_ERR);
248 		}
249 	}
250 
251 	/* set block starting offset */
252 	if (buffer_start == -1)
253 		buffer_start = offset;
254 
255 	/* set current offset */
256 	buffer_index = offset;
257 
258 	/* copy data */
259 	while (cnt) {
260 		/* copy a byte */
261 		block_buffer[buffer_index++] = *data++;
262 		addr += 1;
263 		cnt  -= 1;
264 
265 		/* buffer full */
266 		if (buffer_index > 255) {
267 			/* flush current buffer */
268 			if (flush(0) != DV_OK)
269 				return (DV_ERR);
270 
271 			/* loop */
272 			if (cnt)
273 				goto loop;
274 		}
275 	}
276 
277 	/* ok */
278 	return (DV_OK);
279 }
280 
281 
282 /* ----
283  * flush()
284  * ----
285  */
286 
287 static int
flush(int end)288 flush(int end)
289 {
290 	unsigned char *src;
291 	int dst;
292 	int len;
293 	int i;
294 
295 	/* transfer previous block - if any */
296 	if (buffer_index) {
297 		/* status */
298 		if (display) {
299 			/* set last block if new bank */
300 			if (last_block == 0)
301 				last_block = (old_block & 0xFFFFE0);
302 
303 			/* progress bar */
304 			for (i = last_block; i < old_block; i++)
305 				printf("�");
306 
307 			/* output */
308 			fflush(stdout);
309 		}
310 
311 		/* destination & source addresses, and length */
312 		dst = (0x8000) + ((old_block & 0x1F) << 8) + buffer_start;
313 		src = (block_buffer + buffer_start);
314 		len = (buffer_index - buffer_start);
315 
316 		/* transfer */
317 		if (len) {
318 			if (dv_set_ram(dst, src, len) != DV_OK) {
319 				printf("\n%s!\n", dv_get_errmsg());
320 				return (DV_ERR);
321 			}
322 		}
323 
324 		/* save block index */
325 		last_block = (old_block + 1);
326 
327 		/* status */
328 		if (display) {
329 			/* current block */
330 			printf("�");
331 			fflush(stdout);
332 
333 			/* mask block index */
334 			old_block = (old_block) & 0x1F;
335 
336 			/* ok */
337 			if (old_block == 31)
338 				printf(" OK\n");
339 			else {
340 				/* end transfer */
341 				if (end) {
342 					for (i = old_block; i < 31; i++)
343 						printf("�");
344 
345 					printf(" OK\n");
346 				}
347 			}
348 		}
349 	}
350 
351 	/* reset block buffer */
352 	memset(block_buffer, 0xFF, 256);
353 	buffer_start = -1;
354 	buffer_index =  0;
355 	old_block = block;
356 
357 	/* ok */
358 	return (DV_OK);
359 }
360 
361