First Commit of my working state
[simh.git] / Ibm1130 / ibm1130_plot.c
1 /* ibm1130_plot.c: IBM 1130 1627 plotter emulation
2
3 Based on the SIMH simulator package written by Robert M Supnik
4
5 Brian Knittel
6 Revision History
7
8 2004.10.22 - Written.
9 2006.1.2 - Rewritten as plotter routine by Carl V Claunch
10
11 * (C) Copyright 2004, Brian Knittel.
12 * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
13 * RISK basis, there is no warranty of fitness for any purpose, and the rest of the
14 * usual yada-yada. Please keep this notice and the copyright in any distributions
15 * or modifications.
16 *
17 * This is not a supported product, but I welcome bug reports and fixes.
18 * Mail to simh@ibm1130.org
19 */
20
21 #include "ibm1130_defs.h"
22
23 #ifndef ENABLE_PLOT_SUPPORT
24
25 DEVICE plot_dev = {
26 "PLOT", NULL, NULL, NULL,
27 0, 16, 16, 1, 16, 16,
28 NULL, NULL, NULL,
29 NULL, NULL, NULL};
30
31 void xio_1627_plotter (int32 addr, int32 func, int32 modify)
32 {
33 /* silently eat any plotter commands */
34 }
35
36 #else
37
38 #include "gd.h"
39
40 /***************************************************************************************
41 * 1627 model 1 plotter (based on Calcomp 535 which was sold as IBM 1627)
42 *
43 * - 11" wide carriage, addressible in .01" steps
44 * - continous sheet paper up to 120' in length
45 * - sheet moveable in .01" steps, either direction
46 * - switchable pen, in various colors and line widths
47 *
48 * Simulator implementation will create a JPEG image corresponding to a
49 * landscape mode sheet of paper, the width of the carriage at 11".
50 * A diagram of more than 8" of paper travel will span printed pages
51 * in landscape mode.
52 *
53 * When an 'att plot' command is issued a file is created based on the
54 * default or currently set values of paper length, starting
55 * position of the pen in both X and Y axes, pen color and pen width.
56 * Based on the number of logical pages of paper, the command will create
57 * the proper size canvas internally and create the output JPEG file.
58 *
59 * When a 'det plot' command is issued, the plotter image will be converted
60 * into the file that was specified during the attach process. The
61 * image is not viewable until this point, unless an examine plot is
62 * issued which will dump the current state of the paper into the file.
63 *
64 * The 'set plot' command can set pen width, paper length, pen color,
65 * current carriage X and Y coordinates. Paper length can be set
66 * to alter the default of 800 (8"); changes are ignored until
67 * the next 'attach' command. The current carriage x and y positions
68 * can be set at any time and will go into effect immediately, just
69 * as the pen color and pen width can be altered on the fly.
70 *
71 * NOTE: requires gd library and definition of ENABLE_PLOT_SUPPORT in makefile or Visual C configuration
72 * gd is not included in the main simh and ibm1130.org distributions at the present time.
73 ***************************************************************************************/
74
75 #define PLOT1627_DSW_OP_COMPLETE 0x8000
76 #define PLOT1627_DSW_BUSY 0x0200
77 #define PLOT1627_DSW_NOT_READY 0x0100
78
79 #define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT)
80 #define IS_DEBUG ((plot_unit->flags & UNIT_DEBUG) == UNIT_DEBUG)
81 #define IS_PENDOWN ((plot_unit->flags & UNIT_PEN) == UNIT_PEN)
82
83 static t_stat plot_svc (UNIT *uptr); /* activity routine */
84 static t_stat plot_reset (DEVICE *dptr); /* reset of 1130 */
85 static t_stat plot_attach (UNIT *uptr, char *cptr); /* attach, loads plotter */
86 static t_stat plot_detach (UNIT *uptr); /* detach and save image */
87 static t_stat plot_examine (UNIT *uptr); /* update file with current canvas */
88 static t_stat plot_set_length (UNIT *uptr, int32 val, char * ptr, void *desc); /* set paper length */
89 static t_stat plot_set_pos (UNIT *uptr, int32 val, char * ptr, void *desc); /* reset current X/Y position */
90 static t_stat plot_show_vals(FILE *fp, UNIT *uptr, int32 val, void *descrip); /* print x, y and length */
91 static t_stat plot_show_nl(FILE *fp, UNIT *uptr, int32 val, void *descrip); /* overcome wacky simh behavior */
92 static void update_pen(void); /* will ensure pen action is correct when changes made */
93 static t_stat plot_validate_change (UNIT *uptr, int32 val, char * ptr, void *desc); /* when set command issued */
94 static void process_cmd(void); /* does actual drawing for plotter */
95
96 extern int32 sim_switches; /* switches set on simh command */
97 static int16 plot_dsw = 0; /* device status word */
98 static int16 plot_cmd = 0; /* the command to process */
99 static int32 plot_wait = 1000; /* plotter movement wait */
100 static int32 plot_xpos = 0; /* current X position */
101 static int32 plot_xmax = 799; /* end of paper */
102 static int32 plot_ypos = 0; /* current Y position */
103 static int32 plot_ymax = 1099; /* right edge of carriage */
104
105 #define PEN_DOWN 0x80000000
106 #define PEN_UP 0x00000000
107 static int32 plot_pen = PEN_UP; /* current pen position */
108
109 static int black_pen; /* holds color black */
110 static int blue_pen; /* holds color blue */
111 static int red_pen; /* holds color red */
112 static int green_pen; /* holds color green */
113 static int yellow_pen; /* holds yellow color */
114 static int purple_pen; /* holds color purple */
115 static int ltgrey_pen; /* holds light grey */
116 static int grey_pen; /* holds grey */
117 static int white_background; /* holds white of paper roll */
118 static int plot_pwidth; /* set and display variable */
119 static int plot_pcolor; /* set and display variable */
120 static int need_update = 0; /* flag to force and update_pen() */
121 static gdImagePtr image; /* pointer to our canvas */
122
123 #define UNIT_V_COLOR (UNIT_V_UF + 0) /* color of selected pen - 3 bits */
124 #define UNIT_V_WIDTH (UNIT_V_UF + 3) /* width of pen - two bits */
125 #define UNIT_V_NOOP (UNIT_V_UF + 5) /* dummy for set/show commands */
126 #define UNIT_V_DEBUG (UNIT_V_UF + 6) /* for -d switch on attach command */
127 #define UNIT_V_PEN (UNIT_V_UF + 7) /* track pen state */
128
129 #define UNIT_WIDTH (3u << UNIT_V_WIDTH) /* two bits */
130 #define UNIT_COLOR (7u << UNIT_V_COLOR) /* three bits */
131 #define UNIT_NOOP (1u << UNIT_V_NOOP) /* dummy for set/show */
132 #define UNIT_DEBUG (1u << UNIT_V_DEBUG) /* shows debug mode on */
133 #define UNIT_PEN (1u << UNIT_V_PEN) /* the pen state bit */
134
135 #define PEN_BLACK (0u << UNIT_V_COLOR)
136 #define PEN_RED (1u << UNIT_V_COLOR)
137 #define PEN_BLUE (2u << UNIT_V_COLOR)
138 #define PEN_GREEN (3u << UNIT_V_COLOR)
139 #define PEN_YELLOW (4u << UNIT_V_COLOR)
140 #define PEN_PURPLE (5u << UNIT_V_COLOR)
141 #define PEN_LTGREY (6u << UNIT_V_COLOR)
142 #define PEN_GREY (7u << UNIT_V_COLOR)
143
144 #define SET_COLOR(op) {plot_unit[0].flags &= ~UNIT_COLOR; plot_unit[0].flags |= (op);}
145 #define GET_COLOR (plot_unit[0].flags & UNIT_COLOR)
146
147 #define BLACK 0,0,0
148 #define BLUE 0,0,255
149 #define RED 255,0,0
150 #define GREEN 0,255,0
151 #define YELLOW 200,200,0
152 #define PURPLE 150,0,150
153 #define LTGREY 200,200,200
154 #define GREY 120,120,120
155 #define WHITE 255,255,255
156
157 #define PEN_SINGLE (0u << UNIT_V_WIDTH)
158 #define PEN_DOUBLE (1u << UNIT_V_WIDTH)
159 #define PEN_TRIPLE (2u << UNIT_V_WIDTH)
160 #define PEN_QUAD (3u << UNIT_V_WIDTH)
161
162 #define GET_WIDTH() (plot_unit[0].flags & UNIT_WIDTH)
163 #define SET_WIDTH(cd) {plot_unit[0].flags &= ~UNIT_WIDTH; un.flags |= (cd);}
164
165 UNIT plot_unit[] = {
166 { UDATA (&plot_svc, UNIT_ATTABLE, 0) },
167 };
168
169 REG plot_reg[] = {
170 { HRDATA (DSW, plot_dsw, 16) }, /* device status word */
171 { DRDATA (WTIME, plot_wait, 24), PV_LEFT }, /* plotter movement wait */
172 { DRDATA (Xpos, plot_xpos, 32), PV_LEFT }, /* Current X Position*/
173 { DRDATA (Ypos, plot_ypos, 32), PV_LEFT }, /* Current Y Position*/
174 { FLDATA (PenDown, plot_pen, 0)}, /* Current pen position - 1 = down */
175 { DRDATA (PaperSize, plot_xmax, 32), PV_LEFT }, /* Length of paper in inches */
176 { NULL } };
177
178 MTAB plot_mod[] = {
179 { UNIT_COLOR, PEN_BLACK, "black", "BLACK", &plot_validate_change},
180 { UNIT_COLOR, PEN_RED, "red", "RED", &plot_validate_change},
181 { UNIT_COLOR, PEN_BLUE, "blue", "BLUE", &plot_validate_change},
182 { UNIT_COLOR, PEN_GREEN, "green", "GREEN", &plot_validate_change},
183 { UNIT_COLOR, PEN_YELLOW, "yellow", "YELLOW", &plot_validate_change},
184 { UNIT_COLOR, PEN_PURPLE, "purple", "PURPLE", &plot_validate_change},
185 { UNIT_COLOR, PEN_LTGREY, "ltgrey", "LTGREY", &plot_validate_change},
186 { UNIT_COLOR, PEN_GREY, "grey", "GREY", &plot_validate_change},
187 { UNIT_WIDTH, PEN_SINGLE, "1.0", "1.0", &plot_validate_change},
188 { UNIT_WIDTH, PEN_DOUBLE, "2.0", "2.0", &plot_validate_change},
189 { UNIT_WIDTH, PEN_TRIPLE, "3.0", "3.0", &plot_validate_change},
190 { UNIT_WIDTH, PEN_QUAD, "4.0", "4.0", &plot_validate_change},
191 { UNIT_PEN, UNIT_PEN, "pendown", "PENDOWN", &plot_validate_change},
192 { UNIT_PEN, 0, "penup", "PENUP", &plot_validate_change},
193 /* below is dummy entry to trigger the show routine and print extended values */
194 { UNIT_NOOP, 0, "", NULL, NULL, &plot_show_vals},
195 /* extended entries must allow parm for both unit and dev, but
196 * then they will print the value twice for a 'show plot' command
197 * therefore they are set to not display unless explicity requested
198 * and the special dummy NOOP entry will cause the print of these values */
199 { MTAB_XTD | MTAB_VAL | MTAB_VUN | MTAB_VDV | MTAB_NMO, 2,
200 "length", "LENGTH", &plot_set_length, &plot_show_nl, &plot_reg[5]},
201 { MTAB_XTD | MTAB_VAL | MTAB_VDV | MTAB_VUN | MTAB_NMO, 0,
202 "Xpos", "XPOS", &plot_set_pos, &plot_show_nl, &plot_reg[2]},
203 { MTAB_XTD | MTAB_VAL | MTAB_VDV | MTAB_VUN | MTAB_NMO, 1,
204 "Ypos", "YPOS", &plot_set_pos, &plot_show_nl, &plot_reg[3]},
205 { 0 } };
206
207 DEVICE plot_dev = {
208 "PLOT", plot_unit, plot_reg, plot_mod,
209 1, 16, 16, 1, 16, 16,
210 NULL, NULL, plot_reset,
211 NULL, plot_attach, plot_detach};
212
213 /* xio_1627_plotter - XIO command interpreter for the 1627 plotter model 1 */
214
215 void xio_1627_plotter (iocc_addr, iocc_func, iocc_mod)
216 {
217 char msg[80];
218
219 if (! IS_ONLINE(plot_unit) ) {
220 SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* set not ready */
221 if (IS_DEBUG) printf("Plotter has no paper, ignored\n");
222 return; /* and ignore */
223 }
224
225 switch (iocc_func) {
226 case XIO_READ: /* read XIO */
227 xio_error("Read XIO not supported by 1627 plotter");
228 break;
229
230 case XIO_WRITE: /* write: do one plotter operation */
231 if ((plot_dsw & PLOT1627_DSW_NOT_READY)) {
232 if (IS_DEBUG) printf("Wrote to non-ready Plotter\n");
233 break;
234 }
235 plot_cmd = (uint16) ( M[iocc_addr & mem_mask] >> 10 ); /* pick up command */
236 process_cmd(); /* interpret command */
237 sim_activate(plot_unit, plot_wait); /* schedule interrupt */
238 SETBIT(plot_dsw, PLOT1627_DSW_BUSY); /* mark it busy */
239 break;
240
241 case XIO_SENSE_DEV: /* sense device status */
242 ACC = plot_dsw; /* get current status */
243 if (iocc_mod & 0x01) { /* reset interrupts */
244 CLRBIT(plot_dsw, PLOT1627_DSW_OP_COMPLETE);
245 CLRBIT(ILSW[3], ILSW_3_1627_PLOTTER);
246 }
247 break;
248
249 case XIO_CONTROL: /* control XIO */
250 xio_error("Control XIO not supported by 1627 plotter");
251 break;
252
253 default:
254 sprintf(msg, "Invalid 1627 Plotter XIO function %x", iocc_func);
255 xio_error(msg);
256 }
257 return;
258 }
259
260 // plot_svc - 1627 plotter operation complete
261
262 static t_stat plot_svc (UNIT *uptr)
263 {
264 CLRBIT(plot_dsw, PLOT1627_DSW_BUSY); /* clear reader busy flag */
265
266 SETBIT(plot_dsw, PLOT1627_DSW_OP_COMPLETE); /* indicate read complete */
267
268 SETBIT(ILSW[3], ILSW_3_1627_PLOTTER); /* initiate interrupt */
269 calc_ints();
270
271 return SCPE_OK;
272 }
273
274 /* plot_reset - reset emulated plotter */
275
276 static t_stat plot_reset (DEVICE *dptr)
277 {
278 char * buf;
279 int32 size;
280
281 sim_cancel(plot_unit);
282
283 CLRBIT(plot_dsw, PLOT1627_DSW_BUSY | PLOT1627_DSW_OP_COMPLETE);
284
285 if (IS_DEBUG) printf("reset routine for Plotter\n");
286
287 CLRBIT(ILSW[3], ILSW_3_1627_PLOTTER);
288 calc_ints();
289
290 return SCPE_OK;
291 }
292
293
294 /* plot_attach - attach file to simulated plotter */
295
296 static t_stat plot_attach (UNIT *uptr, char *cptr)
297 {
298 t_stat result;
299
300 CLRBIT(uptr->flags, UNIT_DEBUG);
301 if (sim_switches & SWMASK('D')) SETBIT(uptr->flags, UNIT_DEBUG);
302
303 /* get the output file by using regular attach routine */
304 result = attach_unit(uptr, cptr);
305
306 if (result != SCPE_OK) {
307 if (IS_DEBUG) printf("problem attaching file\n");
308 return result;
309 }
310
311 SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* assume failure */
312
313 /* set up our canvas at the desired size */
314 image = gdImageCreate(plot_ymax+1,plot_xmax+1); /* create our canvas */
315 if (image == NULL) {
316 if (IS_DEBUG) printf("problem creating image canvas\n");
317 return SCPE_MEM;
318 }
319
320 /* set up the basic colors after image created */
321 white_background = gdImageColorAllocate(image,WHITE); /* white is background */
322 black_pen = gdImageColorAllocate(image,BLACK); /* load up black color */
323 blue_pen = gdImageColorAllocate(image,BLUE); /* load up blue color */
324 red_pen = gdImageColorAllocate(image,RED); /* load up red color */
325 green_pen = gdImageColorAllocate(image,GREEN); /* load up green color */
326 yellow_pen = gdImageColorAllocate(image,YELLOW); /* load up yellow color */
327 purple_pen = gdImageColorAllocate(image,PURPLE); /* load up purple color */
328 ltgrey_pen = gdImageColorAllocate(image,LTGREY); /* load up light grey color */
329 grey_pen = gdImageColorAllocate(image,GREY); /* load up grey color */
330
331 if ( (white_background == -1) || (black_pen == -1) ||
332 (red_pen == -1) || (blue_pen == -1) || (green_pen == -1) ||
333 (purple_pen == -1) || (ltgrey_pen == -1) || (grey_pen == -1) ) {
334 if (IS_DEBUG) printf("problem allocating pen colors\n");
335 return SCPE_MEM;
336 }
337
338 CLRBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* we're in business */
339
340 update_pen(); /* routine to ensure pen is okay */
341
342 return SCPE_OK;
343 }
344
345 /* pen updating routine, called at attach and whenever we reset the values */
346
347 void update_pen (void)
348 {
349 int color;
350 int width;
351
352 if (!IS_ONLINE(plot_unit)) return; /* only do this if attached */
353
354 /* pick up latest color as active pen */
355 color = GET_COLOR;
356 switch (color) {
357 case PEN_BLACK:
358 plot_pcolor = black_pen;
359 break;
360
361 case PEN_RED:
362 plot_pcolor = red_pen;
363 break;
364
365 case PEN_BLUE:
366 plot_pcolor = blue_pen;
367 break;
368
369 case PEN_GREEN:
370 plot_pcolor = green_pen;
371 break;
372
373 case PEN_YELLOW:
374 plot_pcolor = yellow_pen;
375 break;
376
377 case PEN_PURPLE:
378 plot_pcolor = purple_pen;
379 break;
380
381 case PEN_LTGREY:
382 plot_pcolor = ltgrey_pen;
383 break;
384
385 case PEN_GREY:
386 plot_pcolor = grey_pen;
387 break;
388
389 default:
390 if (IS_DEBUG) printf("invalid pen color state\n");
391 plot_pcolor = black_pen;
392 break;
393 }
394
395 /* set up anti-aliasing for the line */
396 gdImageSetAntiAliased(image, plot_pcolor);
397
398 /* pick up latest width for pen */
399 width = GET_WIDTH();
400 switch (width) {
401 case PEN_SINGLE:
402 plot_pwidth = 1;
403 gdImageSetThickness(image, 1);
404 break;
405
406 case PEN_TRIPLE:
407 plot_pwidth = 3;
408 gdImageSetThickness(image, 3);
409 break;
410
411 case PEN_DOUBLE:
412 plot_pwidth = 2;
413 gdImageSetThickness(image, 2);
414 break;
415
416 case PEN_QUAD:
417 plot_pwidth = 4;
418 gdImageSetThickness(image, 4);
419 break;
420
421 default:
422 if (IS_DEBUG) printf("invalid pen width\n");
423 plot_pwidth = 1;
424 gdImageSetThickness(image, 1);
425 break;
426 }
427
428 /* now ensure the pen state is accurate */
429 plot_pen = IS_PENDOWN ? PEN_DOWN : PEN_UP;
430 return;
431 }
432
433 /* plot_detach - detach file from simulated plotter */
434 static t_stat plot_detach (UNIT *uptr)
435 {
436 char * buf;
437 int32 size;
438 FILE * fp;
439 int32 result;
440
441 SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY);
442
443 /* copy images to files, close files, set device to detached, free gd memory */
444
445 buf = gdImageGifPtr(image,&size);
446 if (! buf) {
447 if (IS_DEBUG) printf("failure creating GIF in-memory\n");
448 return SCPE_MEM;
449 }
450
451 fp = uptr->fileref; /* get file attached to unit */
452
453 if (! fseek(fp,0,SEEK_SET)) { /* first we reset to begin of file */
454 if (IS_DEBUG) printf("wrote out GIF to file\n");
455 result = fwrite(buf,1,size,fp); /* write out our image to the file */
456 }
457
458 gdFree(buf); /* free up the memory of GIF format */
459 gdImageDestroy(image); /* free up the canvas memory */
460
461 if (result != size) { /* some problem writing it */
462 if (IS_DEBUG) printf("error in write of image file\n");
463 return SCPE_IOERR;
464 }
465
466 return detach_unit(uptr); /* have simh close the file */
467 }
468
469 /* process_cmd - implement the drawing actions of the plotter */
470
471 static void process_cmd (void)
472 {
473 int32 oldx, oldy;
474
475 /* first see if we set any changes to pen or position, do an update */
476 if (need_update) {
477 update_pen();
478 need_update = 0;
479 }
480
481 /* will move pen one step or flip pen up or down */
482 oldx = plot_xpos;
483 oldy = plot_ypos;
484
485 switch (plot_cmd) {
486 case 1: /* raise pen command */
487 plot_pen = PEN_UP;
488 plot_unit->flags = plot_unit->flags & (~UNIT_PEN);
489 return;
490 break;
491
492 case 2: /* +Y command */
493 plot_ypos = plot_ypos + 1;
494 break;
495
496 case 4: /* -Y command */
497 plot_ypos = plot_ypos - 1;
498 break;
499
500 case 8: /* -X command */
501 plot_xpos = plot_xpos - 1;
502 break;
503
504 case 10: /* -X +Y command */
505 plot_xpos = plot_xpos - 1;
506 plot_ypos = plot_ypos + 1;
507 break;
508
509 case 12: /* -X -Y command */
510 plot_xpos = plot_xpos - 1;
511 plot_ypos = plot_ypos - 1;
512 break;
513
514 case 16: /* +X command */
515 plot_xpos = plot_xpos + 1;
516 break;
517
518 case 18: /* +X +Y command */
519 plot_xpos = plot_xpos + 1;
520 plot_ypos = plot_ypos + 1;
521 break;
522
523 case 20: /* +X -Y pen command */
524 plot_xpos = plot_xpos + 1;
525 plot_ypos = plot_ypos - 1;
526 break;
527
528 case 32: /* lower pen command */
529 plot_pen = PEN_DOWN;
530 plot_unit->flags = plot_unit->flags | UNIT_PEN;
531 return;
532 break;
533
534 default:
535 if (IS_DEBUG) printf("invalid plotter command\n");
536 return;
537 break;
538 }
539
540 /* check to see if carriage has moved off any edge */
541 if ((plot_xpos > (plot_xmax+1)) || (plot_ypos > (plot_ymax+1)) ||
542 (plot_xpos < 0) || (plot_ypos < 0)) {
543 /* if so, ignore as 1627 has no way of signalling error */
544 if (IS_DEBUG) printf(
545 "attempted to move carriage off paper edge %d %d for command %d\n",
546 plot_xpos,plot_ypos,plot_cmd);
547 return;
548 }
549
550 /* only draw a line if the pen was down during the movement command */
551 if (plot_pen) {
552 gdImageLine(image, plot_ymax-plot_ypos, plot_xmax-plot_xpos, plot_ymax-oldy, plot_xmax-oldx, gdAntiAliased);
553 /* semantics are 0,0 point is lower right */
554 }
555
556 return;
557 }
558
559 /* plot_set_length - validate and store the length of the paper */
560
561 static t_stat plot_set_length (UNIT *uptr, int32 set, char *ptr, void *desc)
562 {
563 char *cptr;
564 int32 val;
565
566 #define LONGEST_ROLL 1440000 /* longest is 120', 14400", 1,440,000 .01"s */
567
568 val = strtotv (ptr, &cptr, (uint32) 10); /* sim routine to get value */
569 if ((val < 1) | (val >= LONGEST_ROLL)) { /* check valid range */
570 if (IS_DEBUG) printf("setting paper more than 120' or less than 1 inch\n");
571 return SCPE_ARG;
572 }
573
574 /* origin zero drawing, reduce by 1 but show command will fudge by adding it back */
575 *((int32 *)((REG *) desc)->loc) = val - 1;
576
577 return SCPE_OK;
578 }
579
580 /* plot_set_pos - validate and store the new position of the carriage */
581
582 static t_stat plot_set_pos (UNIT *uptr, int32 set, char *ptr, void *desc)
583 {
584 char *cptr;
585 int32 val;
586 int32 max;
587
588 max = (set == 1) ? plot_ymax : plot_xmax;
589 val = strtotv (ptr, &cptr, (uint32) 10);
590 if ((val < 0) | (val > max)) {
591 if (IS_DEBUG) printf("error moving carriage off paper edge\n");
592 return SCPE_ARG;
593 }
594
595 *((int32 *)((REG *) desc)->loc) = val;
596
597 return SCPE_OK;
598 }
599
600 /* routine to display the paper length and carriage position
601 * cannot use regular simh routine because it prints values twice,
602 * once for device and once for unit
603 */
604
605 static t_stat plot_show_vals (FILE *fp, UNIT *uptr, int32 val, void *descrip)
606 {
607 fprintf(fp, "length=%d, Xpos=%d, Ypos=%d",plot_xmax+1, plot_xpos,plot_ypos);
608 return SCPE_OK;
609 }
610
611 /* routine to add a terminating NL character when 'show plot length'
612 * or equivalent for xpos or ypos is issued, as simh will not append for us */
613
614 static t_stat plot_show_nl(FILE *fp, UNIT *uptr, int32 val, void *descrip)
615 {
616 int32 disp;
617 char *label;
618
619 disp = (val == 2) ? plot_xmax + 1 : ((val == 1) ? plot_ypos : plot_xpos);
620 label = (val == 2) ? "length=" : ((val == 1) ? "Ypos=" : "Xpos=");
621
622 fprintf(fp, "%s%d\n", label, disp);
623 return SCPE_OK;
624 }
625
626 /* plot_validate_change - force the update_pen routine to be called after user changes pen setting */
627
628 static t_stat plot_validate_change (UNIT *uptr, int32 set, char *ptr, void *desc)
629 {
630 need_update = 1;
631 return SCPE_OK;
632 }
633
634 #endif /* ENABLE_PLOT_SUPPORT */