fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/utils/pti/ops.c *
7 * Created: 2020-04-30 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2020-2024 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#include "comment.h"
25#include "ops.h"
26#include "space.h"
27
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31
32#include <lib/getopt.h>
33
34#include <drivers/pti/pti.h>
35#include <drivers/pti/pti-io.h>
36
37
38static
39int pti_get_opt (int argc, char **argv, char ***optarg, unsigned cnt)
40{
41 if (pce_getoptarg (argc, argv, optarg, cnt) != 0) {
42 fprintf (stderr, "%s: missing argument\n", arg0);
43 return (1);
44 }
45
46 return (0);
47}
48
49int pti_cat (pti_img_t **img, const char *fname)
50{
51 unsigned long i;
52 unsigned long clk, rem;
53 int level;
54 pti_img_t *src;
55
56 if ((src = pti_load_image (fname)) == NULL) {
57 return (1);
58 }
59
60 if (*img == NULL) {
61 *img = src;
62 return (0);
63 }
64
65 rem = 0;
66
67 for (i = 0; i < src->pulse_cnt; i++) {
68 pti_pulse_get (src->pulse[i], &clk, &level);
69
70 clk = pti_pulse_convert (clk, (*img)->clock, src->clock, &rem);
71
72 if (pti_img_add_pulse ((*img), clk, level)) {
73 pti_img_del (src);
74 return (1);
75 }
76 }
77
78 pti_img_del (src);
79
80 return (0);
81}
82
83int pti_info (pti_img_t *img)
84{
85 unsigned msc;
86 unsigned long min, sec, clk;
87
88 pti_img_get_length (img, &sec, &clk);
89
90 min = sec / 60;
91 sec = sec % 60;
92 msc = (unsigned) ((1000.0 * clk) / img->clock);
93
94 printf ("time: %02lu:%02lu.%03u\n", min, sec, msc);
95 printf ("clock: %lu\n", pti_img_get_clock (img));
96 printf ("pulses: %lu\n", img->pulse_cnt);
97
98 if (img->comment_size > 0) {
99 fputs ("\n", stdout);
100 pti_comment_show (img);
101 }
102
103 return (0);
104}
105
106int pti_invert (pti_img_t *img)
107{
108 unsigned long i;
109 unsigned long clk;
110 int level;
111
112 for (i = 0; i < img->pulse_cnt; i++) {
113 pti_pulse_get (img->pulse[i], &clk, &level);
114 pti_pulse_set (&img->pulse[i], clk, -level);
115 }
116
117 return (0);
118}
119
120int pti_new (pti_img_t **img)
121{
122 pti_img_del (*img);
123
124 if ((*img = pti_img_new()) == NULL) {
125 return (1);
126 }
127
128 pti_img_set_clock (*img, par_default_clock);
129
130 return (0);
131}
132
133int pti_scale (pti_img_t **img, unsigned long dclk, int set)
134{
135 unsigned long i;
136 unsigned long sclk, rem;
137 unsigned long clk;
138 int level;
139 pti_img_t *dst, *src;
140
141 src = *img;
142
143 if ((dst = pti_img_clone (src, 0)) == NULL) {
144 return (1);
145 }
146
147 sclk = pti_img_get_clock (src);
148
149 rem = 0;
150
151 for (i = 0; i < src->pulse_cnt; i++) {
152 pti_pulse_get (src->pulse[i], &clk, &level);
153
154 clk = pti_pulse_convert (clk, dclk, sclk, &rem);
155
156 if (pti_img_add_pulse (dst, clk, level)) {
157 pti_img_del (src);
158 return (1);
159 }
160 }
161
162 pti_img_del (src);
163
164 if (set) {
165 pti_img_set_clock (dst, dclk);
166 }
167
168 *img = dst;
169
170 return (0);
171}
172
173int pti_trim_left (pti_img_t *img, unsigned long sec, unsigned long clk)
174{
175 unsigned long i, j;
176 unsigned long sec2, clk2;
177 int level;
178
179 for (i = 0; i < img->pulse_cnt; i++) {
180 pti_pulse_get (img->pulse[i], &clk2, &level);
181
182 sec2 = clk2 / img->clock;
183 clk2 = clk2 % img->clock;
184
185 if ((sec2 > sec) || ((sec2 == sec) && (clk2 > clk))) {
186 break;
187 }
188
189 if (clk2 > clk) {
190 sec -= 1;
191 clk += img->clock;
192 }
193
194 clk -= clk2;
195 sec -= sec2;
196 }
197
198 if (i >= img->pulse_cnt) {
199 img->pulse_cnt = 0;
200 return (0);
201 }
202
203 if (clk > clk2) {
204 sec2 -= 1;
205 clk2 += img->clock;
206 }
207
208 clk2 -= clk;
209 sec2 -= sec;
210
211 clk2 += img->clock * sec2;
212
213 pti_pulse_set (img->pulse + i, clk2, level);
214
215 j = 0;
216 while (i < img->pulse_cnt) {
217 img->pulse[j++] = img->pulse[i++];
218 }
219
220 img->pulse_cnt = j;
221
222 return (0);
223}
224
225int pti_trim_right (pti_img_t *img, unsigned long sec, unsigned long clk)
226{
227 unsigned long idx;
228
229 pti_img_get_index (img, &idx, sec, clk);
230
231 if (idx < img->pulse_cnt) {
232 img->pulse_cnt = idx;
233 }
234
235 return (0);
236}
237
238int pti_operation (pti_img_t **img, const char *op, int argc, char **argv)
239{
240 int r;
241 char **optarg;
242
243 if (*img == NULL) {
244 if ((*img = pti_img_new()) == NULL) {
245 return (1);
246 }
247
248 pti_img_set_clock (*img, par_default_clock);
249 }
250
251 r = 1;
252
253 if (strcmp (op, "cat") == 0) {
254 if (pti_get_opt (argc, argv, &optarg, 1)) {
255 return (1);
256 }
257
258 r = pti_cat (img, optarg[0]);
259 }
260 else if (strcmp (op, "comment-add") == 0) {
261 if (pti_get_opt (argc, argv, &optarg, 1)) {
262 return (1);
263 }
264
265 r = pti_comment_add (*img, optarg[0]);
266 }
267 else if (strcmp (op, "comment-load") == 0) {
268 if (pti_get_opt (argc, argv, &optarg, 1)) {
269 return (1);
270 }
271
272 r = pti_comment_load (*img, optarg[0]);
273 }
274 else if (strcmp (op, "comment-print") == 0) {
275 r = pti_comment_show (*img);
276 }
277 else if (strcmp (op, "comment-save") == 0) {
278 if (pti_get_opt (argc, argv, &optarg, 1)) {
279 return (1);
280 }
281
282 r = pti_comment_save (*img, optarg[0]);
283 }
284 else if (strcmp (op, "comment-set") == 0) {
285 if (pti_get_opt (argc, argv, &optarg, 1)) {
286 return (1);
287 }
288
289 r = pti_comment_set (*img, optarg[0]);
290 }
291 else if (strcmp (op, "fix-clock") == 0) {
292 unsigned long clk;
293
294 if (pti_get_opt (argc, argv, &optarg, 1)) {
295 return (1);
296 }
297
298 if (pti_parse_freq (optarg[0], &clk)) {
299 return (1);
300 }
301
302 pti_img_set_clock (*img, clk);
303
304 r = 0;
305 }
306 else if (strcmp (op, "info") == 0) {
307 r = pti_info (*img);
308 }
309 else if (strcmp (op, "invert") == 0) {
310 r = pti_invert (*img);
311 }
312 else if (strcmp (op, "new") == 0) {
313 r = pti_new (img);
314 }
315 else if (strcmp (op, "save-inverted") == 0) {
316 int val;
317
318 if (pti_get_opt (argc, argv, &optarg, 1)) {
319 return (1);
320 }
321
322 if (pti_parse_bool (optarg[0], &val)) {
323 return (1);
324 }
325
326 pti_img_set_inverted (*img, val);
327
328 r = 0;
329 }
330 else if (strcmp (op, "scale") == 0) {
331 double fct;
332
333 if (pti_get_opt (argc, argv, &optarg, 1)) {
334 return (1);
335 }
336
337 if (pti_parse_double (optarg[0], &fct)) {
338 return (1);
339 }
340
341 r = pti_scale (img, (unsigned long) (fct * (*img)->clock), 0);
342 }
343 else if (strcmp (op, "set-clock") == 0) {
344 unsigned long clk;
345
346 if (pti_get_opt (argc, argv, &optarg, 1)) {
347 return (1);
348 }
349
350 if (pti_parse_freq (optarg[0], &clk)) {
351 return (1);
352 }
353
354 r = pti_scale (img, clk, 1);
355 }
356 else if (strcmp (op, "space-add-left") == 0) {
357 unsigned long sec, clk;
358
359 if (pti_get_opt (argc, argv, &optarg, 1)) {
360 return (1);
361 }
362
363 if (pti_parse_time_clk (optarg[0], &sec, &clk, (*img)->clock)) {
364 return (1);
365 }
366
367 r = pti_space_add_left (*img, (*img)->clock * sec + clk);
368 }
369 else if ((strcmp (op, "space-add-right") == 0) || (strcmp (op, "space") == 0)) {
370 unsigned long sec, clk;
371
372 if (pti_get_opt (argc, argv, &optarg, 1)) {
373 return (1);
374 }
375
376 if (pti_parse_time_clk (optarg[0], &sec, &clk, (*img)->clock)) {
377 return (1);
378 }
379
380 r = pti_space_add_right (*img, (*img)->clock * sec + clk);
381 }
382 else if (strcmp (op, "space-add") == 0) {
383 unsigned long sec, clk;
384
385 if (pti_get_opt (argc, argv, &optarg, 1)) {
386 return (1);
387 }
388
389 if (pti_parse_time_clk (optarg[0], &sec, &clk, (*img)->clock)) {
390 return (1);
391 }
392
393 r = pti_space_add (*img, (*img)->clock * sec + clk);
394 }
395 else if (strcmp (op, "space-auto") == 0) {
396 unsigned long sec, clk;
397
398 if (pti_get_opt (argc, argv, &optarg, 1)) {
399 return (1);
400 }
401
402 if (pti_parse_time_clk (optarg[0], &sec, &clk, (*img)->clock)) {
403 return (1);
404 }
405
406 r = pti_space_auto (*img, (*img)->clock * sec + clk);
407 }
408 else if (strcmp (op, "space-max") == 0) {
409 unsigned long sec, clk;
410
411 if (pti_get_opt (argc, argv, &optarg, 1)) {
412 return (1);
413 }
414
415 if (pti_parse_time_clk (optarg[0], &sec, &clk, (*img)->clock)) {
416 return (1);
417 }
418
419 r = pti_space_max (*img, (*img)->clock * sec + clk);
420 }
421 else if (strcmp (op, "space-trim-left") == 0) {
422 r = pti_space_trim_left (*img);
423 }
424 else if (strcmp (op, "space-trim-right") == 0) {
425 r = pti_space_trim_right (*img);
426 }
427 else if (strcmp (op, "space-trim") == 0) {
428 r = pti_space_trim (*img);
429 }
430 else if (strcmp (op, "trim-left") == 0) {
431 unsigned long sec, clk;
432
433 if (pti_get_opt (argc, argv, &optarg, 1)) {
434 return (1);
435 }
436
437 if (pti_parse_time_clk (optarg[0], &sec, &clk, (*img)->clock)) {
438 return (1);
439 }
440
441 r = pti_trim_left (*img, sec, clk);
442 }
443 else if (strcmp (op, "trim-right") == 0) {
444 unsigned long sec, clk;
445
446 if (pti_get_opt (argc, argv, &optarg, 1)) {
447 return (1);
448 }
449
450 if (pti_parse_time_clk (optarg[0], &sec, &clk, (*img)->clock)) {
451 return (1);
452 }
453
454 r = pti_trim_right (*img, sec, clk);
455 }
456 else {
457 fprintf (stderr, "%s: unknown operation (%s)\n", arg0, op);
458 return (1);
459 }
460
461 if (r) {
462 fprintf (stderr, "%s: operation failed (%s)\n", arg0, op);
463 }
464
465 return (r);
466}