fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 356 lines 6.3 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/utils/aym/encode.c * 7 * Created: 2015-05-21 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2015-2016 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 <stdlib.h> 26#include <stdio.h> 27#include <string.h> 28 29 30static 31int aym_skip_space (FILE *fp) 32{ 33 int c, com; 34 35 com = 0; 36 37 while ((c = fgetc (fp)) != EOF) { 38 if (c == '#') { 39 com = 1; 40 } 41 else if ((c == 0x0a) || (c == 0x0d)) { 42 com = 0; 43 } 44 else if ((c == ' ') || (c == '\t')) { 45 ; 46 } 47 else if (com) { 48 ; 49 } 50 else { 51 ungetc (c, fp); 52 return (0); 53 } 54 } 55 56 return (0); 57} 58 59static 60int aym_get_str (FILE *fp, char *dst, unsigned max) 61{ 62 int c; 63 unsigned i; 64 65 aym_skip_space (fp); 66 67 i = 0; 68 69 while (i < max) { 70 if ((c = fgetc (fp)) == EOF) { 71 break; 72 } 73 74 if ((c >= 'A') && (c <= 'Z')) { 75 ; 76 } 77 else { 78 ungetc (c, fp); 79 break; 80 } 81 82 dst[i++] = c; 83 } 84 85 if ((i == 0) || (i >= max)) { 86 return (1); 87 } 88 89 dst[i++] = 0; 90 91 return (0); 92} 93 94static 95int aym_get_int (FILE *fp, unsigned long long *val) 96{ 97 int c, ok; 98 unsigned dig; 99 100 aym_skip_space (fp); 101 102 ok = 0; 103 104 *val = 0; 105 106 while (1) { 107 if ((c = fgetc (fp)) == EOF) { 108 break; 109 } 110 111 if ((c >= '0') && (c <= '9')) { 112 dig = c - '0'; 113 } 114 else { 115 ungetc (c, fp); 116 break; 117 } 118 119 *val = 10 * *val + dig; 120 121 ok = 1; 122 } 123 124 return (ok == 0); 125} 126 127static 128int aym_get_byte (FILE *fp, unsigned *val) 129{ 130 int c, ok; 131 unsigned dig; 132 133 aym_skip_space (fp); 134 135 ok = 0; 136 137 *val = 0; 138 139 while (1) { 140 if ((c = fgetc (fp)) == EOF) { 141 break; 142 } 143 144 if ((c >= '0') && (c <= '9')) { 145 dig = c - '0'; 146 } 147 else if ((c >= 'A') && (c <= 'F')) { 148 dig = c - 'A' + 10; 149 } 150 else if ((c >= 'a') && (c <= 'f')) { 151 dig = c - 'a' + 10; 152 } 153 else { 154 ungetc (c, fp); 155 break; 156 } 157 158 *val = 16 * *val + dig; 159 160 ok = 1; 161 } 162 163 return (ok == 0); 164} 165 166static 167void aym_write_delay (FILE *out, unsigned long long val) 168{ 169 while (val >= 0xfff000000) { 170 fputc (0x3f, out); 171 fputc (0xff, out); 172 val -= 0xfff000000; 173 } 174 175 if (val & 0xfff000000) { 176 fputc (0x30 | ((val >> 32) & 0x0f), out); 177 fputc ((val >> 24) & 0xff, out); 178 } 179 180 if (val & 0x00fff000) { 181 fputc (0x20 | ((val >> 20) & 0x0f), out); 182 fputc ((val >> 12) & 0xff, out); 183 } 184 185 if (val & 0x00000fff) { 186 fputc (0x10 | ((val >> 8) & 0x0f), out); 187 fputc (val & 0xff, out); 188 } 189} 190 191static 192int aym_encode_text (FILE *inp, FILE *out) 193{ 194 int c; 195 unsigned i, n, type; 196 unsigned long long val; 197 char str[256]; 198 199 if (aym_get_int (inp, &val)) { 200 return (1); 201 } 202 203 type = val & 0x0f; 204 205 n = 0; 206 207 while ((n < 256) && ((c = fgetc (inp)) != EOF)) { 208 if ((c == 0x0d) || (c == 0x0a)) { 209 break; 210 } 211 212 if ((n == 0) && ((c == ' ') || (c == 't'))) { 213 continue; 214 } 215 216 str[n++] = c; 217 } 218 219 if (n > 255) { 220 return (1); 221 } 222 223 while ((n > 0) && ((str[n - 1] == ' ') || (str[n - 1] == '\t'))) { 224 n -= 1; 225 } 226 227 fputc (0x80 | type, out); 228 fputc (n, out); 229 230 for (i = 0; i < n; i++) { 231 fputc (str[i], out); 232 } 233 234 return (0); 235} 236 237static 238int aym_encode_fp (FILE *inp, FILE *out, unsigned long th) 239{ 240 unsigned long long vers, delay; 241 unsigned char buf[8]; 242 char str[256]; 243 244 if (aym_get_str (inp, str, 256)) { 245 return (1); 246 } 247 248 if (strcmp (str, "AYM") != 0) { 249 fprintf (stderr, "%s: bad magic (%s)\n", arg0, str); 250 return (1); 251 } 252 253 if (aym_get_int (inp, &vers)) { 254 return (1); 255 } 256 257 if (vers != 0) { 258 fprintf (stderr, "%s: unknown version (%llu)\n", arg0, vers); 259 return (1); 260 } 261 262 aym_set_uint32_be (buf, 0, AYM_MAGIC); 263 aym_set_uint32_be (buf, 4, 0); 264 265 if (fwrite (buf, 1, 8, out) != 8) { 266 return (1); 267 } 268 269 delay = 0; 270 271 while (1) { 272 if (aym_get_str (inp, str, 256)) { 273 return (1); 274 } 275 276 if (strcmp (str, "DEL") == 0) { 277 unsigned long long val; 278 279 if (aym_get_int (inp, &val)) { 280 return (1); 281 } 282 283 delay += val; 284 } 285 else if (strcmp (str, "END") == 0) { 286 fputc (0xff, out); 287 fputc (0xff, out); 288 break; 289 } 290 else if (strcmp (str, "REG") == 0) { 291 unsigned v1, v2; 292 293 if ((delay > 0) && (delay >= th)) { 294 aym_write_delay (out, delay); 295 delay = 0; 296 } 297 298 if (aym_get_byte (inp, &v1)) { 299 return (1); 300 } 301 302 if (aym_get_byte (inp, &v2)) { 303 return (1); 304 } 305 306 fputc (v1 & 0x0f, out); 307 fputc (v2 & 0xff, out); 308 } 309 else if (strcmp (str, "TXT") == 0) { 310 if (aym_encode_text (inp, out)) { 311 return (1); 312 } 313 } 314 else { 315 fprintf (stderr, "%s: bad keyword (%s)\n", arg0, str); 316 return (1); 317 } 318 } 319 320 return (0); 321} 322 323int aym_encode (const char *inp, const char *out, unsigned long th) 324{ 325 int r; 326 FILE *finp, *fout; 327 328 if (inp == NULL) { 329 finp = stdin; 330 } 331 else if ((finp = fopen (inp, "r")) == NULL) { 332 fprintf (stderr, "%s: can't open input file (%s)\n", arg0, inp); 333 return (1); 334 } 335 336 if (out == NULL) { 337 fout = stdout; 338 } 339 else if ((fout = fopen (out, "wb")) == NULL) { 340 fprintf (stderr, "%s: can't open output file (%s)\n", arg0, out); 341 fclose (finp); 342 return (1); 343 } 344 345 r = aym_encode_fp (finp, fout, th); 346 347 if (fout != stdout) { 348 fclose (fout); 349 } 350 351 if (finp != stdin) { 352 fclose (finp); 353 } 354 355 return (r); 356}