home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 110_01 / chargen.c < prev    next >
Text File  |  1985-08-21  |  15KB  |  620 lines

  1. /*    Character Generator/Editor
  2.  
  3.     by Bob Pasky
  4.     36 Wiswall Rd.
  5.     Newton Centre, MA 02159
  6.  
  7.     Originally written for Imsai VIO video board to create
  8.     data in the required format for burning its EPROM
  9.     character sets.
  10.  
  11.     The program uses the VIO graphic mode to display an
  12.     enlarged version of a character's dot matrix.
  13.     The character matrix is 7 dots horizontally by 10 rows
  14.     vertically.
  15.  
  16.     Each of the 256 character positions can be displayed, one
  17.     at a time, modified as desired, and saved in memory.
  18.     Once all changes have been made, the data can be formatted
  19.     and saved as a binary file named "CHARSET".
  20.  
  21.     This file, of course, can be retrieved later and unformatted
  22.     in order to re-edit the set.
  23.  
  24.     Additionally, the entire character set can be sent to
  25.     a line printer for a hard-copy of the character matrices.
  26.  
  27.     To begin, you should "get" the file (type 'y' to confirm),
  28.     then "unformat" it. Advance or back up the current character
  29.     display until you reach the character code you wish to edit.
  30.     "Load" the charater into the display area. Move the cursor
  31.     to the desired point in the matrix and strike 'b' or 'd' for
  32.     a bright (dot) or dim (no dot) point at that location.
  33.     Continue until the graphic is in its desired form, then
  34.     "save" it back into the character inventory. Advance or back
  35.     up to any other characters to be edited. Load it, edit it, and
  36.     save it. When all editing is complete, you must "format" the
  37.     inventory before "filing" it to disk.
  38.     The inventory must be in "unformatted" form to print it.
  39.  
  40.     Compiled using BDS-C 1.41, the program uses standard library
  41.     functions. However, certain addresses may need to be modified
  42.     for your particular VIO and display handlers. (I do not have
  43.     the Imsai video driver firmware which normally expects the
  44.     VIO to be addressed at 0xE000.)
  45.  
  46.     I use several simple graphic characters for the character
  47.     display -- open box and solid boxes formed with two adjacent
  48.     character positions, and a rule around the character display
  49.     area formed by horizontal and vertical rules and matching
  50.     corners. If you don't have equivalent graphics, you might try
  51.     using the alternative ASCII characters shown in their
  52.     "define" statements.
  53.  
  54.     The program should be easily adapted for any
  55.     memory-mapped display with 2708/2716-type character ROMs.
  56.  
  57.     I have, in fact, modified this program to output in the
  58.     format required for the Hazeltine 1500 series terminals.
  59. */
  60.  
  61. #include "bdscio.h"
  62.  
  63. #define DISPLAY 0xA000    /* VIO display address        */
  64. #define CHOME 1        /* command to home VIO cursor    */
  65. #define BRKCHR 0x1B    /* escape from printer listing    */
  66.  
  67. #define GRAPHMODE 0xc    /* graphics mode for VIO ctrlr    */
  68. /*    cursor character in two parts left & right:    */
  69. /*    these 2 characters next to one another form an open box    */
  70. #define CURLEFT 0xC3    /* alternate: '<'    */
  71. #define CURRIGHT 0xC9    /* alternate: '>'    */
  72. /*    displayed point in two parts left & right:    */
  73. /*    these 2 characters next to one another form a solid box    */
  74. #define DOTLEFT 0x86    /* alternate: '['    */
  75. #define DOTRIGHT 0xB0    /* alternate: ']'    */
  76. /*    elements of box surrounding display area    */
  77. #define CVERT 0xC5    /* alternate: '|'    */
  78. #define CHORIZ 0xCA    /* alternate: '-'    */
  79. #define CTOPLEFT 0xC6    /* alternate: '+'    */
  80. #define CTOPRIGHT 0xCC    /* alternate: '+'    */
  81. #define CBOTLEFT 0xC3    /* alternate: '+'    */
  82. #define CBOTRIGHT 0xC9    /* alternate: '+'    */
  83.  
  84. #define BUFSIZ 3072    /* char. description buffer    */
  85. #define LISTOUT 5    /* CP/M printer command        */
  86.  
  87. char    cset[256][10];        /* character set descriptions    */
  88. char    garbage[256][2];    /* extra space for unused lines    */
  89. int    cchar;        /* current character displayed    */
  90. int    topleft;    /* address of top left of char    */
  91. int     cuaddr,        /* cursor address    */
  92.     homeaddr,    /* address of home    */
  93.     cx,cy;        /* cursor x,y position    */
  94. char    cuchleft,    /* cursor char. left    */
  95.     cuchrght;    /* cursor char. right    */
  96. char    hxstr[16];    /* list of hex codes    */
  97.  
  98. main()
  99. {
  100. int x;
  101.  
  102.     init();
  103.     home();        /* place cursor at home    */
  104.     swapcur();    /* turn cursor on    */
  105.     strcpy (hxstr,"0123456789ABCDEF");
  106.     dcchar();    /* display ccurrent char info    */
  107.     setmem(cset,BUFSIZ,0);    /* clear buffer area    */
  108.  
  109.     while ( (x=getkbd()) != 'q')
  110.     {
  111.     if(cuchleft!=CURLEFT) {
  112.         poke(cuaddr,cuchleft);
  113.         poke(cuaddr+1,cuchrght);
  114.         }
  115.     switch (x)
  116.         {
  117.     case 'h': left();    /* move cursor left */
  118.         break;
  119.     case 'k': right();    /* and right */
  120.         break;
  121.     case 'j': down();    /* or down */
  122.         break;
  123.     case 'u': up();        /* or up */
  124.         break;
  125.     case 'b': bright();    /* place dot at cursor position */
  126.         break;
  127.     case 'd': dim();    /* remove dot from cursor pos'n */
  128.         break;
  129.     case 'm': home();    /* home cursor */
  130.         break;
  131.     case 'x': clrchar();    /* clear all dots from character */
  132.         break;
  133.     case 's': store();    /* store current character */
  134.         break;
  135.     case 'l': load();    /* get current character */
  136.         break;
  137.     case '[': retreat();    /* decrement current character */
  138.         break;
  139.     case ']': advance();    /* increment current character */
  140.         break;
  141.     case 'f': file();    /* save as file CHARSET */
  142.         break;
  143.     case 'g': getfile();    /* get file CHARSET */
  144.         break;
  145.     case 'p': format();    /* format for output */
  146.         break;
  147.     case 'o': unformat();    /* unformat for editing */
  148.         break;
  149.     case 'q': poke (0xa7ff,8);    /* changes VIO-C to alpha mode    */
  150.         exit();        /* quit altogether */
  151.     case 'c': convert();    /* list on console or printer */
  152.         break;
  153.     default: break;
  154.         }
  155.     swapcur();
  156.     }
  157.     poke (0xa7ff,8);    /* change to alpha mode    */
  158. }
  159.  
  160. getkbd()    /* gets char from kbd, keeping the VIO drivers    */
  161.         /* from cluttering up the screen with the echo    */
  162.         /* of the keyboard characters.            */
  163. {
  164.     return tolower (bios(3,0));
  165. }
  166.  
  167. advance()    /* advance the current displayed character    */
  168. {
  169.     if ((cchar++)>255)cchar=0;
  170.     dcchar();
  171. }
  172. retreat()    /* go back one displayed character        */
  173. {
  174.     if ((cchar--)<0)cchar=255;
  175.     dcchar();
  176. }
  177. dcchar()    /* displays current character info        */
  178. {
  179. int i,hx;
  180.  
  181.     txtplot ("CHARACTER IS ",3,10,0);
  182.     i=strlen("character is x");
  183.     plot(3,10+i,cchar);
  184.     hx=hxstr[cchar/16];
  185.     plot(3,12+i,hx);
  186.     hx=hxstr[cchar%16];
  187.     plot(3,13+i,hx);
  188. }
  189.  
  190. store()        /* save current character description    */
  191. {
  192. int i,j;
  193.     for (i=0;i<10;i++)
  194.         cset[cchar][i]=pack(i);
  195.     txtplot ("Character Stored  ",6,10,0);
  196. }
  197.  
  198. load()        /* load character description        */
  199. {
  200. int i,j,x;
  201.     clrchar();
  202.     while (cy<9) up();
  203.  
  204.     for (i=0; i<10; i++)
  205.         {
  206.         x=cset[cchar][i];
  207.         plot(5,(3*i)+10,hxstr[x/16]);
  208.         plot(5,(3*i)+11,hxstr[x%16]);
  209.  
  210.         for (j=0; j<7; j++)
  211.             {
  212.             if (! ((x>>j)&1) ) bright();
  213.             right();
  214.             }
  215.         while (cx) left();
  216.         down();
  217.         }
  218.     txtplot ("Character Loaded   ",6,10,0);
  219. }
  220.  
  221. pack(i)        /* reads single "raster" line of display    */
  222.         /* returns byte formatted for VIO PROM        */
  223. int i;
  224. {
  225. int j,c,x;
  226.     c=0;
  227.     for (j=0; j<7; j++)
  228.         {
  229.         c=c>>1;
  230.         x=peek(topleft+(80*i)+(2*j)+81);
  231.         if (x==DOTLEFT) c+=64;
  232.         if (x==DOTRIGHT) c+=64;
  233.         }
  234.     return ~(c|128);
  235. }
  236.  
  237. format()    /* converts descriptions into proper order    */
  238.         /* for PROM burning.                */
  239. {
  240. char *pp;
  241. int i,j;
  242. char pset[BUFSIZ];
  243.  
  244. /*    format for VIO ROMs:
  245.     requires 3 2708 EPROMs:
  246.     1.  top 8 rows of characters 0-127
  247.     2.  top 8 rows of characters 128-255
  248.     3.  bottom 2 rows of characters 0-255
  249.     Row one of each of the 128 characters is output, then
  250.     row two of each character, etc.
  251.     For the 3rd ROM, the 9th row for chars 0-127 is output,
  252.     then the 10th row. Blanks fill the next two rows, then
  253.     the 9th and 10th rows for chars 128-255. Two more
  254.     blank rows complete the 3rd ROM.
  255.  
  256.     The hardware uses negative logic: a 0 turns the dot on,
  257.     a 1 means no dot. The left-most dot for each character
  258.     is controlled by the lsb of the byte; the right-most dot
  259.     is bit 6; bit 7 is always 0.
  260. */
  261.     txtplot ("Formatting data    ",6,10,0);
  262.     pp=pset;
  263.     for (j=0;j<8;j++)
  264.         for (i=0;i<128;i++)
  265.             {
  266.             *pp=cset[i][j];
  267.             pp++;
  268.             }
  269.     for (j=0;j<8;j++)
  270.         for (i=128;i<256;i++)
  271.             {
  272.             *pp=cset[i][j];
  273.             pp++;
  274.             }
  275.     for (j=8;j<10;j++)
  276.         for (i=0;i<128;i++)
  277.             {
  278.             *pp=cset[i][j];
  279.             pp++;
  280.             }
  281.     for (i=0x100;i<0x200;i++)
  282.         {
  283.         *pp=0xFF;
  284.         pp++;
  285.         }
  286.     for (j=8;j<10;j++)
  287.         for (i=128;i<256;i++)
  288.             {
  289.             *pp=cset[i][j];
  290.             pp++;
  291.             }
  292.  
  293.     movmem(pset,cset,BUFSIZ);
  294.     txtplot ("Data formatted    ",6,10,0);
  295. }
  296. unformat()    /* converts formatted data (from disk file)    */
  297.         /* so it can be manipulated by program        */
  298. {
  299. char *pp;
  300. int i,j;
  301. char pset[BUFSIZ];
  302.  
  303.     txtplot ("Unformatting data ",6,10,0);
  304.     pp=pset;
  305.     movmem(cset,pset,BUFSIZ);
  306.     for (j=0;j<8;j++)
  307.         for (i=0;i<128;i++)
  308.             {
  309.             cset[i][j]=*pp;
  310.             pp++;
  311.             }
  312.     for (j=0;j<8;j++)
  313.         for (i=128;i<256;i++)
  314.             {
  315.             cset[i][j]=*pp;
  316.             pp++;
  317.             }
  318.     for (j=8;j<10;j++)
  319.         for (i=0;i<128;i++)
  320.             {
  321.             cset[i][j]=*pp;
  322.             pp++;
  323.             }
  324.     pp+=0x100;
  325.     for (j=8;j<10;j++)
  326.         for (i=128;i<256;i++)
  327.             {
  328.             cset[i][j]=*pp;
  329.             pp++;
  330.             }
  331.  
  332.     txtplot ("Data unformatted  ",6,10,0);
  333. }
  334.  
  335. file()        /* saves file, but just in case user hit key by */
  336.         /* mistake, it asks confirmation first        */
  337. {
  338. int fd;
  339.     txtplot ("Save file? (y/n)  ",6,10,0);
  340.     if(getkbd()!='y') {
  341.         txtplot ("                  ",6,10,0);
  342.         return; }
  343.     unlink("CHARSET");
  344.     if((fd=creat("CHARSET"))<0) {
  345.         printf("\nERROR: Can't create file.");
  346.         exit();
  347.         }
  348.     write (fd,cset,BUFSIZ/128);
  349.     close (fd);
  350.     txtplot ("CHARSET saved      ",6,10,0);
  351. }
  352.  
  353. getfile()    /* retrieves a file, but just in case user hits    */
  354.         /* key by mistake, asks confirmation first.    */
  355. {
  356. int fd;
  357.     txtplot ("Get file? (y/n)      ",6,10,0);
  358.     if(getkbd()!='y') {
  359.         txtplot ("                     ",6,10,0);
  360.         return; }
  361.     fd=open ("CHARSET",0);
  362.     read (fd,cset,BUFSIZ/128);
  363.     close (fd);
  364.     txtplot ("CHARSET retrieved    ",6,10,0);
  365. }
  366.  
  367. bright()    /* turn on dot        */
  368. {
  369.     cuchleft=CURLEFT;
  370.     cuchrght=CURRIGHT;
  371.     poke(cuaddr,DOTLEFT);
  372.     poke(cuaddr+1,DOTRIGHT);
  373.     txtplot ("Bright            ",6,10,0);
  374.  
  375. }
  376.  
  377. dim()        /* turn off dot        */
  378. {
  379.     poke (cuaddr,' ');
  380.     cuchleft=CURLEFT;
  381.     cuchrght=CURRIGHT;
  382.     poke(cuaddr+1,' ');
  383.     txtplot ("Dim               ",6,10,0);
  384. }
  385.  
  386. cdisplay()        /* inserts cursor display    */
  387. {
  388.     if(cuchleft!=CURLEFT) {
  389.         poke (cuaddr,cuchleft);
  390.         poke (cuaddr+1,cuchrght);
  391.         }
  392.     getchar();
  393.     cchar++;
  394.     clrchar();
  395. }
  396.  
  397. left()        /* move cursor left    */
  398. {
  399.     if (cx==0) return;
  400.     cx--;
  401.     cuaddr-=2;
  402.     cuchleft=CURLEFT;
  403.     cuchrght=CURRIGHT;
  404.     txtplot ("                  ",6,10,0);
  405. }
  406.  
  407. right()        /* move cursor right    */
  408. {
  409.     if (cx>=6) return;
  410.     cx++;
  411.     cuaddr+=2;
  412.     cuchleft=CURLEFT;
  413.     cuchrght=CURRIGHT;
  414.     txtplot ("                  ",6,10,0);
  415. }
  416.  
  417. up()        /* move cursor up    */
  418. {
  419.     if (cy>=9) return;
  420.     cy++;
  421.     cuaddr-=80;
  422.     cuchleft=CURLEFT;
  423.     cuchrght=CURRIGHT;
  424.     txtplot ("                  ",6,10,0);
  425. }
  426.  
  427. down()        /* move cursor down    */
  428. {
  429.     if (cy==0) return;
  430.     cy--;
  431.     cuaddr+=80;
  432.     cuchleft=CURLEFT;
  433.     cuchrght=CURRIGHT;
  434.     txtplot ("                  ",6,10,0);
  435. }
  436.  
  437. home()        /* move cursor to home pos'n    */
  438. {
  439.     cuaddr=homeaddr;
  440.     cx=0;
  441.     cy=3;
  442.     cuchleft=CURLEFT;
  443.     cuchrght=CURRIGHT;
  444.     txtplot ("                  ",6,10,0);
  445. }
  446.  
  447. clrchar()    /* clear out character display    */
  448. {
  449. int i,j;
  450.     putchar(1);
  451.     for (i=1;i<11;i++)
  452.         for  (j=1;j<15;j++)
  453.             plot (10+i,36+j,' ');
  454.     for (i=1;i<15;i++)    plot (18,36+i,'.');
  455.     home();
  456.     txtplot ("Character cleared ",6,10,0);
  457. }
  458.  
  459. swapcur()    /* swap cursor with what's "under" it    */
  460. {
  461. char temp;
  462.     temp=peek(cuaddr);
  463.     poke(cuaddr,cuchleft);
  464.     cuchleft=temp;
  465.     temp=peek(cuaddr+1);
  466.     poke(cuaddr+1,cuchrght);
  467.     cuchrght=temp;
  468. }
  469.  
  470. init()        /* initialization    */
  471. {
  472.     int i,j,k;
  473.  
  474.     setmem (cset,BUFSIZ,0);    /* clear character set vector */
  475.     setplot(DISPLAY,24,80);    /* set up for 80x24    */
  476.     clrplot();
  477.     poke (DISPLAY+0x7FF,GRAPHMODE);/* set VIO graphics mode    */
  478.     topleft=DISPLAY+(10*80)+36;
  479.     homeaddr=topleft+1+(80*7);
  480.  
  481.     plot (10,36,CTOPLEFT);    /* set up outline of char. display */
  482.     for (i=1;i<15;i++)    plot (10,36+i,CHORIZ);
  483.     plot (10,36+15,CTOPRIGHT);
  484.     for (i=1;i<11;i++)
  485.         {
  486.         plot (10+i,36,CVERT);
  487.         plot (10+i,36+15,CVERT);
  488.         }
  489.     plot (21,36,CBOTLEFT);
  490.     for (i=1;i<15;i++)    plot (21,36+i,CHORIZ);
  491.     plot (21,36+15,CBOTRIGHT);
  492.     cchar=0x20;
  493.     clrchar();
  494.     cuchleft=CURLEFT;
  495.     cuchrght=CURRIGHT;
  496.     home();
  497.     putchar(1);    /* tell monitor's cursor to go home    */
  498.     txtplot("c - cset list",7,0,0);
  499.     txtplot("d - dim",8,0,0);
  500.     txtplot("f - file cset",9,0,0);
  501.     txtplot("g - get cset",10,0,0);
  502.     txtplot("h - left cursor",11,0,0);
  503.     txtplot("j - down cursor",12,0,0);
  504.     txtplot("k - right cursor",13,0,0);
  505.     txtplot("l - load char",14,0,0);
  506.     txtplot("m - home cursor",15,0,0);
  507.     txtplot("o - unformat",16,0,0);
  508.     txtplot("p - format",17,0,0);
  509.     txtplot("q - quit",18,0,0);
  510.     txtplot("s - store char",19,0,0);
  511.     txtplot("u - up cursor",20,0,0);
  512.     txtplot("x - clear char",21,0,0);
  513.     txtplot("] - increment char",22,0,0);
  514.     txtplot("[ - decrement char",23,0,0);
  515.  
  516. }
  517.  
  518. int listf;
  519.  
  520. convert()    /* once converted all characters to    */
  521.         /* a different format. Now its used to    */
  522.         /* print them on display and optionally,*/
  523.         /* a line printer            */
  524. {
  525. int i,j,k;
  526.  
  527.     txtplot ("Printing cset      ",6,10,0);
  528.  
  529. /*    to send listing to a file instead of printer:
  530. **    unlink("CHARSET.LST");
  531. **    if((fdc=fcreat("CHARSET.LST",iobuf))<0) {
  532. **        printf("\nERROR: can't create LST file");
  533. **        goto endconvert;
  534. **        }
  535. */
  536.     txtplot("Listing output?   ",6,10,0);
  537.     if(getkbd()=='y') listf=1;
  538.     else listf=0;
  539.     for (i=0;i<256;i+=4)
  540.         {
  541.         if ((!bios(2,0)) && (bios(3,0) == BRKCHR)) break;
  542.         if (!(i % 16)) putf(0xC);
  543.         putf(' '); putf(' ');
  544.         for (k=i;k<i+4;k++)
  545.             {
  546.             putf(hxstr[k/16]); putf(hxstr[k%16]);
  547.             if ((k+1)%4) hspace();
  548.             }
  549.         hline();
  550.         for (j=0;j<10;j++)
  551.             {
  552.             putf(0xD); putf (0xA);
  553.             sendchr(cset[i][j]);
  554.             sendchr(cset[i+1][j]);
  555.             sendchr(cset[i+2][j]);
  556.             sendchr(cset[i+3][j]);
  557.             }
  558.         hline();
  559.         sendspc();
  560.         }
  561. /*    end of file output (if list to file is enabled):
  562. **    fflush(iobuf);
  563. **    close (fdc);
  564. */
  565.     if (listf) init();    /* set up screen again */
  566.  
  567.     txtplot ("Listing done   ",6,10,0);
  568. endconvert: return;
  569. }
  570.  
  571. hline()        /* do a line of output to printer    */
  572. {
  573. int i,j;
  574.     putf(0xD); putf(0xA);
  575.     for (i=0;i<4;i++)
  576.         {
  577.         putf (' '); putf (' ');
  578.         for (j=0;j<17;j++)
  579.             putf('-');
  580.         putf (' ');
  581.         }
  582. }
  583.  
  584. hspace()    /* spacing        */
  585. {
  586. int i;
  587.     for (i=0;i<18;i++)
  588.         putf(' ');
  589. }
  590.  
  591. sendchr(c)    /* prints a single character description    */
  592. char c;
  593. {
  594. int i,j,k;
  595.     putf(' '); putf(' '); putf('|'); putf (' ');
  596.     for (i=0;i<7;i++)
  597.         {
  598.         if ( (c>>i) & 1) putf (' ');
  599.         else putf ('*');
  600.         putf (' ');
  601.         }
  602.     putf ('|'); putf(' ');
  603. }
  604.  
  605. sendspc()    /* vertical spaces    */
  606. {
  607.     putf(0xD); putf(0xA);
  608.     putf(0xD); putf(0xA);
  609.     putf(0xD); putf(0xA);
  610. }
  611.  
  612. putf(c)        /* byte output, goes to display and    */
  613.         /* optionally to printer        */
  614. char c;
  615. {
  616.     if (c!=0xA) putchar(c);
  617.     if (listf) bdos(LISTOUT,c);
  618. }
  619.  
  620.