fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 472 lines 8.7 kB view raw
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}