fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation

pri: Support FM encoding and decoding

Hampa Hug fe650cc6 28221397

+974 -124
+9
Makefile.dep
··· 2065 2065 src/drivers/pri/pri.h \ 2066 2066 src/drivers/psi/psi.h 2067 2067 2068 + src/drivers/pri/pri-enc-fm.o: src/drivers/pri/pri-enc-fm.c \ 2069 + src/drivers/pri/pri-enc-fm.h \ 2070 + src/drivers/pri/pri-img.h \ 2071 + src/drivers/pri/pri.h \ 2072 + src/drivers/psi/psi.h 2073 + 2068 2074 src/drivers/pri/pri-img-pbit.o: src/drivers/pri/pri-img-pbit.c \ 2069 2075 src/drivers/pri/pri-img-pbit.h \ 2070 2076 src/drivers/pri/pri-img.h \ ··· 2434 2440 src/config.h \ 2435 2441 src/drivers/pri/gcr-mac.h \ 2436 2442 src/drivers/pri/mfm-ibm.h \ 2443 + src/drivers/pri/pri-enc-fm.h \ 2437 2444 src/drivers/pri/pri-img.h \ 2438 2445 src/drivers/pri/pri.h \ 2439 2446 src/drivers/psi/psi-img.h \ ··· 2456 2463 src/config.h \ 2457 2464 src/drivers/pri/gcr-mac.h \ 2458 2465 src/drivers/pri/mfm-ibm.h \ 2466 + src/drivers/pri/pri-enc-fm.h \ 2459 2467 src/drivers/pri/pri-img.h \ 2460 2468 src/drivers/pri/pri.h \ 2461 2469 src/drivers/psi/psi-img.h \ ··· 2477 2485 src/utils/pri/main.o: src/utils/pri/main.c \ 2478 2486 src/config.h \ 2479 2487 src/drivers/pri/mfm-ibm.h \ 2488 + src/drivers/pri/pri-enc-fm.h \ 2480 2489 src/drivers/pri/pri-img.h \ 2481 2490 src/drivers/pri/pri.h \ 2482 2491 src/drivers/psi/psi-img.h \
+2
src/drivers/pri/Makefile.inc
··· 8 8 DRV_PRI_BAS := \ 9 9 gcr-mac \ 10 10 mfm-ibm \ 11 + pri-enc-fm \ 11 12 pri-img-pbit \ 12 13 pri-img-pri \ 13 14 pri-img-tc \ ··· 24 25 25 26 $(rel)/gcr-mac.o: $(rel)/gcr-mac.c 26 27 $(rel)/mfm-ibm.o: $(rel)/mfm-ibm.c 28 + $(rel)/pri-enc-fm.o: $(rel)/pri-enc-fm.c 27 29 $(rel)/pri-img-pbit.o: $(rel)/pri-img-pbit.c 28 30 $(rel)/pri-img-pri.o: $(rel)/pri-img-pri.c 29 31 $(rel)/pri-img-tc.o: $(rel)/pri-img-tc.c
+16 -99
src/drivers/pri/mfm-ibm.c
··· 46 46 47 47 48 48 /* 49 - * Calculate the CRC for FM/MFM 49 + * Calculate the CRC for MFM 50 50 */ 51 51 static 52 52 unsigned mfm_crc (unsigned crc, const void *buf, unsigned cnt) ··· 77 77 78 78 79 79 /* 80 - * Get the next FM/MFM bit 80 + * Get the next MFM bit 81 81 */ 82 82 static 83 83 int mfm_get_bit (mfm_code_t *mfm) ··· 92 92 } 93 93 94 94 /* 95 - * Read an FM/MFM byte 95 + * Read an MFM byte 96 96 */ 97 97 static 98 98 unsigned char mfm_decode_byte (mfm_code_t *mfm) ··· 116 116 } 117 117 118 118 /* 119 - * Read FM/MFM data 119 + * Read MFM data 120 120 */ 121 121 static 122 122 void mfm_read (mfm_code_t *mfm, unsigned char *buf, unsigned cnt) ··· 187 187 188 188 mfm->crc = mfm_crc (0xffff, "\xa1\xa1\xa1", 3); 189 189 mfm->crc = mfm_crc (mfm->crc, val, 1); 190 - 191 - return (0); 192 - } 193 - 194 - /* 195 - * Sync with an FM mark and initialize the CRC. 196 - * 197 - * FE = 11111110 / C7 = 11000111 198 - * F57E = 1 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 199 - * 200 - * FB = 11111011 / C7 = 11000111 201 - * F56F = 1 1 1 1 0 1 0 1 0 1 1 0 1 1 1 1 202 - * 203 - * F8 = 11111000 / C7 = 11000111 204 - * F56A = 1 1 1 1 0 1 0 1 0 1 1 0 1 0 1 0 205 - */ 206 - static 207 - int fm_sync_mark (mfm_code_t *mfm, unsigned char *val) 208 - { 209 - unsigned long pos; 210 - unsigned v; 211 - 212 - v = 0; 213 - 214 - pos = mfm->trk->idx; 215 - 216 - while (1) { 217 - v = ((v << 1) | (mfm_get_bit (mfm) != 0)) & 0xffff; 218 - 219 - if (v == 0xf57e) { 220 - *val = 0xfe; 221 - break; 222 - } 223 - else if (v == 0xf56f) { 224 - *val = 0xfb; 225 - break; 226 - } 227 - else if (v == 0xf56a) { 228 - *val = 0xf8; 229 - break; 230 - } 231 - 232 - if (mfm->trk->idx == pos) { 233 - return (1); 234 - } 235 - } 236 - 237 - mfm->crc = mfm_crc (0xffff, val, 1); 238 - 239 - mfm->clock = 1; 240 190 241 191 return (0); 242 192 } ··· 308 258 } 309 259 310 260 static 311 - int mfm_decode_mark (mfm_code_t *mfm, psi_trk_t *trk, unsigned mark, int fm) 261 + int mfm_decode_mark (mfm_code_t *mfm, psi_trk_t *trk, unsigned mark) 312 262 { 313 263 int r; 314 264 unsigned char mark2; ··· 324 274 return (1); 325 275 } 326 276 327 - psi_sct_set_encoding (sct, fm ? PSI_ENC_FM : PSI_ENC_MFM); 277 + psi_sct_set_encoding (sct, PSI_ENC_MFM); 328 278 329 279 if (sct->n < mfm->min_sct_size) { 330 280 psi_sct_set_size (sct, mfm->min_sct_size, 0); ··· 333 283 pos = mfm->trk->idx; 334 284 wrap = mfm->trk->wrap; 335 285 336 - if (fm) { 337 - r = fm_sync_mark (mfm, &mark2); 338 - } 339 - else { 340 - r = mfm_sync_mark (mfm, &mark2); 341 - } 286 + r = mfm_sync_mark (mfm, &mark2); 342 287 343 288 if (r == 0) { 344 289 if ((mark2 == 0xf8) || (mark2 == 0xfb)) { ··· 397 342 mfm.clock = 0; 398 343 mfm.min_sct_size = par->min_sct_size; 399 344 400 - if (par->decode_mfm) { 401 - pri_trk_set_pos (trk, 0); 402 - 403 - while (trk->wrap == 0) { 404 - if (mfm_sync_mark (&mfm, &mark)) { 405 - break; 406 - } 407 - 408 - if ((trk->wrap) && (trk->idx >= (4 * 16))) { 409 - break; 410 - } 345 + pri_trk_set_pos (trk, 0); 411 346 412 - if (mfm_decode_mark (&mfm, dtrk, mark, 0)) { 413 - psi_trk_del (dtrk); 414 - return (NULL); 415 - } 347 + while (trk->wrap == 0) { 348 + if (mfm_sync_mark (&mfm, &mark)) { 349 + break; 416 350 } 417 351 418 - if (dtrk->sct_cnt > 0) { 419 - return (dtrk); 352 + if ((trk->wrap) && (trk->idx >= (4 * 16))) { 353 + break; 420 354 } 421 - } 422 355 423 - if (par->decode_fm) { 424 - pri_trk_set_pos (trk, 0); 425 - 426 - while (trk->wrap == 0) { 427 - if (fm_sync_mark (&mfm, &mark)) { 428 - break; 429 - } 430 - 431 - if ((trk->wrap) && (trk->idx >= 16)) { 432 - break; 433 - } 434 - 435 - if (mfm_decode_mark (&mfm, dtrk, mark, 1)) { 436 - psi_trk_del (dtrk); 437 - return (NULL); 438 - } 356 + if (mfm_decode_mark (&mfm, dtrk, mark)) { 357 + psi_trk_del (dtrk); 358 + return (NULL); 439 359 } 440 360 } 441 361 ··· 487 407 488 408 void pri_decode_mfm_init (pri_dec_mfm_t *par) 489 409 { 490 - par->decode_mfm = 1; 491 - par->decode_fm = 1; 492 - 493 410 par->min_sct_size = 0; 494 411 } 495 412
+1 -4
src/drivers/pri/mfm-ibm.h
··· 5 5 /***************************************************************************** 6 6 * File name: src/drivers/pri/mfm-ibm.h * 7 7 * Created: 2012-02-01 by Hampa Hug <hampa@hampa.ch> * 8 - * Copyright: (C) 2012-2013 Hampa Hug <hampa@hampa.ch> * 8 + * Copyright: (C) 2012-2014 Hampa Hug <hampa@hampa.ch> * 9 9 *****************************************************************************/ 10 10 11 11 /***************************************************************************** ··· 42 42 43 43 44 44 typedef struct { 45 - char decode_mfm; 46 - char decode_fm; 47 - 48 45 unsigned min_sct_size; 49 46 } pri_dec_mfm_t; 50 47
+661
src/drivers/pri/pri-enc-fm.c
··· 1 + /***************************************************************************** 2 + * pce * 3 + *****************************************************************************/ 4 + 5 + /***************************************************************************** 6 + * File name: src/drivers/pri/pri-enc-fm.c * 7 + * Created: 2014-12-28 by Hampa Hug <hampa@hampa.ch> * 8 + * Copyright: (C) 2014 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 <stdlib.h> 24 + #include <stdio.h> 25 + #include <string.h> 26 + 27 + #include <drivers/psi/psi.h> 28 + 29 + #include "pri.h" 30 + #include "pri-img.h" 31 + #include "pri-enc-fm.h" 32 + 33 + 34 + typedef struct { 35 + pri_trk_t *trk; 36 + 37 + char clock; 38 + 39 + unsigned crc; 40 + 41 + unsigned long last_gap3_start; 42 + } fm_code_t; 43 + 44 + 45 + /* 46 + * Calculate the CRC for FM 47 + */ 48 + static 49 + unsigned fm_crc (unsigned crc, const void *buf, unsigned cnt) 50 + { 51 + unsigned i; 52 + const unsigned char *src; 53 + 54 + src = buf; 55 + 56 + while (cnt > 0) { 57 + crc ^= (unsigned) *src << 8; 58 + 59 + for (i = 0; i < 8; i++) { 60 + if (crc & 0x8000) { 61 + crc = (crc << 1) ^ 0x1021; 62 + } 63 + else { 64 + crc = crc << 1; 65 + } 66 + } 67 + 68 + src += 1; 69 + cnt -= 1; 70 + } 71 + 72 + return (crc & 0xffff); 73 + } 74 + 75 + 76 + /* 77 + * Get the next FM bit 78 + */ 79 + static 80 + int fm_get_bit (fm_code_t *fm) 81 + { 82 + unsigned long bit; 83 + 84 + pri_trk_get_bits (fm->trk, &bit, 1); 85 + 86 + fm->clock = !fm->clock; 87 + 88 + return (bit & 1); 89 + } 90 + 91 + /* 92 + * Read an FM byte 93 + */ 94 + static 95 + unsigned char fm_decode_byte (fm_code_t *fm) 96 + { 97 + unsigned i; 98 + unsigned val; 99 + 100 + if (fm->clock) { 101 + fm_get_bit (fm); 102 + } 103 + 104 + val = 0; 105 + 106 + for (i = 0; i < 8; i++) { 107 + val = (val << 1) | (fm_get_bit (fm) != 0); 108 + 109 + fm_get_bit (fm); 110 + } 111 + 112 + return (val); 113 + } 114 + 115 + /* 116 + * Read FM data 117 + */ 118 + static 119 + void fm_read (fm_code_t *fm, unsigned char *buf, unsigned cnt) 120 + { 121 + unsigned long i; 122 + 123 + for (i = 0; i < cnt; i++) { 124 + buf[i] = fm_decode_byte (fm); 125 + } 126 + } 127 + 128 + /* 129 + * Sync with an FM mark and initialize the CRC. 130 + * 131 + * FE = 11111110 / C7 = 11000111 132 + * F57E = 1 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 133 + * 134 + * FB = 11111011 / C7 = 11000111 135 + * F56F = 1 1 1 1 0 1 0 1 0 1 1 0 1 1 1 1 136 + * 137 + * F8 = 11111000 / C7 = 11000111 138 + * F56A = 1 1 1 1 0 1 0 1 0 1 1 0 1 0 1 0 139 + * 140 + * FC = 11111100 / D7 = 11010111 141 + * F77A = 1 1 1 1 0 1 1 1 0 1 1 1 1 0 1 0 142 + */ 143 + static 144 + int fm_sync_mark (fm_code_t *fm, unsigned char *val) 145 + { 146 + unsigned long pos; 147 + unsigned v; 148 + 149 + v = 0; 150 + 151 + pos = fm->trk->idx; 152 + 153 + while (1) { 154 + v = ((v << 1) | (fm_get_bit (fm) != 0)) & 0xffff; 155 + 156 + if (v == 0xf57e) { 157 + *val = 0xfe; 158 + break; 159 + } 160 + else if (v == 0xf56f) { 161 + *val = 0xfb; 162 + break; 163 + } 164 + else if (v == 0xf56a) { 165 + *val = 0xf8; 166 + break; 167 + } 168 + 169 + if (fm->trk->idx == pos) { 170 + return (1); 171 + } 172 + } 173 + 174 + fm->crc = fm_crc (0xffff, val, 1); 175 + 176 + fm->clock = 1; 177 + 178 + return (0); 179 + } 180 + 181 + static 182 + psi_sct_t *fm_decode_idam (fm_code_t *fm) 183 + { 184 + unsigned c, h, s, n; 185 + unsigned crc; 186 + unsigned long pos; 187 + unsigned char buf[8]; 188 + psi_sct_t *sct; 189 + 190 + pos = fm->trk->idx; 191 + 192 + fm_read (fm, buf, 6); 193 + 194 + crc = pri_get_uint16_be (buf, 4); 195 + 196 + fm->crc = fm_crc (fm->crc, buf, 4); 197 + 198 + c = buf[0]; 199 + h = buf[1]; 200 + s = buf[2]; 201 + n = buf[3]; 202 + 203 + n = 128 << ((n < 8) ? n : 8); 204 + 205 + sct = psi_sct_new (c, h, s, n); 206 + 207 + if (sct == NULL) { 208 + return (NULL); 209 + } 210 + 211 + psi_sct_set_mfm_size (sct, buf[3]); 212 + psi_sct_set_position (sct, pos / 2); 213 + psi_sct_set_flags (sct, PSI_FLAG_NO_DAM, 1); 214 + psi_sct_set_encoding (sct, PSI_ENC_FM); 215 + 216 + if (fm->crc != crc) { 217 + psi_sct_set_flags (sct, PSI_FLAG_CRC_ID, 1); 218 + } 219 + 220 + psi_sct_fill (sct, 0); 221 + 222 + return (sct); 223 + } 224 + 225 + static 226 + int fm_decode_dam (fm_code_t *fm, psi_sct_t *sct, unsigned mark) 227 + { 228 + unsigned crc; 229 + unsigned char buf[4]; 230 + 231 + fm_read (fm, sct->data, sct->n); 232 + fm_read (fm, buf, 2); 233 + 234 + psi_sct_set_flags (sct, PSI_FLAG_NO_DAM, 0); 235 + psi_sct_set_flags (sct, PSI_FLAG_DEL_DAM, mark == 0xf8); 236 + 237 + crc = pri_get_uint16_be (buf, 0); 238 + 239 + fm->crc = fm_crc (fm->crc, sct->data, sct->n); 240 + 241 + if (fm->crc != crc) { 242 + psi_sct_set_flags (sct, PSI_FLAG_CRC_DATA, 1); 243 + } 244 + 245 + return (0); 246 + } 247 + 248 + static 249 + int fm_decode_mark (fm_code_t *fm, psi_trk_t *trk, unsigned mark) 250 + { 251 + unsigned char mark2; 252 + char wrap; 253 + unsigned long pos; 254 + psi_sct_t *sct; 255 + 256 + switch (mark) { 257 + case 0xfe: /* ID address mark */ 258 + sct = fm_decode_idam (fm); 259 + 260 + if (sct == NULL) { 261 + return (1); 262 + } 263 + 264 + pos = fm->trk->idx; 265 + wrap = fm->trk->wrap; 266 + 267 + if (fm_sync_mark (fm, &mark2) == 0) { 268 + if ((mark2 == 0xf8) || (mark2 == 0xfb)) { 269 + pos = fm->trk->idx; 270 + wrap = fm->trk->wrap; 271 + 272 + if (fm_decode_dam (fm, sct, mark2)) { 273 + psi_sct_del (sct); 274 + return (1); 275 + } 276 + } 277 + } 278 + 279 + if (sct->flags & PSI_FLAG_NO_DAM) { 280 + psi_sct_set_size (sct, 0, 0); 281 + } 282 + 283 + fm->trk->idx = pos; 284 + fm->trk->wrap = wrap; 285 + 286 + psi_trk_add_sector (trk, sct); 287 + break; 288 + 289 + case 0xfb: /* data address mark */ 290 + case 0xf8: /* deleted data address mark */ 291 + fprintf (stderr, "fm: dam without idam\n"); 292 + break; 293 + 294 + default: 295 + fprintf (stderr, 296 + "fm: unknown mark (0x%02x)\n", mark 297 + ); 298 + } 299 + 300 + return (0); 301 + } 302 + 303 + psi_trk_t *pri_decode_fm_trk (pri_trk_t *trk, unsigned h) 304 + { 305 + unsigned char mark; 306 + psi_trk_t *dtrk; 307 + fm_code_t fm; 308 + 309 + if ((dtrk = psi_trk_new (h)) == NULL) { 310 + return (NULL); 311 + } 312 + 313 + fm.trk = trk; 314 + fm.clock = 0; 315 + 316 + pri_trk_set_pos (trk, 0); 317 + 318 + while (trk->wrap == 0) { 319 + if (fm_sync_mark (&fm, &mark)) { 320 + break; 321 + } 322 + 323 + if ((trk->wrap) && (trk->idx >= 16)) { 324 + break; 325 + } 326 + 327 + if (fm_decode_mark (&fm, dtrk, mark)) { 328 + psi_trk_del (dtrk); 329 + return (NULL); 330 + } 331 + } 332 + 333 + return (dtrk); 334 + } 335 + 336 + psi_img_t *pri_decode_fm (pri_img_t *img) 337 + { 338 + unsigned long c, h; 339 + pri_cyl_t *cyl; 340 + pri_trk_t *trk; 341 + psi_img_t *dimg; 342 + psi_trk_t *dtrk; 343 + 344 + if ((dimg = psi_img_new()) == NULL) { 345 + return (NULL); 346 + } 347 + 348 + for (c = 0; c < img->cyl_cnt; c++) { 349 + if ((cyl = img->cyl[c]) == NULL) { 350 + continue; 351 + } 352 + 353 + for (h = 0; h < cyl->trk_cnt; h++) { 354 + trk = cyl->trk[h]; 355 + 356 + if (trk == NULL) { 357 + dtrk = psi_trk_new (h); 358 + } 359 + else { 360 + dtrk = pri_decode_fm_trk (trk, h); 361 + } 362 + 363 + if (dtrk == NULL) { 364 + psi_img_del (dimg); 365 + return (NULL); 366 + } 367 + 368 + psi_img_add_track (dimg, dtrk, c); 369 + } 370 + } 371 + 372 + return (dimg); 373 + } 374 + 375 + 376 + static 377 + void fm_encode_byte (fm_code_t *fm, unsigned val, unsigned clk) 378 + { 379 + unsigned i; 380 + unsigned buf; 381 + unsigned long max; 382 + 383 + if (fm->trk->wrap) { 384 + return; 385 + } 386 + 387 + buf = 0; 388 + 389 + for (i = 0; i < 8; i++) { 390 + buf = (buf << 2) | ((clk >> 6) & 2) | ((val >> 7) & 1); 391 + val = val << 1; 392 + clk = clk << 1; 393 + } 394 + 395 + max = fm->trk->size - fm->trk->idx; 396 + 397 + if (max > 16) { 398 + max = 16; 399 + } 400 + 401 + pri_trk_set_bits (fm->trk, buf >> (16 - max), max); 402 + } 403 + 404 + static 405 + void fm_encode_bytes (fm_code_t *fm, const unsigned char *buf, unsigned cnt) 406 + { 407 + while (cnt > 0) { 408 + fm_encode_byte (fm, *buf, 0xff); 409 + buf += 1; 410 + cnt -= 1; 411 + } 412 + } 413 + 414 + static 415 + void fm_encode_sector (fm_code_t *fm, psi_sct_t *sct, unsigned gap3) 416 + { 417 + unsigned i; 418 + unsigned flags; 419 + unsigned long pos; 420 + unsigned char buf[8]; 421 + 422 + if ((sct->position != 0xffffffff) && (sct->position >= (16 * 8))) { 423 + pos = 2 * (sct->position - 16 * 8); 424 + 425 + if (pos >= fm->last_gap3_start) { 426 + pri_trk_set_pos (fm->trk, pos); 427 + } 428 + else { 429 + pri_trk_set_pos (fm->trk, fm->last_gap3_start); 430 + } 431 + } 432 + 433 + flags = sct->flags; 434 + 435 + for (i = 0; i < 6; i++) { 436 + fm_encode_byte (fm, 0, 0xff); 437 + } 438 + 439 + fm_encode_byte (fm, 0xfe, 0xc7); 440 + 441 + fm->crc = fm_crc (0xffff, "\xfe", 1); 442 + 443 + buf[0] = sct->c; 444 + buf[1] = sct->h; 445 + buf[2] = sct->s; 446 + buf[3] = psi_sct_get_mfm_size (sct); 447 + 448 + fm->crc = fm_crc (fm->crc, buf, 4); 449 + 450 + if (flags & PSI_FLAG_CRC_ID) { 451 + fm->crc = ~fm->crc; 452 + } 453 + 454 + buf[4] = (fm->crc >> 8) & 0xff; 455 + buf[5] = fm->crc & 0xff; 456 + 457 + fm_encode_bytes (fm, buf, 6); 458 + 459 + for (i = 0; i < 11; i++) { 460 + fm_encode_byte (fm, 0xff, 0xff); 461 + } 462 + 463 + if (flags & PSI_FLAG_NO_DAM) { 464 + fm->last_gap3_start = fm->trk->idx; 465 + return; 466 + } 467 + 468 + for (i = 0; i < 6; i++) { 469 + fm_encode_byte (fm, 0x00, 0xff); 470 + } 471 + 472 + if (flags & PSI_FLAG_DEL_DAM) { 473 + fm_encode_byte (fm, 0xf8, 0xc7); 474 + fm->crc = fm_crc (0xffff, "\xf8", 1); 475 + } 476 + else { 477 + fm_encode_byte (fm, 0xfb, 0xc7); 478 + fm->crc = fm_crc (0xffff, "\xfb", 1); 479 + } 480 + 481 + fm_encode_bytes (fm, sct->data, sct->n); 482 + 483 + fm->crc = fm_crc (fm->crc, sct->data, sct->n); 484 + 485 + if (flags & PSI_FLAG_CRC_DATA) { 486 + fm->crc = ~fm->crc; 487 + } 488 + 489 + buf[0] = (fm->crc >> 8) & 0xff; 490 + buf[1] = fm->crc & 0xff; 491 + 492 + fm_encode_bytes (fm, buf, 2); 493 + 494 + fm->last_gap3_start = fm->trk->idx; 495 + 496 + for (i = 0; i < gap3; i++) { 497 + fm_encode_byte (fm, 0xff, 0xff); 498 + } 499 + } 500 + 501 + int pri_encode_fm_trk (pri_trk_t *dtrk, psi_trk_t *strk, pri_enc_fm_t *par) 502 + { 503 + unsigned i; 504 + unsigned long bits; 505 + unsigned gap3, scnt; 506 + psi_sct_t *sct; 507 + fm_code_t fm; 508 + 509 + fm.trk = dtrk; 510 + fm.last_gap3_start = 0; 511 + 512 + pri_trk_set_pos (dtrk, 0); 513 + 514 + gap3 = par->gap3; 515 + 516 + if (par->auto_gap3) { 517 + bits = par->gap4a + par->gap1; 518 + 519 + if (par->enable_iam) { 520 + bits += 7; 521 + } 522 + 523 + scnt = 0; 524 + 525 + for (i = 0; i < strk->sct_cnt; i++) { 526 + sct = strk->sct[i]; 527 + 528 + if ((sct->encoding & PSI_ENC_MASK) != PSI_ENC_FM) { 529 + continue; 530 + } 531 + 532 + if ((sct->flags & PSI_FLAG_NO_DAM) == 0) { 533 + scnt += 1; 534 + bits += strk->sct[i]->n + 6 + 7 + 11 + 6 + 1 + 2; 535 + } 536 + else { 537 + bits += strk->sct[i]->n + 6 + 7 + 11; 538 + } 539 + } 540 + 541 + bits *= 16; 542 + 543 + if (scnt > 0) { 544 + if (bits < dtrk->size) { 545 + gap3 = (dtrk->size - bits) / (16 * scnt); 546 + 547 + if (gap3 > par->gap3) { 548 + gap3 = par->gap3; 549 + } 550 + } 551 + else { 552 + gap3 = 1; 553 + 554 + pri_trk_set_size (dtrk, bits + 16 * (scnt * gap3 + 4)); 555 + } 556 + } 557 + } 558 + 559 + for (i = 0; i < par->gap4a; i++) { 560 + fm_encode_byte (&fm, 0xff, 0xff); 561 + } 562 + 563 + if (par->enable_iam) { 564 + for (i = 0; i < 6; i++) { 565 + fm_encode_byte (&fm, 0x00, 0xff); 566 + } 567 + 568 + fm_encode_byte (&fm, 0xfc, 0xd7); 569 + } 570 + 571 + for (i = 0; i < par->gap1; i++) { 572 + fm_encode_byte (&fm, 0xff, 0xff); 573 + } 574 + 575 + for (i = 0; i < strk->sct_cnt; i++) { 576 + sct = strk->sct[i]; 577 + 578 + if ((sct->encoding & PSI_ENC_MASK) == PSI_ENC_FM) { 579 + fm_encode_sector (&fm, sct, gap3); 580 + } 581 + } 582 + 583 + while (dtrk->wrap == 0) { 584 + fm_encode_byte (&fm, 0xff, 0xff); 585 + } 586 + 587 + return (0); 588 + } 589 + 590 + int pri_encode_fm_img (pri_img_t *dimg, psi_img_t *simg, pri_enc_fm_t *par) 591 + { 592 + unsigned long c, h; 593 + psi_cyl_t *cyl; 594 + psi_trk_t *trk; 595 + pri_trk_t *dtrk; 596 + 597 + for (c = 0; c < simg->cyl_cnt; c++) { 598 + cyl = simg->cyl[c]; 599 + 600 + for (h = 0; h < cyl->trk_cnt; h++) { 601 + trk = cyl->trk[h]; 602 + 603 + dtrk = pri_img_get_track (dimg, c, h, 1); 604 + 605 + if (dtrk == NULL) { 606 + return (1); 607 + } 608 + 609 + if (pri_trk_set_size (dtrk, par->track_size)) { 610 + return (1); 611 + } 612 + 613 + pri_trk_set_clock (dtrk, par->clock); 614 + pri_trk_clear_16 (dtrk, 0xffff); 615 + 616 + if (pri_encode_fm_trk (dtrk, trk, par)) { 617 + return (1); 618 + } 619 + } 620 + } 621 + 622 + return (0); 623 + } 624 + 625 + pri_img_t *pri_encode_fm (psi_img_t *img, pri_enc_fm_t *par) 626 + { 627 + pri_img_t *dimg; 628 + 629 + if ((dimg = pri_img_new()) == NULL) { 630 + return (NULL); 631 + } 632 + 633 + if (pri_encode_fm_img (dimg, img, par)) { 634 + pri_img_del (dimg); 635 + return (NULL); 636 + } 637 + 638 + return (dimg); 639 + } 640 + 641 + void pri_encode_fm_init (pri_enc_fm_t *par, unsigned long clock, unsigned rpm) 642 + { 643 + par->clock = clock; 644 + par->track_size = 60 * clock / rpm; 645 + 646 + par->enable_iam = 0; 647 + par->auto_gap3 = 1; 648 + 649 + par->gap4a = 40; 650 + par->gap1 = 26; 651 + par->gap3 = 27; 652 + } 653 + 654 + pri_img_t *pri_encode_fm_sd_300 (psi_img_t *img) 655 + { 656 + pri_enc_fm_t par; 657 + 658 + pri_encode_fm_init (&par, 250000, 300); 659 + 660 + return (pri_encode_fm (img, &par)); 661 + }
+54
src/drivers/pri/pri-enc-fm.h
··· 1 + /***************************************************************************** 2 + * pce * 3 + *****************************************************************************/ 4 + 5 + /***************************************************************************** 6 + * File name: src/drivers/pri/pri-enc-fm.h * 7 + * Created: 2014-12-28 by Hampa Hug <hampa@hampa.ch> * 8 + * Copyright: (C) 2014 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 + #ifndef PCE_PRI_FM_IBM_H 24 + #define PCE_PRI_FM_IBM_H 1 25 + 26 + 27 + #include <drivers/pri/pri.h> 28 + #include <drivers/psi/psi.h> 29 + 30 + 31 + typedef struct { 32 + unsigned long clock; 33 + unsigned long track_size; 34 + 35 + char enable_iam; 36 + char auto_gap3; 37 + 38 + unsigned gap4a; 39 + unsigned gap1; 40 + unsigned gap3; 41 + } pri_enc_fm_t; 42 + 43 + 44 + psi_trk_t *pri_decode_fm_trk (pri_trk_t *trk, unsigned h); 45 + psi_img_t *pri_decode_fm (pri_img_t *img); 46 + 47 + void pri_encode_fm_init (pri_enc_fm_t *par, unsigned long clock, unsigned rpm); 48 + int pri_encode_fm_trk (pri_trk_t *dtrk, psi_trk_t *strk, pri_enc_fm_t *par); 49 + int pri_encode_fm_img (pri_img_t *dimg, psi_img_t *simg, pri_enc_fm_t *par); 50 + pri_img_t *pri_encode_fm (psi_img_t *img, pri_enc_fm_t *par); 51 + pri_img_t *pri_encode_fm_sd_300 (psi_img_t *img); 52 + 53 + 54 + #endif
+62 -11
src/utils/pri/decode.c
··· 30 30 31 31 #include <drivers/pri/pri.h> 32 32 #include <drivers/pri/pri-img.h> 33 + #include <drivers/pri/pri-enc-fm.h> 33 34 #include <drivers/pri/gcr-mac.h> 34 35 #include <drivers/pri/mfm-ibm.h> 35 36 ··· 254 255 255 256 256 257 static 258 + int pri_decode_psi_auto_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque) 259 + { 260 + psi_trk_t *dtrk; 261 + struct pri_decode_psi_s *dec; 262 + 263 + dec = opaque; 264 + 265 + if ((dtrk = pri_decode_mfm_trk (trk, h, &dec->mfm)) == NULL) { 266 + return (1); 267 + } 268 + 269 + if (dtrk->sct_cnt == 0) { 270 + psi_trk_del (dtrk); 271 + 272 + if ((dtrk = pri_decode_fm_trk (trk, h)) == NULL) { 273 + return (1); 274 + } 275 + } 276 + 277 + if (dtrk->sct_cnt == 0) { 278 + psi_trk_del (dtrk); 279 + 280 + if ((dtrk = pri_decode_gcr_trk (trk, h)) == NULL) { 281 + return (1); 282 + } 283 + } 284 + 285 + if (psi_img_add_track (dec->img, dtrk, c)) { 286 + psi_trk_del (dtrk); 287 + return (1); 288 + } 289 + 290 + return (0); 291 + } 292 + 293 + static 257 294 int pri_decode_psi_mfm_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque) 258 295 { 259 296 psi_trk_t *dtrk; ··· 274 311 } 275 312 276 313 static 314 + int pri_decode_psi_fm_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque) 315 + { 316 + psi_trk_t *dtrk; 317 + struct pri_decode_psi_s *dec; 318 + 319 + dec = opaque; 320 + 321 + if ((dtrk = pri_decode_fm_trk (trk, h)) == NULL) { 322 + return (1); 323 + } 324 + 325 + if (psi_img_add_track (dec->img, dtrk, c)) { 326 + psi_trk_del (dtrk); 327 + return (1); 328 + } 329 + 330 + return (0); 331 + } 332 + 333 + static 277 334 int pri_decode_psi_gcr_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque) 278 335 { 279 336 psi_trk_t *dtrk; ··· 302 359 303 360 dec.mfm = par_dec_mfm; 304 361 305 - if (strcmp (type, "fm") == 0) { 306 - dec.mfm.decode_mfm = 0; 307 - dec.mfm.decode_fm = 1; 308 - fct = pri_decode_psi_mfm_cb; 362 + if ((strcmp (type, "auto") == 0) || (strcmp (type, "mfm-fm") == 0)) { 363 + fct = pri_decode_psi_auto_cb; 364 + } 365 + else if (strcmp (type, "fm") == 0) { 366 + fct = pri_decode_psi_fm_cb; 309 367 } 310 368 else if (strcmp (type, "gcr") == 0) { 311 369 fct = pri_decode_psi_gcr_cb; 312 370 } 313 371 else if (strcmp (type, "mfm") == 0) { 314 - dec.mfm.decode_mfm = 1; 315 - dec.mfm.decode_fm = 0; 316 - fct = pri_decode_psi_mfm_cb; 317 - } 318 - else if (strcmp (type, "mfm-fm") == 0) { 319 - dec.mfm.decode_mfm = 1; 320 - dec.mfm.decode_fm = 1; 321 372 fct = pri_decode_psi_mfm_cb; 322 373 } 323 374 else {
+105 -1
src/utils/pri/encode.c
··· 30 30 31 31 #include <drivers/pri/pri.h> 32 32 #include <drivers/pri/pri-img.h> 33 + #include <drivers/pri/pri-enc-fm.h> 33 34 #include <drivers/pri/gcr-mac.h> 34 35 #include <drivers/pri/mfm-ibm.h> 35 36 36 37 38 + extern pri_enc_fm_t par_enc_fm; 37 39 extern pri_enc_mfm_t par_enc_mfm; 38 40 39 41 42 + static 43 + unsigned get_encoding (const psi_trk_t *trk) 44 + { 45 + unsigned i; 46 + psi_sct_t *sct; 47 + 48 + for (i = 0; i < trk->sct_cnt; i++) { 49 + sct = trk->sct[i]; 50 + 51 + switch (sct->encoding & PSI_ENC_MASK) { 52 + case PSI_ENC_FM: 53 + return (PSI_ENC_FM); 54 + 55 + case PSI_ENC_MFM: 56 + return (PSI_ENC_MFM); 57 + } 58 + } 59 + 60 + return (PSI_ENC_UNKNOWN); 61 + } 62 + 63 + static 64 + int pri_encode_auto_img (pri_img_t *dimg, psi_img_t *simg) 65 + { 66 + unsigned enc; 67 + unsigned long c, h; 68 + psi_cyl_t *cyl; 69 + psi_trk_t *trk; 70 + pri_trk_t *dtrk; 71 + 72 + for (c = 0; c < simg->cyl_cnt; c++) { 73 + cyl = simg->cyl[c]; 74 + 75 + for (h = 0; h < cyl->trk_cnt; h++) { 76 + trk = cyl->trk[h]; 77 + 78 + dtrk = pri_img_get_track (dimg, c, h, 1); 79 + 80 + if (dtrk == NULL) { 81 + return (1); 82 + } 83 + 84 + enc = get_encoding (trk); 85 + 86 + if (enc == PSI_ENC_FM) { 87 + if (pri_trk_set_size (dtrk, par_enc_fm.track_size)) { 88 + return (1); 89 + } 90 + 91 + pri_trk_set_clock (dtrk, par_enc_fm.clock); 92 + pri_trk_clear_16 (dtrk, 0xffff); 93 + 94 + if (pri_encode_fm_trk (dtrk, trk, &par_enc_fm)) { 95 + return (1); 96 + } 97 + } 98 + else { 99 + if (pri_trk_set_size (dtrk, par_enc_mfm.track_size)) { 100 + return (1); 101 + } 102 + 103 + pri_trk_set_clock (dtrk, par_enc_mfm.clock); 104 + pri_trk_clear_16 (dtrk, 0x9254); 105 + 106 + if (pri_encode_mfm_trk (dtrk, trk, &par_enc_mfm)) { 107 + return (1); 108 + } 109 + } 110 + } 111 + } 112 + 113 + return (0); 114 + } 115 + 116 + static 117 + pri_img_t *pri_encode_auto (psi_img_t *img) 118 + { 119 + pri_img_t *dimg; 120 + 121 + if ((dimg = pri_img_new()) == NULL) { 122 + return (NULL); 123 + } 124 + 125 + if (pri_encode_auto_img (dimg, img)) { 126 + pri_img_del (dimg); 127 + return (NULL); 128 + } 129 + 130 + return (dimg); 131 + } 132 + 40 133 int pri_encode (pri_img_t **img, const char *type, const char *fname) 41 134 { 42 135 psi_img_t *simg; ··· 46 139 return (1); 47 140 } 48 141 49 - if (strcmp (type, "gcr") == 0) { 142 + if (strcmp (type, "auto") == 0) { 143 + dimg = pri_encode_auto (simg); 144 + } 145 + else if (strcmp (type, "fm") == 0) { 146 + dimg = pri_encode_fm (simg, &par_enc_fm); 147 + } 148 + else if (strcmp (type, "fm-sd-300") == 0) { 149 + par_enc_fm.clock = 250000; 150 + par_enc_fm.track_size = 250000 / 5; 151 + dimg = pri_encode_fm (simg, &par_enc_fm); 152 + } 153 + else if (strcmp (type, "gcr") == 0) { 50 154 dimg = pri_encode_gcr (simg); 51 155 } 52 156 else if (strcmp (type, "mfm") == 0) {
+30 -2
src/utils/pri/main.c
··· 33 33 34 34 #include <drivers/pri/pri.h> 35 35 #include <drivers/pri/pri-img.h> 36 + #include <drivers/pri/pri-enc-fm.h> 36 37 #include <drivers/pri/mfm-ibm.h> 37 38 38 39 ··· 55 56 unsigned long par_trk[2]; 56 57 57 58 unsigned long par_data_rate = 500000; 59 + 60 + pri_enc_fm_t par_enc_fm; 58 61 59 62 pri_dec_mfm_t par_dec_mfm; 60 63 pri_enc_mfm_t par_enc_mfm; ··· 116 119 "parameters are:\n" 117 120 " mfm-auto-gap3, mfm-clock, mfm-iam, mfm-gap1, mfm-gap3, mfm-gap4a,\n" 118 121 " mfm-min-size, mfm-track-size\n" 122 + " fm-auto-gap3, fm-clock, fm-iam, fm-gap1, fm-gap3, fm-gap4a,\n" 123 + " fm-track-size\n" 119 124 "\n" 120 125 "decode types are:\n" 121 - " fm, fm-raw, gcr, gcr-raw, mfm, mfm-fm, mfm-raw, raw\n" 126 + " auto, fm, fm-raw, gcr, gcr-raw, mfm, mfm-raw, raw\n" 122 127 "\n" 123 128 "encode types are:\n" 124 - " gcr, mfm, mfm-dd-300, mfm-hd-300, mfm-hd-360\n" 129 + " auto, fm, fm-sd-300, gcr, mfm, mfm-dd-300, mfm-hd-300, mfm-hd-360\n" 125 130 "\n" 126 131 "file formats are:\n" 127 132 " pri, tc\n" ··· 461 466 else if (strcmp (name, "mfm-track-size") == 0) { 462 467 par_enc_mfm.track_size = strtoul (val, NULL, 0); 463 468 } 469 + else if (strcmp (name, "fm-auto-gap3") == 0) { 470 + par_enc_fm.auto_gap3 = (strtoul (val, NULL, 0) != 0); 471 + } 472 + else if (strcmp (name, "fm-clock") == 0) { 473 + par_enc_fm.clock = strtoul (val, NULL, 0); 474 + } 475 + else if (strcmp (name, "fm-iam") == 0) { 476 + par_enc_fm.enable_iam = (strtoul (val, NULL, 0) != 0); 477 + } 478 + else if (strcmp (name, "fm-gap1") == 0) { 479 + par_enc_fm.gap1 = strtoul (val, NULL, 0); 480 + } 481 + else if (strcmp (name, "fm-gap3") == 0) { 482 + par_enc_fm.gap3 = strtoul (val, NULL, 0); 483 + } 484 + else if (strcmp (name, "fm-gap4a") == 0) { 485 + par_enc_fm.gap4a = strtoul (val, NULL, 0); 486 + } 487 + else if (strcmp (name, "fm-track-size") == 0) { 488 + par_enc_fm.track_size = strtoul (val, NULL, 0); 489 + } 464 490 else { 465 491 return (1); 466 492 } ··· 498 524 arg0 = argv[0]; 499 525 500 526 img = NULL; 527 + 528 + pri_encode_fm_init (&par_enc_fm, 250000, 300); 501 529 502 530 pri_decode_mfm_init (&par_dec_mfm); 503 531 pri_encode_mfm_init (&par_enc_mfm, 500000, 300);
+34 -7
src/utils/pri/pri.1
··· 115 115 Set the image comment to \fItext\fR. 116 116 .TP 117 117 .BI "decode " "type filename" 118 - Decode the image and save it as a pri sector image to \fIfilename\fR. 118 + Decode the image and save it as a psi sector image to \fIfilename\fR. 119 119 Valid decode types are: 120 120 .RS 121 + .TP 122 + .B auto 123 + Try to decode each track as mfm, fm and gcr. 121 124 .TP 122 125 .B fm 123 126 IBM FM ··· 127 130 .TP 128 131 .B mfm 129 132 IBM MFM 130 - .TP 131 - .B mfm-fm 132 - IBM MFM/FM. Tracks are decoded as MFM first and if no sectors are found, 133 - they are decoded as FM. 134 133 .RE 135 134 .TP 136 135 .B delete ··· 143 142 Remove even numbered tracks. 144 143 .TP 145 144 .BI "encode " "type filename" 146 - Load a pri sector image from \fIfilename\fR and encode it. 145 + Load a psi sector image from \fIfilename\fR and encode it. 147 146 Valid encode types are: 148 147 .RS 148 + .TP 149 + .B auto 150 + Automatically determine the encoding for each track 151 + .TP 152 + .B fm 153 + IBM FM 149 154 .TP 150 155 .B gcr 151 156 Apple Macintosh GCR ··· 199 204 Set the GAP4A length in bytes. The default is 96. 200 205 .TP 201 206 .BI "mfm-min-size " integer 202 - Set the minimal sector size when decoding MFM/FM. 207 + Set the minimal sector size when decoding MFM. 203 208 .TP 204 209 .BI "mfm-track-size " integer 210 + Set the track size in bits. 211 + .TP 212 + .BI "fm-auto-gap3 " boolean 213 + Automatically set the GAP3 length. The default is true. 214 + .TP 215 + .BI "fm-clock " integer 216 + Set the FM clock rate (this is twice the data rate). The default is 217 + 250000, suitable for single density disks. 218 + .TP 219 + .BI "fm-iam " boolean 220 + If false, skip the index address mark. The default is false. 221 + .TP 222 + .BI "fm-gap1 " integer 223 + Set the GAP1 length in bytes. The default is 26. 224 + .TP 225 + .BI "fm-gap3 " integer 226 + Set the GAP3 length in bytes. The default is 27. 227 + .TP 228 + .BI "fm-gap4a " integer 229 + Set the GAP4A length in bytes. The default is 40. 230 + .TP 231 + .BI "fm-track-size " integer 205 232 Set the track size in bits. 206 233 .RE 207 234 \