fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 286 lines 5.0 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/lib/ciff.c * 7 * Created: 2022-02-12 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2022 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 <config.h> 24 25#include <lib/ciff.h> 26#include <lib/endian.h> 27 28#include <stdint.h> 29#include <stdio.h> 30 31 32#define CIFF_CRC_POLY 0x1edc6f41 33 34 35static char crc_tab_ok = 0; 36static uint32_t crc_tab[256]; 37 38 39static 40void ciff_init_crc_tab (void) 41{ 42 unsigned i, j; 43 uint32_t val; 44 45 if (crc_tab_ok) { 46 return; 47 } 48 49 for (i = 0; i < 256; i++) { 50 val = (uint32_t) i << 24; 51 52 for (j = 0; j < 8; j++) { 53 if (val & 0x80000000) { 54 val = (val << 1) ^ CIFF_CRC_POLY; 55 } 56 else { 57 val = val << 1; 58 } 59 } 60 61 crc_tab[i] = val; 62 } 63 64 crc_tab_ok = 1; 65} 66 67static 68void ciff_crc (ciff_t *ciff, const void *buf, uint32_t cnt) 69{ 70 uint32_t crc; 71 const uint8_t *src; 72 73 if (crc_tab_ok == 0) { 74 ciff_init_crc_tab(); 75 } 76 77 src = buf; 78 crc = ciff->crc; 79 80 while (cnt-- > 0) { 81 crc = (crc << 8) ^ crc_tab[((crc >> 24) ^ *(src++)) & 0xff]; 82 } 83 84 ciff->crc = crc & 0xffffffff; 85} 86 87void ciff_init (ciff_t *ciff, FILE *fp, int use_crc) 88{ 89 ciff->fp = fp; 90 91 ciff->crc = 0; 92 93 ciff->ckid = 0; 94 ciff->cksize = 0; 95 96 ciff->size = 0; 97 98 ciff->in_chunk = 0; 99 ciff->use_crc = (use_crc != 0); 100 ciff->crc_error = 0; 101} 102 103void ciff_free (ciff_t *ciff) 104{ 105} 106 107int ciff_read (ciff_t *ciff, void *buf, uint32_t cnt) 108{ 109 uint32_t ret; 110 111 if (cnt > ciff->size) { 112 return (1); 113 } 114 115 ret = fread (buf, 1, cnt, ciff->fp); 116 117 ciff->size -= ret; 118 119 if (ciff->use_crc) { 120 ciff_crc (ciff, buf, ret); 121 } 122 123 return (ret != cnt); 124} 125 126int ciff_read_id (ciff_t *ciff) 127{ 128 unsigned char buf[8]; 129 130 if (ciff->in_chunk) { 131 if (ciff_read_crc (ciff)) { 132 return (1); 133 } 134 } 135 136 ciff->crc = 0; 137 ciff->size = 8; 138 139 if (ciff_read (ciff, buf, 8)) { 140 return (1); 141 } 142 143 ciff->ckid = get_uint32_be (buf, 0); 144 ciff->cksize = get_uint32_be (buf, 4); 145 146 ciff->size = ciff->cksize; 147 148 ciff->in_chunk = 1; 149 150 return (0); 151} 152 153int ciff_read_crc (ciff_t *ciff) 154{ 155 unsigned cnt; 156 uint32_t crc; 157 unsigned char buf[256]; 158 159 while (ciff->size > 0) { 160 cnt = (ciff->size < 256) ? ciff->size : 256; 161 162 if (ciff_read (ciff, buf, cnt)) { 163 return (1); 164 } 165 } 166 167 if (ciff->use_crc) { 168 crc = ciff->crc; 169 ciff->size = 4; 170 171 if (ciff_read (ciff, buf, 4)) { 172 return (1); 173 } 174 175 if (get_uint32_be (buf, 0) != crc) { 176 ciff->crc_error = 1; 177 return (1); 178 } 179 } 180 181 ciff->in_chunk = 0; 182 183 return (0); 184} 185 186int ciff_read_chunk (ciff_t *ciff, void *buf, uint32_t size) 187{ 188 if (ciff_read (ciff, buf, size)) { 189 return (1); 190 } 191 192 if (ciff_read_crc (ciff)) { 193 return (1); 194 } 195 196 return (0); 197} 198 199int ciff_write (ciff_t *ciff, const void *buf, uint32_t cnt) 200{ 201 uint32_t ret; 202 203 if (cnt > ciff->size) { 204 return (1); 205 } 206 207 ret = fwrite (buf, 1, cnt, ciff->fp); 208 209 ciff->size -= ret; 210 211 if (ciff->use_crc) { 212 ciff_crc (ciff, buf, cnt); 213 } 214 215 return (ret != cnt); 216} 217 218int ciff_write_id (ciff_t *ciff, uint32_t ckid, uint32_t size) 219{ 220 unsigned char buf[8]; 221 222 if (ciff->in_chunk) { 223 if (ciff_write_crc (ciff)) { 224 return (1); 225 } 226 } 227 228 ciff->ckid = ckid; 229 ciff->cksize = size; 230 231 set_uint32_be (buf, 0, ckid); 232 set_uint32_be (buf, 4, size); 233 234 ciff->crc = 0; 235 ciff->size = 8; 236 237 if (ciff_write (ciff, buf, 8)) { 238 return (1); 239 } 240 241 ciff->size = size; 242 243 ciff->in_chunk = 1; 244 245 return (0); 246} 247 248int ciff_write_crc (ciff_t *ciff) 249{ 250 unsigned char buf[4]; 251 252 if (ciff->size != 0) { 253 return (1); 254 } 255 256 if (ciff->use_crc) { 257 set_uint32_be (buf, 0, ciff->crc); 258 259 ciff->size = 4; 260 261 if (ciff_write (ciff, buf, 4)) { 262 return (1); 263 } 264 } 265 266 ciff->in_chunk = 0; 267 268 return (0); 269} 270 271int ciff_write_chunk (ciff_t *ciff, uint32_t ckid, const void *buf, uint32_t size) 272{ 273 if (ciff_write_id (ciff, ckid, size)) { 274 return (1); 275 } 276 277 if (ciff_write (ciff, buf, size)) { 278 return (1); 279 } 280 281 if (ciff_write_crc (ciff)) { 282 return (1); 283 } 284 285 return (0); 286}