fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/utils/pri/weak.c *
7 * Created: 2015-04-03 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2015-2018 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include "main.h"
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <drivers/pri/pri.h>
30
31
32static
33void set_bits (unsigned char *buf, unsigned long p1, unsigned long p2)
34{
35 while (p1 <= p2) {
36 buf[p1 >> 3] |= 0x80 >> (p1 & 7);
37 p1 += 1;
38 }
39}
40
41static
42void clear_bits (unsigned char *buf, unsigned long p1, unsigned long p2)
43{
44 while (p1 <= p2) {
45 buf[p1 >> 3] &= ~(0x80 >> (p1 & 7));
46 p1 += 1;
47 }
48}
49
50static
51int pri_weak_clean_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
52{
53 unsigned long cnt;
54 unsigned char *buf;
55
56 if (pri_trk_get_weak_mask (trk, &buf, &cnt)) {
57 return (1);
58 }
59
60 if (pri_trk_set_weak_mask (trk, buf, cnt)) {
61 free (buf);
62 return (1);
63 }
64
65 free (buf);
66
67 return (0);
68}
69
70int pri_weak_clean (pri_img_t *img)
71{
72 return (pri_for_all_tracks (img, pri_weak_clean_cb, NULL));
73}
74
75static
76int pri_weak_close_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
77{
78 unsigned long i, n;
79 unsigned j;
80 unsigned cnt;
81 int have1;
82 unsigned long last1, next1;
83 unsigned char *buf;
84
85 cnt = *(unsigned *)opaque;
86
87 if (cnt == 0) {
88 return (0);
89 }
90
91 if (pri_trk_get_weak_mask (trk, &buf, &n)) {
92 return (1);
93 }
94
95 have1 = 0;
96 last1 = 0;
97
98 for (i = 0; i < n; i++) {
99 if (buf[i] == 0) {
100 continue;
101 }
102
103 for (j = 0; j < 8; j++) {
104 if ((buf[i] & (0x80 >> j)) == 0) {
105 continue;
106 }
107
108 next1 = 8 * i + j;
109
110 if (have1) {
111 if ((next1 - last1 - 1) <= cnt) {
112 set_bits (buf, last1, next1);
113 }
114 }
115
116 have1 = 1;
117 last1 = next1;
118 }
119 }
120
121 if (pri_trk_set_weak_mask (trk, buf, n)) {
122 free (buf);
123 return (1);
124 }
125
126 free (buf);
127
128 return (0);
129}
130
131int pri_weak_close (pri_img_t *img, unsigned cnt)
132{
133 return (pri_for_all_tracks (img, pri_weak_close_cb, &cnt));
134}
135
136/*
137 * Mark zero bits that are preceded by at least max zero bits as weak.
138 */
139static
140int pri_weak_detect_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
141{
142 unsigned long pos, msk, bit;
143 unsigned long cnt, max;
144 pri_evt_t *evt;
145
146 cnt = 0;
147 max = *(unsigned long *)opaque;
148
149 pos = 0;
150 msk = 0;
151
152 pri_trk_set_pos (trk, 0);
153
154 while (trk->wrap == 0) {
155 pri_trk_get_bits (trk, &bit, 1);
156
157 if (bit) {
158 cnt = 0;
159 }
160 else if (cnt < max) {
161 cnt += 1;
162 }
163 else {
164 if (msk == 0) {
165 evt = pri_trk_evt_get_before (trk, PRI_EVENT_WEAK, pos);
166
167 if ((evt != NULL) && ((pos - evt->pos) >= 32)) {
168 evt = NULL;
169 }
170
171 if (evt == NULL) {
172 evt = pri_trk_evt_add (trk, PRI_EVENT_WEAK, pos, 0);
173
174 if (evt == NULL) {
175 return (1);
176 }
177 }
178
179 msk = 0x80000000 >> (pos - evt->pos);
180 }
181
182 evt->val |= msk;
183 }
184
185 pos += 1;
186 msk >>= 1;
187 }
188
189 return (0);
190}
191
192int pri_weak_detect (pri_img_t *img, unsigned long cnt)
193{
194 return (pri_for_all_tracks (img, pri_weak_detect_cb, &cnt));
195}
196
197static
198int pri_weak_expand_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
199{
200 unsigned long i, n;
201 unsigned j;
202 unsigned long pos, p1, p2;
203 unsigned long *val;
204 unsigned char *buf1, *buf2;;
205
206 val = opaque;
207
208 if (pri_trk_get_weak_mask (trk, &buf1, &n)) {
209 return (1);
210 }
211
212 if (pri_trk_get_weak_mask (trk, &buf2, &n)) {
213 free (buf1);
214 return (1);
215 }
216
217 for (i = 0; i < n; i++) {
218 if (buf1[i] == 0) {
219 continue;
220 }
221
222 for (j = 0; j < 8; j++) {
223 if ((buf1[i] & (0x80 >> j)) == 0) {
224 continue;
225 }
226
227 pos = 8 * i + j;
228
229 p1 = (pos < val[0]) ? 0 : (pos - val[0]);
230 p2 = pos + val[1];
231
232 if (p2 >= trk->size) {
233 p2 = trk->size - 1;
234 }
235
236 set_bits (buf2, p1, p2);
237 }
238 }
239
240 free (buf1);
241
242 if (pri_trk_set_weak_mask (trk, buf2, n)) {
243 free (buf2);
244 return (1);
245 }
246
247 free (buf2);
248
249 return (0);
250}
251
252int pri_weak_expand (pri_img_t *img, unsigned long left, unsigned long right)
253{
254 unsigned long val[2];
255
256 val[0] = left;
257 val[1] = right;
258
259 return (pri_for_all_tracks (img, pri_weak_expand_cb, val));
260}
261
262static
263int pri_weak_open_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
264{
265 unsigned long i, n;
266 unsigned j;
267 unsigned long cnt, run, pos;
268 unsigned char *buf;
269
270 cnt = *(unsigned long *) opaque;
271
272 if (pri_trk_get_weak_mask (trk, &buf, &n)) {
273 return (1);
274 }
275
276 run = 0;
277
278 for (i = 0; i < n; i++) {
279 if ((run == 0) && (buf[i] == 0)) {
280 continue;
281 }
282
283 for (j = 0; j < 8; j++) {
284 if (buf[i] & (0x80 >> j)) {
285 run += 1;
286 }
287 else if (run > 0) {
288 if (run <= cnt) {
289 pos = 8 * i + j;
290 clear_bits (buf, pos - run - 1, pos - 1);
291 }
292
293 run = 0;
294 }
295 }
296 }
297
298 if (pri_trk_set_weak_mask (trk, buf, n)) {
299 free (buf);
300 return (1);
301 }
302
303 free (buf);
304
305 return (0);
306}
307
308int pri_weak_open (pri_img_t *img, unsigned long cnt)
309{
310 return (pri_for_all_tracks (img, pri_weak_open_cb, &cnt));
311}
312
313
314static
315int pri_weak_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
316{
317 unsigned long idx, msk, bit, tmp;
318 unsigned long type, val;
319 unsigned mode;
320
321 /*
322 * bit 0: random
323 * bit 1: flip
324 * bit 2: set
325 * bit 3: clear
326 */
327 mode = *(unsigned *)opaque;
328
329 idx = 0;
330 msk = 0;
331
332 pri_trk_set_pos (trk, 0);
333
334 while (trk->wrap == 0) {
335 while (pri_trk_get_event (trk, &type, &val) == 0) {
336 if (type == PRI_EVENT_WEAK) {
337 if (mode & 1) {
338 tmp = rand();
339 tmp = (tmp << 10) ^ rand();
340 tmp = (tmp << 10) ^ rand();
341 val &= tmp;
342 }
343
344 msk |= val;
345 }
346 }
347
348 pri_trk_get_bits (trk, &bit, 1);
349
350 if (msk & 0x80000000) {
351 if (mode & 2) {
352 trk->data[idx >> 3] ^= 0x80 >> (idx & 7);
353 }
354 else if (mode & 4) {
355 trk->data[idx >> 3] |= 0x80 >> (idx & 7);
356 }
357 else if (mode & 8) {
358 trk->data[idx >> 3] &= ~(0x80 >> (idx & 7));
359 }
360 }
361
362 idx += 1;
363 msk <<= 1;
364 }
365
366 return (0);
367}
368
369int pri_weak_flip (pri_img_t *img, int random)
370{
371 unsigned mode;
372
373 mode = 2 | (random ? 1 : 0);
374
375 return (pri_for_all_tracks (img, pri_weak_cb, &mode));
376}
377
378int pri_weak_set (pri_img_t *img, int val)
379{
380 unsigned mode;
381
382 mode = val ? 4 : 8;
383
384 return (pri_for_all_tracks (img, pri_weak_cb, &mode));
385}
386
387static
388int pri_weak_load_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
389{
390 unsigned long cnt;
391 unsigned char *buf;
392 FILE *fp;
393
394 fp = opaque;
395
396 cnt = (pri_trk_get_size (trk) + 7) / 8;
397
398 if ((buf = malloc (cnt)) == NULL) {
399 return (1);
400 }
401
402 if (fread (buf, cnt, 1, fp) != 1) {
403 free (buf);
404 return (1);
405 }
406
407 if (pri_trk_set_weak_mask (trk, buf, cnt)) {
408 free (buf);
409 return (1);
410 }
411
412 free (buf);
413
414 return (0);
415}
416
417int pri_weak_load (pri_img_t *img, const char *fname)
418{
419 int r;
420 FILE *fp;
421
422 if ((fp = fopen (fname, "rb")) == NULL) {
423 return (1);
424 }
425
426 r = pri_for_all_tracks (img, pri_weak_load_cb, fp);
427
428 fclose (fp);
429
430 return (r);
431}
432
433static
434int pri_weak_save_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
435{
436 int r;
437 FILE *fp;
438 unsigned long cnt;
439 unsigned char *buf;
440
441 if (pri_trk_get_weak_mask (trk, &buf, &cnt)) {
442 return (1);
443 }
444
445 r = 0;
446
447 fp = opaque;
448
449 if (fwrite (buf, cnt, 1, fp) != 1) {
450 r = 1;
451 }
452
453 free (buf);
454
455 return (r);
456}
457
458int pri_weak_save (pri_img_t *img, const char *fname)
459{
460 int r;
461 FILE *fp;
462
463 if ((fp = fopen (fname, "wb")) == NULL) {
464 return (1);
465 }
466
467 r = pri_for_all_tracks (img, pri_weak_save_cb, fp);
468
469 fclose (fp);
470
471 return (r);
472}