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

Configure Feed

Select the types of activity you want to include in your feed.

psi: Add the new PSI sector image file format

Hampa Hug 1231e707 ac5703d6

+1321 -8
+5
Makefile.dep
··· 1848 1848 src/drivers/psi/psi-io.h \ 1849 1849 src/drivers/psi/psi.h 1850 1850 1851 + src/drivers/psi/psi-img-psi.o: src/drivers/psi/psi-img-psi.c \ 1852 + src/drivers/psi/psi-io.h \ 1853 + src/drivers/psi/psi.h 1854 + 1851 1855 src/drivers/psi/psi-img-raw.o: src/drivers/psi/psi-img-raw.c \ 1852 1856 src/drivers/psi/psi-img-raw.h \ 1853 1857 src/drivers/psi/psi.h ··· 1874 1878 src/drivers/psi/psi-img-imd.h \ 1875 1879 src/drivers/psi/psi-img-msa.h \ 1876 1880 src/drivers/psi/psi-img-pfdc.h \ 1881 + src/drivers/psi/psi-img-psi.h \ 1877 1882 src/drivers/psi/psi-img-raw.h \ 1878 1883 src/drivers/psi/psi-img-tc.h \ 1879 1884 src/drivers/psi/psi-img-td0.h \
+2 -2
Makefile.inc.in
··· 112 112 113 113 DIST += doc/char-drivers.txt doc/keys.txt doc/messages.txt \ 114 114 doc/monitor.txt doc/pce-ibmpc.txt doc/pce-macplus.txt \ 115 - doc/pbit-format.txt doc/pfdc-format.txt doc/rc759-keymap.txt \ 116 - doc/sound-drivers.txt 115 + doc/pbit-format.txt doc/pfdc-format.txt doc/psi-format.txt \ 116 + doc/rc759-keymap.txt doc/sound-drivers.txt 117 117 118 118 # ---------------------------------------------------------------------- 119 119
+213
doc/psi-format.txt
··· 1 + PSI file format (2013-06-09) 2 + ======================================================================== 3 + 4 + File structure 5 + ------------------------------------------------------------------------ 6 + 7 + <file header chunk> 8 + <chunk 0> 9 + <chunk 1> 10 + ... 11 + <chunk n> 12 + <end chunk> 13 + 14 + All integers are in big-endian format. 15 + 16 + 17 + Chunk format 18 + ------------------------------------------------------------------------ 19 + 20 + offset size description 21 + 22 + 0 4 Chunk ID 23 + 4 4 Chunk size (n) 24 + 0 n Chunk data 25 + n 4 Chunk CRC 26 + 27 + - The size does not include the chunk ID, chunk size or chunk CRC 28 + fields. 29 + 30 + - The chunk CRC covers the chunk ID, chunk size and chunk data. 31 + 32 + 33 + CHUNK "PSI ": File header chunk 34 + ------------------------------------------------------------------------ 35 + 36 + offset size description 37 + 38 + 0 4 Chunk ID ('PSI ' = 0x50534920) 39 + 4 4 Chunk size (4) 40 + 0 2 Format version (0) 41 + 2 2 Default sector format 42 + 00 00 unknown 43 + 01 00 IBM FM 44 + 02 00 IBM MFM DD 45 + 02 01 IBM MFM HD 46 + 02 02 IBM MFM ED 47 + 03 00 MAC GCR 48 + 4 4 Chunk CRC 49 + 50 + 51 + CHUNK "END ": End chunk 52 + ------------------------------------------------------------------------ 53 + 54 + offset size description 55 + 56 + 0 4 Chunk ID ('END ') 57 + 4 4 Chunk size (0) 58 + 0 4 Chunk CRC (0x3d64af78) 59 + 60 + 61 + CHUNK "TEXT": Comments 62 + ------------------------------------------------------------------------ 63 + 64 + offset size description 65 + 66 + 0 4 Chunk ID ('TEXT') 67 + 4 4 Chunk size 68 + 0 n Comment 69 + n 4 Chunk CRC 70 + 71 + - Comments should be UTF-8, with lines separated by LF (0x0a). 72 + 73 + 74 + CHUNK "SECT": Sector header 75 + ------------------------------------------------------------------------ 76 + 77 + offset size description 78 + 79 + 0 4 Chunk ID ('SECT') 80 + 4 4 Chunk size (8) 81 + 82 + 0 2 cylinder 83 + 2 1 head 84 + 3 1 sector 85 + 4 2 size in bytes 86 + 6 1 flags 87 + 1 Compressed 88 + 2 Alternate sector 89 + 4 Data CRC error 90 + 7 1 Compressed sector data 91 + 92 + 8 4 Chunk CRC 93 + 94 + - The alternate sector flag indicates that this is the same 95 + physical sector as the one immediately preceding it. 96 + 97 + - The sector header chunk starts a new sector. All non sector 98 + header chunks that follow refer to the same sector. 99 + 100 + - If the sector is marked as compressed, the sector data is 101 + filled with the byte in <compressed sector data> and no 102 + data chunk follows. 103 + 104 + 105 + CHUNK "DATA": Sector data 106 + ------------------------------------------------------------------------ 107 + 108 + offset size description 109 + 110 + 0 4 Chunk ID ('DATA') 111 + 4 4 Chunk size (n) 112 + 0 n Sector data 113 + n 4 Chunk CRC 114 + 115 + 116 + CHUNK "IBMM": IBM MFM sector header 117 + ------------------------------------------------------------------------ 118 + 119 + offset size description 120 + 121 + 0 4 Chunk ID ('IBMM') 122 + 4 4 Chunk size (6) 123 + 0 1 Cylinder 124 + 1 1 Head 125 + 2 1 Sector 126 + 3 1 Size 127 + 4 1 Flags 128 + 1 CRC error in ID field 129 + 2 CRC error in data field 130 + 4 Deleted data adress mark 131 + 8 Missing data adress mark 132 + 5 1 Encoding subtype 133 + 0 Double density (250 KBit/s) 134 + 1 High density (500 KBit/s) 135 + 2 Extra density (1000 KBit/s) 136 + 6 4 Chunk CRC 137 + 138 + 139 + CHUNK "MACG": Macintosh GCR sector header 140 + ------------------------------------------------------------------------ 141 + 142 + offset size description 143 + 144 + 0 4 Chunk ID ('MACG') 145 + 4 4 Chunk size (12) 146 + 0 2 Cylinder 147 + 2 1 Head 148 + 3 1 Sector 149 + 4 1 Sector format 150 + 5 1 Flags 151 + 1 Checksum error in ID field 152 + 2 Checksum error in data field 153 + 4 Missing data mark 154 + 6 12 Tag data 155 + 18 4 Chunk CRC 156 + 157 + 158 + CHUNK "OFFS": Sector position 159 + ------------------------------------------------------------------------ 160 + 161 + offset size description 162 + 163 + 0 4 Chunk ID ('OFFS') 164 + 4 4 Chunk size (4) 165 + 0 4 Sector position in data bits from the start of the track 166 + 4 4 Chunk CRC 167 + 168 + 169 + CHUNK "TIME": Clock rate adjustment 170 + ------------------------------------------------------------------------ 171 + 172 + offset size description 173 + 174 + 0 4 Chunk ID ('TIME') 175 + 4 4 Chunk size (4) 176 + 0 4 Sector read time in data bits 177 + 4 4 Chunk CRC 178 + 179 + - The time it takes to read the data field of this sector is 180 + <sector read time> / <number of bits in data field>. 181 + For example, for a 512 byte sector a sector read time of 4096 182 + would be normal. Larger values would indicate that it takes 183 + longer to read the sector. 184 + 185 + 186 + CRC 187 + ------------------------------------------------------------------------ 188 + 189 + - The algorithm used is big-endian CRC-32 with generator 190 + polynomial 0x1edc6f41. The CRC value is initialized to 0. 191 + 192 + unsigned long psi_crc (const unsigned char *buf, unsigned cnt) 193 + { 194 + unsigned i, j; 195 + unsigned long crc; 196 + 197 + crc = 0; 198 + 199 + for (i = 0; i < cnt; i++) { 200 + crc ^= (unsigned long) (buf[i] & 0xff) << 24; 201 + 202 + for (j = 0; j < 8; j++) { 203 + if (crc & 0x80000000) { 204 + crc = (crc << 1) ^ 0x1edc6f41; 205 + } 206 + else { 207 + crc = crc << 1; 208 + } 209 + } 210 + } 211 + 212 + return (crc & 0xffffffff); 213 + }
+2
src/drivers/psi/Makefile.inc
··· 12 12 psi-img-imd \ 13 13 psi-img-msa \ 14 14 psi-img-pfdc \ 15 + psi-img-psi \ 15 16 psi-img-raw \ 16 17 psi-img-tc \ 17 18 psi-img-td0 \ ··· 44 45 $(rel)/psi-img-pfdc1.o: $(rel)/psi-img-pfdc1.c 45 46 $(rel)/psi-img-pfdc2.o: $(rel)/psi-img-pfdc2.c 46 47 $(rel)/psi-img-pfdc4.o: $(rel)/psi-img-pfdc4.c 48 + $(rel)/psi-img-psi.o: $(rel)/psi-img-psi.c 47 49 $(rel)/psi-img-raw.o: $(rel)/psi-img-raw.c 48 50 $(rel)/psi-img-tc.o: $(rel)/psi-img-tc.c 49 51 $(rel)/psi-img-td0.o: $(rel)/psi-img-td0.c
+1034
src/drivers/psi/psi-img-psi.c
··· 1 + /***************************************************************************** 2 + * pce * 3 + *****************************************************************************/ 4 + 5 + /***************************************************************************** 6 + * File name: src/drivers/psi/psi-img-psi.c * 7 + * Created: 2013-05-29 by Hampa Hug <hampa@hampa.ch> * 8 + * Copyright: (C) 2013 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 "psi.h" 28 + #include "psi-io.h" 29 + 30 + 31 + #define PSI_CHUNK_PSI 0x50534920 32 + #define PSI_CHUNK_TEXT 0x54455854 33 + #define PSI_CHUNK_SECT 0x53454354 34 + #define PSI_CHUNK_IBMM 0x49424d4d 35 + #define PSI_CHUNK_MACG 0x4d414347 36 + #define PSI_CHUNK_OFFS 0x4f464653 37 + #define PSI_CHUNK_TIME 0x54494d45 38 + #define PSI_CHUNK_DATA 0x44415441 39 + #define PSI_CHUNK_END 0x454e4420 40 + 41 + #define PSI_FORMAT_UNK 0x0000 42 + #define PSI_FORMAT_IBMF 0x0100 43 + #define PSI_FORMAT_IBMM_DD 0x0200 44 + #define PSI_FORMAT_IBMM_HD 0x0201 45 + #define PSI_FORMAT_IBMM_ED 0x0202 46 + #define PSI_FORMAT_MACG 0x0300 47 + 48 + #define PSI_CRC_POLY 0x1edc6f41 49 + 50 + #define PSI_FLAG_COMP 0x01 51 + #define PSI_FLAG_ALT 0x02 52 + #define PSI_FLAG_CRC 0x04 53 + 54 + #define PSI_IBMM_CRC_ID 1 55 + #define PSI_IBMM_CRC_DATA 2 56 + #define PSI_IBMM_DEL_DAM 4 57 + #define PSI_IBMM_NO_DAM 8 58 + 59 + #define PSI_MACG_CRC_ID 1 60 + #define PSI_MACG_CRC_DATA 2 61 + #define PSI_MACG_NO_DAM 4 62 + 63 + 64 + static 65 + unsigned long psi_crc (unsigned long crc, const void *buf, unsigned cnt) 66 + { 67 + unsigned i, j; 68 + unsigned val; 69 + unsigned long reg; 70 + const unsigned char *src; 71 + static int tab_ok = 0; 72 + static unsigned long tab[256]; 73 + 74 + if (tab_ok == 0) { 75 + for (i = 0; i < 256; i++) { 76 + reg = (unsigned long) i << 24; 77 + 78 + for (j = 0; j < 8; j++) { 79 + if (reg & 0x80000000) { 80 + reg = (reg << 1) ^ PSI_CRC_POLY; 81 + } 82 + else { 83 + reg = reg << 1; 84 + } 85 + } 86 + 87 + tab[i] = reg; 88 + } 89 + 90 + tab_ok = 1; 91 + } 92 + 93 + src = buf; 94 + 95 + while (cnt > 0) { 96 + val = (crc >> 24) ^ *(src++); 97 + crc = (crc << 8) ^ tab[val & 0xff]; 98 + cnt -= 1; 99 + } 100 + 101 + return (crc & 0xffffffff); 102 + } 103 + 104 + static 105 + int psi_read_crc (FILE *fp, void *buf, unsigned cnt, unsigned long *crc) 106 + { 107 + if (fread (buf, 1, cnt, fp) != cnt) { 108 + return (1); 109 + } 110 + 111 + if (crc != NULL) { 112 + *crc = psi_crc (*crc, buf, cnt); 113 + } 114 + 115 + return (0); 116 + } 117 + 118 + static 119 + int psi_write_crc (FILE *fp, const void *buf, unsigned cnt, unsigned long *crc) 120 + { 121 + if (crc != NULL) { 122 + *crc = psi_crc (*crc, buf, cnt); 123 + } 124 + 125 + if (fwrite (buf, 1, cnt, fp) != cnt) { 126 + return (1); 127 + } 128 + 129 + return (0); 130 + } 131 + 132 + 133 + static 134 + int psi_skip_chunk (FILE *fp, unsigned long cnt, unsigned long crc) 135 + { 136 + unsigned n; 137 + unsigned char buf[256]; 138 + 139 + while (cnt > 0) { 140 + n = (cnt < 256) ? cnt : 256; 141 + 142 + if (psi_read_crc (fp, buf, n, &crc)) { 143 + return (1); 144 + } 145 + 146 + cnt -= n; 147 + } 148 + 149 + if (psi_read_crc (fp, buf, 4, NULL)) { 150 + return (1); 151 + } 152 + 153 + if (psi_get_uint32_be (buf, 0) != crc) { 154 + fprintf (stderr, "psi: crc error\n"); 155 + return (1); 156 + } 157 + 158 + return (0); 159 + } 160 + 161 + static 162 + int psi_load_header (FILE *fp, unsigned long size, unsigned long crc, unsigned *enc) 163 + { 164 + unsigned long vers; 165 + unsigned char buf[8]; 166 + 167 + if (size < 4) { 168 + return (1); 169 + } 170 + 171 + if (psi_read_crc (fp, buf, 4, &crc)) { 172 + return (1); 173 + } 174 + 175 + vers = psi_get_uint16_be (buf, 0); 176 + 177 + if (vers != 0x0000) { 178 + fprintf (stderr, "psi: unknown version (%lu)\n", vers); 179 + return (1); 180 + } 181 + 182 + switch (psi_get_uint16_be (buf, 2)) { 183 + case PSI_FORMAT_IBMF: 184 + *enc = PSI_ENC_FM_DD; 185 + break; 186 + 187 + case PSI_FORMAT_IBMM_DD: 188 + *enc = PSI_ENC_MFM_DD; 189 + break; 190 + 191 + case PSI_FORMAT_IBMM_HD: 192 + *enc = PSI_ENC_MFM_HD; 193 + break; 194 + 195 + case PSI_FORMAT_IBMM_ED: 196 + *enc = PSI_ENC_MFM_ED; 197 + break; 198 + 199 + case PSI_FORMAT_MACG: 200 + *enc = PSI_ENC_GCR; 201 + break; 202 + 203 + default: 204 + *enc = PSI_ENC_UNKNOWN; 205 + break; 206 + } 207 + 208 + if (psi_skip_chunk (fp, size - 4, crc)) { 209 + return (1); 210 + } 211 + 212 + return (0); 213 + } 214 + 215 + static 216 + int psi_load_mfm (FILE *fp, psi_img_t *img, psi_sct_t *sct, unsigned long size, unsigned long crc) 217 + { 218 + unsigned char buf[8]; 219 + 220 + if (sct == NULL) { 221 + return (1); 222 + } 223 + 224 + if (size < 6) { 225 + return (1); 226 + } 227 + 228 + if (psi_read_crc (fp, buf, 6, &crc)) { 229 + return (1); 230 + } 231 + 232 + sct->c = buf[0]; 233 + sct->h = buf[1]; 234 + sct->s = buf[2]; 235 + psi_sct_set_mfm_size (sct, buf[3]); 236 + 237 + if (buf[4] & PSI_IBMM_CRC_ID) { 238 + sct->flags |= PSI_FLAG_CRC_ID; 239 + } 240 + 241 + if (buf[4] & PSI_IBMM_CRC_DATA) { 242 + sct->flags |= PSI_FLAG_CRC_DATA; 243 + } 244 + 245 + if (buf[4] & PSI_IBMM_DEL_DAM) { 246 + sct->flags |= PSI_FLAG_DEL_DAM; 247 + } 248 + 249 + if (buf[4] & PSI_IBMM_NO_DAM) { 250 + sct->flags |= PSI_FLAG_NO_DAM; 251 + } 252 + 253 + switch (buf[5]) { 254 + case 1: 255 + psi_sct_set_encoding (sct, PSI_ENC_MFM_HD); 256 + break; 257 + 258 + case 2: 259 + psi_sct_set_encoding (sct, PSI_ENC_MFM_ED); 260 + break; 261 + 262 + default: 263 + psi_sct_set_encoding (sct, PSI_ENC_MFM_DD); 264 + break; 265 + } 266 + 267 + if (psi_skip_chunk (fp, size - 6, crc)) { 268 + return (1); 269 + } 270 + 271 + return (0); 272 + } 273 + 274 + static 275 + int psi_load_macg (FILE *fp, psi_img_t *img, psi_sct_t *sct, unsigned long size, unsigned long crc) 276 + { 277 + unsigned char buf[18]; 278 + 279 + if (sct == NULL) { 280 + return (1); 281 + } 282 + 283 + if (size < 18) { 284 + return (1); 285 + } 286 + 287 + if (psi_read_crc (fp, buf, 18, &crc)) { 288 + return (1); 289 + } 290 + 291 + sct->c = psi_get_uint16_be (buf, 0); 292 + sct->h = buf[2]; 293 + sct->s = buf[3]; 294 + psi_sct_set_gcr_format (sct, buf[4]); 295 + 296 + if (buf[5] & PSI_MACG_CRC_ID) { 297 + sct->flags |= PSI_FLAG_CRC_ID; 298 + } 299 + 300 + if (buf[5] & PSI_MACG_CRC_DATA) { 301 + sct->flags |= PSI_FLAG_CRC_DATA; 302 + } 303 + 304 + if (buf[5] & PSI_MACG_NO_DAM) { 305 + sct->flags |= PSI_FLAG_NO_DAM; 306 + } 307 + 308 + psi_sct_set_encoding (sct, PSI_ENC_GCR); 309 + 310 + psi_sct_set_tags (sct, buf + 6, 12); 311 + 312 + if (psi_skip_chunk (fp, size - 18, crc)) { 313 + return (1); 314 + } 315 + 316 + return (0); 317 + } 318 + 319 + static 320 + int psi_load_offs (FILE *fp, psi_img_t *img, psi_sct_t *sct, unsigned long size, unsigned long crc) 321 + { 322 + unsigned char buf[4]; 323 + 324 + if ((sct == NULL) || (size < 4)) { 325 + return (1); 326 + } 327 + 328 + if (psi_read_crc (fp, buf, 4, &crc)) { 329 + return (1); 330 + } 331 + 332 + psi_sct_set_position (sct, psi_get_uint32_be (buf, 0)); 333 + 334 + if (psi_skip_chunk (fp, size - 4, crc)) { 335 + return (1); 336 + } 337 + 338 + return (0); 339 + } 340 + 341 + static 342 + int psi_load_time (FILE *fp, psi_img_t *img, psi_sct_t *sct, unsigned long size, unsigned long crc) 343 + { 344 + unsigned char buf[4]; 345 + 346 + if ((sct == NULL) || (size < 4)) { 347 + return (1); 348 + } 349 + 350 + if (psi_read_crc (fp, buf, 4, &crc)) { 351 + return (1); 352 + } 353 + 354 + sct->time = psi_get_uint32_be (buf, 0); 355 + 356 + if (psi_skip_chunk (fp, size - 4, crc)) { 357 + return (1); 358 + } 359 + 360 + return (0); 361 + } 362 + 363 + static 364 + int psi_load_sect (FILE *fp, psi_img_t *img, psi_sct_t **last, unsigned long size, unsigned long crc, unsigned enc) 365 + { 366 + unsigned c, h, s, f, n; 367 + unsigned char buf[8]; 368 + psi_sct_t *sct; 369 + 370 + if (size < 8) { 371 + return (1); 372 + } 373 + 374 + if (psi_read_crc (fp, buf, 8, &crc)) { 375 + return (1); 376 + } 377 + 378 + c = psi_get_uint16_be (buf, 0); 379 + h = buf[2]; 380 + s = buf[3]; 381 + n = psi_get_uint16_be (buf, 4); 382 + f = buf[6]; 383 + 384 + if ((sct = psi_sct_new (c, h, s, n)) == NULL) { 385 + return (1); 386 + } 387 + 388 + if (f & PSI_FLAG_ALT) { 389 + if (*last == NULL) { 390 + fprintf (stderr, "psi: orphaned alternate sector\n"); 391 + psi_sct_del (sct); 392 + return (1); 393 + } 394 + 395 + psi_sct_add_alternate (*last, sct); 396 + } 397 + else { 398 + if (psi_img_add_sector (img, sct, c, h)) { 399 + psi_sct_del (sct); 400 + return (1); 401 + } 402 + } 403 + 404 + if (f & PSI_FLAG_CRC) { 405 + sct->flags |= PSI_FLAG_CRC_DATA; 406 + } 407 + 408 + psi_sct_set_encoding (sct, enc); 409 + 410 + size -= 8; 411 + 412 + if (f & PSI_FLAG_COMP) { 413 + psi_sct_fill (sct, buf[7]); 414 + } 415 + 416 + *last = sct; 417 + 418 + if (psi_skip_chunk (fp, size, crc)) { 419 + return (1); 420 + } 421 + 422 + return (0); 423 + } 424 + 425 + static 426 + int psi_load_data (FILE *fp, psi_img_t *img, psi_sct_t *sct, unsigned long size, unsigned long crc) 427 + { 428 + if (sct == NULL) { 429 + return (1); 430 + } 431 + 432 + if (psi_sct_set_size (sct, size, 0)) { 433 + return (1); 434 + } 435 + 436 + if (size > 0) { 437 + if (psi_read_crc (fp, sct->data, size, &crc)) { 438 + return (1); 439 + } 440 + } 441 + 442 + if (psi_skip_chunk (fp, 0, crc)) { 443 + return (1); 444 + } 445 + 446 + return (0); 447 + } 448 + 449 + static 450 + int psi_load_text (FILE *fp, psi_img_t *img, unsigned long size, unsigned long crc) 451 + { 452 + int r; 453 + unsigned long i, n; 454 + unsigned char *buf; 455 + 456 + if (size == 0) { 457 + return (psi_skip_chunk (fp, size, crc)); 458 + } 459 + 460 + if ((buf = malloc (size)) == NULL) { 461 + return (1); 462 + } 463 + 464 + if (psi_read_crc (fp, buf, size, &crc)) { 465 + free (buf); 466 + return (1); 467 + } 468 + 469 + i = 0; 470 + n = size; 471 + 472 + if (buf[0] == 0x0a) { 473 + i = 1; 474 + n -= 1; 475 + } 476 + 477 + if ((n > 0) && (buf[n - 1] == 0x0a)) { 478 + n -= 1; 479 + } 480 + 481 + r = psi_img_add_comment (img, buf + i, n); 482 + 483 + free (buf); 484 + 485 + r |= psi_skip_chunk (fp, 0, crc); 486 + 487 + return (r); 488 + } 489 + 490 + static 491 + int psi_load_end (FILE *fp, psi_img_t *img, unsigned long size, unsigned long crc) 492 + { 493 + if (psi_skip_chunk (fp, size, crc)) { 494 + return (1); 495 + } 496 + 497 + psi_img_clean_comment (img); 498 + 499 + return (0); 500 + } 501 + 502 + static 503 + int psi_load_fp (FILE *fp, psi_img_t *img) 504 + { 505 + unsigned long ckid, size, crc; 506 + unsigned enc; 507 + psi_sct_t *last; 508 + unsigned char buf[8]; 509 + 510 + crc = 0; 511 + 512 + if (psi_read_crc (fp, buf, 8, &crc)) { 513 + return (1); 514 + } 515 + 516 + ckid = psi_get_uint32_be (buf, 0); 517 + size = psi_get_uint32_be (buf, 4); 518 + 519 + if (ckid != PSI_CHUNK_PSI) { 520 + return (1); 521 + } 522 + 523 + if (psi_load_header (fp, size, crc, &enc)) { 524 + return (1); 525 + } 526 + 527 + last = NULL; 528 + 529 + while (1) { 530 + crc = 0; 531 + 532 + if (psi_read_crc (fp, buf, 8, &crc)) { 533 + return (1); 534 + } 535 + 536 + ckid = psi_get_uint32_be (buf, 0); 537 + size = psi_get_uint32_be (buf, 4); 538 + 539 + switch (ckid) { 540 + case PSI_CHUNK_END: 541 + if (psi_load_end (fp, img, size, crc)) { 542 + return (1); 543 + } 544 + return (0); 545 + 546 + case PSI_CHUNK_SECT: 547 + if (psi_load_sect (fp, img, &last, size, crc, enc)) { 548 + return (1); 549 + } 550 + break; 551 + 552 + case PSI_CHUNK_IBMM: 553 + if (psi_load_mfm (fp, img, last, size, crc)) { 554 + return (1); 555 + } 556 + break; 557 + 558 + case PSI_CHUNK_MACG: 559 + if (psi_load_macg (fp, img, last, size, crc)) { 560 + return (1); 561 + } 562 + break; 563 + 564 + case PSI_CHUNK_OFFS: 565 + if (psi_load_offs (fp, img, last, size, crc)) { 566 + return (1); 567 + } 568 + break; 569 + 570 + case PSI_CHUNK_TIME: 571 + if (psi_load_time (fp, img, last, size, crc)) { 572 + return (1); 573 + } 574 + break; 575 + 576 + case PSI_CHUNK_DATA: 577 + if (psi_load_data (fp, img, last, size, crc)) { 578 + return (1); 579 + } 580 + break; 581 + 582 + case PSI_CHUNK_TEXT: 583 + if (psi_load_text (fp, img, size, crc)) { 584 + return (1); 585 + } 586 + break; 587 + 588 + default: 589 + if (psi_skip_chunk (fp, size, crc)) { 590 + return (1); 591 + } 592 + break; 593 + } 594 + } 595 + 596 + return (1); 597 + } 598 + 599 + psi_img_t *psi_load_psi (FILE *fp) 600 + { 601 + psi_img_t *img; 602 + 603 + if ((img = psi_img_new()) == NULL) { 604 + return (NULL); 605 + } 606 + 607 + if (psi_load_fp (fp, img)) { 608 + psi_img_del (img); 609 + return (NULL); 610 + } 611 + 612 + return (img); 613 + } 614 + 615 + 616 + static 617 + int psi_save_chunk (FILE *fp, unsigned ckid, unsigned size, const void *data) 618 + { 619 + unsigned long crc; 620 + unsigned char buf[8]; 621 + 622 + psi_set_uint32_be (buf, 0, ckid); 623 + psi_set_uint32_be (buf, 4, size); 624 + 625 + crc = 0; 626 + 627 + if (psi_write_crc (fp, buf, 8, &crc)) { 628 + return (1); 629 + } 630 + 631 + if (size > 0) { 632 + if (psi_write_crc (fp, data, size, &crc)) { 633 + return (1); 634 + } 635 + } 636 + 637 + psi_set_uint32_be (buf, 0, crc); 638 + 639 + if (psi_write_crc (fp, buf, 4, NULL)) { 640 + return (1); 641 + } 642 + 643 + return (0); 644 + } 645 + 646 + static 647 + unsigned psi_get_default_encoding (const psi_img_t *img) 648 + { 649 + unsigned c, h, s; 650 + const psi_cyl_t *cyl; 651 + const psi_trk_t *trk; 652 + const psi_sct_t *sct; 653 + 654 + for (c = 0; c < img->cyl_cnt; c++) { 655 + cyl = img->cyl[c]; 656 + 657 + for (h = 0; h < cyl->trk_cnt; h++) { 658 + trk = cyl->trk[h]; 659 + 660 + for (s = 0; s < trk->sct_cnt; s++) { 661 + sct = trk->sct[s]; 662 + 663 + return (sct->encoding); 664 + } 665 + } 666 + } 667 + 668 + return (PSI_ENC_UNKNOWN); 669 + } 670 + 671 + static 672 + int psi_save_header (FILE *fp, const psi_img_t *img, unsigned *enc) 673 + { 674 + unsigned val; 675 + unsigned char buf[4]; 676 + 677 + psi_set_uint16_be (buf, 0, 0); 678 + 679 + *enc = psi_get_default_encoding (img); 680 + 681 + switch (*enc) { 682 + case PSI_ENC_FM_DD: 683 + val = PSI_FORMAT_IBMF; 684 + break; 685 + 686 + case PSI_ENC_MFM_DD: 687 + val = PSI_FORMAT_IBMM_DD; 688 + break; 689 + 690 + case PSI_ENC_MFM_HD: 691 + val = PSI_FORMAT_IBMM_HD; 692 + break; 693 + 694 + case PSI_ENC_MFM_ED: 695 + val = PSI_FORMAT_IBMM_ED; 696 + break; 697 + 698 + case PSI_ENC_GCR: 699 + val = PSI_FORMAT_MACG; 700 + break; 701 + 702 + default: 703 + val = PSI_FORMAT_UNK; 704 + break; 705 + } 706 + 707 + psi_set_uint16_be (buf, 2, val); 708 + 709 + if (psi_save_chunk (fp, PSI_CHUNK_PSI, 4, buf)) { 710 + return (1); 711 + } 712 + 713 + return (0); 714 + } 715 + 716 + static 717 + int psi_save_mfm (FILE *fp, const psi_sct_t *sct, unsigned c, unsigned h, unsigned enc) 718 + { 719 + unsigned n; 720 + int req; 721 + unsigned char buf[8]; 722 + 723 + if ((sct->encoding & PSI_ENC_MASK) != PSI_ENC_MFM) { 724 + return (0); 725 + } 726 + 727 + n = psi_sct_get_mfm_size (sct); 728 + 729 + req = (sct->c != c) || (sct->h != h); 730 + req |= ((n > 8) || (sct->n != (128U << n))); 731 + req |= (sct->flags & (PSI_FLAG_CRC_ID | PSI_FLAG_DEL_DAM | PSI_FLAG_NO_DAM)) != 0; 732 + req |= (sct->encoding != enc); 733 + 734 + if (req == 0) { 735 + return (0); 736 + } 737 + 738 + buf[0] = sct->c & 0xff; 739 + buf[1] = sct->h & 0xff; 740 + buf[2] = sct->s & 0xff; 741 + buf[3] = n; 742 + buf[4] = 0; 743 + 744 + buf[4] |= (sct->flags & PSI_FLAG_CRC_ID) ? PSI_IBMM_CRC_ID : 0; 745 + buf[4] |= (sct->flags & PSI_FLAG_CRC_DATA) ? PSI_IBMM_CRC_DATA : 0; 746 + buf[4] |= (sct->flags & PSI_FLAG_DEL_DAM) ? PSI_IBMM_DEL_DAM : 0; 747 + buf[4] |= (sct->flags & PSI_FLAG_NO_DAM) ? PSI_IBMM_NO_DAM : 0; 748 + 749 + switch (sct->encoding) { 750 + case PSI_ENC_MFM_DD: 751 + buf[5] = 0; 752 + break; 753 + 754 + case PSI_ENC_MFM_HD: 755 + buf[5] = 1; 756 + break; 757 + 758 + case PSI_ENC_MFM_ED: 759 + buf[5] = 2; 760 + break; 761 + 762 + default: 763 + buf[5] = 0; 764 + break; 765 + } 766 + 767 + if (psi_save_chunk (fp, PSI_CHUNK_IBMM, 6, buf)) { 768 + return (1); 769 + } 770 + 771 + return (0); 772 + } 773 + 774 + static 775 + int psi_save_macg (FILE *fp, const psi_sct_t *sct, unsigned c, unsigned h, unsigned enc) 776 + { 777 + unsigned i; 778 + int req; 779 + unsigned char buf[18]; 780 + 781 + if ((sct->encoding & PSI_ENC_MASK) != PSI_ENC_GCR) { 782 + return (0); 783 + } 784 + 785 + req = (sct->c != c) || (sct->h != h); 786 + req |= ((sct->flags & (PSI_FLAG_CRC_ID | PSI_FLAG_NO_DAM)) != 0); 787 + req |= (sct->encoding != enc); 788 + 789 + if (psi_sct_get_tags (sct, buf + 6, 12) > 0) { 790 + for (i = 0; i < 12; i++) { 791 + req |= (buf[6 + i] != 0); 792 + } 793 + } 794 + 795 + if (req == 0) { 796 + return (0); 797 + } 798 + 799 + psi_set_uint16_be (buf, 0, sct->c); 800 + buf[2] = sct->h & 0xff; 801 + buf[3] = sct->s & 0xff; 802 + buf[4] = psi_sct_get_gcr_format (sct); 803 + buf[5] = 0; 804 + 805 + buf[5] |= (sct->flags & PSI_FLAG_CRC_ID) ? PSI_MACG_CRC_ID : 0; 806 + buf[5] |= (sct->flags & PSI_FLAG_CRC_DATA) ? PSI_MACG_CRC_DATA : 0; 807 + buf[5] |= (sct->flags & PSI_FLAG_NO_DAM) ? PSI_MACG_NO_DAM : 0; 808 + 809 + if (psi_save_chunk (fp, PSI_CHUNK_MACG, 18, buf)) { 810 + return (1); 811 + } 812 + 813 + return (0); 814 + } 815 + 816 + static 817 + int psi_save_offs (FILE *fp, const psi_sct_t *sct) 818 + { 819 + unsigned long pos; 820 + unsigned char buf[4]; 821 + 822 + pos = psi_sct_get_position (sct); 823 + 824 + if (pos == 0xffffffff) { 825 + return (0); 826 + } 827 + 828 + psi_set_uint32_be (buf, 0, pos); 829 + 830 + if (psi_save_chunk (fp, PSI_CHUNK_OFFS, 4, buf)) { 831 + return (1); 832 + } 833 + 834 + return (0); 835 + } 836 + 837 + static 838 + int psi_save_time (FILE *fp, const psi_sct_t *sct) 839 + { 840 + unsigned long val; 841 + unsigned char buf[4]; 842 + 843 + val = sct->time; 844 + 845 + if ((val == 0) || (val == (8UL * sct->n))) { 846 + return (0); 847 + } 848 + 849 + psi_set_uint32_be (buf, 0, val); 850 + 851 + if (psi_save_chunk (fp, PSI_CHUNK_TIME, 4, buf)) { 852 + return (1); 853 + } 854 + 855 + return (0); 856 + } 857 + 858 + static 859 + int psi_save_sector (FILE *fp, const psi_sct_t *sct, unsigned c, unsigned h, int alt, unsigned enc) 860 + { 861 + unsigned f; 862 + unsigned char buf[8]; 863 + 864 + f = alt ? PSI_FLAG_ALT : 0; 865 + 866 + if (psi_sct_uniform (sct) && (sct->n > 0)) { 867 + f |= PSI_FLAG_COMP; 868 + } 869 + 870 + if (sct->flags & PSI_FLAG_CRC_DATA) { 871 + f |= PSI_FLAG_CRC; 872 + } 873 + 874 + psi_set_uint16_be (buf, 0, c); 875 + buf[2] = h & 0xff; 876 + buf[3] = sct->s & 0xff; 877 + psi_set_uint16_be (buf, 4, sct->n); 878 + buf[6] = f; 879 + buf[7] = 0; 880 + 881 + if (f & PSI_FLAG_COMP) { 882 + buf[7] = sct->data[0]; 883 + } 884 + 885 + if (psi_save_chunk (fp, PSI_CHUNK_SECT, 8, buf)) { 886 + return (1); 887 + } 888 + 889 + if (psi_save_mfm (fp, sct, c, h, enc)) { 890 + return (1); 891 + } 892 + 893 + if (psi_save_macg (fp, sct, c, h, enc)) { 894 + return (1); 895 + } 896 + 897 + if (psi_save_offs (fp, sct)) { 898 + return (1); 899 + } 900 + 901 + if (psi_save_time (fp, sct)) { 902 + return (1); 903 + } 904 + 905 + if ((f & PSI_FLAG_COMP) == 0) { 906 + if (sct->n > 0) { 907 + if (psi_save_chunk (fp, PSI_CHUNK_DATA, sct->n, sct->data)) { 908 + return (1); 909 + } 910 + } 911 + } 912 + 913 + return (0); 914 + } 915 + 916 + static 917 + int psi_save_alternates (FILE *fp, const psi_sct_t *sct, unsigned c, unsigned h, unsigned enc) 918 + { 919 + if (psi_save_sector (fp, sct, c, h, 0, enc)) { 920 + return (1); 921 + } 922 + 923 + sct = sct->next; 924 + 925 + while (sct != NULL) { 926 + if (psi_save_sector (fp, sct, c, h, 1, enc)) { 927 + return (1); 928 + } 929 + 930 + sct = sct->next; 931 + } 932 + 933 + return (0); 934 + } 935 + 936 + static 937 + int psi_save_text (FILE *fp, const psi_img_t *img) 938 + { 939 + int r; 940 + unsigned long crc; 941 + unsigned char buf[16]; 942 + 943 + if (img->comment_size == 0) { 944 + return (0); 945 + } 946 + 947 + psi_set_uint32_be (buf, 0, PSI_CHUNK_TEXT); 948 + psi_set_uint32_be (buf, 4, img->comment_size + 2); 949 + 950 + buf[8] = 0x0a; 951 + 952 + crc = 0; 953 + 954 + r = psi_write_crc (fp, buf, 9, &crc); 955 + r |= psi_write_crc (fp, img->comment, img->comment_size, &crc); 956 + r |= psi_write_crc (fp, buf + 8, 1, &crc); 957 + psi_set_uint32_be (buf, 0, crc); 958 + r |= psi_write_crc (fp, buf, 4, NULL); 959 + 960 + return (r); 961 + } 962 + 963 + int psi_save_psi (FILE *fp, const psi_img_t *img) 964 + { 965 + unsigned c, h, s; 966 + unsigned enc; 967 + const psi_cyl_t *cyl; 968 + const psi_trk_t *trk; 969 + const psi_sct_t *sct; 970 + 971 + if (psi_save_header (fp, img, &enc)) { 972 + return (1); 973 + } 974 + 975 + if (psi_save_text (fp, img)) { 976 + return (1); 977 + } 978 + 979 + for (c = 0; c < img->cyl_cnt; c++) { 980 + cyl = img->cyl[c]; 981 + 982 + for (h = 0; h < cyl->trk_cnt; h++) { 983 + trk = cyl->trk[h]; 984 + 985 + for (s = 0; s < trk->sct_cnt; s++) { 986 + sct = trk->sct[s]; 987 + 988 + if (psi_save_alternates (fp, sct, c, h, enc)) { 989 + return (1); 990 + } 991 + } 992 + } 993 + } 994 + 995 + if (psi_save_chunk (fp, PSI_CHUNK_END, 0, NULL)) { 996 + return (1); 997 + } 998 + 999 + fflush (fp); 1000 + 1001 + return (0); 1002 + } 1003 + 1004 + 1005 + int psi_probe_psi_fp (FILE *fp) 1006 + { 1007 + unsigned char buf[4]; 1008 + 1009 + if (psi_read_ofs (fp, 0, buf, 4)) { 1010 + return (0); 1011 + } 1012 + 1013 + if (psi_get_uint32_be (buf, 0) != PSI_CHUNK_PSI) { 1014 + return (0); 1015 + } 1016 + 1017 + return (1); 1018 + } 1019 + 1020 + int psi_probe_psi (const char *fname) 1021 + { 1022 + int r; 1023 + FILE *fp; 1024 + 1025 + if ((fp = fopen (fname, "rb")) == NULL) { 1026 + return (0); 1027 + } 1028 + 1029 + r = psi_probe_psi_fp (fp); 1030 + 1031 + fclose (fp); 1032 + 1033 + return (r); 1034 + }
+38
src/drivers/psi/psi-img-psi.h
··· 1 + /***************************************************************************** 2 + * pce * 3 + *****************************************************************************/ 4 + 5 + /***************************************************************************** 6 + * File name: src/drivers/psi/psi-img-psi.h * 7 + * Created: 2013-05-29 by Hampa Hug <hampa@hampa.ch> * 8 + * Copyright: (C) 2013 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 PSI_IMG_PSI_H 24 + #define PSI_IMG_PSI_H 1 25 + 26 + 27 + #include <drivers/psi/psi.h> 28 + 29 + 30 + psi_img_t *psi_load_psi (FILE *fp); 31 + 32 + int psi_save_psi (FILE *fp, const psi_img_t *img); 33 + 34 + int psi_probe_psi_fp (FILE *fp); 35 + int psi_probe_psi (const char *fname); 36 + 37 + 38 + #endif
+15 -1
src/drivers/psi/psi-img.c
··· 32 32 #include "psi-img-imd.h" 33 33 #include "psi-img-msa.h" 34 34 #include "psi-img-pfdc.h" 35 + #include "psi-img-psi.h" 35 36 #include "psi-img-raw.h" 36 37 #include "psi-img-tc.h" 37 38 #include "psi-img-td0.h" ··· 86 87 else if (strcasecmp (ext, ".pfdc") == 0) { 87 88 return (PSI_FORMAT_PFDC); 88 89 } 90 + else if (strcasecmp (ext, ".psi") == 0) { 91 + return (PSI_FORMAT_PSI); 92 + } 89 93 else if (strcasecmp (ext, ".raw") == 0) { 90 94 return (PSI_FORMAT_RAW); 91 95 } ··· 102 106 return (PSI_FORMAT_XDF); 103 107 } 104 108 105 - return (PSI_FORMAT_PFDC); 109 + return (PSI_FORMAT_PSI); 106 110 } 107 111 108 112 psi_img_t *psi_load_fp (FILE *fp, unsigned type) ··· 130 134 case PSI_FORMAT_PFDC4: 131 135 return (psi_load_pfdc (fp)); 132 136 137 + case PSI_FORMAT_PSI: 138 + return (psi_load_psi (fp)); 139 + 133 140 case PSI_FORMAT_RAW: 134 141 return (psi_load_raw (fp)); 135 142 ··· 209 216 case PSI_FORMAT_PFDC4: 210 217 return (psi_save_pfdc (fp, img, 4)); 211 218 219 + case PSI_FORMAT_PSI: 220 + return (psi_save_psi (fp, img)); 221 + 212 222 case PSI_FORMAT_RAW: 213 223 return (psi_save_raw (fp, img)); 214 224 ··· 250 260 251 261 unsigned psi_probe_fp (FILE *fp) 252 262 { 263 + if (psi_probe_psi_fp (fp)) { 264 + return (PSI_FORMAT_PSI); 265 + } 266 + 253 267 if (psi_probe_pfdc_fp (fp)) { 254 268 return (PSI_FORMAT_PFDC); 255 269 }
+6 -5
src/drivers/psi/psi-img.h
··· 38 38 #define PSI_FORMAT_PFDC1 8 39 39 #define PSI_FORMAT_PFDC2 9 40 40 #define PSI_FORMAT_PFDC4 10 41 - #define PSI_FORMAT_RAW 11 42 - #define PSI_FORMAT_ST 12 43 - #define PSI_FORMAT_TC 13 44 - #define PSI_FORMAT_TD0 14 45 - #define PSI_FORMAT_XDF 15 41 + #define PSI_FORMAT_PSI 11 42 + #define PSI_FORMAT_RAW 12 43 + #define PSI_FORMAT_ST 13 44 + #define PSI_FORMAT_TC 14 45 + #define PSI_FORMAT_TD0 15 46 + #define PSI_FORMAT_XDF 16 46 47 47 48 48 49 unsigned psi_guess_type (const char *fname);
+3
src/lib/inidsk.c
··· 320 320 else if (strcmp (type, "pfdc-auto") == 0) { 321 321 dsk = dsk_psi_open (path, PSI_FORMAT_NONE, ro); 322 322 } 323 + else if (strcmp (type, "psi") == 0) { 324 + dsk = dsk_psi_open (path, PSI_FORMAT_PSI, ro); 325 + } 323 326 else if (strcmp (type, "teledisk") == 0) { 324 327 dsk = dsk_psi_open (path, PSI_FORMAT_TD0, ro); 325 328 }
+3
src/utils/psi/main.c
··· 2381 2381 else if (strcmp (name, "pfdc4") == 0) { 2382 2382 *val = PSI_FORMAT_PFDC4; 2383 2383 } 2384 + else if (strcmp (name, "psi") == 0) { 2385 + *val = PSI_FORMAT_PSI; 2386 + } 2384 2387 else if (strcmp (name, "raw") == 0) { 2385 2388 *val = PSI_FORMAT_RAW; 2386 2389 }