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